Changeset 163960 in webkit for trunk/Source/JavaScriptCore/parser


Ignore:
Timestamp:
Feb 12, 2014, 9:14:23 AM (12 years ago)
Author:
[email protected]
Message:

Make it possible to implement JS builtins in JS
https://bugs.webkit.org/show_bug.cgi?id=127887

Reviewed by Michael Saboff.

.:

  • GNUmakefile.am:
  • Source/cmake/gtest/CMakeLists.txt:

Source/JavaScriptCore:

This patch makes it possible to write builtin functions in JS.
The bindings, generators, and definitions are all created automatically
based on js files in the builtins/ directory. This patch includes one
such case: Array.prototype.js with an implementation of every().

There's a lot of refactoring to make it possible for CommonIdentifiers
to include the output of the generated files (DerivedSources/JSCBuiltins.{h,cpp})
without breaking the offset extractor. The result of this refactoring
is that CommonIdentifiers, and a few other miscellaneous headers now
need to be included directly as they were formerly captured through other
paths.

In addition this adds a flag to the Lookup table's hashentry to indicate
that a static function is actually backed by JS. There is then a lot of
logic to thread the special nature of the functon to where it matters.
This allows toString(), .caller, etc to mimic the behaviour of a host
function.

Notes on writing builtins:

  • Each function is compiled independently of the others, and those implementations cannot currently capture all global properties (as that could be potentially unsafe). If a function does capture a global we will deliberately crash.
  • For those "global" properties that we do want access to, we use the @ prefix, e.g. Object(this) becomes @Object(this). The @ identifiers are private names, and behave just like regular properties, only without the risk of adulteration. Again, in the @Object case, we explicitly duplicate the ObjectConstructor reference on the GlobalObject so that we have guaranteed access to the original version of the constructor.
  • call, apply, eval, and Function are all rejected identifiers, again to prevent anything from accidentally using an adulterated object. Instead @call and @apply are available, and happily they completely drop the neq_ptr instruction as they're defined as always being the original call/apply functions.

These restrictions are just intended to make it harder to accidentally
make changes that are incorrect (for instance calling whatever has been
assigned to global.Object, instead of the original constructor function).
However, making a mistake like this should result in a purely semantic
error as fundamentally these functions are treated as though they were
regular JS code in the host global, and have no more privileges than
any other JS.

The initial proof of concept is Array.prototype.every, this shows a 65%
performance improvement, and that improvement is significantly hurt by
our poor optimisation of op_in.

As this is such a limited function, we have not yet exported all symbols
that we could possibly need, but as we implement more, the likelihood
of encountering missing features will reduce.

  • API/JSCallbackObjectFunctions.h:

(JSC::JSCallbackObject<Parent>::getOwnPropertySlot):
(JSC::JSCallbackObject<Parent>::put):
(JSC::JSCallbackObject<Parent>::deleteProperty):
(JSC::JSCallbackObject<Parent>::getStaticValue):
(JSC::JSCallbackObject<Parent>::staticFunctionGetter):
(JSC::JSCallbackObject<Parent>::callbackGetter):

(every):

  • builtins/BuiltinExecutables.cpp: Added.

(JSC::BuiltinExecutables::BuiltinExecutables):
(JSC::BuiltinExecutables::createBuiltinExecutable):

  • builtins/BuiltinExecutables.h:

(JSC::BuiltinExecutables::create):

  • builtins/BuiltinNames.h: Added.

(JSC::BuiltinNames::BuiltinNames):
(JSC::BuiltinNames::getPrivateName):
(JSC::BuiltinNames::getPublicName):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::CodeBlock):

  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::generateFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
(JSC::UnlinkedFunctionExecutable::codeBlockFor):
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):

  • bytecode/UnlinkedCodeBlock.h:

(JSC::ExecutableInfo::ExecutableInfo):
(JSC::UnlinkedFunctionExecutable::create):
(JSC::UnlinkedFunctionExecutable::toStrictness):
(JSC::UnlinkedFunctionExecutable::isBuiltinFunction):
(JSC::UnlinkedCodeBlock::isBuiltinFunction):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator):

  • bytecompiler/BytecodeGenerator.h:

