[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:
franzih 2016-11-16 02:59:53 -08:00 committed by Commit bot
parent fe9ac966cc
commit 0188c3fba3
2 changed files with 104 additions and 0 deletions

View File

@ -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();

View File

@ -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]);
})();