mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 885788 - Implement Object.setPrototypeOf; r=jorendorff
This commit is contained in:
parent
e6d7a3c3dd
commit
b8b45d5fb2
@ -539,6 +539,60 @@ obj_getPrototypeOf(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
obj_setPrototypeOf(JSContext *cx, unsigned argc, Value *vp)
|
||||||
|
{
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
|
||||||
|
RootedObject setPrototypeOf(cx, &args.callee());
|
||||||
|
if (!GlobalObject::warnOnceAboutPrototypeMutation(cx, setPrototypeOf))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (args.length() < 2) {
|
||||||
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
|
||||||
|
"Object.setPrototypeOf", "1", "");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 1-2. */
|
||||||
|
if (args[0].isNullOrUndefined()) {
|
||||||
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CONVERT_TO,
|
||||||
|
args[0].isNull() ? "null" : "undefined", "object");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 3. */
|
||||||
|
if (!args[1].isObjectOrNull()) {
|
||||||
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
|
||||||
|
"Object.setPrototypeOf", "an object or null", InformalValueTypeName(args[1]));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 4. */
|
||||||
|
if (!args[0].isObject()) {
|
||||||
|
args.rval().set(args[0]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 5-6. */
|
||||||
|
RootedObject obj(cx, &args[0].toObject());
|
||||||
|
RootedObject newProto(cx, args[1].toObjectOrNull());
|
||||||
|
|
||||||
|
bool success;
|
||||||
|
if (!JSObject::setProto(cx, obj, newProto, &success))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Step 7. */
|
||||||
|
if (!success) {
|
||||||
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_OBJECT_NOT_EXTENSIBLE, "object");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 8. */
|
||||||
|
args.rval().set(args[0]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#if JS_HAS_OBJ_WATCHPOINT
|
#if JS_HAS_OBJ_WATCHPOINT
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -1014,6 +1068,7 @@ const JSFunctionSpec js::object_methods[] = {
|
|||||||
|
|
||||||
const JSFunctionSpec js::object_static_methods[] = {
|
const JSFunctionSpec js::object_static_methods[] = {
|
||||||
JS_FN("getPrototypeOf", obj_getPrototypeOf, 1,0),
|
JS_FN("getPrototypeOf", obj_getPrototypeOf, 1,0),
|
||||||
|
JS_FN("setPrototypeOf", obj_setPrototypeOf, 2,0),
|
||||||
JS_FN("getOwnPropertyDescriptor", obj_getOwnPropertyDescriptor,2,0),
|
JS_FN("getOwnPropertyDescriptor", obj_getOwnPropertyDescriptor,2,0),
|
||||||
JS_FN("keys", obj_keys, 1,0),
|
JS_FN("keys", obj_keys, 1,0),
|
||||||
JS_FN("is", obj_is, 2,0),
|
JS_FN("is", obj_is, 2,0),
|
||||||
|
102
js/src/jit-test/tests/basic/setPrototypeOf.js
Normal file
102
js/src/jit-test/tests/basic/setPrototypeOf.js
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
load(libdir + 'asserts.js');
|
||||||
|
|
||||||
|
function getObjects() {
|
||||||
|
function func(){}
|
||||||
|
return [func,
|
||||||
|
new func(),
|
||||||
|
{x: 5},
|
||||||
|
/regexp/,
|
||||||
|
[1, 2, 3],
|
||||||
|
new Date(),
|
||||||
|
new Number(1),
|
||||||
|
new Boolean(true),
|
||||||
|
new String('str'),
|
||||||
|
Object.create(null)];
|
||||||
|
}
|
||||||
|
|
||||||
|
var coercibleValues = [1,
|
||||||
|
true,
|
||||||
|
'string'];
|
||||||
|
|
||||||
|
var nonCoercibleValues = [undefined,
|
||||||
|
null];
|
||||||
|
|
||||||
|
var valuesWithoutNull = coercibleValues.concat(undefined);
|
||||||
|
|
||||||
|
function TestSetPrototypeOf(object, proto) {
|
||||||
|
assertEq(Object.setPrototypeOf(object, proto), object);
|
||||||
|
assertEq(Object.getPrototypeOf(object), proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if Object.setPrototypeOf works with coercible values
|
||||||
|
for(var value of coercibleValues) {
|
||||||
|
assertEq(Object.setPrototypeOf(value, {}), value);
|
||||||
|
|
||||||
|
assertThrowsInstanceOf(() => Object.getPrototypeOf(value),
|
||||||
|
TypeError, "Coercible values should not have a prototype");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if Object.setPrototypeOf fails on non-coercible values
|
||||||
|
for (var value of nonCoercibleValues) {
|
||||||
|
assertThrowsInstanceOf(() => Object.setPrototypeOf(value, {}),
|
||||||
|
TypeError, "Object.setPrototypeOf shouldn't work on non-coercible values");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if Object.setPrototypeOf works when prototype is set to non-objects
|
||||||
|
var objects = getObjects();
|
||||||
|
for (var object of objects) {
|
||||||
|
for (var proto of valuesWithoutNull) {
|
||||||
|
assertThrowsInstanceOf(() => Object.setPrototypeOf(object, proto),
|
||||||
|
TypeError, "Object.setPrototypeOf fails when the prototype is set to non-objects");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if Object.setPrototypeOf works when prototype is set to objects
|
||||||
|
var objects1 = getObjects();
|
||||||
|
var objects2 = getObjects();
|
||||||
|
for (var object1 of objects1) {
|
||||||
|
for (var object2 of objects2) {
|
||||||
|
TestSetPrototypeOf(object1, object2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if Object.setPrototypeOf works when prototype is set to null
|
||||||
|
objects = getObjects();
|
||||||
|
for (var object of objects) {
|
||||||
|
TestSetPrototypeOf(object, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if Object.setPrototypeOf fails when object is not extensible
|
||||||
|
var objects = getObjects();
|
||||||
|
var proto = {};
|
||||||
|
for (var object of objects) {
|
||||||
|
Object.preventExtensions(object);
|
||||||
|
assertThrowsInstanceOf(() => Object.setPrototypeOf(object, proto),
|
||||||
|
TypeError, "Object.setPrototypeOf should fail when the object is not extensible");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if Object.setPrototypeOf works with prototype lookup
|
||||||
|
var object = {};
|
||||||
|
assertEq('x' in object, false);
|
||||||
|
assertEq('y' in object, false);
|
||||||
|
|
||||||
|
var oldProto = {
|
||||||
|
x: 'old x',
|
||||||
|
y: 'old y'
|
||||||
|
};
|
||||||
|
Object.setPrototypeOf(object, oldProto);
|
||||||
|
assertEq(object.x, 'old x');
|
||||||
|
assertEq(object.y, 'old y');
|
||||||
|
|
||||||
|
var newProto = {
|
||||||
|
x: 'new x'
|
||||||
|
};
|
||||||
|
Object.setPrototypeOf(object, newProto);
|
||||||
|
assertEq(object.x, 'new x');
|
||||||
|
assertEq('y' in object, false);
|
||||||
|
|
||||||
|
// check if Object.setPrototypeOf throws TypeError on fewer arguments
|
||||||
|
assertThrowsInstanceOf(() => Object.setPrototypeOf(),
|
||||||
|
TypeError, "Object.setPrototypeOf throws TypeError when called without any parameters");
|
||||||
|
assertThrowsInstanceOf(() => Object.setPrototypeOf({}),
|
||||||
|
TypeError, "Object.setPrototypeOf throws TypeError when called with 1 parameter");
|
Loading…
Reference in New Issue
Block a user