mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-23 19:09:49 +00:00
Bug 1529757 - Add JS::GetFunctionRealm and use it in GetPrototypeFromConstructor. r=jorendorff,bzbarsky
Differential Revision: https://phabricator.services.mozilla.com/D27867 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
6b925edfbe
commit
dcb885cbb7
@ -116,6 +116,16 @@ extern JS_PUBLIC_API JSObject* GetRealmErrorPrototype(JSContext* cx);
|
||||
|
||||
extern JS_PUBLIC_API JSObject* GetRealmIteratorPrototype(JSContext* cx);
|
||||
|
||||
// Implements https://tc39.github.io/ecma262/#sec-getfunctionrealm
|
||||
// 7.3.22 GetFunctionRealm ( obj )
|
||||
//
|
||||
// WARNING: may return a realm in a different compartment!
|
||||
//
|
||||
// Will throw an exception and return nullptr when a security wrapper or revoked
|
||||
// proxy is encountered.
|
||||
extern JS_PUBLIC_API Realm* GetFunctionRealm(JSContext* cx,
|
||||
HandleObject objArg);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif // js_Realm_h
|
||||
|
@ -355,18 +355,12 @@ skip script test262/language/expressions/prefix-increment/S11.4.4_A5_T5.js
|
||||
skip script test262/language/expressions/prefix-increment/S11.4.4_A6_T1.js
|
||||
skip script test262/language/expressions/prefix-increment/S11.4.4_A6_T2.js
|
||||
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1288457
|
||||
skip script test262/built-ins/Function/internals/Construct/base-ctor-revoked-proxy.js
|
||||
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=944846
|
||||
skip script test262/built-ins/Number/prototype/toExponential/return-values.js
|
||||
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1225839
|
||||
skip script test262/built-ins/Function/internals/Call/class-ctor-realm.js
|
||||
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1288457
|
||||
skip script test262/built-ins/Function/internals/Construct/base-ctor-revoked-proxy-realm.js
|
||||
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1297179
|
||||
skip script test262/built-ins/Proxy/apply/arguments-realm.js
|
||||
skip script test262/built-ins/Proxy/apply/trap-is-not-callable-realm.js
|
||||
@ -399,9 +393,7 @@ skip script test262/built-ins/Function/internals/Construct/derived-return-val-re
|
||||
skip script test262/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js
|
||||
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1317416
|
||||
skip script test262/language/expressions/super/realm.js
|
||||
skip script test262/built-ins/GeneratorFunction/proto-from-ctor-realm.js
|
||||
skip script test262/built-ins/Function/prototype/bind/proto-from-ctor-realm.js
|
||||
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1317395
|
||||
skip script test262/built-ins/ArrayBuffer/prototype/byteLength/detached-buffer.js
|
||||
|
45
js/src/tests/non262/Function/get-function-realm.js
Normal file
45
js/src/tests/non262/Function/get-function-realm.js
Normal file
@ -0,0 +1,45 @@
|
||||
var g1 = newGlobal();
|
||||
var g1Fun = g1.eval("function Fun() {}; Fun");
|
||||
|
||||
// Bound function => cross-realm function.
|
||||
var bound1 = Function.prototype.bind.call(g1Fun);
|
||||
assertEq(Object.getPrototypeOf(new bound1()), g1.Fun.prototype);
|
||||
|
||||
// Proxy => cross-realm function.
|
||||
var proxy1 = new Proxy(g1Fun, {
|
||||
get: function() {} // Ensure "prototype" is |undefined|.
|
||||
});
|
||||
assertEq(Object.getPrototypeOf(new proxy1()), g1.Object.prototype);
|
||||
|
||||
// Proxy => bound function => cross-realm function.
|
||||
var proxy2 = new Proxy(bound1, {
|
||||
get: function() {}
|
||||
});
|
||||
assertEq(Object.getPrototypeOf(new proxy2()), g1.Object.prototype);
|
||||
|
||||
// Revoked proxy => cross-realm function.
|
||||
var r1 = Proxy.revocable(g1Fun, {
|
||||
get: function(t, name) {
|
||||
assertEq(name, "prototype");
|
||||
r1.revoke();
|
||||
}
|
||||
});
|
||||
assertThrowsInstanceOf(() => new r1.proxy(), g1.TypeError);
|
||||
|
||||
// Bound function => proxy => bound function => cross-realm function.
|
||||
var bound2 = Function.prototype.bind.call(proxy2);
|
||||
assertEq(Object.getPrototypeOf(new bound2()), g1.Object.prototype);
|
||||
|
||||
// Proxy => cross-realm revoked proxy => cross-realm function.
|
||||
var r2 = Proxy.revocable(g1Fun, {
|
||||
get: function(t, name) {
|
||||
assertEq(name, "prototype");
|
||||
r2.revoke();
|
||||
}
|
||||
});
|
||||
var g2 = newGlobal();
|
||||
var proxy3 = new g2.Proxy(r2.proxy, {});
|
||||
assertThrowsInstanceOf(() => new proxy3(), g1.TypeError);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
@ -1183,16 +1183,18 @@ bool js::GetPrototypeFromConstructor(JSContext* cx, HandleObject newTarget,
|
||||
proto.set(nullptr);
|
||||
} else {
|
||||
// Step 4.a: Let realm be ? GetFunctionRealm(constructor);
|
||||
JSObject* unwrappedConstructor = CheckedUnwrapStatic(newTarget);
|
||||
if (!unwrappedConstructor) {
|
||||
ReportAccessDenied(cx);
|
||||
Realm* realm = JS::GetFunctionRealm(cx, newTarget);
|
||||
if (!realm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 4.b: Set proto to realm's intrinsic object named
|
||||
// intrinsicDefaultProto.
|
||||
{
|
||||
AutoRealm ar(cx, unwrappedConstructor);
|
||||
mozilla::Maybe<AutoRealm> ar;
|
||||
if (cx->realm() != realm) {
|
||||
ar.emplace(cx, realm->maybeGlobal());
|
||||
}
|
||||
proto.set(GlobalObject::getOrCreatePrototype(cx, intrinsicDefaultProto));
|
||||
}
|
||||
if (!proto) {
|
||||
@ -1209,7 +1211,7 @@ JSObject* js::CreateThisForFunction(JSContext* cx, HandleFunction callee,
|
||||
HandleObject newTarget,
|
||||
NewObjectKind newKind) {
|
||||
RootedObject proto(cx);
|
||||
if (!GetPrototypeFromConstructor(cx, newTarget, JSProto_Null, &proto)) {
|
||||
if (!GetPrototypeFromConstructor(cx, newTarget, JSProto_Object, &proto)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1037,3 +1037,53 @@ JS_PUBLIC_API JSObject* JS::GetRealmIteratorPrototype(JSContext* cx) {
|
||||
CHECK_THREAD(cx);
|
||||
return GlobalObject::getOrCreateIteratorPrototype(cx, cx->global());
|
||||
}
|
||||
|
||||
JS_PUBLIC_API Realm* JS::GetFunctionRealm(JSContext* cx, HandleObject objArg) {
|
||||
// https://tc39.github.io/ecma262/#sec-getfunctionrealm
|
||||
// 7.3.22 GetFunctionRealm ( obj )
|
||||
|
||||
CHECK_THREAD(cx);
|
||||
cx->check(objArg);
|
||||
|
||||
RootedObject obj(cx, objArg);
|
||||
while (true) {
|
||||
obj = CheckedUnwrapStatic(obj);
|
||||
if (!obj) {
|
||||
ReportAccessDenied(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 1.
|
||||
MOZ_ASSERT(IsCallable(obj));
|
||||
|
||||
// Steps 2 and 3. We use a loop instead of recursion to unwrap bound
|
||||
// functions.
|
||||
if (obj->is<JSFunction>()) {
|
||||
JSFunction* fun = &obj->as<JSFunction>();
|
||||
if (!fun->isBoundFunction()) {
|
||||
return fun->realm();
|
||||
}
|
||||
|
||||
obj = fun->getBoundFunctionTarget();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Step 4.
|
||||
if (IsScriptedProxy(obj)) {
|
||||
// Steps 4.a-b.
|
||||
JSObject* proxyTarget = GetProxyTargetObject(obj);
|
||||
if (!proxyTarget) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_PROXY_REVOKED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 4.c.
|
||||
obj = proxyTarget;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
return cx->realm();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user