Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
roytam1 2023-05-10 11:57:40 +08:00
commit e70aa9a4a1
21 changed files with 219 additions and 59 deletions

View file

@ -12,6 +12,8 @@
#include "gc/Policy.h"
#include "gc/Tracer.h"
#include "vm/SelfHosting.h"
#include "vm/AsyncFunction.h"
#include "vm/AsyncIteration.h"
#include "jsobjinlines.h"
#include "jsscriptinlines.h"
@ -954,15 +956,27 @@ ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject
RootedModuleEnvironmentObject env(cx, &self->initialEnvironment());
RootedFunction fun(cx);
RootedObject obj(cx);
RootedValue value(cx);
for (const auto& funDecl : *funDecls) {
fun = funDecl.fun;
RootedObject obj(cx, Lambda(cx, fun, env));
obj = Lambda(cx, fun, env);
if (!obj)
return false;
value = ObjectValue(*fun);
if (fun->isAsync()) {
if (fun->isStarGenerator()) {
obj = WrapAsyncGenerator(cx, obj.as<JSFunction>());
} else {
obj = WrapAsyncFunction(cx, obj.as<JSFunction>());
}
}
if (!obj)
return false;
value = ObjectValue(*obj);
if (!SetProperty(cx, env, funDecl.name->asPropertyName(), value))
return false;
}

View file

@ -4055,7 +4055,7 @@ reflect_parse(JSContext* cx, uint32_t argc, Value* vp)
return false;
Parser<FullParseHandler> parser(cx, cx->tempLifoAlloc(), options, chars.begin().get(),
chars.length(), /* foldConstants = */ false, usedNames,
nullptr, nullptr, target);
nullptr, nullptr);
if (!parser.checkOptions())
return false;

View file

