Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Unified Diff: test/cctest/test-api.cc

Side-by-side diff isn't available for this file because of its large size.
Issue 2807333003: [api] Add DefineProperty() method that skips interceptors.
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
Download patch
« src/objects.h ('K') | « src/objects.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 65e6135f8a074c5b3a661b94f12805c62aa22bd3..fc30f444924d0d97688f2247a42a84beea1ecaf9 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -15965,6 +15965,322 @@ TEST(DefineProperty) {
}
}
+TEST(DefinePropertyWithoutInterceptors) {
Franzi 2017/04/12 08:58:18 I think the tests should be in test-api-intercepto
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope handle_scope(isolate);
+
+ v8::Local<v8::Name> p;
+
+ CompileRun(
+ "var a = {};"
+ "var b = [];"
+ "Object.defineProperty(a, 'v1', {value: 23});"
+ "Object.defineProperty(a, 'v2', {value: 23, configurable: true});");
+
+ v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
+ env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
+ v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
+ env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
+
+ v8::PropertyDescriptor desc(v8_num(42));
+ {
+ // Use a data descriptor.
+
+ // Cannot change a non-configurable property.
+ p = v8_str("v1");
+ v8::TryCatch try_catch(isolate);
+ CHECK(!obj->DefinePropertyWithoutInterceptors(env.local(), p, desc)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
+
+ // Change a configurable property.
+ p = v8_str("v2");
+ obj->DefinePropertyWithoutInterceptors(env.local(), p, desc).FromJust();
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ val = obj->Get(env.local(), p).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+
+ // Check that missing writable has default value false.
+ p = v8_str("v12");
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ val = obj->Get(env.local(), p).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ v8::PropertyDescriptor desc2(v8_num(43));
+ CHECK(!obj->DefinePropertyWithoutInterceptors(env.local(), p, desc2)
+ .FromJust());
+ val = obj->Get(env.local(), p).ToLocalChecked();
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ {
+ // Set a regular property.
+ p = v8_str("v3");
+ v8::TryCatch try_catch(isolate);
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ }
+
+ {
+ // Set an indexed property.
+ v8::TryCatch try_catch(isolate);
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), v8_str("1"), desc)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ }
+
+ {
+ // No special case when changing array length.
+ v8::TryCatch try_catch(isolate);
+ // Use a writable descriptor, otherwise the next test, that changes
+ // the array length will fail.
+ v8::PropertyDescriptor desc(v8_num(42), true);
+ CHECK(arr->DefinePropertyWithoutInterceptors(env.local(), v8_str("length"),
+ desc)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ {
+ // Special cases for arrays: index exceeds the array's length.
+ v8::TryCatch try_catch(isolate);
+ CHECK(
+ arr->DefinePropertyWithoutInterceptors(env.local(), v8_str("100"), desc)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ CHECK_EQ(101U, arr->Length());
+ v8::Local<v8::Value> val = arr->Get(env.local(), 100).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+
+ // Set an existing entry.
+ CHECK(arr->DefinePropertyWithoutInterceptors(env.local(), v8_str("0"), desc)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ val = arr->Get(env.local(), 0).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ }
+
+ {
+ // Use a generic descriptor.
+ v8::PropertyDescriptor desc_generic;
+
+ p = v8_str("v4");
+ v8::TryCatch try_catch(isolate);
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc_generic)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
+ CHECK(val->IsUndefined());
+
+ obj->Set(env.local(), p, v8_num(1)).FromJust();
+ CHECK(!try_catch.HasCaught());
+
+ val = obj->Get(env.local(), p).ToLocalChecked();
+ CHECK(val->IsUndefined());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ {
+ // Use a data descriptor with undefined value.
+ v8::PropertyDescriptor desc_empty(v8::Undefined(isolate));
+
+ v8::TryCatch try_catch(isolate);
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc_empty)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
+ CHECK(val->IsUndefined());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ {
+ // Use a descriptor with attribute == v8::ReadOnly.
+ v8::PropertyDescriptor desc_read_only(v8_num(42), false);
+ desc_read_only.set_enumerable(true);
+ desc_read_only.set_configurable(true);
+
+ p = v8_str("v5");
+ v8::TryCatch try_catch(isolate);
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc_read_only)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
+ CHECK_EQ(v8::ReadOnly,
+ obj->GetPropertyAttributes(env.local(), p).FromJust());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ {
+ // Use an accessor descriptor with empty handles.
+ v8::PropertyDescriptor desc_empty(v8::Undefined(isolate),
+ v8::Undefined(isolate));
+
+ p = v8_str("v6");
+ v8::TryCatch try_catch(isolate);
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc_empty)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
+ CHECK(val->IsUndefined());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ {
+ // Use an accessor descriptor.
+ CompileRun(
+ "var set = function(x) {this.val = 2*x;};"
+ "var get = function() {return this.val || 0;};");
+
+ v8::Local<v8::Function> get = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(env.local(), v8_str("get")).ToLocalChecked());
+ v8::Local<v8::Function> set = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(env.local(), v8_str("set")).ToLocalChecked());
+ v8::PropertyDescriptor desc(get, set);
+
+ p = v8_str("v7");
+ v8::TryCatch try_catch(isolate);
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+
+ v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(0.0, val->NumberValue(env.local()).FromJust());
+ CHECK(!try_catch.HasCaught());
+
+ obj->Set(env.local(), p, v8_num(7)).FromJust();
+ CHECK(!try_catch.HasCaught());
+
+ val = obj->Get(env.local(), p).ToLocalChecked();
+ CHECK(val->IsNumber());
+ CHECK_EQ(14.0, val->NumberValue(env.local()).FromJust());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ {
+ // Redefine an existing property.
+
+ // desc = {value: 42, enumerable: true}
+ v8::PropertyDescriptor desc(v8_num(42));
+ desc.set_enumerable(true);
+
+ p = v8_str("v8");
+ v8::TryCatch try_catch(isolate);
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+
+ // desc = {enumerable: true}
+ v8::PropertyDescriptor desc_true((v8::Local<v8::Value>()));
+ desc_true.set_enumerable(true);
+
+ // Successful redefinition because all present attributes have the same
+ // value as the current descriptor.
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc_true)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+
+ // desc = {}
+ v8::PropertyDescriptor desc_empty;
+ // Successful redefinition because no attributes are overwritten in the
+ // current descriptor.
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc_empty)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+
+ // desc = {enumerable: false}
+ v8::PropertyDescriptor desc_false((v8::Local<v8::Value>()));
+ desc_false.set_enumerable(false);
+ // Not successful because we cannot define a different value for enumerable.
+ CHECK(!obj->DefinePropertyWithoutInterceptors(env.local(), p, desc_false)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ {
+ // Redefine a property that has a getter.
+ CompileRun("var get = function() {};");
+ v8::Local<v8::Function> get = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(env.local(), v8_str("get")).ToLocalChecked());
+
+ // desc = {get: function() {}}
+ v8::PropertyDescriptor desc(get, v8::Local<v8::Function>());
+ v8::TryCatch try_catch(isolate);
+
+ p = v8_str("v9");
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+
+ // desc_empty = {}
+ // Successful because we are not redefining the current getter.
+ v8::PropertyDescriptor desc_empty;
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc_empty)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+
+ // desc = {get: function() {}}
+ // Successful because we redefine the getter with its current value.
+ CHECK(obj->DefinePropertyWithoutInterceptors(env.local(), p, desc)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+
+ // desc = {get: undefined}
+ v8::PropertyDescriptor desc_undefined(v8::Undefined(isolate),
+ v8::Local<v8::Function>());
+ // Not successful because we cannot redefine with the current value of get
+ // with undefined.
+ CHECK(
+ !obj->DefinePropertyWithoutInterceptors(env.local(), p, desc_undefined)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ CompileRun("Object.freeze(a);");
+ {
+ // We cannot change non-extensible objects.
+ v8::TryCatch try_catch(isolate);
+ CHECK(!obj->DefinePropertyWithoutInterceptors(env.local(), v8_str("v10"),
+ desc)
+ .FromJust());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
+ templ->SetAccessCheckCallback(AccessAlwaysBlocked);
+ v8::Local<v8::Object> access_checked =
+ templ->NewInstance(env.local()).ToLocalChecked();
+ {
+ v8::TryCatch try_catch(isolate);
+ CHECK(access_checked
+ ->DefinePropertyWithoutInterceptors(env.local(), v8_str("v11"),
+ desc)
+ .IsNothing());
+ CHECK(try_catch.HasCaught());
+ }
+}
+
THREADED_TEST(GetCurrentContextWhenNotInContext) {
i::Isolate* isolate = CcTest::i_isolate();
CHECK(isolate != NULL);
« src/objects.h ('K') | « src/objects.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698