diff options
author | Gaming4JC <g4jc@hyperbola.info> | 2019-06-08 15:29:37 -0400 |
---|---|---|
committer | Gaming4JC <g4jc@hyperbola.info> | 2019-07-18 22:38:16 -0400 |
commit | c3e3a917d634ee1e550b2a19096ee99dc2024139 (patch) | |
tree | c7e56641b7dfb16d7841e4238d159ad9271c9313 | |
parent | 7535217e1b164417d9aa05c38e5c23048c8d47ce (diff) | |
download | UXP-c3e3a917d634ee1e550b2a19096ee99dc2024139.tar UXP-c3e3a917d634ee1e550b2a19096ee99dc2024139.tar.gz UXP-c3e3a917d634ee1e550b2a19096ee99dc2024139.tar.lz UXP-c3e3a917d634ee1e550b2a19096ee99dc2024139.tar.xz UXP-c3e3a917d634ee1e550b2a19096ee99dc2024139.zip |
1325157 - Implement a ParserBase class that holds functionality that's identical between syntax parsing and full parsing.
-rw-r--r-- | js/src/frontend/Parser.cpp | 100 | ||||
-rw-r--r-- | js/src/frontend/Parser.h | 251 |
2 files changed, 181 insertions, 170 deletions
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 2a80afbf1..79b5d70f4 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -571,9 +571,8 @@ FunctionBox::initWithEnclosingScope(Scope* enclosingScope) computeInWith(enclosingScope); } -template <typename ParseHandler> void -Parser<ParseHandler>::error(unsigned errorNumber, ...) +ParserBase::error(unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); @@ -585,9 +584,8 @@ Parser<ParseHandler>::error(unsigned errorNumber, ...) va_end(args); } -template <typename ParseHandler> void -Parser<ParseHandler>::errorAt(uint32_t offset, unsigned errorNumber, ...) +ParserBase::errorAt(uint32_t offset, unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); @@ -599,9 +597,8 @@ Parser<ParseHandler>::errorAt(uint32_t offset, unsigned errorNumber, ...) va_end(args); } -template <typename ParseHandler> bool -Parser<ParseHandler>::warning(unsigned errorNumber, ...) +ParserBase::warning(unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); @@ -611,9 +608,8 @@ Parser<ParseHandler>::warning(unsigned errorNumber, ...) return result; } -template <typename ParseHandler> bool -Parser<ParseHandler>::warningAt(uint32_t offset, unsigned errorNumber, ...) +ParserBase::warningAt(uint32_t offset, unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); @@ -623,9 +619,8 @@ Parser<ParseHandler>::warningAt(uint32_t offset, unsigned errorNumber, ...) return result; } -template <typename ParseHandler> bool -Parser<ParseHandler>::extraWarning(unsigned errorNumber, ...) +ParserBase::extraWarning(unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); @@ -634,9 +629,8 @@ Parser<ParseHandler>::extraWarning(unsigned errorNumber, ...) return result; } -template <typename ParseHandler> bool -Parser<ParseHandler>::strictModeError(unsigned errorNumber, ...) +ParserBase::strictModeError(unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); @@ -647,9 +641,8 @@ Parser<ParseHandler>::strictModeError(unsigned errorNumber, ...) return res; } -template <typename ParseHandler> bool -Parser<ParseHandler>::strictModeErrorAt(uint32_t offset, unsigned errorNumber, ...) +ParserBase::strictModeErrorAt(uint32_t offset, unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); @@ -659,9 +652,8 @@ Parser<ParseHandler>::strictModeErrorAt(uint32_t offset, unsigned errorNumber, . return res; } -template <typename ParseHandler> bool -Parser<ParseHandler>::reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...) +ParserBase::reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); @@ -702,16 +694,14 @@ Parser<SyntaxParseHandler>::abortIfSyntaxParser() return false; } -template <typename ParseHandler> -Parser<ParseHandler>::Parser(ExclusiveContext* cx, LifoAlloc& alloc, - const ReadOnlyCompileOptions& options, - const char16_t* chars, size_t length, - bool foldConstants, - UsedNameTracker& usedNames, - Parser<SyntaxParseHandler>* syntaxParser, - LazyScript* lazyOuterFunction) - : AutoGCRooter(cx, PARSER), - context(cx), +ParserBase::ParserBase(ExclusiveContext* cx, LifoAlloc& alloc, + const ReadOnlyCompileOptions& options, + const char16_t* chars, size_t length, + bool foldConstants, + UsedNameTracker& usedNames, + Parser<SyntaxParseHandler>* syntaxParser, + LazyScript* lazyOuterFunction) + : context(cx), alloc(alloc), tokenStream(cx, options, chars, length, thisForCtor()), traceListHead(nullptr), @@ -725,18 +715,44 @@ Parser<ParseHandler>::Parser(ExclusiveContext* cx, LifoAlloc& alloc, checkOptionsCalled(false), #endif abortedSyntaxParse(false), - isUnexpectedEOF_(false), - handler(cx, alloc, tokenStream, syntaxParser, lazyOuterFunction) + isUnexpectedEOF_(false) { cx->perThreadData->frontendCollectionPool.addActiveCompilation(); + tempPoolMark = alloc.mark(); +} + +ParserBase::~ParserBase() +{ + alloc.release(tempPoolMark); + + /* + * The parser can allocate enormous amounts of memory for large functions. + * Eagerly free the memory now (which otherwise won't be freed until the + * next GC) to avoid unnecessary OOMs. + */ + alloc.freeAllIfHugeAndUnused(); + + context->perThreadData->frontendCollectionPool.removeActiveCompilation(); +} +template <typename ParseHandler> +Parser<ParseHandler>::Parser(ExclusiveContext* cx, LifoAlloc& alloc, + const ReadOnlyCompileOptions& options, + const char16_t* chars, size_t length, + bool foldConstants, + UsedNameTracker& usedNames, + Parser<SyntaxParseHandler>* syntaxParser, + LazyScript* lazyOuterFunction) + : ParserBase(cx, alloc, options, chars, length, foldConstants, usedNames, syntaxParser, + lazyOuterFunction), + AutoGCRooter(cx, PARSER), + handler(cx, alloc, tokenStream, syntaxParser, lazyOuterFunction) +{ // The Mozilla specific JSOPTION_EXTRA_WARNINGS option adds extra warnings // which are not generated if functions are parsed lazily. Note that the // standard "use strict" does not inhibit lazy parsing. if (options.extraWarningsOption) handler.disableSyntaxParser(); - - tempPoolMark = alloc.mark(); } template<typename ParseHandler> @@ -747,26 +763,13 @@ Parser<ParseHandler>::checkOptions() checkOptionsCalled = true; #endif - if (!tokenStream.checkOptions()) - return false; - - return true; + return tokenStream.checkOptions(); } template <typename ParseHandler> Parser<ParseHandler>::~Parser() { MOZ_ASSERT(checkOptionsCalled); - alloc.release(tempPoolMark); - - /* - * The parser can allocate enormous amounts of memory for large functions. - * Eagerly free the memory now (which otherwise won't be freed until the - * next GC) to avoid unnecessary OOMs. - */ - alloc.freeAllIfHugeAndUnused(); - - context->perThreadData->frontendCollectionPool.removeActiveCompilation(); } template <typename ParseHandler> @@ -897,9 +900,8 @@ Parser<ParseHandler>::parse() * Strict mode forbids introducing new definitions for 'eval', 'arguments', or * for any strict mode reserved keyword. */ -template <typename ParseHandler> bool -Parser<ParseHandler>::isValidStrictBinding(PropertyName* name) +ParserBase::isValidStrictBinding(PropertyName* name) { return name != context->names().eval && name != context->names().arguments && @@ -9602,9 +9604,8 @@ Parser<ParseHandler>::exprInParens(InHandling inHandling, YieldHandling yieldHan return expr(inHandling, yieldHandling, tripledotHandling, possibleError, PredictInvoked); } -template <typename ParseHandler> bool -Parser<ParseHandler>::warnOnceAboutExprClosure() +ParserBase::warnOnceAboutExprClosure() { #ifndef RELEASE_OR_BETA JSContext* cx = context->maybeJSContext(); @@ -9620,9 +9621,8 @@ Parser<ParseHandler>::warnOnceAboutExprClosure() return true; } -template <typename ParseHandler> bool -Parser<ParseHandler>::warnOnceAboutForEach() +ParserBase::warnOnceAboutForEach() { JSContext* cx = context->maybeJSContext(); if (!cx) diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index f6cff8a6c..e36a6e8b2 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -734,8 +734,138 @@ class UsedNameTracker } }; +class ParserBase : public StrictModeGetter +{ + private: + ParserBase* thisForCtor() { return this; } + + public: + ExclusiveContext* const context; + + LifoAlloc& alloc; + + TokenStream tokenStream; + LifoAlloc::Mark tempPoolMark; + + /* list of parsed objects for GC tracing */ + ObjectBox* traceListHead; + + /* innermost parse context (stack-allocated) */ + ParseContext* pc; + + // For tracking used names in this parsing session. + UsedNameTracker& usedNames; + + /* Compression token for aborting. */ + SourceCompressionTask* sct; + + ScriptSource* ss; + + /* Root atoms and objects allocated for the parsed tree. */ + AutoKeepAtoms keepAtoms; + + /* Perform constant-folding; must be true when interfacing with the emitter. */ + const bool foldConstants:1; + + protected: +#if DEBUG + /* Our fallible 'checkOptions' member function has been called. */ + bool checkOptionsCalled:1; +#endif + + /* + * Not all language constructs can be handled during syntax parsing. If it + * is not known whether the parse succeeds or fails, this bit is set and + * the parse will return false. + */ + bool abortedSyntaxParse:1; + + /* Unexpected end of input, i.e. TOK_EOF not at top-level. */ + bool isUnexpectedEOF_:1; + + public: + ParserBase(ExclusiveContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options, + const char16_t* chars, size_t length, bool foldConstants, + UsedNameTracker& usedNames, Parser<SyntaxParseHandler>* syntaxParser, + LazyScript* lazyOuterFunction); + ~ParserBase(); + + const char* getFilename() const { return tokenStream.getFilename(); } + JSVersion versionNumber() const { return tokenStream.versionNumber(); } + TokenPos pos() const { return tokenStream.currentToken().pos; } + + // Determine whether |yield| is a valid name in the current context, or + // whether it's prohibited due to strictness, JS version, or occurrence + // inside a star generator. + bool yieldExpressionsSupported() { + return (versionNumber() >= JSVERSION_1_7 || pc->isGenerator()) && !pc->isAsync(); + } + + virtual bool strictMode() { return pc->sc()->strict(); } + bool setLocalStrictMode(bool strict) { + MOZ_ASSERT(tokenStream.debugHasNoLookahead()); + return pc->sc()->setLocalStrictMode(strict); + } + + const ReadOnlyCompileOptions& options() const { + return tokenStream.options(); + } + + bool hadAbortedSyntaxParse() { + return abortedSyntaxParse; + } + void clearAbortedSyntaxParse() { + abortedSyntaxParse = false; + } + + bool isUnexpectedEOF() const { return isUnexpectedEOF_; } + + bool reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...); + + /* Report the given error at the current offset. */ + void error(unsigned errorNumber, ...); + + /* Report the given error at the given offset. */ + void errorAt(uint32_t offset, unsigned errorNumber, ...); + + /* + * Handle a strict mode error at the current offset. Report an error if in + * strict mode code, or warn if not, using the given error number and + * arguments. + */ + MOZ_MUST_USE bool strictModeError(unsigned errorNumber, ...); + + /* + * Handle a strict mode error at the given offset. Report an error if in + * strict mode code, or warn if not, using the given error number and + * arguments. + */ + MOZ_MUST_USE bool strictModeErrorAt(uint32_t offset, unsigned errorNumber, ...); + + /* Report the given warning at the current offset. */ + MOZ_MUST_USE bool warning(unsigned errorNumber, ...); + + /* Report the given warning at the given offset. */ + MOZ_MUST_USE bool warningAt(uint32_t offset, unsigned errorNumber, ...); + + /* + * If extra warnings are enabled, report the given warning at the current + * offset. + */ + MOZ_MUST_USE bool extraWarning(unsigned errorNumber, ...); + + bool isValidStrictBinding(PropertyName* name); + + bool warnOnceAboutExprClosure(); + bool warnOnceAboutForEach(); + + protected: + enum InvokedPrediction { PredictUninvoked = false, PredictInvoked = true }; + enum ForInitLocation { InForInit, NotInForInit }; +}; + template <typename ParseHandler> -class Parser final : private JS::AutoGCRooter, public StrictModeGetter +class Parser final : public ParserBase, private JS::AutoGCRooter { private: using Node = typename ParseHandler::Node; @@ -853,50 +983,6 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter }; public: - ExclusiveContext* const context; - - LifoAlloc& alloc; - - TokenStream tokenStream; - LifoAlloc::Mark tempPoolMark; - - /* list of parsed objects for GC tracing */ - ObjectBox* traceListHead; - - /* innermost parse context (stack-allocated) */ - ParseContext* pc; - - // For tracking used names in this parsing session. - UsedNameTracker& usedNames; - - /* Compression token for aborting. */ - SourceCompressionTask* sct; - - ScriptSource* ss; - - /* Root atoms and objects allocated for the parsed tree. */ - AutoKeepAtoms keepAtoms; - - /* Perform constant-folding; must be true when interfacing with the emitter. */ - const bool foldConstants:1; - - private: -#if DEBUG - /* Our fallible 'checkOptions' member function has been called. */ - bool checkOptionsCalled:1; -#endif - - /* - * Not all language constructs can be handled during syntax parsing. If it - * is not known whether the parse succeeds or fails, this bit is set and - * the parse will return false. - */ - bool abortedSyntaxParse:1; - - /* Unexpected end of input, i.e. TOK_EOF not at top-level. */ - bool isUnexpectedEOF_:1; - - public: /* State specific to the kind of parse being performed. */ ParseHandler handler; @@ -904,40 +990,6 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter void freeTree(Node node) { handler.freeTree(node); } public: - bool reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...); - - /* Report the given error at the current offset. */ - void error(unsigned errorNumber, ...); - - /* Report the given error at the given offset. */ - void errorAt(uint32_t offset, unsigned errorNumber, ...); - - /* - * Handle a strict mode error at the current offset. Report an error if in - * strict mode code, or warn if not, using the given error number and - * arguments. - */ - MOZ_MUST_USE bool strictModeError(unsigned errorNumber, ...); - - /* - * Handle a strict mode error at the given offset. Report an error if in - * strict mode code, or warn if not, using the given error number and - * arguments. - */ - MOZ_MUST_USE bool strictModeErrorAt(uint32_t offset, unsigned errorNumber, ...); - - /* Report the given warning at the current offset. */ - MOZ_MUST_USE bool warning(unsigned errorNumber, ...); - - /* Report the given warning at the given offset. */ - MOZ_MUST_USE bool warningAt(uint32_t offset, unsigned errorNumber, ...); - - /* - * If extra warnings are enabled, report the given warning at the current - * offset. - */ - MOZ_MUST_USE bool extraWarning(unsigned errorNumber, ...); - Parser(ExclusiveContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options, const char16_t* chars, size_t length, bool foldConstants, UsedNameTracker& usedNames, Parser<SyntaxParseHandler>* syntaxParser, LazyScript* lazyOuterFunction); @@ -967,9 +1019,6 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter friend void js::frontend::MarkParser(JSTracer* trc, JS::AutoGCRooter* parser); - const char* getFilename() const { return tokenStream.getFilename(); } - JSVersion versionNumber() const { return tokenStream.versionNumber(); } - /* * Parse a top-level JS script. */ @@ -995,15 +1044,6 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter void trace(JSTracer* trc); - bool hadAbortedSyntaxParse() { - return abortedSyntaxParse; - } - void clearAbortedSyntaxParse() { - abortedSyntaxParse = false; - } - - bool isUnexpectedEOF() const { return isUnexpectedEOF_; } - bool checkUnescapedName(); private: @@ -1072,34 +1112,12 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter Node pn, FunctionSyntaxKind kind, mozilla::Maybe<uint32_t> parameterListEnd = mozilla::Nothing(), bool isStandaloneFunction = false); - - - // Determine whether |yield| is a valid name in the current context, or - // whether it's prohibited due to strictness, JS version, or occurrence - // inside a star generator. - bool yieldExpressionsSupported() { - return (versionNumber() >= JSVERSION_1_7 || pc->isGenerator()) && !pc->isAsync(); - } // Match the current token against the BindingIdentifier production with // the given Yield parameter. If there is no match, report a syntax // error. PropertyName* bindingIdentifier(YieldHandling yieldHandling); - virtual bool strictMode() { return pc->sc()->strict(); } - bool setLocalStrictMode(bool strict) { - MOZ_ASSERT(tokenStream.debugHasNoLookahead()); - return pc->sc()->setLocalStrictMode(strict); - } - - const ReadOnlyCompileOptions& options() const { - return tokenStream.options(); - } - - private: - enum InvokedPrediction { PredictUninvoked = false, PredictInvoked = true }; - enum ForInitLocation { InForInit, NotInForInit }; - private: /* * JS parsers, from lowest to highest precedence. @@ -1375,8 +1393,6 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter bool hasValidSimpleStrictParameterNames(); - bool isValidStrictBinding(PropertyName* name); - void reportRedeclaration(HandlePropertyName name, DeclarationKind kind, TokenPos pos); bool notePositionalFormalParameter(Node fn, HandlePropertyName name, bool disallowDuplicateParams, bool* duplicatedParam); @@ -1432,12 +1448,7 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter JSAtom* prefixAccessorName(PropertyType propType, HandleAtom propAtom); - TokenPos pos() const { return tokenStream.currentToken().pos; } - bool asmJS(Node list); - - bool warnOnceAboutExprClosure(); - bool warnOnceAboutForEach(); }; } /* namespace frontend */ |