#include "frontend/SharedContext.h"
#include "frontend/ModuleSharedContext.h"
#include "frontend/ParseContext-inl.h"
#include "vm/EnvironmentObject-inl.h"
namespace js {
namespace frontend {
void SharedContext::computeAllowSyntax(Scope* scope) {
for (ScopeIter si(scope); si; si++) {
if (si.kind() == ScopeKind::Function) {
JSFunction* fun = si.scope()->as<FunctionScope>().canonicalFunction();
if (fun->isArrow()) {
continue;
}
allowNewTarget_ = true;
allowSuperProperty_ = fun->allowSuperProperty();
allowSuperCall_ = fun->isDerivedClassConstructor();
return;
}
}
}
void SharedContext::computeThisBinding(Scope* scope) {
for (ScopeIter si(scope); si; si++) {
if (si.kind() == ScopeKind::Module) {
thisBinding_ = ThisBinding::Module;
return;
}
if (si.kind() == ScopeKind::Function) {
JSFunction* fun = si.scope()->as<FunctionScope>().canonicalFunction();
if (fun->isArrow()) {
continue;
}
if (fun->isDerivedClassConstructor()) {
needsThisTDZChecks_ = true;
}
thisBinding_ = ThisBinding::Function;
return;
}
}
thisBinding_ = ThisBinding::Global;
}
void SharedContext::computeInWith(Scope* scope) {
for (ScopeIter si(scope); si; si++) {
if (si.kind() == ScopeKind::With) {
inWith_ = true;
break;
}
}
}
EvalSharedContext::EvalSharedContext(JSContext* cx, JSObject* enclosingEnv,
Scope* enclosingScope,
Directives directives, bool extraWarnings)
: SharedContext(cx, Kind::Eval, directives, extraWarnings),
enclosingScope_(cx, enclosingScope),
bindings(cx) {
computeAllowSyntax(enclosingScope);
computeInWith(enclosingScope);
computeThisBinding(enclosingScope);
if (enclosingEnv && enclosingScope->hasOnChain(ScopeKind::NonSyntactic)) {
JSObject* env = enclosingEnv;
while (env) {
JSObject* unwrapped = env;
if (env->is<DebugEnvironmentProxy>()) {
unwrapped = &env->as<DebugEnvironmentProxy>().environment();
}
if (unwrapped->is<CallObject>()) {
JSFunction* callee = &unwrapped->as<CallObject>().callee();
computeThisBinding(callee->nonLazyScript()->bodyScope());
break;
}
env = env->enclosingEnvironment();
}
}
}
#ifdef DEBUG
bool FunctionBox::atomsAreKept() { return cx_->zone()->hasKeptAtoms(); }
#endif
FunctionBox::FunctionBox(JSContext* cx, TraceListNode* traceListHead,
JSFunction* fun, uint32_t toStringStart,
Directives directives, bool extraWarnings,
GeneratorKind generatorKind,
FunctionAsyncKind asyncKind)
: ObjectBox(fun, traceListHead),
SharedContext(cx, Kind::FunctionBox, directives, extraWarnings),
enclosingScope_(nullptr),
namedLambdaBindings_(nullptr),
functionScopeBindings_(nullptr),
extraVarScopeBindings_(nullptr),
functionNode(nullptr),
bufStart(0),
bufEnd(0),
startLine(1),
startColumn(0),
toStringStart(toStringStart),
toStringEnd(0),
length(0),
isGenerator_(generatorKind == GeneratorKind::Generator),
isAsync_(asyncKind == FunctionAsyncKind::AsyncFunction),
hasDestructuringArgs(false),
hasParameterExprs(false),
hasDirectEvalInParameterExpr(false),
hasDuplicateParameters(false),
useAsm(false),
isAnnexB(false),
wasEmitted(false),
declaredArguments(false),
usesArguments(false),
usesApply(false),
usesThis(false),
usesReturn(false),
hasRest_(false),
hasExprBody_(false),
hasExtensibleScope_(false),
argumentsHasLocalBinding_(false),
definitelyNeedsArgsObj_(false),
needsHomeObject_(false),
isDerivedClassConstructor_(false),
hasThisBinding_(false),
hasInnerFunctions_(false) {
MOZ_ASSERT(fun->isTenured());
}
void FunctionBox::initFromLazyFunction() {
JSFunction* fun = function();
if (fun->lazyScript()->isDerivedClassConstructor()) {
setDerivedClassConstructor();
}
if (fun->lazyScript()->needsHomeObject()) {
setNeedsHomeObject();
}
if (fun->lazyScript()->hasEnclosingScope()) {
enclosingScope_ = fun->lazyScript()->enclosingScope();
} else {
enclosingScope_ = nullptr;
}
initWithEnclosingScope(enclosingScope_);
}
void FunctionBox::initStandaloneFunction(Scope* enclosingScope) {
MOZ_ASSERT(enclosingScope->is<GlobalScope>());
enclosingScope_ = enclosingScope;
allowNewTarget_ = true;
thisBinding_ = ThisBinding::Function;
}
void FunctionBox::initWithEnclosingParseContext(ParseContext* enclosing,
FunctionSyntaxKind kind) {
SharedContext* sc = enclosing->sc();
useAsm = sc->isFunctionBox() && sc->asFunctionBox()->useAsmOrInsideUseAsm();
JSFunction* fun = function();
if (fun->isArrow()) {
allowNewTarget_ = sc->allowNewTarget();
allowSuperProperty_ = sc->allowSuperProperty();
allowSuperCall_ = sc->allowSuperCall();
needsThisTDZChecks_ = sc->needsThisTDZChecks();
thisBinding_ = sc->thisBinding();
} else {
allowNewTarget_ = true;
allowSuperProperty_ = fun->allowSuperProperty();
if (IsConstructorKind(kind)) {
auto stmt =
enclosing->findInnermostStatement<ParseContext::ClassStatement>();
MOZ_ASSERT(stmt);
stmt->constructorBox = this;
if (kind == FunctionSyntaxKind::DerivedClassConstructor) {
setDerivedClassConstructor();
allowSuperCall_ = true;
needsThisTDZChecks_ = true;
}
}
thisBinding_ = ThisBinding::Function;
}
if (sc->inWith()) {
inWith_ = true;
} else {
auto isWith = [](ParseContext::Statement* stmt) {
return stmt->kind() == StatementKind::With;
};
inWith_ = enclosing->findInnermostStatement(isWith);
}
}
void FunctionBox::initWithEnclosingScope(Scope* enclosingScope) {
if (!function()->isArrow()) {
allowNewTarget_ = true;
allowSuperProperty_ = function()->allowSuperProperty();
if (isDerivedClassConstructor()) {
setDerivedClassConstructor();
allowSuperCall_ = true;
needsThisTDZChecks_ = true;
}
thisBinding_ = ThisBinding::Function;
} else {
computeAllowSyntax(enclosingScope);
computeThisBinding(enclosingScope);
}
computeInWith(enclosingScope);
}
void FunctionBox::setEnclosingScopeForInnerLazyFunction(Scope* enclosingScope) {
MOZ_ASSERT(isLazyFunctionWithoutEnclosingScope());
enclosingScope_ = enclosingScope;
}
void FunctionBox::finish() {
if (!isLazyFunctionWithoutEnclosingScope()) {
return;
}
MOZ_ASSERT(enclosingScope_);
function()->lazyScript()->setEnclosingScope(enclosingScope_);
}
ModuleSharedContext::ModuleSharedContext(JSContext* cx, ModuleObject* module,
Scope* enclosingScope,
ModuleBuilder& builder)
: SharedContext(cx, Kind::Module, Directives(true), false),
module_(cx, module),
enclosingScope_(cx, enclosingScope),
bindings(cx),
builder(builder) {
thisBinding_ = ThisBinding::Module;
}
}
}