Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ default = ["napi-1"]

# Default N-API version. Prefer to select a minimum required version.
# DEPRECATED: This is an alias that should be removed
napi-runtime = ["napi-6"]
napi-runtime = ["napi-8"]

# Select the N-API version
# Feature flags to enable the experimental N-API runtime. For now, this feature
Expand All @@ -41,8 +41,10 @@ napi-3 = ["napi-2"]
napi-4 = ["napi-3"]
napi-5 = ["napi-4"]
napi-6 = ["napi-5"]
napi-latest = ["napi-6"]
napi-experimental = ["napi-6"]
napi-7 = ["napi-6"]
napi-8 = ["napi-7"]
napi-latest = ["napi-8"]
napi-experimental = ["napi-8"]

# DEPRECATED: These perform no action and will be removed in 1.0
try-catch-api = []
Expand Down
2 changes: 1 addition & 1 deletion create-neon/data/versions.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"neon": "0.10",
"napi": "6",
"napi": "8",
"cargo-cp-artifact": "0.1"
}
28 changes: 27 additions & 1 deletion src/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use crate::{
context::{internal::Env, Context},
handle::{Handle, Managed, Root},
result::{NeonResult, Throw},
sys::{self, raw},
sys::{self, raw, Status},
types::{build, function::CallOptions, utf8::Utf8, JsFunction, JsUndefined, JsValue, Value},
};

Expand Down Expand Up @@ -188,6 +188,32 @@ pub trait Object: Value {
})
}

#[cfg(feature = "napi-8")]
fn freeze<'a, C: Context<'a>>(&self, cx: &mut C) -> NeonResult<&Self> {
let env = cx.env().to_raw();
let obj = self.to_raw();
unsafe {
match sys::object::freeze(env, obj) {
Status::Ok => Ok(self),
Status::PendingException => Err(Throw::new()),
_ => cx.throw_type_error("object cannot be frozen"),
}
}
}

#[cfg(feature = "napi-8")]
fn seal<'a, C: Context<'a>>(&self, cx: &mut C) -> NeonResult<&Self> {
let env = cx.env().to_raw();
let obj = self.to_raw();
unsafe {
match sys::object::seal(env, obj) {
Status::Ok => Ok(self),
Status::PendingException => Err(Throw::new()),
_ => cx.throw_type_error("object cannot be sealed"),
}
}
}

fn set<'a, C: Context<'a>, K: PropertyKey, W: Value>(
&self,
cx: &mut C,
Expand Down
17 changes: 17 additions & 0 deletions src/sys/bindings/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,27 @@ mod napi6 {
);
}

#[cfg(feature = "napi-8")]
mod napi8 {
use super::super::types::*;

generate!(
extern "C" {
fn object_freeze(env: Env, object: Value) -> Status;
fn object_seal(env: Env, object: Value) -> Status;
}
);
}

pub(crate) use napi1::*;
#[cfg(feature = "napi-4")]
pub(crate) use napi4::*;
#[cfg(feature = "napi-5")]
pub(crate) use napi5::*;
#[cfg(feature = "napi-6")]
pub(crate) use napi6::*;
#[cfg(feature = "napi-8")]
pub(crate) use napi8::*;

use super::{Env, Status};

Expand Down Expand Up @@ -368,5 +382,8 @@ pub(super) unsafe fn load(env: Env) -> Result<(), libloading::Error> {
#[cfg(feature = "napi-6")]
napi6::load(&host, version, 6)?;

#[cfg(feature = "napi-8")]
napi8::load(&host, version, 8)?;

Ok(())
}
10 changes: 10 additions & 0 deletions src/sys/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ pub unsafe fn new(out: &mut Local, env: Env) {
napi::create_object(env, out as *mut _);
}

#[cfg(feature = "napi-8")]
pub unsafe fn freeze(env: Env, obj: Local) -> napi::Status {
napi::object_freeze(env, obj)
}

#[cfg(feature = "napi-8")]
pub unsafe fn seal(env: Env, obj: Local) -> napi::Status {
napi::object_seal(env, obj)
}

#[cfg(feature = "napi-6")]
/// Mutates the `out` argument to refer to a `napi_value` containing the own property names of the
/// `object` as a JavaScript Array.
Expand Down
2 changes: 1 addition & 1 deletion test/napi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ once_cell = "1"
[dependencies.neon]
version = "*"
path = "../.."
features = ["napi-6"]
features = ["napi-8"]
37 changes: 37 additions & 0 deletions test/napi/lib/objects.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,43 @@ describe("JsObject", function () {
);
});

it("freeze a JsObject", function () {
const originalValue = 1;
const obj = { x: originalValue };

assert.doesNotThrow(function () {
addon.freeze_js_object(obj);
}, "freeze_js_object should not throw");

obj.x = 2;
assert.equal(
obj.x,
originalValue,
"freeze_js_object should not allow mutation"
);

const shouldNotFreeze = new Uint32Array(8);
assert.throws(function () {
addon.freeze_js_object(shouldNotFreeze);
});
});

it("seal a JsObject", function () {
const obj = { x: 1 };

assert.doesNotThrow(function () {
addon.seal_js_object(obj);
}, "seal_js_object should not throw");

delete obj.x;
assert.isOk(obj.x, "seal_js_object should not allow property deletion");

const shouldNotSeal = new Uint32Array(8);
assert.throws(function () {
addon.freeze_js_object(shouldNotSeal);
});
});

it("correctly reads a TypedArray using the borrow API", function () {
var b = new ArrayBuffer(32);
var a = new Int32Array(b, 4, 4);
Expand Down
16 changes: 16 additions & 0 deletions test/napi/src/js/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@ pub fn return_js_object_with_string(mut cx: FunctionContext) -> JsResult<JsObjec
Ok(js_object)
}

pub fn freeze_js_object(mut cx: FunctionContext) -> JsResult<JsUndefined> {
let obj: Handle<JsObject> = cx.argument::<JsObject>(0)?;
match obj.freeze(&mut cx) {
Ok(_) => Ok(cx.undefined()),
Err(e) => cx.throw_error(e.to_string()),
}
}

pub fn seal_js_object(mut cx: FunctionContext) -> JsResult<JsUndefined> {
let obj: Handle<JsObject> = cx.argument::<JsObject>(0)?;
match obj.seal(&mut cx) {
Ok(_) => Ok(cx.undefined()),
Err(e) => cx.throw_error(e.to_string()),
}
}

pub fn return_array_buffer(mut cx: FunctionContext) -> JsResult<JsArrayBuffer> {
let b: Handle<JsArrayBuffer> = cx.array_buffer(16)?;
Ok(b)
Expand Down
2 changes: 2 additions & 0 deletions test/napi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> {
"return_js_object_with_mixed_content",
return_js_object_with_mixed_content,
)?;
cx.export_function("freeze_js_object", freeze_js_object)?;
cx.export_function("seal_js_object", seal_js_object)?;

cx.export_function("return_array_buffer", return_array_buffer)?;
cx.export_function("read_array_buffer_with_lock", read_array_buffer_with_lock)?;
Expand Down