Commit 3f5bc11c authored by rossberg@chromium.org's avatar rossberg@chromium.org

Implement Object.prototype.{hasOwnProperty, propertyIsEnumerable} for proxies.

Refactor trap invocation.
Test other Object.prototype functionality for proxies.

R=ager@chromium.org
BUG=v8:1543
TEST=

Review URL: http://codereview.chromium.org/7436004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8707 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5fba7689
......@@ -195,6 +195,7 @@ function FormatMessage(message) {
non_extensible_proto: ["%0", " is not extensible"],
handler_non_object: ["Proxy.", "%0", " called with non-object as handler"],
handler_trap_missing: ["Proxy handler ", "%0", " has no '", "%1", "' trap"],
handler_trap_must_be_callable: ["Proxy handler ", "%0", " has non-callable '", "%1", "' trap"],
handler_returned_false: ["Proxy handler ", "%0", " returned false for '", "%1", "' trap"],
handler_returned_undefined: ["Proxy handler ", "%0", " returned undefined for '", "%1", "' trap"],
proxy_prop_not_configurable: ["Trap ", "%1", " of proxy handler ", "%0", " returned non-configurable descriptor for property ", "%2"],
......
......@@ -136,6 +136,10 @@ function DerivedHasTrap(name) {
return !!this.getPropertyDescriptor(name)
}
function DerivedHasOwnTrap(name) {
return !!this.getOwnPropertyDescriptor(name)
}
function DerivedKeysTrap() {
var names = this.getOwnPropertyNames()
var enumerableNames = []
......
......@@ -232,6 +232,10 @@ function ObjectValueOf() {
// ECMA-262 - 15.2.4.5
function ObjectHasOwnProperty(V) {
if (%IsJSProxy(this)) {
var handler = %GetHandler(this);
return CallTrap1(handler, "hasOwn", DerivedHasOwnTrap, TO_STRING_INLINE(V));
}
return %HasLocalProperty(TO_OBJECT_INLINE(this), TO_STRING_INLINE(V));
}
......@@ -249,7 +253,12 @@ function ObjectIsPrototypeOf(V) {
// ECMA-262 - 15.2.4.6
function ObjectPropertyIsEnumerable(V) {
return %IsPropertyEnumerable(ToObject(this), ToString(V));
var P = ToString(V);
if (%IsJSProxy(this)) {
var desc = GetOwnProperty(this, P);
return IS_UNDEFINED(desc) ? false : desc.isEnumerable();
}
return %IsPropertyEnumerable(ToObject(this), P);
}
......@@ -310,9 +319,7 @@ function ObjectKeys(obj) {
throw MakeTypeError("obj_ctor_property_non_object", ["keys"]);
if (%IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var keys = handler.keys;
if (IS_UNDEFINED(keys)) keys = DerivedKeysTrap;
var names = %_CallFunction(handler, keys);
var names = CallTrap0(handler, "keys", DerivedKeysTrap);
return ToStringArray(names);
}
return %LocalKeys(obj);
......@@ -583,16 +590,41 @@ function ConvertDescriptorArrayToDescriptor(desc_array) {
}
// For Harmony proxies.
function GetTrap(handler, name, defaultTrap) {
var trap = handler[name];
if (IS_UNDEFINED(trap)) {
if (IS_UNDEFINED(defaultTrap)) {
throw MakeTypeError("handler_trap_missing", [handler, name]);
}
trap = defaultTrap;
} else if (!IS_FUNCTION(trap)) {
throw MakeTypeError("handler_trap_must_be_callable", [handler, name]);
}
return trap;
}
function CallTrap0(handler, name, defaultTrap) {
return %_CallFunction(handler, GetTrap(handler, name, defaultTrap));
}
function CallTrap1(handler, name, defaultTrap, x) {
return %_CallFunction(handler, x, GetTrap(handler, name, defaultTrap));
}
function CallTrap2(handler, name, defaultTrap, x, y) {
return %_CallFunction(handler, x, y, GetTrap(handler, name, defaultTrap));
}
// ES5 section 8.12.2.
function GetProperty(obj, p) {
if (%IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var getProperty = handler.getPropertyDescriptor;
if (IS_UNDEFINED(getProperty)) {
throw MakeTypeError("handler_trap_missing",
[handler, "getPropertyDescriptor"]);
}
var descriptor = %_CallFunction(handler, p, getProperty);
var descriptor = CallTrap1(obj, "getPropertyDescriptor", void 0, p);
if (IS_UNDEFINED(descriptor)) return descriptor;
var desc = ToCompletePropertyDescriptor(descriptor);
if (!desc.isConfigurable()) {
......@@ -613,9 +645,7 @@ function GetProperty(obj, p) {
function HasProperty(obj, p) {
if (%IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var has = handler.has;
if (IS_UNDEFINED(has)) has = DerivedHasTrap;
return ToBoolean(%_CallFunction(handler, obj, p, has));
return ToBoolean(CallTrap1(handler, "has", DerivedHasTrap, p));
}
var desc = GetProperty(obj, p);
return IS_UNDEFINED(desc) ? false : true;
......@@ -623,15 +653,11 @@ function HasProperty(obj, p) {
// ES5 section 8.12.1.
function GetOwnProperty(obj, p) {
function GetOwnProperty(obj, v) {
var p = ToString(v);
if (%IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var getOwnProperty = handler.getOwnPropertyDescriptor;
if (IS_UNDEFINED(getOwnProperty)) {
throw MakeTypeError("handler_trap_missing",
[handler, "getOwnPropertyDescriptor"]);
}
var descriptor = %_CallFunction(handler, p, getOwnProperty);
var descriptor = CallTrap1(handler, "getOwnPropertyDescriptor", void 0, p);
if (IS_UNDEFINED(descriptor)) return descriptor;
var desc = ToCompletePropertyDescriptor(descriptor);
if (!desc.isConfigurable()) {
......@@ -644,7 +670,7 @@ function GetOwnProperty(obj, p) {
// GetOwnProperty returns an array indexed by the constants
// defined in macros.py.
// If p is not a property on obj undefined is returned.
var props = %GetOwnProperty(ToObject(obj), ToString(p));
var props = %GetOwnProperty(ToObject(obj), ToString(v));
// A false value here means that access checks failed.
if (props === false) return void 0;
......@@ -656,11 +682,7 @@ function GetOwnProperty(obj, p) {
// Harmony proxies.
function DefineProxyProperty(obj, p, attributes, should_throw) {
var handler = %GetHandler(obj);
var defineProperty = handler.defineProperty;
if (IS_UNDEFINED(defineProperty)) {
throw MakeTypeError("handler_trap_missing", [handler, "defineProperty"]);
}
var result = %_CallFunction(handler, p, attributes, defineProperty);
var result = CallTrap2(handler, "defineProperty", void 0, p, attributes);
if (!ToBoolean(result)) {
if (should_throw) {
throw MakeTypeError("handler_returned_false",
......@@ -889,12 +911,7 @@ function ObjectGetOwnPropertyNames(obj) {
// Special handling for proxies.
if (%IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var getOwnPropertyNames = handler.getOwnPropertyNames;
if (IS_UNDEFINED(getOwnPropertyNames)) {
throw MakeTypeError("handler_trap_missing",
[handler, "getOwnPropertyNames"]);
}
var names = %_CallFunction(handler, getOwnPropertyNames);
var names = CallTrap0(handler, "getOwnPropertyNames", void 0);
return ToStringArray(names, "getOwnPropertyNames");
}
......@@ -1024,11 +1041,7 @@ function ObjectDefineProperties(obj, properties) {
// Harmony proxies.
function ProxyFix(obj) {
var handler = %GetHandler(obj);
var fix = handler.fix;
if (IS_UNDEFINED(fix)) {
throw MakeTypeError("handler_trap_missing", [handler, "fix"]);
}
var props = %_CallFunction(handler, fix);
var props = CallTrap0(handler, "fix", void 0);
if (IS_UNDEFINED(props)) {
throw MakeTypeError("handler_returned_undefined", [handler, "fix"]);
}
......
This diff is collapsed.
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