Commit 6f0850c6 authored by jkummerow's avatar jkummerow Committed by Commit bot

[proxies] Update Object.defineProperty/ies for JSProxies

BUG=v8:1543
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#32103}
parent ed570fac
......@@ -1010,44 +1010,15 @@ function ObjectCreate(proto, properties) {
// ES5 section 15.2.3.6.
function ObjectDefineProperty(obj, p, attributes) {
// The new pure-C++ implementation doesn't support Proxies yet, nor O.o.
// The new pure-C++ implementation doesn't support O.o.
// TODO(jkummerow): Implement missing features and remove fallback path.
if (%_IsJSProxy(obj) || %IsObserved(obj)) {
if (%IsObserved(obj)) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError(kCalledOnNonObject, "Object.defineProperty");
}
var name = TO_NAME(p);
if (%_IsJSProxy(obj)) {
// Clone the attributes object for protection.
// TODO(rossberg): not spec'ed yet, so not sure if this should involve
// non-own properties as it does (or non-enumerable ones, as it doesn't?).
var attributesClone = { __proto__: null };
for (var a in attributes) {
attributesClone[a] = attributes[a];
}
DefineProxyProperty(obj, name, attributesClone, true);
// The following would implement the spec as in the current proposal,
// but after recent comments on es-discuss, is most likely obsolete.
/*
var defineObj = FromGenericPropertyDescriptor(desc);
var names = ObjectGetOwnPropertyNames(attributes);
var standardNames =
{value: 0, writable: 0, get: 0, set: 0, enumerable: 0, configurable: 0};
for (var i = 0; i < names.length; i++) {
var N = names[i];
if (!(%HasOwnProperty(standardNames, N))) {
var attr = GetOwnPropertyJS(attributes, N);
DefineOwnProperty(descObj, N, attr, true);
}
}
// This is really confusing the types, but it is what the proxies spec
// currently requires:
desc = descObj;
*/
} else {
var desc = ToPropertyDescriptor(attributes);
DefineOwnProperty(obj, name, desc, true);
}
var desc = ToPropertyDescriptor(attributes);
DefineOwnProperty(obj, name, desc, true);
return obj;
}
return %ObjectDefineProperty(obj, p, attributes);
......@@ -1078,9 +1049,9 @@ function GetOwnEnumerablePropertyNames(object) {
// ES5 section 15.2.3.7.
function ObjectDefineProperties(obj, properties) {
// The new pure-C++ implementation doesn't support Proxies yet, nor O.o.
// The new pure-C++ implementation doesn't support O.o.
// TODO(jkummerow): Implement missing features and remove fallback path.
if (%_IsJSProxy(obj) || %_IsJSProxy(properties) || %IsObserved(obj)) {
if (%IsObserved(obj)) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError(kCalledOnNonObject, "Object.defineProperties");
}
......
This diff is collapsed.
......@@ -9528,6 +9528,11 @@ class JSProxy: public JSReceiver {
static bool GetOwnPropertyDescriptor(LookupIterator* it,
PropertyDescriptor* desc);
// ES6 9.5.6
static bool DefineOwnProperty(Isolate* isolate, Handle<JSProxy> object,
Handle<Object> key, PropertyDescriptor* desc,
ShouldThrow should_throw);
MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithHandler(
Handle<JSProxy> proxy,
Handle<Object> receiver,
......@@ -9543,10 +9548,9 @@ class JSProxy: public JSReceiver {
Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
Handle<Object> value, ShouldThrow should_throw, bool* done);
MUST_USE_RESULT static Maybe<PropertyAttributes>
GetPropertyAttributesWithHandler(Handle<JSProxy> proxy,
Handle<Object> receiver,
Handle<Name> name);
MUST_USE_RESULT static Maybe<PropertyAttributes> GetPropertyAttributes(
LookupIterator* it);
MUST_USE_RESULT static Maybe<bool> SetPropertyWithHandler(
Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
Handle<Object> value, ShouldThrow should_throw);
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-proxies
// Check basic call to trap.
var g_target, g_name, g_desc;
var handler = {
defineProperty: function(target, name, desc) {
g_target = target;
g_name = name;
g_desc = desc;
return true;
}
}
var target = {}
var proxy = new Proxy(target, handler);
var desc = { value: 1, writable: true, configurable: true, enumerable: true };
Object.defineProperty(proxy, "foo", desc);
assertSame(target, g_target);
assertEquals("foo", g_name);
assertEquals(desc, g_desc);
// Check specific steps in the spec:
// Step 6: Trap isn't callable.
handler.defineProperty = 1;
assertThrows("Object.defineProperty(proxy, 'foo', {value: 2})", TypeError);
// Step 7: Trap is undefined.
handler.defineProperty = undefined;
Object.defineProperty(proxy, "prop1", desc);
assertEquals(desc, Object.getOwnPropertyDescriptor(target, "prop1"));
var target2 = {};
var proxy2 = new Proxy(target2, {});
Object.defineProperty(proxy2, "prop2", desc);
assertEquals(desc, Object.getOwnPropertyDescriptor(target2, "prop2"));
// Step 9: Property name is passed to the trap as a string.
handler.defineProperty = function(t, name, d) { g_name = name; return true; };
Object.defineProperty(proxy, 0, desc);
assertTrue(typeof g_name === "string");
assertEquals("0", g_name);
// Step 10: Trap returns false.
handler.defineProperty = function(t, n, d) { return false; }
assertThrows("Object.defineProperty(proxy, 'foo', desc)", TypeError);
// Step 15a: Trap returns true for adding a property to a non-extensible target.
handler.defineProperty = function(t, n, d) { return true; }
Object.freeze(target);
assertThrows("Object.defineProperty(proxy, 'foo', desc)", TypeError);
// Step 15b: Trap returns true for adding a non-configurable property.
target = {};
proxy = new Proxy(target, handler);
desc = {value: 1, writable: true, configurable: false, enumerable: true};
assertThrows("Object.defineProperty(proxy, 'foo', desc)", TypeError);
// No exception is thrown if a non-configurable property exists on the target.
Object.defineProperty(target, "nonconf",
{value: 1, writable: true, configurable: false});
Object.defineProperty(proxy, "nonconf", {value: 2, configurable: false});
// Step 16a: Trap returns true for non-compatible property descriptor.
Object.defineProperty(target, "foo",
{value: 1, writable: false, configurable: false});
assertThrows("Object.defineProperty(proxy, 'foo', {value: 2})", TypeError);
// Step 16b: Trap returns true for overwriting a configurable property
// with a non-configurable descriptor.
target.bar = "baz";
assertThrows("Object.defineProperty(proxy, 'bar', {configurable: false})",
TypeError);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment