Index: src/js/v8natives.js |
diff --git a/src/js/v8natives.js b/src/js/v8natives.js |
index dc3c43b8eca5440adf97670f7cf68561c441710b..be7271b1f061dcf61b7b04e815cebc327edd7b58 100644 |
--- a/src/js/v8natives.js |
+++ b/src/js/v8natives.js |
@@ -152,11 +152,8 @@ function ObjectDefineGetter(name, fun) { |
if (!IS_CALLABLE(fun)) { |
throw MakeTypeError(kObjectGetterExpectingFunction); |
} |
- var desc = new PropertyDescriptor(); |
- desc.setGet(fun); |
- desc.setEnumerable(true); |
- desc.setConfigurable(true); |
- DefineOwnProperty(TO_OBJECT(receiver), TO_NAME(name), desc, false); |
+ var desc = {get: fun, enumerable: true, configurable: true}; |
+ %reflect_define_property(receiver, name, desc); |
} |
@@ -177,11 +174,8 @@ function ObjectDefineSetter(name, fun) { |
if (!IS_CALLABLE(fun)) { |
throw MakeTypeError(kObjectSetterExpectingFunction); |
} |
- var desc = new PropertyDescriptor(); |
- desc.setSet(fun); |
- desc.setEnumerable(true); |
- desc.setConfigurable(true); |
- DefineOwnProperty(TO_OBJECT(receiver), TO_NAME(name), desc, false); |
+ var desc = {set: fun, enumerable: true, configurable: true}; |
+ %reflect_define_property(receiver, name, desc); |
} |
@@ -194,296 +188,6 @@ function ObjectLookupSetter(name) { |
} |
-// ES6 6.2.4.1 |
-function IsAccessorDescriptor(desc) { |
- if (IS_UNDEFINED(desc)) return false; |
- return desc.hasGetter() || desc.hasSetter(); |
-} |
- |
- |
-// ES6 6.2.4.2 |
-function IsDataDescriptor(desc) { |
- if (IS_UNDEFINED(desc)) return false; |
- return desc.hasValue() || desc.hasWritable(); |
-} |
- |
- |
-// ES6 6.2.4.3 |
-function IsGenericDescriptor(desc) { |
- if (IS_UNDEFINED(desc)) return false; |
- return !(IsAccessorDescriptor(desc) || IsDataDescriptor(desc)); |
-} |
- |
- |
-function IsInconsistentDescriptor(desc) { |
- return IsAccessorDescriptor(desc) && IsDataDescriptor(desc); |
-} |
- |
- |
-// Harmony Proxies |
-function FromGenericPropertyDescriptor(desc) { |
- if (IS_UNDEFINED(desc)) return desc; |
- var obj = new GlobalObject(); |
- |
- if (desc.hasValue()) { |
- %AddNamedProperty(obj, "value", desc.getValue(), NONE); |
- } |
- if (desc.hasWritable()) { |
- %AddNamedProperty(obj, "writable", desc.isWritable(), NONE); |
- } |
- if (desc.hasGetter()) { |
- %AddNamedProperty(obj, "get", desc.getGet(), NONE); |
- } |
- if (desc.hasSetter()) { |
- %AddNamedProperty(obj, "set", desc.getSet(), NONE); |
- } |
- if (desc.hasEnumerable()) { |
- %AddNamedProperty(obj, "enumerable", desc.isEnumerable(), NONE); |
- } |
- if (desc.hasConfigurable()) { |
- %AddNamedProperty(obj, "configurable", desc.isConfigurable(), NONE); |
- } |
- return obj; |
-} |
- |
- |
-// ES6 6.2.4.5 |
-function ToPropertyDescriptor(obj) { |
- if (!IS_RECEIVER(obj)) throw MakeTypeError(kPropertyDescObject, obj); |
- |
- var desc = new PropertyDescriptor(); |
- |
- if ("enumerable" in obj) { |
- desc.setEnumerable(TO_BOOLEAN(obj.enumerable)); |
- } |
- |
- if ("configurable" in obj) { |
- desc.setConfigurable(TO_BOOLEAN(obj.configurable)); |
- } |
- |
- if ("value" in obj) { |
- desc.setValue(obj.value); |
- } |
- |
- if ("writable" in obj) { |
- desc.setWritable(TO_BOOLEAN(obj.writable)); |
- } |
- |
- if ("get" in obj) { |
- var get = obj.get; |
- if (!IS_UNDEFINED(get) && !IS_CALLABLE(get)) { |
- throw MakeTypeError(kObjectGetterCallable, get); |
- } |
- desc.setGet(get); |
- } |
- |
- if ("set" in obj) { |
- var set = obj.set; |
- if (!IS_UNDEFINED(set) && !IS_CALLABLE(set)) { |
- throw MakeTypeError(kObjectSetterCallable, set); |
- } |
- desc.setSet(set); |
- } |
- |
- if (IsInconsistentDescriptor(desc)) { |
- throw MakeTypeError(kValueAndAccessor, obj); |
- } |
- return desc; |
-} |
- |
-// TODO(cbruni): remove once callers have been removed |
-function ToCompletePropertyDescriptor(obj) { |
- var desc = ToPropertyDescriptor(obj); |
- if (IsGenericDescriptor(desc) || IsDataDescriptor(desc)) { |
- if (!desc.hasValue()) desc.setValue(UNDEFINED); |
- if (!desc.hasWritable()) desc.setWritable(false); |
- } else { |
- // Is accessor descriptor. |
- if (!desc.hasGetter()) desc.setGet(UNDEFINED); |
- if (!desc.hasSetter()) desc.setSet(UNDEFINED); |
- } |
- if (!desc.hasEnumerable()) desc.setEnumerable(false); |
- if (!desc.hasConfigurable()) desc.setConfigurable(false); |
- return desc; |
-} |
- |
- |
-function PropertyDescriptor() { |
- // Initialize here so they are all in-object and have the same map. |
- // Default values from ES5 8.6.1. |
- this.value_ = UNDEFINED; |
- this.hasValue_ = false; |
- this.writable_ = false; |
- this.hasWritable_ = false; |
- this.enumerable_ = false; |
- this.hasEnumerable_ = false; |
- this.configurable_ = false; |
- this.hasConfigurable_ = false; |
- this.get_ = UNDEFINED; |
- this.hasGetter_ = false; |
- this.set_ = UNDEFINED; |
- this.hasSetter_ = false; |
-} |
- |
-utils.SetUpLockedPrototype(PropertyDescriptor, [ |
- "value_", |
- "hasValue_", |
- "writable_", |
- "hasWritable_", |
- "enumerable_", |
- "hasEnumerable_", |
- "configurable_", |
- "hasConfigurable_", |
- "get_", |
- "hasGetter_", |
- "set_", |
- "hasSetter_" |
-], [ |
- "toString", function PropertyDescriptor_ToString() { |
- return "[object PropertyDescriptor]"; |
- }, |
- "setValue", function PropertyDescriptor_SetValue(value) { |
- this.value_ = value; |
- this.hasValue_ = true; |
- }, |
- "getValue", function PropertyDescriptor_GetValue() { |
- return this.value_; |
- }, |
- "hasValue", function PropertyDescriptor_HasValue() { |
- return this.hasValue_; |
- }, |
- "setEnumerable", function PropertyDescriptor_SetEnumerable(enumerable) { |
- this.enumerable_ = enumerable; |
- this.hasEnumerable_ = true; |
- }, |
- "isEnumerable", function PropertyDescriptor_IsEnumerable() { |
- return this.enumerable_; |
- }, |
- "hasEnumerable", function PropertyDescriptor_HasEnumerable() { |
- return this.hasEnumerable_; |
- }, |
- "setWritable", function PropertyDescriptor_SetWritable(writable) { |
- this.writable_ = writable; |
- this.hasWritable_ = true; |
- }, |
- "isWritable", function PropertyDescriptor_IsWritable() { |
- return this.writable_; |
- }, |
- "hasWritable", function PropertyDescriptor_HasWritable() { |
- return this.hasWritable_; |
- }, |
- "setConfigurable", |
- function PropertyDescriptor_SetConfigurable(configurable) { |
- this.configurable_ = configurable; |
- this.hasConfigurable_ = true; |
- }, |
- "hasConfigurable", function PropertyDescriptor_HasConfigurable() { |
- return this.hasConfigurable_; |
- }, |
- "isConfigurable", function PropertyDescriptor_IsConfigurable() { |
- return this.configurable_; |
- }, |
- "setGet", function PropertyDescriptor_SetGetter(get) { |
- this.get_ = get; |
- this.hasGetter_ = true; |
- }, |
- "getGet", function PropertyDescriptor_GetGetter() { |
- return this.get_; |
- }, |
- "hasGetter", function PropertyDescriptor_HasGetter() { |
- return this.hasGetter_; |
- }, |
- "setSet", function PropertyDescriptor_SetSetter(set) { |
- this.set_ = set; |
- this.hasSetter_ = true; |
- }, |
- "getSet", function PropertyDescriptor_GetSetter() { |
- return this.set_; |
- }, |
- "hasSetter", function PropertyDescriptor_HasSetter() { |
- return this.hasSetter_; |
- } |
-]); |
- |
- |
-// Converts an array returned from Runtime_GetOwnProperty to an actual |
-// property descriptor. For a description of the array layout please |
-// see the runtime.cc file. |
-function ConvertDescriptorArrayToDescriptor(desc_array) { |
- if (IS_UNDEFINED(desc_array)) { |
- return UNDEFINED; |
- } |
- |
- var desc = new PropertyDescriptor(); |
- // This is an accessor. |
- if (desc_array[IS_ACCESSOR_INDEX]) { |
- desc.setGet(desc_array[GETTER_INDEX]); |
- desc.setSet(desc_array[SETTER_INDEX]); |
- } else { |
- desc.setValue(desc_array[VALUE_INDEX]); |
- desc.setWritable(desc_array[WRITABLE_INDEX]); |
- } |
- desc.setEnumerable(desc_array[ENUMERABLE_INDEX]); |
- desc.setConfigurable(desc_array[CONFIGURABLE_INDEX]); |
- |
- return desc; |
-} |
- |
- |
-// For Harmony proxies. |
-function GetTrap(handler, name, defaultTrap) { |
- var trap = handler[name]; |
- if (IS_UNDEFINED(trap)) { |
- if (IS_UNDEFINED(defaultTrap)) { |
- throw MakeTypeError(kIllegalInvocation); |
- } |
- trap = defaultTrap; |
- } else if (!IS_CALLABLE(trap)) { |
- throw MakeTypeError(kIllegalInvocation); |
- } |
- return trap; |
-} |
- |
- |
-function CallTrap1(handler, name, defaultTrap, x) { |
- return %_Call(GetTrap(handler, name, defaultTrap), handler, x); |
-} |
- |
- |
-function CallTrap2(handler, name, defaultTrap, x, y) { |
- return %_Call(GetTrap(handler, name, defaultTrap), handler, x, y); |
-} |
- |
- |
-// ES5 section 8.12.1. |
-// TODO(jkummerow): Deprecated. Migrate all callers to |
-// ObjectGetOwnPropertyDescriptor and delete this. |
-function GetOwnPropertyJS(obj, v) { |
- var p = TO_NAME(v); |
- if (IS_PROXY(obj)) { |
- // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
- if (IS_SYMBOL(v)) return UNDEFINED; |
- |
- var handler = %JSProxyGetHandler(obj); |
- var descriptor = CallTrap1( |
- handler, "getOwnPropertyDescriptor", UNDEFINED, p); |
- if (IS_UNDEFINED(descriptor)) return descriptor; |
- var desc = ToCompletePropertyDescriptor(descriptor); |
- if (!desc.isConfigurable()) { |
- throw MakeTypeError(kIllegalInvocation); |
- } |
- 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_Legacy(TO_OBJECT(obj), p); |
- |
- return ConvertDescriptorArrayToDescriptor(props); |
-} |
- |
- |
// ES6 7.3.9 |
function GetMethod(obj, p) { |
var func = obj[p]; |
@@ -493,234 +197,6 @@ function GetMethod(obj, p) { |
} |
-// Harmony proxies. |
-function DefineProxyProperty(obj, p, attributes, should_throw) { |
- // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
- if (IS_SYMBOL(p)) return false; |
- |
- var handler = %JSProxyGetHandler(obj); |
- var result = CallTrap2(handler, "defineProperty", UNDEFINED, p, attributes); |
- if (!result) { |
- if (should_throw) { |
- throw MakeTypeError(kIllegalInvocation); |
- } else { |
- return false; |
- } |
- } |
- return true; |
-} |
- |
- |
-// ES6 9.1.6 [[DefineOwnProperty]](P, Desc) |
-function DefineObjectProperty(obj, p, desc, should_throw) { |
- var current_array = %GetOwnProperty_Legacy(obj, TO_NAME(p)); |
- var current = ConvertDescriptorArrayToDescriptor(current_array); |
- var extensible = %object_is_extensible(obj); |
- |
- if (IS_UNDEFINED(current) && !extensible) { |
- if (should_throw) { |
- throw MakeTypeError(kDefineDisallowed, p); |
- } else { |
- return false; |
- } |
- } |
- |
- if (!IS_UNDEFINED(current)) { |
- if ((IsGenericDescriptor(desc) || |
- IsDataDescriptor(desc) == IsDataDescriptor(current)) && |
- (!desc.hasEnumerable() || |
- %SameValue(desc.isEnumerable(), current.isEnumerable())) && |
- (!desc.hasConfigurable() || |
- %SameValue(desc.isConfigurable(), current.isConfigurable())) && |
- (!desc.hasWritable() || |
- %SameValue(desc.isWritable(), current.isWritable())) && |
- (!desc.hasValue() || |
- %SameValue(desc.getValue(), current.getValue())) && |
- (!desc.hasGetter() || |
- %SameValue(desc.getGet(), current.getGet())) && |
- (!desc.hasSetter() || |
- %SameValue(desc.getSet(), current.getSet()))) { |
- return true; |
- } |
- if (!current.isConfigurable()) { |
- // Step 7 |
- if (desc.isConfigurable() || |
- (desc.hasEnumerable() && |
- desc.isEnumerable() != current.isEnumerable())) { |
- if (should_throw) { |
- throw MakeTypeError(kRedefineDisallowed, p); |
- } else { |
- return false; |
- } |
- } |
- // Step 8 |
- if (!IsGenericDescriptor(desc)) { |
- // Step 9a |
- if (IsDataDescriptor(current) != IsDataDescriptor(desc)) { |
- if (should_throw) { |
- throw MakeTypeError(kRedefineDisallowed, p); |
- } else { |
- return false; |
- } |
- } |
- // Step 10a |
- if (IsDataDescriptor(current) && IsDataDescriptor(desc)) { |
- var currentIsWritable = current.isWritable(); |
- if (currentIsWritable != desc.isWritable()) { |
- if (!currentIsWritable) { |
- if (should_throw) { |
- throw MakeTypeError(kRedefineDisallowed, p); |
- } else { |
- return false; |
- } |
- } |
- } |
- if (!currentIsWritable && desc.hasValue() && |
- !%SameValue(desc.getValue(), current.getValue())) { |
- if (should_throw) { |
- throw MakeTypeError(kRedefineDisallowed, p); |
- } else { |
- return false; |
- } |
- } |
- } |
- // Step 11 |
- if (IsAccessorDescriptor(desc) && IsAccessorDescriptor(current)) { |
- if (desc.hasSetter() && |
- !%SameValue(desc.getSet(), current.getSet())) { |
- if (should_throw) { |
- throw MakeTypeError(kRedefineDisallowed, p); |
- } else { |
- return false; |
- } |
- } |
- if (desc.hasGetter() && !%SameValue(desc.getGet(),current.getGet())) { |
- if (should_throw) { |
- throw MakeTypeError(kRedefineDisallowed, p); |
- } else { |
- return false; |
- } |
- } |
- } |
- } |
- } |
- } |
- |
- // Send flags - enumerable and configurable are common - writable is |
- // only send to the data descriptor. |
- // Take special care if enumerable and configurable is not defined on |
- // desc (we need to preserve the existing values from current). |
- var flag = NONE; |
- if (desc.hasEnumerable()) { |
- flag |= desc.isEnumerable() ? 0 : DONT_ENUM; |
- } else if (!IS_UNDEFINED(current)) { |
- flag |= current.isEnumerable() ? 0 : DONT_ENUM; |
- } else { |
- flag |= DONT_ENUM; |
- } |
- |
- if (desc.hasConfigurable()) { |
- flag |= desc.isConfigurable() ? 0 : DONT_DELETE; |
- } else if (!IS_UNDEFINED(current)) { |
- flag |= current.isConfigurable() ? 0 : DONT_DELETE; |
- } else |
- flag |= DONT_DELETE; |
- |
- if (IsDataDescriptor(desc) || |
- (IsGenericDescriptor(desc) && |
- (IS_UNDEFINED(current) || IsDataDescriptor(current)))) { |
- // There are 3 cases that lead here: |
- // Step 4a - defining a new data property. |
- // Steps 9b & 12 - replacing an existing accessor property with a data |
- // property. |
- // Step 12 - updating an existing data property with a data or generic |
- // descriptor. |
- |
- if (desc.hasWritable()) { |
- flag |= desc.isWritable() ? 0 : READ_ONLY; |
- } else if (!IS_UNDEFINED(current)) { |
- flag |= current.isWritable() ? 0 : READ_ONLY; |
- } else { |
- flag |= READ_ONLY; |
- } |
- |
- var value = UNDEFINED; // Default value is undefined. |
- if (desc.hasValue()) { |
- value = desc.getValue(); |
- } else if (!IS_UNDEFINED(current) && IsDataDescriptor(current)) { |
- value = current.getValue(); |
- } |
- |
- %DefineDataPropertyUnchecked(obj, p, value, flag); |
- } else { |
- // There are 3 cases that lead here: |
- // Step 4b - defining a new accessor property. |
- // Steps 9c & 12 - replacing an existing data property with an accessor |
- // property. |
- // Step 12 - updating an existing accessor property with an accessor |
- // descriptor. |
- var getter = null; |
- if (desc.hasGetter()) { |
- getter = desc.getGet(); |
- } else if (IsAccessorDescriptor(current) && current.hasGetter()) { |
- getter = current.getGet(); |
- } |
- var setter = null; |
- if (desc.hasSetter()) { |
- setter = desc.getSet(); |
- } else if (IsAccessorDescriptor(current) && current.hasSetter()) { |
- setter = current.getSet(); |
- } |
- %DefineAccessorPropertyUnchecked(obj, p, getter, setter, flag); |
- } |
- return true; |
-} |
- |
- |
-// ES5 section 15.4.5.1. |
-function DefineArrayProperty(obj, p, desc, should_throw) { |
- // Step 3 - Special handling for array index. |
- if (!IS_SYMBOL(p)) { |
- var index = TO_UINT32(p); |
- if (TO_STRING(index) == p && index != 4294967295) { |
- var length = obj.length; |
- var length_desc = GetOwnPropertyJS(obj, "length"); |
- if ((index >= length && !length_desc.isWritable()) || |
- !DefineObjectProperty(obj, p, desc, true)) { |
- if (should_throw) { |
- throw MakeTypeError(kDefineDisallowed, p); |
- } else { |
- return false; |
- } |
- } |
- if (index >= length) { |
- obj.length = index + 1; |
- } |
- return true; |
- } |
- } |
- |
- // Step 5 - Fallback to default implementation. |
- return DefineObjectProperty(obj, p, desc, should_throw); |
-} |
- |
- |
-// ES5 section 8.12.9, ES5 section 15.4.5.1 and Harmony proxies. |
-function DefineOwnProperty(obj, p, desc, should_throw) { |
- if (IS_PROXY(obj)) { |
- // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
- if (IS_SYMBOL(p)) return false; |
- |
- var attributes = FromGenericPropertyDescriptor(desc); |
- return DefineProxyProperty(obj, p, attributes, should_throw); |
- } else if (IS_ARRAY(obj)) { |
- return DefineArrayProperty(obj, p, desc, should_throw); |
- } else { |
- return DefineObjectProperty(obj, p, desc, should_throw); |
- } |
-} |
- |
- |
// ES6 section 19.1.2.18. |
function ObjectSetPrototypeOf(obj, proto) { |
CHECK_OBJECT_COERCIBLE(obj, "Object.setPrototypeOf"); |
@@ -784,8 +260,8 @@ utils.InstallFunctions(GlobalObject.prototype, DONT_ENUM, [ |
"__defineSetter__", ObjectDefineSetter, |
"__lookupSetter__", ObjectLookupSetter |
]); |
-utils.InstallGetterSetter(GlobalObject.prototype, "__proto__", ObjectGetProto, |
- ObjectSetProto); |
+utils.InstallGetterSetter( |
+ GlobalObject.prototype, "__proto__", ObjectGetProto, ObjectSetProto); |
// Set up non-enumerable functions in the Object object. |
utils.InstallFunctions(GlobalObject, DONT_ENUM, [ |