68.14.8 - js

This commit is contained in:
Fedor 2025-04-19 19:14:02 +03:00
parent 789a0fa277
commit 6c3e867c73
152 changed files with 304 additions and 992 deletions

View File

@ -19,7 +19,6 @@
#include "js/RootingAPI.h" // JS::Handle, JS::MutableHandle
struct JS_PUBLIC_API JSContext;
class JS_PUBLIC_API JSFunction;
class JS_PUBLIC_API JSObject;
class JS_PUBLIC_API JSScript;
@ -102,9 +101,6 @@ extern JS_PUBLIC_API TranscodeResult EncodeScript(JSContext* cx,
TranscodeBuffer& buffer,
Handle<JSScript*> script);
extern JS_PUBLIC_API TranscodeResult EncodeInterpretedFunction(
JSContext* cx, TranscodeBuffer& buffer, Handle<JSObject*> funobj);
// Decode JSScript from the buffer.
//
// The start of `buffer` and `cursorIndex` should meet
@ -124,11 +120,6 @@ extern JS_PUBLIC_API TranscodeResult
DecodeScript(JSContext* cx, const ReadOnlyCompileOptions& options,
const TranscodeRange& range, MutableHandle<JSScript*> scriptp);
extern JS_PUBLIC_API TranscodeResult DecodeInterpretedFunction(
JSContext* cx, const ReadOnlyCompileOptions& options,
TranscodeBuffer& buffer, MutableHandle<JSFunction*> funp,
size_t cursorIndex = 0);
// If js::UseOffThreadParseGlobal is true, decode JSScript from the buffer.
//
// If js::UseOffThreadParseGlobal is false, decode CompilationStencil from the

View File

