[test] Add tests for definitions in object literal.
Properties can be defined inside the object literal (ES6) or after object creation. The behavior differes if there are accessors, interceptors or proxies in the Object prototype chain. These test cases assure we preserve correct behavior as we improve performance of definitions in literals. BUG=v8:5624 Review-Url: https://codereview.chromium.org/2501553002 Cr-Commit-Position: refs/heads/master@{#41024}
This commit is contained in:
parent
fe9ac966cc
commit
0188c3fba3
@ -656,6 +656,68 @@ THREADED_TEST(DefinerCallbackGetAndDefine) {
|
||||
CHECK_EQ(define_was_called_in_order, true);
|
||||
}
|
||||
|
||||
namespace { // namespace for InObjectLiteralDefinitionWithInterceptor
|
||||
|
||||
// Workaround for no-snapshot builds: only intercept once Context::New() is
|
||||
// done, otherwise we'll intercept
|
||||
// bootstrapping like defining array on the global object.
|
||||
bool context_is_done = false;
|
||||
bool getter_callback_was_called = false;
|
||||
|
||||
void ReturnUndefinedGetterCallback(
|
||||
Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
if (context_is_done) {
|
||||
getter_callback_was_called = true;
|
||||
info.GetReturnValue().SetUndefined();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Check that an interceptor is not invoked during ES6 style definitions inside
|
||||
// an object literal.
|
||||
THREADED_TEST(InObjectLiteralDefinitionWithInterceptor) {
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
LocalContext env;
|
||||
|
||||
// Set up a context in which all global object definitions are intercepted.
|
||||
v8::Local<v8::FunctionTemplate> templ =
|
||||
v8::FunctionTemplate::New(CcTest::isolate());
|
||||
v8::Local<ObjectTemplate> object_template = templ->InstanceTemplate();
|
||||
object_template->SetHandler(
|
||||
v8::NamedPropertyHandlerConfiguration(ReturnUndefinedGetterCallback));
|
||||
v8::Local<v8::Context> ctx =
|
||||
v8::Context::New(CcTest::isolate(), nullptr, object_template);
|
||||
|
||||
context_is_done = true;
|
||||
|
||||
// The interceptor returns undefined for any global object,
|
||||
// so setting a property on an object should throw.
|
||||
v8::Local<v8::String> code = v8_str("var o = {}; o.x = 5");
|
||||
{
|
||||
getter_callback_was_called = false;
|
||||
v8::TryCatch try_catch(CcTest::isolate());
|
||||
CHECK(v8::Script::Compile(ctx, code).ToLocalChecked()->Run(ctx).IsEmpty());
|
||||
CHECK(try_catch.HasCaught());
|
||||
CHECK(getter_callback_was_called);
|
||||
}
|
||||
|
||||
// Defining a property in the object literal should not throw
|
||||
// because the interceptor is not invoked.
|
||||
{
|
||||
getter_callback_was_called = false;
|
||||
v8::TryCatch try_catch(CcTest::isolate());
|
||||
code = v8_str("var l = {x: 5};");
|
||||
CHECK(v8::Script::Compile(ctx, code)
|
||||
.ToLocalChecked()
|
||||
->Run(ctx)
|
||||
.ToLocalChecked()
|
||||
->IsUndefined());
|
||||
CHECK(!try_catch.HasCaught());
|
||||
CHECK(!getter_callback_was_called);
|
||||
}
|
||||
}
|
||||
|
||||
THREADED_TEST(InterceptorHasOwnProperty) {
|
||||
LocalContext context;
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
|
@ -260,3 +260,45 @@ TestNumericNamesSetter(['1.2', '1.3'], {
|
||||
set 1.2(_) {; },
|
||||
set 1.30(_) {; }
|
||||
});
|
||||
|
||||
|
||||
(function TestPrototypeInObjectLiteral() {
|
||||
// The prototype chain should not be used if the definition
|
||||
// happens in the object literal.
|
||||
|
||||
Object.defineProperty(Object.prototype, 'c', {
|
||||
get: function () {
|
||||
return 21;
|
||||
},
|
||||
set: function () {
|
||||
}
|
||||
});
|
||||
|
||||
var o = {};
|
||||
o.c = 7;
|
||||
assertEquals(21, o.c);
|
||||
|
||||
var l = {c: 7};
|
||||
assertEquals(7, l.c);
|
||||
|
||||
delete Object.prototype.c;
|
||||
})();
|
||||
|
||||
(function TestProxyWithDefinitionInObjectLiteral() {
|
||||
// Trap for set should not be used if the definition
|
||||
// happens in the object literal.
|
||||
var handler = {
|
||||
set: function(target, name, value) {
|
||||
}
|
||||
};
|
||||
|
||||
const prop = 'a';
|
||||
|
||||
var p = new Proxy({}, handler);
|
||||
p[prop] = 'my value';
|
||||
assertEquals(undefined, p[prop]);
|
||||
|
||||
|
||||
var l = new Proxy({[prop]: 'my value'}, handler);
|
||||
assertEquals('my value', l[prop]);
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user