From a45800b99f3b5432bd8ff21419b42b1759ae585e Mon Sep 17 00:00:00 2001 From: TheDadi Date: Tue, 11 Oct 2022 16:58:28 +0200 Subject: [PATCH 01/10] add node 16 & 18 to build --- .github/workflows/ci.yaml | 6 +++--- .github/workflows/prebuild.yaml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3c92ea1c8..31b7497bc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: [10, 12, 14, 16] + node: [10, 12, 14, 16, 18] steps: - uses: actions/setup-node@v3 with: @@ -33,7 +33,7 @@ jobs: runs-on: windows-2019 strategy: matrix: - node: [10, 12, 14, 16] + node: [10, 12, 14, 16, 18] steps: - uses: actions/setup-node@v3 with: @@ -57,7 +57,7 @@ jobs: runs-on: macos-latest strategy: matrix: - node: [10, 12, 14, 16] + node: [10, 12, 14, 16, 18] steps: - uses: actions/setup-node@v3 with: diff --git a/.github/workflows/prebuild.yaml b/.github/workflows/prebuild.yaml index b10cc1522..a112eef87 100644 --- a/.github/workflows/prebuild.yaml +++ b/.github/workflows/prebuild.yaml @@ -24,7 +24,7 @@ jobs: Linux: strategy: matrix: - node: [8, 9, 10, 11, 12, 13, 14] + node: [8, 9, 10, 11, 12, 13, 14, 16, 18] canvas_tag: [] # e.g. "v2.6.1" name: ${{ matrix.canvas_tag}}, Node.js ${{ matrix.node }}, Linux runs-on: ubuntu-latest @@ -97,7 +97,7 @@ jobs: macOS: strategy: matrix: - node: [8, 9, 10, 11, 12, 13, 14] + node: [8, 9, 10, 11, 12, 13, 14, 16, 18] canvas_tag: [] # e.g. "v2.6.1" name: ${{ matrix.canvas_tag}}, Node.js ${{ matrix.node }}, macOS runs-on: macos-latest @@ -163,7 +163,7 @@ jobs: Win: strategy: matrix: - node: [8, 9, 10, 11, 12, 13, 14] + node: [8, 9, 10, 11, 12, 13, 14, 16, 18] canvas_tag: [] # e.g. "v2.6.1" name: ${{ matrix.canvas_tag}}, Node.js ${{ matrix.node }}, Windows runs-on: windows-latest From cb172614adddee33b83c370a310a1a47915cf0f7 Mon Sep 17 00:00:00 2001 From: TheDadi Date: Tue, 11 Oct 2022 17:02:25 +0200 Subject: [PATCH 02/10] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 034783003..240207fa4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "canvas", "description": "Canvas graphics API backed by Cairo", - "version": "2.10.1", + "version": "2.10.2", "author": "TJ Holowaychuk ", "main": "index.js", "browser": "browser.js", From 61b1d4da3d64499427cdcaa0c23b95b5317664c9 Mon Sep 17 00:00:00 2001 From: TheDadi Date: Tue, 11 Oct 2022 20:39:23 +0200 Subject: [PATCH 03/10] fix Assertion failed: (object->InternalFieldCount() > 0), function Unwrap, file nan_object_wrap.h, line 32. --- package.json | 2 +- src/Canvas.cc | 14 ++++++---- src/CanvasRenderingContext2d.cc | 49 +++++++++++++++++---------------- src/Image.cc | 18 ++++++------ src/ImageData.cc | 12 ++++---- src/Util.h | 25 ----------------- test/canvas.test.js | 5 +--- test/image.test.js | 5 +--- test/imageData.test.js | 3 -- 9 files changed, 52 insertions(+), 81 deletions(-) diff --git a/package.json b/package.json index 240207fa4..bfc152224 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "types": "types/index.d.ts", "dependencies": { "@mapbox/node-pre-gyp": "^1.0.0", - "nan": "^2.15.0", + "nan": "^2.17.0", "simple-get": "^3.0.3" }, "devDependencies": { diff --git a/src/Canvas.cc b/src/Canvas.cc index 3e339f033..45b9fb2bb 100644 --- a/src/Canvas.cc +++ b/src/Canvas.cc @@ -57,17 +57,21 @@ Canvas::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { ctor->SetClassName(Nan::New("Canvas").ToLocalChecked()); // Prototype - Local proto = ctor->PrototypeTemplate(); + Local proto = ctor->InstanceTemplate(); Nan::SetPrototypeMethod(ctor, "toBuffer", ToBuffer); Nan::SetPrototypeMethod(ctor, "streamPNGSync", StreamPNGSync); Nan::SetPrototypeMethod(ctor, "streamPDFSync", StreamPDFSync); #ifdef HAVE_JPEG Nan::SetPrototypeMethod(ctor, "streamJPEGSync", StreamJPEGSync); #endif - SetProtoAccessor(proto, Nan::New("type").ToLocalChecked(), GetType, NULL, ctor); - SetProtoAccessor(proto, Nan::New("stride").ToLocalChecked(), GetStride, NULL, ctor); - SetProtoAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth, SetWidth, ctor); - SetProtoAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight, SetHeight, ctor); + + // link getters and setter to the object property + Local inst = ctor->InstanceTemplate(); + + Nan::SetAccessor(inst, Nan::New("type").ToLocalChecked(), GetType, NULL); + Nan::SetAccessor(inst, Nan::New("stride").ToLocalChecked(), GetStride, NULL); + Nan::SetAccessor(inst, Nan::New("width").ToLocalChecked(), GetWidth, SetWidth); + Nan::SetAccessor(inst, Nan::New("height").ToLocalChecked(), GetHeight, SetHeight); Nan::SetTemplate(proto, "PNG_NO_FILTERS", Nan::New(PNG_NO_FILTERS)); Nan::SetTemplate(proto, "PNG_FILTER_NONE", Nan::New(PNG_FILTER_NONE)); diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index 60a86cb3b..bb0aec223 100644 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -101,7 +101,6 @@ Context2d::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { ctor->SetClassName(Nan::New("CanvasRenderingContext2D").ToLocalChecked()); // Prototype - Local proto = ctor->PrototypeTemplate(); Nan::SetPrototypeMethod(ctor, "drawImage", DrawImage); Nan::SetPrototypeMethod(ctor, "putImageData", PutImageData); Nan::SetPrototypeMethod(ctor, "getImageData", GetImageData); @@ -142,29 +141,31 @@ Context2d::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { Nan::SetPrototypeMethod(ctor, "createPattern", CreatePattern); Nan::SetPrototypeMethod(ctor, "createLinearGradient", CreateLinearGradient); Nan::SetPrototypeMethod(ctor, "createRadialGradient", CreateRadialGradient); - SetProtoAccessor(proto, Nan::New("pixelFormat").ToLocalChecked(), GetFormat, NULL, ctor); - SetProtoAccessor(proto, Nan::New("patternQuality").ToLocalChecked(), GetPatternQuality, SetPatternQuality, ctor); - SetProtoAccessor(proto, Nan::New("imageSmoothingEnabled").ToLocalChecked(), GetImageSmoothingEnabled, SetImageSmoothingEnabled, ctor); - SetProtoAccessor(proto, Nan::New("globalCompositeOperation").ToLocalChecked(), GetGlobalCompositeOperation, SetGlobalCompositeOperation, ctor); - SetProtoAccessor(proto, Nan::New("globalAlpha").ToLocalChecked(), GetGlobalAlpha, SetGlobalAlpha, ctor); - SetProtoAccessor(proto, Nan::New("shadowColor").ToLocalChecked(), GetShadowColor, SetShadowColor, ctor); - SetProtoAccessor(proto, Nan::New("miterLimit").ToLocalChecked(), GetMiterLimit, SetMiterLimit, ctor); - SetProtoAccessor(proto, Nan::New("lineWidth").ToLocalChecked(), GetLineWidth, SetLineWidth, ctor); - SetProtoAccessor(proto, Nan::New("lineCap").ToLocalChecked(), GetLineCap, SetLineCap, ctor); - SetProtoAccessor(proto, Nan::New("lineJoin").ToLocalChecked(), GetLineJoin, SetLineJoin, ctor); - SetProtoAccessor(proto, Nan::New("lineDashOffset").ToLocalChecked(), GetLineDashOffset, SetLineDashOffset, ctor); - SetProtoAccessor(proto, Nan::New("shadowOffsetX").ToLocalChecked(), GetShadowOffsetX, SetShadowOffsetX, ctor); - SetProtoAccessor(proto, Nan::New("shadowOffsetY").ToLocalChecked(), GetShadowOffsetY, SetShadowOffsetY, ctor); - SetProtoAccessor(proto, Nan::New("shadowBlur").ToLocalChecked(), GetShadowBlur, SetShadowBlur, ctor); - SetProtoAccessor(proto, Nan::New("antialias").ToLocalChecked(), GetAntiAlias, SetAntiAlias, ctor); - SetProtoAccessor(proto, Nan::New("textDrawingMode").ToLocalChecked(), GetTextDrawingMode, SetTextDrawingMode, ctor); - SetProtoAccessor(proto, Nan::New("quality").ToLocalChecked(), GetQuality, SetQuality, ctor); - SetProtoAccessor(proto, Nan::New("currentTransform").ToLocalChecked(), GetCurrentTransform, SetCurrentTransform, ctor); - SetProtoAccessor(proto, Nan::New("fillStyle").ToLocalChecked(), GetFillStyle, SetFillStyle, ctor); - SetProtoAccessor(proto, Nan::New("strokeStyle").ToLocalChecked(), GetStrokeStyle, SetStrokeStyle, ctor); - SetProtoAccessor(proto, Nan::New("font").ToLocalChecked(), GetFont, SetFont, ctor); - SetProtoAccessor(proto, Nan::New("textBaseline").ToLocalChecked(), GetTextBaseline, SetTextBaseline, ctor); - SetProtoAccessor(proto, Nan::New("textAlign").ToLocalChecked(), GetTextAlign, SetTextAlign, ctor); + + Local inst = ctor->InstanceTemplate(); + Nan::SetAccessor(inst, Nan::New("pixelFormat").ToLocalChecked(), GetFormat, NULL); + Nan::SetAccessor(inst, Nan::New("patternQuality").ToLocalChecked(), GetPatternQuality, SetPatternQuality); + Nan::SetAccessor(inst, Nan::New("imageSmoothingEnabled").ToLocalChecked(), GetImageSmoothingEnabled, SetImageSmoothingEnabled); + Nan::SetAccessor(inst, Nan::New("globalCompositeOperation").ToLocalChecked(), GetGlobalCompositeOperation, SetGlobalCompositeOperation); + Nan::SetAccessor(inst, Nan::New("globalAlpha").ToLocalChecked(), GetGlobalAlpha, SetGlobalAlpha); + Nan::SetAccessor(inst, Nan::New("shadowColor").ToLocalChecked(), GetShadowColor, SetShadowColor); + Nan::SetAccessor(inst, Nan::New("miterLimit").ToLocalChecked(), GetMiterLimit, SetMiterLimit); + Nan::SetAccessor(inst, Nan::New("lineWidth").ToLocalChecked(), GetLineWidth, SetLineWidth); + Nan::SetAccessor(inst, Nan::New("lineCap").ToLocalChecked(), GetLineCap, SetLineCap); + Nan::SetAccessor(inst, Nan::New("lineJoin").ToLocalChecked(), GetLineJoin, SetLineJoin); + Nan::SetAccessor(inst, Nan::New("lineDashOffset").ToLocalChecked(), GetLineDashOffset, SetLineDashOffset); + Nan::SetAccessor(inst, Nan::New("shadowOffsetX").ToLocalChecked(), GetShadowOffsetX, SetShadowOffsetX); + Nan::SetAccessor(inst, Nan::New("shadowOffsetY").ToLocalChecked(), GetShadowOffsetY, SetShadowOffsetY); + Nan::SetAccessor(inst, Nan::New("shadowBlur").ToLocalChecked(), GetShadowBlur, SetShadowBlur); + Nan::SetAccessor(inst, Nan::New("antialias").ToLocalChecked(), GetAntiAlias, SetAntiAlias); + Nan::SetAccessor(inst, Nan::New("textDrawingMode").ToLocalChecked(), GetTextDrawingMode, SetTextDrawingMode); + Nan::SetAccessor(inst, Nan::New("quality").ToLocalChecked(), GetQuality, SetQuality); + Nan::SetAccessor(inst, Nan::New("currentTransform").ToLocalChecked(), GetCurrentTransform, SetCurrentTransform); + Nan::SetAccessor(inst, Nan::New("fillStyle").ToLocalChecked(), GetFillStyle, SetFillStyle); + Nan::SetAccessor(inst, Nan::New("strokeStyle").ToLocalChecked(), GetStrokeStyle, SetStrokeStyle); + Nan::SetAccessor(inst, Nan::New("font").ToLocalChecked(), GetFont, SetFont); + Nan::SetAccessor(inst, Nan::New("textBaseline").ToLocalChecked(), GetTextBaseline, SetTextBaseline); + Nan::SetAccessor(inst, Nan::New("textAlign").ToLocalChecked(), GetTextAlign, SetTextAlign); Local ctx = Nan::GetCurrentContext(); Nan::Set(target, Nan::New("CanvasRenderingContext2d").ToLocalChecked(), ctor->GetFunction(ctx).ToLocalChecked()); Nan::Set(target, Nan::New("CanvasRenderingContext2dInit").ToLocalChecked(), Nan::New(SaveExternalModules)); diff --git a/src/Image.cc b/src/Image.cc index 103b65ee7..cca3fe3d1 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -8,7 +8,6 @@ #include #include #include -#include "Util.h" /* Cairo limit: * https://lists.cairographics.org/archives/cairo/2010-December/021422.html @@ -58,14 +57,15 @@ Image::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { ctor->InstanceTemplate()->SetInternalFieldCount(1); ctor->SetClassName(Nan::New("Image").ToLocalChecked()); - // Prototype - Local proto = ctor->PrototypeTemplate(); - SetProtoAccessor(proto, Nan::New("complete").ToLocalChecked(), GetComplete, NULL, ctor); - SetProtoAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth, SetWidth, ctor); - SetProtoAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight, SetHeight, ctor); - SetProtoAccessor(proto, Nan::New("naturalWidth").ToLocalChecked(), GetNaturalWidth, NULL, ctor); - SetProtoAccessor(proto, Nan::New("naturalHeight").ToLocalChecked(), GetNaturalHeight, NULL, ctor); - SetProtoAccessor(proto, Nan::New("dataMode").ToLocalChecked(), GetDataMode, SetDataMode, ctor); + // link getters and setter to the object property + Local inst = ctor->InstanceTemplate(); + Nan::SetAccessor(inst, Nan::New("complete").ToLocalChecked(), GetComplete, NULL); + Nan::SetAccessor(inst, Nan::New("width").ToLocalChecked(), GetWidth, SetWidth); + Nan::SetAccessor(inst, Nan::New("height").ToLocalChecked(), GetHeight, SetHeight);; + Nan::SetAccessor(inst, Nan::New("naturalWidth").ToLocalChecked(), GetNaturalWidth, NULL); + Nan::SetAccessor(inst, Nan::New("naturalHeight").ToLocalChecked(), GetNaturalHeight, NULL); + Nan::SetAccessor(inst, Nan::New("dataMode").ToLocalChecked(), GetDataMode, SetDataMode); + ctor->Set(Nan::New("MODE_IMAGE").ToLocalChecked(), Nan::New(DATA_IMAGE)); ctor->Set(Nan::New("MODE_MIME").ToLocalChecked(), Nan::New(DATA_MIME)); diff --git a/src/ImageData.cc b/src/ImageData.cc index 668733d39..53f52a7c6 100644 --- a/src/ImageData.cc +++ b/src/ImageData.cc @@ -2,8 +2,6 @@ #include "ImageData.h" -#include "Util.h" - using namespace v8; Nan::Persistent ImageData::constructor; @@ -22,10 +20,12 @@ ImageData::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { ctor->InstanceTemplate()->SetInternalFieldCount(1); ctor->SetClassName(Nan::New("ImageData").ToLocalChecked()); - // Prototype - Local proto = ctor->PrototypeTemplate(); - SetProtoAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth, NULL, ctor); - SetProtoAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight, NULL, ctor); + // link getters and setter to the object property + Local inst = ctor->InstanceTemplate(); + + Nan::SetAccessor(inst, Nan::New("width").ToLocalChecked(), GetWidth, NULL); + Nan::SetAccessor(inst, Nan::New("height").ToLocalChecked(), GetHeight, NULL); + Local ctx = Nan::GetCurrentContext(); Nan::Set(target, Nan::New("ImageData").ToLocalChecked(), ctor->GetFunction(ctx).ToLocalChecked()); } diff --git a/src/Util.h b/src/Util.h index dba6883a2..0e6d1d89c 100644 --- a/src/Util.h +++ b/src/Util.h @@ -1,32 +1,7 @@ #pragma once -#include -#include #include -// Wrapper around Nan::SetAccessor that makes it easier to change the last -// argument (signature). Getters/setters must be accessed only when there is -// actually an instance, i.e. MyClass.prototype.getter1 should not try to -// unwrap the non-existent 'this'. See #803, #847, #885, nodejs/node#15099, ... -inline void SetProtoAccessor( - v8::Local tpl, - v8::Local name, - Nan::GetterCallback getter, - Nan::SetterCallback setter, - v8::Local ctor - ) { - Nan::SetAccessor( - tpl, - name, - getter, - setter, - v8::Local(), - v8::DEFAULT, - v8::None, - v8::AccessorSignature::New(v8::Isolate::GetCurrent(), ctor) - ); -} - inline bool streq_casein(std::string& str1, std::string& str2) { return str1.size() == str2.size() && std::equal(str1.begin(), str1.end(), str2.begin(), [](char& c1, char& c2) { return c1 == c2 || std::toupper(c1) == std::toupper(c2); diff --git a/test/canvas.test.js b/test/canvas.test.js index 670127783..9dc3dd1c2 100644 --- a/test/canvas.test.js +++ b/test/canvas.test.js @@ -29,12 +29,9 @@ describe('Canvas', function () { // Run with --expose-gc and uncomment this line to help find memory problems: // afterEach(gc); - it('Prototype and ctor are well-shaped, don\'t hit asserts on accessors (GH-803)', function () { + it('Instance and ctor are well-shaped, don\'t hit asserts on accessors (GH-803)', function () { const c = new Canvas(10, 10) - assert.throws(function () { Canvas.prototype.width }, /incompatible receiver/) - assert(!c.hasOwnProperty('width')) assert('width' in c) - assert('width' in Canvas.prototype) }) it('.parseFont()', function () { diff --git a/test/image.test.js b/test/image.test.js index 8d54dd90f..151cc7ad7 100644 --- a/test/image.test.js +++ b/test/image.test.js @@ -22,12 +22,9 @@ const svgTree = path.join(__dirname, '/fixtures/tree.svg') const bmpDir = path.join(__dirname, '/fixtures/bmp') describe('Image', function () { - it('Prototype and ctor are well-shaped, don\'t hit asserts on accessors (GH-803)', function () { + it('Instance and ctor are well-shaped, don\'t hit asserts on accessors (GH-803)', function () { const img = new Image() - assert.throws(function () { Image.prototype.width }, /incompatible receiver/) - assert(!img.hasOwnProperty('width')) assert('width' in img) - assert(Image.prototype.hasOwnProperty('width')) }) it('loads JPEG image', function () { diff --git a/test/imageData.test.js b/test/imageData.test.js index d3c84c29a..fbb021d45 100644 --- a/test/imageData.test.js +++ b/test/imageData.test.js @@ -8,9 +8,6 @@ const {ImageData} = require('../') const assert = require('assert') describe('ImageData', function () { - it('Prototype and ctor are well-shaped, don\'t hit asserts on accessors (GH-803)', function () { - assert.throws(function () { ImageData.prototype.width }, /incompatible receiver/) - }) it('stringifies as [object ImageData]', function () { const imageData = createImageData(2, 3) From 7bf5d4d7b352fe4f29afe60159f6795bbb860e63 Mon Sep 17 00:00:00 2001 From: TheDadi Date: Tue, 11 Oct 2022 20:51:01 +0200 Subject: [PATCH 04/10] Update CHANGELOG.md --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 513643483..99b4636c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,13 @@ project adheres to [Semantic Versioning](http://semver.org/). ### Added ### Fixed +2.10.2 +================== +### Fixed +* Fix `Assertion failed: (object->InternalFieldCount() > 0), function Unwrap, file nan_object_wrap.h, line 32.` ([#2025](https://github.com/Automattic/node-canvas/issues/2025)) +* Update nan to v2.17.0 to ensure Node.js v18+ support. +* Added prebuilt images for Node.js v18 + 2.10.1 ================== ### Fixed From 805776c377e95a3869b55b9c7ef975c512fe225c Mon Sep 17 00:00:00 2001 From: TheDadi Date: Tue, 11 Oct 2022 20:53:34 +0200 Subject: [PATCH 05/10] Update CHANGELOG.md --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99b4636c0..ddd3977af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,8 +15,11 @@ project adheres to [Semantic Versioning](http://semver.org/). ================== ### Fixed * Fix `Assertion failed: (object->InternalFieldCount() > 0), function Unwrap, file nan_object_wrap.h, line 32.` ([#2025](https://github.com/Automattic/node-canvas/issues/2025)) +### Added +* Prebuilt images for Node.js v18 +### Changed * Update nan to v2.17.0 to ensure Node.js v18+ support. -* Added prebuilt images for Node.js v18 +* Implement `SetAccessor` on `InstanceTemplate` instead of `PrototypeTemplate` 2.10.1 ================== From bce1898dfe85a074361fcb024f9cb553fe119737 Mon Sep 17 00:00:00 2001 From: TheDadi Date: Tue, 11 Oct 2022 21:16:30 +0200 Subject: [PATCH 06/10] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ddd3977af..719c9e1e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ project adheres to [Semantic Versioning](http://semver.org/). ### Fixed * Fix `Assertion failed: (object->InternalFieldCount() > 0), function Unwrap, file nan_object_wrap.h, line 32.` ([#2025](https://github.com/Automattic/node-canvas/issues/2025)) ### Added -* Prebuilt images for Node.js v18 +* Prebuilt binaries for Node.js v18 ### Changed * Update nan to v2.17.0 to ensure Node.js v18+ support. * Implement `SetAccessor` on `InstanceTemplate` instead of `PrototypeTemplate` From 283dc06569ebe310528cc60a5be00ca2792ebeb1 Mon Sep 17 00:00:00 2001 From: TheDadi Date: Wed, 12 Oct 2022 10:01:00 +0200 Subject: [PATCH 07/10] reimplement accessors on prototype --- src/Canvas.cc | 42 ++++-- src/CanvasRenderingContext2d.cc | 229 ++++++++++++++++++++++++++++---- src/Image.cc | 50 +++++-- src/ImageData.cc | 18 ++- test/canvas.test.js | 5 +- test/image.test.js | 5 +- test/imageData.test.js | 3 + 7 files changed, 299 insertions(+), 53 deletions(-) diff --git a/src/Canvas.cc b/src/Canvas.cc index 45b9fb2bb..a7318ca82 100644 --- a/src/Canvas.cc +++ b/src/Canvas.cc @@ -57,21 +57,17 @@ Canvas::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { ctor->SetClassName(Nan::New("Canvas").ToLocalChecked()); // Prototype - Local proto = ctor->InstanceTemplate(); + Local proto = ctor->PrototypeTemplate(); Nan::SetPrototypeMethod(ctor, "toBuffer", ToBuffer); Nan::SetPrototypeMethod(ctor, "streamPNGSync", StreamPNGSync); Nan::SetPrototypeMethod(ctor, "streamPDFSync", StreamPDFSync); #ifdef HAVE_JPEG Nan::SetPrototypeMethod(ctor, "streamJPEGSync", StreamJPEGSync); #endif - - // link getters and setter to the object property - Local inst = ctor->InstanceTemplate(); - - Nan::SetAccessor(inst, Nan::New("type").ToLocalChecked(), GetType, NULL); - Nan::SetAccessor(inst, Nan::New("stride").ToLocalChecked(), GetStride, NULL); - Nan::SetAccessor(inst, Nan::New("width").ToLocalChecked(), GetWidth, SetWidth); - Nan::SetAccessor(inst, Nan::New("height").ToLocalChecked(), GetHeight, SetHeight); + Nan::SetAccessor(proto, Nan::New("type").ToLocalChecked(), GetType); + Nan::SetAccessor(proto, Nan::New("stride").ToLocalChecked(), GetStride); + Nan::SetAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth, SetWidth); + Nan::SetAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight, SetHeight); Nan::SetTemplate(proto, "PNG_NO_FILTERS", Nan::New(PNG_NO_FILTERS)); Nan::SetTemplate(proto, "PNG_FILTER_NONE", Nan::New(PNG_FILTER_NONE)); @@ -148,6 +144,10 @@ NAN_METHOD(Canvas::New) { */ NAN_GETTER(Canvas::GetType) { + if (!Canvas::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Canvas.GetType called on incompatible receiver"); + return; + } Canvas *canvas = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(canvas->backend()->getName()).ToLocalChecked()); } @@ -156,6 +156,10 @@ NAN_GETTER(Canvas::GetType) { * Get stride. */ NAN_GETTER(Canvas::GetStride) { + if (!Canvas::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Canvas.GetStride called on incompatible receiver"); + return; + } Canvas *canvas = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(canvas->stride())); } @@ -165,6 +169,10 @@ NAN_GETTER(Canvas::GetStride) { */ NAN_GETTER(Canvas::GetWidth) { + if (!Canvas::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Canvas.GetWidth called on incompatible receiver"); + return; + } Canvas *canvas = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(canvas->getWidth())); } @@ -174,6 +182,10 @@ NAN_GETTER(Canvas::GetWidth) { */ NAN_SETTER(Canvas::SetWidth) { + if (!Canvas::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Canvas.SetWidth called on incompatible receiver"); + return; + } if (value->IsNumber()) { Canvas *canvas = Nan::ObjectWrap::Unwrap(info.This()); canvas->backend()->setWidth(Nan::To(value).FromMaybe(0)); @@ -186,6 +198,10 @@ NAN_SETTER(Canvas::SetWidth) { */ NAN_GETTER(Canvas::GetHeight) { + if (!Canvas::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Canvas.GetHeight called on incompatible receiver"); + return; + } Canvas *canvas = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(canvas->getHeight())); } @@ -195,6 +211,10 @@ NAN_GETTER(Canvas::GetHeight) { */ NAN_SETTER(Canvas::SetHeight) { + if (!Canvas::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Canvas.SetHeight called on incompatible receiver"); + return; + } if (value->IsNumber()) { Canvas *canvas = Nan::ObjectWrap::Unwrap(info.This()); canvas->backend()->setHeight(Nan::To(value).FromMaybe(0)); @@ -777,13 +797,13 @@ NAN_METHOD(Canvas::RegisterFont) { NAN_METHOD(Canvas::DeregisterAllFonts) { // Unload all fonts from pango to free up memory bool success = true; - + std::for_each(font_face_list.begin(), font_face_list.end(), [&](FontFace& f) { if (!deregister_font( (unsigned char *)f.file_path )) success = false; pango_font_description_free(f.user_desc); pango_font_description_free(f.sys_desc); }); - + font_face_list.clear(); if (!success) Nan::ThrowError("Could not deregister one or more fonts"); } diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index bb0aec223..5dee6417a 100644 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -101,6 +101,7 @@ Context2d::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { ctor->SetClassName(Nan::New("CanvasRenderingContext2D").ToLocalChecked()); // Prototype + Local proto = ctor->PrototypeTemplate(); Nan::SetPrototypeMethod(ctor, "drawImage", DrawImage); Nan::SetPrototypeMethod(ctor, "putImageData", PutImageData); Nan::SetPrototypeMethod(ctor, "getImageData", GetImageData); @@ -141,31 +142,29 @@ Context2d::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { Nan::SetPrototypeMethod(ctor, "createPattern", CreatePattern); Nan::SetPrototypeMethod(ctor, "createLinearGradient", CreateLinearGradient); Nan::SetPrototypeMethod(ctor, "createRadialGradient", CreateRadialGradient); - - Local inst = ctor->InstanceTemplate(); - Nan::SetAccessor(inst, Nan::New("pixelFormat").ToLocalChecked(), GetFormat, NULL); - Nan::SetAccessor(inst, Nan::New("patternQuality").ToLocalChecked(), GetPatternQuality, SetPatternQuality); - Nan::SetAccessor(inst, Nan::New("imageSmoothingEnabled").ToLocalChecked(), GetImageSmoothingEnabled, SetImageSmoothingEnabled); - Nan::SetAccessor(inst, Nan::New("globalCompositeOperation").ToLocalChecked(), GetGlobalCompositeOperation, SetGlobalCompositeOperation); - Nan::SetAccessor(inst, Nan::New("globalAlpha").ToLocalChecked(), GetGlobalAlpha, SetGlobalAlpha); - Nan::SetAccessor(inst, Nan::New("shadowColor").ToLocalChecked(), GetShadowColor, SetShadowColor); - Nan::SetAccessor(inst, Nan::New("miterLimit").ToLocalChecked(), GetMiterLimit, SetMiterLimit); - Nan::SetAccessor(inst, Nan::New("lineWidth").ToLocalChecked(), GetLineWidth, SetLineWidth); - Nan::SetAccessor(inst, Nan::New("lineCap").ToLocalChecked(), GetLineCap, SetLineCap); - Nan::SetAccessor(inst, Nan::New("lineJoin").ToLocalChecked(), GetLineJoin, SetLineJoin); - Nan::SetAccessor(inst, Nan::New("lineDashOffset").ToLocalChecked(), GetLineDashOffset, SetLineDashOffset); - Nan::SetAccessor(inst, Nan::New("shadowOffsetX").ToLocalChecked(), GetShadowOffsetX, SetShadowOffsetX); - Nan::SetAccessor(inst, Nan::New("shadowOffsetY").ToLocalChecked(), GetShadowOffsetY, SetShadowOffsetY); - Nan::SetAccessor(inst, Nan::New("shadowBlur").ToLocalChecked(), GetShadowBlur, SetShadowBlur); - Nan::SetAccessor(inst, Nan::New("antialias").ToLocalChecked(), GetAntiAlias, SetAntiAlias); - Nan::SetAccessor(inst, Nan::New("textDrawingMode").ToLocalChecked(), GetTextDrawingMode, SetTextDrawingMode); - Nan::SetAccessor(inst, Nan::New("quality").ToLocalChecked(), GetQuality, SetQuality); - Nan::SetAccessor(inst, Nan::New("currentTransform").ToLocalChecked(), GetCurrentTransform, SetCurrentTransform); - Nan::SetAccessor(inst, Nan::New("fillStyle").ToLocalChecked(), GetFillStyle, SetFillStyle); - Nan::SetAccessor(inst, Nan::New("strokeStyle").ToLocalChecked(), GetStrokeStyle, SetStrokeStyle); - Nan::SetAccessor(inst, Nan::New("font").ToLocalChecked(), GetFont, SetFont); - Nan::SetAccessor(inst, Nan::New("textBaseline").ToLocalChecked(), GetTextBaseline, SetTextBaseline); - Nan::SetAccessor(inst, Nan::New("textAlign").ToLocalChecked(), GetTextAlign, SetTextAlign); + Nan::SetAccessor(proto, Nan::New("pixelFormat").ToLocalChecked(), GetFormat); + Nan::SetAccessor(proto, Nan::New("patternQuality").ToLocalChecked(), GetPatternQuality, SetPatternQuality); + Nan::SetAccessor(proto, Nan::New("imageSmoothingEnabled").ToLocalChecked(), GetImageSmoothingEnabled, SetImageSmoothingEnabled); + Nan::SetAccessor(proto, Nan::New("globalCompositeOperation").ToLocalChecked(), GetGlobalCompositeOperation, SetGlobalCompositeOperation); + Nan::SetAccessor(proto, Nan::New("globalAlpha").ToLocalChecked(), GetGlobalAlpha, SetGlobalAlpha); + Nan::SetAccessor(proto, Nan::New("shadowColor").ToLocalChecked(), GetShadowColor, SetShadowColor); + Nan::SetAccessor(proto, Nan::New("miterLimit").ToLocalChecked(), GetMiterLimit, SetMiterLimit); + Nan::SetAccessor(proto, Nan::New("lineWidth").ToLocalChecked(), GetLineWidth, SetLineWidth); + Nan::SetAccessor(proto, Nan::New("lineCap").ToLocalChecked(), GetLineCap, SetLineCap); + Nan::SetAccessor(proto, Nan::New("lineJoin").ToLocalChecked(), GetLineJoin, SetLineJoin); + Nan::SetAccessor(proto, Nan::New("lineDashOffset").ToLocalChecked(), GetLineDashOffset, SetLineDashOffset); + Nan::SetAccessor(proto, Nan::New("shadowOffsetX").ToLocalChecked(), GetShadowOffsetX, SetShadowOffsetX); + Nan::SetAccessor(proto, Nan::New("shadowOffsetY").ToLocalChecked(), GetShadowOffsetY, SetShadowOffsetY); + Nan::SetAccessor(proto, Nan::New("shadowBlur").ToLocalChecked(), GetShadowBlur, SetShadowBlur); + Nan::SetAccessor(proto, Nan::New("antialias").ToLocalChecked(), GetAntiAlias, SetAntiAlias); + Nan::SetAccessor(proto, Nan::New("textDrawingMode").ToLocalChecked(), GetTextDrawingMode, SetTextDrawingMode); + Nan::SetAccessor(proto, Nan::New("quality").ToLocalChecked(), GetQuality, SetQuality); + Nan::SetAccessor(proto, Nan::New("currentTransform").ToLocalChecked(), GetCurrentTransform, SetCurrentTransform); + Nan::SetAccessor(proto, Nan::New("fillStyle").ToLocalChecked(), GetFillStyle, SetFillStyle); + Nan::SetAccessor(proto, Nan::New("strokeStyle").ToLocalChecked(), GetStrokeStyle, SetStrokeStyle); + Nan::SetAccessor(proto, Nan::New("font").ToLocalChecked(), GetFont, SetFont); + Nan::SetAccessor(proto, Nan::New("textBaseline").ToLocalChecked(), GetTextBaseline, SetTextBaseline); + Nan::SetAccessor(proto, Nan::New("textAlign").ToLocalChecked(), GetTextAlign, SetTextAlign); Local ctx = Nan::GetCurrentContext(); Nan::Set(target, Nan::New("CanvasRenderingContext2d").ToLocalChecked(), ctor->GetFunction(ctx).ToLocalChecked()); Nan::Set(target, Nan::New("CanvasRenderingContext2dInit").ToLocalChecked(), Nan::New(SaveExternalModules)); @@ -761,6 +760,10 @@ NAN_METHOD(Context2d::SaveExternalModules) { */ NAN_GETTER(Context2d::GetFormat) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetFormat called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); std::string pixelFormatString; switch (context->canvas()->backend()->getFormat()) { @@ -1440,6 +1443,10 @@ NAN_METHOD(Context2d::DrawImage) { */ NAN_GETTER(Context2d::GetGlobalAlpha) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetGlobalAlpha called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(context->state->globalAlpha)); } @@ -1449,6 +1456,10 @@ NAN_GETTER(Context2d::GetGlobalAlpha) { */ NAN_SETTER(Context2d::SetGlobalAlpha) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetGlobalAlpha called on incompatible receiver"); + return; + } double n = Nan::To(value).FromMaybe(0); if (n >= 0 && n <= 1) { Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); @@ -1461,6 +1472,10 @@ NAN_SETTER(Context2d::SetGlobalAlpha) { */ NAN_GETTER(Context2d::GetGlobalCompositeOperation) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetGlobalCompositeOperation called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); cairo_t *ctx = context->context(); @@ -1511,6 +1526,10 @@ NAN_GETTER(Context2d::GetGlobalCompositeOperation) { */ NAN_SETTER(Context2d::SetPatternQuality) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetPatternQuality called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); Nan::Utf8String quality(Nan::To(value).ToLocalChecked()); if (0 == strcmp("fast", *quality)) { @@ -1531,6 +1550,10 @@ NAN_SETTER(Context2d::SetPatternQuality) { */ NAN_GETTER(Context2d::GetPatternQuality) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetPatternQuality called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); const char *quality; switch (context->state->patternQuality) { @@ -1548,6 +1571,10 @@ NAN_GETTER(Context2d::GetPatternQuality) { */ NAN_SETTER(Context2d::SetImageSmoothingEnabled) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetImageSmoothingEnabled called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); context->state->imageSmoothingEnabled = Nan::To(value).FromMaybe(false); } @@ -1557,6 +1584,10 @@ NAN_SETTER(Context2d::SetImageSmoothingEnabled) { */ NAN_GETTER(Context2d::GetImageSmoothingEnabled) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetImageSmoothingEnabled called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(context->state->imageSmoothingEnabled)); } @@ -1566,6 +1597,10 @@ NAN_GETTER(Context2d::GetImageSmoothingEnabled) { */ NAN_SETTER(Context2d::SetGlobalCompositeOperation) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetGlobalCompositeOperation called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); cairo_t *ctx = context->context(); Nan::Utf8String opStr(Nan::To(value).ToLocalChecked()); // Unlike CSS colors, this *is* case-sensitive @@ -1613,6 +1648,10 @@ NAN_SETTER(Context2d::SetGlobalCompositeOperation) { */ NAN_GETTER(Context2d::GetShadowOffsetX) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetShadowOffsetX called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(context->state->shadowOffsetX)); } @@ -1622,6 +1661,10 @@ NAN_GETTER(Context2d::GetShadowOffsetX) { */ NAN_SETTER(Context2d::SetShadowOffsetX) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetShadowOffsetX called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); context->state->shadowOffsetX = Nan::To(value).FromMaybe(0); } @@ -1631,6 +1674,10 @@ NAN_SETTER(Context2d::SetShadowOffsetX) { */ NAN_GETTER(Context2d::GetShadowOffsetY) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetShadowOffsetY called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(context->state->shadowOffsetY)); } @@ -1640,6 +1687,10 @@ NAN_GETTER(Context2d::GetShadowOffsetY) { */ NAN_SETTER(Context2d::SetShadowOffsetY) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetShadowOffsetY called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); context->state->shadowOffsetY = Nan::To(value).FromMaybe(0); } @@ -1649,6 +1700,10 @@ NAN_SETTER(Context2d::SetShadowOffsetY) { */ NAN_GETTER(Context2d::GetShadowBlur) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetShadowBlur called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(context->state->shadowBlur)); } @@ -1658,6 +1713,10 @@ NAN_GETTER(Context2d::GetShadowBlur) { */ NAN_SETTER(Context2d::SetShadowBlur) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetShadowBlur called on incompatible receiver"); + return; + } int n = Nan::To(value).FromMaybe(0); if (n >= 0) { Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); @@ -1670,6 +1729,10 @@ NAN_SETTER(Context2d::SetShadowBlur) { */ NAN_GETTER(Context2d::GetAntiAlias) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetAntiAlias called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); const char *aa; switch (cairo_get_antialias(context->context())) { @@ -1686,6 +1749,10 @@ NAN_GETTER(Context2d::GetAntiAlias) { */ NAN_SETTER(Context2d::SetAntiAlias) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetAntiAlias called on incompatible receiver"); + return; + } Nan::Utf8String str(Nan::To(value).ToLocalChecked()); Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); cairo_t *ctx = context->context(); @@ -1709,6 +1776,10 @@ NAN_SETTER(Context2d::SetAntiAlias) { */ NAN_GETTER(Context2d::GetTextDrawingMode) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetTextDrawingMode called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); const char *mode; if (context->state->textDrawingMode == TEXT_DRAW_PATHS) { @@ -1726,6 +1797,10 @@ NAN_GETTER(Context2d::GetTextDrawingMode) { */ NAN_SETTER(Context2d::SetTextDrawingMode) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetTextDrawingMode called on incompatible receiver"); + return; + } Nan::Utf8String str(Nan::To(value).ToLocalChecked()); Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); if (0 == strcmp("path", *str)) { @@ -1740,6 +1815,10 @@ NAN_SETTER(Context2d::SetTextDrawingMode) { */ NAN_GETTER(Context2d::GetQuality) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetQuality called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); const char *filter; switch (cairo_pattern_get_filter(cairo_get_source(context->context()))) { @@ -1757,6 +1836,10 @@ NAN_GETTER(Context2d::GetQuality) { */ NAN_SETTER(Context2d::SetQuality) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetQuality called on incompatible receiver"); + return; + } Nan::Utf8String str(Nan::To(value).ToLocalChecked()); Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); cairo_filter_t filter; @@ -1819,6 +1902,10 @@ void parse_matrix_from_object(cairo_matrix_t &matrix, Local mat) { */ NAN_GETTER(Context2d::GetCurrentTransform) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetCurrentTransform called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); Local instance = get_current_transform(context); @@ -1830,6 +1917,10 @@ NAN_GETTER(Context2d::GetCurrentTransform) { */ NAN_SETTER(Context2d::SetCurrentTransform) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetCurrentTransform called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); Local ctx = Nan::GetCurrentContext(); Local mat = Nan::To(value).ToLocalChecked(); @@ -1851,6 +1942,10 @@ NAN_SETTER(Context2d::SetCurrentTransform) { */ NAN_GETTER(Context2d::GetFillStyle) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetFillStyle called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); Isolate *iso = Isolate::GetCurrent(); Local style; @@ -1868,6 +1963,10 @@ NAN_GETTER(Context2d::GetFillStyle) { */ NAN_SETTER(Context2d::SetFillStyle) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetFillStyle called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); if (value->IsString()) { @@ -1895,6 +1994,10 @@ NAN_SETTER(Context2d::SetFillStyle) { */ NAN_GETTER(Context2d::GetStrokeStyle) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetStrokeStyle called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); Local style; @@ -1911,6 +2014,10 @@ NAN_GETTER(Context2d::GetStrokeStyle) { */ NAN_SETTER(Context2d::SetStrokeStyle) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetStrokeStyle called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); if (value->IsString()) { @@ -1938,6 +2045,10 @@ NAN_SETTER(Context2d::SetStrokeStyle) { */ NAN_GETTER(Context2d::GetMiterLimit) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetMiterLimit called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(cairo_get_miter_limit(context->context()))); } @@ -1947,6 +2058,10 @@ NAN_GETTER(Context2d::GetMiterLimit) { */ NAN_SETTER(Context2d::SetMiterLimit) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetMiterLimit called on incompatible receiver"); + return; + } double n = Nan::To(value).FromMaybe(0); if (n > 0) { Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); @@ -1959,6 +2074,10 @@ NAN_SETTER(Context2d::SetMiterLimit) { */ NAN_GETTER(Context2d::GetLineWidth) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetLineWidth called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(cairo_get_line_width(context->context()))); } @@ -1968,6 +2087,10 @@ NAN_GETTER(Context2d::GetLineWidth) { */ NAN_SETTER(Context2d::SetLineWidth) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetLineWidth called on incompatible receiver"); + return; + } double n = Nan::To(value).FromMaybe(0); if (n > 0 && n != std::numeric_limits::infinity()) { Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); @@ -1980,6 +2103,10 @@ NAN_SETTER(Context2d::SetLineWidth) { */ NAN_GETTER(Context2d::GetLineJoin) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetLineJoin called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); const char *join; switch (cairo_get_line_join(context->context())) { @@ -1995,6 +2122,10 @@ NAN_GETTER(Context2d::GetLineJoin) { */ NAN_SETTER(Context2d::SetLineJoin) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetLineJoin called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); cairo_t *ctx = context->context(); Nan::Utf8String type(Nan::To(value).ToLocalChecked()); @@ -2012,6 +2143,10 @@ NAN_SETTER(Context2d::SetLineJoin) { */ NAN_GETTER(Context2d::GetLineCap) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetLineCap called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); const char *cap; switch (cairo_get_line_cap(context->context())) { @@ -2027,6 +2162,10 @@ NAN_GETTER(Context2d::GetLineCap) { */ NAN_SETTER(Context2d::SetLineCap) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetLineCap called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); cairo_t *ctx = context->context(); Nan::Utf8String type(Nan::To(value).ToLocalChecked()); @@ -2061,6 +2200,10 @@ NAN_METHOD(Context2d::IsPointInPath) { */ NAN_SETTER(Context2d::SetShadowColor) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetShadowColor called on incompatible receiver"); + return; + } short ok; Nan::Utf8String str(Nan::To(value).ToLocalChecked()); uint32_t rgba = rgba_from_string(*str, &ok); @@ -2075,6 +2218,10 @@ NAN_SETTER(Context2d::SetShadowColor) { */ NAN_GETTER(Context2d::GetShadowColor) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetShadowColor called on incompatible receiver"); + return; + } char buf[64]; Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); rgba_to_string(context->state->shadow, buf, sizeof(buf)); @@ -2550,6 +2697,10 @@ NAN_METHOD(Context2d::MoveTo) { */ NAN_GETTER(Context2d::GetFont) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetFont called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); Isolate *iso = Isolate::GetCurrent(); Local font; @@ -2572,6 +2723,10 @@ NAN_GETTER(Context2d::GetFont) { */ NAN_SETTER(Context2d::SetFont) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetFont called on incompatible receiver"); + return; + } if (!value->IsString()) return; Isolate *iso = Isolate::GetCurrent(); @@ -2629,6 +2784,10 @@ NAN_SETTER(Context2d::SetFont) { */ NAN_GETTER(Context2d::GetTextBaseline) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetTextBaseline called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); Isolate *iso = Isolate::GetCurrent(); Local font; @@ -2646,6 +2805,10 @@ NAN_GETTER(Context2d::GetTextBaseline) { */ NAN_SETTER(Context2d::SetTextBaseline) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetTextBaseline called on incompatible receiver"); + return; + } if (!value->IsString()) return; Nan::Utf8String opStr(Nan::To(value).ToLocalChecked()); @@ -2670,6 +2833,10 @@ NAN_SETTER(Context2d::SetTextBaseline) { */ NAN_GETTER(Context2d::GetTextAlign) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetTextAlign called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); Isolate *iso = Isolate::GetCurrent(); Local font; @@ -2687,6 +2854,10 @@ NAN_GETTER(Context2d::GetTextAlign) { */ NAN_SETTER(Context2d::SetTextAlign) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetTextAlign called on incompatible receiver"); + return; + } if (!value->IsString()) return; Nan::Utf8String opStr(Nan::To(value).ToLocalChecked()); @@ -2847,6 +3018,10 @@ NAN_METHOD(Context2d::GetLineDash) { * ref: http://www.w3.org/TR/2dcontext/#dom-context-2d-setlinedash */ NAN_SETTER(Context2d::SetLineDashOffset) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.SetLineDashOffset called on incompatible receiver"); + return; + } double offset = Nan::To(value).FromMaybe(0); if (!std::isfinite(offset)) return; @@ -2864,6 +3039,10 @@ NAN_SETTER(Context2d::SetLineDashOffset) { * ref: http://www.w3.org/TR/2dcontext/#dom-context-2d-setlinedash */ NAN_GETTER(Context2d::GetLineDashOffset) { + if (!Context2d::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Context2d.GetLineDashOffset called on incompatible receiver"); + return; + } Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); cairo_t *ctx = context->context(); double offset; diff --git a/src/Image.cc b/src/Image.cc index cca3fe3d1..35ee7947a 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -57,15 +57,14 @@ Image::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { ctor->InstanceTemplate()->SetInternalFieldCount(1); ctor->SetClassName(Nan::New("Image").ToLocalChecked()); - // link getters and setter to the object property - Local inst = ctor->InstanceTemplate(); - Nan::SetAccessor(inst, Nan::New("complete").ToLocalChecked(), GetComplete, NULL); - Nan::SetAccessor(inst, Nan::New("width").ToLocalChecked(), GetWidth, SetWidth); - Nan::SetAccessor(inst, Nan::New("height").ToLocalChecked(), GetHeight, SetHeight);; - Nan::SetAccessor(inst, Nan::New("naturalWidth").ToLocalChecked(), GetNaturalWidth, NULL); - Nan::SetAccessor(inst, Nan::New("naturalHeight").ToLocalChecked(), GetNaturalHeight, NULL); - Nan::SetAccessor(inst, Nan::New("dataMode").ToLocalChecked(), GetDataMode, SetDataMode); - + // Prototype + Local proto = ctor->PrototypeTemplate(); + Nan::SetAccessor(proto, Nan::New("complete").ToLocalChecked(), GetComplete); + Nan::SetAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth, SetWidth); + Nan::SetAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight, SetHeight); + Nan::SetAccessor(proto, Nan::New("naturalWidth").ToLocalChecked(), GetNaturalWidth); + Nan::SetAccessor(proto, Nan::New("naturalHeight").ToLocalChecked(), GetNaturalHeight); + Nan::SetAccessor(proto, Nan::New("dataMode").ToLocalChecked(), GetDataMode, SetDataMode); ctor->Set(Nan::New("MODE_IMAGE").ToLocalChecked(), Nan::New(DATA_IMAGE)); ctor->Set(Nan::New("MODE_MIME").ToLocalChecked(), Nan::New(DATA_MIME)); @@ -108,6 +107,10 @@ NAN_GETTER(Image::GetComplete) { */ NAN_GETTER(Image::GetDataMode) { + if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Image.GetDataMode called on incompatible receiver"); + return; + } Image *img = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(img->data_mode)); } @@ -117,6 +120,10 @@ NAN_GETTER(Image::GetDataMode) { */ NAN_SETTER(Image::SetDataMode) { + if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Image.SetDataMode called on incompatible receiver"); + return; + } if (value->IsNumber()) { Image *img = Nan::ObjectWrap::Unwrap(info.This()); int mode = Nan::To(value).FromMaybe(0); @@ -129,6 +136,10 @@ NAN_SETTER(Image::SetDataMode) { */ NAN_GETTER(Image::GetNaturalWidth) { + if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Image.GetNaturalWidth called on incompatible receiver"); + return; + } Image *img = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(img->naturalWidth)); } @@ -138,6 +149,10 @@ NAN_GETTER(Image::GetNaturalWidth) { */ NAN_GETTER(Image::GetWidth) { + if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Image.GetWidth called on incompatible receiver"); + return; + } Image *img = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(img->width)); } @@ -147,6 +162,10 @@ NAN_GETTER(Image::GetWidth) { */ NAN_SETTER(Image::SetWidth) { + if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Image.SetWidth called on incompatible receiver"); + return; + } if (value->IsNumber()) { Image *img = Nan::ObjectWrap::Unwrap(info.This()); img->width = Nan::To(value).FromMaybe(0); @@ -158,6 +177,10 @@ NAN_SETTER(Image::SetWidth) { */ NAN_GETTER(Image::GetNaturalHeight) { + if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Image.GetNaturalHeight called on incompatible receiver"); + return; + } Image *img = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(img->naturalHeight)); } @@ -167,6 +190,10 @@ NAN_GETTER(Image::GetNaturalHeight) { */ NAN_GETTER(Image::GetHeight) { + if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method Image.GetHeight called on incompatible receiver"); + return; + } Image *img = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(img->height)); } @@ -175,6 +202,11 @@ NAN_GETTER(Image::GetHeight) { */ NAN_SETTER(Image::SetHeight) { + if (!Image::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + // #1534 + Nan::ThrowTypeError("Method Image.SetHeight called on incompatible receiver"); + return; + } if (value->IsNumber()) { Image *img = Nan::ObjectWrap::Unwrap(info.This()); img->height = Nan::To(value).FromMaybe(0); diff --git a/src/ImageData.cc b/src/ImageData.cc index 53f52a7c6..03da2e270 100644 --- a/src/ImageData.cc +++ b/src/ImageData.cc @@ -20,12 +20,10 @@ ImageData::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { ctor->InstanceTemplate()->SetInternalFieldCount(1); ctor->SetClassName(Nan::New("ImageData").ToLocalChecked()); - // link getters and setter to the object property - Local inst = ctor->InstanceTemplate(); - - Nan::SetAccessor(inst, Nan::New("width").ToLocalChecked(), GetWidth, NULL); - Nan::SetAccessor(inst, Nan::New("height").ToLocalChecked(), GetHeight, NULL); - + // Prototype + Local proto = ctor->PrototypeTemplate(); + Nan::SetAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth); + Nan::SetAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight); Local ctx = Nan::GetCurrentContext(); Nan::Set(target, Nan::New("ImageData").ToLocalChecked(), ctor->GetFunction(ctx).ToLocalChecked()); } @@ -126,6 +124,10 @@ NAN_METHOD(ImageData::New) { */ NAN_GETTER(ImageData::GetWidth) { + if (!ImageData::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method ImageData.GetWidth called on incompatible receiver"); + return; + } ImageData *imageData = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(imageData->width())); } @@ -135,6 +137,10 @@ NAN_GETTER(ImageData::GetWidth) { */ NAN_GETTER(ImageData::GetHeight) { + if (!ImageData::constructor.Get(info.GetIsolate())->HasInstance(info.This())) { + Nan::ThrowTypeError("Method ImageData.GetHeight called on incompatible receiver"); + return; + } ImageData *imageData = Nan::ObjectWrap::Unwrap(info.This()); info.GetReturnValue().Set(Nan::New(imageData->height())); } diff --git a/test/canvas.test.js b/test/canvas.test.js index 9dc3dd1c2..670127783 100644 --- a/test/canvas.test.js +++ b/test/canvas.test.js @@ -29,9 +29,12 @@ describe('Canvas', function () { // Run with --expose-gc and uncomment this line to help find memory problems: // afterEach(gc); - it('Instance and ctor are well-shaped, don\'t hit asserts on accessors (GH-803)', function () { + it('Prototype and ctor are well-shaped, don\'t hit asserts on accessors (GH-803)', function () { const c = new Canvas(10, 10) + assert.throws(function () { Canvas.prototype.width }, /incompatible receiver/) + assert(!c.hasOwnProperty('width')) assert('width' in c) + assert('width' in Canvas.prototype) }) it('.parseFont()', function () { diff --git a/test/image.test.js b/test/image.test.js index 151cc7ad7..8d54dd90f 100644 --- a/test/image.test.js +++ b/test/image.test.js @@ -22,9 +22,12 @@ const svgTree = path.join(__dirname, '/fixtures/tree.svg') const bmpDir = path.join(__dirname, '/fixtures/bmp') describe('Image', function () { - it('Instance and ctor are well-shaped, don\'t hit asserts on accessors (GH-803)', function () { + it('Prototype and ctor are well-shaped, don\'t hit asserts on accessors (GH-803)', function () { const img = new Image() + assert.throws(function () { Image.prototype.width }, /incompatible receiver/) + assert(!img.hasOwnProperty('width')) assert('width' in img) + assert(Image.prototype.hasOwnProperty('width')) }) it('loads JPEG image', function () { diff --git a/test/imageData.test.js b/test/imageData.test.js index fbb021d45..d3c84c29a 100644 --- a/test/imageData.test.js +++ b/test/imageData.test.js @@ -8,6 +8,9 @@ const {ImageData} = require('../') const assert = require('assert') describe('ImageData', function () { + it('Prototype and ctor are well-shaped, don\'t hit asserts on accessors (GH-803)', function () { + assert.throws(function () { ImageData.prototype.width }, /incompatible receiver/) + }) it('stringifies as [object ImageData]', function () { const imageData = createImageData(2, 3) From cc86cb86ab6c8b311ee631adf8359f86c8b8a264 Mon Sep 17 00:00:00 2001 From: TheDadi Date: Wed, 12 Oct 2022 10:09:36 +0200 Subject: [PATCH 08/10] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 719c9e1e6..c683a6378 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ project adheres to [Semantic Versioning](http://semver.org/). * Prebuilt binaries for Node.js v18 ### Changed * Update nan to v2.17.0 to ensure Node.js v18+ support. -* Implement `SetAccessor` on `InstanceTemplate` instead of `PrototypeTemplate` +* Implement valid `this` checks in all `SetAccessor` methods. 2.10.1 ================== From 2bfee73fb8b9eeb8e0e455547ff388b94538e65f Mon Sep 17 00:00:00 2001 From: TheDadi Date: Tue, 25 Oct 2022 16:40:46 +0200 Subject: [PATCH 09/10] add review comments --- CHANGELOG.md | 2 -- package.json | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 719c9e1e6..6e1365847 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,8 +15,6 @@ project adheres to [Semantic Versioning](http://semver.org/). ================== ### Fixed * Fix `Assertion failed: (object->InternalFieldCount() > 0), function Unwrap, file nan_object_wrap.h, line 32.` ([#2025](https://github.com/Automattic/node-canvas/issues/2025)) -### Added -* Prebuilt binaries for Node.js v18 ### Changed * Update nan to v2.17.0 to ensure Node.js v18+ support. * Implement `SetAccessor` on `InstanceTemplate` instead of `PrototypeTemplate` diff --git a/package.json b/package.json index bfc152224..cd6754ea4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "canvas", "description": "Canvas graphics API backed by Cairo", - "version": "2.10.2", + "version": "2.10.1", "author": "TJ Holowaychuk ", "main": "index.js", "browser": "browser.js", From 389fb35a19d51b2758e90961bdd92de01f55073a Mon Sep 17 00:00:00 2001 From: TheDadi Date: Tue, 25 Oct 2022 16:42:26 +0200 Subject: [PATCH 10/10] remove deprecated constructor overload --- src/Point.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Point.h b/src/Point.h index 50c7b711c..a797dc46c 100644 --- a/src/Point.h +++ b/src/Point.h @@ -1,11 +1,17 @@ // Copyright (c) 2010 LearnBoost - #pragma once +#include + template class Point { public: T x, y; Point(T x=0, T y=0): x(x), y(y) {} Point(const Point&) = default; + Point& operator=(Point other) { + std::swap(x, other.x); + std::swap(y, other.y); + return *this; + } };