@ -183,7 +183,6 @@ MSG_DEF(JSMSG_OBJECT_ACCESS_DENIED, 0, JSEXN_ERR, "Permission denied to acces
MSG_DEF(JSMSG_PROPERTY_ACCESS_DENIED, 1, JSEXN_ERR, "Permission denied to access property {0}")
// JSAPI-only (Not thrown as JS exceptions)
MSG_DEF(JSMSG_BAD_CLONE_FUNOBJ_SCOPE, 0, JSEXN_TYPEERR, "bad cloned function scope chain")
MSG_DEF(JSMSG_CANT_CLONE_OBJECT, 0, JSEXN_TYPEERR, "can't clone object")
MSG_DEF(JSMSG_CANT_OPEN, 2, JSEXN_ERR, "can't open {0}: {1}")
MSG_DEF(JSMSG_SUPPORT_NOT_ENABLED, 1, JSEXN_ERR, "support for {0} is not enabled")

View File

@ -4724,7 +4724,6 @@ static bool ShellCloneAndExecuteScript(JSContext* cx, unsigned argc,
JS::CompileOptions options(cx);
options.setFileAndLine(filename.get(), lineno);
options.setNoScriptRval(true);
JS::SourceText<char16_t> srcBuf;
if (!srcBuf.init(cx, src, srclen, SourceOwnership::Borrowed)) {
@ -4746,14 +4745,19 @@ static bool ShellCloneAndExecuteScript(JSContext* cx, unsigned argc,
return false;
}
AutoRealm ar(cx, global);
JS::RootedValue rval(cx);
if (!JS::CloneAndExecuteScript(cx, script, &rval)) {
{
AutoRealm ar(cx, global);
if (!JS::CloneAndExecuteScript(cx, script, &rval)) {
return false;
}
}
if (!cx->compartment()->wrap(cx, &rval)) {
return false;
}
args.rval().setUndefined();
args.rval().set(rval);
return true;
}

View File

@ -1,6 +1,6 @@
// |jit-test| error:AsmJS modules do not yet support cloning; skip-if: !isAsmJSCompilationAvailable()
var g = newGlobal();
g.evaluate(`
cloneAndExecuteScript(`
function h() {
function f() {
'use asm';
@ -9,6 +9,4 @@ g.evaluate(`
}
return f;
}
`);
var h = clone(g.h);
h();
`, g);

View File

@ -1,6 +1,4 @@
// |jit-test| error:Error; skip-if: !isAsmJSCompilationAvailable()
// |jit-test| error:Error: AsmJS modules do not yet support cloning; skip-if: !isAsmJSCompilationAvailable()
var g = newGlobal({newCompartment: true});
evaluate("function h() { function f() { 'use asm'; function g() { return 42 } return g } return f }", { global:g});
var h = clone(g.h);
assertEq(h()()(), 42);
cloneAndExecuteScript("function h() { function f() { 'use asm'; function g() { return 42 } return g } return f }", g);

View File

@ -3,16 +3,12 @@
var globals = [];
for (var i = 0; i < 24; ++i) {
var g = newGlobal();
g.eval(`
function f(){}
var env = {};
`);
globals.push(g);
}
var i = 0;
oomTest(function() {
globals[(i++) % globals.length].eval(`
this.clone(this.f, this.env);
evaluate("function f() {}", {envChainObject: this.env});
`);
});

View File

@ -23,4 +23,3 @@ this.gczeal(hits, 2);
var fn = g.evaluate("(function (a) { return 5 + a; })");
var g2 = newGlobal({newCompartment: true});
dbg.addDebuggee(g2, dbg);
g2.clone(fn);

View File

@ -10,11 +10,6 @@ var p = new Proxy(t, {
},
get(t, id) { return t[id]; }
});
evaluate(`function testFunc() {
x += " x";
}`);
var cloneFunc = clone(testFunc, p);
cloneFunc();
evaluate(`x += " x";`, {envChainObject: p});
assertEq(hits, 2);
assertEq(t.x, "undefined x");

View File

@ -1,5 +0,0 @@
// |jit-test| error: Error
var g = newGlobal();
g.f = setJitCompilerOption;
g.eval("clone(f)()(9)")

View File

@ -1,4 +0,0 @@
// |jit-test| error: can't clone
var gv = newGlobal();
gv.f = (class get {});
gv.eval('f = clone(f);');

View File

@ -1,7 +0,0 @@
load(libdir + "asserts.js");
function C(a, b) {}
var f = C.bind(null, 2);
var that = this;
assertThrowsInstanceOf(function () { g = clone(f, that)}, TypeError);

View File

@ -1,4 +0,0 @@
var g = newGlobal();
var f1 = g.evaluate("(function (x) { function inner() {}; })");
gczeal(2, 1); // Exercise all the edge cases in cloning, please.
var f2 = clone(f1);

View File

@ -19,9 +19,9 @@ function test(str, arg, result)
// test reflection logic
Reflect.parse(got);
// test xdr by cloning a cross-compartment function
// test script cloning
var code = "(function (x) { " + str + " })";
var c = clone(otherGlobal.evaluate(code));
var c = cloneAndExecuteScript(code, otherGlobal);
assertEq(c.toString(), eval(code).toString());
var got = fun(arg);

View File

@ -1,21 +1,22 @@
var g = newGlobal();
g.f = new Function('return function(x) { return x };');
assertEq(g.eval("clone(f)()(9)"), 9);
var f;
f = cloneAndExecuteScript('(function(x) { return x })', g);
assertEq(f(9), 9);
g.f = new Function('return function(x) { { let y = x+1; return y } };');
assertEq(g.eval("clone(f)()(9)"), 10);
f = cloneAndExecuteScript('(function(x) { { let y = x+1; return y } })', g);
assertEq(f(9), 10);
g.f = new Function('return function(x) { { let y = x, z = 1; return y+z } };');
assertEq(g.eval("clone(f)()(9)"), 10);
f = cloneAndExecuteScript('(function(x) { { let y = x, z = 1; return y+z } })', g);
assertEq(f(9), 10);
g.f = new Function('return function(x) { return x.search(/ponies/) };');
assertEq(g.eval("clone(f)()('123ponies')"), 3);
f = cloneAndExecuteScript('(function(x) { return x.search(/ponies/) })', g);
assertEq(f('123ponies'), 3);
g.f = new Function('return function(x,y) { return x.search(/a/) + y.search(/b/) };');
assertEq(g.eval("clone(f)()('12a','foo')"), 1);
f = cloneAndExecuteScript('(function(x, y) { return x.search(/a/) + y.search(/b/) })', g);
assertEq(f('12a','foo'), 1);
g.f = new Function('return function(x) { switch(x) { case "a": return "b"; case null: return "c" } };');
assertEq(g.eval("clone(f)()('a')"), "b");
assertEq(g.eval("clone(f)()(null)"), "c");
assertEq(g.eval("clone(f)()(3)"), undefined);
f = cloneAndExecuteScript('(function(x) { switch(x) { case "a": return "b"; case null: return "c" } })', g);
assertEq(f('a'), "b");
assertEq(f(null), "c");
assertEq(f(3), undefined);

View File

@ -6,20 +6,6 @@ function assertWithMessage(got, expected, message) {
assertEq(message + ": " + got, message + ": " + expected);
}
function testFunc() {
assertWithMessage(checkNameLookup(), "local", "nameLookup");
assertWithMessage(checkThisBinding(), "local", "thisBinding");
// Important: lambda needs to close over "reason", so it won't just get the
// scope of testFunc as its scope. Instead it'll get the Call object
// "reason" lives in.
var reason = " in lambda in Call";
(function() {
assertWithMessage(checkNameLookup(), "local", "nameLookup" + reason);
assertWithMessage(checkThisBinding(), "local", "thisBinding" + reason);
})();
}
var obj = {
checkNameLookup: function() {
return "local";
@ -30,5 +16,16 @@ var obj = {
},
};
var cloneFunc = clone(testFunc, obj);
cloneFunc();
evaluate("(" + function() {
assertWithMessage(checkNameLookup(), "local", "nameLookup");
assertWithMessage(checkThisBinding(), "local", "thisBinding");
// Important: lambda needs to close over "reason", so it won't just get the
// scope of testFunc as its scope. Instead it'll get the Call object
// "reason" lives in.
var reason = " in lambda in Call";
(function() {
assertWithMessage(checkNameLookup(), "local", "nameLookup" + reason);
assertWithMessage(checkThisBinding(), "local", "thisBinding" + reason);
})();
} + ")()", {envChainObject: obj});

View File

@ -1 +0,0 @@
// |jit-test| error: Error

View File

@ -1 +0,0 @@
// |jit-test| skip-if: !('gczeal' in this)

View File

@ -1 +0,0 @@
// |jit-test| error: Error

View File

@ -1 +0,0 @@
// |jit-test| skip-if: !('gczeal' in this)

View File

@ -1,11 +1,9 @@
// Looking at ScriptSourceObjects in invisible-to-debugger compartments is okay.
var gi = newGlobal({ newCompartment: true, invisibleToDebugger: true });
gi.eval('function f() {}');
var gv = newGlobal({newCompartment: true});
gv.f = gi.f;
gv.eval('f = clone(f);');
gi.cloneAndExecuteScript('function f() {}', gv);
var dbg = new Debugger;
var gvw = dbg.addDebuggee(gv);

View File

@ -1,6 +1,5 @@
var g = newGlobal({newCompartment: true});
g.f = function() {};
g.eval('f = clone(f);');
cloneAndExecuteScript('function f() {}', g);
var dbg = new Debugger;
var dg = dbg.addDebuggee(g);
dg.getOwnPropertyDescriptor('f').value.script.source;

View File

@ -37,9 +37,8 @@ assertEq(fn(8), 13);
assertEq(hits, 1);
// cloning functions across compartments
fn = g.evaluate("(function(a) { return 5 + a; })");
var g2 = newGlobal({newCompartment: true});
dbg.addDebuggee(g2, dbg);
hits = 0;
g2.clone(fn);
cloneAndExecuteScript("(function(a) { return 5 + a; })", g2);
assertEq(hits, 1);

View File

@ -44,7 +44,7 @@ test(function () { g.eval("var obj = {get x() { return 1; }, set x(v) { print(v)
test(function () { return g.Function("a", "b", "return b - a;"); });
// cloning a function with nested functions
test(function () { g.clone(evaluate("(function(x) { return x + 1; })")); });
test(function () { cloneAndExecuteScript("(function(x) { return x + 1; })", g); });
// eval declaring a star generator
test(function () { g.eval("function* sg(n) { for (var i=0;i<n;i++) yield i; }"); });

View File

@ -5,10 +5,8 @@
gczeal(2,21);
var gi = newGlobal();
gi.eval('function f() {}');
var gv = newGlobal();
gv.f = gi.f;
gv.eval('f = clone(f);');
gi.cloneAndExecuteScript('function f() {}', gv);
var dbg = new Debugger;

View File

@ -22,7 +22,6 @@ UNIFIED_SOURCES += [
"testCallArgs.cpp",
"testCallNonGenericMethodOnProxy.cpp",
"testChromeBuffer.cpp",
"testCloneScript.cpp",
"testCompileNonSyntactic.cpp",
"testCompileUtf8.cpp",
"testDateToLocaleString.cpp",

View File

@ -1,157 +0,0 @@
/* Test script cloning.
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Utf8.h" // mozilla::Utf8Unit
#include <string.h> // strlen
#include "jsapi.h" // sundry symbols not moved to more-specific headers yet
#include "jsfriendapi.h"
#include "jspubtd.h" // JS::RootedObjectVector
#include "js/CompilationAndEvaluation.h" // JS::CompileFunction
#include "js/CompileOptions.h" // JS::CompileOptions
#include "js/RootingAPI.h" // JS::Rooted
#include "js/SourceText.h" // JS::Source{Ownership,Text}
#include "js/TypeDecls.h" // JSFunction, JSObject
#include "jsapi-tests/tests.h"
BEGIN_TEST(test_cloneScript) {
JS::RootedObject A(cx, createGlobal());
JS::RootedObject B(cx, createGlobal());
CHECK(A);
CHECK(B);
static const char source[] =
"var i = 0;\n"
"var sum = 0;\n"
"while (i < 10) {\n"
" sum += i;\n"
" ++i;\n"
"}\n"
"(sum);\n";
JS::RootedObject obj(cx);
// compile for A
{
JSAutoRealm a(cx, A);
JS::SourceText<mozilla::Utf8Unit> srcBuf;
CHECK(srcBuf.init(cx, source, mozilla::ArrayLength(source) - 1,
JS::SourceOwnership::Borrowed));
JS::CompileOptions options(cx);
options.setFileAndLine(__FILE__, 1);
JS::RootedFunction fun(cx);
JS::RootedObjectVector emptyScopeChain(cx);
fun = JS::CompileFunction(cx, emptyScopeChain, options, "f", 0, nullptr,
srcBuf);
CHECK(fun);
CHECK(obj = JS_GetFunctionObject(fun));
}
// clone into B
{
JSAutoRealm b(cx, B);
CHECK(JS::CloneFunctionObject(cx, obj));
}
return true;
}
END_TEST(test_cloneScript)
struct Principals final : public JSPrincipals {
public:
Principals() { refcount = 0; }
bool write(JSContext* cx, JSStructuredCloneWriter* writer) override {
MOZ_ASSERT(false, "not imlemented");
return false;
}
bool isSystemOrAddonPrincipal() override { return true; }
};
static void DestroyPrincipals(JSPrincipals* principals) {
auto p = static_cast<Principals*>(principals);
delete p;
}
BEGIN_TEST(test_cloneScriptWithPrincipals) {
JS_InitDestroyPrincipalsCallback(cx, DestroyPrincipals);
JS::AutoHoldPrincipals principalsA(cx, new Principals());
JS::AutoHoldPrincipals principalsB(cx, new Principals());
JS::RootedObject A(cx, createGlobal(principalsA.get()));
JS::RootedObject B(cx, createGlobal(principalsB.get()));
CHECK(A);
CHECK(B);
const char* argnames[] = {"arg"};
static const char source[] = "return function() { return arg; }";
JS::RootedObject obj(cx);
// Compile in A
{
JSAutoRealm a(cx, A);
JS::SourceText<mozilla::Utf8Unit> srcBuf;
CHECK(srcBuf.init(cx, source, mozilla::ArrayLength(source) - 1,
JS::SourceOwnership::Borrowed));
JS::CompileOptions options(cx);
options.setFileAndLine(__FILE__, 1);
JS::RootedFunction fun(cx);
JS::RootedObjectVector emptyScopeChain(cx);
fun = JS::CompileFunction(cx, emptyScopeChain, options, "f",
mozilla::ArrayLength(argnames), argnames, srcBuf);
CHECK(fun);
JSScript* script;
CHECK(script = JS_GetFunctionScript(cx, fun));
CHECK(JS_GetScriptPrincipals(script) == principalsA.get());
CHECK(obj = JS_GetFunctionObject(fun));
}
// Clone into B
{
JSAutoRealm b(cx, B);
JS::RootedObject cloned(cx);
CHECK(cloned = JS::CloneFunctionObject(cx, obj));
JS::RootedFunction fun(cx);
JS::RootedValue clonedValue(cx, JS::ObjectValue(*cloned));
CHECK(fun = JS_ValueToFunction(cx, clonedValue));
JSScript* script;
CHECK(script = JS_GetFunctionScript(cx, fun));
CHECK(JS_GetScriptPrincipals(script) == principalsB.get());
JS::RootedValue v(cx);
JS::RootedValue arg(cx, JS::Int32Value(1));
CHECK(JS_CallFunctionValue(cx, B, clonedValue, JS::HandleValueArray(arg),
&v));
CHECK(v.isObject());
JSObject* funobj = &v.toObject();
CHECK(JS_ObjectIsFunction(funobj));
CHECK(fun = JS_ValueToFunction(cx, v));
CHECK(script = JS_GetFunctionScript(cx, fun));
CHECK(JS_GetScriptPrincipals(script) == principalsB.get());
}
return true;
}
END_TEST(test_cloneScriptWithPrincipals)

View File

@ -3282,105 +3282,6 @@ JS_PUBLIC_API JSFunction* JS::NewFunctionFromSpec(JSContext* cx,
return NewFunctionFromSpec(cx, fs, id);
}
static bool IsFunctionCloneable(HandleFunction fun) {
// If a function was compiled with non-global syntactic environments on
// the environment chain, we could have baked in EnvironmentCoordinates
// into the script. We cannot clone it without breaking the compiler's
// assumptions.
for (ScopeIter si(fun->nonLazyScript()->enclosingScope()); si; si++) {
if (si.scope()->is<GlobalScope>()) {
return true;
}
if (si.hasSyntacticEnvironment()) {
return false;
}
}
return true;
}
static JSObject* CloneFunctionObject(JSContext* cx, HandleObject funobj,
HandleObject env, HandleScope scope) {
AssertHeapIsIdle();
CHECK_THREAD(cx);
cx->check(env);
MOZ_ASSERT(env);
// Note that funobj can be in a different compartment.
if (!funobj->is<JSFunction>()) {
MOZ_RELEASE_ASSERT(!IsCrossCompartmentWrapper(funobj));
AutoRealm ar(cx, funobj);
RootedValue v(cx, ObjectValue(*funobj));
ReportIsNotFunction(cx, v);
return nullptr;
}
// Only allow cloning normal, interpreted functions.
RootedFunction fun(cx, &funobj->as<JSFunction>());
if (fun->isNativeFun() || fun->isBoundFunction() ||
fun->kind() != FunctionFlags::NormalFunction || fun->isExtended() ||
fun->isSelfHostedBuiltin()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_CANT_CLONE_OBJECT);
return nullptr;
}
if (fun->hasSelfHostedLazyScript()) {
AutoRealm ar(cx, fun);
if (!JSFunction::getOrCreateScript(cx, fun)) {
return nullptr;
}
}
RootedScript script(cx, fun->nonLazyScript());
if (!IsFunctionCloneable(fun)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
return nullptr;
}
if (CanReuseScriptForClone(cx->realm(), fun, env)) {
return CloneFunctionReuseScript(cx, fun, env, fun->getAllocKind(),
nullptr);
}
Rooted<ScriptSourceObject*> sourceObject(cx, script->sourceObject());
if (cx->compartment() != sourceObject->compartment()) {
sourceObject = ScriptSourceObject::clone(cx, sourceObject);
if (!sourceObject) {
return nullptr;
}
}
JSFunction* clone = CloneFunctionAndScript(cx, fun, env, scope, sourceObject,
fun->getAllocKind());
#ifdef DEBUG
// The cloned function should itself be cloneable.
RootedFunction cloneRoot(cx, clone);
MOZ_ASSERT_IF(cloneRoot, IsFunctionCloneable(cloneRoot));
#endif
return clone;
}
JS_PUBLIC_API JSObject* JS::CloneFunctionObject(JSContext* cx,
HandleObject funobj) {
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
return CloneFunctionObject(cx, funobj, globalLexical, emptyGlobalScope);
}
extern JS_PUBLIC_API JSObject* JS::CloneFunctionObject(
JSContext* cx, HandleObject funobj, HandleObjectVector envChain) {
RootedObject env(cx);
RootedScope scope(cx);
if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env)) {
return nullptr;
}
return CloneFunctionObject(cx, funobj, env, scope);
}
JS_PUBLIC_API JSObject* JS_GetFunctionObject(JSFunction* fun) { return fun; }
JS_PUBLIC_API JSString* JS_GetFunctionId(JSFunction* fun) {
@ -5700,19 +5601,6 @@ JS_PUBLIC_API JS::TranscodeResult JS::EncodeScript(JSContext* cx,
return JS::TranscodeResult::Ok;
}
JS_PUBLIC_API JS::TranscodeResult JS::EncodeInterpretedFunction(
JSContext* cx, TranscodeBuffer& buffer, HandleObject funobjArg) {
XDREncoder encoder(cx, buffer, buffer.length());
RootedFunction funobj(cx, &funobjArg->as<JSFunction>());
XDRResult res = encoder.codeFunction(&funobj);
if (res.isErr()) {
buffer.clearAndFree();
return res.unwrapErr();
}
MOZ_ASSERT(!buffer.empty());
return JS::TranscodeResult::Ok;
}
JS_PUBLIC_API JS::TranscodeResult JS::DecodeScript(
JSContext* cx, const ReadOnlyCompileOptions& options,
TranscodeBuffer& buffer, JS::MutableHandleScript scriptp,
@ -5804,24 +5692,6 @@ JS_PUBLIC_API JS::TranscodeResult JS::DecodeScript(
return JS::TranscodeResult::Ok;
}
JS_PUBLIC_API JS::TranscodeResult JS::DecodeInterpretedFunction(
JSContext* cx, const ReadOnlyCompileOptions& options,
TranscodeBuffer& buffer, JS::MutableHandleFunction funp,
size_t cursorIndex) {
Rooted<UniquePtr<XDRDecoder>> decoder(
cx, js::MakeUnique<XDRDecoder>(cx, &options, buffer, cursorIndex));
if (!decoder) {
ReportOutOfMemory(cx);
return JS::TranscodeResult::Throw;
}
XDRResult res = decoder->codeFunction(funp);
MOZ_ASSERT(bool(funp) == res.isOk());
if (res.isErr()) {
return res.unwrapErr();
}
return JS::TranscodeResult::Ok;
}
JS_PUBLIC_API JS::TranscodeResult JS::DecodeScriptAndStartIncrementalEncoding(
JSContext* cx, const ReadOnlyCompileOptions& options,
TranscodeBuffer& buffer, JS::MutableHandleScript scriptp,

View File

@ -1676,25 +1676,6 @@ extern JS_PUBLIC_API bool JS_IsFunctionBound(JSFunction* fun);
extern JS_PUBLIC_API JSObject* JS_GetBoundFunctionTarget(JSFunction* fun);
namespace JS {
/**
* Clone a top-level function into cx's global. This function will dynamically
* fail if funobj was lexically nested inside some other function.
*/
extern JS_PUBLIC_API JSObject* CloneFunctionObject(JSContext* cx,
HandleObject funobj);
/**
* As above, but providing an explicit scope chain. scopeChain must not include
* the global object on it; that's implicit. It needs to contain the other
* objects that should end up on the clone's scope chain.
*/
extern JS_PUBLIC_API JSObject* CloneFunctionObject(
JSContext* cx, HandleObject funobj, HandleObjectVector scopeChain);
} // namespace JS
extern JS_PUBLIC_API JSObject* JS_GetGlobalFromScript(JSScript* script);
extern JS_PUBLIC_API const char* JS_GetScriptFilename(JSScript* script);

View File

@ -190,26 +190,6 @@ extern JS_FRIEND_API bool GetIsSecureContext(JS::Realm* realm);
extern JS_FRIEND_API bool JS_CopyOwnPropertiesAndPrivateFields(
JSContext* cx, JS::HandleObject target, JS::HandleObject obj);
/*
* Single-property version of the above. This function asserts that an |own|
* property of the given name exists on |obj|.
*
* On entry, |cx| must be same-compartment with |obj|. |target| must not be a
* cross-compartment wrapper because we have to enter its realm.
*
* The copyBehavior argument controls what happens with
* non-configurable properties.
*/
typedef enum {
MakeNonConfigurableIntoConfigurable,
CopyNonConfigurableAsIs
} PropertyCopyBehavior;
extern JS_FRIEND_API bool JS_CopyPropertyFrom(
JSContext* cx, JS::HandleId id, JS::HandleObject target,
JS::HandleObject obj,
PropertyCopyBehavior copyBehavior = CopyNonConfigurableAsIs);
extern JS_FRIEND_API bool JS_WrapPropertyDescriptor(
JSContext* cx, JS::MutableHandle<JS::PropertyDescriptor> desc);

View File

@ -3852,59 +3852,6 @@ static bool Intern(JSContext* cx, unsigned argc, Value* vp) {
return true;
}
static bool Clone(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() == 0) {
JS_ReportErrorASCII(cx, "Invalid arguments to clone");
return false;
}
RootedObject funobj(cx);
{
Maybe<JSAutoRealm> ar;
RootedObject obj(cx, args[0].isPrimitive() ? nullptr : &args[0].toObject());
if (obj && obj->is<CrossCompartmentWrapperObject>()) {
obj = UncheckedUnwrap(obj);
ar.emplace(cx, obj);
args[0].setObject(*obj);
}
if (obj && obj->is<JSFunction>()) {
funobj = obj;
} else {
JSFunction* fun = JS_ValueToFunction(cx, args[0]);
if (!fun) {
return false;
}
funobj = JS_GetFunctionObject(fun);
}
}
RootedObject env(cx);
if (args.length() > 1) {
if (!JS_ValueToObject(cx, args[1], &env)) {
return false;
}
} else {
env = JS::CurrentGlobalOrNull(cx);
MOZ_ASSERT(env);
}
// Should it worry us that we might be getting with wrappers
// around with wrappers here?
JS::RootedObjectVector envChain(cx);
if (env && !env->is<GlobalObject>() && !envChain.append(env)) {
return false;
}
JSObject* clone = JS::CloneFunctionObject(cx, funobj, envChain);
if (!clone) {
return false;
}
args.rval().setObject(*clone);
return true;
}
static bool Crash(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() == 0) {
@ -8717,10 +8664,6 @@ static bool TransplantableObject(JSContext* cx, unsigned argc, Value* vp) {
// clang-format off
static const JSFunctionSpecWithHelp shell_functions[] = {
JS_FN_HELP("clone", Clone, 1, 0,
"clone(fun[, scope])",
" Clone function object."),
JS_FN_HELP("options", Options, 0, 0,
"options([option ...])",
" Get or toggle JavaScript options."),

View File

@ -1,17 +1,4 @@
// |reftest| skip-if(!xulRuntime.shell) -- needs clone, cloneAndExecuteScript, drainJobQueue
// Async functions can be cloned.
let f = clone(async function f() {
var a = await 1;
var b = await 2;
var c = await 3;
return a + b + c;
});
var V;
f().then(v => V = v);
drainJobQueue();
assertEq(V, 6);
// |reftest| skip-if(!xulRuntime.shell) -- needs cloneAndExecuteScript, drainJobQueue
// Async function source code scripts can be cloned.
let g = newGlobal();

View File

@ -25,12 +25,10 @@ function test()
else {
expect = 'PASSED';
f = evaluate("(function () { return a * a; })");
g = clone(f, {a: 3});
f = null;
f = evaluate("(function () { return a * a; })", {envChainObject: {a: 3}});
gc();
try {
a_squared = g(2);
a_squared = f(2);
if (a_squared != 9)
throw "Unexpected return from g: a_squared == " + a_squared;
actual = "PASSED";

View File

@ -1,76 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
*
* Date: 06 Mar 2002
* SUMMARY: Testing cloned function objects
* See http://bugzilla.mozilla.org/show_bug.cgi?id=127557
*
* Before this bug was fixed, this testcase would error when run:
*
* ReferenceError: h_peer is not defined
*
* The line |g.prototype = new Object| below is essential: this is
* what was confusing the engine in its attempt to look up h_peer
*/
//-----------------------------------------------------------------------------
var UBound = 0;
var BUGNUMBER = 127557;
var summary = 'Testing cloned function objects';
var cnCOMMA = ',';
var status = '';
var statusitems = [];
var actual = '';
var actualvalues = [];
var expect= '';
var expectedvalues = [];
if (typeof clone == 'function')
{
status = inSection(1);
var f = evaluate("(function(x, y) {\n" +
" function h() { return h_peer(); }\n" +
" function h_peer() { return (x + cnCOMMA + y); }\n" +
" return h;\n" +
"})");
var g = clone(f);
g.prototype = new Object;
var h = g(5,6);
actual = h();
expect = '5,6';
addThis();
}
else
{
reportCompare('Test not run', 'Test not run', 'shell only test requires clone()');
}
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function addThis()
{
statusitems[UBound] = status;
actualvalues[UBound] = actual;
expectedvalues[UBound] = expect;
UBound++;
}
function test()
{
printBugNumber(BUGNUMBER);
printStatus(summary);
for (var i=0; i<UBound; i++)
{
reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]);
}
}

View File

@ -1012,9 +1012,8 @@ bool JSObject::nonNativeSetElement(JSContext* cx, HandleObject obj,
return nonNativeSetProperty(cx, obj, id, v, receiver, result);
}
JS_FRIEND_API bool JS_CopyPropertyFrom(JSContext* cx, HandleId id,
HandleObject target, HandleObject obj,
PropertyCopyBehavior copyBehavior) {
static bool CopyPropertyFrom(JSContext* cx, HandleId id, HandleObject target,
HandleObject obj) {
// |target| must not be a CCW because we need to enter its realm below and
// CCWs are not associated with a single realm.
MOZ_ASSERT(!IsCrossCompartmentWrapper(target));
@ -1036,11 +1035,6 @@ JS_FRIEND_API bool JS_CopyPropertyFrom(JSContext* cx, HandleId id,
return true;
}
if (copyBehavior == MakeNonConfigurableIntoConfigurable) {
// Mask off the JSPROP_PERMANENT bit.
desc.attributesRef() &= ~JSPROP_PERMANENT;
}
JSAutoRealm ar(cx, target);
cx->markId(id);
RootedId wrappedId(cx, id);
@ -1070,7 +1064,7 @@ JS_FRIEND_API bool JS_CopyOwnPropertiesAndPrivateFields(JSContext* cx,
}
for (size_t i = 0; i < props.length(); ++i) {
if (!JS_CopyPropertyFrom(cx, props[i], target, obj)) {
if (!CopyPropertyFrom(cx, props[i], target, obj)) {
return false;
}
}

View File

@ -1,12 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
SpecialPowers.wrap(document).getAnonymousNodes({__proto__: XPCNativeWrapper.prototype});
</script>
</head>
<body>
</body>
</html>

View File

@ -15,7 +15,6 @@ load 420513-1.html
load 453935-1.html
load 467693-1.html
load 468552-1.html
load 471366-1.html
load 475185-1.html
load 475291-1.html
load 503286-1.html

View File

@ -267,12 +267,5 @@ interface nsIXPConnect : nsISupports
in JSContextPtr aJSContext,
in const_JSReadOnlyCompileOptionsRef aOptions);
[noscript] void writeFunction(in nsIObjectOutputStream aStream,
in JSContextPtr aJSContext,
in JSObjectPtr aJSObject);
[noscript] JSObjectPtr readFunction(in nsIObjectInputStream aStream,
in JSContextPtr aJSContext);
[infallible] readonly attribute boolean isShuttingDown;
};

View File

@ -66,9 +66,13 @@
#include "mozilla/dom/XMLHttpRequest.h"
#include "mozilla/dom/XMLSerializerBinding.h"
#include "mozilla/dom/FormDataBinding.h"
#include "mozilla/dom/nsCSPContext.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/DeferredFinalize.h"
#include "mozilla/ExtensionPolicyService.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/StaticPrefs_extensions.h"
using namespace mozilla;
using namespace JS;
@ -336,6 +340,46 @@ static bool SandboxCreateFetch(JSContext* cx, HandleObject obj) {
dom::Headers_Binding::GetConstructorObject(cx);
}
static bool SandboxStructuredClone(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
if (!args.requireAtLeast(cx, "structuredClone", 1)) {
return false;
}
RootedDictionary<dom::StructuredSerializeOptions> options(cx);
BindingCallContext callCx(cx, "structuredClone");
if (!options.Init(cx, args.hasDefined(1) ? args[1] : JS::NullHandleValue,
"Argument 2", false)) {
return false;
}
nsIGlobalObject* global = CurrentNativeGlobal(cx);
if (!global) {
JS_ReportErrorASCII(cx, "structuredClone: Missing global");
return false;
}
JS::Rooted<JS::Value> result(cx);
ErrorResult rv;
nsContentUtils::StructuredClone(cx, global, args[0], options, &result, rv);
if (rv.MaybeSetPendingException(cx)) {
return false;
}
MOZ_ASSERT_IF(result.isGCThing(),
!JS::GCThingIsMarkedGray(result.toGCCellPtr()));
args.rval().set(result);
return true;
}
static bool SandboxCreateStructuredClone(JSContext* cx, HandleObject obj) {
MOZ_ASSERT(JS_IsGlobalObject(obj));
return JS_DefineFunction(cx, obj, "structuredClone", SandboxStructuredClone,
1, 0);
}
static bool SandboxIsProxy(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() < 1) {
@ -880,6 +924,8 @@ bool xpc::GlobalProperties::Parse(JSContext* cx, JS::HandleObject obj) {
crypto = true;
} else if (JS_LinearStringEqualsLiteral(nameStr, "fetch")) {
fetch = true;
} else if (JS_LinearStringEqualsLiteral(nameStr, "structuredClone")) {
structuredClone = true;
} else if (JS_LinearStringEqualsLiteral(nameStr, "indexedDB")) {
indexedDB = true;
#ifdef MOZ_WEBRTC
@ -1000,6 +1046,10 @@ bool xpc::GlobalProperties::Define(JSContext* cx, JS::HandleObject obj) {
return false;
}
if (structuredClone && !SandboxCreateStructuredClone(cx, obj)) {
return false;
}
#ifdef MOZ_WEBRTC
if (rtcIdentityProvider && !SandboxCreateRTCIdentityProvider(cx, obj)) {
return false;
@ -1029,6 +1079,75 @@ bool xpc::GlobalProperties::DefineInSandbox(JSContext* cx,
return Define(cx, obj);
}
/**
* If enabled, apply the extension base CSP, then apply the
* content script CSP which will either be a default or one
* provided by the extension in its manifest.
*/
nsresult ApplyAddonContentScriptCSP(nsISupports* prinOrSop) {
if (!StaticPrefs::extensions_content_script_csp_enabled()) {
return NS_OK;
}
nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(prinOrSop);
if (!principal) {
return NS_OK;
}
auto* basePrin = BasePrincipal::Cast(principal);
// We only get an addonPolicy if the principal is an
// expanded principal with an extension principal in it.
auto* addonPolicy = basePrin->ContentScriptAddonPolicy();
if (!addonPolicy) {
return NS_OK;
}
nsString url;
MOZ_TRY_VAR(url, addonPolicy->GetURL(NS_LITERAL_STRING("")));
nsCOMPtr<nsIURI> selfURI;
MOZ_TRY(NS_NewURI(getter_AddRefs(selfURI), url));
nsAutoString baseCSP;
MOZ_ALWAYS_SUCCEEDS(
ExtensionPolicyService::GetSingleton().GetBaseCSP(baseCSP));
// If we got here, we're definitly an expanded principal.
auto expanded = basePrin->As<ExpandedPrincipal>();
nsCOMPtr<nsIContentSecurityPolicy> csp;
#ifdef MOZ_DEBUG
// Bug 1548468: Move CSP off ExpandedPrincipal
expanded->GetCsp(getter_AddRefs(csp));
if (csp) {
uint32_t count = 0;
csp->GetPolicyCount(&count);
if (count > 0) {
// Ensure that the policy was not already added.
nsAutoString parsedPolicyStr;
for (uint32_t i = 0; i < count; i++) {
csp->GetPolicyString(i, parsedPolicyStr);
MOZ_ASSERT(!parsedPolicyStr.Equals(baseCSP));
}
}
}
#endif
csp = new nsCSPContext();
MOZ_TRY(
csp->SetRequestContextWithPrincipal(expanded, selfURI, EmptyString(), 0));
bool reportOnly = StaticPrefs::extensions_content_script_csp_report_only();
MOZ_TRY(csp->AppendPolicy(baseCSP, reportOnly, false));
// Set default or extension provided csp.
const nsAString& contentScriptCSP = addonPolicy->ContentScriptCSP();
MOZ_TRY(csp->AppendPolicy(contentScriptCSP, reportOnly, false));
expanded->SetCsp(csp);
return NS_OK;
}
nsresult xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp,
nsISupports* prinOrSop,
SandboxOptions& options) {
@ -1111,8 +1230,6 @@ nsresult xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp,
MOZ_RELEASE_ASSERT(priv->allowWaivers == options.allowWaivers);
MOZ_RELEASE_ASSERT(priv->isWebExtensionContentScript ==
options.isWebExtensionContentScript);
MOZ_RELEASE_ASSERT(priv->isContentXBLCompartment ==
options.isContentXBLScope);
MOZ_RELEASE_ASSERT(priv->isUAWidgetCompartment == options.isUAWidgetScope);
MOZ_RELEASE_ASSERT(priv->hasExclusiveExpandos == hasExclusiveExpandos);
MOZ_RELEASE_ASSERT(priv->wantXrays == wantXrays);
@ -1120,7 +1237,6 @@ nsresult xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp,
CompartmentPrivate* priv = CompartmentPrivate::Get(sandbox);
priv->allowWaivers = options.allowWaivers;
priv->isWebExtensionContentScript = options.isWebExtensionContentScript;
priv->isContentXBLCompartment = options.isContentXBLScope;
priv->isUAWidgetCompartment = options.isUAWidgetScope;
priv->hasExclusiveExpandos = hasExclusiveExpandos;
priv->wantXrays = wantXrays;
@ -1779,6 +1895,8 @@ nsresult nsXPCComponents_utils_Sandbox::CallOrConstruct(
} else {
ok = GetExpandedPrincipal(cx, obj, options, getter_AddRefs(expanded));
prinOrSop = expanded;
// If this is an addon content script we need to apply the csp.
MOZ_TRY(ApplyAddonContentScriptCSP(prinOrSop));
}
} else {
ok = GetPrincipalOrSOP(cx, obj, getter_AddRefs(prinOrSop));

View File

@ -200,7 +200,6 @@ CompartmentPrivate::CompartmentPrivate(
wantXrays(false),
allowWaivers(true),
isWebExtensionContentScript(false),
isContentXBLCompartment(false),
isUAWidgetCompartment(false),
hasExclusiveExpandos(false),
wasShutdown(false),
@ -497,20 +496,6 @@ Scriptability& Scriptability::Get(JSObject* aScope) {
return RealmPrivate::Get(aScope)->scriptability;
}
bool IsContentXBLCompartment(JS::Compartment* compartment) {
// We always eagerly create compartment privates for content XBL compartments.
CompartmentPrivate* priv = CompartmentPrivate::Get(compartment);
return priv && priv->isContentXBLCompartment;
}
bool IsContentXBLScope(JS::Realm* realm) {
return IsContentXBLCompartment(JS::GetCompartmentForRealm(realm));
}
bool IsInContentXBLScope(JSObject* obj) {
return IsContentXBLCompartment(JS::GetCompartment(obj));
}
bool IsUAWidgetCompartment(JS::Compartment* compartment) {
// We always eagerly create compartment privates for UA Widget compartments.
CompartmentPrivate* priv = CompartmentPrivate::Get(compartment);
@ -2075,11 +2060,7 @@ class OrphanReporter : public JS::ObjectPrivateVisitor {
virtual size_t sizeOfIncludingThis(nsISupports* aSupports) override {
nsCOMPtr<nsINode> node = do_QueryInterface(aSupports);
// https://bugzilla.mozilla.org/show_bug.cgi?id=773533#c11 explains that we
// have to skip XBL elements because they violate certain assumptions. Yuk.
if (!node || node->IsInComposedDoc() ||
(node->IsElement() &&
node->AsElement()->IsInNamespace(kNameSpaceID_XBL))) {
if (!node || node->IsInComposedDoc()) {
return 0;
}

View File

@ -1014,7 +1014,7 @@ static bool GetCurrentWorkingDirectory(nsAString& workingDirectory) {
// size back down to the actual string length
cwd.SetLength(strlen(result) + 1);
cwd.Replace(cwd.Length() - 1, 1, '/');
workingDirectory = NS_ConvertUTF8toUTF16(cwd);
CopyUTF8toUTF16(cwd, workingDirectory);
#endif
return true;
}

View File

@ -173,19 +173,6 @@ bool XPCWrappedNativeScope::AttachComponentsObject(JSContext* aCx) {
return true;
}
JSObject* XPCWrappedNativeScope::EnsureContentXBLScope(JSContext* cx) {
JS::RootedObject global(cx, CurrentGlobalOrNull(cx));
MOZ_ASSERT(js::IsObjectInContextCompartment(global, cx));
MOZ_ASSERT(!IsContentXBLScope());
MOZ_ASSERT(strcmp(js::GetObjectClass(global)->name,
"nsXBLPrototypeScript compilation scope"));
// We can probably remove EnsureContentXBLScope and clean up all its callers,
// but a bunch (all?) of those callers will just go away when we remove XBL
// support, so it's simpler to just leave it here as a no-op.
return global;
}
bool XPCWrappedNativeScope::XBLScopeStateMatches(nsIPrincipal* aPrincipal) {
return mAllowContentXBLScope ==
!RemoteXULForbidsXBLScopeForPrincipal(aPrincipal);
@ -199,19 +186,6 @@ bool XPCWrappedNativeScope::AllowContentXBLScope(Realm* aRealm) {
}
namespace xpc {
JSObject* GetXBLScope(JSContext* cx, JSObject* contentScopeArg) {
JS::RootedObject contentScope(cx, contentScopeArg);
JSAutoRealm ar(cx, contentScope);
XPCWrappedNativeScope* nativeScope = ObjectScope(contentScope);
RootedObject scope(cx, nativeScope->EnsureContentXBLScope(cx));
NS_ENSURE_TRUE(scope, nullptr); // See bug 858642.
scope = js::UncheckedUnwrap(scope);
JS::ExposeObjectToActiveJS(scope);
return scope;
}
JSObject* GetUAWidgetScope(JSContext* cx, JSObject* contentScopeArg) {
JS::RootedObject contentScope(cx, contentScopeArg);
JSAutoRealm ar(cx, contentScope);

View File

@ -909,17 +909,10 @@ void SetLocationForGlobal(JSObject* global, nsIURI* locationURI) {
} // namespace xpc
static nsresult WriteScriptOrFunction(nsIObjectOutputStream* stream,
JSContext* cx, JSScript* scriptArg,
HandleObject functionObj) {
// Exactly one of script or functionObj must be given
MOZ_ASSERT(!scriptArg != !functionObj);
NS_IMETHODIMP
nsXPConnect::WriteScript(nsIObjectOutputStream* stream, JSContext* cx,
JSScript* scriptArg) {
RootedScript script(cx, scriptArg);
if (!script) {
RootedFunction fun(cx, JS_GetObjectFunction(functionObj));
script.set(JS_GetFunctionScript(cx, fun));
}
uint8_t flags = 0; // We don't have flags anymore.
nsresult rv = stream->Write8(flags);
@ -929,13 +922,7 @@ static nsresult WriteScriptOrFunction(nsIObjectOutputStream* stream,
TranscodeBuffer buffer;
TranscodeResult code;
{
if (functionObj) {
code = EncodeInterpretedFunction(cx, buffer, functionObj);
} else {
code = EncodeScript(cx, buffer, script);
}
}
code = EncodeScript(cx, buffer, script);
if (code != TranscodeResult::Ok) {
if (code == TranscodeResult::Throw) {
@ -960,14 +947,10 @@ static nsresult WriteScriptOrFunction(nsIObjectOutputStream* stream,
return rv;
}
static nsresult ReadScriptOrFunction(nsIObjectInputStream* stream,
JSContext* cx,
const JS::ReadOnlyCompileOptions& options,
JSScript** scriptp,
JSObject** functionObjp) {
// Exactly one of script or functionObj must be given
MOZ_ASSERT(!scriptp != !functionObjp);
NS_IMETHODIMP
nsXPConnect::ReadScript(nsIObjectInputStream* stream, JSContext* cx,
const JS::ReadOnlyCompileOptions& options,
JSScript** scriptp) {
uint8_t flags;
nsresult rv = stream->Read8(&flags);
if (NS_FAILED(rv)) {
@ -1001,27 +984,14 @@ static nsresult ReadScriptOrFunction(nsIObjectInputStream* stream,
{
TranscodeResult code;
if (scriptp) {
Rooted<JSScript*> script(cx);
code = DecodeScript(cx, options, buffer, &script);
if (code == TranscodeResult::Ok) {
*scriptp = script.get();
} else {
if (code == TranscodeResult::Throw) {
JS_ClearPendingException(cx);
return NS_ERROR_OUT_OF_MEMORY;
}
}
Rooted<JSScript*> script(cx);
code = DecodeScript(cx, options, buffer, &script);
if (code == TranscodeResult::Ok) {
*scriptp = script.get();
} else {
Rooted<JSFunction*> funobj(cx);
code = DecodeInterpretedFunction(cx, options, buffer, &funobj);
if (code == TranscodeResult::Ok) {
*functionObjp = JS_GetFunctionObject(funobj.get());
} else {
if (code == TranscodeResult::Throw) {
JS_ClearPendingException(cx);
return NS_ERROR_OUT_OF_MEMORY;
}
if (code == TranscodeResult::Throw) {
JS_ClearPendingException(cx);
return NS_ERROR_OUT_OF_MEMORY;
}
}
@ -1032,34 +1002,6 @@ static nsresult ReadScriptOrFunction(nsIObjectInputStream* stream,
return rv;
}
NS_IMETHODIMP
nsXPConnect::WriteScript(nsIObjectOutputStream* stream, JSContext* cx,
JSScript* script) {
return WriteScriptOrFunction(stream, cx, script, nullptr);
}
NS_IMETHODIMP
nsXPConnect::ReadScript(nsIObjectInputStream* stream, JSContext* cx,
const JS::ReadOnlyCompileOptions& options,
JSScript** scriptp) {
return ReadScriptOrFunction(stream, cx, options, scriptp, nullptr);
}
NS_IMETHODIMP
nsXPConnect::WriteFunction(nsIObjectOutputStream* stream, JSContext* cx,
JSObject* functionObjArg) {
RootedObject functionObj(cx, functionObjArg);
return WriteScriptOrFunction(stream, cx, nullptr, functionObj);
}
NS_IMETHODIMP
nsXPConnect::ReadFunction(nsIObjectInputStream* stream, JSContext* cx,
JSObject** functionObjp) {
JS::CompileOptions compileOptions(cx);
return ReadScriptOrFunction(stream, cx, compileOptions, nullptr,
functionObjp);
}
NS_IMETHODIMP
nsXPConnect::GetIsShuttingDown(bool* aIsShuttingDown) {
if (!aIsShuttingDown) {
@ -1144,8 +1086,7 @@ bool IsChromeOrXBL(JSContext* cx, JSObject* /* unused */) {
// Note that, for performance, we don't check AllowXULXBLForPrincipal here,
// and instead rely on the fact that AllowContentXBLScope() only returns false
// in remote XUL situations.
return AccessCheck::isChrome(c) || IsContentXBLCompartment(c) ||
!AllowContentXBLScope(realm);
return AccessCheck::isChrome(c) || !AllowContentXBLScope(realm);
}
bool IsNotUAWidget(JSContext* cx, JSObject* /* unused */) {

View File

@ -60,7 +60,6 @@ XPC_MSG_DEF(NS_ERROR_XPC_BAD_INITIALIZER_NAME , "Bad initializer name
XPC_MSG_DEF(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN , "Operation failed because the XPConnect subsystem has been shutdown")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN , "Cannot modify properties of a WrappedNative")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL , "Could not convert JavaScript argument - 0 was passed, expected object. Did you mean null?")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_PASS_CPOW_TO_NATIVE , "It's illegal to pass a CPOW to native code")
/* common global codes (from nsError.h) */

View File

@ -880,12 +880,6 @@ class XPCWrappedNativeScope final
void AddSizeOfIncludingThis(JSContext* cx, ScopeSizeInfo* scopeSizeInfo);
// Gets the appropriate scope object for XBL in this compartment. This method
// relies on compartment-per-global still (and release-asserts this). The
// context must be same-realm with this compartment's single global upon
// entering, and the scope object is wrapped into this compartment.
JSObject* EnsureContentXBLScope(JSContext* cx);
// Check whether our mAllowContentXBLScope state matches the given
// principal. This is used to avoid sharing compartments on
// mismatch.
@ -906,9 +900,6 @@ class XPCWrappedNativeScope final
return js::GetFirstGlobalInCompartment(Compartment());
}
bool IsContentXBLScope() {
return xpc::IsContentXBLCompartment(Compartment());
}
bool AllowContentXBLScope(JS::Realm* aRealm);
// ID Object prototype caches.
@ -2296,6 +2287,7 @@ struct GlobalProperties {
bool caches : 1;
bool crypto : 1;
bool fetch : 1;
bool structuredClone : 1;
bool indexedDB : 1;
bool rtcIdentityProvider : 1;
@ -2346,7 +2338,6 @@ class MOZ_STACK_CLASS SandboxOptions : public OptionsBase {
sameZoneAs(cx),
freshCompartment(false),
freshZone(false),
isContentXBLScope(false),
isUAWidgetScope(false),
invisibleToDebugger(false),
discardSource(false),
@ -2366,7 +2357,6 @@ class MOZ_STACK_CLASS SandboxOptions : public OptionsBase {
JS::RootedObject sameZoneAs;
bool freshCompartment;
bool freshZone;
bool isContentXBLScope;
bool isUAWidgetScope;
bool invisibleToDebugger;
bool discardSource;
@ -2644,8 +2634,7 @@ class CompartmentPrivate {
// Don't share if we have any weird state set.
return !wantXrays && !isWebExtensionContentScript &&
!isContentXBLCompartment && !isUAWidgetCompartment &&
mScope->XBLScopeStateMatches(principal);
!isUAWidgetCompartment && mScope->XBLScopeStateMatches(principal);
}
CompartmentOriginInfo originInfo;
@ -2665,10 +2654,6 @@ class CompartmentPrivate {
// receives various bits of special compatibility behavior.
bool isWebExtensionContentScript;
// True if this compartment is a content XBL compartment. Every global in
// such a compartment is a content XBL scope.
bool isContentXBLCompartment;
// True if this compartment is a UA widget compartment.
bool isUAWidgetCompartment;

View File

@ -110,10 +110,6 @@ JSObject* TransplantObjectRetainingXrayExpandos(JSContext* cx,
JS::HandleObject origobj,
JS::HandleObject target);
bool IsContentXBLCompartment(JS::Compartment* compartment);
bool IsContentXBLScope(JS::Realm* realm);
bool IsInContentXBLScope(JSObject* obj);
bool IsUAWidgetCompartment(JS::Compartment* compartment);
bool IsUAWidgetScope(JS::Realm* realm);
bool IsInUAWidgetScope(JSObject* obj);
@ -122,33 +118,10 @@ bool MightBeWebContentCompartment(JS::Compartment* compartment);
void SetCompartmentChangedDocumentDomain(JS::Compartment* compartment);
// Return a raw XBL scope object corresponding to contentScope, which must
// be an object whose global is a DOM window.
//
// The return value is not wrapped into cx->compartment, so be sure to enter
// its compartment before doing anything meaningful.
//
// Also note that XBL scopes are lazily created, so the return-value should be
// null-checked unless the caller can ensure that the scope must already
// exist.
//
// This function asserts if |contentScope| is itself in an XBL scope to catch
// sloppy consumers. Conversely, GetXBLScopeOrGlobal will handle objects that
// are in XBL scope (by just returning the global).
JSObject* GetXBLScope(JSContext* cx, JSObject* contentScope);
JSObject* GetUAWidgetScope(JSContext* cx, nsIPrincipal* principal);
JSObject* GetUAWidgetScope(JSContext* cx, JSObject* contentScope);
inline JSObject* GetXBLScopeOrGlobal(JSContext* cx, JSObject* obj) {
MOZ_ASSERT(!js::IsCrossCompartmentWrapper(obj));
if (IsInContentXBLScope(obj)) {
return JS::GetNonCCWObjectGlobal(obj);
}
return GetXBLScope(cx, obj);
}
// Returns whether XBL scopes have been explicitly disabled for code running
// in this compartment. See the comment around mAllowContentXBLScope.
bool AllowContentXBLScope(JS::Realm* realm);

View File

@ -1,11 +1,10 @@
[DEFAULT]
skip-if = os == 'android'
support-files =
bug503926.xul
bug503926.xhtml
file_bug484459.html
file_bug618176.xul
file_bug618176.xhtml
file_bug996069.html
file_bug1050049.xml
file_bug1281071.html
file_discardSystemSource.html
file_empty.html
@ -22,7 +21,6 @@ support-files =
!/js/xpconnect/tests/mochitest/file_bug738244.html
!/js/xpconnect/tests/mochitest/file_bug760131.html
!/js/xpconnect/tests/mochitest/file_bug795275.html
!/js/xpconnect/tests/mochitest/file_bug795275.xml
!/js/xpconnect/tests/mochitest/file_bug799348.html
!/js/xpconnect/tests/mochitest/file_bug860494.html
!/js/xpconnect/tests/mochitest/file_documentdomain.html
@ -37,92 +35,91 @@ prefs =
javascript.options.experimental.private_fields=true
javascript.options.large_arraybuffers=true
[test_APIExposer.xul]
[test_bug361111.xul]
[test_bug448587.xul]
[test_bug484459.xul]
[test_APIExposer.xhtml]
[test_bug361111.xhtml]
[test_bug448587.xhtml]
[test_bug484459.xhtml]
skip-if = os == 'win' || os == 'mac' || (os == 'linux' && !debug) # bug 1131110, 1255284
[test_bug500931.xul]
[test_bug503926.xul]
[test_bug533596.xul]
[test_bug571849.xul]
[test_bug596580.xul]
[test_bug610390.xul]
[test_bug614757.xul]
[test_bug616992.xul]
[test_bug618176.xul]
[test_bug654370.xul]
[test_bug658560.xul]
[test_bug658909.xul]
[test_bug664689.xul]
[test_bug679861.xul]
[test_bug706301.xul]
[test_bug726949.xul]
[test_bug732665.xul]
[test_bug738244.xul]
[test_bug743843.xul]
[test_bug760076.xul]
[test_bug500931.xhtml]
[test_bug503926.xhtml]
[test_bug533596.xhtml]
[test_bug571849.xhtml]
[test_bug596580.xhtml]
[test_bug610390.xhtml]
[test_bug614757.xhtml]
[test_bug616992.xhtml]
[test_bug618176.xhtml]
[test_bug654370.xhtml]
[test_bug658560.xhtml]
[test_bug658909.xhtml]
[test_bug664689.xhtml]
[test_bug679861.xhtml]
[test_bug706301.xhtml]
[test_bug726949.xhtml]
[test_bug732665.xhtml]
[test_bug738244.xhtml]
[test_bug743843.xhtml]
[test_bug760076.xhtml]
[test_bug760131.html]
[test_bug763343.xul]
[test_bug771429.xul]
[test_bug773962.xul]
[test_bug792280.xul]
[test_bug793433.xul]
[test_bug795275.xul]
[test_bug799348.xul]
[test_bug801241.xul]
[test_bug812415.xul]
[test_bug853283.xul]
[test_bug853571.xul]
[test_bug858101.xul]
[test_bug860494.xul]
[test_bug865948.xul]
[test_bug866823.xul]
[test_bug895340.xul]
[test_bug932906.xul]
[test_bug996069.xul]
[test_bug1041626.xul]
[test_bug1042436.xul]
[test_bug1050049.html]
[test_bug763343.xhtml]
[test_bug771429.xhtml]
[test_bug773962.xhtml]
[test_bug792280.xhtml]
[test_bug793433.xhtml]
[test_bug795275.xhtml]
[test_bug799348.xhtml]
[test_bug801241.xhtml]
[test_bug812415.xhtml]
[test_bug853283.xhtml]
[test_bug853571.xhtml]
[test_bug858101.xhtml]
[test_bug860494.xhtml]
[test_bug865948.xhtml]
[test_bug866823.xhtml]
[test_bug895340.xhtml]
[test_bug932906.xhtml]
[test_bug996069.xhtml]
[test_bug1041626.xhtml]
[test_bug1042436.xhtml]
[test_bug1065185.html]
[test_bug1074863.html]
[test_bug1092477.xul]
[test_bug1092477.xhtml]
[test_bug1124898.html]
[test_bug1126911.html]
[test_bug1281071.xul]
[test_bug1390159.xul]
[test_bug1281071.xhtml]
[test_bug1390159.xhtml]
[test_bug1430164.html]
[test_bug1516237.html]
[test_chrometoSource.xul]
[test_cloneInto.xul]
[test_cows.xul]
[test_chrometoSource.xhtml]
[test_cloneInto.xhtml]
[test_cows.xhtml]
[test_private_field_cows.xhtml]
[test_discardSystemSource.xul]
[test_documentdomain.xul]
[test_doublewrappedcompartments.xul]
[test_evalInSandbox.xul]
[test_evalInWindow.xul]
[test_exnstack.xul]
[test_expandosharing.xul]
[test_exposeInDerived.xul]
[test_localstorage_with_nsEp.xul]
[test_matches.xul]
[test_nodelists.xul]
[test_discardSystemSource.xhtml]
[test_documentdomain.xhtml]
[test_doublewrappedcompartments.xhtml]
[test_evalInSandbox.xhtml]
[test_evalInWindow.xhtml]
[test_exnstack.xhtml]
[test_expandosharing.xhtml]
[test_exposeInDerived.xhtml]
[test_localstorage_with_nsEp.xhtml]
[test_matches.xhtml]
[test_nodelists.xhtml]
[test_nsScriptErrorWithStack.html]
[test_onGarbageCollection.html]
[test_precisegc.xul]
[test_sandboxImport.xul]
[test_scriptSettings.xul]
[test_precisegc.xhtml]
[test_sandboxImport.xhtml]
[test_scriptSettings.xhtml]
[test_scripterror.html]
[test_sharedChromeCompartment.html]
[test_weakmap_keys_preserved.xul]
[test_weakmap_keys_preserved2.xul]
[test_weakref.xul]
[test_weakmap_keys_preserved.xhtml]
[test_weakmap_keys_preserved2.xhtml]
[test_weakref.xhtml]
[test_windowProxyDeadWrapper.html]
[test_wrappers.xul]
[test_xrayic.xul]
[test_wrappers.xhtml]
[test_xrayic.xhtml]
[test_xrayLargeTypedArray.html]
skip-if = bits == 32 # Large ArrayBuffers not supported on 32-bit.
[test_xrayToJS.xul]
[test_xrayToJS.xhtml]
[test_bug1530146.html]
support-files = file_bug1530146.html file_bug1530146_inner.html

View File

@ -1,10 +0,0 @@
<?xml version="1.0"?>
<bindings id="testBindings" xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml">
<binding id="regularChromeBinding">
<content><html:p>Anonymous Paragraph</html:p></content>
</binding>
<binding id="whitelistedChromeBinding" bindToUntrustedContent="true">
<content><html:p>Anonymous Paragraph</html:p></content>
</binding>
</bindings>

View File

@ -1,56 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1050049
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1050049</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://global/skin"/>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 1050049 **/
SimpleTest.waitForExplicitFinish();
var regularBindingURI = window.location.toString().replace("test_bug1050049.html", "file_bug1050049.xml") + "#regularChromeBinding";
var whitelistedBindingURI = window.location.toString().replace("test_bug1050049.html", "file_bug1050049.xml") + "#whitelistedChromeBinding";
function testApplyBinding(doc, bindingURI, expectBind) {
var d = doc.createElement('div');
doc.body.appendChild(d);
d.style.MozBinding = "url(" + bindingURI + ")";
return new Promise(function(resolve, reject) {
// Wait two ticks of the refresh driver for the binding to be applied.
function onceBindingWouldBeApplied() {
is(!!doc.getAnonymousNodes(d), expectBind, "Binding " + (expectBind ? "should" : "shouldn't") +
" be applied: " + bindingURI + ", " + doc.location);
resolve();
}
window.requestAnimationFrame(function() { window.requestAnimationFrame(onceBindingWouldBeApplied); });
});
}
function go() {
testApplyBinding(document, regularBindingURI, true)
.then(testApplyBinding.bind(null, window[0].document, regularBindingURI, false))
.then(testApplyBinding.bind(null, document, whitelistedBindingURI, true))
.then(testApplyBinding.bind(null, window[0].document, whitelistedBindingURI, true))
.then(SimpleTest.finish.bind(SimpleTest));
}
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1050049">Mozilla Bug 1050049</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<iframe onload="go();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html"></iframe>
</body>
</html>

View File

@ -18,7 +18,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=448587.xul
<script type="application/javascript">
<![CDATA[
// Bonus test - collaborate with test_bug361111.xul to make sure that
// Bonus test - collaborate with test_bug361111.xhtml to make sure that
// flushPrefEnv is appropriately called.
ok(!SpecialPowers.Services.prefs.prefHasUserValue('testing.some_arbitrary_pref'),
"Pref shouldn't carry over from previous test!");

View File

@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=484459
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
SimpleTest.waitForExplicitFinish();
var url = "chrome://mochitests/content/chrome/js/xpconnect/tests/chrome/test_bug484459.xul";
var url = "chrome://mochitests/content/chrome/js/xpconnect/tests/chrome/test_bug484459.xhtml";
function go() {
var w = $('ifr').contentWindow.wrappedJSObject;
var sandbox = new Cu.Sandbox(w);

View File

@ -13,7 +13,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=503926
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=503926"
target="_blank">Mozilla Bug 503926</a>
<iframe id="ifr" type="content" onload="loaded()" src="bug503926.xul#iframe"/>
<iframe id="ifr" type="content" onload="loaded()" src="bug503926.xhtml#iframe"/>
<iframe id="ifrContent" type="content" onload="loaded()" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html"/>
</body>
@ -47,7 +47,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=503926
ok(!contentWin.passed, "untrusted QI should not be called");
// Try with a dialog.
openDialog("bug503926.xul", "chromeDialog", "modal");
openDialog("bug503926.xhtml", "chromeDialog", "modal");
SimpleTest.finish();
}

View File

@ -24,7 +24,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=618176
}
addLoadEvent(function() {
window.open("file_bug618176.xul", "", "chrome");
window.open("file_bug618176.xhtml", "", "chrome");
});
]]></script>
</window>

Some files were not shown because too many files have changed in this diff Show More