(JSC::BytecodeGenerator::isBuiltinFunction):
(JSC::BytecodeGenerator::makeFunction):

  • bytecompiler/NodesCodegen.cpp:

(JSC::CallFunctionCallDotNode::emitBytecode):
(JSC::ApplyFunctionCallDotNode::emitBytecode):

  • create_hash_table:
  • generate-js-builtins: Added.

(getCopyright):
(getFunctions):
(generateCode):
(mangleName):
(FunctionExecutable):
(Identifier):
(JSGlobalObject):
(SourceCode):
(UnlinkedFunctionExecutable):
(VM):

  • interpreter/CachedCall.h:

(JSC::CachedCall::CachedCall):

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::makeFunctionCallNode):

  • parser/Lexer.cpp:

(JSC::Lexer<T>::Lexer):
(JSC::isSafeBuiltinIdentifier):
(JSC::Lexer<LChar>::parseIdentifier):
(JSC::Lexer<UChar>::parseIdentifier):
(JSC::Lexer<T>::lex):

  • parser/Lexer.h:

(JSC::isSafeIdentifier):
(JSC::Lexer<T>::lexExpectIdentifier):

  • parser/Nodes.cpp:

(JSC::ProgramNode::setClosedVariables):

  • parser/Nodes.h:

(JSC::ScopeNode::capturedVariables):
(JSC::ScopeNode::setClosedVariables):
(JSC::ProgramNode::closedVariables):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::Parser):
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::didFinishParsing):
(JSC::Parser<LexerType>::printUnexpectedTokenText):

  • parser/Parser.h:

(JSC::Scope::getUsedVariables):
(JSC::Parser::closedVariables):
(JSC::parse):

  • parser/ParserModes.h:
  • parser/ParserTokens.h:
  • runtime/ArrayPrototype.cpp:
  • runtime/CodeCache.cpp:

(JSC::CodeCache::getFunctionExecutableFromGlobalCode):

  • runtime/CommonIdentifiers.cpp:

(JSC::CommonIdentifiers::CommonIdentifiers):
(JSC::CommonIdentifiers::~CommonIdentifiers):
(JSC::CommonIdentifiers::getPrivateName):
(JSC::CommonIdentifiers::getPublicName):

  • runtime/CommonIdentifiers.h:

(JSC::CommonIdentifiers::builtinNames):

  • runtime/ExceptionHelpers.cpp:

(JSC::createUndefinedVariableError):

  • runtime/Executable.h:

(JSC::EvalExecutable::executableInfo):
(JSC::ProgramExecutable::executableInfo):
(JSC::FunctionExecutable::isBuiltinFunction):

  • runtime/FunctionPrototype.cpp:

(JSC::functionProtoFuncToString):

  • runtime/JSActivation.cpp:

(JSC::JSActivation::symbolTableGet):
(JSC::JSActivation::symbolTablePut):
(JSC::JSActivation::symbolTablePutWithAttributes):

  • runtime/JSFunction.cpp:

(JSC::JSFunction::createBuiltinFunction):
(JSC::JSFunction::calculatedDisplayName):
(JSC::JSFunction::sourceCode):
(JSC::JSFunction::isHostOrBuiltinFunction):
(JSC::JSFunction::isBuiltinFunction):
(JSC::JSFunction::callerGetter):
(JSC::JSFunction::getOwnPropertySlot):
(JSC::JSFunction::getOwnNonIndexPropertyNames):
(JSC::JSFunction::put):
(JSC::JSFunction::defineOwnProperty):

  • runtime/JSFunction.h:
  • runtime/JSFunctionInlines.h:

(JSC::JSFunction::nativeFunction):
(JSC::JSFunction::nativeConstructor):
(JSC::isHostFunction):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::reset):
(JSC::JSGlobalObject::visitChildren):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::objectConstructor):
(JSC::JSGlobalObject::symbolTableHasProperty):

  • runtime/JSObject.cpp:

(JSC::getClassPropertyNames):
(JSC::JSObject::reifyStaticFunctionsForDelete):
(JSC::JSObject::putDirectBuiltinFunction):

  • runtime/JSObject.h:
  • runtime/JSSymbolTableObject.cpp:

(JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):

  • runtime/JSSymbolTableObject.h:

