From af7d42ee6bfb34ee143cdef54ece3d20cb3fc35d Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Fri, 27 Feb 2026 10:40:25 -0500 Subject: [PATCH 1/8] doc: add instructions to build with ninja (#1709) --- CONTRIBUTING.md | 3 +++ doc/contributing/build_with_ninja.md | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 doc/contributing/build_with_ninja.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 36f563988..6485f4279 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -92,6 +92,9 @@ Multiple filter conditions can be joined to broaden the test selection compile and run all tests under folders threadsafe_function and typed_threadsafe_function and also the objectwrap.cc file npm run unit --filter='*function objectwrap' +As an alternative, `ninja` can be used to build the tests. Please +follow the instructions in [Build with ninja](doc/contributing/build_with_ninja.md). + ## Debug To run the **node-addon-api** tests with `--debug` option: diff --git a/doc/contributing/build_with_ninja.md b/doc/contributing/build_with_ninja.md new file mode 100644 index 000000000..d59e9bbef --- /dev/null +++ b/doc/contributing/build_with_ninja.md @@ -0,0 +1,16 @@ +# Build Test with Ninja + +Ninja can be used to speed up building tests with optimized parallelism. + +To build the tests with ninja and node-gyp, run the following commands: + +```sh +/node-addon-api $ node-gyp configure -C test -- -f ninja +/node-addon-api $ ninja -C test/build/Release +# Run tests +/node-addon-api $ node ./test/index.js + +# Run tests with debug addon +/node-addon-api $ ninja -C test/build/Debug +/node-addon-api $ NODE_API_BUILD_CONFIG=Debug node ./test/index.js +``` From 845ba8e4b0888ca20ed3f7c95f9d461cbce338c5 Mon Sep 17 00:00:00 2001 From: Umuoy Date: Fri, 6 Mar 2026 21:44:07 +0800 Subject: [PATCH 2/8] fix: add missing const to ObjectReference::Set string parameter (#1713) --- napi-inl.h | 4 ++-- napi.h | 2 +- test/object_reference.cc | 20 ++++++++++++++++++++ test/object_reference.js | 2 ++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/napi-inl.h b/napi-inl.h index 0f1717ecd..b49bbf07d 100644 --- a/napi-inl.h +++ b/napi-inl.h @@ -3809,8 +3809,8 @@ inline MaybeOrValue ObjectReference::Set(const std::string& utf8name, return Value().Set(utf8name, value); } -inline MaybeOrValue ObjectReference::Set(const std::string& utf8name, - std::string& utf8value) const { +inline MaybeOrValue ObjectReference::Set( + const std::string& utf8name, const std::string& utf8value) const { HandleScope scope(_env); return Value().Set(utf8name, utf8value); } diff --git a/napi.h b/napi.h index 013a9114d..6f4f8e5ea 100644 --- a/napi.h +++ b/napi.h @@ -1733,7 +1733,7 @@ class ObjectReference : public Reference { MaybeOrValue Set(const std::string& utf8name, napi_value value) const; MaybeOrValue Set(const std::string& utf8name, Napi::Value value) const; MaybeOrValue Set(const std::string& utf8name, - std::string& utf8value) const; + const std::string& utf8value) const; MaybeOrValue Set(const std::string& utf8name, bool boolValue) const; MaybeOrValue Set(const std::string& utf8name, double numberValue) const; diff --git a/test/object_reference.cc b/test/object_reference.cc index e74b14b2c..691b5f63d 100644 --- a/test/object_reference.cc +++ b/test/object_reference.cc @@ -28,6 +28,25 @@ ObjectReference casted_reference; enum VAL_TYPES { JS = 0, C_STR, CPP_STR, BOOL, INT, DOUBLE, JS_CAST }; +// Test that Set() with std::string key and value accepts temporaries (rvalues). +// This verifies that the parameter is `const std::string&` rather than +// `std::string&`. +void SetWithTempString(const Napi::CallbackInfo& info) { + Env env = info.Env(); + HandleScope scope(env); + + Napi::ObjectReference ref = Persistent(Object::New(env)); + ref.SuppressDestruct(); + + ref.Set(std::string("tempKey"), std::string("tempValue")); + ref.Set(std::string("anotherKey"), info[0].As().Utf8Value()); + + assert(MaybeUnwrap(ref.Get("tempKey")).As().Utf8Value() == + "tempValue"); + assert(MaybeUnwrap(ref.Get("anotherKey")).As().Utf8Value() == + info[0].As().Utf8Value()); +} + void MoveOperatorsTest(const Napi::CallbackInfo& info) { Napi::ObjectReference existingRef; Napi::ObjectReference existingRef2; @@ -412,6 +431,7 @@ Object InitObjectReference(Env env) { exports["unrefObjects"] = Function::New(env, UnrefObjects); exports["refObjects"] = Function::New(env, RefObjects); exports["moveOpTest"] = Function::New(env, MoveOperatorsTest); + exports["setWithTempString"] = Function::New(env, SetWithTempString); return exports; } diff --git a/test/object_reference.js b/test/object_reference.js index 8039b3741..5b713dce8 100644 --- a/test/object_reference.js +++ b/test/object_reference.js @@ -47,6 +47,8 @@ const configObjects = [ function test (binding) { binding.objectreference.moveOpTest(); + binding.objectreference.setWithTempString('testValue'); + function testCastedEqual (testToCompare) { const compareTest = ['hello', 'world', '!']; if (testToCompare instanceof Array) { From 7fef9739166ebb89263459e9f4c3363678cd6367 Mon Sep 17 00:00:00 2001 From: Julien Schueller Date: Thu, 12 Mar 2026 15:34:31 +0100 Subject: [PATCH 3/8] fix: fix -Wextra-semi (#1718) --- napi.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/napi.h b/napi.h index 6f4f8e5ea..a1507dd45 100644 --- a/napi.h +++ b/napi.h @@ -359,10 +359,10 @@ class BasicEnv { // ... occurs when comparing foo.Env() == bar.Env() or foo.Env() == nullptr bool operator==(const BasicEnv& other) const { return _env == other._env; - }; + } bool operator==(std::nullptr_t /*other*/) const { return _env == nullptr; - }; + } #if NAPI_VERSION > 2 template @@ -3126,8 +3126,8 @@ class AsyncProgressWorkerBase : public AsyncWorker { AsyncProgressWorkerBase* asyncprogressworker() { return _asyncprogressworker; - }; - DataType* data() { return _data; }; + } + DataType* data() { return _data; } private: AsyncProgressWorkerBase* _asyncprogressworker; From 967bbd5911c7e90b428d4769b9ab1b1a0cee4451 Mon Sep 17 00:00:00 2001 From: Kevin Eady <8634912+KevinEady@users.noreply.github.com> Date: Sun, 15 Mar 2026 03:53:48 +0100 Subject: [PATCH 4/8] feat: add Object::GetPrototype and Object::SetPrototype (#1715) Fixes: #1691 --- doc/object.md | 22 ++++++++++++++++++++++ napi-inl.h | 13 +++++++++++++ napi.h | 6 ++++++ test/object/object.cc | 18 ++++++++++++++++++ test/object/object.js | 12 ++++++++++++ 5 files changed, 71 insertions(+) diff --git a/doc/object.md b/doc/object.md index a4d3280b8..fb7d53ad1 100644 --- a/doc/object.md +++ b/doc/object.md @@ -241,6 +241,28 @@ from being added to it and marking all existing properties as non-configurable. Values of present properties can still be changed as long as they are writable. +### GetPrototype() + +```cpp +Napi::Object Napi::Object::GetPrototype() const; +``` + +The `Napi::Object::GetPrototype()` method returns the prototype of the object. + +### SetPrototype() + +```cpp +bool Napi::Object::SetPrototype(const Napi::Object& value) const; +``` + +- `[in] value`: The prototype value. + +The `Napi::Object::SetPrototype()` method sets the prototype of the object. + +**NOTE**: The support for `Napi::Object::SetPrototype` is only available when +using `NAPI_EXPERIMENTAL` and building against Node.js headers that support this +feature. + ### operator\[\]() ```cpp diff --git a/napi-inl.h b/napi-inl.h index b49bbf07d..3b82ec827 100644 --- a/napi-inl.h +++ b/napi-inl.h @@ -1966,6 +1966,19 @@ inline MaybeOrValue Object::Seal() const { } #endif // NAPI_VERSION >= 8 +inline MaybeOrValue Object::GetPrototype() const { + napi_value result; + napi_status status = napi_get_prototype(_env, _value, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Object(_env, result), Object); +} + +#ifdef NODE_API_EXPERIMENTAL_HAS_SET_PROTOTYPE +inline MaybeOrValue Object::SetPrototype(const Object& value) const { + napi_status status = node_api_set_prototype(_env, _value, value); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); +} +#endif + //////////////////////////////////////////////////////////////////////////////// // External class //////////////////////////////////////////////////////////////////////////////// diff --git a/napi.h b/napi.h index a1507dd45..d92702e69 100644 --- a/napi.h +++ b/napi.h @@ -1118,6 +1118,12 @@ class Object : public TypeTaggable { /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getprototypeof MaybeOrValue Seal() const; #endif // NAPI_VERSION >= 8 + + MaybeOrValue GetPrototype() const; + +#ifdef NODE_API_EXPERIMENTAL_HAS_SET_PROTOTYPE + MaybeOrValue SetPrototype(const Object& value) const; +#endif }; template diff --git a/test/object/object.cc b/test/object/object.cc index be0bcadde..60aae768f 100644 --- a/test/object/object.cc +++ b/test/object/object.cc @@ -343,6 +343,19 @@ Value InstanceOf(const CallbackInfo& info) { return Boolean::New(info.Env(), MaybeUnwrap(obj.InstanceOf(constructor))); } +Value GetPrototype(const CallbackInfo& info) { + Object obj = info[0].UnsafeAs(); + return MaybeUnwrap(obj.GetPrototype()); +} + +#ifdef NODE_API_EXPERIMENTAL_HAS_SET_PROTOTYPE +Value SetPrototype(const CallbackInfo& info) { + Object obj = info[0].UnsafeAs(); + Object prototype = info[1].UnsafeAs(); + return Boolean::New(info.Env(), MaybeUnwrap(obj.SetPrototype(prototype))); +} +#endif // NODE_API_EXPERIMENTAL_HAS_SET_PROTOTYPE + Object InitObject(Env env) { Object exports = Object::New(env); @@ -426,5 +439,10 @@ Object InitObject(Env env) { Function::New(env, SubscriptSetWithCppStyleString); exports["subscriptSetAtIndex"] = Function::New(env, SubscriptSetAtIndex); + exports["getPrototype"] = Function::New(env, GetPrototype); +#ifdef NODE_API_EXPERIMENTAL_HAS_SET_PROTOTYPE + exports["setPrototype"] = Function::New(env, SetPrototype); +#endif // NODE_API_EXPERIMENTAL_HAS_SET_PROTOTYPE + return exports; } diff --git a/test/object/object.js b/test/object/object.js index 6cd9735e9..13488940c 100644 --- a/test/object/object.js +++ b/test/object/object.js @@ -215,4 +215,16 @@ function test (binding) { c: 3 }); } + + for (const prototype of [null, {}, Object.prototype]) { + const obj = Object.create(prototype); + assert.strictEqual(binding.object.getPrototype(obj), prototype); + } + + if ('setPrototype' in binding.object) { + const prototype = {}; + const obj = Object.create(null); + assert.strictEqual(binding.object.setPrototype(obj, prototype), true); + assert.strictEqual(Object.getPrototypeOf(obj), prototype); + } } From f8210c617b399b17cdd97657762c896b1433ed29 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 10:28:43 -0400 Subject: [PATCH 5/8] chore(deps): bump the all group across 1 directory with 6 updates (#1717) Bumps the all group with 6 updates in the / directory: | Package | From | To | | --- | --- | --- | | [step-security/harden-runner](https://github.com/step-security/harden-runner) | `2.14.0` | `2.15.1` | | [actions/setup-node](https://github.com/actions/setup-node) | `6.2.0` | `6.3.0` | | [github/codeql-action](https://github.com/github/codeql-action) | `4.31.11` | `4.32.6` | | [actions/dependency-review-action](https://github.com/actions/dependency-review-action) | `4.8.2` | `4.9.0` | | [actions/upload-artifact](https://github.com/actions/upload-artifact) | `6.0.0` | `7.0.0` | | [actions/stale](https://github.com/actions/stale) | `10.1.1` | `10.2.0` | Updates `step-security/harden-runner` from 2.14.0 to 2.15.1 - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/20cf305ff2072d973412fa9b1e3a4f227bda3c76...58077d3c7e43986b6b15fba718e8ea69e387dfcc) Updates `actions/setup-node` from 6.2.0 to 6.3.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/6044e13b5dc448c55e2357c09f80417699197238...53b83947a5a98c8d113130e565377fae1a50d02f) Updates `github/codeql-action` from 4.31.11 to 4.32.6 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/19b2f06db2b6f5108140aeb04014ef02b648f789...0d579ffd059c29b07949a3cce3983f0780820c98) Updates `actions/dependency-review-action` from 4.8.2 to 4.9.0 - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261...2031cfc080254a8a887f58cffee85186f0e49e48) Updates `actions/upload-artifact` from 6.0.0 to 7.0.0 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/b7c566a772e6b6bfb58ed0dc250532a479d7789f...bbbca2ddaa5d8feaa63e36b76fdaad77386f024f) Updates `actions/stale` from 10.1.1 to 10.2.0 - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/997185467fa4f803885201cee163a9f38240193d...b5d41d4e1d5dceea10e7104786b73624c18a190f) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-version: 2.15.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all - dependency-name: actions/setup-node dependency-version: 6.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all - dependency-name: github/codeql-action dependency-version: 4.32.6 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all - dependency-name: actions/dependency-review-action dependency-version: 4.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all - dependency-name: actions/upload-artifact dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: all - dependency-name: actions/stale dependency-version: 10.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-win.yml | 4 ++-- .github/workflows/ci.yml | 4 ++-- .github/workflows/codeql.yml | 8 ++++---- .github/workflows/coverage-linux.yml | 4 ++-- .github/workflows/dependency-review.yml | 4 ++-- .github/workflows/linter.yml | 4 ++-- .github/workflows/node-api-headers.yml | 4 ++-- .github/workflows/release-please.yml | 6 +++--- .github/workflows/scorecards.yml | 6 +++--- .github/workflows/stale.yml | 4 ++-- 10 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci-win.yml b/.github/workflows/ci-win.yml index fe07ff638..2417ab986 100644 --- a/.github/workflows/ci-win.yml +++ b/.github/workflows/ci-win.yml @@ -36,7 +36,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Harden Runner - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 with: egress-policy: audit @@ -46,7 +46,7 @@ jobs: with: python-version: ${{ env.PYTHON_VERSION }} - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ matrix.node-version }} architecture: ${{ matrix.architecture }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 590240c4a..c5694ef0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Harden Runner - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 with: egress-policy: audit @@ -44,7 +44,7 @@ jobs: with: python-version: ${{ env.PYTHON_VERSION }} - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ matrix.node-version }} - name: Check Node.js installation diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9a394e247..8758fdcef 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -41,7 +41,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 with: egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs @@ -50,7 +50,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 + uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -70,7 +70,7 @@ jobs: - name: Use Node.js v18.x if: matrix.language == 'cpp' - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 18.x @@ -80,6 +80,6 @@ jobs: npx node-gyp rebuild -C test - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 + uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/coverage-linux.yml b/.github/workflows/coverage-linux.yml index a108a3031..3d116e405 100644 --- a/.github/workflows/coverage-linux.yml +++ b/.github/workflows/coverage-linux.yml @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 with: egress-policy: audit @@ -47,7 +47,7 @@ jobs: with: python-version: ${{ env.PYTHON_VERSION }} - name: Use Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ env.NODE_VERSION }} - name: Environment Information diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 60895a3ba..8d6513bed 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -17,11 +17,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 with: egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs - name: 'Checkout Repository' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: 'Dependency Review' - uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 + uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 145e7e6f0..4cd921796 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -16,7 +16,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Harden Runner - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 with: egress-policy: audit @@ -25,7 +25,7 @@ jobs: fetch-depth: 0 - run: git branch -a - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ matrix.node-version }} - run: npm install diff --git a/.github/workflows/node-api-headers.yml b/.github/workflows/node-api-headers.yml index 1ae5a963f..59c686348 100644 --- a/.github/workflows/node-api-headers.yml +++ b/.github/workflows/node-api-headers.yml @@ -30,7 +30,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Harden Runner - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 with: egress-policy: audit @@ -40,7 +40,7 @@ jobs: with: python-version: ${{ env.PYTHON_VERSION }} - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ matrix.node-version }} - name: Check Node.js installation diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index adc44c2b8..a6f09719a 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -20,7 +20,7 @@ jobs: pull-requests: write steps: - name: Harden Runner - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 with: egress-policy: audit @@ -39,12 +39,12 @@ jobs: id-token: write steps: - name: Harden Runner - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 with: egress-policy: audit - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 24 # npm >= 11.5.1 registry-url: 'https://registry.npmjs.org' diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index f1c51695f..d902982dc 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -31,7 +31,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 with: egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs @@ -63,7 +63,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: SARIF file path: results.sarif @@ -71,6 +71,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 + uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 with: sarif_file: results.sarif diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d1fbf2dbc..7554cf154 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -14,11 +14,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 with: egress-policy: audit - - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1 + - uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: 'This issue is stale because it has been open many days with no activity. It will be closed soon unless the stale label is removed or a comment is made.' From 7b8d69e0ba912291aea0b337f7f1814b1032f7f0 Mon Sep 17 00:00:00 2001 From: Kevin Eady <8634912+KevinEady@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:05:58 +0100 Subject: [PATCH 6/8] feat: add support for SharedArrayBuffer in DataViews (#1714) --- doc/dataview.md | 64 ++++++++++++++++++++++++++++++++++++++- napi-inl.h | 41 +++++++++++++++++++++++-- napi.h | 26 +++++++++++++++- test/dataview/dataview.cc | 53 ++++++++++++++++++++++++++++---- test/dataview/dataview.js | 63 ++++++++++++++++++++++++++++++-------- 5 files changed, 225 insertions(+), 22 deletions(-) diff --git a/doc/dataview.md b/doc/dataview.md index 66fb28919..619ceecca 100644 --- a/doc/dataview.md +++ b/doc/dataview.md @@ -6,6 +6,11 @@ The `Napi::DataView` class corresponds to the [JavaScript `DataView`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView) class. +**NOTE**: The support for `Napi::DataView::New()` overloads accepting an +`Napi::SharedArrayBuffer` parameter is only available when using +`NAPI_EXPERIMENTAL` and building against Node.js headers that support this +feature. + ## Methods ### New @@ -50,6 +55,48 @@ static Napi::DataView Napi::DataView::New(napi_env env, Napi::ArrayBuffer arrayB Returns a new `Napi::DataView` instance. +### New + +Allocates a new `Napi::DataView` instance with a given `Napi::SharedArrayBuffer`. + +```cpp +static Napi::DataView Napi::DataView::New(napi_env env, Napi::SharedArrayBuffer sharedArrayBuffer); +``` + +- `[in] env`: The environment in which to create the `Napi::DataView` instance. +- `[in] sharedArrayBuffer` : `Napi::SharedArrayBuffer` underlying the `Napi::DataView`. + +Returns a new `Napi::DataView` instance. + +### New + +Allocates a new `Napi::DataView` instance with a given `Napi::SharedArrayBuffer`. + +```cpp +static Napi::DataView Napi::DataView::New(napi_env env, Napi::SharedArrayBuffer sharedArrayBuffer, size_t byteOffset); +``` + +- `[in] env`: The environment in which to create the `Napi::DataView` instance. +- `[in] sharedArrayBuffer` : `Napi::SharedArrayBuffer` underlying the `Napi::DataView`. +- `[in] byteOffset` : The byte offset within the `Napi::SharedArrayBuffer` from which to start projecting the `Napi::DataView`. + +Returns a new `Napi::DataView` instance. + +### New + +Allocates a new `Napi::DataView` instance with a given `Napi::SharedArrayBuffer`. + +```cpp +static Napi::DataView Napi::DataView::New(napi_env env, Napi::SharedArrayBuffer sharedArrayBuffer, size_t byteOffset, size_t byteLength); +``` + +- `[in] env`: The environment in which to create the `Napi::DataView` instance. +- `[in] sharedArrayBuffer` : `Napi::SharedArrayBuffer` underlying the `Napi::DataView`. +- `[in] byteOffset` : The byte offset within the `Napi::SharedArrayBuffer` from which to start projecting the `Napi::DataView`. +- `[in] byteLength` : Number of elements in the `Napi::DataView`. + +Returns a new `Napi::DataView` instance. + ### Constructor Initializes an empty instance of the `Napi::DataView` class. @@ -75,7 +122,22 @@ Napi::DataView(napi_env env, napi_value value); Napi::ArrayBuffer Napi::DataView::ArrayBuffer() const; ``` -Returns the backing array buffer. +Returns the backing array buffer as an `Napi::ArrayBuffer`. + +**NOTE**: If the `Napi::DataView` is not backed by an `Napi::ArrayBuffer`, this +method will terminate the process with a fatal error when using +`NODE_ADDON_API_ENABLE_TYPE_CHECK_ON_AS` or exhibit undefined behavior +otherwise. Use `Buffer()` instead to get the backing buffer without assuming its +type. + +### Buffer + +```cpp +Napi::Value Napi::DataView::Buffer() const; +``` + +Returns the backing array buffer as a generic `Napi::Value`, allowing optional +type-checking with `Is*()` and type-casting with `As<>()` methods. ### ByteOffset diff --git a/napi-inl.h b/napi-inl.h index 3b82ec827..7ef2e64a2 100644 --- a/napi-inl.h +++ b/napi-inl.h @@ -2302,6 +2302,39 @@ inline DataView DataView::New(napi_env env, return DataView(env, value); } +#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER +inline DataView DataView::New(napi_env env, + Napi::SharedArrayBuffer arrayBuffer) { + return New(env, arrayBuffer, 0, arrayBuffer.ByteLength()); +} + +inline DataView DataView::New(napi_env env, + Napi::SharedArrayBuffer arrayBuffer, + size_t byteOffset) { + if (byteOffset > arrayBuffer.ByteLength()) { + NAPI_THROW(RangeError::New( + env, "Start offset is outside the bounds of the buffer"), + DataView()); + } + return New( + env, arrayBuffer, byteOffset, arrayBuffer.ByteLength() - byteOffset); +} + +inline DataView DataView::New(napi_env env, + Napi::SharedArrayBuffer arrayBuffer, + size_t byteOffset, + size_t byteLength) { + if (byteOffset + byteLength > arrayBuffer.ByteLength()) { + NAPI_THROW(RangeError::New(env, "Invalid DataView length"), DataView()); + } + napi_value value; + napi_status status = + napi_create_dataview(env, byteLength, arrayBuffer, byteOffset, &value); + NAPI_THROW_IF_FAILED(env, status, DataView()); + return DataView(env, value); +} +#endif // NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER + inline void DataView::CheckCast(napi_env env, napi_value value) { NAPI_CHECK(value != nullptr, "DataView::CheckCast", "empty value"); @@ -2325,6 +2358,10 @@ inline DataView::DataView(napi_env env, napi_value value) : Object(env, value) { } inline Napi::ArrayBuffer DataView::ArrayBuffer() const { + return Buffer().As(); +} + +inline Napi::Value DataView::Buffer() const { napi_value arrayBuffer; napi_status status = napi_get_dataview_info(_env, _value /* dataView */, @@ -2332,8 +2369,8 @@ inline Napi::ArrayBuffer DataView::ArrayBuffer() const { nullptr /* data */, &arrayBuffer /* arrayBuffer */, nullptr /* byteOffset */); - NAPI_THROW_IF_FAILED(_env, status, Napi::ArrayBuffer()); - return Napi::ArrayBuffer(_env, arrayBuffer); + NAPI_THROW_IF_FAILED(_env, status, Napi::Value()); + return Napi::Value(_env, arrayBuffer); } inline size_t DataView::ByteOffset() const { diff --git a/napi.h b/napi.h index d92702e69..fd1e5922a 100644 --- a/napi.h +++ b/napi.h @@ -1456,13 +1456,37 @@ class DataView : public Object { size_t byteOffset, size_t byteLength); +#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER + static DataView New(napi_env env, Napi::SharedArrayBuffer arrayBuffer); + static DataView New(napi_env env, + Napi::SharedArrayBuffer arrayBuffer, + size_t byteOffset); + static DataView New(napi_env env, + Napi::SharedArrayBuffer arrayBuffer, + size_t byteOffset, + size_t byteLength); +#endif + static void CheckCast(napi_env env, napi_value value); DataView(); ///< Creates a new _empty_ DataView instance. DataView(napi_env env, napi_value value); ///< Wraps a Node-API value primitive. - Napi::ArrayBuffer ArrayBuffer() const; ///< Gets the backing array buffer. + // Gets the backing `ArrayBuffer`. + // + // If this `DataView` is not backed by an `ArrayBuffer`, this method will + // terminate the process with a fatal error when using + // `NODE_ADDON_API_ENABLE_TYPE_CHECK_ON_AS` or exhibit undefined behavior + // otherwise. Use `Buffer()` instead to get the backing buffer without + // assuming its type. + Napi::ArrayBuffer ArrayBuffer() const; + + // Gets the backing buffer (an `ArrayBuffer` or `SharedArrayBuffer`). + // + // Use `IsArrayBuffer()` or `IsSharedArrayBuffer()` to check the type of the + // backing buffer prior to casting with `As()`. + Napi::Value Buffer() const; size_t ByteOffset() const; ///< Gets the offset into the buffer where the array starts. size_t ByteLength() const; ///< Gets the length of the array in bytes. diff --git a/test/dataview/dataview.cc b/test/dataview/dataview.cc index f055d95f1..cbd5933e7 100644 --- a/test/dataview/dataview.cc +++ b/test/dataview/dataview.cc @@ -2,24 +2,51 @@ using namespace Napi; -static Value CreateDataView1(const CallbackInfo& info) { +static Value CreateDataView(const CallbackInfo& info) { ArrayBuffer arrayBuffer = info[0].As(); return DataView::New(info.Env(), arrayBuffer); } -static Value CreateDataView2(const CallbackInfo& info) { +static Value CreateDataViewWithByteOffset(const CallbackInfo& info) { ArrayBuffer arrayBuffer = info[0].As(); size_t byteOffset = info[1].As().Uint32Value(); return DataView::New(info.Env(), arrayBuffer, byteOffset); } -static Value CreateDataView3(const CallbackInfo& info) { +static Value CreateDataViewWithByteOffsetAndByteLength( + const CallbackInfo& info) { ArrayBuffer arrayBuffer = info[0].As(); size_t byteOffset = info[1].As().Uint32Value(); size_t byteLength = info[2].As().Uint32Value(); return DataView::New(info.Env(), arrayBuffer, byteOffset, byteLength); } +#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER +static Value CreateDataViewOnSharedArrayBuffer(const CallbackInfo& info) { + SharedArrayBuffer arrayBuffer = info[0].As(); + return DataView::New(info.Env(), arrayBuffer); +} + +static Value CreateDataViewOnSharedArrayBufferWithByteOffset( + const CallbackInfo& info) { + SharedArrayBuffer arrayBuffer = info[0].As(); + size_t byteOffset = info[1].As().Uint32Value(); + return DataView::New(info.Env(), arrayBuffer, byteOffset); +} + +static Value CreateDataViewOnSharedArrayBufferWithByteOffsetAndByteLength( + const CallbackInfo& info) { + SharedArrayBuffer arrayBuffer = info[0].As(); + size_t byteOffset = info[1].As().Uint32Value(); + size_t byteLength = info[2].As().Uint32Value(); + return DataView::New(info.Env(), arrayBuffer, byteOffset, byteLength); +} +#endif + +static Value GetBuffer(const CallbackInfo& info) { + return info[0].As().Buffer(); +} + static Value GetArrayBuffer(const CallbackInfo& info) { return info[0].As().ArrayBuffer(); } @@ -37,10 +64,24 @@ static Value GetByteLength(const CallbackInfo& info) { Object InitDataView(Env env) { Object exports = Object::New(env); - exports["createDataView1"] = Function::New(env, CreateDataView1); - exports["createDataView2"] = Function::New(env, CreateDataView2); - exports["createDataView3"] = Function::New(env, CreateDataView3); + exports["createDataView"] = Function::New(env, CreateDataView); + exports["createDataViewWithByteOffset"] = + Function::New(env, CreateDataViewWithByteOffset); + exports["createDataViewWithByteOffsetAndByteLength"] = + Function::New(env, CreateDataViewWithByteOffsetAndByteLength); + +#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER + exports["createDataViewOnSharedArrayBuffer"] = + Function::New(env, CreateDataViewOnSharedArrayBuffer); + exports["createDataViewOnSharedArrayBufferWithByteOffset"] = + Function::New(env, CreateDataViewOnSharedArrayBufferWithByteOffset); + exports["createDataViewOnSharedArrayBufferWithByteOffsetAndByteLength"] = + Function::New( + env, CreateDataViewOnSharedArrayBufferWithByteOffsetAndByteLength); +#endif + exports["getArrayBuffer"] = Function::New(env, GetArrayBuffer); + exports["getBuffer"] = Function::New(env, GetBuffer); exports["getByteOffset"] = Function::New(env, GetByteOffset); exports["getByteLength"] = Function::New(env, GetByteLength); diff --git a/test/dataview/dataview.js b/test/dataview/dataview.js index 595612856..5916f6b90 100644 --- a/test/dataview/dataview.js +++ b/test/dataview/dataview.js @@ -3,12 +3,19 @@ const assert = require('assert'); module.exports = require('../common').runTest(test); +let runSharedArrayBufferTests = true; + function test (binding) { function testDataViewCreation (factory, arrayBuffer, offset, length) { const view = factory(arrayBuffer, offset, length); offset = offset || 0; - assert.ok(dataview.getArrayBuffer(view) instanceof ArrayBuffer); - assert.strictEqual(dataview.getArrayBuffer(view), arrayBuffer); + if (arrayBuffer instanceof ArrayBuffer) { + assert.ok(dataview.getArrayBuffer(view) instanceof ArrayBuffer); + assert.strictEqual(dataview.getArrayBuffer(view), arrayBuffer); + } else { + assert.ok(dataview.getBuffer(view) instanceof SharedArrayBuffer); + assert.strictEqual(dataview.getBuffer(view), arrayBuffer); + } assert.strictEqual(dataview.getByteOffset(view), offset); assert.strictEqual(dataview.getByteLength(view), length || arrayBuffer.byteLength - offset); @@ -20,16 +27,48 @@ function test (binding) { }, RangeError); } - const dataview = binding.dataview; - const arrayBuffer = new ArrayBuffer(10); + const { hasSharedArrayBuffer, dataview } = binding; + + { + const arrayBuffer = new ArrayBuffer(10); + + testDataViewCreation(dataview.createDataView, arrayBuffer); + testDataViewCreation(dataview.createDataViewWithByteOffset, arrayBuffer, 2); + testDataViewCreation(dataview.createDataViewWithByteOffset, arrayBuffer, 10); + testDataViewCreation(dataview.createDataViewWithByteOffsetAndByteLength, arrayBuffer, 2, 4); + testDataViewCreation(dataview.createDataViewWithByteOffsetAndByteLength, arrayBuffer, 10, 0); + + testInvalidRange(dataview.createDataViewWithByteOffset, arrayBuffer, 11); + testInvalidRange(dataview.createDataViewWithByteOffsetAndByteLength, arrayBuffer, 11, 0); + testInvalidRange(dataview.createDataViewWithByteOffsetAndByteLength, arrayBuffer, 6, 5); + } + + if (hasSharedArrayBuffer && runSharedArrayBufferTests) { + const sab = new SharedArrayBuffer(10); - testDataViewCreation(dataview.createDataView1, arrayBuffer); - testDataViewCreation(dataview.createDataView2, arrayBuffer, 2); - testDataViewCreation(dataview.createDataView2, arrayBuffer, 10); - testDataViewCreation(dataview.createDataView3, arrayBuffer, 2, 4); - testDataViewCreation(dataview.createDataView3, arrayBuffer, 10, 0); + try { + testDataViewCreation(dataview.createDataViewOnSharedArrayBuffer, sab); + } catch (ex) { + // The `napi_create_dataview` API does not have a valid `#define` + // preprocessor guard for SharedArrayBuffer support, so it is + // possible that the API is present but creating a DataView on + // SharedArrayBuffer is not supported in the current version of Node.js. + // In that case, we should skip the test instead of throwing. + if (ex.message === 'Invalid argument') { + console.warn(`The current version of Node.js (${process.version}) does not support creating DataViews on SharedArrayBuffers; skipping tests.`); + runSharedArrayBufferTests = false; + return; + } - testInvalidRange(dataview.createDataView2, arrayBuffer, 11); - testInvalidRange(dataview.createDataView3, arrayBuffer, 11, 0); - testInvalidRange(dataview.createDataView3, arrayBuffer, 6, 5); + throw ex; + } + testDataViewCreation(dataview.createDataViewOnSharedArrayBufferWithByteOffset, sab, 2); + testDataViewCreation(dataview.createDataViewOnSharedArrayBufferWithByteOffset, sab, 10); + testDataViewCreation(dataview.createDataViewOnSharedArrayBufferWithByteOffsetAndByteLength, sab, 2, 4); + testDataViewCreation(dataview.createDataViewOnSharedArrayBufferWithByteOffsetAndByteLength, sab, 10, 0); + + testInvalidRange(dataview.createDataViewOnSharedArrayBufferWithByteOffset, sab, 11); + testInvalidRange(dataview.createDataViewOnSharedArrayBufferWithByteOffsetAndByteLength, sab, 11, 0); + testInvalidRange(dataview.createDataViewOnSharedArrayBufferWithByteOffsetAndByteLength, sab, 6, 5); + } } From 7fb063d95ff5ef816d1616f9acf4afac854cfd4c Mon Sep 17 00:00:00 2001 From: Charles Cabergs Date: Mon, 23 Mar 2026 18:57:27 +0100 Subject: [PATCH 7/8] feat: add Date::New overload for a std::chrono::system_clock::time_point (#1705) Co-authored-by: Kevin Eady <8634912+KevinEady@users.noreply.github.com> --- doc/date.md | 14 ++++++++++++++ napi-inl.h | 7 +++++++ napi.h | 7 +++++++ test/date.cc | 7 +++++++ test/date.js | 4 +++- 5 files changed, 38 insertions(+), 1 deletion(-) diff --git a/doc/date.md b/doc/date.md index 4c5fefa5e..7131b016f 100644 --- a/doc/date.md +++ b/doc/date.md @@ -37,6 +37,20 @@ static Napi::Date Napi::Date::New(Napi::Env env, double value); Returns a new instance of `Napi::Date` object. +### New + +Creates a new instance of a `Napi::Date` object. + +```cpp +static Napi::Date Napi::Date::New(napi_env env, std::chrono::system_clock::time_point time_point); +``` + + - `[in] env`: The environment in which to construct the `Napi::Date` object. + - `[in] value`: The point in time, represented by an + `std::chrono::system_clock::time_point`. + +Returns a new instance of `Napi::Date` object. + ### ValueOf ```cpp diff --git a/napi-inl.h b/napi-inl.h index 7ef2e64a2..568a6baa5 100644 --- a/napi-inl.h +++ b/napi-inl.h @@ -1199,6 +1199,13 @@ inline Date Date::New(napi_env env, double val) { return Date(env, value); } +inline Date Date::New(napi_env env, std::chrono::system_clock::time_point tp) { + using namespace std::chrono; + auto ms = static_cast( + duration_cast(tp.time_since_epoch()).count()); + return Date::New(env, ms); +} + inline void Date::CheckCast(napi_env env, napi_value value) { NAPI_CHECK(value != nullptr, "Date::CheckCast", "empty value"); diff --git a/napi.h b/napi.h index fd1e5922a..4efe551e0 100644 --- a/napi.h +++ b/napi.h @@ -17,6 +17,7 @@ #if NAPI_HAS_THREADS #include #endif // NAPI_HAS_THREADS +#include #include #include @@ -685,6 +686,12 @@ class Date : public Value { double value ///< Number value ); + /// Creates a new Date value from a std::chrono::system_clock::time_point. + static Date New( + napi_env env, ///< Node-API environment + std::chrono::system_clock::time_point time_point ///< Time point value + ); + static void CheckCast(napi_env env, napi_value value); Date(); ///< Creates a new _empty_ Date instance. diff --git a/test/date.cc b/test/date.cc index efd433af4..a446bde22 100644 --- a/test/date.cc +++ b/test/date.cc @@ -11,6 +11,11 @@ Value CreateDate(const CallbackInfo& info) { return Date::New(info.Env(), input); } +Value CreateDateFromTimePoint(const CallbackInfo& info) { + auto input = std::chrono::system_clock::time_point{}; + return Date::New(info.Env(), input); +} + Value IsDate(const CallbackInfo& info) { Date input = info[0].As(); @@ -35,6 +40,8 @@ Value OperatorValue(const CallbackInfo& info) { Object InitDate(Env env) { Object exports = Object::New(env); exports["CreateDate"] = Function::New(env, CreateDate); + exports["CreateDateFromTimePoint"] = + Function::New(env, CreateDateFromTimePoint); exports["IsDate"] = Function::New(env, IsDate); exports["ValueOf"] = Function::New(env, ValueOf); exports["OperatorValue"] = Function::New(env, OperatorValue); diff --git a/test/date.js b/test/date.js index 86c8af6ac..588b741b1 100644 --- a/test/date.js +++ b/test/date.js @@ -9,9 +9,11 @@ function test (binding) { CreateDate, IsDate, ValueOf, - OperatorValue + OperatorValue, + CreateDateFromTimePoint } = binding.date; assert.deepStrictEqual(CreateDate(0), new Date(0)); + assert.deepStrictEqual(CreateDateFromTimePoint(), new Date(0)); assert.strictEqual(IsDate(new Date(0)), true); assert.strictEqual(ValueOf(new Date(42)), 42); assert.strictEqual(OperatorValue(new Date(42)), true); From 0eafea52a443e5b707afe5829d4bfca762c06e66 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 09:09:51 +0800 Subject: [PATCH 8/8] chore: release v8.7.0 (#1716) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 15 +++++++++++++++ README.md | 2 +- package.json | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c1579bf95..5fd9048a6 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "8.6.0" + ".": "8.7.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fd7b3f87..69bb7d160 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # node-addon-api Changelog +## [8.7.0](https://github.com/nodejs/node-addon-api/compare/v8.6.0...v8.7.0) (2026-03-23) + + +### Features + +* add Date::New overload for a std::chrono::system_clock::time_point ([#1705](https://github.com/nodejs/node-addon-api/issues/1705)) ([7fb063d](https://github.com/nodejs/node-addon-api/commit/7fb063d95ff5ef816d1616f9acf4afac854cfd4c)) +* add Object::GetPrototype and Object::SetPrototype ([#1715](https://github.com/nodejs/node-addon-api/issues/1715)) ([967bbd5](https://github.com/nodejs/node-addon-api/commit/967bbd5911c7e90b428d4769b9ab1b1a0cee4451)), closes [#1691](https://github.com/nodejs/node-addon-api/issues/1691) +* add support for SharedArrayBuffer in DataViews ([#1714](https://github.com/nodejs/node-addon-api/issues/1714)) ([7b8d69e](https://github.com/nodejs/node-addon-api/commit/7b8d69e0ba912291aea0b337f7f1814b1032f7f0)) + + +### Bug Fixes + +* add missing const to ObjectReference::Set string parameter ([#1713](https://github.com/nodejs/node-addon-api/issues/1713)) ([845ba8e](https://github.com/nodejs/node-addon-api/commit/845ba8e4b0888ca20ed3f7c95f9d461cbce338c5)) +* fix -Wextra-semi ([#1718](https://github.com/nodejs/node-addon-api/issues/1718)) ([7fef973](https://github.com/nodejs/node-addon-api/commit/7fef9739166ebb89263459e9f4c3363678cd6367)) + ## [8.6.0](https://github.com/nodejs/node-addon-api/compare/v8.5.0...v8.6.0) (2026-01-30) diff --git a/README.md b/README.md index 39df5a975..72a449eb2 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ and exception handling semantics with low overhead. API references are available in the [doc](doc/README.md) directory. -## Current version: 8.6.0 +## Current version: 8.7.0 (See [CHANGELOG.md](CHANGELOG.md) for complete Changelog) diff --git a/package.json b/package.json index b9393c6cf..d9b2e39bf 100644 --- a/package.json +++ b/package.json @@ -472,7 +472,7 @@ "lint:fix": "eslint --fix && node tools/clang-format --fix" }, "pre-commit": "lint", - "version": "8.6.0", + "version": "8.7.0", "support": true, "engines": { "node": "^18 || ^20 || >= 21"