[es6] Support optional "receiver" argument in Reflect.get.

Also add some more tests.

R=rossberg
BUG=

Review URL: https://codereview.chromium.org/1392203002

Cr-Commit-Position: refs/heads/master@{#31181}
This commit is contained in:
neis 2015-10-08 07:23:03 -07:00 committed by Commit bot
parent 7a0a682083
commit cfe7c9c5ce
5 changed files with 82 additions and 20 deletions

View File

@ -1892,12 +1892,16 @@ void Genesis::InitializeGlobal_harmony_tolength() {
}
static void SimpleInstallFunction(
Handle<JSObject>& base, const char* name, Builtins::Name call, int len) {
static void SimpleInstallFunction(Handle<JSObject>& base, const char* name,
Builtins::Name call, int len, bool adapt) {
Handle<JSFunction> fun =
InstallFunction(base, name, JS_OBJECT_TYPE, JSObject::kHeaderSize,
MaybeHandle<JSObject>(), call);
fun->shared()->set_internal_formal_parameter_count(len);
if (adapt) {
fun->shared()->set_internal_formal_parameter_count(len);
} else {
fun->shared()->DontAdaptArguments();
}
fun->shared()->set_length(len);
}
@ -1914,13 +1918,13 @@ void Genesis::InitializeGlobal_harmony_reflect() {
JSObject::AddProperty(global, reflect_string, reflect, DONT_ENUM);
SimpleInstallFunction(reflect, "deleteProperty",
Builtins::kReflectDeleteProperty, 2);
Builtins::kReflectDeleteProperty, 2, true);
SimpleInstallFunction(reflect, "get",
Builtins::kReflectGet, 3);
Builtins::kReflectGet, 3, false);
SimpleInstallFunction(reflect, "has",
Builtins::kReflectHas, 2);
Builtins::kReflectHas, 2, true);
SimpleInstallFunction(reflect, "isExtensible",
Builtins::kReflectIsExtensible, 1);
Builtins::kReflectIsExtensible, 1, true);
}

View File

