@napi-rs/canvas 1.0.12 → 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +39 -19
  2. package/package.json +12 -12
package/index.js CHANGED
@@ -103,11 +103,26 @@ if (!('has' in GlobalFonts)) {
103
103
  })
104
104
  }
105
105
 
106
- const _toBlob = CanvasElement.prototype.toBlob
107
- const _convertToBlob = CanvasElement.prototype.convertToBlob
106
+ // Re-evaluating this module (Jest resets its module registry per test
107
+ // file; the .node binding and its prototypes stay loaded) must wrap the
108
+ // native methods again, not the previous wrappers: their argument padding
109
+ // would corrupt the argument count the native methods read.
110
+ const NATIVE_METHODS = Symbol.for('@napi-rs/canvas:native-methods')
111
+ function nativeMethods(proto) {
112
+ let stash = proto[NATIVE_METHODS]
113
+ if (stash === undefined) {
114
+ stash = {}
115
+ Object.defineProperty(proto, NATIVE_METHODS, { value: stash })
116
+ }
117
+ return stash
118
+ }
119
+
120
+ const canvasNative = nativeMethods(CanvasElement.prototype)
121
+ const _toBlob = (canvasNative.toBlob ??= CanvasElement.prototype.toBlob)
122
+ const _convertToBlob = (canvasNative.convertToBlob ??= CanvasElement.prototype.convertToBlob)
108
123
  // A native method of CanvasElement for the receiver check: with no arguments
109
124
  // it has no side effects.
110
- const canvasBrand = CanvasElement.prototype.getContext
125
+ const canvasBrand = (canvasNative.getContext ??= CanvasElement.prototype.getContext)
111
126
  if ('Blob' in globalThis) {
112
127
  // toBlob(callback, type, quality), as Chrome: the receiver, the argument
113
128
  // count and the callback are checked first, then the native method converts
@@ -155,7 +170,8 @@ if ('Blob' in globalThis) {
155
170
  }
156
171
  }
157
172
 
158
- const _getTransform = CanvasRenderingContext2D.prototype.getTransform
173
+ const ctxNative = nativeMethods(CanvasRenderingContext2D.prototype)
174
+ const _getTransform = (ctxNative.getTransform ??= CanvasRenderingContext2D.prototype.getTransform)
159
175
 