@ -74,9 +74,8 @@ class MOZ_STACK_CLASS BytecodeCompiler
bool createScriptSource(Maybe<uint32_t> parameterListEnd);
bool maybeCompressSource();
bool canLazilyParse();
bool createParser(ParseGoal goal);
bool createSourceAndParser(ParseGoal goal,
Maybe<uint32_t> parameterListEnd = Nothing());
bool createParser();
bool createSourceAndParser(Maybe<uint32_t> parameterListEnd = Nothing());
// If toString{Start,End} are not explicitly passed, assume the script's
// offsets in the source used to parse it are the same as what should be
@ -213,7 +212,7 @@ BytecodeCompiler::canLazilyParse()
}
bool
BytecodeCompiler::createParser(ParseGoal goal)
BytecodeCompiler::createParser()
{
usedNames.emplace(cx);
if (!usedNames->init())
@ -222,14 +221,14 @@ BytecodeCompiler::createParser(ParseGoal goal)
if (canLazilyParse()) {
syntaxParser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(),
/* foldConstants = */ false, *usedNames,
(Parser<SyntaxParseHandler>*) nullptr, (LazyScript*) nullptr, goal);
(Parser<SyntaxParseHandler>*) nullptr, (LazyScript*) nullptr);
if (!syntaxParser->checkOptions())
return false;
}
parser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(),
/* foldConstants = */ true, *usedNames, syntaxParser.ptrOr(nullptr), nullptr, goal);
/* foldConstants = */ true, *usedNames, syntaxParser.ptrOr(nullptr), nullptr);
parser->sct = sourceCompressor;
parser->ss = scriptSource;
if (!parser->checkOptions())
@ -240,12 +239,11 @@ BytecodeCompiler::createParser(ParseGoal goal)
}
bool
BytecodeCompiler::createSourceAndParser(ParseGoal goal,
Maybe<uint32_t> parameterListEnd /* = Nothing() */)
BytecodeCompiler::createSourceAndParser(Maybe<uint32_t> parameterListEnd /* = Nothing() */)
{
return createScriptSource(parameterListEnd) &&
maybeCompressSource() &&
createParser(goal);
createParser();
}
bool
@ -324,7 +322,7 @@ BytecodeCompiler::maybeCompleteCompressSource()
JSScript*
BytecodeCompiler::compileScript(HandleObject environment, SharedContext* sc)
{
if (!createSourceAndParser(ParseGoal::Script))
if (!createSourceAndParser())
return nullptr;
if (!createScript())
@ -394,7 +392,7 @@ BytecodeCompiler::compileEvalScript(HandleObject environment, HandleScope enclos
ModuleObject*
BytecodeCompiler::compileModule()
{
if (!createSourceAndParser(ParseGoal::Module))
if (!createSourceAndParser())
return nullptr;
Rooted<ModuleObject*> module(cx, ModuleObject::create(cx));
@ -451,7 +449,7 @@ BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
MOZ_ASSERT(fun);
MOZ_ASSERT(fun->isTenured());
if (!createSourceAndParser(ParseGoal::Script, parameterListEnd))
if (!createSourceAndParser(parameterListEnd))
return false;
// Speculatively parse using the default directives implied by the context.
@ -651,7 +649,7 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
if (!usedNames.init())
return false;
Parser<FullParseHandler> parser(cx, cx->tempLifoAlloc(), options, chars, length,
/* foldConstants = */ true, usedNames, nullptr, lazy, lazy->parseGoal());
/* foldConstants = */ true, usedNames, nullptr, lazy);
if (!parser.checkOptions())
return false;

View file

@ -491,6 +491,9 @@ FunctionBox::initFromLazyFunction()
setDerivedClassConstructor();
if (fun->lazyScript()->needsHomeObject())
setNeedsHomeObject();
if (fun->lazyScript()->hasModuleGoal()) {
setHasModuleGoal();
}
enclosingScope_ = fun->lazyScript()->enclosingScope();
initWithEnclosingScope(enclosingScope_);
}
@ -557,6 +560,9 @@ FunctionBox::initWithEnclosingParseContext(ParseContext* enclosing, FunctionSynt
}
}
// We inherit the parse goal from our top-level.
hasModuleGoal_ = sc->hasModuleGoal();
if (sc->inWith()) {
inWith_ = true;
} else {
@ -787,8 +793,7 @@ ParserBase::ParserBase(ExclusiveContext* cx, LifoAlloc& alloc,
bool foldConstants,
UsedNameTracker& usedNames,
Parser<SyntaxParseHandler>* syntaxParser,
LazyScript* lazyOuterFunction,
ParseGoal parseGoal)
LazyScript* lazyOuterFunction)
: context(cx),
alloc(alloc),
tokenStream(cx, options, chars, length, thisForCtor()),
@ -804,8 +809,7 @@ ParserBase::ParserBase(ExclusiveContext* cx, LifoAlloc& alloc,
#endif
abortedSyntaxParse(false),
isUnexpectedEOF_(false),
awaitHandling_(AwaitIsName),
parseGoal_(uint8_t(parseGoal))
awaitHandling_(AwaitIsName)
{
cx->perThreadData->frontendCollectionPool.addActiveCompilation();
tempPoolMark = alloc.mark();
@ -832,10 +836,9 @@ Parser<ParseHandler>::Parser(ExclusiveContext* cx, LifoAlloc& alloc,
bool foldConstants,
UsedNameTracker& usedNames,
Parser<SyntaxParseHandler>* syntaxParser,
LazyScript* lazyOuterFunction,
ParseGoal parseGoal)
LazyScript* lazyOuterFunction)
: ParserBase(cx, alloc, options, chars, length, foldConstants, usedNames, syntaxParser,
lazyOuterFunction, parseGoal),
lazyOuterFunction),
AutoGCRooter(cx, PARSER),
handler(cx, alloc, tokenStream, syntaxParser, lazyOuterFunction)
{
@ -949,6 +952,7 @@ ModuleSharedContext::ModuleSharedContext(ExclusiveContext* cx, ModuleObject* mod
builder(builder)
{
thisBinding_ = ThisBinding::Module;
hasModuleGoal_ = true;
}
template <typename ParseHandler>
@ -2473,8 +2477,7 @@ Parser<SyntaxParseHandler>::finishFunction(bool isStandaloneFunction /* = false
pc->innerFunctionsForLazy, versionNumber(),
funbox->bufStart, funbox->bufEnd,
funbox->toStringStart,
funbox->startLine, funbox->startColumn,
parseGoal());
funbox->startLine, funbox->startColumn);
if (!lazy)
return false;
@ -2498,6 +2501,8 @@ Parser<SyntaxParseHandler>::finishFunction(bool isStandaloneFunction /* = false
lazy->setShouldDeclareArguments();
if (funbox->hasThisBinding())
lazy->setHasThisBinding();
if (funbox->hasModuleGoal())
lazy->setHasModuleGoal();
// Flags that need to copied back into the parser when we do the full
// parse.
@ -5780,14 +5785,15 @@ Parser<ParseHandler>::exportVariableStatement(uint32_t begin)
template <typename ParseHandler>
typename ParseHandler::UnaryNodeType
Parser<ParseHandler>::exportFunctionDeclaration(uint32_t begin)
Parser<ParseHandler>::exportFunctionDeclaration(uint32_t begin,
FunctionAsyncKind asyncKind /* = SyncFunction */)
{
if (!abortIfSyntaxParser())
return null();
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
Node kid = functionStmt(pos().begin, YieldIsKeyword, NameRequired);
Node kid = functionStmt(pos().begin, YieldIsKeyword, NameRequired, asyncKind);
if (!kid)
return null();
@ -6010,6 +6016,20 @@ Parser<ParseHandler>::exportDeclaration()
case TOK_FUNCTION:
return exportFunctionDeclaration(begin);
case TOK_ASYNC: {
TokenKind nextSameLine = TOK_EOF;
if (!tokenStream.peekTokenSameLine(&nextSameLine))
return null();
if (nextSameLine == TOK_FUNCTION) {
tokenStream.consumeKnownToken(TOK_FUNCTION);
return exportFunctionDeclaration(begin, AsyncFunction);
}
error(JSMSG_DECLARATION_AFTER_EXPORT);
return null();
}
case TOK_CLASS:
return exportClassDeclaration(begin);

View file

@ -817,8 +817,6 @@ class ParserBase : public StrictModeGetter
/* AwaitHandling */ uint8_t awaitHandling_:2;
uint8_t parseGoal_:1;
public:
bool awaitIsKeyword() const {
return awaitHandling_ == AwaitIsKeyword || awaitHandling_ == AwaitIsModuleKeyword;
@ -828,13 +826,13 @@ class ParserBase : public StrictModeGetter
}
ParseGoal parseGoal() const {
return ParseGoal(parseGoal_);
return pc->sc()->hasModuleGoal() ? ParseGoal::Module : ParseGoal::Script;
}
ParserBase(ExclusiveContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
const char16_t* chars, size_t length, bool foldConstants,
UsedNameTracker& usedNames, Parser<SyntaxParseHandler>* syntaxParser,
LazyScript* lazyOuterFunction, ParseGoal parseGoal);
LazyScript* lazyOuterFunction);
~ParserBase();
const char* getFilename() const { return tokenStream.getFilename(); }
@ -1072,7 +1070,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
public:
Parser(ExclusiveContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
const char16_t* chars, size_t length, bool foldConstants, UsedNameTracker& usedNames,
Parser<SyntaxParseHandler>* syntaxParser, LazyScript* lazyOuterFunction, ParseGoal parseGoal);
Parser<SyntaxParseHandler>* syntaxParser, LazyScript* lazyOuterFunction);
~Parser();
friend class AutoAwaitIsKeyword<ParseHandler>;
@ -1337,7 +1335,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
BinaryNodeType exportBatch(uint32_t begin);
bool checkLocalExportNames(ListNodeType node);
Node exportClause(uint32_t begin);
UnaryNodeType exportFunctionDeclaration(uint32_t begin);
UnaryNodeType exportFunctionDeclaration(uint32_t begin,
FunctionAsyncKind asyncKind = SyncFunction);
UnaryNodeType exportVariableStatement(uint32_t begin);
UnaryNodeType exportClassDeclaration(uint32_t begin);
UnaryNodeType exportLexicalDeclaration(uint32_t begin, DeclarationKind kind);

View file

@ -249,6 +249,9 @@ class SharedContext
bool inWith_;
bool needsThisTDZChecks_;
// Script is being parsed with a goal of Module.
bool hasModuleGoal_ : 1;
void computeAllowSyntax(Scope* scope);
void computeInWith(Scope* scope);
void computeThisBinding(Scope* scope);
@ -267,7 +270,8 @@ class SharedContext
allowSuperCall_(false),
allowArguments_(true),
inWith_(false),
needsThisTDZChecks_(false)
needsThisTDZChecks_(false),
hasModuleGoal_(false)
{ }
// If this is the outermost SharedContext, the Scope that encloses
@ -287,6 +291,7 @@ class SharedContext
ThisBinding thisBinding() const { return thisBinding_; }
bool hasModuleGoal() const { return hasModuleGoal_; }
bool allowNewTarget() const { return allowNewTarget_; }
bool allowSuperProperty() const { return allowSuperProperty_; }
bool allowSuperCall() const { return allowSuperCall_; }
@ -303,6 +308,7 @@ class SharedContext
void setBindingsAccessedDynamically() { anyCxFlags.bindingsAccessedDynamically = true; }
void setHasDebuggerStatement() { anyCxFlags.hasDebuggerStatement = true; }
void setHasDirectEval() { anyCxFlags.hasDirectEval = true; }
void setHasModuleGoal() { hasModuleGoal_ = true; }
inline bool allBindingsClosedOver();

View file

@ -0,0 +1,15 @@
if (!('oomTest' in this))
quit();
loadFile(`
function parseAndEvaluate(source) {
let m = parseModule(source);
m.declarationInstantiation();
}
parseAndEvaluate("async function a() { await 2 + 3; }")
`);
function loadFile(lfVarx) {
oomTest(function() {
eval(lfVarx);
});
}

View file

@ -4265,8 +4265,7 @@ JS_BufferIsCompilableUnit(JSContext* cx, HandleObject obj, const char* utf8, siz
frontend::Parser<frontend::FullParseHandler> parser(cx, cx->tempLifoAlloc(),
options, chars, length,
/* foldConstants = */ true,
usedNames, nullptr, nullptr,
frontend::ParseGoal::Script);
usedNames, nullptr, nullptr);
JS::WarningReporter older = JS::SetWarningReporter(cx, nullptr);
if (!parser.checkOptions() || !parser.parse()) {
// We ran into an error. If it was because we ran out of source, we

View file

@ -2926,6 +2926,12 @@ JSScript::fullyInitFromEmitter(ExclusiveContext* cx, HandleScript script, Byteco
script->bodyScopeIndex_ = bce->bodyScopeIndex;
script->hasNonSyntacticScope_ = bce->outermostScope()->hasOnChain(ScopeKind::NonSyntactic);
if(bce->sc->hasModuleGoal()) {
LazyScript* lazy = script->maybeLazyScript();
if(lazy)
lazy->setHasModuleGoal();
}
if (bce->sc->isFunctionBox())
initFromFunctionBox(cx, script, bce->sc->asFunctionBox());
else if (bce->sc->isModuleContext())
@ -4231,8 +4237,7 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
Handle<GCVector<JSFunction*, 8>> innerFunctions,
JSVersion version,
uint32_t begin, uint32_t end,
uint32_t toStringStart, uint32_t lineno, uint32_t column,
frontend::ParseGoal parseGoal)
uint32_t toStringStart, uint32_t lineno, uint32_t column)
{
union {
PackedView p;
@ -4255,7 +4260,6 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
p.isLikelyConstructorWrapper = false;
p.isDerivedClassConstructor = false;
p.needsHomeObject = false;
p.parseGoal = uint32_t(parseGoal);
LazyScript* res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, toStringStart,
lineno, column);

View file

@ -2108,7 +2108,7 @@ class LazyScript : public gc::TenuredCell
uint32_t isFieldInitializer : 1;
uint32_t needsHomeObject : 1;
uint32_t hasRest : 1;
uint32_t parseGoal : 1;
uint32_t hasModuleGoal : 1;
};
union {
@ -2150,8 +2150,7 @@ class LazyScript : public gc::TenuredCell
const frontend::AtomVector& closedOverBindings,
Handle<GCVector<JSFunction*, 8>> innerFunctions,
JSVersion version, uint32_t begin, uint32_t end,
uint32_t toStringStart, uint32_t lineno, uint32_t column,
frontend::ParseGoal parseGoal);
uint32_t toStringStart, uint32_t lineno, uint32_t column);
// Create a LazyScript and initialize the closedOverBindings and the
// innerFunctions with dummy values to be replaced in a later initialization
@ -2262,8 +2261,20 @@ class LazyScript : public gc::TenuredCell
p_.isExprBody = true;
}
frontend::ParseGoal parseGoal() const {
return frontend::ParseGoal(p_.parseGoal);
// This was added in Issue #2236 to compensate for the lack of
// Mozilla's ImmutableFlags feature, if ImmutableFlags ever gets
// ported remove the next 2 methods.
bool hasModuleGoal() const {
return p_.hasModuleGoal;
}
void setHasModuleGoal() {
p_.hasModuleGoal = true;
}
js::frontend::ParseGoal parseGoal() const {
return hasModuleGoal() ? js::frontend::ParseGoal::Module
: js::frontend::ParseGoal::Script;
}
bool strict() const {

View file

@ -4342,8 +4342,7 @@ Parse(JSContext* cx, unsigned argc, Value* vp)
if (!usedNames.init())
return false;
Parser<FullParseHandler> parser(cx, cx->tempLifoAlloc(), options, chars, length,
/* foldConstants = */ true, usedNames, nullptr, nullptr,
ParseGoal::Script);
/* foldConstants = */ true, usedNames, nullptr, nullptr);
if (!parser.checkOptions())
return false;
@ -4394,8 +4393,7 @@ SyntaxParse(JSContext* cx, unsigned argc, Value* vp)
return false;
Parser<frontend::SyntaxParseHandler> parser(cx, cx->tempLifoAlloc(),
options, chars, length, false,
usedNames, nullptr, nullptr,
ParseGoal::Script);
usedNames, nullptr, nullptr);
if (!parser.checkOptions())
return false;

View file

@ -0,0 +1,13 @@
// |reftest| module
async function f() {
return "success";
}
var AsyncFunction = (async function(){}).constructor;
assertEq(f instanceof AsyncFunction, true);
f().then(v => {
reportCompare("success", v);
});

View file

@ -0,0 +1,13 @@
// |reftest| module skip-if(release_or_beta)
async function* f() {
return "success";
}
var AsyncGenerator = (async function*(){}).constructor;
assertEq(f instanceof AsyncGenerator, true);
f().next().then(v => {
reportCompare("success", v.value);
});

View file

View file

View file

@ -5084,8 +5084,7 @@ Debugger::isCompilableUnit(JSContext* cx, unsigned argc, Value* vp)
frontend::Parser<frontend::FullParseHandler> parser(cx, cx->tempLifoAlloc(),
options, chars.twoByteChars(),
length, /* foldConstants = */ true,
usedNames, nullptr, nullptr,
frontend::ParseGoal::Script);
usedNames, nullptr, nullptr);
JS::WarningReporter older = JS::SetWarningReporter(cx, nullptr);
if (!parser.checkOptions() || !parser.parse()) {
// We ran into an error. If it was because we ran out of memory we report