mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 950407 - Fix ES6 Proxy forwarding, and apropriately throw on indirect ArrayBuffer __proto__ sets. (r=bholley,Waldo sr=mrbkap)
This commit is contained in:
parent
6af45f3d96
commit
ee4a0c8dfe
@ -429,6 +429,26 @@ JSObject::setProto(JSContext *cx, JS::HandleObject obj, JS::HandleObject proto,
|
||||
return js::Proxy::setPrototypeOf(cx, obj, proto, succeeded);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disallow mutating the [[Prototype]] on ArrayBuffer objects, which
|
||||
* due to their complicated delegate-object shenanigans can't easily
|
||||
* have a mutable [[Prototype]].
|
||||
*/
|
||||
if (obj->is<js::ArrayBufferObject>()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
|
||||
"Object", "__proto__ setter", "ArrayBuffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Explicityly disallow mutating the [[Prototype]] of Location objects
|
||||
* for flash-related security reasons.
|
||||
*/
|
||||
if (!strcmp(obj->getClass()->name, "Location")) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ES6 9.1.2 step 5 forbids changing [[Prototype]] if not [[Extensible]]. */
|
||||
bool extensible;
|
||||
if (!JSObject::isExtensible(cx, obj, &extensible))
|
||||
|
@ -3250,15 +3250,12 @@ proxy(JSContext *cx, unsigned argc, jsval *vp)
|
||||
RootedObject handler(cx, NonNullObject(cx, args[1]));
|
||||
if (!handler)
|
||||
return false;
|
||||
RootedObject proto(cx);
|
||||
if (!JSObject::getProto(cx, target, &proto))
|
||||
return false;
|
||||
RootedValue priv(cx, ObjectValue(*target));
|
||||
ProxyOptions options;
|
||||
options.setCallable(target->isCallable());
|
||||
ProxyObject *proxy =
|
||||
ProxyObject::New(cx, &ScriptedDirectProxyHandler::singleton,
|
||||
priv, TaggedProto(proto), cx->global(),
|
||||
priv, TaggedProto(TaggedProto::LazyProto), cx->global(),
|
||||
options);
|
||||
if (!proxy)
|
||||
return false;
|
||||
|
59
js/src/tests/ecma_6/Proxy/proxy-__proto__.js
Normal file
59
js/src/tests/ecma_6/Proxy/proxy-__proto__.js
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
var gTestfile = 'proxy-__proto__.js';
|
||||
var BUGNUMBER = 950407;
|
||||
var summary = "Behavior of __proto__ on ES6 proxies";
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
/**************
|
||||
* BEGIN TEST *
|
||||
**************/
|
||||
|
||||
var protoDesc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__");
|
||||
var protoGetter = protoDesc.get;
|
||||
var protoSetter = protoDesc.set;
|
||||
|
||||
function testProxy(target, initialProto)
|
||||
{
|
||||
print("Now testing behavior for new Proxy(" + ("" + target) + ", {})");
|
||||
|
||||
var pobj = new Proxy(target, {});
|
||||
|
||||
// Check [[Prototype]] before attempted mutation
|
||||
assertEq(Object.getPrototypeOf(pobj), initialProto);
|
||||
assertEq(protoGetter.call(pobj), initialProto);
|
||||
|
||||
// Attempt [[Prototype]] mutation
|
||||
protoSetter.call(pobj, null);
|
||||
|
||||
// Check [[Prototype]] after attempted mutation
|
||||
assertEq(Object.getPrototypeOf(pobj), null);
|
||||
assertEq(protoGetter.call(pobj), null);
|
||||
assertEq(Object.getPrototypeOf(target), null);
|
||||
}
|
||||
|
||||
// Proxy object with non-null [[Prototype]]
|
||||
var nonNullProto = { toString: function() { return "non-null prototype"; } };
|
||||
var target = Object.create(nonNullProto);
|
||||
testProxy(target, nonNullProto);
|
||||
|
||||
// Proxy object with null [[Prototype]]
|
||||
target = Object.create(null);
|
||||
target.toString = function() { return "null prototype" };
|
||||
testProxy(target, null);
|
||||
|
||||
// Proxy function with [[Call]]
|
||||
var callForCallOnly = function () { };
|
||||
callForCallOnly.toString = function() { return "callable target"; };
|
||||
testProxy(callForCallOnly, Function.prototype);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
print("Tests complete");
|
11
js/src/tests/ecma_6/Proxy/regress-bug950407.js
Normal file
11
js/src/tests/ecma_6/Proxy/regress-bug950407.js
Normal file
@ -0,0 +1,11 @@
|
||||
var ab = ArrayBuffer(5);
|
||||
var p = new Proxy(ab, {});
|
||||
var ps = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set;
|
||||
var threw = 0;
|
||||
try {
|
||||
ps.call(p, {});
|
||||
} catch(ex) {
|
||||
threw = 1;
|
||||
}
|
||||
|
||||
reportCompare(1, threw, "Setting __proto__ on a proxy to an ArrayBuffer must throw.");
|
0
js/src/tests/ecma_6/Proxy/shell.js
Normal file
0
js/src/tests/ecma_6/Proxy/shell.js
Normal file
@ -123,17 +123,6 @@ ProtoSetterImpl(JSContext *cx, CallArgs args)
|
||||
|
||||
Rooted<JSObject*> obj(cx, &args.thisv().toObject());
|
||||
|
||||
/*
|
||||
* Disallow mutating the [[Prototype]] on ArrayBuffer objects, which
|
||||
* due to their complicated delegate-object shenanigans can't easily
|
||||
* have a mutable [[Prototype]].
|
||||
*/
|
||||
if (obj->is<ArrayBufferObject>()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
|
||||
"Object", "__proto__ setter", "ArrayBuffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Do nothing if __proto__ isn't being set to an object or null. */
|
||||
if (args.length() == 0 || !args[0].isObjectOrNull()) {
|
||||
args.rval().setUndefined();
|
||||
@ -142,12 +131,6 @@ ProtoSetterImpl(JSContext *cx, CallArgs args)
|
||||
|
||||
Rooted<JSObject*> newProto(cx, args[0].toObjectOrNull());
|
||||
|
||||
unsigned dummy;
|
||||
RootedId nid(cx, NameToId(cx->names().proto));
|
||||
RootedValue v(cx);
|
||||
if (!CheckAccess(cx, obj, nid, JSAccessMode(JSACC_PROTO | JSACC_WRITE), &v, &dummy))
|
||||
return false;
|
||||
|
||||
bool success;
|
||||
if (!JSObject::setProto(cx, obj, newProto, &success))
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user