[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:
parent
7a0a682083
commit
cfe7c9c5ce
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
})();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user