mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
n-api: support for object freeze/seal
PR-URL: https://github.com/nodejs/node/pull/35359 Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com> Reviewed-By: Michael Dawson <midawson@redhat.com> Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
This commit is contained in:
parent
c208a20f9c
commit
19f14517c7
|
|
@ -4227,6 +4227,53 @@ this API will set the properties on the object one at a time, as defined by
|
|||
`DefineOwnProperty()` (described in [Section 9.1.6][] of the ECMA-262
|
||||
specification).
|
||||
|
||||
#### napi_object_freeze
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
> Stability: 1 - Experimental
|
||||
|
||||
```c
|
||||
napi_status napi_object_freeze(napi_env env,
|
||||
napi_value object);
|
||||
```
|
||||
|
||||
* `[in] env`: The environment that the N-API call is invoked under.
|
||||
* `[in] object`: The object to freeze.
|
||||
|
||||
Returns `napi_ok` if the API succeeded.
|
||||
|
||||
This method freezes a given object. This prevents new properties from
|
||||
being added to it, existing properties from being removed, prevents
|
||||
changing the enumerability, configurability, or writability of existing
|
||||
properties, and prevents the values of existing properties from being changed.
|
||||
It also prevents the object's prototype from being changed. This is described
|
||||
in [Section 19.1.2.6](https://tc39.es/ecma262/#sec-object.freeze) of the
|
||||
ECMA-262 specification.
|
||||
|
||||
#### napi_object_seal
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
> Stability: 1 - Experimental
|
||||
|
||||
```c
|
||||
napi_status napi_object_seal(napi_env env,
|
||||
napi_value object);
|
||||
```
|
||||
|
||||
* `[in] env`: The environment that the N-API call is invoked under.
|
||||
* `[in] object`: The object to seal.
|
||||
|
||||
Returns `napi_ok` if the API succeeded.
|
||||
|
||||
This method seals a given object. This prevents new properties from being
|
||||
added to it, as well as marking all existing properties as non-configurable.
|
||||
This is described in [Section 19.1.2.20](https://tc39.es/ecma262/#sec-object.seal)
|
||||
of the ECMA-262 specification.
|
||||
|
||||
## Working with JavaScript functions
|
||||
|
||||
N-API provides a set of APIs that allow JavaScript code to
|
||||
|
|
|
|||
|
|
@ -550,6 +550,10 @@ napi_check_object_type_tag(napi_env env,
|
|||
napi_value value,
|
||||
const napi_type_tag* type_tag,
|
||||
bool* result);
|
||||
NAPI_EXTERN napi_status napi_object_freeze(napi_env env,
|
||||
napi_value object);
|
||||
NAPI_EXTERN napi_status napi_object_seal(napi_env env,
|
||||
napi_value object);
|
||||
#endif // NAPI_EXPERIMENTAL
|
||||
|
||||
EXTERN_C_END
|
||||
|
|
|
|||
|
|
@ -1362,6 +1362,42 @@ napi_status napi_define_properties(napi_env env,
|
|||
return GET_RETURN_STATUS(env);
|
||||
}
|
||||
|
||||
napi_status napi_object_freeze(napi_env env,
|
||||
napi_value object) {
|
||||
NAPI_PREAMBLE(env);
|
||||
|
||||
v8::Local<v8::Context> context = env->context();
|
||||
v8::Local<v8::Object> obj;
|
||||
|
||||
CHECK_TO_OBJECT(env, context, obj, object);
|
||||
|
||||
v8::Maybe<bool> set_frozen =
|
||||
obj->SetIntegrityLevel(context, v8::IntegrityLevel::kFrozen);
|
||||
|
||||
RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
|
||||
set_frozen.FromMaybe(false), napi_generic_failure);
|
||||
|
||||
return GET_RETURN_STATUS(env);
|
||||
}
|
||||
|
||||
napi_status napi_object_seal(napi_env env,
|
||||
napi_value object) {
|
||||
NAPI_PREAMBLE(env);
|
||||
|
||||
v8::Local<v8::Context> context = env->context();
|
||||
v8::Local<v8::Object> obj;
|
||||
|
||||
CHECK_TO_OBJECT(env, context, obj, object);
|
||||
|
||||
v8::Maybe<bool> set_sealed =
|
||||
obj->SetIntegrityLevel(context, v8::IntegrityLevel::kSealed);
|
||||
|
||||
RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
|
||||
set_sealed.FromMaybe(false), napi_generic_failure);
|
||||
|
||||
return GET_RETURN_STATUS(env);
|
||||
}
|
||||
|
||||
napi_status napi_is_array(napi_env env, napi_value value, bool* result) {
|
||||
CHECK_ENV(env);
|
||||
CHECK_ARG(env, value);
|
||||
|
|
|
|||
|
|
@ -275,3 +275,43 @@ assert.deepStrictEqual(test_object.TestGetProperty(), {
|
|||
keyIsNull: 'Invalid argument',
|
||||
resultIsNull: 'Invalid argument'
|
||||
});
|
||||
|
||||
{
|
||||
const obj = { x: 'a', y: 'b', z: 'c' };
|
||||
|
||||
test_object.TestSeal(obj);
|
||||
|
||||
assert.strictEqual(Object.isSealed(obj), true);
|
||||
|
||||
assert.throws(() => {
|
||||
obj.w = 'd';
|
||||
}, /Cannot add property w, object is not extensible/);
|
||||
|
||||
assert.throws(() => {
|
||||
delete obj.x;
|
||||
}, /Cannot delete property 'x' of #<Object>/);
|
||||
|
||||
// Sealed objects allow updating existing properties,
|
||||
// so this should not throw.
|
||||
obj.x = 'd';
|
||||
}
|
||||
|
||||
{
|
||||
const obj = { x: 10, y: 10, z: 10 };
|
||||
|
||||
test_object.TestFreeze(obj);
|
||||
|
||||
assert.strictEqual(Object.isFrozen(obj), true);
|
||||
|
||||
assert.throws(() => {
|
||||
obj.x = 10;
|
||||
}, /Cannot assign to read only property 'x' of object '#<Object>/);
|
||||
|
||||
assert.throws(() => {
|
||||
obj.w = 15;
|
||||
}, /Cannot add property w, object is not extensible/);
|
||||
|
||||
assert.throws(() => {
|
||||
delete obj.x;
|
||||
}, /Cannot delete property 'x' of #<Object>/);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -472,6 +472,30 @@ static napi_value TestGetProperty(napi_env env,
|
|||
return object;
|
||||
}
|
||||
|
||||
static napi_value TestFreeze(napi_env env,
|
||||
napi_callback_info info) {
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
|
||||
|
||||
napi_value object = args[0];
|
||||
NAPI_CALL(env, napi_object_freeze(env, object));
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
static napi_value TestSeal(napi_env env,
|
||||
napi_callback_info info) {
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
|
||||
|
||||
napi_value object = args[0];
|
||||
NAPI_CALL(env, napi_object_seal(env, object));
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
// We create two type tags. They are basically 128-bit UUIDs.
|
||||
static const napi_type_tag type_tags[2] = {
|
||||
{ 0xdaf987b3cc62481a, 0xb745b0497f299531 },
|
||||
|
|
@ -532,6 +556,8 @@ napi_value Init(napi_env env, napi_value exports) {
|
|||
DECLARE_NAPI_PROPERTY("TypeTaggedInstance", TypeTaggedInstance),
|
||||
DECLARE_NAPI_PROPERTY("CheckTypeTag", CheckTypeTag),
|
||||
DECLARE_NAPI_PROPERTY("TestGetProperty", TestGetProperty),
|
||||
DECLARE_NAPI_PROPERTY("TestFreeze", TestFreeze),
|
||||
DECLARE_NAPI_PROPERTY("TestSeal", TestSeal),
|
||||
};
|
||||
|
||||
init_test_null(env, exports);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user