# we cannot handle those anyway.
macro IS_SPEC_FUNCTION(arg) = (%_ClassOf(arg) === 'Function');
+# Macro for ES6 CheckObjectCoercible
+# Will throw a TypeError of the form "[functionName] called on null or undefined".
+macro CHECK_OBJECT_COERCIBLE(arg, functionName) = if (IS_NULL_OR_UNDEFINED(arg) && !IS_UNDETECTABLE(arg)) throw MakeTypeError('called_on_null_or_undefined', [functionName]);
+
# Indices in bound function info retrieved by %BoundFunctionGetBindings(...).
const kBoundFunctionIndex = 0;
const kBoundThisIndex = 1;
getter_must_be_callable: ["Getter must be a function: ", "%0"],
setter_must_be_callable: ["Setter must be a function: ", "%0"],
value_and_accessor: ["Invalid property. A property cannot both have accessors and be writable or have a value, ", "%0"],
- proto_object_or_null: ["Object prototype may only be an Object or null"],
+ proto_object_or_null: ["Object prototype may only be an Object or null: ", "%0"],
property_desc_object: ["Property description must be an object: ", "%0"],
redefine_disallowed: ["Cannot redefine property: ", "%0"],
define_disallowed: ["Cannot define property:", "%0", ", object is not extensible."],
// ECMA-262, section 15.5.4.4
function StringCharAt(pos) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.charAt"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.charAt");
+
var result = %_StringCharAt(this, pos);
if (%_IsSmi(result)) {
result = %_StringCharAt(TO_STRING_INLINE(this), TO_INTEGER(pos));
// ECMA-262 section 15.5.4.5
function StringCharCodeAt(pos) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.charCodeAt"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.charCodeAt");
+
var result = %_StringCharCodeAt(this, pos);
if (!%_IsSmi(result)) {
result = %_StringCharCodeAt(TO_STRING_INLINE(this), TO_INTEGER(pos));
// ECMA-262, section 15.5.4.6
function StringConcat() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.concat"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.concat");
+
var len = %_ArgumentsLength();
var this_as_string = TO_STRING_INLINE(this);
if (len === 1) {
// ECMA-262 section 15.5.4.7
function StringIndexOf(pattern /* position */) { // length == 1
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.indexOf"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.indexOf");
+
var subject = TO_STRING_INLINE(this);
pattern = TO_STRING_INLINE(pattern);
var index = 0;
// ECMA-262 section 15.5.4.8
function StringLastIndexOf(pat /* position */) { // length == 1
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.lastIndexOf"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.lastIndexOf");
+
var sub = TO_STRING_INLINE(this);
var subLength = sub.length;
var pat = TO_STRING_INLINE(pat);
// This function is implementation specific. For now, we do not
// do anything locale specific.
function StringLocaleCompare(other) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.localeCompare"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.localeCompare");
+
return %StringLocaleCompare(TO_STRING_INLINE(this),
TO_STRING_INLINE(other));
}
// ECMA-262 section 15.5.4.10
function StringMatch(regexp) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.match"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.match");
+
var subject = TO_STRING_INLINE(this);
if (IS_REGEXP(regexp)) {
// Emulate RegExp.prototype.exec's side effect in step 5, even though
// ECMA-262, section 15.5.4.11
function StringReplace(search, replace) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.replace"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.replace");
+
var subject = TO_STRING_INLINE(this);
// Decision tree for dispatch
// ECMA-262 section 15.5.4.12
function StringSearch(re) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.search"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.search");
+
var regexp;
if (IS_STRING(re)) {
regexp = %_GetFromCache(STRING_TO_REGEXP_CACHE_ID, re);
// ECMA-262 section 15.5.4.13
function StringSlice(start, end) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.slice"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.slice");
+
var s = TO_STRING_INLINE(this);
var s_len = s.length;
var start_i = TO_INTEGER(start);
// ECMA-262 section 15.5.4.14
function StringSplit(separator, limit) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.split"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.split");
+
var subject = TO_STRING_INLINE(this);
limit = (IS_UNDEFINED(limit)) ? 0xffffffff : TO_UINT32(limit);
// ECMA-262 section 15.5.4.15
function StringSubstring(start, end) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.subString"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.subString");
+
var s = TO_STRING_INLINE(this);
var s_len = s.length;
// This is not a part of ECMA-262.
function StringSubstr(start, n) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.substr"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.substr");
+
var s = TO_STRING_INLINE(this);
var len;
// ECMA-262, 15.5.4.16
function StringToLowerCase() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.toLowerCase"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLowerCase");
+
return %StringToLowerCase(TO_STRING_INLINE(this));
}
// ECMA-262, 15.5.4.17
function StringToLocaleLowerCase() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.toLocaleLowerCase"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleLowerCase");
+
return %StringToLowerCase(TO_STRING_INLINE(this));
}
// ECMA-262, 15.5.4.18
function StringToUpperCase() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.toUpperCase"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.toUpperCase");
+
return %StringToUpperCase(TO_STRING_INLINE(this));
}
// ECMA-262, 15.5.4.19
function StringToLocaleUpperCase() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.toLocaleUpperCase"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleUpperCase");
+
return %StringToUpperCase(TO_STRING_INLINE(this));
}
// ES5, 15.5.4.20
function StringTrim() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.trim"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.trim");
+
return %StringTrim(TO_STRING_INLINE(this), true, true);
}
function StringTrimLeft() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.trimLeft"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.trimLeft");
+
return %StringTrim(TO_STRING_INLINE(this), true, false);
}
function StringTrimRight() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.trimRight"]);
- }
+ CHECK_OBJECT_COERCIBLE(this, "String.prototype.trimRight");
+
return %StringTrim(TO_STRING_INLINE(this), false, true);
}
return %GetPrototype(obj);
}
+// ES6 section 19.1.2.19.
+function ObjectSetPrototypeOf(obj, proto) {
+ CHECK_OBJECT_COERCIBLE(obj, "Object.setPrototypeOf");
+
+ if (proto !== null && !IS_SPEC_OBJECT(proto)) {
+ throw MakeTypeError("proto_object_or_null", [proto]);
+ }
+
+ if (IS_SPEC_OBJECT(obj)) {
+ %SetPrototype(obj, proto);
+ }
+
+ return obj;
+}
+
// ES5 section 15.2.3.3
function ObjectGetOwnPropertyDescriptor(obj, p) {
"defineProperties", ObjectDefineProperties,
"freeze", ObjectFreeze,
"getPrototypeOf", ObjectGetPrototypeOf,
+ "setPrototypeOf", ObjectSetPrototypeOf,
"getOwnPropertyDescriptor", ObjectGetOwnPropertyDescriptor,
"getOwnPropertyNames", ObjectGetOwnPropertyNames,
// getOwnPropertySymbols is added in symbol.js.
--- /dev/null
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-symbols
+
+
+function getObjects() {
+ function func() {}
+ return [
+ func,
+ new func(),
+ {x: 5},
+ /regexp/,
+ ['array'],
+ // new Error(),
+ new Date(),
+ new Number(1),
+ new Boolean(true),
+ new String('str'),
+ Object(Symbol())
+ ];
+}
+
+
+var coercibleValues = [
+ 1,
+ true,
+ 'string',
+ Symbol()
+];
+
+
+var nonCoercibleValues = [
+ undefined,
+ null
+];
+
+
+var valuesWithoutNull = coercibleValues.concat(undefined);
+
+
+function TestSetPrototypeOfCoercibleValues() {
+ for (var i = 0; i < coercibleValues.length; i++) {
+ var value = coercibleValues[i];
+ assertThrows(function() {
+ Object.getPrototypeOf(value);
+ }, TypeError);
+
+ assertEquals(Object.setPrototypeOf(value, {}), value);
+
+ assertThrows(function() {
+ Object.getPrototypeOf(value);
+ }, TypeError);
+ }
+}
+TestSetPrototypeOfCoercibleValues();
+
+
+function TestSetPrototypeOfNonCoercibleValues() {
+ for (var i = 0; i < nonCoercibleValues.length; i++) {
+ var value = nonCoercibleValues[i];
+ assertThrows(function() {
+ Object.setPrototypeOf(value, {});
+ }, TypeError);
+ }
+}
+TestSetPrototypeOfNonCoercibleValues();
+
+
+function TestSetPrototypeToNonObject(proto) {
+ var objects = getObjects();
+ for (var i = 0; i < objects.length; i++) {
+ var object = objects[i];
+ for (var j = 0; j < valuesWithoutNull.length; j++) {
+ var proto = valuesWithoutNull[j];
+ assertThrows(function() {
+ Object.setPrototypeOf(object, proto);
+ }, TypeError);
+ }
+ }
+}
+TestSetPrototypeToNonObject();
+
+
+function TestSetPrototypeOf(object, proto) {
+ assertEquals(Object.setPrototypeOf(object, proto), object);
+ assertEquals(Object.getPrototypeOf(object), proto);
+}
+
+
+function TestSetPrototypeOfForObjects() {
+ var objects1 = getObjects();
+ var objects2 = getObjects();
+ for (var i = 0; i < objects1.length; i++) {
+ for (var j = 0; j < objects2.length; j++) {
+ TestSetPrototypeOf(objects1[i], objects2[j]);
+ }
+ }
+}
+TestSetPrototypeOfForObjects();
+
+
+function TestSetPrototypeToNull() {
+ var objects = getObjects();
+ for (var i = 0; i < objects.length; i++) {
+ TestSetPrototypeOf(objects[i], null);
+ }
+}
+TestSetPrototypeToNull();
+
+
+function TestSetPrototypeOfNonExtensibleObject() {
+ var objects = getObjects();
+ var proto = {};
+ for (var i = 0; i < objects.length; i++) {
+ var object = objects[i];
+ Object.preventExtensions(object);
+ assertThrows(function() {
+ Object.setPrototypeOf(object, proto);
+ }, TypeError);
+ }
+}
+TestSetPrototypeOfNonExtensibleObject();
+
+
+function TestLookup() {
+ var object = {};
+ assertFalse('x' in object);
+ assertFalse('y' in object);
+
+ var oldProto = {
+ x: 'old x',
+ y: 'old y'
+ };
+ Object.setPrototypeOf(object, oldProto);
+ assertEquals(object.x, 'old x');
+ assertEquals(object.y, 'old y');
+
+ var newProto = {
+ x: 'new x'
+ };
+ Object.setPrototypeOf(object, newProto);
+ assertEquals(object.x, 'new x');
+ assertFalse('y' in object);
+}
+TestLookup();
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-PASS Object.create() threw exception TypeError: Object prototype may only be an Object or null.
-PASS Object.create('a string') threw exception TypeError: Object prototype may only be an Object or null.
+PASS Object.create() threw exception TypeError: Object prototype may only be an Object or null: undefined.
+PASS Object.create('a string') threw exception TypeError: Object prototype may only be an Object or null: a string.
PASS Object.create({}, 'a string') threw exception TypeError: Property description must be an object: a.
PASS Object.create(null, 'a string') threw exception TypeError: Property description must be an object: a.
PASS JSON.stringify(Object.create(null,{property:{value:'foo', enumerable:true}, property2:{value:'foo', enumerable:true}})) is '{"property":"foo","property2":"foo"}'
FAIL getSortedOwnPropertyNames(decodeURIComponent) should be length,name. Was arguments,caller,length,name.
FAIL getSortedOwnPropertyNames(encodeURI) should be length,name. Was arguments,caller,length,name.
FAIL getSortedOwnPropertyNames(encodeURIComponent) should be length,name. Was arguments,caller,length,name.
-FAIL getSortedOwnPropertyNames(Object) should be create,defineProperties,defineProperty,freeze,getOwnPropertyDescriptor,getOwnPropertyNames,getPrototypeOf,isExtensible,isFrozen,isSealed,keys,length,name,preventExtensions,prototype,seal. Was arguments,caller,create,defineProperties,defineProperty,freeze,getOwnPropertyDescriptor,getOwnPropertyNames,getPrototypeOf,is,isExtensible,isFrozen,isSealed,keys,length,name,preventExtensions,prototype,seal.
+FAIL getSortedOwnPropertyNames(Object) should be create,defineProperties,defineProperty,freeze,getOwnPropertyDescriptor,getOwnPropertyNames,getPrototypeOf,isExtensible,isFrozen,isSealed,keys,length,name,preventExtensions,prototype,seal,setPrototypeOf. Was arguments,caller,create,defineProperties,defineProperty,freeze,getOwnPropertyDescriptor,getOwnPropertyNames,getPrototypeOf,is,isExtensible,isFrozen,isSealed,keys,length,name,preventExtensions,prototype,seal,setPrototypeOf.
PASS getSortedOwnPropertyNames(Object.prototype) is ['__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', '__proto__', 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf']
FAIL getSortedOwnPropertyNames(Function) should be length,name,prototype. Was arguments,caller,length,name,prototype.
FAIL getSortedOwnPropertyNames(Function.prototype) should be apply,bind,call,constructor,length,name,toString. Was apply,arguments,bind,call,caller,constructor,length,name,toString.
"encodeURI": "['length', 'name']",
"encodeURIComponent": "['length', 'name']",
// Built-in ECMA objects
- "Object": "['create', 'defineProperties', 'defineProperty', 'freeze', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', 'getPrototypeOf', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'length', 'name', 'preventExtensions', 'prototype', 'seal']",
+ "Object": "['create', 'defineProperties', 'defineProperty', 'freeze', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', 'getPrototypeOf', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'length', 'name', 'preventExtensions', 'prototype', 'seal', 'setPrototypeOf']",
"Object.prototype": "['__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', '__proto__', 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf']",
"Function": "['length', 'name', 'prototype']",
"Function.prototype": "['apply', 'bind', 'call', 'constructor', 'length', 'name', 'toString']",