(JSC::symbolTableGet):
(JSC::symbolTablePut):
(JSC::symbolTablePutWithAttributes):

  • runtime/Lookup.cpp:

(JSC::setUpStaticFunctionSlot):

  • runtime/Lookup.h:

(JSC::HashEntry::builtinGenerator):
(JSC::HashEntry::propertyGetter):
(JSC::HashEntry::propertyPutter):
(JSC::HashTable::entry):
(JSC::getStaticPropertySlot):
(JSC::getStaticValueSlot):
(JSC::putEntry):

  • runtime/NativeErrorConstructor.cpp:

(JSC::NativeErrorConstructor::finishCreation):

  • runtime/NativeErrorConstructor.h:
  • runtime/PropertySlot.h:
  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:

(JSC::VM::builtinExecutables):

Tools:

CMake updates

  • DumpRenderTree/CMakeLists.txt:
  • WebKitTestRunner/CMakeLists.txt:
  • WinCELauncher/CMakeLists.txt:

LayoutTests:

Updated the test results for new error messages (now that they're
actually helpful), and added a js-regress test to track performance.

  • js/array-every-expected.txt:
  • js/dom/array-prototype-properties-expected.txt:
  • js/regress/array-prototype-every-expected.txt: Added.
  • js/regress/array-prototype-every.html: Added.
  • js/regress/script-tests/array-prototype-every.js: Added.

(test1):
(test2):
(test3):

