Index: src/v8natives.js |
diff --git a/src/v8natives.js b/src/v8natives.js |
index 9843635866323d5c5495edf0ffbdb9d12400f01e..76c327c021b13ac76ce23b78fc8f15df6d1ad8d5 100644 |
--- a/src/v8natives.js |
+++ b/src/v8natives.js |
@@ -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"]); |
} |