-
Notifications
You must be signed in to change notification settings - Fork 153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Canvas API #380
Merged
Merged
Implement Canvas API #380
Changes from all commits
Commits
Show all changes
118 commits
Select commit
Hold shift + click to select a range
ca5b033
Merge master
delima02 9daba15
Revert "Merge master"
delima02 dfebb96
CanvasRenderingContext2D and OffscreenCanvas
delima02 d810e14
Add tests for CanvasRenderingContext2D
delima02 3f20f3e
Remove unnecessary comments
delima02 237e34c
Revert allowing noImplicitAny for tests
delima02 797b3cb
Remove JS files from src/test/tsconfig
delima02 3e625be
Remove unnecessary excluded directory from test/tsconfig
delima02 fca3af6
Only test what should be in second and third tests for clearRect
delima02 b3d0a32
Fix implementation and tests for beginPath and closePath
delima02 95d3a14
Change static context to most recent OffscreenCanvas instance in tests
delima02 ad8e8bb
Add meta-programming to reduce the number of lines while delegating c…
delima02 ade3271
Add missing tests for putImageData
delima02 60e1f81
Simplify ImageBitmap creation logic for tests
delima02 74bb308
Merge conflicts with master
delima02 5fd3614
Await for same promise instance needed by test, instead of new one
delima02 3f84ccd
Remove unnecessary check from third test for each method tested
delima02 fe54ac6
Fix test purposes by moving assertion from third test to second test …
delima02 36f9696
Add missing tests for createPattern, drawImage, and putImageData
delima02 8f5eb73
Remove object from delegate function definition arguments
delima02 584cba3
Have HTMLCanvasElement actually own the context
delima02 506f654
Add transfer call on OffscreenCanvas upgrade and canvas demo page
delima02 8a73ccc
Use exact version numbers for sinon dependency
delima02 ef45d03
Improve Canvas API demo
delima02 a13a52f
Remove OffscreenCanvas message event listener when not needed
delima02 58443e2
Switch Context2DImpl and Context2D naming
delima02 afb3306
Use single quotes instead of double quotes, when possible
delima02 d0f4415
Change more double quotes to singles for consistency
delima02 4013812
Fix indentation in offscreen-canvas.ts
delima02 cbcdd76
Fix indentation in offscreen-canvas.ts
delima02 9a1cd14
Format context tests file
delima02 85784df
Format files that did not run through prettier before
delima02 a74fbad
Empty calls array after all pending methods have been called
delima02 bc3572f
Add tests for HTMLCanvasElement.getContext
delima02 dd4e5a6
Check for correct canvas instance being used to retrieve context async
delima02 29f4204
Add one more example to canvas demo
delima02 e06cfb6
Merge branch 'master' into delima02-canvas
delima02 5e046e8
Fix Document creation for tests after merge conflicts
delima02 ae376f6
Fix OffscreenCanvas transfer call after merge conflicts
delima02 57d29cb
Merge
delima02 6b5b80f
More polyfill methods and remove console logs
delima02 33b7724
Add .test to test files
delima02 efedcab
Meta-program polyfill methods.
delima02 81f6a25
Make houses bigger in Canvas demo.
delima02 b1b40f9
Delete SampleContext.ts since no longer needed.
delima02 dd9ee4e
Create polyfill context in getContext method.
delima02 19e6d19
Have CommandExecutor take only Uint16Array's.
delima02 bad9acc
Remove unnecessary argcount check for setters.
delima02 95f37ee
Add color to example houses to test methods with strings
delima02 1e75f01
Revert changes in mutator.ts.
delima02 3da8531
Only request an OffscreenCanvas if supported.
delima02 3c14f7d
Revert changes in MutationTransfer.ts.
delima02 69abf90
Pass in offscreen polyfill method calls using a different mechanism
delima02 ad0e4b9
Revert install.ts.
delima02 46bc90f
Rename OFFSCREEN_CONTEXT_CALL to OFFSCREEN_POLYFILL
delima02 78bdadf
Remove context creation from polyfill constructor.
delima02 c9f5f7c
Remove unused TransferrableKeys.extra.
delima02 526a4ac
Remove unnecessary call to callQueuedCalls and console logs.
delima02 93adcbf
Improve debug print function for offscreen polyfill processor
delima02 d31a005
Refactor ofscreen processor to avoid bugs when converting typedarrays.
delima02 c254ca3
Rename canvas test files to include .test
delima02 49c4f77
Fix some method signatures for CanvasRenderingContext2D.
delima02 47445fd
Merge branch 'delima02-canvas' into delima02-poly
delima02 56706c9
Add +1 to string arg index to avoid negatives.
delima02 e81eaf9
Fix implementation for beginPath
delima02 f5884de
getLineDash and setLineDash (tested locally)
delima02 d8acae7
clip() and fill()
delima02 49d38f1
setTransform and remove extra defs of lineDash methods.
delima02 303da7f
Add optional argument for fillText and strokeText
delima02 59e5eb6
Add optional argument to ellipse() and arc()
delima02 b8ad611
Refactor polyfill and call transfer.
delima02 c11599e
Use [...arguments] to delegate all CanvasRenderingContext2D calls.
delima02 b6a2254
Throw for unsupported method signatures.
delima02 37ebe23
NIT and some refactoring
delima02 207155e
Remove duplication and args from methods that don't take any
delima02 8c0dfe3
Fix float32Needed bug
delima02 c5d9893
Tweak lineDash methods
delima02 6c294e7
Merge master
delima02 f6fb0f3
Merge master
delima02 7008704
Fix polyfill CommandExectutor's print() impl.
delima02 a174656
Merge master.
delima02 d6d1bb3
Tweak canvas demo
delima02 ee8d4ef
Improve canvas demo
delima02 d51fb79
Bump up bundle size
delima02 e29eaa0
Merge master.
delima02 a424b2a
Merge branch 'delima02-canvas' into delima02-poly
delima02 e419317
Merge pull request #1 from delima02/delima02-poly
delima02 c32e90e
Merge branch 'master' into delima02-canvas
delima02 a6e11f7
Merge branch 'master' into delima02-canvas
delima02 4cde664
Add missing templating in context used for testing
delima02 b2a5a54
Fix circular dependency by templating.
delima02 86f8ed5
Fix memory leak + remove unnecessary if.
delima02 b82070f
Remove unnecessary comments
delima02 5edc97a
Merge branch 'master' into delima02-canvas
delima02 7730c80
Make 'transferables' an optional argument in messageToWorker
delima02 b5c0dc6
Indicate OffscreenCanvas not available in TS with comment
delima02 1e7b7f9
Rename DOMTypes and group all canvas files in folder
delima02 ce20391
Add getters for CanvasRenderingContext2D
delima02 4a3c909
Replace fake 'describe' blocks with comments
delima02 67ce3b2
Missing getters and tests for getters.
delima02 c39a38e
Rename "spy" to something more appropriate in testing helper fn.
delima02 09e0dbf
Remove unneeded 'workerContext' from offscreen call processor.
delima02 3a4edf4
Tests for offscreen call processor.
delima02 d1e58bd
Merge branch 'delima02-canvas' of github.com:delima02/worker-dom into…
delima02 1afb6ed
Increase bundle size.
delima02 17cabfd
Merge branch 'master' into delima02-canvas
delima02 f0d1b3b
Increase bundle size
delima02 a0e3276
Have 'sandbox' be passed through test context.
delima02 a105d69
Rename some variables.
delima02 120eec2
Make 'getOffscreenCanvasAsync' private and owned by CanvasRenderingCo…
delima02 37204db
Split CanvasRenderingContext2D's delegate function into three differe…
delima02 5bb059c
Rename test OffscreenCanvas class to FakeOffscreenCanvas
delima02 283dbec
Rename CanvasRenderingContext2DImplementation to CanvasRenderingConte…
delima02 cae19fd
Create test stubs inline.
delima02 79ebff9
merge master
delima02 65b2c32
Remove global dependency from Canvas API
delima02 3d8ce3d
Fix demo.
delima02 16a1a64
Increase bundle size.
delima02 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
/** | ||
* Copyright 2018 The AMP HTML Authors. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS-IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
const existingCanvasBtn = document.getElementById('existingCanvasBtn'); | ||
const newCanvasBtn = document.getElementById('newCanvasBtn'); | ||
const doubleCanvasBtn = document.getElementById('doubleCanvasBtn'); | ||
|
||
const myCanvas = document.getElementById('myCanvas'); | ||
const myCtx = myCanvas.getContext('2d'); | ||
|
||
function draw(e) { | ||
myCtx.lineTo(e.offsetX, e.offsetY); | ||
myCtx.stroke(); | ||
} | ||
|
||
myCanvas.addEventListener('mousedown', e => { | ||
myCtx.strokeStyle = 'red'; | ||
myCtx.lineWidth = 2; | ||
myCtx.setLineDash([10, 10]); | ||
myCtx.beginPath(); | ||
myCtx.moveTo(e.offsetX, e.offsetY); | ||
myCanvas.addEventListener('mousemove', draw); | ||
}); | ||
|
||
myCanvas.addEventListener('mouseup', e => { | ||
myCanvas.removeEventListener('mousemove', draw); | ||
}); | ||
|
||
existingCanvasBtn.addEventListener('click', async () => { | ||
// Scenario #1: | ||
// Canvas is already on the page | ||
myCtx.fillStyle = 'blue'; | ||
myCtx.strokeStyle = 'blue'; | ||
myCtx.lineWidth = 5; | ||
myCtx.setLineDash([1, 0]); | ||
myCtx.beginPath(); | ||
myCtx.strokeRect(212.5, 222.5, 75, 55); | ||
myCtx.fillRect(240, 247.5, 20, 30); | ||
myCtx.moveTo(200, 222.5); | ||
myCtx.lineTo(250, 182.5); | ||
myCtx.lineTo(300, 222.5); | ||
myCtx.closePath(); | ||
myCtx.stroke(); | ||
|
||
}); | ||
|
||
newCanvasBtn.addEventListener('click', async () => { | ||
// Scenario #2: | ||
// Create a canvas element using document.createElement() | ||
const canvas = document.createElement('canvas'); | ||
const newCanvasDiv = document.getElementById('newCanvasDiv'); | ||
canvas.width = 250; | ||
canvas.height = 250; | ||
newCanvasDiv.appendChild(canvas); | ||
const ctx = canvas.getContext('2d'); | ||
|
||
ctx.lineWidth = 5; | ||
ctx.fillStyle = 'orange'; | ||
ctx.strokeStyle = 'orange'; | ||
ctx.strokeRect(87.5, 97.5, 75, 55); | ||
ctx.fillRect(115, 122.5, 20, 30); | ||
ctx.moveTo(75, 97.5); | ||
ctx.lineTo(125, 57.5); | ||
ctx.lineTo(175, 97.5); | ||
|
||
ctx.closePath(); | ||
ctx.stroke(); | ||
}); | ||
|
||
doubleCanvasBtn.addEventListener('click', async () => { | ||
// Scenario #3: | ||
// Two different canvas elements created at the same time. | ||
// This scenario is needed to make sure async logic works correctly. | ||
const canvasOne = document.createElement('canvas'); | ||
const canvasTwo = document.createElement('canvas'); | ||
|
||
canvasOne.width = 250; | ||
canvasOne.height = 250; | ||
canvasTwo.width = 250; | ||
canvasTwo.height = 250; | ||
|
||
const newCanvasDiv = document.getElementById('newCanvasDiv'); | ||
|
||
newCanvasDiv.appendChild(canvasOne); | ||
newCanvasDiv.appendChild(canvasTwo); | ||
|
||
|
||
const ctxOne = canvasOne.getContext('2d'); | ||
const ctxTwo = canvasTwo.getContext('2d'); | ||
|
||
ctxOne.lineWidth = 5; | ||
ctxOne.fillStyle = 'red'; | ||
ctxOne.strokeStyle = 'red'; | ||
ctxOne.strokeRect(87.5, 97.5, 75, 55); | ||
ctxOne.fillRect(115, 122.5, 20, 30); | ||
ctxOne.moveTo(75, 97.5); | ||
ctxOne.lineTo(125, 57.5); | ||
ctxOne.lineTo(175, 97.5); | ||
ctxOne.closePath(); | ||
ctxOne.stroke(); | ||
|
||
ctxTwo.lineWidth = 5; | ||
ctxTwo.fillStyle = 'green'; | ||
ctxTwo.strokeStyle = 'green'; | ||
ctxTwo.strokeRect(87.5, 97.5, 75, 55); | ||
ctxTwo.fillRect(115, 122.5, 20, 30); | ||
ctxTwo.moveTo(75, 97.5); | ||
ctxTwo.lineTo(125, 57.5); | ||
ctxTwo.lineTo(175, 97.5); | ||
|
||
ctxTwo.closePath(); | ||
ctxTwo.stroke(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<!DOCTYPE html> | ||
<html style="background: #e6e9e9;"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<title>Hello World</title> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<link href="/demo.css" rel="stylesheet"> | ||
<script src="/dist/main.mjs" type="module"></script> | ||
<script src="/dist/main.js" nomodule defer></script> | ||
<!-- This comment block is intended to make it easier to test both the script module and nomodule path --> | ||
<!-- Comment either block to enable module/nomodule or disable it. --> | ||
<!-- <script src="/dist/main.js" defer></script> --> | ||
</head> | ||
<body style="background: #e6e9e9;"> | ||
<div src="canvas.js" id="upgrade-me"> | ||
<div id="canvasButtonsDiv"> | ||
|
||
<button id="existingCanvasBtn">Draw on already existing canvas</button> | ||
<button id="newCanvasBtn">Create new canvas and draw on it</button> | ||
<button id="doubleCanvasBtn">Create two new canvases and draw on them</button> | ||
</div> | ||
<div> | ||
<canvas width="500" height="500" id="myCanvas"></canvas> | ||
<div id="newCanvasDiv"></div> | ||
</div> | ||
</div> | ||
<script type="module"> | ||
import {upgradeElement} from '/dist/main.mjs'; | ||
upgradeElement(document.getElementById('upgrade-me'), '/dist/worker/worker.mjs'); | ||
</script> | ||
<script nomodule async=false defer> | ||
document.addEventListener('DOMContentLoaded', function() { | ||
MainThread.upgradeElement(document.getElementById('upgrade-me'), '/dist/worker.js'); | ||
}, false); | ||
</script> | ||
<!-- This comment block is intended to make it easier to test both the script module and nomodule path --> | ||
<!-- Comment either block to enable module/nomodule or disable it. --> | ||
<!-- <script async=false defer> | ||
document.addEventListener('DOMContentLoaded', function() { | ||
MainThread.upgradeElement(document.getElementById('upgrade-me'), './dist/worker.js'); | ||
}, false); | ||
</script> --> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { WorkerContext } from '../worker'; | ||
import { TransferrableKeys } from '../../transfer/TransferrableKeys'; | ||
import { MessageType } from '../../transfer/Messages'; | ||
import { CommandExecutor } from './interface'; | ||
import { OffscreenCanvasMutationIndex } from '../../transfer/TransferrableMutation'; | ||
|
||
export function OffscreenCanvasProcessor(workerContext: WorkerContext): CommandExecutor { | ||
return { | ||
execute(mutations: Uint16Array, startPosition: number, target: RenderableElement): number { | ||
if (target) { | ||
const canvas = target as HTMLCanvasElement; | ||
const offscreen = canvas.transferControlToOffscreen(); | ||
workerContext.messageToWorker( | ||
{ | ||
[TransferrableKeys.type]: MessageType.OFFSCREEN_CANVAS_INSTANCE, | ||
[TransferrableKeys.target]: [target._index_], | ||
[TransferrableKeys.data]: offscreen, // Object, an OffscreenCanvas | ||
}, | ||
[offscreen], | ||
); | ||
} else { | ||
console.error(`getNode() yields null – ${target}`); | ||
} | ||
|
||
return startPosition + OffscreenCanvasMutationIndex.End; | ||
}, | ||
print(mutations: Uint16Array, startPosition: number, target?: RenderableElement | null): Object { | ||
|
||
return { | ||
type: 'OFFSCREEN_CANVAS_INSTANCE', | ||
target, | ||
}; | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import { CommandExecutor } from './interface'; | ||
import { OffscreenContextPolyfillMutationIndex } from '../../transfer/TransferrableMutation'; | ||
import { NumericBoolean } from '../../utils'; | ||
import { Strings } from '../strings'; | ||
|
||
export function OffscreenPolyfillCallProcessor(strings: Strings): CommandExecutor { | ||
return { | ||
execute(mutations: Uint16Array, startPosition: number, target: RenderableElement): number { | ||
const float32Needed = mutations[startPosition + OffscreenContextPolyfillMutationIndex.Float32Needed] === NumericBoolean.TRUE; | ||
const argCount = mutations[startPosition + OffscreenContextPolyfillMutationIndex.ArgumentCount]; | ||
const methodCalled = strings.get(mutations[startPosition + OffscreenContextPolyfillMutationIndex.MethodCalled]); | ||
const isSetter = mutations[startPosition + OffscreenContextPolyfillMutationIndex.IsSetter] === NumericBoolean.TRUE; | ||
const stringArgIndex = mutations[startPosition + OffscreenContextPolyfillMutationIndex.StringArgIndex]; | ||
|
||
const argsStart = startPosition + OffscreenContextPolyfillMutationIndex.Args; | ||
let argsTypedArray: Uint16Array | Float32Array; | ||
let argEnd = argCount; | ||
|
||
if (float32Needed) { | ||
argEnd *= 2; | ||
argsTypedArray = new Float32Array(mutations.slice(argsStart, argsStart + argEnd).buffer); | ||
} else { | ||
argsTypedArray = mutations.slice(argsStart, argsStart + argEnd); | ||
} | ||
|
||
const mainContext = (target as HTMLCanvasElement).getContext('2d'); | ||
let args = [] as any[]; | ||
|
||
if (argCount > 0) { | ||
argsTypedArray.forEach((arg: any, i: number) => { | ||
if (stringArgIndex - 1 === i) { | ||
args.push(strings.get(arg)); | ||
} else { | ||
args.push(arg); | ||
} | ||
}); | ||
|
||
// setLineDash has a single argument: number[] | ||
// values from the array argument are transferred independently, so we must do this | ||
if (methodCalled === 'setLineDash') { | ||
args = [args]; | ||
} | ||
} | ||
|
||
if (isSetter) { | ||
(mainContext as any)[methodCalled] = args[0]; | ||
} else { | ||
(mainContext as any)[methodCalled](...args); | ||
} | ||
|
||
return startPosition + OffscreenContextPolyfillMutationIndex.End + argEnd; | ||
}, | ||
print(mutations: Uint16Array, startPosition: number, target?: RenderableElement | null): Object { | ||
const float32Needed = mutations[startPosition + OffscreenContextPolyfillMutationIndex.Float32Needed] === NumericBoolean.TRUE; | ||
const argCount = mutations[startPosition + OffscreenContextPolyfillMutationIndex.ArgumentCount]; | ||
const methodCalled = strings.get(mutations[startPosition + OffscreenContextPolyfillMutationIndex.MethodCalled]); | ||
const isSetter = mutations[startPosition + OffscreenContextPolyfillMutationIndex.IsSetter] === NumericBoolean.TRUE; | ||
const stringArgIndex = mutations[startPosition + OffscreenContextPolyfillMutationIndex.StringArgIndex]; | ||
|
||
const argsStart = startPosition + OffscreenContextPolyfillMutationIndex.Args; | ||
let argsTypedArray: Uint16Array | Float32Array; | ||
let argEnd = argCount; | ||
|
||
if (float32Needed) { | ||
argEnd *= 2; | ||
argsTypedArray = new Float32Array(mutations.slice(argsStart, argsStart + argEnd).buffer); | ||
} else { | ||
argsTypedArray = mutations.slice(argsStart, argsStart + argEnd); | ||
} | ||
|
||
let args = [] as any[]; | ||
|
||
if (argCount > 0) { | ||
argsTypedArray.forEach((arg: any, i: number) => { | ||
if (stringArgIndex - 1 === i) { | ||
args.push(strings.get(arg)); | ||
} else { | ||
args.push(arg); | ||
} | ||
}); | ||
|
||
// setLineDash has a single argument: number[] | ||
// values from the array argument are transferred independently, so we must do this | ||
if (methodCalled === 'setLineDash') { | ||
args = [args]; | ||
} | ||
} | ||
|
||
return { | ||
type: 'OFFSCREEN_POLYFILL', | ||
target, | ||
Float32Needed: float32Needed, | ||
ArgumentCount: argCount, | ||
MethodCalled: methodCalled, | ||
IsSetter: isSetter, | ||
StringArgIndex: stringArgIndex, | ||
Args: args, | ||
End: startPosition + OffscreenContextPolyfillMutationIndex.End + argEnd, | ||
}; | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have tests that cover these processor functions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now we do 👍