160
176
  CanvasRenderingContext2D.prototype.getTransform = function getTransform() {
161
177
  const transform = _getTransform.apply(this, arguments)
@@ -206,7 +222,8 @@ function bindingTypeError(brand, self, method, iface, message) {
206
222
  // napi pads missing arguments with undefined, so the native method cannot
207
223
  // tell f(1) from f(1, undefined); an explicit undefined counts in Chrome.
208
224
  function requireArguments(proto, brand, iface, method, required) {
209
- const native = proto[method]
225
+ const stash = nativeMethods(proto)
226
+ const native = (stash[method] ??= proto[method])
210
227
  const wrapper = {
211
228
  [method]() {
212
229
  if (arguments.length < required) {
@@ -256,7 +273,8 @@ for (const [Class, iface] of [
256
273
  [CanvasElement, 'HTMLCanvasElement'],
257
274
  [SVGCanvas, 'SVGCanvas'],
258
275
  ]) {
259
- requireArguments(Class.prototype, Class.prototype.getContext, iface, 'getContext', 1)
276
+ const stash = nativeMethods(Class.prototype)
277
+ requireArguments(Class.prototype, (stash.getContext ??= Class.prototype.getContext), iface, 'getContext', 1)
260
278
  }
261
279
 
262
280
  const pathBrand = Path2D.prototype.getFillType
@@ -312,7 +330,7 @@ function argumentCount(count, last) {
312
330
  // These wrappers and drawImage's read only the arguments the call has: past
313
331
  // arguments.length, arguments[i] would read Object.prototype[i], which
314
332
  // Chrome never reads.
315
- const _fill = CanvasRenderingContext2D.prototype.fill
333
+ const _fill = (ctxNative.fill ??= CanvasRenderingContext2D.prototype.fill)
316
334
  CanvasRenderingContext2D.prototype.fill = function fill() {
317
335
  const count = Math.min(arguments.length, 2)
318
336
  return _fill.call(
@@ -323,7 +341,7 @@ CanvasRenderingContext2D.prototype.fill = function fill() {
323
341
  )
324
342
  }
325
343
 
326
- const _clip = CanvasRenderingContext2D.prototype.clip
344
+ const _clip = (ctxNative.clip ??= CanvasRenderingContext2D.prototype.clip)
327
345
  CanvasRenderingContext2D.prototype.clip = function clip() {
328
346
  const count = Math.min(arguments.length, 2)
329
347
  return _clip.call(
@@ -334,7 +352,7 @@ CanvasRenderingContext2D.prototype.clip = function clip() {
334
352
  )
335
353
  }
336
354
 
337
- const _stroke = CanvasRenderingContext2D.prototype.stroke
355
+ const _stroke = (ctxNative.stroke ??= CanvasRenderingContext2D.prototype.stroke)
338
356
  CanvasRenderingContext2D.prototype.stroke = function stroke() {
339
357
  if (arguments.length === 0) {
340
358
  return _stroke.call(this, undefined, undefined)
@@ -343,7 +361,7 @@ CanvasRenderingContext2D.prototype.stroke = function stroke() {
343
361
  return _stroke.call(this, path, argumentCount(1, path))
344
362
  }
345
363
 
346
- const _isPointInPath = CanvasRenderingContext2D.prototype.isPointInPath
364
+ const _isPointInPath = (ctxNative.isPointInPath ??= CanvasRenderingContext2D.prototype.isPointInPath)
347
365
  CanvasRenderingContext2D.prototype.isPointInPath = function isPointInPath() {
348
366
  if (arguments.length < 2) {
349
367
  argumentCountError(ctxBrand, this, 'isPointInPath', 'CanvasRenderingContext2D', 2, arguments.length)
@@ -362,7 +380,7 @@ CanvasRenderingContext2D.prototype.isPointInPath = function isPointInPath() {
362
380
  }
363
381
  Object.defineProperty(CanvasRenderingContext2D.prototype.isPointInPath, 'length', { value: 2 })
364
382
 
365
- const _isPointInStroke = CanvasRenderingContext2D.prototype.isPointInStroke
383
+ const _isPointInStroke = (ctxNative.isPointInStroke ??= CanvasRenderingContext2D.prototype.isPointInStroke)
366
384
  CanvasRenderingContext2D.prototype.isPointInStroke = function isPointInStroke() {
367
385
  if (arguments.length < 2) {
368
386
  argumentCountError(ctxBrand, this, 'isPointInStroke', 'CanvasRenderingContext2D', 2, arguments.length)
@@ -498,7 +516,7 @@ function matrix2DFromInit(init, prefix, full) {
498
516
  // DOMMatrixInit is read above; the native method takes six numbers. It reads
499
517
  // a first argument that is not a number as a DOMMatrixInit, the form a raw
500
518
  // js-binding call may use, so ToNumber runs here for such an `a`.
501
- const _setTransform = CanvasRenderingContext2D.prototype.setTransform
519
+ const _setTransform = (ctxNative.setTransform ??= CanvasRenderingContext2D.prototype.setTransform)
502
520
  // A cheap native method: on another receiver it throws 'Illegal invocation',
503
521
  // which Chrome checks before it converts any argument.
504
522
  const ctxReceiver = CanvasRenderingContext2D.prototype.isContextLost
@@ -526,8 +544,9 @@ CanvasRenderingContext2D.prototype.setTransform = function setTransform() {
526
544
  // transform (undefined or null is `{}`), a native method that takes only the
527
545
  // path adds it as it is; Chrome's Path2D has no such method, so it comes off
528
546
  // the prototype.
529
- const _addPath = Path2D.prototype.addPath
530
- const _addPathWithoutTransform = Path2D.prototype._addPathWithoutTransform
547
+ const pathNative = nativeMethods(Path2D.prototype)
548
+ const _addPath = (pathNative.addPath ??= Path2D.prototype.addPath)
549
+ const _addPathWithoutTransform = (pathNative._addPathWithoutTransform ??= Path2D.prototype._addPathWithoutTransform)
531
550
  delete Path2D.prototype._addPathWithoutTransform
532
551
  const ADD_PATH = "Failed to execute 'addPath' on 'Path2D': "
533
552
  Path2D.prototype.addPath = function addPath() {
@@ -554,7 +573,7 @@ Object.defineProperty(Path2D.prototype.addPath, 'length', { value: 1 })
554
573
  // createImageData(): WebIDL picks the overload from the argument count, and an
555
574
  // explicit undefined counts: createImageData(imagedata, undefined) is the
556
575
  // (sw, sh) form.
557
- const _createImageData = CanvasRenderingContext2D.prototype.createImageData
576
+ const _createImageData = (ctxNative.createImageData ??= CanvasRenderingContext2D.prototype.createImageData)
558
577
 
559
578
  CanvasRenderingContext2D.prototype.createImageData = function createImageData() {
560
579
  const count = arguments.length
@@ -574,7 +593,7 @@ Object.defineProperty(CanvasRenderingContext2D.prototype.createImageData, 'lengt
574
593
  // putImageData(imagedata, dx, dy) or (imagedata, dx, dy, dirtyX, dirtyY,
575
594
  // dirtyWidth, dirtyHeight): as in Chrome, it needs 3 arguments; the native
576
595
  // method picks the overload from the argument count (3 or 7).
577
- const _putImageData = CanvasRenderingContext2D.prototype.putImageData
596
+ const _putImageData = (ctxNative.putImageData ??= CanvasRenderingContext2D.prototype.putImageData)
578
597
 
579
598
  CanvasRenderingContext2D.prototype.putImageData = function putImageData() {
580
599
  const count = arguments.length
@@ -601,7 +620,7 @@ Object.defineProperty(CanvasRenderingContext2D.prototype.putImageData, 'length',
601
620
  // required, and the image is converted before the repetition, a
602
621
  // [LegacyNullToEmptyString] DOMString (canvas_2d_recorder_context.idl), so
603
622
  // null is '' and undefined is 'undefined'.
604
- const _createPattern = CanvasRenderingContext2D.prototype.createPattern
623
+ const _createPattern = (ctxNative.createPattern ??= CanvasRenderingContext2D.prototype.createPattern)
605
624
 
606
625
  CanvasRenderingContext2D.prototype.createPattern = function createPattern(image, repetition) {
607
626
  return _createPattern.call(this, image, repetition, ARGUMENT_COUNTS[Math.min(arguments.length, 4)])
@@ -610,14 +629,15 @@ CanvasRenderingContext2D.prototype.createPattern = function createPattern(image,
610
629
  // addColorStop(offset, color): both arguments are required. CanvasGradient
611
630
  // has no other native method to check the receiver first, so the native
612
631
  // method itself reads the real count from the marker after them.
613
- const _addColorStop = CanvasGradient.prototype.addColorStop
632
+ const gradientNative = nativeMethods(CanvasGradient.prototype)
633
+ const _addColorStop = (gradientNative.addColorStop ??= CanvasGradient.prototype.addColorStop)
614
634
  CanvasGradient.prototype.addColorStop = function addColorStop(offset, color) {
615
635
  return _addColorStop.call(this, offset, color, ARGUMENT_COUNTS[Math.min(arguments.length, 2)])
616
636
  }
617
637
 
618
638
  // Workaround for webpack bundling issue with drawImage
619
639
  // Store the original drawImage method
620
- const _drawImage = CanvasRenderingContext2D.prototype.drawImage
640
+ const _drawImage = (ctxNative.drawImage ??= CanvasRenderingContext2D.prototype.drawImage)
621
641
 
622
642
  // Override drawImage to ensure proper type recognition in bundled environments.
623
643
  // As in Chrome, it needs 3 arguments; the native method picks the overload
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@napi-rs/canvas",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "description": "Canvas for Node.js with skia backend",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -161,16 +161,16 @@
161
161
  "@napi-rs/canvas": "workspace:"
162
162
  },
163
163
  "optionalDependencies": {
164
- "@napi-rs/canvas-linux-x64-gnu": "1.0.12",
165
- "@napi-rs/canvas-darwin-x64": "1.0.12",
166
- "@napi-rs/canvas-win32-x64-msvc": "1.0.12",
167
- "@napi-rs/canvas-win32-arm64-msvc": "1.0.12",
168
- "@napi-rs/canvas-linux-arm-gnueabihf": "1.0.12",
169
- "@napi-rs/canvas-linux-x64-musl": "1.0.12",
170
- "@napi-rs/canvas-linux-arm64-gnu": "1.0.12",
171
- "@napi-rs/canvas-linux-arm64-musl": "1.0.12",
172
- "@napi-rs/canvas-darwin-arm64": "1.0.12",
173
- "@napi-rs/canvas-android-arm64": "1.0.12",
174
- "@napi-rs/canvas-linux-riscv64-gnu": "1.0.12"
164
+ "@napi-rs/canvas-linux-x64-gnu": "1.0.13",
165
+ "@napi-rs/canvas-darwin-x64": "1.0.13",
166
+ "@napi-rs/canvas-win32-x64-msvc": "1.0.13",
167
+ "@napi-rs/canvas-win32-arm64-msvc": "1.0.13",
168
+ "@napi-rs/canvas-linux-arm-gnueabihf": "1.0.13",
169
+ "@napi-rs/canvas-linux-x64-musl": "1.0.13",
170
+ "@napi-rs/canvas-linux-arm64-gnu": "1.0.13",
171
+ "@napi-rs/canvas-linux-arm64-musl": "1.0.13",
172
+ "@napi-rs/canvas-darwin-arm64": "1.0.13",
173
+ "@napi-rs/canvas-android-arm64": "1.0.13",
174
+ "@napi-rs/canvas-linux-riscv64-gnu": "1.0.13"
175
175
  }
176
176
  }