@ -1474,14 +1474,10 @@ BUILTIN(ReflectDeleteProperty) {
// ES6 section 26.1.6 Reflect.get
BUILTIN(ReflectGet) {
HandleScope scope(isolate);
DCHECK_LE(3, args.length());
DCHECK_LE(args.length(), 4);
Handle<Object> target = args.at<Object>(1);
Handle<Object> key = args.at<Object>(2);
// Handle<Object> receiver = args.length() == 4 ? args.at<Object>(3) : target;
//
// TODO(neis): We ignore the receiver argument for now because
// GetPropertyOrElement doesn't support it yet.
Handle<Object> undef = isolate->factory()->undefined_value();
Handle<Object> target = args.length() > 1 ? args.at<Object>(1) : undef;
Handle<Object> key = args.length() > 2 ? args.at<Object>(2) : undef;
Handle<Object> receiver = args.length() > 3 ? args.at<Object>(3) : target;
if (!target->IsJSReceiver()) {
THROW_NEW_ERROR_RETURN_FAILURE(
@ -1496,7 +1492,8 @@ BUILTIN(ReflectGet) {
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Object::GetPropertyOrElement(target, name));
isolate, result, Object::GetPropertyOrElement(
Handle<JSReceiver>::cast(target), name, receiver));
return *result;
}

View File

@ -7259,6 +7259,16 @@ MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object,
}
MaybeHandle<Object> Object::GetPropertyOrElement(Handle<JSReceiver> holder,
Handle<Name> name,
Handle<Object> receiver,
LanguageMode language_mode) {
LookupIterator it = LookupIterator::PropertyOrElement(
name->GetIsolate(), receiver, name, holder);
return GetProperty(&it, language_mode);
}
Maybe<bool> JSReceiver::HasProperty(Handle<JSReceiver> object,
Handle<Name> name) {
// Call the "has" trap on proxies.

View File

@ -1250,6 +1250,9 @@ class Object {
MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement(
Handle<Object> object, Handle<Name> name,
LanguageMode language_mode = SLOPPY);
MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement(
Handle<JSReceiver> holder, Handle<Name> name, Handle<Object> receiver,
LanguageMode language_mode = SLOPPY);
MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty(
Isolate* isolate, Handle<Object> object, const char* key,
LanguageMode language_mode = SLOPPY);

View File

@ -53,6 +53,10 @@ function prepare(tgt) {
tgt[sym] = "foo";
tgt["noconf"] = 43;
Object.defineProperty(tgt, "noconf", {configurable: false});
Object.defineProperty(tgt, "getter",
{ get: function () {return this.bla}, configurable: true });
Object.defineProperty(tgt, "setter",
{ set: function () {}, configurable: true });
}
@ -83,14 +87,43 @@ function prepare(tgt) {
(function testReflectGetOnObject() {
var receiver = {bla: false};
for (let tgt of objects) {
prepare(tgt);
assertEquals(true, Reflect.get(tgt, "bla"));
assertEquals(true, Reflect.get(tgt, "bla", tgt));
assertEquals(true, Reflect.get(tgt, "bla", receiver));
assertEquals(42, Reflect.get(tgt, 4));
assertEquals(42, Reflect.get(tgt, 4, tgt));
assertEquals(42, Reflect.get(tgt, 4, receiver));
assertEquals(42, Reflect.get(tgt, "4"));
assertEquals(42, Reflect.get(tgt, "4", tgt));
assertEquals(42, Reflect.get(tgt, "4", receiver));
assertEquals("foo", Reflect.get(tgt, sym));
assertEquals(undefined, Reflect.get(tgt, "doesnotexist"));
assertEquals("foo", Reflect.get(tgt, sym, tgt));
assertEquals("foo", Reflect.get(tgt, sym, receiver));
assertEquals(43, Reflect.get(tgt, "noconf"));
assertEquals(43, Reflect.get(tgt, "noconf", tgt));
assertEquals(43, Reflect.get(tgt, "noconf", receiver));
assertEquals(true, Reflect.get(tgt, "getter"));
assertEquals(true, Reflect.get(tgt, "getter", tgt));
assertEquals(false, Reflect.get(tgt, "getter", receiver));
assertEquals(undefined, Reflect.get(tgt, "setter"));
assertEquals(undefined, Reflect.get(tgt, "setter", tgt));
assertEquals(undefined, Reflect.get(tgt, "setter", receiver));
assertEquals(undefined, Reflect.get(tgt, "foo"));
assertEquals(undefined, Reflect.get(tgt, "foo", tgt));
assertEquals(undefined, Reflect.get(tgt, "foo", receiver));
assertEquals(undefined, Reflect.get(tgt, 666));
assertEquals(undefined, Reflect.get(tgt, 666, tgt));
assertEquals(undefined, Reflect.get(tgt, 666, receiver));
let proto = tgt.__proto__;
tgt.__proto__ = { get foo() {return this.bla} };
assertEquals(true, Reflect.get(tgt, "foo"));
assertEquals(true, Reflect.get(tgt, "foo", tgt));
assertEquals(false, Reflect.get(tgt, "foo", receiver));
tgt.__proto__ = proto;
}
})();
@ -128,8 +161,16 @@ function prepare(tgt) {
assertTrue(Reflect.has(tgt, 4));
assertTrue(Reflect.has(tgt, "4"));
assertTrue(Reflect.has(tgt, sym));
assertFalse(Reflect.has(tgt, "doesnotexist"));
assertTrue(Reflect.has(tgt, "noconf"));
assertTrue(Reflect.has(tgt, "getter"));
assertTrue(Reflect.has(tgt, "setter"));
assertFalse(Reflect.has(tgt, "foo"));
assertFalse(Reflect.has(tgt, 666));
let proto = tgt.__proto__;
tgt.__proto__ = { get foo() {return this.bla} };
assertEquals(true, Reflect.has(tgt, "foo"));
tgt.__proto__ = proto;
}
})();
@ -173,10 +214,17 @@ function prepare(tgt) {
}
assertTrue(Reflect.deleteProperty(tgt, sym));
assertEquals(undefined, Object.getOwnPropertyDescriptor(tgt, sym));
assertTrue(Reflect.deleteProperty(tgt, "doesnotexist"));
assertTrue(Reflect.deleteProperty(tgt, 666));
assertFalse(Reflect.deleteProperty(tgt, "noconf"));
assertEquals(43, tgt.noconf);
assertTrue(Reflect.deleteProperty(tgt, "getter"));
assertTrue(Reflect.deleteProperty(tgt, "setter"));
assertTrue(Reflect.deleteProperty(tgt, "foo"));
assertTrue(Reflect.deleteProperty(tgt, 666));
let proto = tgt.__proto__;
tgt.__proto__ = { get foo() {return this.bla} };
assertEquals(true, Reflect.deleteProperty(tgt, "foo"));
tgt.__proto__ = proto;
}
})();