Location:
trunk/Source/JavaScriptCore/parser
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/parser/ASTBuilder.h

    r163225 r163960  
    889889    DotAccessorNode* dot = static_cast<DotAccessorNode*>(func);
    890890    FunctionCallDotNode* node;
    891     if (dot->identifier() == m_vm->propertyNames->call)
     891    if (dot->identifier() == m_vm->propertyNames->call || dot->identifier() == m_vm->propertyNames->callPrivateName)
    892892        node = new (m_vm) CallFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divotStart, divotEnd);
    893     else if (dot->identifier() == m_vm->propertyNames->apply)
     893    else if (dot->identifier() == m_vm->propertyNames->apply || dot->identifier() == m_vm->propertyNames->applyPrivateName)
    894894        node = new (m_vm) ApplyFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divotStart, divotEnd);
    895895    else
  • trunk/Source/JavaScriptCore/parser/Lexer.cpp

    r163844 r163960  
    9292    // Other types (only one so far)
    9393    CharacterWhiteSpace,
     94    CharacterPrivateIdentifierStart
    9495};
    9596
     
    160161/*  62 - >                  */ CharacterGreater,
    161162/*  63 - ?                  */ CharacterQuestion,
    162 /*  64 - @                  */ CharacterInvalid,
     163/*  64 - @                  */ CharacterPrivateIdentifierStart,
    163164/*  65 - A                  */ CharacterIdentifierStart,
    164165/*  66 - B                  */ CharacterIdentifierStart,
     
    488489
    489490template <typename T>
    490 Lexer<T>::Lexer(VM* vm)
     491Lexer<T>::Lexer(VM* vm, JSParserStrictness strictness)
    491492    : m_isReparsing(false)
    492493    , m_vm(vm)
     494    , m_parsingBuiltinFunction(strictness == JSParseBuiltin)
    493495{
    494496}
     
    755757    m_buffer16.append(static_cast<UChar>(c));
    756758}
    757 
     759   
     760#if !ASSERT_DISABLED
     761bool isSafeBuiltinIdentifier(VM& vm, const Identifier* ident)
     762{
     763    if (!ident)
     764        return true;
     765    /* Just block any use of suspicious identifiers.  This is intended to
     766     * be used as a safety net while implementing builtins.
     767     */
     768    if (*ident == vm.propertyNames->call)
     769        return false;
     770    if (*ident == vm.propertyNames->apply)
     771        return false;
     772    if (*ident == vm.propertyNames->eval)
     773        return false;
     774    if (*ident == vm.propertyNames->Function)
     775        return false;
     776    return true;
     777}
     778#endif
     779   
    758780template <>
    759781template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<LChar>::parseIdentifier(JSTokenData* tokenData, unsigned lexerFlags, bool strictMode)
     
    767789        }
    768790    }
    769 
     791   
     792    bool isPrivateName = m_current == '@' && m_parsingBuiltinFunction;
     793    if (isPrivateName)
     794        shift();
     795   
    770796    const LChar* identifierStart = currentSourcePtr();
    771797    unsigned identifierLineStart = currentLineStartOffset();
     
    781807    const Identifier* ident = 0;
    782808   
    783     if (shouldCreateIdentifier) {
     809    if (shouldCreateIdentifier || m_parsingBuiltinFunction) {
    784810        int identifierLength = currentSourcePtr() - identifierStart;
    785811        ident = makeIdentifier(identifierStart, identifierLength);
    786 
     812        if (m_parsingBuiltinFunction) {
     813            if (!isSafeBuiltinIdentifier(*m_vm, ident) && !isPrivateName) {
     814                m_lexErrorMessage = makeString("The use of '", ident->string(), "' is disallowed in builtin functions.");
     815                return ERRORTOK;
     816            }
     817            if (isPrivateName)
     818                ident = m_vm->propertyNames->getPrivateName(*ident);
     819            else if (*ident == m_vm->propertyNames->undefinedKeyword)
     820                tokenData->ident = &m_vm->propertyNames->undefinedPrivateName;
     821            if (!ident)
     822                return INVALID_PRIVATE_NAME_ERRORTOK;
     823        }
    787824        tokenData->ident = ident;
    788825    } else
    789826        tokenData->ident = 0;
    790827
    791     if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords))) {
     828    if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords)) && !isPrivateName) {
    792829        ASSERT(shouldCreateIdentifier);
    793830        if (remaining < maxTokenLength) {
     
    816853        }
    817854    }
     855   
     856    bool isPrivateName = m_current == '@' && m_parsingBuiltinFunction;
     857    if (isPrivateName)
     858        shift();
    818859
    819860    const UChar* identifierStart = currentSourcePtr();
     
    828869   
    829870    if (UNLIKELY(m_current == '\\')) {
     871        ASSERT(!isPrivateName);
    830872        setOffsetFromSourcePtr(identifierStart, identifierLineStart);
    831873        return parseIdentifierSlowCase<shouldCreateIdentifier>(tokenData, lexerFlags, strictMode);
     
    839881    const Identifier* ident = 0;
    840882   
    841     if (shouldCreateIdentifier) {
     883    if (shouldCreateIdentifier || m_parsingBuiltinFunction) {
    842884        int identifierLength = currentSourcePtr() - identifierStart;
    843885        if (isAll8Bit)
     
    845887        else
    846888            ident = makeIdentifier(identifierStart, identifierLength);
    847        
     889        if (m_parsingBuiltinFunction) {
     890            if (!isSafeBuiltinIdentifier(*m_vm, ident) && !isPrivateName) {
     891                m_lexErrorMessage = makeString("The use of '", ident->string(), "' is disallowed in builtin functions.");
     892                return ERRORTOK;
     893            }
     894            if (isPrivateName)
     895                ident = m_vm->propertyNames->getPrivateName(*ident);
     896            else if (*ident == m_vm->propertyNames->undefinedKeyword)
     897                tokenData->ident = &m_vm->propertyNames->undefinedPrivateName;
     898            if (!ident)
     899                return INVALID_PRIVATE_NAME_ERRORTOK;
     900        }
    848901        tokenData->ident = ident;
    849902    } else
    850903        tokenData->ident = 0;
    851904   
    852     if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords))) {
     905    if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords)) && !isPrivateName) {
    853906        ASSERT(shouldCreateIdentifier);
    854907        if (remaining < maxTokenLength) {
     
    16601713        FALLTHROUGH;
    16611714    case CharacterBackSlash:
     1715        parseIdent:
    16621716        if (lexerFlags & LexexFlagsDontBuildKeywords)
    16631717            token = parseIdentifier<false>(tokenData, lexerFlags, strictMode);
     
    16721726        m_lineStart = m_code;
    16731727        goto start;
     1728    case CharacterPrivateIdentifierStart:
     1729        if (m_parsingBuiltinFunction)
     1730            goto parseIdent;
     1731
     1732        FALLTHROUGH;
    16741733    case CharacterInvalid:
    16751734        m_lexErrorMessage = invalidCharacterMessage();
  • trunk/Source/JavaScriptCore/parser/Lexer.h

    r163325 r163960  
    7272
    7373public:
    74     Lexer(VM*);
     74    Lexer(VM*, JSParserStrictness);
    7575    ~Lexer();
    7676
     
    238238
    239239    VM* m_vm;
     240    bool m_parsingBuiltinFunction;
    240241};
    241242
     
    335336    return &m_arena->makeIdentifierLCharFromUChar(m_vm, characters, length);
    336337}
     338
     339#if ASSERT_DISABLED
     340ALWAYS_INLINE bool isSafeBuiltinIdentifier(VM&, const Identifier*) { return true; }
     341#else
     342bool isSafeBuiltinIdentifier(VM&, const Identifier*);
     343#endif
    337344
    338345template <typename T>
     
    371378
    372379    // Create the identifier if needed
    373     if (lexerFlags & LexexFlagsDontBuildKeywords)
     380    if (lexerFlags & LexexFlagsDontBuildKeywords
     381#if !ASSERT_DISABLED
     382        && !m_parsingBuiltinFunction
     383#endif
     384        )
    374385        tokenData->ident = 0;
    375386    else
    376387        tokenData->ident = makeLCharIdentifier(start, ptr - start);
     388
    377389    tokenLocation->line = m_lineNumber;
    378390    tokenLocation->lineStartOffset = currentLineStartOffset();
     
    382394    tokenRecord->m_startPosition = startPosition;
    383395    tokenRecord->m_endPosition = currentPosition();
     396#if !ASSERT_DISABLED
     397    if (m_parsingBuiltinFunction) {
     398        if (!isSafeBuiltinIdentifier(*m_vm, tokenData->ident))
     399            return ERRORTOK;
     400    }
     401#endif
     402
    384403    m_lastToken = IDENT;
    385404    return IDENT;
  • trunk/Source/JavaScriptCore/parser/Nodes.cpp

    r163844 r163960  
    133133}
    134134
     135
     136void ProgramNode::setClosedVariables(const Vector<RefPtr<StringImpl>>&& closedVariables)
     137{
     138    m_closedVariables = std::move(closedVariables);
     139}
     140
    135141// ------------------------------ EvalNode -----------------------------
    136142
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r163321 r163960  
    14321432        bool hasCapturedVariables() const { return !!m_capturedVariables.size(); }
    14331433        size_t capturedVariableCount() const { return m_capturedVariables.size(); }
     1434        const IdentifierSet& capturedVariables() const { return m_capturedVariables; }
    14341435        bool captures(const Identifier& ident) { return m_capturedVariables.contains(ident.impl()); }
    14351436
     
    14471448
    14481449        void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination);
     1450       
     1451        void setClosedVariables(const Vector<RefPtr<StringImpl>>&&) { }
    14491452
    14501453    protected:
     
    14761479        static const bool scopeIsFunction = false;
    14771480
     1481        void setClosedVariables(const Vector<RefPtr<StringImpl>>&&);
     1482        const Vector<RefPtr<StringImpl>>& closedVariables() const { return m_closedVariables; }
    14781483    private:
    14791484        ProgramNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
    14801485
    14811486        virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
    1482 
     1487        Vector<RefPtr<StringImpl>> m_closedVariables;
    14831488        unsigned m_startColumn;
    14841489        unsigned m_endColumn;
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r163959 r163960  
    206206    , m_lastFunctionName(nullptr)
    207207    , m_sourceElements(0)
    208 {
    209     m_lexer = adoptPtr(new LexerType(vm));
     208    , m_parsingBuiltin(strictness == JSParseBuiltin)
     209{
     210    m_lexer = adoptPtr(new LexerType(vm, strictness));
    210211    m_arena = m_vm->parserArena.get();
    211212    m_lexer->setCode(source, m_arena);
     
    272273    bool modifiedParameter = false;
    273274    scope->getCapturedVariables(capturedVariables, modifiedParameter);
     275   
    274276    CodeFeatures features = context.features();
    275277    if (scope->strictMode())
     
    279281    if (modifiedParameter)
    280282        features |= ModifiedParameterFeature;
    281 
     283   
     284    Vector<RefPtr<StringImpl>> closedVariables;
     285    if (m_parsingBuiltin) {
     286        RELEASE_ASSERT(!capturedVariables.size());
     287        IdentifierSet usedVariables;
     288        scope->getUsedVariables(usedVariables);
     289        for (const auto& variable : usedVariables) {
     290            if (scope->hasDeclaredVariable(Identifier(m_vm, variable.get())))
     291                continue;
     292           
     293            if (scope->hasDeclaredParameter(Identifier(m_vm, variable.get())))
     294                continue;
     295            closedVariables.append(variable);
     296        }
     297    }
    282298    didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
    283         context.numConstants(), capturedVariables);
     299        context.numConstants(), capturedVariables, std::move(closedVariables));
    284300
    285301    return parseError;
     
    288304template <typename LexerType>
    289305void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack,
    290     ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int numConstants, IdentifierSet& capturedVars)
     306    ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int numConstants, IdentifierSet& capturedVars, const Vector<RefPtr<StringImpl>>&& closedVariables)
    291307{
    292308    m_sourceElements = sourceElements;
     
    294310    m_funcDeclarations = funcStack;
    295311    m_capturedVariables.swap(capturedVars);
     312    m_closedVariables = closedVariables;
    296313    m_features = features;
    297314    m_numConstants = numConstants;
     
    23632380        out.print("Unexpected use of reserved word '", getToken(), "'");
    23642381        return;
     2382
     2383    case INVALID_PRIVATE_NAME_ERRORTOK:
     2384        out.print("Invalid private name '", getToken(), "'");
     2385        return;
    23652386           
    23662387    case IDENT:
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r163225 r163960  
    260260    }
    261261
     262    void getUsedVariables(IdentifierSet& usedVariables)
     263    {
     264        usedVariables.swap(m_usedVariables);
     265    }
    262266
    263267    void useVariable(const Identifier* ident, bool isEval)
     
    415419
    416420    JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); }
     421    const Vector<RefPtr<StringImpl>>&& closedVariables() { return std::move(m_closedVariables); }
    417422
    418423private:
     
    541546
    542547    void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*,
    543         ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures, int, IdentifierSet&);
     548        ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures, int, IdentifierSet&, const Vector<RefPtr<StringImpl>>&&);
    544549
    545550    // Used to determine type of error to report.
     
    841846    RefPtr<SourceProviderCache> m_functionCache;
    842847    SourceElements* m_sourceElements;
     848    bool m_parsingBuiltin;
    843849    ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
    844850    ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
    845851    IdentifierSet m_capturedVariables;
     852    Vector<RefPtr<StringImpl>> m_closedVariables;
    846853    CodeFeatures m_features;
    847854    int m_numConstants;
     
    958965        if (positionBeforeLastNewline)
    959966            *positionBeforeLastNewline = parser.positionBeforeLastNewline();
     967        if (strictness == JSParseBuiltin) {
     968            if (!result)
     969                WTF::dataLog("Error compiling builtin: ", error.m_message, "\n");
     970            RELEASE_ASSERT(result);
     971            result->setClosedVariables(std::move(parser.closedVariables()));
     972        }
    960973        return result.release();
    961974    }
  • trunk/Source/JavaScriptCore/parser/ParserModes.h

    r163321 r163960  
    3232namespace JSC {
    3333
    34 enum JSParserStrictness { JSParseNormal, JSParseStrict };
     34enum JSParserStrictness { JSParseNormal, JSParseBuiltin, JSParseStrict };
    3535enum JSParserMode { JSParseProgramCode, JSParseFunctionCode };
    3636
  • trunk/Source/JavaScriptCore/parser/ParserTokens.h

    r163225 r163960  
    150150    UNTERMINATED_STRING_LITERAL_ERRORTOK = 8 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
    151151    INVALID_STRING_LITERAL_ERRORTOK = 9 | ErrorTokenFlag,
     152    INVALID_PRIVATE_NAME_ERRORTOK = 10 | ErrorTokenFlag
    152153};
    153154
Note: See TracChangeset for help on using the changeset viewer.