| Index: src/v8natives.js
|
| ===================================================================
|
| --- src/v8natives.js (revision 8778)
|
| +++ src/v8natives.js (working copy)
|
| @@ -162,13 +162,14 @@
|
|
|
| function SetupGlobal() {
|
| // ECMA 262 - 15.1.1.1.
|
| - %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE);
|
| + %SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY);
|
|
|
| // ECMA-262 - 15.1.1.2.
|
| - %SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE);
|
| + %SetProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE | READ_ONLY);
|
|
|
| // ECMA-262 - 15.1.1.3.
|
| - %SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE);
|
| + %SetProperty(global, "undefined", void 0,
|
| + DONT_ENUM | DONT_DELETE | READ_ONLY);
|
|
|
| // Setup non-enumerable function on the global object.
|
| InstallFunctions(global, DONT_ENUM, $Array(
|
| @@ -209,7 +210,7 @@
|
| if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
|
| return '[object Undefined]';
|
| }
|
| - if (IS_NULL(this)) return '[object Null]';
|
| + if (IS_NULL(this)) return '[object Null]';
|
| return "[object " + %_ClassOf(ToObject(this)) + "]";
|
| }
|
|
|
| @@ -232,6 +233,10 @@
|
|
|
| // 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 +254,12 @@
|
|
|
| // 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);
|
| }
|
|
|
|
|
| @@ -308,6 +318,11 @@
|
| function ObjectKeys(obj) {
|
| if (!IS_SPEC_OBJECT(obj))
|
| throw MakeTypeError("obj_ctor_property_non_object", ["keys"]);
|
| + if (%IsJSProxy(obj)) {
|
| + var handler = %GetHandler(obj);
|
| + var names = CallTrap0(handler, "keys", DerivedKeysTrap);
|
| + return ToStringArray(names);
|
| + }
|
| return %LocalKeys(obj);
|
| }
|
|
|
| @@ -576,19 +591,44 @@
|
| }
|
|
|
|
|
| +// 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 = getProperty.call(handler, p);
|
| + var descriptor = CallTrap1(obj, "getPropertyDescriptor", void 0, p);
|
| if (IS_UNDEFINED(descriptor)) return descriptor;
|
| var desc = ToCompletePropertyDescriptor(descriptor);
|
| - if (!desc.configurable) {
|
| + if (!desc.isConfigurable()) {
|
| throw MakeTypeError("proxy_prop_not_configurable",
|
| [handler, "getPropertyDescriptor", p, descriptor]);
|
| }
|
| @@ -606,9 +646,7 @@
|
| function HasProperty(obj, p) {
|
| if (%IsJSProxy(obj)) {
|
| var handler = %GetHandler(obj);
|
| - var has = handler.has;
|
| - if (IS_UNDEFINED(has)) has = DerivedHasTrap;
|
| - return ToBoolean(has.call(handler, obj, p));
|
| + return ToBoolean(CallTrap1(handler, "has", DerivedHasTrap, p));
|
| }
|
| var desc = GetProperty(obj, p);
|
| return IS_UNDEFINED(desc) ? false : true;
|
| @@ -616,11 +654,24 @@
|
|
|
|
|
| // 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 descriptor = CallTrap1(handler, "getOwnPropertyDescriptor", void 0, p);
|
| + if (IS_UNDEFINED(descriptor)) return descriptor;
|
| + var desc = ToCompletePropertyDescriptor(descriptor);
|
| + if (!desc.isConfigurable()) {
|
| + throw MakeTypeError("proxy_prop_not_configurable",
|
| + [handler, "getOwnPropertyDescriptor", p, descriptor]);
|
| + }
|
| + return desc;
|
| + }
|
| +
|
| // 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;
|
| @@ -632,14 +683,11 @@
|
| // 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 = defineProperty.call(handler, p, attributes);
|
| + var result = CallTrap2(handler, "defineProperty", void 0, p, attributes);
|
| if (!ToBoolean(result)) {
|
| if (should_throw) {
|
| - throw MakeTypeError("handler_failed", [handler, "defineProperty"]);
|
| + throw MakeTypeError("handler_returned_false",
|
| + [handler, "defineProperty"]);
|
| } else {
|
| return false;
|
| }
|
| @@ -829,7 +877,8 @@
|
| // ES5 section 15.2.3.3
|
| function ObjectGetOwnPropertyDescriptor(obj, p) {
|
| if (!IS_SPEC_OBJECT(obj))
|
| - throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyDescriptor"]);
|
| + throw MakeTypeError("obj_ctor_property_non_object",
|
| + ["getOwnPropertyDescriptor"]);
|
| var desc = GetOwnProperty(obj, p);
|
| return FromPropertyDescriptor(desc);
|
| }
|
| @@ -863,12 +912,7 @@
|
| // 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 = getOwnPropertyNames.call(handler);
|
| + var names = CallTrap0(handler, "getOwnPropertyNames", void 0);
|
| return ToStringArray(names, "getOwnPropertyNames");
|
| }
|
|
|
| @@ -995,11 +1039,26 @@
|
| }
|
|
|
|
|
| +// Harmony proxies.
|
| +function ProxyFix(obj) {
|
| + var handler = %GetHandler(obj);
|
| + var props = CallTrap0(handler, "fix", void 0);
|
| + if (IS_UNDEFINED(props)) {
|
| + throw MakeTypeError("handler_returned_undefined", [handler, "fix"]);
|
| + }
|
| + %Fix(obj);
|
| + ObjectDefineProperties(obj, props);
|
| +}
|
| +
|
| +
|
| // ES5 section 15.2.3.8.
|
| function ObjectSeal(obj) {
|
| if (!IS_SPEC_OBJECT(obj)) {
|
| throw MakeTypeError("obj_ctor_property_non_object", ["seal"]);
|
| }
|
| + if (%IsJSProxy(obj)) {
|
| + ProxyFix(obj);
|
| + }
|
| var names = ObjectGetOwnPropertyNames(obj);
|
| for (var i = 0; i < names.length; i++) {
|
| var name = names[i];
|
| @@ -1009,7 +1068,8 @@
|
| DefineOwnProperty(obj, name, desc, true);
|
| }
|
| }
|
| - return ObjectPreventExtension(obj);
|
| + %PreventExtensions(obj);
|
| + return obj;
|
| }
|
|
|
|
|
| @@ -1018,6 +1078,9 @@
|
| if (!IS_SPEC_OBJECT(obj)) {
|
| throw MakeTypeError("obj_ctor_property_non_object", ["freeze"]);
|
| }
|
| + if (%IsJSProxy(obj)) {
|
| + ProxyFix(obj);
|
| + }
|
| var names = ObjectGetOwnPropertyNames(obj);
|
| for (var i = 0; i < names.length; i++) {
|
| var name = names[i];
|
| @@ -1028,7 +1091,8 @@
|
| DefineOwnProperty(obj, name, desc, true);
|
| }
|
| }
|
| - return ObjectPreventExtension(obj);
|
| + %PreventExtensions(obj);
|
| + return obj;
|
| }
|
|
|
|
|
| @@ -1037,6 +1101,9 @@
|
| if (!IS_SPEC_OBJECT(obj)) {
|
| throw MakeTypeError("obj_ctor_property_non_object", ["preventExtension"]);
|
| }
|
| + if (%IsJSProxy(obj)) {
|
| + ProxyFix(obj);
|
| + }
|
| %PreventExtensions(obj);
|
| return obj;
|
| }
|
| @@ -1047,6 +1114,9 @@
|
| if (!IS_SPEC_OBJECT(obj)) {
|
| throw MakeTypeError("obj_ctor_property_non_object", ["isSealed"]);
|
| }
|
| + if (%IsJSProxy(obj)) {
|
| + return false;
|
| + }
|
| var names = ObjectGetOwnPropertyNames(obj);
|
| for (var i = 0; i < names.length; i++) {
|
| var name = names[i];
|
| @@ -1065,6 +1135,9 @@
|
| if (!IS_SPEC_OBJECT(obj)) {
|
| throw MakeTypeError("obj_ctor_property_non_object", ["isFrozen"]);
|
| }
|
| + if (%IsJSProxy(obj)) {
|
| + return false;
|
| + }
|
| var names = ObjectGetOwnPropertyNames(obj);
|
| for (var i = 0; i < names.length; i++) {
|
| var name = names[i];
|
| @@ -1084,6 +1157,9 @@
|
| if (!IS_SPEC_OBJECT(obj)) {
|
| throw MakeTypeError("obj_ctor_property_non_object", ["isExtensible"]);
|
| }
|
| + if (%IsJSProxy(obj)) {
|
| + return true;
|
| + }
|
| return %IsExtensible(obj);
|
| }
|
|
|
|
|