deno/tests/napi/object_wrap_test.js
Nathan Whitaker 368eb9073b
fix(napi): Read reference ownership before calling finalizer to avoid crash (#24203)
Fixes #23493.

What was happening here was that napi-rs was freeing the napi reference
([here](19e3488efc/crates/napi/src/bindgen_runtime/mod.rs (L62)))
during its finalize callback (which we call
[here](fb31eaa9ca/cli/napi/js_native_api.rs (L132))).
We then were [reading the `ownership`
field](fb31eaa9ca/cli/napi/js_native_api.rs (L136))
of that freed reference.

For some reason on arm macs the freed memory gets zeroed, so the value
of `ownership` was `0` when we read it (i.e. it was
`ReferenceOwnership::Runtime`). We then freed it again (since we thought
we owned it), causing the segfault.
2024-06-13 22:31:42 +00:00

51 lines
1.4 KiB
JavaScript

// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { Buffer } from "node:buffer";
import { assert, assertEquals, loadTestLibrary } from "./common.js";
const objectWrap = loadTestLibrary();
Deno.test("napi object wrap new", function () {
const obj = new objectWrap.NapiObject(0);
assertEquals(obj.get_value(), 0);
obj.set_value(10);
assertEquals(obj.get_value(), 10);
obj.increment();
assertEquals(obj.get_value(), 11);
obj.increment();
obj.set_value(10);
assertEquals(obj.get_value(), 10);
assertEquals(objectWrap.NapiObject.factory(), 64);
});
Deno.test("napi bind finalizer", function () {
const obj = {};
objectWrap.test_bind_finalizer(obj);
});
Deno.test("napi external finalizer", function () {
let obj = objectWrap.test_external_finalizer();
assert(obj);
obj = null;
});
Deno.test("napi external buffer", function () {
let buf = objectWrap.test_external_buffer();
assertEquals(buf, new Buffer([1, 2, 3]));
buf = null;
});
Deno.test("napi external arraybuffer", function () {
let buf = objectWrap.test_external_arraybuffer();
assertEquals(new Uint8Array(buf), new Uint8Array([1, 2, 3]));
buf = null;
});
Deno.test("napi object wrap userland owned", function () {
let obj = new objectWrap.NapiObjectOwned(1);
assertEquals(obj.get_value(), 1);
obj = null;
// force finalize callback to get called
globalThis.gc();
});