зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 12 changesets (bug 1165486) for windows spidermonkey failures CLOSED TREE
Backed out changeset ce3c302864bf (bug 1165486) Backed out changeset f69852001c61 (bug 1165486) Backed out changeset 06cc09729bf4 (bug 1165486) Backed out changeset 52772afc023e (bug 1165486) Backed out changeset 502ddf7d2268 (bug 1165486) Backed out changeset b04ab7bd78af (bug 1165486) Backed out changeset 53fcddbe4cfb (bug 1165486) Backed out changeset 63bd369e5349 (bug 1165486) Backed out changeset 1e35269a8062 (bug 1165486) Backed out changeset e3c11d517e18 (bug 1165486) Backed out changeset ccd90228daf6 (bug 1165486) Backed out changeset eb11e655d223 (bug 1165486)
This commit is contained in:
Родитель
76d8ba0697
Коммит
9dceeed482
|
@ -1788,7 +1788,8 @@ nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We're going to run these against some non-global scope.
|
// We're going to run these against some non-global scope.
|
||||||
if (!JS::CompileForNonSyntacticScope(cx, options, srcBuf, &script)) {
|
options.setHasPollutedScope(true);
|
||||||
|
if (!JS::Compile(cx, options, srcBuf, &script)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,18 @@ TryEvalJSON(JSContext* cx, JSLinearString* str, MutableHandleValue rval)
|
||||||
: ParseEvalStringAsJSON(cx, linearChars.twoByteRange(), rval);
|
: ParseEvalStringAsJSON(cx, linearChars.twoByteRange(), rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
HasPollutedScopeChain(JSObject* scopeChain)
|
||||||
|
{
|
||||||
|
while (scopeChain) {
|
||||||
|
if (scopeChain->is<DynamicWithObject>())
|
||||||
|
return true;
|
||||||
|
scopeChain = scopeChain->enclosingScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Define subset of ExecuteType so that casting performs the injection.
|
// Define subset of ExecuteType so that casting performs the injection.
|
||||||
enum EvalType { DIRECT_EVAL = EXECUTE_DIRECT_EVAL, INDIRECT_EVAL = EXECUTE_INDIRECT_EVAL };
|
enum EvalType { DIRECT_EVAL = EXECUTE_DIRECT_EVAL, INDIRECT_EVAL = EXECUTE_INDIRECT_EVAL };
|
||||||
|
|
||||||
|
@ -314,8 +326,13 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame
|
||||||
if (!staticScope)
|
if (!staticScope)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
bool hasPollutedGlobalScope =
|
||||||
|
HasPollutedScopeChain(scopeobj) ||
|
||||||
|
(evalType == DIRECT_EVAL && callerScript->hasPollutedGlobalScope());
|
||||||
|
|
||||||
CompileOptions options(cx);
|
CompileOptions options(cx);
|
||||||
options.setFileAndLine(filename, 1)
|
options.setFileAndLine(filename, 1)
|
||||||
|
.setHasPollutedScope(hasPollutedGlobalScope)
|
||||||
.setIsRunOnce(true)
|
.setIsRunOnce(true)
|
||||||
.setForEval(true)
|
.setForEval(true)
|
||||||
.setNoScriptRval(false)
|
.setNoScriptRval(false)
|
||||||
|
@ -333,7 +350,7 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame
|
||||||
: SourceBufferHolder::NoOwnership;
|
: SourceBufferHolder::NoOwnership;
|
||||||
SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
|
SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
|
||||||
JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
|
JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
|
||||||
scopeobj, staticScope, callerScript,
|
scopeobj, callerScript, staticScope,
|
||||||
options, srcBuf, linearStr, staticLevel);
|
options, srcBuf, linearStr, staticLevel);
|
||||||
if (!compiled)
|
if (!compiled)
|
||||||
return false;
|
return false;
|
||||||
|
@ -387,7 +404,7 @@ js::DirectEvalStringFromIon(JSContext* cx,
|
||||||
bool mutedErrors;
|
bool mutedErrors;
|
||||||
uint32_t pcOffset;
|
uint32_t pcOffset;
|
||||||
DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
|
DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
|
||||||
&mutedErrors, CALLED_FROM_JSOP_EVAL);
|
&mutedErrors, CALLED_FROM_JSOP_EVAL);
|
||||||
|
|
||||||
const char* introducerFilename = filename;
|
const char* introducerFilename = filename;
|
||||||
if (maybeScript && maybeScript->scriptSource()->introducerFilename())
|
if (maybeScript && maybeScript->scriptSource()->introducerFilename())
|
||||||
|
@ -400,6 +417,8 @@ js::DirectEvalStringFromIon(JSContext* cx,
|
||||||
|
|
||||||
CompileOptions options(cx);
|
CompileOptions options(cx);
|
||||||
options.setFileAndLine(filename, 1)
|
options.setFileAndLine(filename, 1)
|
||||||
|
.setHasPollutedScope(HasPollutedScopeChain(scopeobj) ||
|
||||||
|
callerScript->hasPollutedGlobalScope())
|
||||||
.setIsRunOnce(true)
|
.setIsRunOnce(true)
|
||||||
.setForEval(true)
|
.setForEval(true)
|
||||||
.setNoScriptRval(false)
|
.setNoScriptRval(false)
|
||||||
|
@ -417,7 +436,7 @@ js::DirectEvalStringFromIon(JSContext* cx,
|
||||||
: SourceBufferHolder::NoOwnership;
|
: SourceBufferHolder::NoOwnership;
|
||||||
SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
|
SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
|
||||||
JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
|
JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
|
||||||
scopeobj, staticScope, callerScript,
|
scopeobj, callerScript, staticScope,
|
||||||
options, srcBuf, linearStr, staticLevel);
|
options, srcBuf, linearStr, staticLevel);
|
||||||
if (!compiled)
|
if (!compiled)
|
||||||
return false;
|
return false;
|
||||||
|
@ -488,31 +507,35 @@ js::ExecuteInGlobalAndReturnScope(JSContext* cx, HandleObject global, HandleScri
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
assertSameCompartment(cx, global);
|
assertSameCompartment(cx, global);
|
||||||
MOZ_ASSERT(global->is<GlobalObject>());
|
MOZ_ASSERT(global->is<GlobalObject>());
|
||||||
MOZ_RELEASE_ASSERT(scriptArg->hasNonSyntacticScope());
|
MOZ_RELEASE_ASSERT(scriptArg->hasPollutedGlobalScope());
|
||||||
|
|
||||||
RootedScript script(cx, scriptArg);
|
RootedScript script(cx, scriptArg);
|
||||||
if (script->compartment() != cx->compartment()) {
|
if (script->compartment() != cx->compartment()) {
|
||||||
Rooted<ScopeObject*> staticScope(cx, StaticNonSyntacticScopeObjects::create(cx, nullptr));
|
script = CloneScript(cx, nullptr, nullptr, script);
|
||||||
if (!staticScope)
|
|
||||||
return false;
|
|
||||||
script = CloneGlobalScript(cx, staticScope, script);
|
|
||||||
if (!script)
|
if (!script)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Debugger::onNewScript(cx, script);
|
Debugger::onNewScript(cx, script);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rooted<GlobalObject*> globalRoot(cx, &global->as<GlobalObject>());
|
RootedObject scope(cx, JS_NewPlainObject(cx));
|
||||||
Rooted<ScopeObject*> scope(cx, NonSyntacticVariablesObject::create(cx, globalRoot));
|
|
||||||
if (!scope)
|
if (!scope)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!scope->setQualifiedVarObj(cx))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!scope->setUnqualifiedVarObj(cx))
|
||||||
|
return false;
|
||||||
|
|
||||||
JSObject* thisobj = GetThisObject(cx, global);
|
JSObject* thisobj = GetThisObject(cx, global);
|
||||||
if (!thisobj)
|
if (!thisobj)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
RootedValue thisv(cx, ObjectValue(*thisobj));
|
RootedValue thisv(cx, ObjectValue(*thisobj));
|
||||||
RootedValue rval(cx);
|
RootedValue rval(cx);
|
||||||
|
// XXXbz when this is fixed to pass in an actual ScopeObject, fix
|
||||||
|
// up the assert in js::CloneFunctionObject accordingly.
|
||||||
if (!ExecuteKernel(cx, script, *scope, thisv, UndefinedValue(), EXECUTE_GLOBAL,
|
if (!ExecuteKernel(cx, script, *scope, thisv, UndefinedValue(), EXECUTE_GLOBAL,
|
||||||
NullFramePtr() /* evalInFrame */, rval.address()))
|
NullFramePtr() /* evalInFrame */, rval.address()))
|
||||||
{
|
{
|
||||||
|
|
|
@ -2272,10 +2272,11 @@ EvalReturningScope(JSContext* cx, unsigned argc, jsval* vp)
|
||||||
JS::CompileOptions options(cx);
|
JS::CompileOptions options(cx);
|
||||||
options.setFileAndLine(filename.get(), lineno);
|
options.setFileAndLine(filename.get(), lineno);
|
||||||
options.setNoScriptRval(true);
|
options.setNoScriptRval(true);
|
||||||
|
options.setHasPollutedScope(true);
|
||||||
|
|
||||||
JS::SourceBufferHolder srcBuf(src, srclen, JS::SourceBufferHolder::NoOwnership);
|
JS::SourceBufferHolder srcBuf(src, srclen, JS::SourceBufferHolder::NoOwnership);
|
||||||
RootedScript script(cx);
|
RootedScript script(cx);
|
||||||
if (!JS::CompileForNonSyntacticScope(cx, options, srcBuf, &script))
|
if (!JS::Compile(cx, options, srcBuf, &script))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (global) {
|
if (global) {
|
||||||
|
|
|
@ -144,11 +144,10 @@ MaybeCheckEvalFreeVariables(ExclusiveContext* cxArg, HandleScript evalCaller, Ha
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
CanLazilyParse(ExclusiveContext* cx, HandleObject staticScope,
|
CanLazilyParse(ExclusiveContext* cx, const ReadOnlyCompileOptions& options)
|
||||||
const ReadOnlyCompileOptions& options)
|
|
||||||
{
|
{
|
||||||
return options.canLazilyParse &&
|
return options.canLazilyParse &&
|
||||||
!HasNonSyntacticStaticScopeChain(staticScope) &&
|
!options.hasPollutedGlobalScope &&
|
||||||
!cx->compartment()->options().disableLazyParsing() &&
|
!cx->compartment()->options().disableLazyParsing() &&
|
||||||
!cx->compartment()->options().discardSource() &&
|
!cx->compartment()->options().discardSource() &&
|
||||||
!options.sourceIsLazy;
|
!options.sourceIsLazy;
|
||||||
|
@ -211,8 +210,8 @@ frontend::CreateScriptSourceObject(ExclusiveContext* cx, const ReadOnlyCompileOp
|
||||||
|
|
||||||
JSScript*
|
JSScript*
|
||||||
frontend::CompileScript(ExclusiveContext* cx, LifoAlloc* alloc, HandleObject scopeChain,
|
frontend::CompileScript(ExclusiveContext* cx, LifoAlloc* alloc, HandleObject scopeChain,
|
||||||
Handle<ScopeObject*> enclosingStaticScope,
|
|
||||||
HandleScript evalCaller,
|
HandleScript evalCaller,
|
||||||
|
Handle<StaticEvalObject*> evalStaticScope,
|
||||||
const ReadOnlyCompileOptions& options,
|
const ReadOnlyCompileOptions& options,
|
||||||
SourceBufferHolder& srcBuf,
|
SourceBufferHolder& srcBuf,
|
||||||
JSString* source_ /* = nullptr */,
|
JSString* source_ /* = nullptr */,
|
||||||
|
@ -261,7 +260,7 @@ frontend::CompileScript(ExclusiveContext* cx, LifoAlloc* alloc, HandleObject sco
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canLazilyParse = CanLazilyParse(cx, enclosingStaticScope, options);
|
bool canLazilyParse = CanLazilyParse(cx, options);
|
||||||
|
|
||||||
Maybe<Parser<SyntaxParseHandler> > syntaxParser;
|
Maybe<Parser<SyntaxParseHandler> > syntaxParser;
|
||||||
if (canLazilyParse) {
|
if (canLazilyParse) {
|
||||||
|
@ -285,22 +284,22 @@ frontend::CompileScript(ExclusiveContext* cx, LifoAlloc* alloc, HandleObject sco
|
||||||
|
|
||||||
bool savedCallerFun = evalCaller && evalCaller->functionOrCallerFunction();
|
bool savedCallerFun = evalCaller && evalCaller->functionOrCallerFunction();
|
||||||
Directives directives(options.strictOption);
|
Directives directives(options.strictOption);
|
||||||
GlobalSharedContext globalsc(cx, directives, enclosingStaticScope, options.extraWarningsOption);
|
GlobalSharedContext globalsc(cx, directives, evalStaticScope, options.extraWarningsOption);
|
||||||
|
|
||||||
Rooted<JSScript*> script(cx, JSScript::Create(cx, enclosingStaticScope, savedCallerFun,
|
Rooted<JSScript*> script(cx, JSScript::Create(cx, evalStaticScope, savedCallerFun,
|
||||||
options, staticLevel, sourceObject, 0,
|
options, staticLevel, sourceObject, 0,
|
||||||
srcBuf.length()));
|
srcBuf.length()));
|
||||||
if (!script)
|
if (!script)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
bool insideNonGlobalEval =
|
bool insideNonGlobalEval =
|
||||||
enclosingStaticScope && enclosingStaticScope->is<StaticEvalObject>() &&
|
evalStaticScope && evalStaticScope->enclosingScopeForStaticScopeIter();
|
||||||
enclosingStaticScope->as<StaticEvalObject>().enclosingScopeForStaticScopeIter();
|
|
||||||
BytecodeEmitter::EmitterMode emitterMode =
|
BytecodeEmitter::EmitterMode emitterMode =
|
||||||
options.selfHostingMode ? BytecodeEmitter::SelfHosting : BytecodeEmitter::Normal;
|
options.selfHostingMode ? BytecodeEmitter::SelfHosting : BytecodeEmitter::Normal;
|
||||||
BytecodeEmitter bce(/* parent = */ nullptr, &parser, &globalsc, script,
|
BytecodeEmitter bce(/* parent = */ nullptr, &parser, &globalsc, script,
|
||||||
/* lazyScript = */ nullptr, options.forEval,
|
/* lazyScript = */ nullptr, options.forEval,
|
||||||
evalCaller, insideNonGlobalEval, options.lineno, emitterMode);
|
evalCaller, insideNonGlobalEval,
|
||||||
|
options.lineno, emitterMode);
|
||||||
if (!bce.init())
|
if (!bce.init())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -562,7 +561,7 @@ CompileFunctionBody(JSContext* cx, MutableHandleFunction fun, const ReadOnlyComp
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canLazilyParse = CanLazilyParse(cx, enclosingStaticScope, options);
|
bool canLazilyParse = CanLazilyParse(cx, options);
|
||||||
|
|
||||||
Maybe<Parser<SyntaxParseHandler> > syntaxParser;
|
Maybe<Parser<SyntaxParseHandler> > syntaxParser;
|
||||||
if (canLazilyParse) {
|
if (canLazilyParse) {
|
||||||
|
|
|
@ -17,17 +17,18 @@ class AutoNameVector;
|
||||||
class LazyScript;
|
class LazyScript;
|
||||||
class LifoAlloc;
|
class LifoAlloc;
|
||||||
class ScriptSourceObject;
|
class ScriptSourceObject;
|
||||||
class ScopeObject;
|
class StaticEvalObject;
|
||||||
struct SourceCompressionTask;
|
struct SourceCompressionTask;
|
||||||
|
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
|
|
||||||
JSScript*
|
JSScript*
|
||||||
CompileScript(ExclusiveContext* cx, LifoAlloc* alloc,
|
CompileScript(ExclusiveContext* cx, LifoAlloc* alloc,
|
||||||
HandleObject scopeChain, Handle<ScopeObject*> enclosingStaticScope,
|
HandleObject scopeChain, HandleScript evalCaller,
|
||||||
HandleScript evalCaller, const ReadOnlyCompileOptions& options,
|
Handle<StaticEvalObject*> evalStaticScope,
|
||||||
SourceBufferHolder& srcBuf, JSString* source_ = nullptr,
|
const ReadOnlyCompileOptions& options, SourceBufferHolder& srcBuf,
|
||||||
unsigned staticLevel = 0, SourceCompressionTask* extraSct = nullptr);
|
JSString* source_ = nullptr, unsigned staticLevel = 0,
|
||||||
|
SourceCompressionTask* extraSct = nullptr);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const char16_t* chars, size_t length);
|
CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const char16_t* chars, size_t length);
|
||||||
|
|
|
@ -769,7 +769,7 @@ BytecodeEmitter::enclosingStaticScope()
|
||||||
|
|
||||||
// Top-level eval scripts have a placeholder static scope so that
|
// Top-level eval scripts have a placeholder static scope so that
|
||||||
// StaticScopeIter may iterate through evals.
|
// StaticScopeIter may iterate through evals.
|
||||||
return sc->asGlobalSharedContext()->topStaticScope();
|
return sc->asGlobalSharedContext()->evalStaticScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
return sc->asFunctionBox()->function();
|
return sc->asFunctionBox()->function();
|
||||||
|
@ -1548,14 +1548,14 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn)
|
||||||
// Use generic ops if a catch block is encountered.
|
// Use generic ops if a catch block is encountered.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ssi.hasSyntacticDynamicScopeObject())
|
if (ssi.hasDynamicScopeObject())
|
||||||
hops++;
|
hops++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
RootedScript script(cx, ssi.funScript());
|
RootedScript script(cx, ssi.funScript());
|
||||||
if (script->functionNonDelazifying()->atom() == pn->pn_atom)
|
if (script->functionNonDelazifying()->atom() == pn->pn_atom)
|
||||||
return false;
|
return false;
|
||||||
if (ssi.hasSyntacticDynamicScopeObject()) {
|
if (ssi.hasDynamicScopeObject()) {
|
||||||
uint32_t slot;
|
uint32_t slot;
|
||||||
if (lookupAliasedName(script, pn->pn_atom->asPropertyName(), &slot, pn)) {
|
if (lookupAliasedName(script, pn->pn_atom->asPropertyName(), &slot, pn)) {
|
||||||
JSOp op;
|
JSOp op;
|
||||||
|
@ -1587,9 +1587,9 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn)
|
||||||
if (insideNonGlobalEval)
|
if (insideNonGlobalEval)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Skip trying to use GNAME ops if we know our script has a non-syntactic
|
// Skip trying to use GNAME ops if we know our script has a polluted
|
||||||
// scope, since they'll just get treated as NAME ops anyway.
|
// global scope, since they'll just get treated as NAME ops anyway.
|
||||||
if (script->hasNonSyntacticScope())
|
if (script->hasPollutedGlobalScope())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Deoptimized names also aren't necessarily globals.
|
// Deoptimized names also aren't necessarily globals.
|
||||||
|
@ -2356,14 +2356,13 @@ BytecodeEmitter::checkRunOnceContext()
|
||||||
bool
|
bool
|
||||||
BytecodeEmitter::needsImplicitThis()
|
BytecodeEmitter::needsImplicitThis()
|
||||||
{
|
{
|
||||||
if (sc->inWith())
|
if (sc->isFunctionBox() && sc->asFunctionBox()->inWith)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (StmtInfoBCE* stmt = topStmt; stmt; stmt = stmt->down) {
|
for (StmtInfoBCE* stmt = topStmt; stmt; stmt = stmt->down) {
|
||||||
if (stmt->type == STMT_WITH)
|
if (stmt->type == STMT_WITH)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3407,19 +3406,6 @@ BytecodeEmitter::emitFunctionScript(ParseNode* body)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FunctionBox* funbox = sc->asFunctionBox();
|
FunctionBox* funbox = sc->asFunctionBox();
|
||||||
|
|
||||||
// Link the function and the script to each other, so that StaticScopeIter
|
|
||||||
// may walk the scope chain of currently compiling scripts.
|
|
||||||
RootedFunction fun(cx, funbox->function());
|
|
||||||
MOZ_ASSERT(fun->isInterpreted());
|
|
||||||
|
|
||||||
script->setFunction(fun);
|
|
||||||
|
|
||||||
if (fun->isInterpretedLazy())
|
|
||||||
fun->setUnlazifiedScript(script);
|
|
||||||
else
|
|
||||||
fun->setScript(script);
|
|
||||||
|
|
||||||
if (funbox->argumentsHasLocalBinding()) {
|
if (funbox->argumentsHasLocalBinding()) {
|
||||||
MOZ_ASSERT(offset() == 0); /* See JSScript::argumentsBytecode. */
|
MOZ_ASSERT(offset() == 0); /* See JSScript::argumentsBytecode. */
|
||||||
switchToPrologue();
|
switchToPrologue();
|
||||||
|
@ -3523,6 +3509,15 @@ BytecodeEmitter::emitFunctionScript(ParseNode* body)
|
||||||
MOZ_ASSERT(!script->hasRunOnce());
|
MOZ_ASSERT(!script->hasRunOnce());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize fun->script() so that the debugger has a valid fun->script(). */
|
||||||
|
RootedFunction fun(cx, script->functionNonDelazifying());
|
||||||
|
MOZ_ASSERT(fun->isInterpreted());
|
||||||
|
|
||||||
|
if (fun->isInterpretedLazy())
|
||||||
|
fun->setUnlazifiedScript(script);
|
||||||
|
else
|
||||||
|
fun->setScript(script);
|
||||||
|
|
||||||
tellDebuggerAboutCompiledScript(cx);
|
tellDebuggerAboutCompiledScript(cx);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -5770,6 +5765,8 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
||||||
Rooted<JSScript*> parent(cx, script);
|
Rooted<JSScript*> parent(cx, script);
|
||||||
CompileOptions options(cx, parser->options());
|
CompileOptions options(cx, parser->options());
|
||||||
options.setMutedErrors(parent->mutedErrors())
|
options.setMutedErrors(parent->mutedErrors())
|
||||||
|
.setHasPollutedScope(parent->hasPollutedGlobalScope())
|
||||||
|
.setSelfHostingMode(parent->selfHosted())
|
||||||
.setNoScriptRval(false)
|
.setNoScriptRval(false)
|
||||||
.setForEval(false)
|
.setForEval(false)
|
||||||
.setVersion(parent->getVersion());
|
.setVersion(parent->getVersion());
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
class ScopeObject;
|
class StaticEvalObject;
|
||||||
|
|
||||||
namespace frontend {
|
namespace frontend {
|
||||||
|
|
||||||
|
|
|
@ -596,7 +596,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct
|
||||||
bufEnd(0),
|
bufEnd(0),
|
||||||
length(0),
|
length(0),
|
||||||
generatorKindBits_(GeneratorKindAsBits(generatorKind)),
|
generatorKindBits_(GeneratorKindAsBits(generatorKind)),
|
||||||
inWith_(false), // initialized below
|
inWith(false), // initialized below
|
||||||
inGenexpLambda(false),
|
inGenexpLambda(false),
|
||||||
hasDestructuringArgs(false),
|
hasDestructuringArgs(false),
|
||||||
useAsm(false),
|
useAsm(false),
|
||||||
|
@ -612,7 +612,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct
|
||||||
MOZ_ASSERT(fun->isTenured());
|
MOZ_ASSERT(fun->isTenured());
|
||||||
|
|
||||||
if (!outerpc) {
|
if (!outerpc) {
|
||||||
inWith_ = false;
|
inWith = false;
|
||||||
|
|
||||||
} else if (outerpc->parsingWith) {
|
} else if (outerpc->parsingWith) {
|
||||||
// This covers cases that don't involve eval(). For example:
|
// This covers cases that don't involve eval(). For example:
|
||||||
|
@ -621,7 +621,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct
|
||||||
//
|
//
|
||||||
// In this case, |outerpc| corresponds to global code, and
|
// In this case, |outerpc| corresponds to global code, and
|
||||||
// outerpc->parsingWith is true.
|
// outerpc->parsingWith is true.
|
||||||
inWith_ = true;
|
inWith = true;
|
||||||
|
|
||||||
} else if (outerpc->sc->isFunctionBox()) {
|
} else if (outerpc->sc->isFunctionBox()) {
|
||||||
// This is like the above case, but for more deeply nested functions.
|
// This is like the above case, but for more deeply nested functions.
|
||||||
|
@ -632,17 +632,8 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct
|
||||||
// In this case, the inner anonymous function needs to inherit the
|
// In this case, the inner anonymous function needs to inherit the
|
||||||
// setting of |inWith| from the outer one.
|
// setting of |inWith| from the outer one.
|
||||||
FunctionBox* parent = outerpc->sc->asFunctionBox();
|
FunctionBox* parent = outerpc->sc->asFunctionBox();
|
||||||
if (parent && parent->inWith())
|
if (parent && parent->inWith)
|
||||||
inWith_ = true;
|
inWith = true;
|
||||||
} else {
|
|
||||||
// This is like the above case, but when inside eval.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
//
|
|
||||||
// with(o) { eval("(function() { g(); })();"); }
|
|
||||||
//
|
|
||||||
// In this case, the static scope chain tells us the presence of with.
|
|
||||||
inWith_ = outerpc->sc->inWith();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2224,7 +2215,7 @@ Parser<SyntaxParseHandler>::finishFunctionDefinition(Node pn, FunctionBox* funbo
|
||||||
// while its ParseContext and associated lexdeps and inner functions are
|
// while its ParseContext and associated lexdeps and inner functions are
|
||||||
// still available.
|
// still available.
|
||||||
|
|
||||||
if (funbox->inWith())
|
if (funbox->inWith)
|
||||||
return abortIfSyntaxParser();
|
return abortIfSyntaxParser();
|
||||||
|
|
||||||
size_t numFreeVariables = pc->lexdeps->count();
|
size_t numFreeVariables = pc->lexdeps->count();
|
||||||
|
|
|
@ -235,7 +235,6 @@ class SharedContext
|
||||||
SuperProperty
|
SuperProperty
|
||||||
};
|
};
|
||||||
virtual bool allowSyntax(AllowedSyntax allowed) const = 0;
|
virtual bool allowSyntax(AllowedSyntax allowed) const = 0;
|
||||||
virtual bool inWith() const = 0;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static bool FunctionAllowsSyntax(JSFunction* func, AllowedSyntax allowed)
|
static bool FunctionAllowsSyntax(JSFunction* func, AllowedSyntax allowed)
|
||||||
|
@ -257,13 +256,21 @@ class SharedContext
|
||||||
class GlobalSharedContext : public SharedContext
|
class GlobalSharedContext : public SharedContext
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Handle<ScopeObject*> topStaticScope_;
|
Handle<StaticEvalObject*> staticEvalScope_;
|
||||||
bool allowNewTarget_;
|
|
||||||
bool allowSuperProperty_;
|
|
||||||
bool inWith_;
|
|
||||||
|
|
||||||
bool computeAllowSyntax(AllowedSyntax allowed) const {
|
public:
|
||||||
StaticScopeIter<CanGC> it(context, topStaticScope_);
|
GlobalSharedContext(ExclusiveContext* cx,
|
||||||
|
Directives directives, Handle<StaticEvalObject*> staticEvalScope,
|
||||||
|
bool extraWarnings)
|
||||||
|
: SharedContext(cx, directives, extraWarnings),
|
||||||
|
staticEvalScope_(staticEvalScope)
|
||||||
|
{}
|
||||||
|
|
||||||
|
ObjectBox* toObjectBox() { return nullptr; }
|
||||||
|
HandleObject evalStaticScope() const { return staticEvalScope_; }
|
||||||
|
|
||||||
|
bool allowSyntax(AllowedSyntax allowed) const {
|
||||||
|
StaticScopeIter<CanGC> it(context, staticEvalScope_);
|
||||||
for (; !it.done(); it++) {
|
for (; !it.done(); it++) {
|
||||||
if (it.type() == StaticScopeIter<CanGC>::Function &&
|
if (it.type() == StaticScopeIter<CanGC>::Function &&
|
||||||
!it.fun().isArrow())
|
!it.fun().isArrow())
|
||||||
|
@ -273,40 +280,6 @@ class GlobalSharedContext : public SharedContext
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool computeInWith() const {
|
|
||||||
for (StaticScopeIter<CanGC> it(context, topStaticScope_); !it.done(); it++) {
|
|
||||||
if (it.type() == StaticScopeIter<CanGC>::With)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
GlobalSharedContext(ExclusiveContext* cx,
|
|
||||||
Directives directives, Handle<ScopeObject*> topStaticScope,
|
|
||||||
bool extraWarnings)
|
|
||||||
: SharedContext(cx, directives, extraWarnings),
|
|
||||||
topStaticScope_(topStaticScope),
|
|
||||||
allowNewTarget_(computeAllowSyntax(AllowedSyntax::NewTarget)),
|
|
||||||
allowSuperProperty_(computeAllowSyntax(AllowedSyntax::SuperProperty)),
|
|
||||||
inWith_(computeInWith())
|
|
||||||
{}
|
|
||||||
|
|
||||||
ObjectBox* toObjectBox() { return nullptr; }
|
|
||||||
HandleObject topStaticScope() const { return topStaticScope_; }
|
|
||||||
bool allowSyntax(AllowedSyntax allowSyntax) const override {
|
|
||||||
switch (allowSyntax) {
|
|
||||||
case AllowedSyntax::NewTarget:
|
|
||||||
// Any function supports new.target
|
|
||||||
return allowNewTarget_;
|
|
||||||
case AllowedSyntax::SuperProperty:
|
|
||||||
return allowSuperProperty_;
|
|
||||||
default:;
|
|
||||||
}
|
|
||||||
MOZ_CRASH("Unknown AllowedSyntax query");
|
|
||||||
}
|
|
||||||
bool inWith() const override { return inWith_; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionBox : public ObjectBox, public SharedContext
|
class FunctionBox : public ObjectBox, public SharedContext
|
||||||
|
@ -320,7 +293,7 @@ class FunctionBox : public ObjectBox, public SharedContext
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
|
|
||||||
uint8_t generatorKindBits_; /* The GeneratorKind of this function. */
|
uint8_t generatorKindBits_; /* The GeneratorKind of this function. */
|
||||||
bool inWith_:1; /* some enclosing scope is a with-statement */
|
bool inWith:1; /* some enclosing scope is a with-statement */
|
||||||
bool inGenexpLambda:1; /* lambda from generator expression */
|
bool inGenexpLambda:1; /* lambda from generator expression */
|
||||||
bool hasDestructuringArgs:1; /* arguments list contains destructuring expression */
|
bool hasDestructuringArgs:1; /* arguments list contains destructuring expression */
|
||||||
bool useAsm:1; /* see useAsmOrInsideUseAsm */
|
bool useAsm:1; /* see useAsmOrInsideUseAsm */
|
||||||
|
@ -399,13 +372,9 @@ class FunctionBox : public ObjectBox, public SharedContext
|
||||||
isGenerator();
|
isGenerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allowSyntax(AllowedSyntax allowed) const override {
|
bool allowSyntax(AllowedSyntax allowed) const {
|
||||||
return FunctionAllowsSyntax(function(), allowed);
|
return FunctionAllowsSyntax(function(), allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inWith() const override {
|
|
||||||
return inWith_;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline FunctionBox*
|
inline FunctionBox*
|
||||||
|
|
|
@ -4,7 +4,6 @@ var g = newGlobal();
|
||||||
var g2 = newGlobal();
|
var g2 = newGlobal();
|
||||||
var dbg = new Debugger(g, g2);
|
var dbg = new Debugger(g, g2);
|
||||||
var log = '';
|
var log = '';
|
||||||
var canary = 42;
|
|
||||||
|
|
||||||
dbg.onNewScript = function (evalScript) {
|
dbg.onNewScript = function (evalScript) {
|
||||||
log += 'e';
|
log += 'e';
|
||||||
|
@ -25,8 +24,5 @@ dbg.onDebuggerStatement = function (frame) {
|
||||||
};
|
};
|
||||||
|
|
||||||
assertEq(log, '');
|
assertEq(log, '');
|
||||||
var evalScope = g.evalReturningScope("canary = 'dead'; debugger; // nee", g2);
|
var evalScope = g.evalReturningScope("debugger; // nee", g2);
|
||||||
assertEq(log, 'ecbd');
|
assertEq(log, 'ecbd');
|
||||||
assertEq(canary, 42);
|
|
||||||
assertEq(evalScope.canary, 'dead');
|
|
||||||
|
|
||||||
|
|
|
@ -704,14 +704,13 @@ InitFromBailout(JSContext* cx, HandleScript caller, jsbytecode* callerPC,
|
||||||
scopeChain = fun->environment();
|
scopeChain = fun->environment();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// For global scripts without a non-syntactic scope the scope
|
// For global scripts without a polluted global scope the scope
|
||||||
// chain is the script's global (Ion does not compile scripts
|
// chain is the script's global (Ion does not compile scripts
|
||||||
// with a non-syntactic global scope). Also note that it's
|
// with a polluted global scope). Also note that it's invalid to
|
||||||
// invalid to resume into the prologue in this case because
|
// resume into the prologue in this case because the prologue
|
||||||
// the prologue expects the scope chain in R1 for eval and
|
// expects the scope chain in R1 for eval and global scripts.
|
||||||
// global scripts.
|
|
||||||
MOZ_ASSERT(!script->isForEval());
|
MOZ_ASSERT(!script->isForEval());
|
||||||
MOZ_ASSERT(!script->hasNonSyntacticScope());
|
MOZ_ASSERT(!script->hasPollutedGlobalScope());
|
||||||
scopeChain = &(script->global());
|
scopeChain = &(script->global());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#endif
|
#endif
|
||||||
#include "jit/SharedICHelpers.h"
|
#include "jit/SharedICHelpers.h"
|
||||||
#include "jit/VMFunctions.h"
|
#include "jit/VMFunctions.h"
|
||||||
#include "vm/ScopeObject.h"
|
|
||||||
#include "vm/TraceLogging.h"
|
#include "vm/TraceLogging.h"
|
||||||
|
|
||||||
#include "jsscriptinlines.h"
|
#include "jsscriptinlines.h"
|
||||||
|
@ -129,7 +128,7 @@ BaselineCompiler::compile()
|
||||||
return Method_Error;
|
return Method_Error;
|
||||||
|
|
||||||
if (fun->isNamedLambda()) {
|
if (fun->isNamedLambda()) {
|
||||||
RootedObject declEnvObject(cx, DeclEnvObject::createTemplateObject(cx, fun, TenuredObject));
|
RootedObject declEnvObject(cx, DeclEnvObject::createTemplateObject(cx, fun, gc::TenuredHeap));
|
||||||
if (!declEnvObject)
|
if (!declEnvObject)
|
||||||
return Method_Error;
|
return Method_Error;
|
||||||
templateScope->as<ScopeObject>().setEnclosingScope(declEnvObject);
|
templateScope->as<ScopeObject>().setEnclosingScope(declEnvObject);
|
||||||
|
@ -2063,7 +2062,7 @@ BaselineCompiler::emit_JSOP_IN()
|
||||||
bool
|
bool
|
||||||
BaselineCompiler::emit_JSOP_GETGNAME()
|
BaselineCompiler::emit_JSOP_GETGNAME()
|
||||||
{
|
{
|
||||||
if (script->hasNonSyntacticScope())
|
if (script->hasPollutedGlobalScope())
|
||||||
return emit_JSOP_GETNAME();
|
return emit_JSOP_GETNAME();
|
||||||
|
|
||||||
RootedPropertyName name(cx, script->getName(pc));
|
RootedPropertyName name(cx, script->getName(pc));
|
||||||
|
@ -2098,7 +2097,7 @@ BaselineCompiler::emit_JSOP_GETGNAME()
|
||||||
bool
|
bool
|
||||||
BaselineCompiler::emit_JSOP_BINDGNAME()
|
BaselineCompiler::emit_JSOP_BINDGNAME()
|
||||||
{
|
{
|
||||||
if (!script->hasNonSyntacticScope()) {
|
if (!script->hasPollutedGlobalScope()) {
|
||||||
frame.push(ObjectValue(script->global()));
|
frame.push(ObjectValue(script->global()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2921,7 +2920,7 @@ BaselineCompiler::emit_JSOP_IMPLICITTHIS()
|
||||||
bool
|
bool
|
||||||
BaselineCompiler::emit_JSOP_GIMPLICITTHIS()
|
BaselineCompiler::emit_JSOP_GIMPLICITTHIS()
|
||||||
{
|
{
|
||||||
if (!script->hasNonSyntacticScope()) {
|
if (!script->hasPollutedGlobalScope()) {
|
||||||
frame.push(UndefinedValue());
|
frame.push(UndefinedValue());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6031,7 +6031,7 @@ DoGetNameFallback(JSContext* cx, BaselineFrame* frame, ICGetName_Fallback* stub_
|
||||||
attached = true;
|
attached = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!attached && IsGlobalOp(JSOp(*pc)) && !script->hasNonSyntacticScope()) {
|
if (!attached && IsGlobalOp(JSOp(*pc)) && !script->hasPollutedGlobalScope()) {
|
||||||
if (!TryAttachGlobalNameAccessorStub(cx, script, pc, stub, scopeChain.as<GlobalObject>(),
|
if (!TryAttachGlobalNameAccessorStub(cx, script, pc, stub, scopeChain.as<GlobalObject>(),
|
||||||
name, &attached, &isTemporarilyUnoptimizable))
|
name, &attached, &isTemporarilyUnoptimizable))
|
||||||
{
|
{
|
||||||
|
@ -6061,7 +6061,7 @@ DoGetNameFallback(JSContext* cx, BaselineFrame* frame, ICGetName_Fallback* stub_
|
||||||
if (attached)
|
if (attached)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (IsGlobalOp(JSOp(*pc)) && !script->hasNonSyntacticScope()) {
|
if (IsGlobalOp(JSOp(*pc)) && !script->hasPollutedGlobalScope()) {
|
||||||
Handle<GlobalObject*> global = scopeChain.as<GlobalObject>();
|
Handle<GlobalObject*> global = scopeChain.as<GlobalObject>();
|
||||||
if (!TryAttachGlobalNameValueStub(cx, script, pc, stub, global, name, &attached))
|
if (!TryAttachGlobalNameValueStub(cx, script, pc, stub, global, name, &attached))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -170,7 +170,7 @@ BytecodeAnalysis::init(TempAllocator& alloc, GSNCache& gsn)
|
||||||
case JSOP_GETGNAME:
|
case JSOP_GETGNAME:
|
||||||
case JSOP_SETGNAME:
|
case JSOP_SETGNAME:
|
||||||
case JSOP_STRICTSETGNAME:
|
case JSOP_STRICTSETGNAME:
|
||||||
if (script_->hasNonSyntacticScope())
|
if (script_->hasPollutedGlobalScope())
|
||||||
usesScopeChain_ = true;
|
usesScopeChain_ = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -4683,7 +4683,7 @@ CodeGenerator::visitSimdUnbox(LSimdUnbox* lir)
|
||||||
bailoutFrom(&bail, lir->snapshot());
|
bailoutFrom(&bail, lir->snapshot());
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef js::DeclEnvObject* (*NewDeclEnvObjectFn)(JSContext*, HandleFunction, NewObjectKind);
|
typedef js::DeclEnvObject* (*NewDeclEnvObjectFn)(JSContext*, HandleFunction, gc::InitialHeap);
|
||||||
static const VMFunction NewDeclEnvObjectInfo =
|
static const VMFunction NewDeclEnvObjectInfo =
|
||||||
FunctionInfo<NewDeclEnvObjectFn>(DeclEnvObject::createTemplateObject);
|
FunctionInfo<NewDeclEnvObjectFn>(DeclEnvObject::createTemplateObject);
|
||||||
|
|
||||||
|
@ -4697,7 +4697,7 @@ CodeGenerator::visitNewDeclEnvObject(LNewDeclEnvObject* lir)
|
||||||
|
|
||||||
// If we have a template object, we can inline call object creation.
|
// If we have a template object, we can inline call object creation.
|
||||||
OutOfLineCode* ool = oolCallVM(NewDeclEnvObjectInfo, lir,
|
OutOfLineCode* ool = oolCallVM(NewDeclEnvObjectInfo, lir,
|
||||||
ArgList(ImmGCPtr(info.funMaybeLazy()), Imm32(GenericObject)),
|
ArgList(ImmGCPtr(info.funMaybeLazy()), Imm32(gc::DefaultHeap)),
|
||||||
StoreRegisterTo(objReg));
|
StoreRegisterTo(objReg));
|
||||||
|
|
||||||
bool initContents = ShouldInitFixedSlots(lir, templateObj);
|
bool initContents = ShouldInitFixedSlots(lir, templateObj);
|
||||||
|
|
|
@ -2128,12 +2128,12 @@ CheckScript(JSContext* cx, JSScript* script, bool osr)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (script->hasNonSyntacticScope() && !script->functionNonDelazifying()) {
|
if (script->hasPollutedGlobalScope() && !script->functionNonDelazifying()) {
|
||||||
// Support functions with a non-syntactic global scope but not other
|
// Support functions with a polluted global scope but not other
|
||||||
// scripts. For global scripts, IonBuilder currently uses the global
|
// scripts. For global scripts, IonBuilder currently uses the global
|
||||||
// object as scope chain, this is not valid when the script has a
|
// object as scope chain, this is not valid when the script has a
|
||||||
// non-syntactic global scope.
|
// polluted global scope.
|
||||||
TrackAndSpewIonAbort(cx, script, "has non-syntactic global scope");
|
TrackAndSpewIonAbort(cx, script, "has polluted global scope");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -613,7 +613,7 @@ IonBuilder::analyzeNewLoopTypes(MBasicBlock* entry, jsbytecode* start, jsbytecod
|
||||||
type = MIRType_Undefined;
|
type = MIRType_Undefined;
|
||||||
break;
|
break;
|
||||||
case JSOP_GIMPLICITTHIS:
|
case JSOP_GIMPLICITTHIS:
|
||||||
if (!script()->hasNonSyntacticScope())
|
if (!script()->hasPollutedGlobalScope())
|
||||||
type = MIRType_Undefined;
|
type = MIRType_Undefined;
|
||||||
break;
|
break;
|
||||||
case JSOP_NULL:
|
case JSOP_NULL:
|
||||||
|
@ -1177,10 +1177,10 @@ IonBuilder::initScopeChain(MDefinition* callee)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// For global scripts without a non-syntactic global scope, the scope
|
// For global scripts without a polluted global scope, the scope chain
|
||||||
// chain is the global object.
|
// is the global object.
|
||||||
MOZ_ASSERT(!script()->isForEval());
|
MOZ_ASSERT(!script()->isForEval());
|
||||||
MOZ_ASSERT(!script()->hasNonSyntacticScope());
|
MOZ_ASSERT(!script()->hasPollutedGlobalScope());
|
||||||
scope = constant(ObjectValue(script()->global()));
|
scope = constant(ObjectValue(script()->global()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1795,7 +1795,7 @@ IonBuilder::inspectOpcode(JSOp op)
|
||||||
case JSOP_GETGNAME:
|
case JSOP_GETGNAME:
|
||||||
{
|
{
|
||||||
PropertyName* name = info().getAtom(pc)->asPropertyName();
|
PropertyName* name = info().getAtom(pc)->asPropertyName();
|
||||||
if (!script()->hasNonSyntacticScope())
|
if (!script()->hasPollutedGlobalScope())
|
||||||
return jsop_getgname(name);
|
return jsop_getgname(name);
|
||||||
return jsop_getname(name);
|
return jsop_getname(name);
|
||||||
}
|
}
|
||||||
|
@ -1804,7 +1804,7 @@ IonBuilder::inspectOpcode(JSOp op)
|
||||||
case JSOP_STRICTSETGNAME:
|
case JSOP_STRICTSETGNAME:
|
||||||
{
|
{
|
||||||
PropertyName* name = info().getAtom(pc)->asPropertyName();
|
PropertyName* name = info().getAtom(pc)->asPropertyName();
|
||||||
if (script()->hasNonSyntacticScope())
|
if (script()->hasPollutedGlobalScope())
|
||||||
return jsop_setprop(name);
|
return jsop_setprop(name);
|
||||||
JSObject* obj = &script()->global();
|
JSObject* obj = &script()->global();
|
||||||
return setStaticName(obj, name);
|
return setStaticName(obj, name);
|
||||||
|
@ -1823,7 +1823,7 @@ IonBuilder::inspectOpcode(JSOp op)
|
||||||
}
|
}
|
||||||
|
|
||||||
case JSOP_BINDGNAME:
|
case JSOP_BINDGNAME:
|
||||||
if (!script()->hasNonSyntacticScope())
|
if (!script()->hasPollutedGlobalScope())
|
||||||
return pushConstant(ObjectValue(script()->global()));
|
return pushConstant(ObjectValue(script()->global()));
|
||||||
// Fall through to JSOP_BINDNAME
|
// Fall through to JSOP_BINDNAME
|
||||||
case JSOP_BINDNAME:
|
case JSOP_BINDNAME:
|
||||||
|
@ -1970,7 +1970,7 @@ IonBuilder::inspectOpcode(JSOp op)
|
||||||
return jsop_debugger();
|
return jsop_debugger();
|
||||||
|
|
||||||
case JSOP_GIMPLICITTHIS:
|
case JSOP_GIMPLICITTHIS:
|
||||||
if (!script()->hasNonSyntacticScope())
|
if (!script()->hasPollutedGlobalScope())
|
||||||
return pushConstant(UndefinedValue());
|
return pushConstant(UndefinedValue());
|
||||||
|
|
||||||
// Just fall through to the unsupported bytecode case.
|
// Just fall through to the unsupported bytecode case.
|
||||||
|
@ -7608,7 +7608,7 @@ bool
|
||||||
IonBuilder::jsop_getname(PropertyName* name)
|
IonBuilder::jsop_getname(PropertyName* name)
|
||||||
{
|
{
|
||||||
MDefinition* object;
|
MDefinition* object;
|
||||||
if (IsGlobalOp(JSOp(*pc)) && !script()->hasNonSyntacticScope()) {
|
if (IsGlobalOp(JSOp(*pc)) && !script()->hasPollutedGlobalScope()) {
|
||||||
MInstruction* global = constant(ObjectValue(script()->global()));
|
MInstruction* global = constant(ObjectValue(script()->global()));
|
||||||
object = global;
|
object = global;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2553,7 +2553,7 @@ InlineFrameIterator::computeScopeChain(Value scopeChainValue, MaybeReadFallback&
|
||||||
// Ion does not handle non-function scripts that have anything other than
|
// Ion does not handle non-function scripts that have anything other than
|
||||||
// the global on their scope chain.
|
// the global on their scope chain.
|
||||||
MOZ_ASSERT(!script()->isForEval());
|
MOZ_ASSERT(!script()->isForEval());
|
||||||
MOZ_ASSERT(!script()->hasNonSyntacticScope());
|
MOZ_ASSERT(!script()->hasPollutedGlobalScope());
|
||||||
return &script()->global();
|
return &script()->global();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
261
js/src/jsapi.cpp
261
js/src/jsapi.cpp
|
@ -3283,22 +3283,12 @@ JS::GetSelfHostedFunction(JSContext* cx, const char* selfHostedName, HandleId id
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CreateNonSyntacticScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
|
CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
|
||||||
MutableHandleObject dynamicScopeObj,
|
MutableHandleObject dynamicScopeObj,
|
||||||
MutableHandle<ScopeObject*> staticScopeObj)
|
MutableHandleObject staticScopeObj)
|
||||||
{
|
{
|
||||||
if (!js::CreateScopeObjectsForScopeChain(cx, scopeChain, cx->global(), dynamicScopeObj))
|
return js::CreateScopeObjectsForScopeChain(cx, scopeChain, cx->global(),
|
||||||
return false;
|
dynamicScopeObj, staticScopeObj);
|
||||||
|
|
||||||
if (scopeChain.empty()) {
|
|
||||||
staticScopeObj.set(nullptr);
|
|
||||||
} else {
|
|
||||||
staticScopeObj.set(StaticNonSyntacticScopeObjects::create(cx, nullptr));
|
|
||||||
if (!staticScopeObj)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -3309,23 +3299,11 @@ IsFunctionCloneable(HandleFunction fun, HandleObject dynamicScope)
|
||||||
|
|
||||||
// If a function was compiled to be lexically nested inside some other
|
// If a function was compiled to be lexically nested inside some other
|
||||||
// script, we cannot clone it without breaking the compiler's assumptions.
|
// script, we cannot clone it without breaking the compiler's assumptions.
|
||||||
if (JSObject* scope = fun->nonLazyScript()->enclosingStaticScope()) {
|
JSObject* scope = fun->nonLazyScript()->enclosingStaticScope();
|
||||||
// If the script already deals with a non-syntactic scope, we can clone
|
if (scope && (!scope->is<StaticEvalObject>() ||
|
||||||
// it.
|
scope->as<StaticEvalObject>().isDirect() ||
|
||||||
if (scope->is<StaticNonSyntacticScopeObjects>())
|
scope->as<StaticEvalObject>().isStrict()))
|
||||||
return true;
|
{
|
||||||
|
|
||||||
// If the script is an indirect eval that is immediately scoped under
|
|
||||||
// the global, we can clone it.
|
|
||||||
if (scope->is<StaticEvalObject>() &&
|
|
||||||
!scope->as<StaticEvalObject>().isDirect() &&
|
|
||||||
!scope->as<StaticEvalObject>().isStrict())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Any other enclosing static scope (e.g., function, block) cannot be
|
|
||||||
// cloned.
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3333,8 +3311,7 @@ IsFunctionCloneable(HandleFunction fun, HandleObject dynamicScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSObject*
|
static JSObject*
|
||||||
CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject dynamicScope,
|
CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject dynamicScope)
|
||||||
Handle<ScopeObject*> staticScope)
|
|
||||||
{
|
{
|
||||||
AssertHeapIsIdle(cx);
|
AssertHeapIsIdle(cx);
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
|
@ -3371,21 +3348,7 @@ CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject dynamicScop
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CanReuseScriptForClone(cx->compartment(), fun, dynamicScope)) {
|
return CloneFunctionObject(cx, fun, dynamicScope, fun->getAllocKind());
|
||||||
// If the script is to be reused, either the script can already handle
|
|
||||||
// non-syntactic scopes, or there is no new static scope.
|
|
||||||
#ifdef DEBUG
|
|
||||||
// Fail here if we OOM during debug asserting.
|
|
||||||
// CloneFunctionReuseScript will delazify the script anyways, so we
|
|
||||||
// are not creating an extra failure condition for DEBUG builds.
|
|
||||||
if (!fun->getOrCreateScript(cx))
|
|
||||||
return nullptr;
|
|
||||||
MOZ_ASSERT(!staticScope || fun->nonLazyScript()->hasNonSyntacticScope());
|
|
||||||
#endif
|
|
||||||
return CloneFunctionReuseScript(cx, fun, dynamicScope, fun->getAllocKind());
|
|
||||||
}
|
|
||||||
|
|
||||||
return CloneFunctionAndScript(cx, fun, dynamicScope, staticScope, fun->getAllocKind());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
@ -3393,18 +3356,18 @@ namespace JS {
|
||||||
JS_PUBLIC_API(JSObject*)
|
JS_PUBLIC_API(JSObject*)
|
||||||
CloneFunctionObject(JSContext* cx, JS::Handle<JSObject*> funobj)
|
CloneFunctionObject(JSContext* cx, JS::Handle<JSObject*> funobj)
|
||||||
{
|
{
|
||||||
return CloneFunctionObject(cx, funobj, cx->global(), /* staticScope = */ nullptr);
|
return CloneFunctionObject(cx, funobj, cx->global());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSObject*)
|
extern JS_PUBLIC_API(JSObject*)
|
||||||
CloneFunctionObject(JSContext* cx, HandleObject funobj, AutoObjectVector& scopeChain)
|
CloneFunctionObject(JSContext* cx, HandleObject funobj, AutoObjectVector& scopeChain)
|
||||||
{
|
{
|
||||||
RootedObject dynamicScope(cx);
|
RootedObject dynamicScope(cx);
|
||||||
Rooted<ScopeObject*> staticScope(cx);
|
RootedObject unusedStaticScope(cx);
|
||||||
if (!CreateNonSyntacticScopeChain(cx, scopeChain, &dynamicScope, &staticScope))
|
if (!CreateScopeObjectsForScopeChain(cx, scopeChain, &dynamicScope, &unusedStaticScope))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return CloneFunctionObject(cx, funobj, dynamicScope, staticScope);
|
return CloneFunctionObject(cx, funobj, dynamicScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace JS
|
} // namespace JS
|
||||||
|
@ -3874,40 +3837,31 @@ JS::CompileOptions::CompileOptions(JSContext* cx, JSVersion version)
|
||||||
asmJSOption = cx->runtime()->options().asmJS();
|
asmJSOption = cx->runtime()->options().asmJS();
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SyntacticScopeOption { HasSyntacticScope, HasNonSyntacticScope };
|
bool
|
||||||
|
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||||
static bool
|
SourceBufferHolder& srcBuf, MutableHandleScript script)
|
||||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& options, SyntacticScopeOption scopeOption,
|
|
||||||
SourceBufferHolder& srcBuf, MutableHandleScript script)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
|
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
|
||||||
AssertHeapIsIdle(cx);
|
AssertHeapIsIdle(cx);
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
AutoLastFrameCheck lfc(cx);
|
AutoLastFrameCheck lfc(cx);
|
||||||
|
|
||||||
Rooted<ScopeObject*> staticScope(cx);
|
|
||||||
if (scopeOption == HasNonSyntacticScope) {
|
|
||||||
staticScope = StaticNonSyntacticScopeObjects::create(cx, nullptr);
|
|
||||||
if (!staticScope)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
script.set(frontend::CompileScript(cx, &cx->tempLifoAlloc(), cx->global(),
|
script.set(frontend::CompileScript(cx, &cx->tempLifoAlloc(), cx->global(),
|
||||||
staticScope, nullptr, options, srcBuf));
|
nullptr, nullptr, options, srcBuf));
|
||||||
return !!script;
|
return !!script;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& options, SyntacticScopeOption scopeOption,
|
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||||
const char16_t* chars, size_t length, MutableHandleScript script)
|
const char16_t* chars, size_t length, MutableHandleScript script)
|
||||||
{
|
{
|
||||||
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
|
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
|
||||||
return ::Compile(cx, options, scopeOption, srcBuf, script);
|
return Compile(cx, options, srcBuf, script);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& options, SyntacticScopeOption scopeOption,
|
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||||
const char* bytes, size_t length, MutableHandleScript script)
|
const char* bytes, size_t length, MutableHandleScript script)
|
||||||
{
|
{
|
||||||
mozilla::UniquePtr<char16_t, JS::FreePolicy> chars;
|
mozilla::UniquePtr<char16_t, JS::FreePolicy> chars;
|
||||||
if (options.utf8)
|
if (options.utf8)
|
||||||
|
@ -3917,101 +3871,30 @@ Compile(JSContext* cx, const ReadOnlyCompileOptions& options, SyntacticScopeOpti
|
||||||
if (!chars)
|
if (!chars)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return ::Compile(cx, options, scopeOption, chars.get(), length, script);
|
return Compile(cx, options, chars.get(), length, script);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& options, SyntacticScopeOption scopeOption,
|
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options, FILE* fp,
|
||||||
FILE* fp, MutableHandleScript script)
|
MutableHandleScript script)
|
||||||
{
|
{
|
||||||
FileContents buffer(cx);
|
FileContents buffer(cx);
|
||||||
if (!ReadCompleteFile(cx, fp, buffer))
|
if (!ReadCompleteFile(cx, fp, buffer))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return ::Compile(cx, options, scopeOption, buffer.begin(), buffer.length(), script);
|
return Compile(cx, options, buffer.begin(), buffer.length(), script);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& optionsArg, SyntacticScopeOption scopeOption,
|
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& optionsArg, const char* filename,
|
||||||
const char* filename, MutableHandleScript script)
|
MutableHandleScript script)
|
||||||
{
|
{
|
||||||
AutoFile file;
|
AutoFile file;
|
||||||
if (!file.open(cx, filename))
|
if (!file.open(cx, filename))
|
||||||
return false;
|
return false;
|
||||||
CompileOptions options(cx, optionsArg);
|
CompileOptions options(cx, optionsArg);
|
||||||
options.setFileAndLine(filename, 1);
|
options.setFileAndLine(filename, 1);
|
||||||
return ::Compile(cx, options, scopeOption, file.fp(), script);
|
return Compile(cx, options, file.fp(), script);
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
|
|
||||||
{
|
|
||||||
return ::Compile(cx, options, HasSyntacticScope, srcBuf, script);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
const char* bytes, size_t length, JS::MutableHandleScript script)
|
|
||||||
{
|
|
||||||
return ::Compile(cx, options, HasSyntacticScope, bytes, length, script);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
const char16_t* chars, size_t length, JS::MutableHandleScript script)
|
|
||||||
{
|
|
||||||
return ::Compile(cx, options, HasSyntacticScope, chars, length, script);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
FILE* file, JS::MutableHandleScript script)
|
|
||||||
{
|
|
||||||
return ::Compile(cx, options, HasSyntacticScope, file, script);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
const char* filename, JS::MutableHandleScript script)
|
|
||||||
{
|
|
||||||
return ::Compile(cx, options, HasSyntacticScope, filename, script);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
|
|
||||||
{
|
|
||||||
return ::Compile(cx, options, HasNonSyntacticScope, srcBuf, script);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
const char* bytes, size_t length, JS::MutableHandleScript script)
|
|
||||||
{
|
|
||||||
return ::Compile(cx, options, HasNonSyntacticScope, bytes, length, script);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
const char16_t* chars, size_t length,
|
|
||||||
JS::MutableHandleScript script)
|
|
||||||
{
|
|
||||||
return ::Compile(cx, options, HasNonSyntacticScope, chars, length, script);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
FILE* file, JS::MutableHandleScript script)
|
|
||||||
{
|
|
||||||
return ::Compile(cx, options, HasNonSyntacticScope, file, script);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
const char* filename, JS::MutableHandleScript script)
|
|
||||||
{
|
|
||||||
return ::Compile(cx, options, HasNonSyntacticScope, filename, script);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
JS_PUBLIC_API(bool)
|
||||||
|
@ -4194,13 +4077,13 @@ CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||||
if (!fun)
|
if (!fun)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Make sure the static scope chain matches up when we have a
|
// Make sure to handle cases when we have a polluted scopechain.
|
||||||
// non-syntactic scope.
|
|
||||||
MOZ_ASSERT_IF(!enclosingDynamicScope->is<GlobalObject>(),
|
|
||||||
HasNonSyntacticStaticScopeChain(enclosingStaticScope));
|
|
||||||
|
|
||||||
CompileOptions options(cx, optionsArg);
|
CompileOptions options(cx, optionsArg);
|
||||||
if (!frontend::CompileFunctionBody(cx, fun, options, formals, srcBuf, enclosingStaticScope))
|
if (!enclosingDynamicScope->is<GlobalObject>())
|
||||||
|
options.setHasPollutedScope(true);
|
||||||
|
|
||||||
|
if (!frontend::CompileFunctionBody(cx, fun, options, formals, srcBuf,
|
||||||
|
enclosingStaticScope))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -4213,8 +4096,8 @@ JS::CompileFunction(JSContext* cx, AutoObjectVector& scopeChain,
|
||||||
SourceBufferHolder& srcBuf, MutableHandleFunction fun)
|
SourceBufferHolder& srcBuf, MutableHandleFunction fun)
|
||||||
{
|
{
|
||||||
RootedObject dynamicScopeObj(cx);
|
RootedObject dynamicScopeObj(cx);
|
||||||
Rooted<ScopeObject*> staticScopeObj(cx);
|
RootedObject staticScopeObj(cx);
|
||||||
if (!CreateNonSyntacticScopeChain(cx, scopeChain, &dynamicScopeObj, &staticScopeObj))
|
if (!CreateScopeObjectsForScopeChain(cx, scopeChain, &dynamicScopeObj, &staticScopeObj))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return CompileFunction(cx, options, name, nargs, argnames,
|
return CompileFunction(cx, options, name, nargs, argnames,
|
||||||
|
@ -4288,34 +4171,33 @@ JS_DecompileFunctionBody(JSContext* cx, HandleFunction fun, unsigned indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_NEVER_INLINE static bool
|
MOZ_NEVER_INLINE static bool
|
||||||
ExecuteScript(JSContext* cx, HandleObject scope, HandleScript script, jsval* rval)
|
ExecuteScript(JSContext* cx, HandleObject obj, HandleScript scriptArg, jsval* rval)
|
||||||
{
|
{
|
||||||
|
RootedScript script(cx, scriptArg);
|
||||||
|
|
||||||
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
|
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
|
||||||
AssertHeapIsIdle(cx);
|
AssertHeapIsIdle(cx);
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
assertSameCompartment(cx, scope, script);
|
assertSameCompartment(cx, obj, scriptArg);
|
||||||
MOZ_ASSERT_IF(!scope->is<GlobalObject>(), script->hasNonSyntacticScope());
|
|
||||||
|
if (!script->hasPollutedGlobalScope() && !obj->is<GlobalObject>()) {
|
||||||
|
script = CloneScript(cx, nullptr, nullptr, script, HasPollutedGlobalScope);
|
||||||
|
if (!script)
|
||||||
|
return false;
|
||||||
|
js::Debugger::onNewScript(cx, script);
|
||||||
|
}
|
||||||
AutoLastFrameCheck lfc(cx);
|
AutoLastFrameCheck lfc(cx);
|
||||||
return Execute(cx, script, *scope, rval);
|
return Execute(cx, script, *obj, rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ExecuteScript(JSContext* cx, AutoObjectVector& scopeChain, HandleScript scriptArg, jsval* rval)
|
ExecuteScript(JSContext* cx, AutoObjectVector& scopeChain, HandleScript scriptArg, jsval* rval)
|
||||||
{
|
{
|
||||||
RootedObject dynamicScope(cx);
|
RootedObject dynamicScope(cx);
|
||||||
Rooted<ScopeObject*> staticScope(cx);
|
RootedObject unusedStaticScope(cx);
|
||||||
if (!CreateNonSyntacticScopeChain(cx, scopeChain, &dynamicScope, &staticScope))
|
if (!CreateScopeObjectsForScopeChain(cx, scopeChain, &dynamicScope, &unusedStaticScope))
|
||||||
return false;
|
return false;
|
||||||
|
return ExecuteScript(cx, dynamicScope, scriptArg, rval);
|
||||||
RootedScript script(cx, scriptArg);
|
|
||||||
if (!script->hasNonSyntacticScope()) {
|
|
||||||
script = CloneGlobalScript(cx, staticScope, script);
|
|
||||||
if (!script)
|
|
||||||
return false;
|
|
||||||
js::Debugger::onNewScript(cx, script);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ExecuteScript(cx, dynamicScope, script, rval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
|
MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
|
||||||
|
@ -4349,7 +4231,7 @@ JS::CloneAndExecuteScript(JSContext* cx, HandleScript scriptArg)
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
RootedScript script(cx, scriptArg);
|
RootedScript script(cx, scriptArg);
|
||||||
if (script->compartment() != cx->compartment()) {
|
if (script->compartment() != cx->compartment()) {
|
||||||
script = CloneGlobalScript(cx, /* enclosingScope = */ nullptr, script);
|
script = CloneScript(cx, nullptr, nullptr, script);
|
||||||
if (!script)
|
if (!script)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -4361,8 +4243,7 @@ JS::CloneAndExecuteScript(JSContext* cx, HandleScript scriptArg)
|
||||||
static const unsigned LARGE_SCRIPT_LENGTH = 500*1024;
|
static const unsigned LARGE_SCRIPT_LENGTH = 500*1024;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
Evaluate(JSContext* cx, HandleObject scope, Handle<ScopeObject*> staticScope,
|
Evaluate(JSContext* cx, HandleObject scope, const ReadOnlyCompileOptions& optionsArg,
|
||||||
const ReadOnlyCompileOptions& optionsArg,
|
|
||||||
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
||||||
{
|
{
|
||||||
CompileOptions options(cx, optionsArg);
|
CompileOptions options(cx, optionsArg);
|
||||||
|
@ -4373,14 +4254,12 @@ Evaluate(JSContext* cx, HandleObject scope, Handle<ScopeObject*> staticScope,
|
||||||
|
|
||||||
AutoLastFrameCheck lfc(cx);
|
AutoLastFrameCheck lfc(cx);
|
||||||
|
|
||||||
MOZ_ASSERT_IF(!scope->is<GlobalObject>(), HasNonSyntacticStaticScopeChain(staticScope));
|
options.setHasPollutedScope(!scope->is<GlobalObject>());
|
||||||
|
|
||||||
options.setIsRunOnce(true);
|
options.setIsRunOnce(true);
|
||||||
SourceCompressionTask sct(cx);
|
SourceCompressionTask sct(cx);
|
||||||
RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(),
|
RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(),
|
||||||
scope, staticScope,
|
scope, nullptr, nullptr, options,
|
||||||
/* evalCaller = */ nullptr, options,
|
srcBuf, nullptr, 0, &sct));
|
||||||
srcBuf, /* source = */ nullptr, 0, &sct));
|
|
||||||
if (!script)
|
if (!script)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -4410,10 +4289,10 @@ Evaluate(JSContext* cx, AutoObjectVector& scopeChain, const ReadOnlyCompileOptio
|
||||||
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
||||||
{
|
{
|
||||||
RootedObject dynamicScope(cx);
|
RootedObject dynamicScope(cx);
|
||||||
Rooted<ScopeObject*> staticScope(cx);
|
RootedObject unusedStaticScope(cx);
|
||||||
if (!CreateNonSyntacticScopeChain(cx, scopeChain, &dynamicScope, &staticScope))
|
if (!CreateScopeObjectsForScopeChain(cx, scopeChain, &dynamicScope, &unusedStaticScope))
|
||||||
return false;
|
return false;
|
||||||
return ::Evaluate(cx, dynamicScope, staticScope, optionsArg, srcBuf, rval);
|
return ::Evaluate(cx, dynamicScope, optionsArg, srcBuf, rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -4421,7 +4300,7 @@ Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||||
const char16_t* chars, size_t length, MutableHandleValue rval)
|
const char16_t* chars, size_t length, MutableHandleValue rval)
|
||||||
{
|
{
|
||||||
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
|
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
|
||||||
return ::Evaluate(cx, cx->global(), nullptr, optionsArg, srcBuf, rval);
|
return ::Evaluate(cx, cx->global(), optionsArg, srcBuf, rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern JS_PUBLIC_API(bool)
|
extern JS_PUBLIC_API(bool)
|
||||||
|
@ -4437,7 +4316,7 @@ JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::GiveOwnership);
|
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::GiveOwnership);
|
||||||
bool ok = ::Evaluate(cx, cx->global(), nullptr, options, srcBuf, rval);
|
bool ok = ::Evaluate(cx, cx->global(), options, srcBuf, rval);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4461,7 +4340,7 @@ JS_PUBLIC_API(bool)
|
||||||
JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||||
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
||||||
{
|
{
|
||||||
return ::Evaluate(cx, cx->global(), nullptr, optionsArg, srcBuf, rval);
|
return ::Evaluate(cx, cx->global(), optionsArg, srcBuf, rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
JS_PUBLIC_API(bool)
|
||||||
|
|
|
@ -3446,6 +3446,7 @@ class JS_FRIEND_API(ReadOnlyCompileOptions)
|
||||||
utf8(false),
|
utf8(false),
|
||||||
lineno(1),
|
lineno(1),
|
||||||
column(0),
|
column(0),
|
||||||
|
hasPollutedGlobalScope(false),
|
||||||
isRunOnce(false),
|
isRunOnce(false),
|
||||||
forEval(false),
|
forEval(false),
|
||||||
noScriptRval(false),
|
noScriptRval(false),
|
||||||
|
@ -3485,6 +3486,7 @@ class JS_FRIEND_API(ReadOnlyCompileOptions)
|
||||||
bool utf8;
|
bool utf8;
|
||||||
unsigned lineno;
|
unsigned lineno;
|
||||||
unsigned column;
|
unsigned column;
|
||||||
|
bool hasPollutedGlobalScope;
|
||||||
// isRunOnce only applies to non-function scripts.
|
// isRunOnce only applies to non-function scripts.
|
||||||
bool isRunOnce;
|
bool isRunOnce;
|
||||||
bool forEval;
|
bool forEval;
|
||||||
|
@ -3577,6 +3579,7 @@ class JS_FRIEND_API(OwningCompileOptions) : public ReadOnlyCompileOptions
|
||||||
}
|
}
|
||||||
OwningCompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
|
OwningCompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
|
||||||
OwningCompileOptions& setColumn(unsigned c) { column = c; return *this; }
|
OwningCompileOptions& setColumn(unsigned c) { column = c; return *this; }
|
||||||
|
OwningCompileOptions& setHasPollutedScope(bool p) { hasPollutedGlobalScope = p; return *this; }
|
||||||
OwningCompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
|
OwningCompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
|
||||||
OwningCompileOptions& setForEval(bool eval) { forEval = eval; return *this; }
|
OwningCompileOptions& setForEval(bool eval) { forEval = eval; return *this; }
|
||||||
OwningCompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
|
OwningCompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
|
||||||
|
@ -3660,6 +3663,7 @@ class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) : public ReadOnlyCompileOpti
|
||||||
}
|
}
|
||||||
CompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
|
CompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
|
||||||
CompileOptions& setColumn(unsigned c) { column = c; return *this; }
|
CompileOptions& setColumn(unsigned c) { column = c; return *this; }
|
||||||
|
CompileOptions& setHasPollutedScope(bool p) { hasPollutedGlobalScope = p; return *this; }
|
||||||
CompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
|
CompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
|
||||||
CompileOptions& setForEval(bool eval) { forEval = eval; return *this; }
|
CompileOptions& setForEval(bool eval) { forEval = eval; return *this; }
|
||||||
CompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
|
CompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
|
||||||
|
@ -3703,32 +3707,12 @@ Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||||
const char16_t* chars, size_t length, JS::MutableHandleScript script);
|
const char16_t* chars, size_t length, JS::MutableHandleScript script);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(bool)
|
extern JS_PUBLIC_API(bool)
|
||||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
Compile(JSContext* cx, const ReadOnlyCompileOptions& options, FILE* file,
|
||||||
FILE* file, JS::MutableHandleScript script);
|
JS::MutableHandleScript script);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(bool)
|
extern JS_PUBLIC_API(bool)
|
||||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
Compile(JSContext* cx, const ReadOnlyCompileOptions& options, const char* filename,
|
||||||
const char* filename, JS::MutableHandleScript script);
|
JS::MutableHandleScript script);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(bool)
|
|
||||||
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
SourceBufferHolder& srcBuf, JS::MutableHandleScript script);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(bool)
|
|
||||||
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
const char* bytes, size_t length, JS::MutableHandleScript script);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(bool)
|
|
||||||
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
const char16_t* chars, size_t length, JS::MutableHandleScript script);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(bool)
|
|
||||||
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
FILE* file, JS::MutableHandleScript script);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(bool)
|
|
||||||
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|
||||||
const char* filename, JS::MutableHandleScript script);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(bool)
|
extern JS_PUBLIC_API(bool)
|
||||||
CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length);
|
CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length);
|
||||||
|
|
245
js/src/jsfun.cpp
245
js/src/jsfun.cpp
|
@ -35,7 +35,6 @@
|
||||||
#include "jit/JitFrameIterator.h"
|
#include "jit/JitFrameIterator.h"
|
||||||
#include "js/CallNonGenericMethod.h"
|
#include "js/CallNonGenericMethod.h"
|
||||||
#include "js/Proxy.h"
|
#include "js/Proxy.h"
|
||||||
#include "vm/Debugger.h"
|
|
||||||
#include "vm/GlobalObject.h"
|
#include "vm/GlobalObject.h"
|
||||||
#include "vm/Interpreter.h"
|
#include "vm/Interpreter.h"
|
||||||
#include "vm/Shape.h"
|
#include "vm/Shape.h"
|
||||||
|
@ -525,7 +524,7 @@ js::XDRInterpretedFunction(XDRState<mode>* xdr, HandleObject enclosingScope, Han
|
||||||
HasSingletonType = 0x8
|
HasSingletonType = 0x8
|
||||||
};
|
};
|
||||||
|
|
||||||
/* NB: Keep this in sync with CloneInnerInterpretedFunction. */
|
/* NB: Keep this in sync with CloneFunctionAndScript. */
|
||||||
RootedAtom atom(xdr->cx());
|
RootedAtom atom(xdr->cx());
|
||||||
uint32_t firstword = 0; /* bitmask of FirstWordFlag */
|
uint32_t firstword = 0; /* bitmask of FirstWordFlag */
|
||||||
uint32_t flagsword = 0; /* word for argument count and fun->flags */
|
uint32_t flagsword = 0; /* word for argument count and fun->flags */
|
||||||
|
@ -616,9 +615,10 @@ js::XDRInterpretedFunction(XDRState<mode>* xdr, HandleObject enclosingScope, Han
|
||||||
fun->setFlags(uint16_t(flagsword));
|
fun->setFlags(uint16_t(flagsword));
|
||||||
fun->initAtom(atom);
|
fun->initAtom(atom);
|
||||||
if (firstword & IsLazy) {
|
if (firstword & IsLazy) {
|
||||||
MOZ_ASSERT(fun->lazyScript() == lazy);
|
fun->initLazyScript(lazy);
|
||||||
} else {
|
} else {
|
||||||
MOZ_ASSERT(fun->nonLazyScript() == script);
|
fun->initScript(script);
|
||||||
|
script->setFunction(fun);
|
||||||
MOZ_ASSERT(fun->nargs() == script->bindings.numArgs());
|
MOZ_ASSERT(fun->nargs() == script->bindings.numArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,6 +637,44 @@ js::XDRInterpretedFunction(XDRState<XDR_ENCODE>*, HandleObject, HandleScript, Mu
|
||||||
template bool
|
template bool
|
||||||
js::XDRInterpretedFunction(XDRState<XDR_DECODE>*, HandleObject, HandleScript, MutableHandleFunction);
|
js::XDRInterpretedFunction(XDRState<XDR_DECODE>*, HandleObject, HandleScript, MutableHandleFunction);
|
||||||
|
|
||||||
|
JSObject*
|
||||||
|
js::CloneFunctionAndScript(JSContext* cx, HandleObject enclosingScope, HandleFunction srcFun,
|
||||||
|
PollutedGlobalScopeOption polluted)
|
||||||
|
{
|
||||||
|
/* NB: Keep this in sync with XDRInterpretedFunction. */
|
||||||
|
RootedObject cloneProto(cx);
|
||||||
|
if (srcFun->isStarGenerator()) {
|
||||||
|
cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
|
||||||
|
if (!cloneProto)
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
gc::AllocKind allocKind = srcFun->getAllocKind();
|
||||||
|
RootedFunction clone(cx, NewFunctionWithProto(cx, nullptr, 0,
|
||||||
|
JSFunction::INTERPRETED, nullptr, nullptr,
|
||||||
|
cloneProto, allocKind, TenuredObject));
|
||||||
|
if (!clone)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
JSScript::AutoDelazify srcScript(cx, srcFun);
|
||||||
|
if (!srcScript)
|
||||||
|
return nullptr;
|
||||||
|
RootedScript clonedScript(cx, CloneScript(cx, enclosingScope, clone, srcScript, polluted));
|
||||||
|
if (!clonedScript)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
clone->setArgCount(srcFun->nargs());
|
||||||
|
clone->setFlags(srcFun->flags());
|
||||||
|
clone->initAtom(srcFun->displayAtom());
|
||||||
|
clone->initScript(clonedScript);
|
||||||
|
clonedScript->setFunction(clone);
|
||||||
|
if (!JSFunction::setTypeForScriptedFunction(cx, clone))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
RootedScript cloneScript(cx, clone->nonLazyScript());
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* [[HasInstance]] internal method for Function objects: fetch the .prototype
|
* [[HasInstance]] internal method for Function objects: fetch the .prototype
|
||||||
* property of its 'this' parameter, and walks the prototype chain of v (only
|
* property of its 'this' parameter, and walks the prototype chain of v (only
|
||||||
|
@ -790,7 +828,7 @@ CreateFunctionPrototype(JSContext* cx, JSProtoKey key)
|
||||||
/*
|
/*
|
||||||
* The default 'new' group of Function.prototype is required by type
|
* The default 'new' group of Function.prototype is required by type
|
||||||
* inference to have unknown properties, to simplify handling of e.g.
|
* inference to have unknown properties, to simplify handling of e.g.
|
||||||
* NewFunctionClone.
|
* CloneFunctionObject.
|
||||||
*/
|
*/
|
||||||
if (!JSObject::setNewGroupUnknown(cx, &JSFunction::class_, functionProto))
|
if (!JSObject::setNewGroupUnknown(cx, &JSFunction::class_, functionProto))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1385,13 +1423,16 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFuncti
|
||||||
|
|
||||||
if (script) {
|
if (script) {
|
||||||
RootedObject enclosingScope(cx, lazy->enclosingScope());
|
RootedObject enclosingScope(cx, lazy->enclosingScope());
|
||||||
RootedScript clonedScript(cx, CloneScriptIntoFunction(cx, enclosingScope, fun, script));
|
RootedScript clonedScript(cx, CloneScript(cx, enclosingScope, fun, script));
|
||||||
if (!clonedScript)
|
if (!clonedScript)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
clonedScript->setSourceObject(lazy->sourceObject());
|
clonedScript->setSourceObject(lazy->sourceObject());
|
||||||
|
|
||||||
fun->initAtom(script->functionNonDelazifying()->displayAtom());
|
fun->initAtom(script->functionNonDelazifying()->displayAtom());
|
||||||
|
clonedScript->setFunction(fun);
|
||||||
|
|
||||||
|
fun->setUnlazifiedScript(clonedScript);
|
||||||
|
|
||||||
if (!lazy->maybeScript())
|
if (!lazy->maybeScript())
|
||||||
lazy->initScript(clonedScript);
|
lazy->initScript(clonedScript);
|
||||||
|
@ -1978,20 +2019,6 @@ js::NewScriptedFunction(ExclusiveContext* cx, unsigned nargs,
|
||||||
atom, nullptr, allocKind, newKind);
|
atom, nullptr, allocKind, newKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static bool
|
|
||||||
NewFunctionScopeIsWellFormed(ExclusiveContext* cx, HandleObject parent)
|
|
||||||
{
|
|
||||||
// Assert that the parent is null, global, or a debug scope proxy. All
|
|
||||||
// other cases of polluting global scope behavior are handled by
|
|
||||||
// ScopeObjects (viz. non-syntactic DynamicWithObject and
|
|
||||||
// NonSyntacticVariablesObject).
|
|
||||||
RootedObject realParent(cx, SkipScopeParent(parent));
|
|
||||||
return !realParent || realParent == cx->global() ||
|
|
||||||
realParent->is<DebugScopeObject>();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JSFunction*
|
JSFunction*
|
||||||
js::NewFunctionWithProto(ExclusiveContext* cx, Native native,
|
js::NewFunctionWithProto(ExclusiveContext* cx, Native native,
|
||||||
unsigned nargs, JSFunction::Flags flags, HandleObject enclosingDynamicScope,
|
unsigned nargs, JSFunction::Flags flags, HandleObject enclosingDynamicScope,
|
||||||
|
@ -2001,7 +2028,6 @@ js::NewFunctionWithProto(ExclusiveContext* cx, Native native,
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(allocKind == AllocKind::FUNCTION || allocKind == AllocKind::FUNCTION_EXTENDED);
|
MOZ_ASSERT(allocKind == AllocKind::FUNCTION || allocKind == AllocKind::FUNCTION_EXTENDED);
|
||||||
MOZ_ASSERT_IF(native, !enclosingDynamicScope);
|
MOZ_ASSERT_IF(native, !enclosingDynamicScope);
|
||||||
MOZ_ASSERT(NewFunctionScopeIsWellFormed(cx, enclosingDynamicScope));
|
|
||||||
|
|
||||||
RootedObject funobj(cx);
|
RootedObject funobj(cx);
|
||||||
// Don't mark asm.js module functions as singleton since they are
|
// Don't mark asm.js module functions as singleton since they are
|
||||||
|
@ -2009,6 +2035,17 @@ js::NewFunctionWithProto(ExclusiveContext* cx, Native native,
|
||||||
// isSingleton implies isInterpreted.
|
// isSingleton implies isInterpreted.
|
||||||
if (native && !IsAsmJSModuleNative(native))
|
if (native && !IsAsmJSModuleNative(native))
|
||||||
newKind = SingletonObject;
|
newKind = SingletonObject;
|
||||||
|
#ifdef DEBUG
|
||||||
|
RootedObject nonScopeParent(cx, SkipScopeParent(enclosingDynamicScope));
|
||||||
|
// We'd like to assert that nonScopeParent is null-or-global, but
|
||||||
|
// js::ExecuteInGlobalAndReturnScope and debugger eval bits mess that up.
|
||||||
|
// Assert that it's one of those or a debug scope proxy or the unqualified
|
||||||
|
// var obj, since it should still be ok to parent to the global in that
|
||||||
|
// case.
|
||||||
|
MOZ_ASSERT(!nonScopeParent || nonScopeParent == cx->global() ||
|
||||||
|
nonScopeParent->is<DebugScopeObject>() ||
|
||||||
|
nonScopeParent->isUnqualifiedVarObj());
|
||||||
|
#endif
|
||||||
funobj = NewObjectWithClassProto(cx, &JSFunction::class_, proto, allocKind,
|
funobj = NewObjectWithClassProto(cx, &JSFunction::class_, proto, allocKind,
|
||||||
newKind);
|
newKind);
|
||||||
if (!funobj)
|
if (!funobj)
|
||||||
|
@ -2042,8 +2079,8 @@ js::NewFunctionWithProto(ExclusiveContext* cx, Native native,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
js::CanReuseScriptForClone(JSCompartment* compartment, HandleFunction fun,
|
js::CloneFunctionObjectUseSameScript(JSCompartment* compartment, HandleFunction fun,
|
||||||
HandleObject newParent)
|
HandleObject newParent)
|
||||||
{
|
{
|
||||||
if (compartment != fun->compartment() ||
|
if (compartment != fun->compartment() ||
|
||||||
fun->isSingleton() ||
|
fun->isSingleton() ||
|
||||||
|
@ -2064,36 +2101,75 @@ js::CanReuseScriptForClone(JSCompartment* compartment, HandleFunction fun,
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// We need to clone the script if we're interpreted and not already marked
|
// We need to clone the script if we're interpreted and not already marked
|
||||||
// as having a non-syntactic scope. If we're lazy, go ahead and clone the
|
// as having a polluted scope. If we're lazy, go ahead and clone the
|
||||||
// script; see the big comment at the end of CopyScriptInternal for the
|
// script; see the big comment at the end of CloneScript for the explanation
|
||||||
// explanation of what's going on there.
|
// of what's going on there.
|
||||||
return !fun->isInterpreted() ||
|
return !fun->isInterpreted() ||
|
||||||
(fun->hasScript() && fun->nonLazyScript()->hasNonSyntacticScope());
|
(fun->hasScript() && fun->nonLazyScript()->hasPollutedGlobalScope());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline JSFunction*
|
JSFunction*
|
||||||
NewFunctionClone(JSContext* cx, HandleFunction fun, NewObjectKind newKind,
|
js::CloneFunctionObject(JSContext* cx, HandleFunction fun, HandleObject parent,
|
||||||
gc::AllocKind allocKind, HandleObject proto)
|
gc::AllocKind allocKind,
|
||||||
|
NewObjectKind newKindArg /* = GenericObject */,
|
||||||
|
HandleObject proto)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(parent);
|
||||||
|
MOZ_ASSERT(!fun->isBoundFunction());
|
||||||
|
|
||||||
|
bool useSameScript = CloneFunctionObjectUseSameScript(cx->compartment(), fun, parent);
|
||||||
|
|
||||||
|
NewObjectKind newKind = useSameScript ? newKindArg : SingletonObject;
|
||||||
RootedObject cloneProto(cx, proto);
|
RootedObject cloneProto(cx, proto);
|
||||||
if (!proto && fun->isStarGenerator()) {
|
if (!cloneProto && fun->isStarGenerator()) {
|
||||||
cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
|
cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
|
||||||
if (!cloneProto)
|
if (!cloneProto)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
RootedObject realParent(cx, SkipScopeParent(parent));
|
||||||
|
// We'd like to assert that realParent is null-or-global, but
|
||||||
|
// js::ExecuteInGlobalAndReturnScope and debugger eval bits mess that up.
|
||||||
|
// Assert that it's one of those or a debug scope proxy or the unqualified
|
||||||
|
// var obj, since it should still be ok to parent to the global in that
|
||||||
|
// case.
|
||||||
|
MOZ_ASSERT(!realParent || realParent == cx->global() ||
|
||||||
|
realParent->is<DebugScopeObject>() ||
|
||||||
|
realParent->isUnqualifiedVarObj());
|
||||||
|
#endif
|
||||||
JSObject* cloneobj = NewObjectWithClassProto(cx, &JSFunction::class_, cloneProto,
|
JSObject* cloneobj = NewObjectWithClassProto(cx, &JSFunction::class_, cloneProto,
|
||||||
allocKind, newKind);
|
allocKind, newKind);
|
||||||
if (!cloneobj)
|
if (!cloneobj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
RootedFunction clone(cx, &cloneobj->as<JSFunction>());
|
RootedFunction clone(cx, &cloneobj->as<JSFunction>());
|
||||||
|
|
||||||
|
JSScript::AutoDelazify funScript(cx);
|
||||||
|
if (!useSameScript && fun->isInterpretedLazy()) {
|
||||||
|
funScript = fun;
|
||||||
|
if (!funScript)
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(useSameScript || !fun->isInterpretedLazy());
|
||||||
|
|
||||||
uint16_t flags = fun->flags() & ~JSFunction::EXTENDED;
|
uint16_t flags = fun->flags() & ~JSFunction::EXTENDED;
|
||||||
if (allocKind == AllocKind::FUNCTION_EXTENDED)
|
if (allocKind == AllocKind::FUNCTION_EXTENDED)
|
||||||
flags |= JSFunction::EXTENDED;
|
flags |= JSFunction::EXTENDED;
|
||||||
|
|
||||||
clone->setArgCount(fun->nargs());
|
clone->setArgCount(fun->nargs());
|
||||||
clone->setFlags(flags);
|
clone->setFlags(flags);
|
||||||
|
if (fun->hasScript()) {
|
||||||
|
clone->initScript(fun->nonLazyScript());
|
||||||
|
clone->initEnvironment(parent);
|
||||||
|
} else if (fun->isInterpretedLazy()) {
|
||||||
|
MOZ_ASSERT(fun->compartment() == clone->compartment());
|
||||||
|
MOZ_ASSERT(useSameScript);
|
||||||
|
LazyScript* lazy = fun->lazyScriptOrNull();
|
||||||
|
clone->initLazyScript(lazy);
|
||||||
|
clone->initEnvironment(parent);
|
||||||
|
} else {
|
||||||
|
clone->initNative(fun->native(), fun->jitInfo());
|
||||||
|
}
|
||||||
clone->initAtom(fun->displayAtom());
|
clone->initAtom(fun->displayAtom());
|
||||||
|
|
||||||
if (allocKind == AllocKind::FUNCTION_EXTENDED) {
|
if (allocKind == AllocKind::FUNCTION_EXTENDED) {
|
||||||
|
@ -2105,97 +2181,34 @@ NewFunctionClone(JSContext* cx, HandleFunction fun, NewObjectKind newKind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return clone;
|
if (useSameScript) {
|
||||||
}
|
/*
|
||||||
|
* Clone the function, reusing its script. We can use the same group as
|
||||||
JSFunction*
|
* the original function provided that its prototype is correct.
|
||||||
js::CloneFunctionReuseScript(JSContext* cx, HandleFunction fun, HandleObject parent,
|
*/
|
||||||
gc::AllocKind allocKind /* = FUNCTION */ ,
|
if (fun->getProto() == clone->getProto())
|
||||||
NewObjectKind newKind /* = GenericObject */,
|
clone->setGroup(fun->group());
|
||||||
HandleObject proto /* = nullptr */)
|
return clone;
|
||||||
{
|
|
||||||
MOZ_ASSERT(NewFunctionScopeIsWellFormed(cx, parent));
|
|
||||||
MOZ_ASSERT(!fun->isBoundFunction());
|
|
||||||
MOZ_ASSERT(CanReuseScriptForClone(cx->compartment(), fun, parent));
|
|
||||||
|
|
||||||
RootedFunction clone(cx, NewFunctionClone(cx, fun, newKind, allocKind, proto));
|
|
||||||
if (!clone)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (fun->hasScript()) {
|
|
||||||
clone->initScript(fun->nonLazyScript());
|
|
||||||
clone->initEnvironment(parent);
|
|
||||||
} else if (fun->isInterpretedLazy()) {
|
|
||||||
MOZ_ASSERT(fun->compartment() == clone->compartment());
|
|
||||||
LazyScript* lazy = fun->lazyScriptOrNull();
|
|
||||||
clone->initLazyScript(lazy);
|
|
||||||
clone->initEnvironment(parent);
|
|
||||||
} else {
|
|
||||||
clone->initNative(fun->native(), fun->jitInfo());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RootedFunction cloneRoot(cx, clone);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clone the function, reusing its script. We can use the same group as
|
* Across compartments or if we have to introduce a polluted scope we have
|
||||||
* the original function provided that its prototype is correct.
|
* to clone the script for interpreted functions. Cross-compartment cloning
|
||||||
|
* only happens via JSAPI (JS::CloneFunctionObject) which dynamically
|
||||||
|
* ensures that 'script' has no enclosing lexical scope (only the global
|
||||||
|
* scope or other non-lexical scope).
|
||||||
*/
|
*/
|
||||||
if (fun->getProto() == clone->getProto())
|
PollutedGlobalScopeOption globalScopeOption = parent->is<GlobalObject>() ?
|
||||||
clone->setGroup(fun->group());
|
HasCleanGlobalScope : HasPollutedGlobalScope;
|
||||||
return clone;
|
if (cloneRoot->isInterpreted() &&
|
||||||
}
|
!CloneFunctionScript(cx, fun, cloneRoot, globalScopeOption, newKindArg))
|
||||||
|
{
|
||||||
JSFunction*
|
|
||||||
js::CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject parent,
|
|
||||||
HandleObject newStaticScope,
|
|
||||||
gc::AllocKind allocKind /* = FUNCTION */,
|
|
||||||
HandleObject proto /* = nullptr */)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NewFunctionScopeIsWellFormed(cx, parent));
|
|
||||||
MOZ_ASSERT(!fun->isBoundFunction());
|
|
||||||
|
|
||||||
RootedFunction clone(cx, NewFunctionClone(cx, fun, SingletonObject, allocKind, proto));
|
|
||||||
if (!clone)
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (fun->hasScript()) {
|
|
||||||
clone->initScript(nullptr);
|
|
||||||
clone->initEnvironment(parent);
|
|
||||||
} else {
|
|
||||||
clone->initNative(fun->native(), fun->jitInfo());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
return cloneRoot;
|
||||||
* Across compartments or if we have to introduce a non-syntactic scope we
|
|
||||||
* have to clone the script for interpreted functions. Cross-compartment
|
|
||||||
* cloning only happens via JSAPI (JS::CloneFunctionObject) which
|
|
||||||
* dynamically ensures that 'script' has no enclosing lexical scope (only
|
|
||||||
* the global scope or other non-lexical scope).
|
|
||||||
*/
|
|
||||||
#ifdef DEBUG
|
|
||||||
RootedObject terminatingScope(cx, parent);
|
|
||||||
while (IsSyntacticScope(terminatingScope))
|
|
||||||
terminatingScope = terminatingScope->enclosingScope();
|
|
||||||
MOZ_ASSERT_IF(!terminatingScope->is<GlobalObject>(),
|
|
||||||
HasNonSyntacticStaticScopeChain(newStaticScope));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (clone->isInterpreted()) {
|
|
||||||
JSScript::AutoDelazify funScript(cx);
|
|
||||||
funScript = fun;
|
|
||||||
if (!funScript)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
RootedScript script(cx, fun->nonLazyScript());
|
|
||||||
MOZ_ASSERT(script->compartment() == fun->compartment());
|
|
||||||
MOZ_ASSERT(cx->compartment() == clone->compartment(),
|
|
||||||
"Otherwise we could relazify clone below!");
|
|
||||||
|
|
||||||
RootedScript clonedScript(cx, CloneScriptIntoFunction(cx, newStaticScope, clone, script));
|
|
||||||
if (!clonedScript)
|
|
||||||
return nullptr;
|
|
||||||
Debugger::onNewScript(cx, clonedScript);
|
|
||||||
}
|
|
||||||
|
|
||||||
return clone;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -633,20 +633,14 @@ class FunctionExtended : public JSFunction
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool
|
extern bool
|
||||||
CanReuseScriptForClone(JSCompartment* compartment, HandleFunction fun, HandleObject newParent);
|
CloneFunctionObjectUseSameScript(JSCompartment* compartment, HandleFunction fun,
|
||||||
|
HandleObject newParent);
|
||||||
|
|
||||||
extern JSFunction*
|
extern JSFunction*
|
||||||
CloneFunctionReuseScript(JSContext* cx, HandleFunction fun, HandleObject parent,
|
CloneFunctionObject(JSContext* cx, HandleFunction fun, HandleObject parent,
|
||||||
gc::AllocKind kind = gc::AllocKind::FUNCTION,
|
gc::AllocKind kind = gc::AllocKind::FUNCTION,
|
||||||
NewObjectKind newKindArg = GenericObject,
|
NewObjectKind newKindArg = GenericObject,
|
||||||
HandleObject proto = nullptr);
|
HandleObject proto = nullptr);
|
||||||
|
|
||||||
// Functions whose scripts are cloned are always given singleton types.
|
|
||||||
extern JSFunction*
|
|
||||||
CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject parent,
|
|
||||||
HandleObject newStaticScope,
|
|
||||||
gc::AllocKind kind = gc::AllocKind::FUNCTION,
|
|
||||||
HandleObject proto = nullptr);
|
|
||||||
|
|
||||||
extern bool
|
extern bool
|
||||||
FindBody(JSContext* cx, HandleFunction fun, HandleLinearString src, size_t* bodyStart,
|
FindBody(JSContext* cx, HandleFunction fun, HandleLinearString src, size_t* bodyStart,
|
||||||
|
@ -708,6 +702,10 @@ bool
|
||||||
XDRInterpretedFunction(XDRState<mode>* xdr, HandleObject enclosingScope,
|
XDRInterpretedFunction(XDRState<mode>* xdr, HandleObject enclosingScope,
|
||||||
HandleScript enclosingScript, MutableHandleFunction objp);
|
HandleScript enclosingScript, MutableHandleFunction objp);
|
||||||
|
|
||||||
|
extern JSObject*
|
||||||
|
CloneFunctionAndScript(JSContext* cx, HandleObject enclosingScope, HandleFunction fun,
|
||||||
|
PollutedGlobalScopeOption polluted);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Report an error that call.thisv is not compatible with the specified class,
|
* Report an error that call.thisv is not compatible with the specified class,
|
||||||
* assuming that the method (clasp->name).prototype.<name of callee function>
|
* assuming that the method (clasp->name).prototype.<name of callee function>
|
||||||
|
|
|
@ -85,12 +85,7 @@ CloneFunctionObjectIfNotSingleton(JSContext* cx, HandleFunction fun, HandleObjec
|
||||||
gc::AllocKind kind = fun->isExtended()
|
gc::AllocKind kind = fun->isExtended()
|
||||||
? extendedFinalizeKind
|
? extendedFinalizeKind
|
||||||
: finalizeKind;
|
: finalizeKind;
|
||||||
|
return CloneFunctionObject(cx, fun, parent, kind, newKind, proto);
|
||||||
if (CanReuseScriptForClone(cx->compartment(), fun, parent))
|
|
||||||
return CloneFunctionReuseScript(cx, fun, parent, kind, newKind, proto);
|
|
||||||
|
|
||||||
RootedObject staticScope(cx, fun->getOrCreateScript(cx)->enclosingStaticScope());
|
|
||||||
return CloneFunctionAndScript(cx, fun, parent, staticScope, kind, proto);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
|
@ -1076,7 +1076,7 @@ NewObjectGCKind(const js::Class* clasp)
|
||||||
|
|
||||||
static inline JSObject*
|
static inline JSObject*
|
||||||
NewObject(ExclusiveContext* cx, HandleObjectGroup group, gc::AllocKind kind,
|
NewObject(ExclusiveContext* cx, HandleObjectGroup group, gc::AllocKind kind,
|
||||||
NewObjectKind newKind, uint32_t initialShapeFlags = 0)
|
NewObjectKind newKind)
|
||||||
{
|
{
|
||||||
const Class* clasp = group->clasp();
|
const Class* clasp = group->clasp();
|
||||||
|
|
||||||
|
@ -1091,8 +1091,7 @@ NewObject(ExclusiveContext* cx, HandleObjectGroup group, gc::AllocKind kind,
|
||||||
? GetGCKindSlots(gc::GetGCObjectKind(clasp), clasp)
|
? GetGCKindSlots(gc::GetGCObjectKind(clasp), clasp)
|
||||||
: GetGCKindSlots(kind, clasp);
|
: GetGCKindSlots(kind, clasp);
|
||||||
|
|
||||||
RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, group->proto(), nfixed,
|
RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, group->proto(), nfixed));
|
||||||
initialShapeFlags));
|
|
||||||
if (!shape)
|
if (!shape)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -1140,8 +1139,7 @@ NewObjectWithTaggedProtoIsCachable(ExclusiveContext* cxArg, Handle<TaggedProto>
|
||||||
JSObject*
|
JSObject*
|
||||||
js::NewObjectWithGivenTaggedProto(ExclusiveContext* cxArg, const Class* clasp,
|
js::NewObjectWithGivenTaggedProto(ExclusiveContext* cxArg, const Class* clasp,
|
||||||
Handle<TaggedProto> proto,
|
Handle<TaggedProto> proto,
|
||||||
gc::AllocKind allocKind, NewObjectKind newKind,
|
gc::AllocKind allocKind, NewObjectKind newKind)
|
||||||
uint32_t initialShapeFlags)
|
|
||||||
{
|
{
|
||||||
if (CanBeFinalizedInBackground(allocKind, clasp))
|
if (CanBeFinalizedInBackground(allocKind, clasp))
|
||||||
allocKind = GetBackgroundAllocKind(allocKind);
|
allocKind = GetBackgroundAllocKind(allocKind);
|
||||||
|
@ -1163,7 +1161,7 @@ js::NewObjectWithGivenTaggedProto(ExclusiveContext* cxArg, const Class* clasp,
|
||||||
if (!group)
|
if (!group)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
RootedObject obj(cxArg, NewObject(cxArg, group, allocKind, newKind, initialShapeFlags));
|
RootedObject obj(cxArg, NewObject(cxArg, group, allocKind, newKind));
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
|
|
@ -422,10 +422,10 @@ class JSObject : public js::gc::Cell
|
||||||
* slot of the object. For other scope objects, the chain goes directly to
|
* slot of the object. For other scope objects, the chain goes directly to
|
||||||
* the global.
|
* the global.
|
||||||
*
|
*
|
||||||
* In code which is not marked hasNonSyntacticScope, scope chains can
|
* In code which is not marked hasPollutedGlobalScope, scope chains can
|
||||||
* contain only syntactic scope objects (see IsSyntacticScope) with a global
|
* contain only syntactic scope objects (see IsSyntacticScope) with a global
|
||||||
* object at the root as the scope of the outermost non-function script. In
|
* object at the root as the scope of the outermost non-function script. In
|
||||||
* hasNonSyntacticScope code, the scope of the outermost non-function
|
* hasPollutedGlobalScope code, the scope of the outermost non-function
|
||||||
* script might not be a global object, and can have a mix of other objects
|
* script might not be a global object, and can have a mix of other objects
|
||||||
* above it before the global object is reached.
|
* above it before the global object is reached.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -224,9 +224,6 @@ JSObject::isQualifiedVarObj()
|
||||||
{
|
{
|
||||||
if (is<js::DebugScopeObject>())
|
if (is<js::DebugScopeObject>())
|
||||||
return as<js::DebugScopeObject>().scope().isQualifiedVarObj();
|
return as<js::DebugScopeObject>().scope().isQualifiedVarObj();
|
||||||
// TODO: We would like to assert that only GlobalObject or
|
|
||||||
// NonSyntacticVariables object is a qualified varobj, but users of
|
|
||||||
// js::Execute still need to be vetted. See bug 1171177.
|
|
||||||
return hasAllFlags(js::BaseShape::QUALIFIED_VAROBJ);
|
return hasAllFlags(js::BaseShape::QUALIFIED_VAROBJ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,9 +232,7 @@ JSObject::isUnqualifiedVarObj()
|
||||||
{
|
{
|
||||||
if (is<js::DebugScopeObject>())
|
if (is<js::DebugScopeObject>())
|
||||||
return as<js::DebugScopeObject>().scope().isUnqualifiedVarObj();
|
return as<js::DebugScopeObject>().scope().isUnqualifiedVarObj();
|
||||||
bool rv = hasAllFlags(js::BaseShape::UNQUALIFIED_VAROBJ);
|
return hasAllFlags(js::BaseShape::UNQUALIFIED_VAROBJ);
|
||||||
MOZ_ASSERT_IF(rv, is<js::GlobalObject>() || is<js::NonSyntacticVariablesObject>());
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
@ -608,38 +603,25 @@ typedef AutoVectorRooter<PropertyDescriptor> AutoPropertyDescriptorVector;
|
||||||
*/
|
*/
|
||||||
JSObject*
|
JSObject*
|
||||||
NewObjectWithGivenTaggedProto(ExclusiveContext* cx, const Class* clasp, Handle<TaggedProto> proto,
|
NewObjectWithGivenTaggedProto(ExclusiveContext* cx, const Class* clasp, Handle<TaggedProto> proto,
|
||||||
gc::AllocKind allocKind, NewObjectKind newKind,
|
gc::AllocKind allocKind, NewObjectKind newKind);
|
||||||
uint32_t initialShapeFlags = 0);
|
|
||||||
|
|
||||||
inline JSObject*
|
inline JSObject*
|
||||||
NewObjectWithGivenTaggedProto(ExclusiveContext* cx, const Class* clasp, Handle<TaggedProto> proto,
|
NewObjectWithGivenTaggedProto(ExclusiveContext* cx, const Class* clasp, Handle<TaggedProto> proto,
|
||||||
NewObjectKind newKind = GenericObject,
|
NewObjectKind newKind = GenericObject)
|
||||||
uint32_t initialShapeFlags = 0)
|
|
||||||
{
|
{
|
||||||
gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
|
gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
|
||||||
return NewObjectWithGivenTaggedProto(cx, clasp, proto, allocKind, newKind, initialShapeFlags);
|
return NewObjectWithGivenTaggedProto(cx, clasp, proto, allocKind, newKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T*
|
inline T*
|
||||||
NewObjectWithGivenTaggedProto(ExclusiveContext* cx, Handle<TaggedProto> proto,
|
NewObjectWithGivenTaggedProto(ExclusiveContext* cx, Handle<TaggedProto> proto,
|
||||||
NewObjectKind newKind = GenericObject,
|
NewObjectKind newKind = GenericObject)
|
||||||
uint32_t initialShapeFlags = 0)
|
|
||||||
{
|
{
|
||||||
JSObject* obj = NewObjectWithGivenTaggedProto(cx, &T::class_, proto, newKind,
|
JSObject* obj = NewObjectWithGivenTaggedProto(cx, &T::class_, proto, newKind);
|
||||||
initialShapeFlags);
|
|
||||||
return obj ? &obj->as<T>() : nullptr;
|
return obj ? &obj->as<T>() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline T*
|
|
||||||
NewObjectWithNullTaggedProto(ExclusiveContext* cx, NewObjectKind newKind = GenericObject,
|
|
||||||
uint32_t initialShapeFlags = 0)
|
|
||||||
{
|
|
||||||
Rooted<TaggedProto> nullProto(cx, TaggedProto(nullptr));
|
|
||||||
return NewObjectWithGivenTaggedProto<T>(cx, nullProto, newKind, initialShapeFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline JSObject*
|
inline JSObject*
|
||||||
NewObjectWithGivenProto(ExclusiveContext* cx, const Class* clasp, HandleObject proto,
|
NewObjectWithGivenProto(ExclusiveContext* cx, const Class* clasp, HandleObject proto,
|
||||||
gc::AllocKind allocKind, NewObjectKind newKind)
|
gc::AllocKind allocKind, NewObjectKind newKind)
|
||||||
|
|
|
@ -576,10 +576,10 @@ enum XDRClassKind {
|
||||||
|
|
||||||
template<XDRMode mode>
|
template<XDRMode mode>
|
||||||
bool
|
bool
|
||||||
js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript enclosingScript,
|
js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
|
||||||
HandleFunction fun, MutableHandleScript scriptp)
|
HandleFunction fun, MutableHandleScript scriptp)
|
||||||
{
|
{
|
||||||
/* NB: Keep this in sync with CopyScript. */
|
/* NB: Keep this in sync with CloneScript. */
|
||||||
|
|
||||||
enum ScriptBits {
|
enum ScriptBits {
|
||||||
NoScriptRval,
|
NoScriptRval,
|
||||||
|
@ -600,7 +600,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
||||||
HasSingleton,
|
HasSingleton,
|
||||||
TreatAsRunOnce,
|
TreatAsRunOnce,
|
||||||
HasLazyScript,
|
HasLazyScript,
|
||||||
HasNonSyntacticScope,
|
HasPollutedGlobalScope,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t length, lineno, column, nslots, staticLevel;
|
uint32_t length, lineno, column, nslots, staticLevel;
|
||||||
|
@ -613,7 +613,6 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
||||||
|
|
||||||
JSContext* cx = xdr->cx();
|
JSContext* cx = xdr->cx();
|
||||||
RootedScript script(cx);
|
RootedScript script(cx);
|
||||||
RootedObject enclosingScope(cx, enclosingScopeArg);
|
|
||||||
natoms = nsrcnotes = 0;
|
natoms = nsrcnotes = 0;
|
||||||
nconsts = nobjects = nregexps = ntrynotes = nblockscopes = nyieldoffsets = 0;
|
nconsts = nobjects = nregexps = ntrynotes = nblockscopes = nyieldoffsets = 0;
|
||||||
|
|
||||||
|
@ -733,8 +732,8 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
||||||
scriptBits |= (1 << TreatAsRunOnce);
|
scriptBits |= (1 << TreatAsRunOnce);
|
||||||
if (script->isRelazifiable())
|
if (script->isRelazifiable())
|
||||||
scriptBits |= (1 << HasLazyScript);
|
scriptBits |= (1 << HasLazyScript);
|
||||||
if (script->hasNonSyntacticScope())
|
if (script->hasPollutedGlobalScope())
|
||||||
scriptBits |= (1 << HasNonSyntacticScope);
|
scriptBits |= (1 << HasPollutedGlobalScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!xdr->codeUint32(&prologueLength))
|
if (!xdr->codeUint32(&prologueLength))
|
||||||
|
@ -802,26 +801,10 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
||||||
MOZ_ASSERT(enclosingScript->sourceObject()->is<ScriptSourceObject>());
|
MOZ_ASSERT(enclosingScript->sourceObject()->is<ScriptSourceObject>());
|
||||||
sourceObject = &enclosingScript->sourceObject()->as<ScriptSourceObject>();
|
sourceObject = &enclosingScript->sourceObject()->as<ScriptSourceObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the outermost script has a non-syntactic scope, reflect that on
|
|
||||||
// the static scope chain.
|
|
||||||
if (scriptBits & (1 << HasNonSyntacticScope) && !enclosingScope) {
|
|
||||||
enclosingScope = StaticNonSyntacticScopeObjects::create(cx, nullptr);
|
|
||||||
if (!enclosingScope)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
script = JSScript::Create(cx, enclosingScope, !!(scriptBits & (1 << SavedCallerFun)),
|
script = JSScript::Create(cx, enclosingScope, !!(scriptBits & (1 << SavedCallerFun)),
|
||||||
options, /* staticLevel = */ 0, sourceObject, 0, 0);
|
options, /* staticLevel = */ 0, sourceObject, 0, 0);
|
||||||
if (!script)
|
if (!script)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Set the script in its function now so that inner scripts to be
|
|
||||||
// decoded may iterate the static scope chain.
|
|
||||||
if (fun) {
|
|
||||||
fun->initScript(script);
|
|
||||||
script->setFunction(fun);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* JSScript::partiallyInit assumes script->bindings is fully initialized. */
|
/* JSScript::partiallyInit assumes script->bindings is fully initialized. */
|
||||||
|
@ -866,8 +849,8 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
||||||
script->hasSingletons_ = true;
|
script->hasSingletons_ = true;
|
||||||
if (scriptBits & (1 << TreatAsRunOnce))
|
if (scriptBits & (1 << TreatAsRunOnce))
|
||||||
script->treatAsRunOnce_ = true;
|
script->treatAsRunOnce_ = true;
|
||||||
if (scriptBits & (1 << HasNonSyntacticScope))
|
if (scriptBits & (1 << HasPollutedGlobalScope))
|
||||||
script->hasNonSyntacticScope_ = true;
|
script->hasPollutedGlobalScope_ = true;
|
||||||
|
|
||||||
if (scriptBits & (1 << IsLegacyGenerator)) {
|
if (scriptBits & (1 << IsLegacyGenerator)) {
|
||||||
MOZ_ASSERT(!(scriptBits & (1 << IsStarGenerator)));
|
MOZ_ASSERT(!(scriptBits & (1 << IsStarGenerator)));
|
||||||
|
@ -999,7 +982,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
||||||
MOZ_ASSERT(enclosingStaticScopeIndex < i);
|
MOZ_ASSERT(enclosingStaticScopeIndex < i);
|
||||||
enclosingStaticScope = script->objects()->vector[enclosingStaticScopeIndex];
|
enclosingStaticScope = script->objects()->vector[enclosingStaticScopeIndex];
|
||||||
} else {
|
} else {
|
||||||
enclosingStaticScope = fun ? fun : enclosingScope;
|
enclosingStaticScope = fun;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1036,15 +1019,8 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
||||||
|
|
||||||
StaticScopeIter<NoGC> ssi(funEnclosingScope);
|
StaticScopeIter<NoGC> ssi(funEnclosingScope);
|
||||||
|
|
||||||
// Starting from a nested function, hitting a non-syntactic
|
if (ssi.done() || ssi.type() == StaticScopeIter<NoGC>::Function) {
|
||||||
// scope on the static scope chain means that its enclosing
|
MOZ_ASSERT(ssi.done() == !fun);
|
||||||
// function has a non-syntactic scope. Nested functions
|
|
||||||
// themselves never have non-syntactic scope chains.
|
|
||||||
if (ssi.done() ||
|
|
||||||
ssi.type() == StaticScopeIter<NoGC>::NonSyntactic ||
|
|
||||||
ssi.type() == StaticScopeIter<NoGC>::Function)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT_IF(ssi.done() || ssi.type() != StaticScopeIter<NoGC>::Function, !fun);
|
|
||||||
funEnclosingScopeIndex = UINT32_MAX;
|
funEnclosingScopeIndex = UINT32_MAX;
|
||||||
} else if (ssi.type() == StaticScopeIter<NoGC>::Block) {
|
} else if (ssi.type() == StaticScopeIter<NoGC>::Block) {
|
||||||
funEnclosingScopeIndex = FindScopeObjectIndex(script, ssi.block());
|
funEnclosingScopeIndex = FindScopeObjectIndex(script, ssi.block());
|
||||||
|
@ -1060,7 +1036,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
||||||
|
|
||||||
if (mode == XDR_DECODE) {
|
if (mode == XDR_DECODE) {
|
||||||
if (funEnclosingScopeIndex == UINT32_MAX) {
|
if (funEnclosingScopeIndex == UINT32_MAX) {
|
||||||
funEnclosingScope = fun ? fun : enclosingScope;
|
funEnclosingScope = fun;
|
||||||
} else {
|
} else {
|
||||||
MOZ_ASSERT(funEnclosingScopeIndex < i);
|
MOZ_ASSERT(funEnclosingScopeIndex < i);
|
||||||
funEnclosingScope = script->objects()->vector[funEnclosingScopeIndex];
|
funEnclosingScope = script->objects()->vector[funEnclosingScopeIndex];
|
||||||
|
@ -1201,13 +1177,9 @@ js::XDRLazyScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == XDR_DECODE) {
|
if (mode == XDR_DECODE)
|
||||||
lazy.set(LazyScript::Create(cx, fun, nullptr, enclosingScope, enclosingScript,
|
lazy.set(LazyScript::Create(cx, fun, nullptr, enclosingScope, enclosingScript,
|
||||||
packedFields, begin, end, lineno, column));
|
packedFields, begin, end, lineno, column));
|
||||||
if (!lazy)
|
|
||||||
return false;
|
|
||||||
fun->initLazyScript(lazy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Code free variables.
|
// Code free variables.
|
||||||
|
@ -2457,16 +2429,11 @@ JSScript::Create(ExclusiveContext* cx, HandleObject enclosingScope, bool savedCa
|
||||||
script->savedCallerFun_ = savedCallerFun;
|
script->savedCallerFun_ = savedCallerFun;
|
||||||
script->initCompartment(cx);
|
script->initCompartment(cx);
|
||||||
|
|
||||||
|
script->hasPollutedGlobalScope_ = options.hasPollutedGlobalScope;
|
||||||
script->selfHosted_ = options.selfHostingMode;
|
script->selfHosted_ = options.selfHostingMode;
|
||||||
script->noScriptRval_ = options.noScriptRval;
|
script->noScriptRval_ = options.noScriptRval;
|
||||||
script->treatAsRunOnce_ = options.isRunOnce;
|
script->treatAsRunOnce_ = options.isRunOnce;
|
||||||
|
|
||||||
// Compute whether this script is under a non-syntactic scope. We don't
|
|
||||||
// need to walk the entire static scope chain if the script is nested in a
|
|
||||||
// function. In that case, we can propagate the cached value from the
|
|
||||||
// outer script.
|
|
||||||
script->hasNonSyntacticScope_ = HasNonSyntacticStaticScopeChain(enclosingScope);
|
|
||||||
|
|
||||||
script->version = options.version;
|
script->version = options.version;
|
||||||
MOZ_ASSERT(script->getVersion() == options.version); // assert that no overflow occurred
|
MOZ_ASSERT(script->getVersion() == options.version); // assert that no overflow occurred
|
||||||
|
|
||||||
|
@ -2701,13 +2668,10 @@ JSScript::fullyInitFromEmitter(ExclusiveContext* cx, HandleScript script, Byteco
|
||||||
|
|
||||||
RootedFunction fun(cx, nullptr);
|
RootedFunction fun(cx, nullptr);
|
||||||
if (funbox) {
|
if (funbox) {
|
||||||
// The function should have already been earlier to enable
|
|
||||||
// StaticScopeIter to walk the static scope chain of
|
|
||||||
// currently compiling scripts.
|
|
||||||
MOZ_ASSERT(script->functionNonDelazifying() == funbox->function());
|
|
||||||
MOZ_ASSERT(!bce->script->noScriptRval());
|
MOZ_ASSERT(!bce->script->noScriptRval());
|
||||||
script->isGeneratorExp_ = funbox->inGenexpLambda;
|
script->isGeneratorExp_ = funbox->inGenexpLambda;
|
||||||
script->setGeneratorKind(funbox->generatorKind());
|
script->setGeneratorKind(funbox->generatorKind());
|
||||||
|
script->setFunction(funbox->function());
|
||||||
if (bce->yieldOffsetList.length() != 0)
|
if (bce->yieldOffsetList.length() != 0)
|
||||||
bce->yieldOffsetList.finish(script->yieldOffsets(), prologueLength);
|
bce->yieldOffsetList.finish(script->yieldOffsets(), prologueLength);
|
||||||
}
|
}
|
||||||
|
@ -3040,48 +3004,15 @@ Rebase(JSScript* dst, JSScript* src, T* srcp)
|
||||||
return reinterpret_cast<T*>(dst->data + off);
|
return reinterpret_cast<T*>(dst->data + off);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSObject*
|
JSScript*
|
||||||
CloneInnerInterpretedFunction(JSContext* cx, HandleObject enclosingScope, HandleFunction srcFun)
|
js::CloneScript(JSContext* cx, HandleObject enclosingScope, HandleFunction fun, HandleScript src,
|
||||||
{
|
PollutedGlobalScopeOption polluted /* = HasCleanGlobalScope */,
|
||||||
/* NB: Keep this in sync with XDRInterpretedFunction. */
|
NewObjectKind newKind /* = GenericObject */)
|
||||||
RootedObject cloneProto(cx);
|
|
||||||
if (srcFun->isStarGenerator()) {
|
|
||||||
cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
|
|
||||||
if (!cloneProto)
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
gc::AllocKind allocKind = srcFun->getAllocKind();
|
|
||||||
RootedFunction clone(cx, NewFunctionWithProto(cx, nullptr, 0,
|
|
||||||
JSFunction::INTERPRETED, nullptr, nullptr,
|
|
||||||
cloneProto, allocKind, TenuredObject));
|
|
||||||
if (!clone)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
JSScript::AutoDelazify srcScript(cx, srcFun);
|
|
||||||
if (!srcScript)
|
|
||||||
return nullptr;
|
|
||||||
JSScript* cloneScript = CloneScriptIntoFunction(cx, enclosingScope, clone, srcScript);
|
|
||||||
if (!cloneScript)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
clone->setArgCount(srcFun->nargs());
|
|
||||||
clone->setFlags(srcFun->flags());
|
|
||||||
clone->initAtom(srcFun->displayAtom());
|
|
||||||
if (!JSFunction::setTypeForScriptedFunction(cx, clone))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScript src,
|
|
||||||
HandleScript dst)
|
|
||||||
{
|
{
|
||||||
if (src->treatAsRunOnce() && !src->functionNonDelazifying()) {
|
if (src->treatAsRunOnce() && !src->functionNonDelazifying()) {
|
||||||
// Toplevel run-once scripts may not be cloned.
|
// Toplevel run-once scripts may not be cloned.
|
||||||
JS_ReportError(cx, "No cloning toplevel run-once scripts");
|
JS_ReportError(cx, "No cloning toplevel run-once scripts");
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NB: Keep this in sync with XDRScript. */
|
/* NB: Keep this in sync with XDRScript. */
|
||||||
|
@ -3100,7 +3031,7 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
|
||||||
size_t size = src->dataSize();
|
size_t size = src->dataSize();
|
||||||
uint8_t* data = AllocScriptData(cx->zone(), size);
|
uint8_t* data = AllocScriptData(cx->zone(), size);
|
||||||
if (size && !data)
|
if (size && !data)
|
||||||
return false;
|
return nullptr;
|
||||||
|
|
||||||
/* Bindings */
|
/* Bindings */
|
||||||
|
|
||||||
|
@ -3108,7 +3039,7 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
|
||||||
InternalHandle<Bindings*> bindingsHandle =
|
InternalHandle<Bindings*> bindingsHandle =
|
||||||
InternalHandle<Bindings*>::fromMarkedLocation(bindings.address());
|
InternalHandle<Bindings*>::fromMarkedLocation(bindings.address());
|
||||||
if (!Bindings::clone(cx, bindingsHandle, data, src))
|
if (!Bindings::clone(cx, bindingsHandle, data, src))
|
||||||
return false;
|
return nullptr;
|
||||||
|
|
||||||
/* Objects */
|
/* Objects */
|
||||||
|
|
||||||
|
@ -3125,7 +3056,7 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
|
||||||
if (NestedScopeObject* enclosingBlock = innerBlock->enclosingNestedScope())
|
if (NestedScopeObject* enclosingBlock = innerBlock->enclosingNestedScope())
|
||||||
enclosingScope = objects[FindScopeObjectIndex(src, *enclosingBlock)];
|
enclosingScope = objects[FindScopeObjectIndex(src, *enclosingBlock)];
|
||||||
else
|
else
|
||||||
enclosingScope = scriptStaticScope;
|
enclosingScope = fun;
|
||||||
|
|
||||||
clone = CloneNestedScopeObject(cx, enclosingScope, innerBlock);
|
clone = CloneNestedScopeObject(cx, enclosingScope, innerBlock);
|
||||||
} else if (obj->is<JSFunction>()) {
|
} else if (obj->is<JSFunction>()) {
|
||||||
|
@ -3134,36 +3065,32 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
|
||||||
if (cx->compartment() != innerFun->compartment()) {
|
if (cx->compartment() != innerFun->compartment()) {
|
||||||
MOZ_ASSERT(innerFun->isAsmJSNative());
|
MOZ_ASSERT(innerFun->isAsmJSNative());
|
||||||
JS_ReportError(cx, "AsmJS modules do not yet support cloning.");
|
JS_ReportError(cx, "AsmJS modules do not yet support cloning.");
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
clone = innerFun;
|
clone = innerFun;
|
||||||
} else {
|
} else {
|
||||||
if (innerFun->isInterpretedLazy()) {
|
if (innerFun->isInterpretedLazy()) {
|
||||||
AutoCompartment ac(cx, innerFun);
|
AutoCompartment ac(cx, innerFun);
|
||||||
if (!innerFun->getOrCreateScript(cx))
|
if (!innerFun->getOrCreateScript(cx))
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
RootedObject staticScope(cx, innerFun->nonLazyScript()->enclosingStaticScope());
|
RootedObject staticScope(cx, innerFun->nonLazyScript()->enclosingStaticScope());
|
||||||
StaticScopeIter<CanGC> ssi(cx, staticScope);
|
StaticScopeIter<CanGC> ssi(cx, staticScope);
|
||||||
RootedObject enclosingScope(cx);
|
RootedObject enclosingScope(cx);
|
||||||
if (ssi.done() || ssi.type() == StaticScopeIter<CanGC>::NonSyntactic) {
|
if (ssi.done() || ssi.type() == StaticScopeIter<CanGC>::Function)
|
||||||
enclosingScope = scriptStaticScope;
|
enclosingScope = fun;
|
||||||
} else if (ssi.type() == StaticScopeIter<CanGC>::Function) {
|
else if (ssi.type() == StaticScopeIter<CanGC>::Block)
|
||||||
MOZ_ASSERT(scriptStaticScope->is<JSFunction>());
|
|
||||||
enclosingScope = scriptStaticScope;
|
|
||||||
} else if (ssi.type() == StaticScopeIter<CanGC>::Block) {
|
|
||||||
enclosingScope = objects[FindScopeObjectIndex(src, ssi.block())];
|
enclosingScope = objects[FindScopeObjectIndex(src, ssi.block())];
|
||||||
} else {
|
else
|
||||||
enclosingScope = objects[FindScopeObjectIndex(src, ssi.staticWith())];
|
enclosingScope = objects[FindScopeObjectIndex(src, ssi.staticWith())];
|
||||||
}
|
|
||||||
|
|
||||||
clone = CloneInnerInterpretedFunction(cx, enclosingScope, innerFun);
|
clone = CloneFunctionAndScript(cx, enclosingScope, innerFun, polluted);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
clone = DeepCloneObjectLiteral(cx, obj, TenuredObject);
|
clone = DeepCloneObjectLiteral(cx, obj, TenuredObject);
|
||||||
}
|
}
|
||||||
if (!clone || !objects.append(clone))
|
if (!clone || !objects.append(clone))
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3175,11 +3102,50 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
|
||||||
for (unsigned i = 0; i < nregexps; i++) {
|
for (unsigned i = 0; i < nregexps; i++) {
|
||||||
JSObject* clone = CloneScriptRegExpObject(cx, vector[i]->as<RegExpObject>());
|
JSObject* clone = CloneScriptRegExpObject(cx, vector[i]->as<RegExpObject>());
|
||||||
if (!clone || !regexps.append(clone))
|
if (!clone || !regexps.append(clone))
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now that all fallible allocation is complete, do the copying. */
|
/*
|
||||||
|
* Wrap the script source object as needed. Self-hosted scripts may be
|
||||||
|
* in another runtime, so lazily create a new script source object to
|
||||||
|
* use for them.
|
||||||
|
*/
|
||||||
|
RootedObject sourceObject(cx);
|
||||||
|
if (cx->runtime()->isSelfHostingCompartment(src->compartment())) {
|
||||||
|
if (!cx->compartment()->selfHostingScriptSource) {
|
||||||
|
CompileOptions options(cx);
|
||||||
|
FillSelfHostingCompileOptions(options);
|
||||||
|
|
||||||
|
ScriptSourceObject* obj = frontend::CreateScriptSourceObject(cx, options);
|
||||||
|
if (!obj)
|
||||||
|
return nullptr;
|
||||||
|
cx->compartment()->selfHostingScriptSource.set(obj);
|
||||||
|
}
|
||||||
|
sourceObject = cx->compartment()->selfHostingScriptSource;
|
||||||
|
} else {
|
||||||
|
sourceObject = src->sourceObject();
|
||||||
|
if (!cx->compartment()->wrap(cx, &sourceObject))
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now that all fallible allocation is complete, create the GC thing. */
|
||||||
|
|
||||||
|
CompileOptions options(cx);
|
||||||
|
options.setMutedErrors(src->mutedErrors())
|
||||||
|
.setHasPollutedScope(src->hasPollutedGlobalScope() ||
|
||||||
|
polluted == HasPollutedGlobalScope)
|
||||||
|
.setSelfHostingMode(src->selfHosted())
|
||||||
|
.setNoScriptRval(src->noScriptRval())
|
||||||
|
.setVersion(src->getVersion());
|
||||||
|
|
||||||
|
RootedScript dst(cx, JSScript::Create(cx, enclosingScope, src->savedCallerFun(),
|
||||||
|
options, src->staticLevel(),
|
||||||
|
sourceObject, src->sourceStart(), src->sourceEnd()));
|
||||||
|
if (!dst) {
|
||||||
|
js_free(data);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
dst->bindings = bindings;
|
dst->bindings = bindings;
|
||||||
|
|
||||||
|
@ -3241,107 +3207,61 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function delazification assumes that their script does not have a
|
* Function delazification assumes that their script does not have a
|
||||||
* non-syntactic global scope. We ensure that as follows:
|
* polluted global scope. We ensure that as follows:
|
||||||
*
|
*
|
||||||
* 1) Initial parsing only creates lazy functions if
|
* 1) Initial parsing only creates lazy functions if
|
||||||
* !hasNonSyntacticScope.
|
* !hasPollutedGlobalScope.
|
||||||
* 2) Cloning a lazy function into a non-global scope will always require
|
* 2) Cloning a lazy function into a non-global scope will always require
|
||||||
* that its script be cloned. See comments in
|
* that its script be cloned. See comments in
|
||||||
* CloneFunctionObjectUseSameScript.
|
* CloneFunctionObjectUseSameScript.
|
||||||
* 3) Cloning a script never sets a lazyScript on the clone, so the function
|
* 3) Cloning a script never sets a lazyScript on the clone, so the function
|
||||||
* cannot be relazified.
|
* cannot be relazified.
|
||||||
*
|
*
|
||||||
* If you decide that lazy functions should be supported with a
|
* If you decide that lazy functions should be supported with a polluted
|
||||||
* non-syntactic global scope, make sure delazification can deal.
|
* global scope, make sure delazification can deal.
|
||||||
*/
|
*/
|
||||||
MOZ_ASSERT_IF(dst->hasNonSyntacticScope(), !dst->maybeLazyScript());
|
MOZ_ASSERT_IF(dst->hasPollutedGlobalScope(), !dst->maybeLazyScript());
|
||||||
MOZ_ASSERT_IF(dst->hasNonSyntacticScope(), !dst->isRelazifiable());
|
MOZ_ASSERT_IF(dst->hasPollutedGlobalScope(), !dst->isRelazifiable());
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
js::CloneFunctionScript(JSContext* cx, HandleFunction original, HandleFunction clone,
|
||||||
|
PollutedGlobalScopeOption polluted, NewObjectKind newKind)
|
||||||
|
{
|
||||||
|
RootedScript script(cx, clone->nonLazyScript());
|
||||||
|
MOZ_ASSERT(script);
|
||||||
|
MOZ_ASSERT(script->compartment() == original->compartment());
|
||||||
|
MOZ_ASSERT(cx->compartment() == clone->compartment(),
|
||||||
|
"Otherwise we could relazify clone below!");
|
||||||
|
|
||||||
|
// The only scripts with enclosing static scopes that may be cloned across
|
||||||
|
// compartments are non-strict, indirect eval scripts, as their dynamic
|
||||||
|
// scope chains terminate in the global scope immediately.
|
||||||
|
RootedObject scope(cx, script->enclosingStaticScope());
|
||||||
|
if (script->compartment() != cx->compartment() && scope) {
|
||||||
|
MOZ_ASSERT(!scope->as<StaticEvalObject>().isDirect() &&
|
||||||
|
!scope->as<StaticEvalObject>().isStrict());
|
||||||
|
scope = StaticEvalObject::create(cx, nullptr);
|
||||||
|
if (!scope)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
clone->initScript(nullptr);
|
||||||
|
|
||||||
|
JSScript* cscript = CloneScript(cx, scope, clone, script, polluted, newKind);
|
||||||
|
if (!cscript)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
clone->setScript(cscript);
|
||||||
|
cscript->setFunction(clone);
|
||||||
|
|
||||||
|
script = clone->nonLazyScript();
|
||||||
|
Debugger::onNewScript(cx, script);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSScript*
|
|
||||||
CreateEmptyScriptForClone(JSContext* cx, HandleObject enclosingScope, HandleScript src)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Wrap the script source object as needed. Self-hosted scripts may be
|
|
||||||
* in another runtime, so lazily create a new script source object to
|
|
||||||
* use for them.
|
|
||||||
*/
|
|
||||||
RootedObject sourceObject(cx);
|
|
||||||
if (cx->runtime()->isSelfHostingCompartment(src->compartment())) {
|
|
||||||
if (!cx->compartment()->selfHostingScriptSource) {
|
|
||||||
CompileOptions options(cx);
|
|
||||||
FillSelfHostingCompileOptions(options);
|
|
||||||
|
|
||||||
ScriptSourceObject* obj = frontend::CreateScriptSourceObject(cx, options);
|
|
||||||
if (!obj)
|
|
||||||
return nullptr;
|
|
||||||
cx->compartment()->selfHostingScriptSource.set(obj);
|
|
||||||
}
|
|
||||||
sourceObject = cx->compartment()->selfHostingScriptSource;
|
|
||||||
} else {
|
|
||||||
sourceObject = src->sourceObject();
|
|
||||||
if (!cx->compartment()->wrap(cx, &sourceObject))
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
CompileOptions options(cx);
|
|
||||||
options.setMutedErrors(src->mutedErrors())
|
|
||||||
.setSelfHostingMode(src->selfHosted())
|
|
||||||
.setNoScriptRval(src->noScriptRval())
|
|
||||||
.setVersion(src->getVersion());
|
|
||||||
|
|
||||||
return JSScript::Create(cx, enclosingScope, src->savedCallerFun(),
|
|
||||||
options, src->staticLevel(),
|
|
||||||
sourceObject, src->sourceStart(), src->sourceEnd());
|
|
||||||
}
|
|
||||||
|
|
||||||
JSScript*
|
|
||||||
js::CloneGlobalScript(JSContext* cx, Handle<ScopeObject*> enclosingScope, HandleScript src)
|
|
||||||
{
|
|
||||||
// No enclosingScope means clean global.
|
|
||||||
MOZ_ASSERT(!enclosingScope || enclosingScope->is<StaticNonSyntacticScopeObjects>());
|
|
||||||
|
|
||||||
RootedScript dst(cx, CreateEmptyScriptForClone(cx, enclosingScope, src));
|
|
||||||
if (!dst)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (!detail::CopyScript(cx, enclosingScope, src, dst))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSScript*
|
|
||||||
js::CloneScriptIntoFunction(JSContext* cx, HandleObject enclosingScope, HandleFunction fun,
|
|
||||||
HandleScript src)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(fun->isInterpreted());
|
|
||||||
|
|
||||||
// Allocate the destination script up front and set it as the script of
|
|
||||||
// |fun|, which is to be its container.
|
|
||||||
//
|
|
||||||
// This is so that when cloning nested functions, they can walk the static
|
|
||||||
// scope chain via fun and correctly compute the presence of a
|
|
||||||
// non-syntactic global.
|
|
||||||
RootedScript dst(cx, CreateEmptyScriptForClone(cx, enclosingScope, src));
|
|
||||||
if (!dst)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
dst->setFunction(fun);
|
|
||||||
if (fun->isInterpretedLazy())
|
|
||||||
fun->setUnlazifiedScript(dst);
|
|
||||||
else
|
|
||||||
fun->initScript(dst);
|
|
||||||
|
|
||||||
if (!detail::CopyScript(cx, fun, src, dst)) {
|
|
||||||
fun->setScript(nullptr);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugScript*
|
DebugScript*
|
||||||
JSScript::debugScript()
|
JSScript::debugScript()
|
||||||
{
|
{
|
||||||
|
|
|
@ -755,6 +755,16 @@ bool
|
||||||
XDRScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
|
XDRScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
|
||||||
HandleFunction fun, MutableHandleScript scriptp);
|
HandleFunction fun, MutableHandleScript scriptp);
|
||||||
|
|
||||||
|
enum PollutedGlobalScopeOption {
|
||||||
|
HasPollutedGlobalScope,
|
||||||
|
HasCleanGlobalScope
|
||||||
|
};
|
||||||
|
|
||||||
|
JSScript*
|
||||||
|
CloneScript(JSContext* cx, HandleObject enclosingScope, HandleFunction fun, HandleScript script,
|
||||||
|
PollutedGlobalScopeOption polluted = HasCleanGlobalScope,
|
||||||
|
NewObjectKind newKind = GenericObject);
|
||||||
|
|
||||||
template<XDRMode mode>
|
template<XDRMode mode>
|
||||||
bool
|
bool
|
||||||
XDRLazyScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
|
XDRLazyScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
|
||||||
|
@ -767,16 +777,6 @@ template<XDRMode mode>
|
||||||
bool
|
bool
|
||||||
XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp);
|
XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp);
|
||||||
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
// Do not call this directly! It is exposed for the friend declaration in
|
|
||||||
// JSScript.
|
|
||||||
bool
|
|
||||||
CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScript src, HandleScript dst);
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
class JSScript : public js::gc::TenuredCell
|
class JSScript : public js::gc::TenuredCell
|
||||||
|
@ -784,13 +784,13 @@ class JSScript : public js::gc::TenuredCell
|
||||||
template <js::XDRMode mode>
|
template <js::XDRMode mode>
|
||||||
friend
|
friend
|
||||||
bool
|
bool
|
||||||
js::XDRScript(js::XDRState<mode>* xdr, js::HandleObject enclosingScope,
|
js::XDRScript(js::XDRState<mode>* xdr, js::HandleObject enclosingScope, js::HandleScript enclosingScript,
|
||||||
js::HandleScript enclosingScript,
|
|
||||||
js::HandleFunction fun, js::MutableHandleScript scriptp);
|
js::HandleFunction fun, js::MutableHandleScript scriptp);
|
||||||
|
|
||||||
friend bool
|
friend JSScript*
|
||||||
js::detail::CopyScript(JSContext* cx, js::HandleObject scriptStaticScope, js::HandleScript src,
|
js::CloneScript(JSContext* cx, js::HandleObject enclosingScope, js::HandleFunction fun,
|
||||||
js::HandleScript dst);
|
js::HandleScript src, js::PollutedGlobalScopeOption polluted,
|
||||||
|
js::NewObjectKind newKind);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//
|
//
|
||||||
|
@ -936,7 +936,7 @@ class JSScript : public js::gc::TenuredCell
|
||||||
// True if the script has a non-syntactic scope on its dynamic scope chain.
|
// True if the script has a non-syntactic scope on its dynamic scope chain.
|
||||||
// That is, there are objects about which we know nothing between the
|
// That is, there are objects about which we know nothing between the
|
||||||
// outermost syntactic scope and the global.
|
// outermost syntactic scope and the global.
|
||||||
bool hasNonSyntacticScope_:1;
|
bool hasPollutedGlobalScope_:1;
|
||||||
|
|
||||||
// see Parser::selfHostingMode.
|
// see Parser::selfHostingMode.
|
||||||
bool selfHosted_:1;
|
bool selfHosted_:1;
|
||||||
|
@ -1176,8 +1176,8 @@ class JSScript : public js::gc::TenuredCell
|
||||||
|
|
||||||
bool explicitUseStrict() const { return explicitUseStrict_; }
|
bool explicitUseStrict() const { return explicitUseStrict_; }
|
||||||
|
|
||||||
bool hasNonSyntacticScope() const {
|
bool hasPollutedGlobalScope() const {
|
||||||
return hasNonSyntacticScope_;
|
return hasPollutedGlobalScope_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool selfHosted() const { return selfHosted_; }
|
bool selfHosted() const { return selfHosted_; }
|
||||||
|
@ -2278,12 +2278,9 @@ DescribeScriptedCallerForCompilation(JSContext* cx, MutableHandleScript maybeScr
|
||||||
uint32_t* pcOffset, bool* mutedErrors,
|
uint32_t* pcOffset, bool* mutedErrors,
|
||||||
LineOption opt = NOT_CALLED_FROM_JSOP_EVAL);
|
LineOption opt = NOT_CALLED_FROM_JSOP_EVAL);
|
||||||
|
|
||||||
JSScript*
|
bool
|
||||||
CloneScriptIntoFunction(JSContext* cx, HandleObject enclosingScope, HandleFunction fun,
|
CloneFunctionScript(JSContext* cx, HandleFunction original, HandleFunction clone,
|
||||||
HandleScript src);
|
PollutedGlobalScopeOption polluted, NewObjectKind newKind);
|
||||||
|
|
||||||
JSScript*
|
|
||||||
CloneGlobalScript(JSContext* cx, Handle<ScopeObject*> enclosingScope, HandleScript src);
|
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
|
|
|
@ -4318,36 +4318,6 @@ ReflectTrackedOptimizations(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static bool
|
|
||||||
DumpStaticScopeChain(JSContext* cx, unsigned argc, Value* vp)
|
|
||||||
{
|
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
|
||||||
RootedObject callee(cx, &args.callee());
|
|
||||||
|
|
||||||
if (args.length() != 1) {
|
|
||||||
ReportUsageError(cx, callee, "Wrong number of arguments");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!args[0].isObject() || !args[0].toObject().is<JSFunction>()) {
|
|
||||||
ReportUsageError(cx, callee, "Argument must be an interpreted function");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
|
|
||||||
if (!fun->isInterpreted()) {
|
|
||||||
ReportUsageError(cx, callee, "Argument must be an interpreted function");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
js::DumpStaticScopeChain(fun->getOrCreateScript(cx));
|
|
||||||
|
|
||||||
args.rval().setUndefined();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
namespace shell {
|
namespace shell {
|
||||||
|
|
||||||
|
@ -4996,12 +4966,6 @@ static const JSFunctionSpecWithHelp fuzzing_unsafe_functions[] = {
|
||||||
" any. If |fun| is not a scripted function or has not been compiled by\n"
|
" any. If |fun| is not a scripted function or has not been compiled by\n"
|
||||||
" Ion, null is returned."),
|
" Ion, null is returned."),
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
JS_FN_HELP("dumpStaticScopeChain", DumpStaticScopeChain, 1, 0,
|
|
||||||
"dumpStaticScopeChain(fun)",
|
|
||||||
" Prints the static scope chain of an interpreted function fun."),
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JS_FS_HELP_END
|
JS_FS_HELP_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6261,14 +6261,12 @@ EvaluateInEnv(JSContext* cx, Handle<Env*> env, HandleValue thisv, AbstractFrameP
|
||||||
* boundaries, and we are putting a DebugScopeProxy or non-syntactic With on
|
* boundaries, and we are putting a DebugScopeProxy or non-syntactic With on
|
||||||
* the scope chain.
|
* the scope chain.
|
||||||
*/
|
*/
|
||||||
Rooted<ScopeObject*> enclosingStaticScope(cx);
|
Rooted<StaticEvalObject*> staticScope(cx, StaticEvalObject::create(cx, nullptr));
|
||||||
if (!env->is<GlobalObject>())
|
|
||||||
enclosingStaticScope = StaticNonSyntacticScopeObjects::create(cx, nullptr);
|
|
||||||
Rooted<StaticEvalObject*> staticScope(cx, StaticEvalObject::create(cx, enclosingStaticScope));
|
|
||||||
if (!staticScope)
|
if (!staticScope)
|
||||||
return false;
|
return false;
|
||||||
CompileOptions options(cx);
|
CompileOptions options(cx);
|
||||||
options.setIsRunOnce(true)
|
options.setHasPollutedScope(true)
|
||||||
|
.setIsRunOnce(true)
|
||||||
.setForEval(true)
|
.setForEval(true)
|
||||||
.setNoScriptRval(false)
|
.setNoScriptRval(false)
|
||||||
.setFileAndLine(filename, lineno)
|
.setFileAndLine(filename, lineno)
|
||||||
|
@ -6277,8 +6275,8 @@ EvaluateInEnv(JSContext* cx, Handle<Env*> env, HandleValue thisv, AbstractFrameP
|
||||||
.maybeMakeStrictMode(frame ? frame.script()->strict() : false);
|
.maybeMakeStrictMode(frame ? frame.script()->strict() : false);
|
||||||
RootedScript callerScript(cx, frame ? frame.script() : nullptr);
|
RootedScript callerScript(cx, frame ? frame.script() : nullptr);
|
||||||
SourceBufferHolder srcBuf(chars.start().get(), chars.length(), SourceBufferHolder::NoOwnership);
|
SourceBufferHolder srcBuf(chars.start().get(), chars.length(), SourceBufferHolder::NoOwnership);
|
||||||
RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(), env, staticScope,
|
RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(), env, callerScript,
|
||||||
callerScript, options, srcBuf,
|
staticScope, options, srcBuf,
|
||||||
/* source = */ nullptr,
|
/* source = */ nullptr,
|
||||||
/* staticLevel = */ frame ? 1 : 0));
|
/* staticLevel = */ frame ? 1 : 0));
|
||||||
if (!script)
|
if (!script)
|
||||||
|
@ -6419,8 +6417,14 @@ DebuggerGenericEval(JSContext* cx, const char* fullMethodName, const Value& code
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
RootedObject dynamicScope(cx);
|
RootedObject dynamicScope(cx);
|
||||||
if (!CreateScopeObjectsForScopeChain(cx, scopeChain, env, &dynamicScope))
|
// We ignore the static scope here. See comments about static
|
||||||
|
// scopes in EvaluateInEnv.
|
||||||
|
RootedObject unusedStaticScope(cx);
|
||||||
|
if (!CreateScopeObjectsForScopeChain(cx, scopeChain, env, &dynamicScope,
|
||||||
|
&unusedStaticScope))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
env = dynamicScope;
|
env = dynamicScope;
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,9 +304,9 @@ SetNameOperation(JSContext* cx, JSScript* script, jsbytecode* pc, HandleObject s
|
||||||
*pc == JSOP_STRICTSETNAME ||
|
*pc == JSOP_STRICTSETNAME ||
|
||||||
*pc == JSOP_SETGNAME ||
|
*pc == JSOP_SETGNAME ||
|
||||||
*pc == JSOP_STRICTSETGNAME);
|
*pc == JSOP_STRICTSETGNAME);
|
||||||
MOZ_ASSERT_IF(*pc == JSOP_SETGNAME && !script->hasNonSyntacticScope(),
|
MOZ_ASSERT_IF(*pc == JSOP_SETGNAME && !script->hasPollutedGlobalScope(),
|
||||||
scope == cx->global());
|
scope == cx->global());
|
||||||
MOZ_ASSERT_IF(*pc == JSOP_STRICTSETGNAME && !script->hasNonSyntacticScope(),
|
MOZ_ASSERT_IF(*pc == JSOP_STRICTSETGNAME && !script->hasPollutedGlobalScope(),
|
||||||
scope == cx->global());
|
scope == cx->global());
|
||||||
|
|
||||||
bool strict = *pc == JSOP_STRICTSETNAME || *pc == JSOP_STRICTSETGNAME;
|
bool strict = *pc == JSOP_STRICTSETNAME || *pc == JSOP_STRICTSETGNAME;
|
||||||
|
|
|
@ -274,7 +274,7 @@ GetNameOperation(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc, MutableHan
|
||||||
* the actual behavior even if the id could be found on the scope chain
|
* the actual behavior even if the id could be found on the scope chain
|
||||||
* before the global object.
|
* before the global object.
|
||||||
*/
|
*/
|
||||||
if (IsGlobalOp(JSOp(*pc)) && !fp->script()->hasNonSyntacticScope())
|
if (IsGlobalOp(JSOp(*pc)) && !fp->script()->hasPollutedGlobalScope())
|
||||||
obj = &obj->global();
|
obj = &obj->global();
|
||||||
|
|
||||||
Shape* shape = nullptr;
|
Shape* shape = nullptr;
|
||||||
|
@ -863,7 +863,7 @@ js::ExecuteKernel(JSContext* cx, HandleScript script, JSObject& scopeChainArg, c
|
||||||
while (IsSyntacticScope(terminatingScope))
|
while (IsSyntacticScope(terminatingScope))
|
||||||
terminatingScope = terminatingScope->enclosingScope();
|
terminatingScope = terminatingScope->enclosingScope();
|
||||||
MOZ_ASSERT(terminatingScope->is<GlobalObject>() ||
|
MOZ_ASSERT(terminatingScope->is<GlobalObject>() ||
|
||||||
script->hasNonSyntacticScope());
|
script->hasPollutedGlobalScope());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (script->treatAsRunOnce()) {
|
if (script->treatAsRunOnce()) {
|
||||||
|
@ -899,8 +899,8 @@ js::Execute(JSContext* cx, HandleScript script, JSObject& scopeChainArg, Value*
|
||||||
RootedObject scopeChain(cx, &scopeChainArg);
|
RootedObject scopeChain(cx, &scopeChainArg);
|
||||||
MOZ_ASSERT(scopeChain == GetInnerObject(scopeChain));
|
MOZ_ASSERT(scopeChain == GetInnerObject(scopeChain));
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(scopeChain->is<GlobalObject>() || script->hasNonSyntacticScope(),
|
MOZ_RELEASE_ASSERT(scopeChain->is<GlobalObject>() || script->hasPollutedGlobalScope(),
|
||||||
"Only scripts with non-syntactic scopes can be executed with "
|
"Only scripts with polluted scopes can be executed with "
|
||||||
"interesting scopechains");
|
"interesting scopechains");
|
||||||
|
|
||||||
/* Ensure the scope chain is all same-compartment and terminates in a global. */
|
/* Ensure the scope chain is all same-compartment and terminates in a global. */
|
||||||
|
@ -1177,7 +1177,6 @@ PopScope(JSContext* cx, ScopeIter& si)
|
||||||
break;
|
break;
|
||||||
case ScopeIter::Call:
|
case ScopeIter::Call:
|
||||||
case ScopeIter::Eval:
|
case ScopeIter::Eval:
|
||||||
case ScopeIter::NonSyntactic:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2316,7 +2315,7 @@ CASE(JSOP_BINDGNAME)
|
||||||
CASE(JSOP_BINDNAME)
|
CASE(JSOP_BINDNAME)
|
||||||
{
|
{
|
||||||
JSOp op = JSOp(*REGS.pc);
|
JSOp op = JSOp(*REGS.pc);
|
||||||
if (op == JSOP_BINDNAME || script->hasNonSyntacticScope()) {
|
if (op == JSOP_BINDNAME || script->hasPollutedGlobalScope()) {
|
||||||
ReservedRooted<JSObject*> scopeChain(&rootObject0, REGS.fp()->scopeChain());
|
ReservedRooted<JSObject*> scopeChain(&rootObject0, REGS.fp()->scopeChain());
|
||||||
ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
|
ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
|
||||||
|
|
||||||
|
@ -3056,7 +3055,7 @@ CASE(JSOP_IMPLICITTHIS)
|
||||||
CASE(JSOP_GIMPLICITTHIS)
|
CASE(JSOP_GIMPLICITTHIS)
|
||||||
{
|
{
|
||||||
JSOp op = JSOp(*REGS.pc);
|
JSOp op = JSOp(*REGS.pc);
|
||||||
if (op == JSOP_IMPLICITTHIS || script->hasNonSyntacticScope()) {
|
if (op == JSOP_IMPLICITTHIS || script->hasPollutedGlobalScope()) {
|
||||||
ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
|
ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
|
||||||
ReservedRooted<JSObject*> scopeObj(&rootObject0, REGS.fp()->scopeChain());
|
ReservedRooted<JSObject*> scopeObj(&rootObject0, REGS.fp()->scopeChain());
|
||||||
ReservedRooted<JSObject*> scope(&rootObject1);
|
ReservedRooted<JSObject*> scope(&rootObject1);
|
||||||
|
@ -3935,7 +3934,7 @@ CASE(JSOP_SUPERBASE)
|
||||||
{
|
{
|
||||||
ScopeIter si(cx, REGS.fp()->scopeChain(), REGS.fp()->script()->innermostStaticScope(REGS.pc));
|
ScopeIter si(cx, REGS.fp()->scopeChain(), REGS.fp()->script()->innermostStaticScope(REGS.pc));
|
||||||
for (; !si.done(); ++si) {
|
for (; !si.done(); ++si) {
|
||||||
if (si.hasSyntacticScopeObject() && si.type() == ScopeIter::Call) {
|
if (si.hasScopeObject() && si.type() == ScopeIter::Call) {
|
||||||
JSFunction& callee = si.scope().as<CallObject>().callee();
|
JSFunction& callee = si.scope().as<CallObject>().callee();
|
||||||
|
|
||||||
// Arrow functions don't have the information we're looking for,
|
// Arrow functions don't have the information we're looking for,
|
||||||
|
|
|
@ -1570,9 +1570,9 @@
|
||||||
macro(JSOP_RETRVAL, 153,"retrval", NULL, 1, 0, 0, JOF_BYTE) \
|
macro(JSOP_RETRVAL, 153,"retrval", NULL, 1, 0, 0, JOF_BYTE) \
|
||||||
\
|
\
|
||||||
/*
|
/*
|
||||||
* Looks up name on global scope and pushes its value onto the stack,
|
* Looks up name on global scope and pushes its value onto the stack, unless
|
||||||
* unless the script has a non-syntactic global scope, in which case it
|
* the script has a polluted global, in which case it acts just like
|
||||||
* acts just like JSOP_NAME.
|
* JSOP_NAME.
|
||||||
*
|
*
|
||||||
* Free variable references that must either be found on the global or a
|
* Free variable references that must either be found on the global or a
|
||||||
* ReferenceError.
|
* ReferenceError.
|
||||||
|
@ -1586,7 +1586,7 @@
|
||||||
* Pops the top two values on the stack as 'val' and 'scope', sets property
|
* Pops the top two values on the stack as 'val' and 'scope', sets property
|
||||||
* of 'scope' as 'val' and pushes 'val' back on the stack.
|
* of 'scope' as 'val' and pushes 'val' back on the stack.
|
||||||
*
|
*
|
||||||
* 'scope' should be the global scope unless the script has a non-syntactic
|
* 'scope' should be the global scope unless the script has a polluted
|
||||||
* global scope, in which case acts like JSOP_SETNAME.
|
* global scope, in which case acts like JSOP_SETNAME.
|
||||||
* Category: Variables and Scopes
|
* Category: Variables and Scopes
|
||||||
* Type: Free Variables
|
* Type: Free Variables
|
||||||
|
@ -1600,7 +1600,7 @@
|
||||||
* of 'scope' as 'val' and pushes 'val' back on the stack. Throws a
|
* of 'scope' as 'val' and pushes 'val' back on the stack. Throws a
|
||||||
* TypeError if the set fails, per strict mode semantics.
|
* TypeError if the set fails, per strict mode semantics.
|
||||||
*
|
*
|
||||||
* 'scope' should be the global scope unless the script has a non-syntactic
|
* 'scope' should be the global scope unless the script has a polluted
|
||||||
* global scope, in which case acts like JSOP_STRICTSETNAME.
|
* global scope, in which case acts like JSOP_STRICTSETNAME.
|
||||||
* Category: Variables and Scopes
|
* Category: Variables and Scopes
|
||||||
* Type: Free Variables
|
* Type: Free Variables
|
||||||
|
@ -1871,7 +1871,7 @@
|
||||||
macro(JSOP_UNUSED213, 213, "unused213", NULL, 1, 0, 0, JOF_BYTE) \
|
macro(JSOP_UNUSED213, 213, "unused213", NULL, 1, 0, 0, JOF_BYTE) \
|
||||||
/*
|
/*
|
||||||
* Pushes the global scope onto the stack if the script doesn't have a
|
* Pushes the global scope onto the stack if the script doesn't have a
|
||||||
* non-syntactic global scope. Otherwise will act like JSOP_BINDNAME.
|
* polluted global scope. Otherwise will act like JSOP_BINDNAME.
|
||||||
*
|
*
|
||||||
* 'nameIndex' is only used when acting like JSOP_BINDNAME.
|
* 'nameIndex' is only used when acting like JSOP_BINDNAME.
|
||||||
* Category: Variables and Scopes
|
* Category: Variables and Scopes
|
||||||
|
|
|
@ -84,8 +84,6 @@ StaticScopeIter<allowGC>::operator++(int)
|
||||||
obj = obj->template as<NestedScopeObject>().enclosingScopeForStaticScopeIter();
|
obj = obj->template as<NestedScopeObject>().enclosingScopeForStaticScopeIter();
|
||||||
} else if (obj->template is<StaticEvalObject>()) {
|
} else if (obj->template is<StaticEvalObject>()) {
|
||||||
obj = obj->template as<StaticEvalObject>().enclosingScopeForStaticScopeIter();
|
obj = obj->template as<StaticEvalObject>().enclosingScopeForStaticScopeIter();
|
||||||
} else if (obj->template is<StaticNonSyntacticScopeObjects>()) {
|
|
||||||
obj = obj->template as<StaticNonSyntacticScopeObjects>().enclosingScopeForStaticScopeIter();
|
|
||||||
} else if (onNamedLambda || !obj->template as<JSFunction>().isNamedLambda()) {
|
} else if (onNamedLambda || !obj->template as<JSFunction>().isNamedLambda()) {
|
||||||
onNamedLambda = false;
|
onNamedLambda = false;
|
||||||
obj = obj->template as<JSFunction>().nonLazyScript()->enclosingStaticScope();
|
obj = obj->template as<JSFunction>().nonLazyScript()->enclosingStaticScope();
|
||||||
|
@ -94,32 +92,27 @@ StaticScopeIter<allowGC>::operator++(int)
|
||||||
}
|
}
|
||||||
MOZ_ASSERT_IF(obj, obj->template is<NestedScopeObject>() ||
|
MOZ_ASSERT_IF(obj, obj->template is<NestedScopeObject>() ||
|
||||||
obj->template is<StaticEvalObject>() ||
|
obj->template is<StaticEvalObject>() ||
|
||||||
obj->template is<StaticNonSyntacticScopeObjects>() ||
|
|
||||||
obj->template is<JSFunction>());
|
obj->template is<JSFunction>());
|
||||||
MOZ_ASSERT_IF(onNamedLambda, obj->template is<JSFunction>());
|
MOZ_ASSERT_IF(onNamedLambda, obj->template is<JSFunction>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
template <AllowGC allowGC>
|
||||||
inline bool
|
inline bool
|
||||||
StaticScopeIter<allowGC>::hasSyntacticDynamicScopeObject() const
|
StaticScopeIter<allowGC>::hasDynamicScopeObject() const
|
||||||
{
|
{
|
||||||
if (obj->template is<JSFunction>())
|
return obj->template is<StaticBlockObject>()
|
||||||
return obj->template as<JSFunction>().isHeavyweight();
|
? obj->template as<StaticBlockObject>().needsClone()
|
||||||
if (obj->template is<StaticBlockObject>())
|
: (obj->template is<StaticEvalObject>()
|
||||||
return obj->template as<StaticBlockObject>().needsClone();
|
? obj->template as<StaticEvalObject>().isStrict()
|
||||||
if (obj->template is<StaticWithObject>())
|
: (obj->template is<StaticWithObject>() ||
|
||||||
return true;
|
obj->template as<JSFunction>().isHeavyweight()));
|
||||||
if (obj->template is<StaticEvalObject>())
|
|
||||||
return obj->template as<StaticEvalObject>().isStrict();
|
|
||||||
MOZ_ASSERT(obj->template is<StaticNonSyntacticScopeObjects>());
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
template <AllowGC allowGC>
|
||||||
inline Shape*
|
inline Shape*
|
||||||
StaticScopeIter<allowGC>::scopeShape() const
|
StaticScopeIter<allowGC>::scopeShape() const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(hasSyntacticDynamicScopeObject());
|
MOZ_ASSERT(hasDynamicScopeObject());
|
||||||
MOZ_ASSERT(type() != NamedLambda && type() != Eval);
|
MOZ_ASSERT(type() != NamedLambda && type() != Eval);
|
||||||
if (type() == Block)
|
if (type() == Block)
|
||||||
return block().lastProperty();
|
return block().lastProperty();
|
||||||
|
@ -138,8 +131,6 @@ StaticScopeIter<allowGC>::type() const
|
||||||
? With
|
? With
|
||||||
: (obj->template is<StaticEvalObject>()
|
: (obj->template is<StaticEvalObject>()
|
||||||
? Eval
|
? Eval
|
||||||
: (obj->template is<StaticNonSyntacticScopeObjects>())
|
|
||||||
? NonSyntactic
|
|
||||||
: Function));
|
: Function));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,14 +158,6 @@ StaticScopeIter<allowGC>::eval() const
|
||||||
return obj->template as<StaticEvalObject>();
|
return obj->template as<StaticEvalObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
|
||||||
inline StaticNonSyntacticScopeObjects&
|
|
||||||
StaticScopeIter<allowGC>::nonSyntactic() const
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(type() == NonSyntactic);
|
|
||||||
return obj->template as<StaticNonSyntacticScopeObjects>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
template <AllowGC allowGC>
|
||||||
inline JSScript*
|
inline JSScript*
|
||||||
StaticScopeIter<allowGC>::funScript() const
|
StaticScopeIter<allowGC>::funScript() const
|
||||||
|
|
|
@ -43,7 +43,7 @@ js::ScopeCoordinateToStaticScopeShape(JSScript* script, jsbytecode* pc)
|
||||||
uint32_t hops = ScopeCoordinate(pc).hops();
|
uint32_t hops = ScopeCoordinate(pc).hops();
|
||||||
while (true) {
|
while (true) {
|
||||||
MOZ_ASSERT(!ssi.done());
|
MOZ_ASSERT(!ssi.done());
|
||||||
if (ssi.hasSyntacticDynamicScopeObject()) {
|
if (ssi.hasDynamicScopeObject()) {
|
||||||
if (!hops)
|
if (!hops)
|
||||||
break;
|
break;
|
||||||
hops--;
|
hops--;
|
||||||
|
@ -107,7 +107,7 @@ js::ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc)
|
||||||
StaticScopeIter<NoGC> ssi(script->innermostStaticScopeInScript(pc));
|
StaticScopeIter<NoGC> ssi(script->innermostStaticScopeInScript(pc));
|
||||||
uint32_t hops = ScopeCoordinate(pc).hops();
|
uint32_t hops = ScopeCoordinate(pc).hops();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (ssi.hasSyntacticDynamicScopeObject()) {
|
if (ssi.hasDynamicScopeObject()) {
|
||||||
if (!hops)
|
if (!hops)
|
||||||
break;
|
break;
|
||||||
hops--;
|
hops--;
|
||||||
|
@ -212,7 +212,7 @@ CallObject::create(JSContext* cx, HandleScript script, HandleObject enclosing, H
|
||||||
if (!callobj)
|
if (!callobj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
callobj->setEnclosingScope(enclosing);
|
callobj->as<ScopeObject>().setEnclosingScope(enclosing);
|
||||||
callobj->initFixedSlot(CALLEE_SLOT, ObjectOrNullValue(callee));
|
callobj->initFixedSlot(CALLEE_SLOT, ObjectOrNullValue(callee));
|
||||||
|
|
||||||
if (script->treatAsRunOnce()) {
|
if (script->treatAsRunOnce()) {
|
||||||
|
@ -323,10 +323,22 @@ const Class DeclEnvObject::class_ = {
|
||||||
* scope and callee) or used as a template for jit compilation.
|
* scope and callee) or used as a template for jit compilation.
|
||||||
*/
|
*/
|
||||||
DeclEnvObject*
|
DeclEnvObject*
|
||||||
DeclEnvObject::createTemplateObject(JSContext* cx, HandleFunction fun, NewObjectKind newKind)
|
DeclEnvObject::createTemplateObject(JSContext* cx, HandleFunction fun, gc::InitialHeap heap)
|
||||||
{
|
{
|
||||||
Rooted<DeclEnvObject*> obj(cx);
|
MOZ_ASSERT(IsNurseryAllocable(FINALIZE_KIND));
|
||||||
obj = NewObjectWithNullTaggedProto<DeclEnvObject>(cx, newKind, BaseShape::DELEGATE);
|
|
||||||
|
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
|
||||||
|
if (!group)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
RootedShape emptyDeclEnvShape(cx);
|
||||||
|
emptyDeclEnvShape = EmptyShape::getInitialShape(cx, &class_, TaggedProto(nullptr),
|
||||||
|
FINALIZE_KIND, BaseShape::DELEGATE);
|
||||||
|
if (!emptyDeclEnvShape)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, FINALIZE_KIND, heap,
|
||||||
|
emptyDeclEnvShape, group)));
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -344,13 +356,13 @@ DeclEnvObject::createTemplateObject(JSContext* cx, HandleFunction fun, NewObject
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
MOZ_ASSERT(!obj->hasDynamicSlots());
|
MOZ_ASSERT(!obj->hasDynamicSlots());
|
||||||
return obj;
|
return &obj->as<DeclEnvObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclEnvObject*
|
DeclEnvObject*
|
||||||
DeclEnvObject::create(JSContext* cx, HandleObject enclosing, HandleFunction callee)
|
DeclEnvObject::create(JSContext* cx, HandleObject enclosing, HandleFunction callee)
|
||||||
{
|
{
|
||||||
Rooted<DeclEnvObject*> obj(cx, createTemplateObject(cx, callee, GenericObject));
|
Rooted<DeclEnvObject*> obj(cx, createTemplateObject(cx, callee, gc::DefaultHeap));
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -388,7 +400,20 @@ js::XDRStaticWithObject(XDRState<XDR_DECODE>*, HandleObject, MutableHandle<Stati
|
||||||
StaticWithObject*
|
StaticWithObject*
|
||||||
StaticWithObject::create(ExclusiveContext* cx)
|
StaticWithObject::create(ExclusiveContext* cx)
|
||||||
{
|
{
|
||||||
return NewObjectWithNullTaggedProto<StaticWithObject>(cx, TenuredObject, BaseShape::DELEGATE);
|
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
|
||||||
|
if (!group)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &class_, TaggedProto(nullptr),
|
||||||
|
FINALIZE_KIND));
|
||||||
|
if (!shape)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
RootedObject obj(cx, JSObject::create(cx, FINALIZE_KIND, gc::TenuredHeap, shape, group));
|
||||||
|
if (!obj)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return &obj->as<StaticWithObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSObject*
|
static JSObject*
|
||||||
|
@ -408,11 +433,18 @@ DynamicWithObject::create(JSContext* cx, HandleObject object, HandleObject enclo
|
||||||
HandleObject staticWith, WithKind kind)
|
HandleObject staticWith, WithKind kind)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(staticWith->is<StaticWithObject>());
|
MOZ_ASSERT(staticWith->is<StaticWithObject>());
|
||||||
|
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_,
|
||||||
|
TaggedProto(staticWith.get())));
|
||||||
|
if (!group)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
Rooted<TaggedProto> proto(cx, TaggedProto(staticWith));
|
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &class_, TaggedProto(staticWith),
|
||||||
Rooted<DynamicWithObject*> obj(cx);
|
FINALIZE_KIND));
|
||||||
obj = NewObjectWithGivenTaggedProto<DynamicWithObject>(cx, proto, GenericObject,
|
if (!shape)
|
||||||
BaseShape::DELEGATE);
|
return nullptr;
|
||||||
|
|
||||||
|
RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, FINALIZE_KIND,
|
||||||
|
gc::DefaultHeap, shape, group)));
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -420,12 +452,12 @@ DynamicWithObject::create(JSContext* cx, HandleObject object, HandleObject enclo
|
||||||
if (!thisp)
|
if (!thisp)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
obj->setEnclosingScope(enclosing);
|
obj->as<ScopeObject>().setEnclosingScope(enclosing);
|
||||||
obj->setFixedSlot(OBJECT_SLOT, ObjectValue(*object));
|
obj->setFixedSlot(OBJECT_SLOT, ObjectValue(*object));
|
||||||
obj->setFixedSlot(THIS_SLOT, ObjectValue(*thisp));
|
obj->setFixedSlot(THIS_SLOT, ObjectValue(*thisp));
|
||||||
obj->setFixedSlot(KIND_SLOT, Int32Value(kind));
|
obj->setFixedSlot(KIND_SLOT, Int32Value(kind));
|
||||||
|
|
||||||
return obj;
|
return &obj->as<DynamicWithObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -535,14 +567,23 @@ const Class DynamicWithObject::class_ = {
|
||||||
/* static */ StaticEvalObject*
|
/* static */ StaticEvalObject*
|
||||||
StaticEvalObject::create(JSContext* cx, HandleObject enclosing)
|
StaticEvalObject::create(JSContext* cx, HandleObject enclosing)
|
||||||
{
|
{
|
||||||
StaticEvalObject* obj =
|
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
|
||||||
NewObjectWithNullTaggedProto<StaticEvalObject>(cx, TenuredObject, BaseShape::DELEGATE);
|
if (!group)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &class_, TaggedProto(nullptr),
|
||||||
|
FINALIZE_KIND, BaseShape::DELEGATE));
|
||||||
|
if (!shape)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, FINALIZE_KIND,
|
||||||
|
gc::TenuredHeap, shape, group)));
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
obj->setReservedSlot(SCOPE_CHAIN_SLOT, ObjectOrNullValue(enclosing));
|
obj->setReservedSlot(SCOPE_CHAIN_SLOT, ObjectOrNullValue(enclosing));
|
||||||
obj->setReservedSlot(STRICT_SLOT, BooleanValue(false));
|
obj->setReservedSlot(STRICT_SLOT, BooleanValue(false));
|
||||||
return obj;
|
return &obj->as<StaticEvalObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Class StaticEvalObject::class_ = {
|
const Class StaticEvalObject::class_ = {
|
||||||
|
@ -551,50 +592,6 @@ const Class StaticEvalObject::class_ = {
|
||||||
JSCLASS_IS_ANONYMOUS
|
JSCLASS_IS_ANONYMOUS
|
||||||
};
|
};
|
||||||
|
|
||||||
/* static */ StaticNonSyntacticScopeObjects*
|
|
||||||
StaticNonSyntacticScopeObjects::create(JSContext*cx, HandleObject enclosing)
|
|
||||||
{
|
|
||||||
StaticNonSyntacticScopeObjects* obj =
|
|
||||||
NewObjectWithNullTaggedProto<StaticNonSyntacticScopeObjects>(cx, TenuredObject,
|
|
||||||
BaseShape::DELEGATE);
|
|
||||||
if (!obj)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
obj->setReservedSlot(SCOPE_CHAIN_SLOT, ObjectOrNullValue(enclosing));
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Class StaticNonSyntacticScopeObjects::class_ = {
|
|
||||||
"StaticNonSyntacticScopeObjects",
|
|
||||||
JSCLASS_HAS_RESERVED_SLOTS(StaticNonSyntacticScopeObjects::RESERVED_SLOTS) |
|
|
||||||
JSCLASS_IS_ANONYMOUS
|
|
||||||
};
|
|
||||||
|
|
||||||
/* static */ NonSyntacticVariablesObject*
|
|
||||||
NonSyntacticVariablesObject::create(JSContext* cx, Handle<GlobalObject*> global)
|
|
||||||
{
|
|
||||||
Rooted<NonSyntacticVariablesObject*> obj(cx,
|
|
||||||
NewObjectWithNullTaggedProto<NonSyntacticVariablesObject>(cx, TenuredObject,
|
|
||||||
BaseShape::DELEGATE));
|
|
||||||
if (!obj)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (!obj->setQualifiedVarObj(cx))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (!obj->setUnqualifiedVarObj(cx))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
obj->setEnclosingScope(global);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Class NonSyntacticVariablesObject::class_ = {
|
|
||||||
"NonSyntacticVariablesObject",
|
|
||||||
JSCLASS_HAS_RESERVED_SLOTS(NonSyntacticVariablesObject::RESERVED_SLOTS) |
|
|
||||||
JSCLASS_IS_ANONYMOUS
|
|
||||||
};
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
/* static */ ClonedBlockObject*
|
/* static */ ClonedBlockObject*
|
||||||
|
@ -609,10 +606,7 @@ ClonedBlockObject::create(JSContext* cx, Handle<StaticBlockObject*> block, Handl
|
||||||
|
|
||||||
RootedShape shape(cx, block->lastProperty());
|
RootedShape shape(cx, block->lastProperty());
|
||||||
|
|
||||||
gc::AllocKind allocKind = gc::GetGCObjectKind(&BlockObject::class_);
|
RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, FINALIZE_KIND,
|
||||||
if (CanBeFinalizedInBackground(allocKind, &BlockObject::class_))
|
|
||||||
allocKind = GetBackgroundAllocKind(allocKind);
|
|
||||||
RootedNativeObject obj(cx, MaybeNativeObject(JSObject::create(cx, allocKind,
|
|
||||||
gc::TenuredHeap, shape, group)));
|
gc::TenuredHeap, shape, group)));
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -686,7 +680,22 @@ ClonedBlockObject::clone(JSContext* cx, Handle<ClonedBlockObject*> clonedBlock)
|
||||||
StaticBlockObject*
|
StaticBlockObject*
|
||||||
StaticBlockObject::create(ExclusiveContext* cx)
|
StaticBlockObject::create(ExclusiveContext* cx)
|
||||||
{
|
{
|
||||||
return NewObjectWithNullTaggedProto<StaticBlockObject>(cx, TenuredObject, BaseShape::DELEGATE);
|
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &BlockObject::class_,
|
||||||
|
TaggedProto(nullptr)));
|
||||||
|
if (!group)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
RootedShape emptyBlockShape(cx);
|
||||||
|
emptyBlockShape = EmptyShape::getInitialShape(cx, &BlockObject::class_, TaggedProto(nullptr),
|
||||||
|
FINALIZE_KIND, BaseShape::DELEGATE);
|
||||||
|
if (!emptyBlockShape)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
JSObject* obj = JSObject::create(cx, FINALIZE_KIND, gc::TenuredHeap, emptyBlockShape, group);
|
||||||
|
if (!obj)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return &obj->as<StaticBlockObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ Shape*
|
/* static */ Shape*
|
||||||
|
@ -884,13 +893,22 @@ js::CloneNestedScopeObject(JSContext* cx, HandleObject enclosingScope, Handle<Ne
|
||||||
/* static */ UninitializedLexicalObject*
|
/* static */ UninitializedLexicalObject*
|
||||||
UninitializedLexicalObject::create(JSContext* cx, HandleObject enclosing)
|
UninitializedLexicalObject::create(JSContext* cx, HandleObject enclosing)
|
||||||
{
|
{
|
||||||
UninitializedLexicalObject* obj =
|
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
|
||||||
NewObjectWithNullTaggedProto<UninitializedLexicalObject>(cx, GenericObject,
|
if (!group)
|
||||||
BaseShape::DELEGATE);
|
return nullptr;
|
||||||
|
|
||||||
|
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &class_, TaggedProto(nullptr),
|
||||||
|
FINALIZE_KIND));
|
||||||
|
if (!shape)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
RootedObject obj(cx, JSObject::create(cx, FINALIZE_KIND, gc::DefaultHeap, shape, group));
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
obj->setEnclosingScope(enclosing);
|
|
||||||
return obj;
|
obj->as<ScopeObject>().setEnclosingScope(enclosing);
|
||||||
|
|
||||||
|
return &obj->as<UninitializedLexicalObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1027,14 +1045,7 @@ ScopeIter::ScopeIter(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc
|
||||||
void
|
void
|
||||||
ScopeIter::incrementStaticScopeIter()
|
ScopeIter::incrementStaticScopeIter()
|
||||||
{
|
{
|
||||||
// If settled on a non-syntactic static scope, only increment ssi_ once
|
ssi_++;
|
||||||
// we've iterated through all the non-syntactic dynamic ScopeObjects.
|
|
||||||
if (ssi_.type() == StaticScopeIter<CanGC>::NonSyntactic) {
|
|
||||||
if (!hasNonSyntacticScopeObject())
|
|
||||||
ssi_++;
|
|
||||||
} else {
|
|
||||||
ssi_++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For named lambdas, DeclEnvObject scopes are always attached to their
|
// For named lambdas, DeclEnvObject scopes are always attached to their
|
||||||
// CallObjects. Skip it here, as they are special cased in users of
|
// CallObjects. Skip it here, as they are special cased in users of
|
||||||
|
@ -1061,7 +1072,7 @@ ScopeIter::settle()
|
||||||
frame_ = NullFramePtr();
|
frame_ = NullFramePtr();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (!ssi_.done() && hasAnyScopeObject()) {
|
if (!ssi_.done() && hasScopeObject()) {
|
||||||
switch (ssi_.type()) {
|
switch (ssi_.type()) {
|
||||||
case StaticScopeIter<CanGC>::Function:
|
case StaticScopeIter<CanGC>::Function:
|
||||||
MOZ_ASSERT(scope_->as<CallObject>().callee().nonLazyScript() == ssi_.funScript());
|
MOZ_ASSERT(scope_->as<CallObject>().callee().nonLazyScript() == ssi_.funScript());
|
||||||
|
@ -1075,9 +1086,6 @@ ScopeIter::settle()
|
||||||
case StaticScopeIter<CanGC>::Eval:
|
case StaticScopeIter<CanGC>::Eval:
|
||||||
MOZ_ASSERT(scope_->as<CallObject>().isForEval());
|
MOZ_ASSERT(scope_->as<CallObject>().isForEval());
|
||||||
break;
|
break;
|
||||||
case StaticScopeIter<CanGC>::NonSyntactic:
|
|
||||||
MOZ_ASSERT(!IsSyntacticScope(scope_));
|
|
||||||
break;
|
|
||||||
case StaticScopeIter<CanGC>::NamedLambda:
|
case StaticScopeIter<CanGC>::NamedLambda:
|
||||||
MOZ_CRASH("named lambda static scopes should have been skipped");
|
MOZ_CRASH("named lambda static scopes should have been skipped");
|
||||||
}
|
}
|
||||||
|
@ -1088,7 +1096,7 @@ ScopeIter::settle()
|
||||||
ScopeIter&
|
ScopeIter&
|
||||||
ScopeIter::operator++()
|
ScopeIter::operator++()
|
||||||
{
|
{
|
||||||
if (hasAnyScopeObject()) {
|
if (hasScopeObject()) {
|
||||||
scope_ = &scope_->as<ScopeObject>().enclosingScope();
|
scope_ = &scope_->as<ScopeObject>().enclosingScope();
|
||||||
if (scope_->is<DeclEnvObject>())
|
if (scope_->is<DeclEnvObject>())
|
||||||
scope_ = &scope_->as<DeclEnvObject>().enclosingScope();
|
scope_ = &scope_->as<DeclEnvObject>().enclosingScope();
|
||||||
|
@ -1114,8 +1122,6 @@ ScopeIter::type() const
|
||||||
return With;
|
return With;
|
||||||
case StaticScopeIter<CanGC>::Eval:
|
case StaticScopeIter<CanGC>::Eval:
|
||||||
return Eval;
|
return Eval;
|
||||||
case StaticScopeIter<CanGC>::NonSyntactic:
|
|
||||||
return NonSyntactic;
|
|
||||||
case StaticScopeIter<CanGC>::NamedLambda:
|
case StaticScopeIter<CanGC>::NamedLambda:
|
||||||
MOZ_CRASH("named lambda static scopes should have been skipped");
|
MOZ_CRASH("named lambda static scopes should have been skipped");
|
||||||
default:
|
default:
|
||||||
|
@ -1126,7 +1132,7 @@ ScopeIter::type() const
|
||||||
ScopeObject&
|
ScopeObject&
|
||||||
ScopeIter::scope() const
|
ScopeIter::scope() const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(hasAnyScopeObject());
|
MOZ_ASSERT(hasScopeObject());
|
||||||
return scope_->as<ScopeObject>();
|
return scope_->as<ScopeObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1145,8 +1151,6 @@ ScopeIter::maybeStaticScope() const
|
||||||
return &staticWith();
|
return &staticWith();
|
||||||
case StaticScopeIter<CanGC>::Eval:
|
case StaticScopeIter<CanGC>::Eval:
|
||||||
return &staticEval();
|
return &staticEval();
|
||||||
case StaticScopeIter<CanGC>::NonSyntactic:
|
|
||||||
return &staticNonSyntactic();
|
|
||||||
case StaticScopeIter<CanGC>::NamedLambda:
|
case StaticScopeIter<CanGC>::NamedLambda:
|
||||||
MOZ_CRASH("named lambda static scopes should have been skipped");
|
MOZ_CRASH("named lambda static scopes should have been skipped");
|
||||||
default:
|
default:
|
||||||
|
@ -1746,7 +1750,7 @@ const DebugScopeProxy DebugScopeProxy::singleton;
|
||||||
DebugScopeObject::create(JSContext* cx, ScopeObject& scope, HandleObject enclosing)
|
DebugScopeObject::create(JSContext* cx, ScopeObject& scope, HandleObject enclosing)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(scope.compartment() == cx->compartment());
|
MOZ_ASSERT(scope.compartment() == cx->compartment());
|
||||||
MOZ_ASSERT(!enclosing->is<ScopeObject>());
|
MOZ_ASSERT(!IsSyntacticScope(enclosing));
|
||||||
|
|
||||||
RootedValue priv(cx, ObjectValue(scope));
|
RootedValue priv(cx, ObjectValue(scope));
|
||||||
JSObject* obj = NewProxyObject(cx, &DebugScopeProxy::singleton, priv,
|
JSObject* obj = NewProxyObject(cx, &DebugScopeProxy::singleton, priv,
|
||||||
|
@ -2008,7 +2012,7 @@ DebugScopes::addDebugScope(JSContext* cx, ScopeObject& scope, DebugScopeObject&
|
||||||
DebugScopeObject*
|
DebugScopeObject*
|
||||||
DebugScopes::hasDebugScope(JSContext* cx, const ScopeIter& si)
|
DebugScopes::hasDebugScope(JSContext* cx, const ScopeIter& si)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!si.hasSyntacticScopeObject());
|
MOZ_ASSERT(!si.hasScopeObject());
|
||||||
|
|
||||||
DebugScopes* scopes = cx->compartment()->debugScopes;
|
DebugScopes* scopes = cx->compartment()->debugScopes;
|
||||||
if (!scopes)
|
if (!scopes)
|
||||||
|
@ -2024,7 +2028,7 @@ DebugScopes::hasDebugScope(JSContext* cx, const ScopeIter& si)
|
||||||
bool
|
bool
|
||||||
DebugScopes::addDebugScope(JSContext* cx, const ScopeIter& si, DebugScopeObject& debugScope)
|
DebugScopes::addDebugScope(JSContext* cx, const ScopeIter& si, DebugScopeObject& debugScope)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!si.hasSyntacticScopeObject());
|
MOZ_ASSERT(!si.hasScopeObject());
|
||||||
MOZ_ASSERT(cx->compartment() == debugScope.compartment());
|
MOZ_ASSERT(cx->compartment() == debugScope.compartment());
|
||||||
MOZ_ASSERT_IF(si.withinInitialFrame() && si.initialFrame().isFunctionFrame(),
|
MOZ_ASSERT_IF(si.withinInitialFrame() && si.initialFrame().isFunctionFrame(),
|
||||||
!si.initialFrame().callee()->isGenerator());
|
!si.initialFrame().callee()->isGenerator());
|
||||||
|
@ -2242,7 +2246,7 @@ DebugScopes::updateLiveScopes(JSContext* cx)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (ScopeIter si(cx, frame, i.pc()); si.withinInitialFrame(); ++si) {
|
for (ScopeIter si(cx, frame, i.pc()); si.withinInitialFrame(); ++si) {
|
||||||
if (si.hasSyntacticScopeObject()) {
|
if (si.hasScopeObject()) {
|
||||||
MOZ_ASSERT(si.scope().compartment() == cx->compartment());
|
MOZ_ASSERT(si.scope().compartment() == cx->compartment());
|
||||||
DebugScopes* scopes = ensureCompartmentData(cx);
|
DebugScopes* scopes = ensureCompartmentData(cx);
|
||||||
if (!scopes)
|
if (!scopes)
|
||||||
|
@ -2360,7 +2364,7 @@ GetDebugScopeForScope(JSContext* cx, const ScopeIter& si)
|
||||||
static DebugScopeObject*
|
static DebugScopeObject*
|
||||||
GetDebugScopeForMissing(JSContext* cx, const ScopeIter& si)
|
GetDebugScopeForMissing(JSContext* cx, const ScopeIter& si)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!si.hasSyntacticScopeObject() && si.canHaveSyntacticScopeObject());
|
MOZ_ASSERT(!si.hasScopeObject() && si.canHaveScopeObject());
|
||||||
|
|
||||||
if (DebugScopeObject* debugScope = DebugScopes::hasDebugScope(cx, si))
|
if (DebugScopeObject* debugScope = DebugScopes::hasDebugScope(cx, si))
|
||||||
return debugScope;
|
return debugScope;
|
||||||
|
@ -2427,8 +2431,6 @@ GetDebugScopeForMissing(JSContext* cx, const ScopeIter& si)
|
||||||
case ScopeIter::With:
|
case ScopeIter::With:
|
||||||
case ScopeIter::Eval:
|
case ScopeIter::Eval:
|
||||||
MOZ_CRASH("should already have a scope");
|
MOZ_CRASH("should already have a scope");
|
||||||
case ScopeIter::NonSyntactic:
|
|
||||||
MOZ_CRASH("non-syntactic scopes cannot be synthesized");
|
|
||||||
}
|
}
|
||||||
if (!debugScope)
|
if (!debugScope)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -2443,11 +2445,11 @@ static JSObject*
|
||||||
GetDebugScopeForNonScopeObject(const ScopeIter& si)
|
GetDebugScopeForNonScopeObject(const ScopeIter& si)
|
||||||
{
|
{
|
||||||
JSObject& enclosing = si.enclosingScope();
|
JSObject& enclosing = si.enclosingScope();
|
||||||
MOZ_ASSERT(!enclosing.is<ScopeObject>());
|
MOZ_ASSERT(!IsSyntacticScope(&enclosing));
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
JSObject* o = &enclosing;
|
JSObject* o = &enclosing;
|
||||||
while ((o = o->enclosingScope()))
|
while ((o = o->enclosingScope()))
|
||||||
MOZ_ASSERT(!o->is<ScopeObject>());
|
MOZ_ASSERT(!IsSyntacticScope(o));
|
||||||
#endif
|
#endif
|
||||||
return &enclosing;
|
return &enclosing;
|
||||||
}
|
}
|
||||||
|
@ -2460,10 +2462,10 @@ GetDebugScope(JSContext* cx, const ScopeIter& si)
|
||||||
if (si.done())
|
if (si.done())
|
||||||
return GetDebugScopeForNonScopeObject(si);
|
return GetDebugScopeForNonScopeObject(si);
|
||||||
|
|
||||||
if (si.hasAnyScopeObject())
|
if (si.hasScopeObject())
|
||||||
return GetDebugScopeForScope(cx, si);
|
return GetDebugScopeForScope(cx, si);
|
||||||
|
|
||||||
if (si.canHaveSyntacticScopeObject())
|
if (si.canHaveScopeObject())
|
||||||
return GetDebugScopeForMissing(cx, si);
|
return GetDebugScopeForMissing(cx, si);
|
||||||
|
|
||||||
ScopeIter copy(cx, si);
|
ScopeIter copy(cx, si);
|
||||||
|
@ -2512,7 +2514,8 @@ js::GetObjectEnvironmentObjectForFunction(JSFunction* fun)
|
||||||
bool
|
bool
|
||||||
js::CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
|
js::CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
|
||||||
HandleObject dynamicTerminatingScope,
|
HandleObject dynamicTerminatingScope,
|
||||||
MutableHandleObject dynamicScopeObj)
|
MutableHandleObject dynamicScopeObj,
|
||||||
|
MutableHandleObject staticScopeObj)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
for (size_t i = 0; i < scopeChain.length(); ++i) {
|
for (size_t i = 0; i < scopeChain.length(); ++i) {
|
||||||
|
@ -2542,55 +2545,12 @@ js::CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamicScopeObj.set(dynamicEnclosingScope);
|
dynamicScopeObj.set(dynamicEnclosingScope);
|
||||||
|
staticScopeObj.set(staticEnclosingScope);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
js::HasNonSyntacticStaticScopeChain(JSObject* staticScope)
|
|
||||||
{
|
|
||||||
for (StaticScopeIter<NoGC> ssi(staticScope); !ssi.done(); ssi++) {
|
|
||||||
// If we hit a function scope, we can short circuit the logic, as
|
|
||||||
// scripts cache whether they are under a non-syntactic scope.
|
|
||||||
if (ssi.type() == StaticScopeIter<NoGC>::Function)
|
|
||||||
return ssi.funScript()->hasNonSyntacticScope();
|
|
||||||
if (ssi.type() == StaticScopeIter<NoGC>::NonSyntactic)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
void
|
|
||||||
js::DumpStaticScopeChain(JSScript* script)
|
|
||||||
{
|
|
||||||
JSObject* enclosingScope = script->enclosingStaticScope();
|
|
||||||
for (StaticScopeIter<NoGC> ssi(enclosingScope); !ssi.done(); ssi++) {
|
|
||||||
switch (ssi.type()) {
|
|
||||||
case StaticScopeIter<NoGC>::Function:
|
|
||||||
fprintf(stdout, "function");
|
|
||||||
break;
|
|
||||||
case StaticScopeIter<NoGC>::Block:
|
|
||||||
fprintf(stdout, "block");
|
|
||||||
break;
|
|
||||||
case StaticScopeIter<NoGC>::With:
|
|
||||||
fprintf(stdout, "with");
|
|
||||||
break;
|
|
||||||
case StaticScopeIter<NoGC>::NamedLambda:
|
|
||||||
fprintf(stdout, "named lambda");
|
|
||||||
break;
|
|
||||||
case StaticScopeIter<NoGC>::Eval:
|
|
||||||
fprintf(stdout, "eval");
|
|
||||||
break;
|
|
||||||
case StaticScopeIter<NoGC>::NonSyntactic:
|
|
||||||
fprintf(stdout, "non-syntactic");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fprintf(stdout, " -> ");
|
|
||||||
}
|
|
||||||
fprintf(stdout, "global\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef HashSet<PropertyName*> PropertyNameSet;
|
typedef HashSet<PropertyName*> PropertyNameSet;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -2623,7 +2583,7 @@ RemoveReferencedNames(JSContext* cx, HandleScript script, PropertyNameSet& remai
|
||||||
case JSOP_GETGNAME:
|
case JSOP_GETGNAME:
|
||||||
case JSOP_SETGNAME:
|
case JSOP_SETGNAME:
|
||||||
case JSOP_STRICTSETGNAME:
|
case JSOP_STRICTSETGNAME:
|
||||||
if (script->hasNonSyntacticScope())
|
if (script->hasPollutedGlobalScope())
|
||||||
name = script->getName(pc);
|
name = script->getName(pc);
|
||||||
else
|
else
|
||||||
name = nullptr;
|
name = nullptr;
|
||||||
|
|
|
@ -22,7 +22,6 @@ namespace frontend { struct Definition; }
|
||||||
|
|
||||||
class StaticWithObject;
|
class StaticWithObject;
|
||||||
class StaticEvalObject;
|
class StaticEvalObject;
|
||||||
class StaticNonSyntacticScopeObjects;
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
@ -63,7 +62,6 @@ class StaticScopeIter
|
||||||
obj->is<StaticBlockObject>() ||
|
obj->is<StaticBlockObject>() ||
|
||||||
obj->is<StaticWithObject>() ||
|
obj->is<StaticWithObject>() ||
|
||||||
obj->is<StaticEvalObject>() ||
|
obj->is<StaticEvalObject>() ||
|
||||||
obj->is<StaticNonSyntacticScopeObjects>() ||
|
|
||||||
obj->is<JSFunction>());
|
obj->is<JSFunction>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +81,6 @@ class StaticScopeIter
|
||||||
obj->is<StaticBlockObject>() ||
|
obj->is<StaticBlockObject>() ||
|
||||||
obj->is<StaticWithObject>() ||
|
obj->is<StaticWithObject>() ||
|
||||||
obj->is<StaticEvalObject>() ||
|
obj->is<StaticEvalObject>() ||
|
||||||
obj->is<StaticNonSyntacticScopeObjects>() ||
|
|
||||||
obj->is<JSFunction>());
|
obj->is<JSFunction>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,19 +95,16 @@ class StaticScopeIter
|
||||||
bool done() const;
|
bool done() const;
|
||||||
void operator++(int);
|
void operator++(int);
|
||||||
|
|
||||||
// Return whether this static scope will have a syntactic scope (i.e. a
|
/* Return whether this static scope will be on the dynamic scope chain. */
|
||||||
// ScopeObject that isn't a non-syntactic With or
|
bool hasDynamicScopeObject() const;
|
||||||
// NonSyntacticVariablesObject) on the dynamic scope chain.
|
|
||||||
bool hasSyntacticDynamicScopeObject() const;
|
|
||||||
Shape* scopeShape() const;
|
Shape* scopeShape() const;
|
||||||
|
|
||||||
enum Type { Function, Block, With, NamedLambda, Eval, NonSyntactic };
|
enum Type { Function, Block, With, NamedLambda, Eval };
|
||||||
Type type() const;
|
Type type() const;
|
||||||
|
|
||||||
StaticBlockObject& block() const;
|
StaticBlockObject& block() const;
|
||||||
StaticWithObject& staticWith() const;
|
StaticWithObject& staticWith() const;
|
||||||
StaticEvalObject& eval() const;
|
StaticEvalObject& eval() const;
|
||||||
StaticNonSyntacticScopeObjects& nonSyntactic() const;
|
|
||||||
JSScript* funScript() const;
|
JSScript* funScript() const;
|
||||||
JSFunction& fun() const;
|
JSFunction& fun() const;
|
||||||
};
|
};
|
||||||
|
@ -181,28 +175,26 @@ ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc);
|
||||||
* scope objects is:
|
* scope objects is:
|
||||||
*
|
*
|
||||||
* JSObject Generic object
|
* JSObject Generic object
|
||||||
* |
|
* \
|
||||||
* ScopeObject---+---+ Engine-internal scope
|
* ScopeObject Engine-internal scope
|
||||||
* | | | | |
|
* \ \ \ \
|
||||||
* | | | | StaticNonSyntacticScopeObjects See NB2
|
* \ \ \ StaticEvalObject Placeholder so eval scopes may be iterated through
|
||||||
* | | | |
|
* \ \ \
|
||||||
* | | | StaticEvalObject Placeholder so eval scopes may be iterated through
|
* \ \ DeclEnvObject Holds name of recursive/heavyweight named lambda
|
||||||
* | | |
|
* \ \
|
||||||
* | | DeclEnvObject Holds name of recursive/heavyweight named lambda
|
* \ CallObject Scope of entire function or strict eval
|
||||||
* | |
|
* \
|
||||||
* | CallObject Scope of entire function or strict eval
|
* NestedScopeObject Scope created for a statement
|
||||||
* |
|
* \ \ \
|
||||||
* NestedScopeObject Scope created for a statement
|
* \ \ StaticWithObject Template for "with" object in static scope chain
|
||||||
* | | |
|
* \ \
|
||||||
* | | StaticWithObject Template for "with" object in static scope chain
|
* \ DynamicWithObject Run-time "with" object on scope chain
|
||||||
* | |
|
* \
|
||||||
* | DynamicWithObject Run-time "with" object on scope chain
|
* BlockObject Shared interface of cloned/static block objects
|
||||||
* |
|
* \ \
|
||||||
* BlockObject Shared interface of cloned/static block objects
|
* \ ClonedBlockObject let, switch, catch, for
|
||||||
* | |
|
* \
|
||||||
* | ClonedBlockObject let, switch, catch, for
|
* StaticBlockObject See NB
|
||||||
* |
|
|
||||||
* StaticBlockObject See NB
|
|
||||||
*
|
*
|
||||||
* This hierarchy represents more than just the interface hierarchy: reserved
|
* This hierarchy represents more than just the interface hierarchy: reserved
|
||||||
* slots in base classes are fixed for all derived classes. Thus, for example,
|
* slots in base classes are fixed for all derived classes. Thus, for example,
|
||||||
|
@ -214,9 +206,6 @@ ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc);
|
||||||
* are cloned at runtime. These objects should never escape into the wild and
|
* are cloned at runtime. These objects should never escape into the wild and
|
||||||
* support a restricted set of ScopeObject operations.
|
* support a restricted set of ScopeObject operations.
|
||||||
*
|
*
|
||||||
* NB2: StaticNonSyntacticScopeObjects notify either of 0+ non-syntactic
|
|
||||||
* DynamicWithObjects on the dynamic scope chain or a NonSyntacticScopeObject.
|
|
||||||
*
|
|
||||||
* See also "Debug scope objects" below.
|
* See also "Debug scope objects" below.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -351,10 +340,12 @@ class DeclEnvObject : public ScopeObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const uint32_t RESERVED_SLOTS = 2;
|
static const uint32_t RESERVED_SLOTS = 2;
|
||||||
|
static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT2_BACKGROUND;
|
||||||
|
|
||||||
static const Class class_;
|
static const Class class_;
|
||||||
|
|
||||||
static DeclEnvObject*
|
static DeclEnvObject*
|
||||||
createTemplateObject(JSContext* cx, HandleFunction fun, NewObjectKind newKind);
|
createTemplateObject(JSContext* cx, HandleFunction fun, gc::InitialHeap heap);
|
||||||
|
|
||||||
static DeclEnvObject* create(JSContext* cx, HandleObject enclosing, HandleFunction callee);
|
static DeclEnvObject* create(JSContext* cx, HandleObject enclosing, HandleFunction callee);
|
||||||
|
|
||||||
|
@ -363,15 +354,16 @@ class DeclEnvObject : public ScopeObject
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Static eval scope placeholder objects on the static scope chain. Created at
|
// Static eval scope template objects on the static scope. Created at the
|
||||||
// the time of compiling the eval script, and set as its static enclosing
|
// time of compiling the eval script, and set as its static enclosing scope.
|
||||||
// scope.
|
|
||||||
class StaticEvalObject : public ScopeObject
|
class StaticEvalObject : public ScopeObject
|
||||||
{
|
{
|
||||||
static const uint32_t STRICT_SLOT = 1;
|
static const uint32_t STRICT_SLOT = 1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const unsigned RESERVED_SLOTS = 2;
|
static const unsigned RESERVED_SLOTS = 2;
|
||||||
|
static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT2_BACKGROUND;
|
||||||
|
|
||||||
static const Class class_;
|
static const Class class_;
|
||||||
|
|
||||||
static StaticEvalObject* create(JSContext* cx, HandleObject enclosing);
|
static StaticEvalObject* create(JSContext* cx, HandleObject enclosing);
|
||||||
|
@ -395,42 +387,6 @@ class StaticEvalObject : public ScopeObject
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Static scope objects that stand in for one or more "polluting global"
|
|
||||||
// scopes on the dynamic scope chain.
|
|
||||||
//
|
|
||||||
// There are two flavors of polluting global scopes on the dynamic scope
|
|
||||||
// chain: either 0+ non-syntactic DynamicWithObjects, or 1
|
|
||||||
// NonSyntacticVariablesObject, created exclusively in
|
|
||||||
// js::ExecuteInGlobalAndReturnScope.
|
|
||||||
class StaticNonSyntacticScopeObjects : public ScopeObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const unsigned RESERVED_SLOTS = 1;
|
|
||||||
static const Class class_;
|
|
||||||
|
|
||||||
static StaticNonSyntacticScopeObjects* create(JSContext* cx, HandleObject enclosing);
|
|
||||||
|
|
||||||
JSObject* enclosingScopeForStaticScopeIter() {
|
|
||||||
return getReservedSlot(SCOPE_CHAIN_SLOT).toObjectOrNull();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// A non-syntactic dynamic scope object that captures non-lexical
|
|
||||||
// bindings. That is, a scope object that captures both qualified var
|
|
||||||
// assignments and unqualified bareword assignments. Its parent is always the
|
|
||||||
// real global.
|
|
||||||
//
|
|
||||||
// This is used in ExecuteInGlobalAndReturnScope and sits in front of the
|
|
||||||
// global scope to capture 'var' and bareword asignments.
|
|
||||||
class NonSyntacticVariablesObject : public ScopeObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const unsigned RESERVED_SLOTS = 1;
|
|
||||||
static const Class class_;
|
|
||||||
|
|
||||||
static NonSyntacticVariablesObject* create(JSContext* cx, Handle<GlobalObject*> global);
|
|
||||||
};
|
|
||||||
|
|
||||||
class NestedScopeObject : public ScopeObject
|
class NestedScopeObject : public ScopeObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -480,6 +436,8 @@ class StaticWithObject : public NestedScopeObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const unsigned RESERVED_SLOTS = 1;
|
static const unsigned RESERVED_SLOTS = 1;
|
||||||
|
static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT2_BACKGROUND;
|
||||||
|
|
||||||
static const Class class_;
|
static const Class class_;
|
||||||
|
|
||||||
static StaticWithObject* create(ExclusiveContext* cx);
|
static StaticWithObject* create(ExclusiveContext* cx);
|
||||||
|
@ -494,6 +452,8 @@ class DynamicWithObject : public NestedScopeObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const unsigned RESERVED_SLOTS = 4;
|
static const unsigned RESERVED_SLOTS = 4;
|
||||||
|
static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT4_BACKGROUND;
|
||||||
|
|
||||||
static const Class class_;
|
static const Class class_;
|
||||||
|
|
||||||
enum WithKind {
|
enum WithKind {
|
||||||
|
@ -545,6 +505,8 @@ class BlockObject : public NestedScopeObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const unsigned RESERVED_SLOTS = 2;
|
static const unsigned RESERVED_SLOTS = 2;
|
||||||
|
static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT4_BACKGROUND;
|
||||||
|
|
||||||
static const Class class_;
|
static const Class class_;
|
||||||
|
|
||||||
/* Return the abstract stack depth right before entering this nested scope. */
|
/* Return the abstract stack depth right before entering this nested scope. */
|
||||||
|
@ -631,7 +593,7 @@ class StaticBlockObject : public BlockObject
|
||||||
* variable of the block isAliased.
|
* variable of the block isAliased.
|
||||||
*/
|
*/
|
||||||
bool needsClone() {
|
bool needsClone() {
|
||||||
return numVariables() > 0 && !getSlot(RESERVED_SLOTS).isFalse();
|
return !getFixedSlot(RESERVED_SLOTS).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Frontend-only functions ***********************************************/
|
/* Frontend-only functions ***********************************************/
|
||||||
|
@ -735,6 +697,8 @@ class UninitializedLexicalObject : public ScopeObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const unsigned RESERVED_SLOTS = 1;
|
static const unsigned RESERVED_SLOTS = 1;
|
||||||
|
static const gc::AllocKind FINALIZE_KIND = gc::AllocKind::OBJECT2_BACKGROUND;
|
||||||
|
|
||||||
static const Class class_;
|
static const Class class_;
|
||||||
|
|
||||||
static UninitializedLexicalObject* create(JSContext* cx, HandleObject enclosing);
|
static UninitializedLexicalObject* create(JSContext* cx, HandleObject enclosing);
|
||||||
|
@ -795,20 +759,17 @@ class ScopeIter
|
||||||
inline JSObject& enclosingScope() const;
|
inline JSObject& enclosingScope() const;
|
||||||
|
|
||||||
// If !done():
|
// If !done():
|
||||||
enum Type { Call, Block, With, Eval, NonSyntactic };
|
enum Type { Call, Block, With, Eval };
|
||||||
Type type() const;
|
Type type() const;
|
||||||
|
|
||||||
inline bool hasNonSyntacticScopeObject() const;
|
inline bool hasScopeObject() const;
|
||||||
inline bool hasSyntacticScopeObject() const;
|
inline bool canHaveScopeObject() const;
|
||||||
inline bool hasAnyScopeObject() const;
|
|
||||||
inline bool canHaveSyntacticScopeObject() const;
|
|
||||||
ScopeObject& scope() const;
|
ScopeObject& scope() const;
|
||||||
|
|
||||||
JSObject* maybeStaticScope() const;
|
JSObject* maybeStaticScope() const;
|
||||||
StaticBlockObject& staticBlock() const { return ssi_.block(); }
|
StaticBlockObject& staticBlock() const { return ssi_.block(); }
|
||||||
StaticWithObject& staticWith() const { return ssi_.staticWith(); }
|
StaticWithObject& staticWith() const { return ssi_.staticWith(); }
|
||||||
StaticEvalObject& staticEval() const { return ssi_.eval(); }
|
StaticEvalObject& staticEval() const { return ssi_.eval(); }
|
||||||
StaticNonSyntacticScopeObjects& staticNonSyntactic() const { return ssi_.nonSyntactic(); }
|
|
||||||
JSFunction& fun() const { return ssi_.fun(); }
|
JSFunction& fun() const { return ssi_.fun(); }
|
||||||
|
|
||||||
bool withinInitialFrame() const { return !!frame_; }
|
bool withinInitialFrame() const { return !!frame_; }
|
||||||
|
@ -1048,8 +1009,7 @@ JSObject::is<js::ScopeObject>() const
|
||||||
return is<js::CallObject>() ||
|
return is<js::CallObject>() ||
|
||||||
is<js::DeclEnvObject>() ||
|
is<js::DeclEnvObject>() ||
|
||||||
is<js::NestedScopeObject>() ||
|
is<js::NestedScopeObject>() ||
|
||||||
is<js::UninitializedLexicalObject>() ||
|
is<js::UninitializedLexicalObject>();
|
||||||
is<js::NonSyntacticVariablesObject>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -1081,8 +1041,8 @@ inline bool
|
||||||
IsSyntacticScope(JSObject* scope)
|
IsSyntacticScope(JSObject* scope)
|
||||||
{
|
{
|
||||||
return scope->is<ScopeObject>() &&
|
return scope->is<ScopeObject>() &&
|
||||||
(!scope->is<DynamicWithObject>() || scope->as<DynamicWithObject>().isSyntactic()) &&
|
(!scope->is<DynamicWithObject>() ||
|
||||||
!scope->is<NonSyntacticVariablesObject>();
|
scope->as<DynamicWithObject>().isSyntactic());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Value&
|
inline const Value&
|
||||||
|
@ -1106,54 +1066,16 @@ ScopeIter::done() const
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
ScopeIter::hasSyntacticScopeObject() const
|
ScopeIter::hasScopeObject() const
|
||||||
{
|
{
|
||||||
return ssi_.hasSyntacticDynamicScopeObject();
|
return ssi_.hasDynamicScopeObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
ScopeIter::hasNonSyntacticScopeObject() const
|
ScopeIter::canHaveScopeObject() const
|
||||||
{
|
{
|
||||||
// The case we're worrying about here is a NonSyntactic static scope which
|
// Non-strict eval scopes cannot have dynamic scope objects.
|
||||||
// has 0+ corresponding non-syntactic DynamicWithObject scopes or a
|
return !ssi_.done() && (type() != Eval || staticEval().isStrict());
|
||||||
// NonSyntacticVariablesObject.
|
|
||||||
if (ssi_.type() == StaticScopeIter<CanGC>::NonSyntactic) {
|
|
||||||
MOZ_ASSERT_IF(scope_->is<DynamicWithObject>(),
|
|
||||||
!scope_->as<DynamicWithObject>().isSyntactic());
|
|
||||||
return scope_->is<DynamicWithObject>() ||
|
|
||||||
scope_->is<NonSyntacticVariablesObject>();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
ScopeIter::hasAnyScopeObject() const
|
|
||||||
{
|
|
||||||
return hasSyntacticScopeObject() || hasNonSyntacticScopeObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
ScopeIter::canHaveSyntacticScopeObject() const
|
|
||||||
{
|
|
||||||
if (ssi_.done())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (type()) {
|
|
||||||
case Call:
|
|
||||||
return true;
|
|
||||||
case Block:
|
|
||||||
return true;
|
|
||||||
case With:
|
|
||||||
return true;
|
|
||||||
case Eval:
|
|
||||||
// Only strict eval scopes can have dynamic scope objects.
|
|
||||||
return staticEval().isStrict();
|
|
||||||
case NonSyntactic:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Silence warnings.
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JSObject&
|
inline JSObject&
|
||||||
|
@ -1171,12 +1093,10 @@ ScopeIter::enclosingScope() const
|
||||||
extern bool
|
extern bool
|
||||||
CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
|
CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
|
||||||
HandleObject dynamicTerminatingScope,
|
HandleObject dynamicTerminatingScope,
|
||||||
MutableHandleObject dynamicScopeObj);
|
MutableHandleObject dynamicScopeObj,
|
||||||
|
MutableHandleObject staticScopeObj);
|
||||||
bool HasNonSyntacticStaticScopeChain(JSObject* staticScope);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void DumpStaticScopeChain(JSScript* script);
|
|
||||||
bool
|
bool
|
||||||
AnalyzeEntrainedVariables(JSContext* cx, HandleScript script);
|
AnalyzeEntrainedVariables(JSContext* cx, HandleScript script);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1722,9 +1722,7 @@ CloneObject(JSContext* cx, HandleNativeObject selfHostedObject)
|
||||||
js::gc::AllocKind kind = hasName
|
js::gc::AllocKind kind = hasName
|
||||||
? gc::AllocKind::FUNCTION_EXTENDED
|
? gc::AllocKind::FUNCTION_EXTENDED
|
||||||
: selfHostedFunction->getAllocKind();
|
: selfHostedFunction->getAllocKind();
|
||||||
MOZ_ASSERT(!CanReuseScriptForClone(cx->compartment(), selfHostedFunction, cx->global()));
|
clone = CloneFunctionObject(cx, selfHostedFunction, cx->global(), kind, TenuredObject);
|
||||||
clone = CloneFunctionAndScript(cx, selfHostedFunction, cx->global(),
|
|
||||||
/* newStaticScope = */ nullptr, kind);
|
|
||||||
// To be able to re-lazify the cloned function, its name in the
|
// To be able to re-lazify the cloned function, its name in the
|
||||||
// self-hosting compartment has to be stored on the clone.
|
// self-hosting compartment has to be stored on the clone.
|
||||||
if (clone && hasName)
|
if (clone && hasName)
|
||||||
|
@ -1808,17 +1806,22 @@ JSRuntime::cloneSelfHostedFunctionScript(JSContext* cx, HandlePropertyName name,
|
||||||
// JSFunction::generatorKind can't handle lazy self-hosted functions, so we make sure there
|
// JSFunction::generatorKind can't handle lazy self-hosted functions, so we make sure there
|
||||||
// aren't any.
|
// aren't any.
|
||||||
MOZ_ASSERT(!sourceFun->isGenerator());
|
MOZ_ASSERT(!sourceFun->isGenerator());
|
||||||
MOZ_ASSERT(sourceFun->nargs() == targetFun->nargs());
|
|
||||||
// The target function might have been relazified after it's flags changed.
|
|
||||||
targetFun->setFlags((targetFun->flags() & ~JSFunction::INTERPRETED_LAZY) |
|
|
||||||
sourceFun->flags() | JSFunction::EXTENDED);
|
|
||||||
MOZ_ASSERT(targetFun->isExtended());
|
|
||||||
|
|
||||||
RootedScript sourceScript(cx, sourceFun->getOrCreateScript(cx));
|
RootedScript sourceScript(cx, sourceFun->getOrCreateScript(cx));
|
||||||
if (!sourceScript)
|
if (!sourceScript)
|
||||||
return false;
|
return false;
|
||||||
MOZ_ASSERT(!sourceScript->enclosingStaticScope());
|
MOZ_ASSERT(!sourceScript->enclosingStaticScope());
|
||||||
return !!CloneScriptIntoFunction(cx, /* enclosingScope = */ nullptr, targetFun, sourceScript);
|
JSScript* cscript = CloneScript(cx, nullptr, targetFun, sourceScript);
|
||||||
|
if (!cscript)
|
||||||
|
return false;
|
||||||
|
cscript->setFunction(targetFun);
|
||||||
|
|
||||||
|
MOZ_ASSERT(sourceFun->nargs() == targetFun->nargs());
|
||||||
|
// The target function might have been relazified after it's flags changed.
|
||||||
|
targetFun->setFlags((targetFun->flags() & ~JSFunction::INTERPRETED_LAZY) |
|
||||||
|
sourceFun->flags() | JSFunction::EXTENDED);
|
||||||
|
targetFun->setScript(cscript);
|
||||||
|
MOZ_ASSERT(targetFun->isExtended());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -153,12 +153,7 @@ AssertDynamicScopeMatchesStaticScope(JSContext* cx, JSScript* script, JSObject*
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
RootedObject enclosingScope(cx, script->enclosingStaticScope());
|
RootedObject enclosingScope(cx, script->enclosingStaticScope());
|
||||||
for (StaticScopeIter<NoGC> i(enclosingScope); !i.done(); i++) {
|
for (StaticScopeIter<NoGC> i(enclosingScope); !i.done(); i++) {
|
||||||
if (i.type() == StaticScopeIter<NoGC>::NonSyntactic) {
|
if (i.hasDynamicScopeObject()) {
|
||||||
while (scope->is<DynamicWithObject>() || scope->is<NonSyntacticVariablesObject>()) {
|
|
||||||
MOZ_ASSERT(!IsSyntacticScope(scope));
|
|
||||||
scope = &scope->as<ScopeObject>().enclosingScope();
|
|
||||||
}
|
|
||||||
} else if (i.hasSyntacticDynamicScopeObject()) {
|
|
||||||
switch (i.type()) {
|
switch (i.type()) {
|
||||||
case StaticScopeIter<NoGC>::Function:
|
case StaticScopeIter<NoGC>::Function:
|
||||||
MOZ_ASSERT(scope->as<CallObject>().callee().nonLazyScript() == i.funScript());
|
MOZ_ASSERT(scope->as<CallObject>().callee().nonLazyScript() == i.funScript());
|
||||||
|
@ -178,14 +173,13 @@ AssertDynamicScopeMatchesStaticScope(JSContext* cx, JSScript* script, JSObject*
|
||||||
case StaticScopeIter<NoGC>::Eval:
|
case StaticScopeIter<NoGC>::Eval:
|
||||||
scope = &scope->as<CallObject>().enclosingScope();
|
scope = &scope->as<CallObject>().enclosingScope();
|
||||||
break;
|
break;
|
||||||
case StaticScopeIter<NoGC>::NonSyntactic:
|
|
||||||
MOZ_CRASH("NonSyntactic should not have a syntactic scope");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(scope->is<GlobalObject>() || scope->is<DebugScopeObject>());
|
// The scope chain is always ended by one or more non-syntactic
|
||||||
|
// ScopeObjects (viz. GlobalObject or a non-syntactic WithObject).
|
||||||
|
MOZ_ASSERT(!IsSyntacticScope(scope));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,7 +245,8 @@ InterpreterFrame::epilogue(JSContext* cx)
|
||||||
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
|
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
|
||||||
DebugScopes::onPopStrictEvalScope(this);
|
DebugScopes::onPopStrictEvalScope(this);
|
||||||
} else if (isDirectEvalFrame()) {
|
} else if (isDirectEvalFrame()) {
|
||||||
MOZ_ASSERT_IF(isDebuggerEvalFrame(), !IsSyntacticScope(scopeChain()));
|
if (isDebuggerEvalFrame())
|
||||||
|
MOZ_ASSERT(!IsSyntacticScope(scopeChain()));
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Debugger.Object.prototype.evalInGlobal creates indirect eval
|
* Debugger.Object.prototype.evalInGlobal creates indirect eval
|
||||||
|
@ -1143,7 +1138,7 @@ FrameIter::matchCallee(JSContext* cx, HandleFunction fun) const
|
||||||
// expect both functions to have the same JSScript. If so, and if they are
|
// expect both functions to have the same JSScript. If so, and if they are
|
||||||
// different, then they cannot be equal.
|
// different, then they cannot be equal.
|
||||||
RootedObject global(cx, &fun->global());
|
RootedObject global(cx, &fun->global());
|
||||||
bool useSameScript = CanReuseScriptForClone(fun->compartment(), currentCallee, global);
|
bool useSameScript = CloneFunctionObjectUseSameScript(fun->compartment(), currentCallee, global);
|
||||||
if (useSameScript &&
|
if (useSameScript &&
|
||||||
(currentCallee->hasScript() != fun->hasScript() ||
|
(currentCallee->hasScript() != fun->hasScript() ||
|
||||||
currentCallee->nonLazyScript() != fun->nonLazyScript()))
|
currentCallee->nonLazyScript() != fun->nonLazyScript()))
|
||||||
|
|
|
@ -146,10 +146,8 @@ PrepareScript(nsIURI* uri,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!reuseGlobal) {
|
if (!reuseGlobal) {
|
||||||
if (JS_IsGlobalObject(targetObj))
|
options.setHasPollutedScope(!JS_IsGlobalObject(targetObj));
|
||||||
JS::Compile(cx, options, srcBuf, script);
|
JS::Compile(cx, options, srcBuf, script);
|
||||||
else
|
|
||||||
JS::CompileForNonSyntacticScope(cx, options, srcBuf, script);
|
|
||||||
} else {
|
} else {
|
||||||
AutoObjectVector scopeChain(cx);
|
AutoObjectVector scopeChain(cx);
|
||||||
if (!JS_IsGlobalObject(targetObj) &&
|
if (!JS_IsGlobalObject(targetObj) &&
|
||||||
|
@ -164,11 +162,9 @@ PrepareScript(nsIURI* uri,
|
||||||
// We only use lazy source when no special encoding is specified because
|
// We only use lazy source when no special encoding is specified because
|
||||||
// the lazy source loader doesn't know the encoding.
|
// the lazy source loader doesn't know the encoding.
|
||||||
if (!reuseGlobal) {
|
if (!reuseGlobal) {
|
||||||
options.setSourceIsLazy(true);
|
options.setSourceIsLazy(true)
|
||||||
if (JS_IsGlobalObject(targetObj))
|
.setHasPollutedScope(!JS_IsGlobalObject(targetObj));
|
||||||
JS::Compile(cx, options, buf, len, script);
|
JS::Compile(cx, options, buf, len, script);
|
||||||
else
|
|
||||||
JS::CompileForNonSyntacticScope(cx, options, buf, len, script);
|
|
||||||
} else {
|
} else {
|
||||||
AutoObjectVector scopeChain(cx);
|
AutoObjectVector scopeChain(cx);
|
||||||
if (!JS_IsGlobalObject(targetObj) &&
|
if (!JS_IsGlobalObject(targetObj) &&
|
||||||
|
|
Загрузка…
Ссылка в новой задаче