Create a new API Object::SetNativeDataProperty
This new API sets a native data property on an object
directly, as Template::SetNativeDataProperty does.
It is similar to Object::SetAccessor, but properties
set by SetNativeDataProperty without kReadOnly flag
can be replaced.
Bug:chromium:617892
Change-Id: I32973f7190906d76be6802da9a0489edce0bd93e
Reviewed-on: https://chromium-review.googlesource.com/479474
Reviewed-by: Jochen Eisinger <jochen@chromium.org>
Commit-Queue: Hitoshi Yoshida <peria@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44716}
diff --git a/include/v8.h b/include/v8.h
index accc280..57449bb 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -3146,6 +3146,16 @@
AccessControl settings = DEFAULT);
/**
+ * Sets a native data property like Template::SetNativeDataProperty, but
+ * this method sets on this object directly.
+ */
+ V8_WARN_UNUSED_RESULT Maybe<bool> SetNativeDataProperty(
+ Local<Context> context, Local<Name> name,
+ AccessorNameGetterCallback getter,
+ AccessorNameSetterCallback setter = nullptr,
+ Local<Value> data = Local<Value>(), PropertyAttribute attributes = None);
+
+ /**
* Functionality for private properties.
* This is an experimental feature, use at your own risk.
* Note: Private properties are not inherited. Do not rely on this, since it
diff --git a/src/api.cc b/src/api.cc
index 6816047..eee1be8 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -4782,21 +4782,20 @@
return Has(context, index).FromMaybe(false);
}
-
template <typename Getter, typename Setter, typename Data>
static Maybe<bool> ObjectSetAccessor(Local<Context> context, Object* self,
Local<Name> name, Getter getter,
Setter setter, Data data,
AccessControl settings,
- PropertyAttribute attributes) {
+ PropertyAttribute attributes,
+ bool is_special_data_property) {
PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, SetAccessor, bool);
if (!Utils::OpenHandle(self)->IsJSObject()) return Just(false);
i::Handle<i::JSObject> obj =
i::Handle<i::JSObject>::cast(Utils::OpenHandle(self));
v8::Local<AccessorSignature> signature;
- auto info =
- MakeAccessorInfo(name, getter, setter, data, settings, attributes,
- signature, i::FLAG_disable_old_api_accessors, false);
+ auto info = MakeAccessorInfo(name, getter, setter, data, settings, attributes,
+ signature, is_special_data_property, false);
if (info.is_null()) return Nothing<bool>();
bool fast = obj->HasFastProperties();
i::Handle<i::Object> result;
@@ -4817,7 +4816,8 @@
MaybeLocal<Value> data, AccessControl settings,
PropertyAttribute attribute) {
return ObjectSetAccessor(context, this, name, getter, setter,
- data.FromMaybe(Local<Value>()), settings, attribute);
+ data.FromMaybe(Local<Value>()), settings, attribute,
+ i::FLAG_disable_old_api_accessors);
}
@@ -4826,7 +4826,8 @@
AccessControl settings, PropertyAttribute attributes) {
auto context = ContextFromHeapObject(Utils::OpenHandle(this));
return ObjectSetAccessor(context, this, name, getter, setter, data, settings,
- attributes).FromMaybe(false);
+ attributes, i::FLAG_disable_old_api_accessors)
+ .FromMaybe(false);
}
@@ -4836,7 +4837,8 @@
PropertyAttribute attributes) {
auto context = ContextFromHeapObject(Utils::OpenHandle(this));
return ObjectSetAccessor(context, this, name, getter, setter, data, settings,
- attributes).FromMaybe(false);
+ attributes, i::FLAG_disable_old_api_accessors)
+ .FromMaybe(false);
}
@@ -4859,6 +4861,15 @@
static_cast<i::PropertyAttributes>(attribute));
}
+Maybe<bool> Object::SetNativeDataProperty(v8::Local<v8::Context> context,
+ v8::Local<Name> name,
+ AccessorNameGetterCallback getter,
+ AccessorNameSetterCallback setter,
+ v8::Local<Value> data,
+ PropertyAttribute attributes) {
+ return ObjectSetAccessor(context, this, name, getter, setter, data, DEFAULT,
+ attributes, true);
+}
Maybe<bool> v8::Object::HasOwnProperty(Local<Context> context,
Local<Name> key) {
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index c378c57..3e088a9 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -2938,6 +2938,7 @@
v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
+ v8::Local<v8::Symbol> sym4 = v8::Symbol::New(isolate, v8_str("native"));
CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
@@ -3024,6 +3025,23 @@
->Equals(env.local(), v8::Integer::New(isolate, 42))
.FromJust());
+ CHECK(obj->SetNativeDataProperty(env.local(), sym4, SymbolAccessorGetter)
+ .FromJust());
+ CHECK(obj->Get(env.local(), sym4).ToLocalChecked()->IsUndefined());
+ CHECK(obj->Set(env.local(), v8_str("accessor_native"),
+ v8::Integer::New(isolate, 123))
+ .FromJust());
+ CHECK_EQ(123, obj->Get(env.local(), sym4)
+ .ToLocalChecked()
+ ->Int32Value(env.local())
+ .FromJust());
+ CHECK(obj->Set(env.local(), sym4, v8::Integer::New(isolate, 314)).FromJust());
+ CHECK(obj->Get(env.local(), sym4)
+ .ToLocalChecked()
+ ->Equals(env.local(), v8::Integer::New(isolate, 314))
+ .FromJust());
+ CHECK(obj->Delete(env.local(), v8_str("accessor_native")).FromJust());
+
// Add another property and delete it afterwards to force the object in
// slow case.
CHECK(