1 | /* |
2 | * Copyright (C) 1999-2001 Harri Porten ([email protected]) |
3 | * Copyright (C) 2001 Peter Kelly ([email protected]) |
4 | * Copyright (C) 2003-2019 Apple Inc. All rights reserved. |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Library General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2 of the License, or (at your option) any later version. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Library General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Library General Public License |
17 | * along with this library; see the file COPYING.LIB. If not, write to |
18 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
19 | * Boston, MA 02110-1301, USA. |
20 | * |
21 | */ |
22 | |
23 | #pragma once |
24 | |
25 | #include "ExecutableInfo.h" |
26 | #include "Lexer.h" |
27 | #include "ModuleScopeData.h" |
28 | #include "Nodes.h" |
29 | #include "ParseHash.h" |
30 | #include "ParserArena.h" |
31 | #include "ParserError.h" |
32 | #include "ParserFunctionInfo.h" |
33 | #include "ParserTokens.h" |
34 | #include "SourceProvider.h" |
35 | #include "SourceProviderCache.h" |
36 | #include "SourceProviderCacheItem.h" |
37 | #include "VariableEnvironment.h" |
38 | #include <wtf/Forward.h> |
39 | #include <wtf/Noncopyable.h> |
40 | #include <wtf/RefPtr.h> |
41 | |
42 | namespace JSC { |
43 | |
44 | class FunctionMetadataNode; |
45 | class FunctionParameters; |
46 | class Identifier; |
47 | class VM; |
48 | class SourceCode; |
49 | class SyntaxChecker; |
50 | struct DebuggerParseData; |
51 | |
52 | // Macros to make the more common TreeBuilder types a little less verbose |
53 | #define TreeStatement typename TreeBuilder::Statement |
54 | #define TreeExpression typename TreeBuilder::Expression |
55 | #define TreeFormalParameterList typename TreeBuilder::FormalParameterList |
56 | #define TreeSourceElements typename TreeBuilder::SourceElements |
57 | #define TreeClause typename TreeBuilder::Clause |
58 | #define TreeClauseList typename TreeBuilder::ClauseList |
59 | #define TreeArguments typename TreeBuilder::Arguments |
60 | #define TreeArgumentsList typename TreeBuilder::ArgumentsList |
61 | #define TreeFunctionBody typename TreeBuilder::FunctionBody |
62 | #define TreeClassExpression typename TreeBuilder::ClassExpression |
63 | #define TreeProperty typename TreeBuilder::Property |
64 | #define TreePropertyList typename TreeBuilder::PropertyList |
65 | #define TreeDestructuringPattern typename TreeBuilder::DestructuringPattern |
66 | |
67 | COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens); |
68 | |
69 | enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode }; |
70 | enum FunctionBodyType { ArrowFunctionBodyExpression, ArrowFunctionBodyBlock, StandardFunctionBodyBlock }; |
71 | enum class FunctionNameRequirements { None, Named, Unnamed }; |
72 | |
73 | enum class DestructuringKind { |
74 | DestructureToVariables, |
75 | DestructureToLet, |
76 | DestructureToConst, |
77 | DestructureToCatchParameters, |
78 | DestructureToParameters, |
79 | DestructureToExpressions |
80 | }; |
81 | |
82 | enum class DeclarationType { |
83 | VarDeclaration, |
84 | LetDeclaration, |
85 | ConstDeclaration |
86 | }; |
87 | |
88 | enum class DeclarationImportType { |
89 | Imported, |
90 | ImportedNamespace, |
91 | NotImported |
92 | }; |
93 | |
94 | enum DeclarationResult { |
95 | Valid = 0, |
96 | InvalidStrictMode = 1 << 0, |
97 | InvalidDuplicateDeclaration = 1 << 1 |
98 | }; |
99 | |
100 | typedef uint8_t DeclarationResultMask; |
101 | |
102 | enum class DeclarationDefaultContext { |
103 | Standard, |
104 | ExportDefault, |
105 | }; |
106 | |
107 | enum class InferName { |
108 | Allowed, |
109 | Disallowed, |
110 | }; |
111 | |
112 | template <typename T> inline bool isEvalNode() { return false; } |
113 | template <> inline bool isEvalNode<EvalNode>() { return true; } |
114 | |
115 | struct ScopeLabelInfo { |
116 | UniquedStringImpl* uid; |
117 | bool isLoop; |
118 | }; |
119 | |
120 | ALWAYS_INLINE static bool isArguments(const VM& vm, const Identifier* ident) |
121 | { |
122 | return vm.propertyNames->arguments == *ident; |
123 | } |
124 | ALWAYS_INLINE static bool isEval(const VM& vm, const Identifier* ident) |
125 | { |
126 | return vm.propertyNames->eval == *ident; |
127 | } |
128 | ALWAYS_INLINE static bool isEvalOrArgumentsIdentifier(const VM& vm, const Identifier* ident) |
129 | { |
130 | return isEval(vm, ident) || isArguments(vm, ident); |
131 | } |
132 | ALWAYS_INLINE static bool isIdentifierOrKeyword(const JSToken& token) |
133 | { |
134 | return token.m_type == IDENT || token.m_type & KeywordTokenFlag; |
135 | } |
136 | // _Any_ContextualKeyword includes keywords such as "let" or "yield", which have a specific meaning depending on the current parse mode |
137 | // or strict mode. These helpers allow to treat all contextual keywords as identifiers as required. |
138 | ALWAYS_INLINE static bool isAnyContextualKeyword(const JSToken& token) |
139 | { |
140 | return token.m_type >= FirstContextualKeywordToken && token.m_type <= LastContextualKeywordToken; |
141 | } |
142 | ALWAYS_INLINE static bool isIdentifierOrAnyContextualKeyword(const JSToken& token) |
143 | { |
144 | return token.m_type == IDENT || isAnyContextualKeyword(token); |
145 | } |
146 | // _Safe_ContextualKeyword includes only contextual keywords which can be treated as identifiers independently from parse mode. The exeption |
147 | // to this rule is `await`, but matchSpecIdentifier() always treats it as an identifier regardless. |
148 | ALWAYS_INLINE static bool isSafeContextualKeyword(const JSToken& token) |
149 | { |
150 | return token.m_type >= FirstSafeContextualKeywordToken && token.m_type <= LastSafeContextualKeywordToken; |
151 | } |
152 | |
153 | JS_EXPORT_PRIVATE extern std::atomic<unsigned> globalParseCount; |
154 | |
155 | struct Scope { |
156 | WTF_MAKE_NONCOPYABLE(Scope); |
157 | |
158 | public: |
159 | Scope(const VM& vm, bool isFunction, bool isGenerator, bool strictMode, bool isArrowFunction, bool isAsyncFunction) |
160 | : m_vm(vm) |
161 | , m_shadowsArguments(false) |
162 | , m_usesEval(false) |
163 | , m_needsFullActivation(false) |
164 | , m_hasDirectSuper(false) |
165 | , m_needsSuperBinding(false) |
166 | , m_allowsVarDeclarations(true) |
167 | , m_allowsLexicalDeclarations(true) |
168 | , m_strictMode(strictMode) |
169 | , m_isFunction(isFunction) |
170 | , m_isGenerator(isGenerator) |
171 | , m_isGeneratorBoundary(false) |
172 | , m_isArrowFunction(isArrowFunction) |
173 | , m_isArrowFunctionBoundary(false) |
174 | , m_isAsyncFunction(isAsyncFunction) |
175 | , m_isAsyncFunctionBoundary(false) |
176 | , m_isLexicalScope(false) |
177 | , m_isGlobalCodeScope(false) |
178 | , m_isSimpleCatchParameterScope(false) |
179 | , m_isFunctionBoundary(false) |
180 | , m_isValidStrictMode(true) |
181 | , m_hasArguments(false) |
182 | , m_isEvalContext(false) |
183 | , m_hasNonSimpleParameterList(false) |
184 | , m_evalContextType(EvalContextType::None) |
185 | , m_constructorKind(static_cast<unsigned>(ConstructorKind::None)) |
186 | , m_expectedSuperBinding(static_cast<unsigned>(SuperBinding::NotNeeded)) |
187 | , m_loopDepth(0) |
188 | , m_switchDepth(0) |
189 | , m_innerArrowFunctionFeatures(0) |
190 | { |
191 | m_usedVariables.append(UniquedStringImplPtrSet()); |
192 | } |
193 | |
194 | Scope(Scope&&) = default; |
195 | |
196 | void startSwitch() { m_switchDepth++; } |
197 | void endSwitch() { m_switchDepth--; } |
198 | void startLoop() { m_loopDepth++; } |
199 | void endLoop() { ASSERT(m_loopDepth); m_loopDepth--; } |
200 | bool inLoop() { return !!m_loopDepth; } |
201 | bool breakIsValid() { return m_loopDepth || m_switchDepth; } |
202 | bool continueIsValid() { return m_loopDepth; } |
203 | |
204 | void pushLabel(const Identifier* label, bool isLoop) |
205 | { |
206 | if (!m_labels) |
207 | m_labels = makeUnique<LabelStack>(); |
208 | m_labels->append(ScopeLabelInfo { label->impl(), isLoop }); |
209 | } |
210 | |
211 | void popLabel() |
212 | { |
213 | ASSERT(m_labels); |
214 | ASSERT(m_labels->size()); |
215 | m_labels->removeLast(); |
216 | } |
217 | |
218 | ScopeLabelInfo* getLabel(const Identifier* label) |
219 | { |
220 | if (!m_labels) |
221 | return 0; |
222 | for (int i = m_labels->size(); i > 0; i--) { |
223 | if (m_labels->at(i - 1).uid == label->impl()) |
224 | return &m_labels->at(i - 1); |
225 | } |
226 | return 0; |
227 | } |
228 | |
229 | void setSourceParseMode(SourceParseMode mode) |
230 | { |
231 | switch (mode) { |
232 | case SourceParseMode::AsyncGeneratorBodyMode: |
233 | setIsAsyncGeneratorFunctionBody(); |
234 | break; |
235 | case SourceParseMode::AsyncArrowFunctionBodyMode: |
236 | setIsAsyncArrowFunctionBody(); |
237 | break; |
238 | |
239 | case SourceParseMode::AsyncFunctionBodyMode: |
240 | setIsAsyncFunctionBody(); |
241 | break; |
242 | |
243 | case SourceParseMode::GeneratorBodyMode: |
244 | setIsGenerator(); |
245 | break; |
246 | |
247 | case SourceParseMode::GeneratorWrapperFunctionMode: |
248 | case SourceParseMode::GeneratorWrapperMethodMode: |
249 | setIsGeneratorFunction(); |
250 | break; |
251 | |
252 | case SourceParseMode::AsyncGeneratorWrapperMethodMode: |
253 | case SourceParseMode::AsyncGeneratorWrapperFunctionMode: |
254 | setIsAsyncGeneratorFunction(); |
255 | break; |
256 | |
257 | case SourceParseMode::NormalFunctionMode: |
258 | case SourceParseMode::GetterMode: |
259 | case SourceParseMode::SetterMode: |
260 | case SourceParseMode::MethodMode: |
261 | setIsFunction(); |
262 | break; |
263 | |
264 | case SourceParseMode::ArrowFunctionMode: |
265 | setIsArrowFunction(); |
266 | break; |
267 | |
268 | case SourceParseMode::AsyncFunctionMode: |
269 | case SourceParseMode::AsyncMethodMode: |
270 | setIsAsyncFunction(); |
271 | break; |
272 | |
273 | case SourceParseMode::AsyncArrowFunctionMode: |
274 | setIsAsyncArrowFunction(); |
275 | break; |
276 | |
277 | case SourceParseMode::ProgramMode: |
278 | case SourceParseMode::ModuleAnalyzeMode: |
279 | case SourceParseMode::ModuleEvaluateMode: |
280 | break; |
281 | } |
282 | } |
283 | |
284 | bool isFunction() const { return m_isFunction; } |
285 | bool isFunctionBoundary() const { return m_isFunctionBoundary; } |
286 | bool isGenerator() const { return m_isGenerator; } |
287 | bool isGeneratorBoundary() const { return m_isGeneratorBoundary; } |
288 | bool isAsyncFunction() const { return m_isAsyncFunction; } |
289 | bool isAsyncFunctionBoundary() const { return m_isAsyncFunctionBoundary; } |
290 | |
291 | bool hasArguments() const { return m_hasArguments; } |
292 | |
293 | void setIsGlobalCodeScope() { m_isGlobalCodeScope = true; } |
294 | bool isGlobalCodeScope() const { return m_isGlobalCodeScope; } |
295 | |
296 | void setIsSimpleCatchParameterScope() { m_isSimpleCatchParameterScope = true; } |
297 | bool isSimpleCatchParameterScope() { return m_isSimpleCatchParameterScope; } |
298 | |
299 | void setIsLexicalScope() |
300 | { |
301 | m_isLexicalScope = true; |
302 | m_allowsLexicalDeclarations = true; |
303 | } |
304 | bool isLexicalScope() { return m_isLexicalScope; } |
305 | bool usesEval() { return m_usesEval; } |
306 | |
307 | const HashSet<UniquedStringImpl*>& closedVariableCandidates() const { return m_closedVariableCandidates; } |
308 | VariableEnvironment& declaredVariables() { return m_declaredVariables; } |
309 | VariableEnvironment& lexicalVariables() { return m_lexicalVariables; } |
310 | VariableEnvironment& finalizeLexicalEnvironment() |
311 | { |
312 | if (m_usesEval || m_needsFullActivation) |
313 | m_lexicalVariables.markAllVariablesAsCaptured(); |
314 | else |
315 | computeLexicallyCapturedVariablesAndPurgeCandidates(); |
316 | |
317 | return m_lexicalVariables; |
318 | } |
319 | |
320 | void computeLexicallyCapturedVariablesAndPurgeCandidates() |
321 | { |
322 | // Because variables may be defined at any time in the range of a lexical scope, we must |
323 | // track lexical variables that might be captured. Then, when we're preparing to pop the top |
324 | // lexical scope off the stack, we should find which variables are truly captured, and which |
325 | // variable still may be captured in a parent scope. |
326 | if (m_lexicalVariables.size() && m_closedVariableCandidates.size()) { |
327 | for (UniquedStringImpl* impl : m_closedVariableCandidates) |
328 | m_lexicalVariables.markVariableAsCapturedIfDefined(impl); |
329 | } |
330 | |
331 | // We can now purge values from the captured candidates because they're captured in this scope. |
332 | { |
333 | for (const auto& entry : m_lexicalVariables) { |
334 | if (entry.value.isCaptured()) |
335 | m_closedVariableCandidates.remove(entry.key.get()); |
336 | } |
337 | } |
338 | } |
339 | |
340 | DeclarationResultMask declareCallee(const Identifier* ident) |
341 | { |
342 | auto addResult = m_declaredVariables.add(ident->impl()); |
343 | // We want to track if callee is captured, but we don't want to act like it's a 'var' |
344 | // because that would cause the BytecodeGenerator to emit bad code. |
345 | addResult.iterator->value.clearIsVar(); |
346 | |
347 | DeclarationResultMask result = DeclarationResult::Valid; |
348 | if (isEvalOrArgumentsIdentifier(m_vm, ident)) |
349 | result |= DeclarationResult::InvalidStrictMode; |
350 | return result; |
351 | } |
352 | |
353 | DeclarationResultMask declareVariable(const Identifier* ident) |
354 | { |
355 | ASSERT(m_allowsVarDeclarations); |
356 | DeclarationResultMask result = DeclarationResult::Valid; |
357 | bool isValidStrictMode = !isEvalOrArgumentsIdentifier(m_vm, ident); |
358 | m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; |
359 | auto addResult = m_declaredVariables.add(ident->impl()); |
360 | addResult.iterator->value.setIsVar(); |
361 | if (!isValidStrictMode) |
362 | result |= DeclarationResult::InvalidStrictMode; |
363 | return result; |
364 | } |
365 | |
366 | DeclarationResultMask declareFunction(const Identifier* ident, bool declareAsVar, bool isSloppyModeHoistingCandidate) |
367 | { |
368 | ASSERT(m_allowsVarDeclarations || m_allowsLexicalDeclarations); |
369 | DeclarationResultMask result = DeclarationResult::Valid; |
370 | bool isValidStrictMode = !isEvalOrArgumentsIdentifier(m_vm, ident); |
371 | if (!isValidStrictMode) |
372 | result |= DeclarationResult::InvalidStrictMode; |
373 | m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; |
374 | auto addResult = declareAsVar ? m_declaredVariables.add(ident->impl()) : m_lexicalVariables.add(ident->impl()); |
375 | if (isSloppyModeHoistingCandidate) |
376 | addResult.iterator->value.setIsSloppyModeHoistingCandidate(); |
377 | if (declareAsVar) { |
378 | addResult.iterator->value.setIsVar(); |
379 | if (m_lexicalVariables.contains(ident->impl())) |
380 | result |= DeclarationResult::InvalidDuplicateDeclaration; |
381 | } else { |
382 | addResult.iterator->value.setIsLet(); |
383 | ASSERT_WITH_MESSAGE(!m_declaredVariables.size(), "We should only declare a function as a lexically scoped variable in scopes where var declarations aren't allowed. I.e, in strict mode and not at the top-level scope of a function or program." ); |
384 | if (!addResult.isNewEntry) { |
385 | if (!isSloppyModeHoistingCandidate || !addResult.iterator->value.isFunction()) |
386 | result |= DeclarationResult::InvalidDuplicateDeclaration; |
387 | } |
388 | } |
389 | |
390 | addResult.iterator->value.setIsFunction(); |
391 | |
392 | return result; |
393 | } |
394 | |
395 | void addVariableBeingHoisted(const Identifier* ident) |
396 | { |
397 | ASSERT(!m_allowsVarDeclarations); |
398 | m_variablesBeingHoisted.add(ident->impl()); |
399 | } |
400 | |
401 | void addSloppyModeHoistableFunctionCandidate(const Identifier* ident) |
402 | { |
403 | ASSERT(m_allowsVarDeclarations); |
404 | m_sloppyModeHoistableFunctionCandidates.add(ident->impl()); |
405 | } |
406 | |
407 | void appendFunction(FunctionMetadataNode* node) |
408 | { |
409 | ASSERT(node); |
410 | m_functionDeclarations.append(node); |
411 | } |
412 | DeclarationStacks::FunctionStack&& takeFunctionDeclarations() { return WTFMove(m_functionDeclarations); } |
413 | |
414 | |
415 | DeclarationResultMask declareLexicalVariable(const Identifier* ident, bool isConstant, DeclarationImportType importType = DeclarationImportType::NotImported) |
416 | { |
417 | ASSERT(m_allowsLexicalDeclarations); |
418 | DeclarationResultMask result = DeclarationResult::Valid; |
419 | bool isValidStrictMode = !isEvalOrArgumentsIdentifier(m_vm, ident); |
420 | m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; |
421 | auto addResult = m_lexicalVariables.add(ident->impl()); |
422 | if (isConstant) |
423 | addResult.iterator->value.setIsConst(); |
424 | else |
425 | addResult.iterator->value.setIsLet(); |
426 | |
427 | if (importType == DeclarationImportType::Imported) |
428 | addResult.iterator->value.setIsImported(); |
429 | else if (importType == DeclarationImportType::ImportedNamespace) { |
430 | addResult.iterator->value.setIsImported(); |
431 | addResult.iterator->value.setIsImportedNamespace(); |
432 | } |
433 | |
434 | if (!addResult.isNewEntry || m_variablesBeingHoisted.contains(ident->impl())) |
435 | result |= DeclarationResult::InvalidDuplicateDeclaration; |
436 | if (!isValidStrictMode) |
437 | result |= DeclarationResult::InvalidStrictMode; |
438 | |
439 | return result; |
440 | } |
441 | |
442 | ALWAYS_INLINE bool hasDeclaredVariable(const Identifier& ident) |
443 | { |
444 | return hasDeclaredVariable(ident.impl()); |
445 | } |
446 | |
447 | bool hasDeclaredVariable(const RefPtr<UniquedStringImpl>& ident) |
448 | { |
449 | auto iter = m_declaredVariables.find(ident.get()); |
450 | if (iter == m_declaredVariables.end()) |
451 | return false; |
452 | VariableEnvironmentEntry entry = iter->value; |
453 | return entry.isVar(); // The callee isn't a "var". |
454 | } |
455 | |
456 | ALWAYS_INLINE bool hasLexicallyDeclaredVariable(const Identifier& ident) |
457 | { |
458 | return hasLexicallyDeclaredVariable(ident.impl()); |
459 | } |
460 | |
461 | bool hasLexicallyDeclaredVariable(const RefPtr<UniquedStringImpl>& ident) const |
462 | { |
463 | return m_lexicalVariables.contains(ident.get()); |
464 | } |
465 | |
466 | ALWAYS_INLINE bool hasDeclaredParameter(const Identifier& ident) |
467 | { |
468 | return hasDeclaredParameter(ident.impl()); |
469 | } |
470 | |
471 | bool hasDeclaredParameter(const RefPtr<UniquedStringImpl>& ident) |
472 | { |
473 | return m_declaredParameters.contains(ident.get()) || hasDeclaredVariable(ident); |
474 | } |
475 | |
476 | void preventAllVariableDeclarations() |
477 | { |
478 | m_allowsVarDeclarations = false; |
479 | m_allowsLexicalDeclarations = false; |
480 | } |
481 | void preventVarDeclarations() { m_allowsVarDeclarations = false; } |
482 | bool allowsVarDeclarations() const { return m_allowsVarDeclarations; } |
483 | bool allowsLexicalDeclarations() const { return m_allowsLexicalDeclarations; } |
484 | |
485 | DeclarationResultMask declareParameter(const Identifier* ident) |
486 | { |
487 | ASSERT(m_allowsVarDeclarations); |
488 | DeclarationResultMask result = DeclarationResult::Valid; |
489 | bool isArgumentsIdent = isArguments(m_vm, ident); |
490 | auto addResult = m_declaredVariables.add(ident->impl()); |
491 | bool isValidStrictMode = (addResult.isNewEntry || !addResult.iterator->value.isParameter()) |
492 | && m_vm.propertyNames->eval != *ident && !isArgumentsIdent; |
493 | addResult.iterator->value.clearIsVar(); |
494 | addResult.iterator->value.setIsParameter(); |
495 | m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; |
496 | m_declaredParameters.add(ident->impl()); |
497 | if (!isValidStrictMode) |
498 | result |= DeclarationResult::InvalidStrictMode; |
499 | if (isArgumentsIdent) |
500 | m_shadowsArguments = true; |
501 | if (!addResult.isNewEntry) |
502 | result |= DeclarationResult::InvalidDuplicateDeclaration; |
503 | |
504 | return result; |
505 | } |
506 | |
507 | bool usedVariablesContains(UniquedStringImpl* impl) const |
508 | { |
509 | for (const UniquedStringImplPtrSet& set : m_usedVariables) { |
510 | if (set.contains(impl)) |
511 | return true; |
512 | } |
513 | return false; |
514 | } |
515 | template <typename Func> |
516 | void forEachUsedVariable(const Func& func) |
517 | { |
518 | for (const UniquedStringImplPtrSet& set : m_usedVariables) { |
519 | for (UniquedStringImpl* impl : set) |
520 | func(impl); |
521 | } |
522 | } |
523 | void useVariable(const Identifier* ident, bool isEval) |
524 | { |
525 | useVariable(ident->impl(), isEval); |
526 | } |
527 | void useVariable(UniquedStringImpl* impl, bool isEval) |
528 | { |
529 | m_usesEval |= isEval; |
530 | m_usedVariables.last().add(impl); |
531 | } |
532 | |
533 | void pushUsedVariableSet() { m_usedVariables.append(UniquedStringImplPtrSet()); } |
534 | size_t currentUsedVariablesSize() { return m_usedVariables.size(); } |
535 | |
536 | void revertToPreviousUsedVariables(size_t size) { m_usedVariables.resize(size); } |
537 | |
538 | void setNeedsFullActivation() { m_needsFullActivation = true; } |
539 | bool needsFullActivation() const { return m_needsFullActivation; } |
540 | bool isArrowFunctionBoundary() { return m_isArrowFunctionBoundary; } |
541 | bool isArrowFunction() { return m_isArrowFunction; } |
542 | |
543 | bool hasDirectSuper() const { return m_hasDirectSuper; } |
544 | bool setHasDirectSuper() { return std::exchange(m_hasDirectSuper, true); } |
545 | |
546 | bool needsSuperBinding() const { return m_needsSuperBinding; } |
547 | bool setNeedsSuperBinding() { return std::exchange(m_needsSuperBinding, true); } |
548 | |
549 | void setEvalContextType(EvalContextType evalContextType) { m_evalContextType = evalContextType; } |
550 | EvalContextType evalContextType() { return m_evalContextType; } |
551 | |
552 | InnerArrowFunctionCodeFeatures innerArrowFunctionFeatures() { return m_innerArrowFunctionFeatures; } |
553 | |
554 | void setExpectedSuperBinding(SuperBinding superBinding) { m_expectedSuperBinding = static_cast<unsigned>(superBinding); } |
555 | SuperBinding expectedSuperBinding() const { return static_cast<SuperBinding>(m_expectedSuperBinding); } |
556 | void setConstructorKind(ConstructorKind constructorKind) { m_constructorKind = static_cast<unsigned>(constructorKind); } |
557 | ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); } |
558 | |
559 | void setInnerArrowFunctionUsesSuperCall() { m_innerArrowFunctionFeatures |= SuperCallInnerArrowFunctionFeature; } |
560 | void setInnerArrowFunctionUsesSuperProperty() { m_innerArrowFunctionFeatures |= SuperPropertyInnerArrowFunctionFeature; } |
561 | void setInnerArrowFunctionUsesEval() { m_innerArrowFunctionFeatures |= EvalInnerArrowFunctionFeature; } |
562 | void setInnerArrowFunctionUsesThis() { m_innerArrowFunctionFeatures |= ThisInnerArrowFunctionFeature; } |
563 | void setInnerArrowFunctionUsesNewTarget() { m_innerArrowFunctionFeatures |= NewTargetInnerArrowFunctionFeature; } |
564 | void setInnerArrowFunctionUsesArguments() { m_innerArrowFunctionFeatures |= ArgumentsInnerArrowFunctionFeature; } |
565 | |
566 | bool isEvalContext() const { return m_isEvalContext; } |
567 | void setIsEvalContext(bool isEvalContext) { m_isEvalContext = isEvalContext; } |
568 | |
569 | void setInnerArrowFunctionUsesEvalAndUseArgumentsIfNeeded() |
570 | { |
571 | ASSERT(m_isArrowFunction); |
572 | |
573 | if (m_usesEval) |
574 | setInnerArrowFunctionUsesEval(); |
575 | |
576 | if (usedVariablesContains(m_vm.propertyNames->arguments.impl())) |
577 | setInnerArrowFunctionUsesArguments(); |
578 | } |
579 | |
580 | void addClosedVariableCandidateUnconditionally(UniquedStringImpl* impl) |
581 | { |
582 | m_closedVariableCandidates.add(impl); |
583 | } |
584 | |
585 | void collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables) |
586 | { |
587 | if (nestedScope->m_usesEval) |
588 | m_usesEval = true; |
589 | |
590 | { |
591 | UniquedStringImplPtrSet& destinationSet = m_usedVariables.last(); |
592 | for (const UniquedStringImplPtrSet& usedVariablesSet : nestedScope->m_usedVariables) { |
593 | for (UniquedStringImpl* impl : usedVariablesSet) { |
594 | if (nestedScope->m_declaredVariables.contains(impl) || nestedScope->m_lexicalVariables.contains(impl)) |
595 | continue; |
596 | |
597 | // "arguments" reference should be resolved at function boudary. |
598 | if (nestedScope->isFunctionBoundary() && nestedScope->hasArguments() && impl == m_vm.propertyNames->arguments.impl() && !nestedScope->isArrowFunctionBoundary()) |
599 | continue; |
600 | |
601 | destinationSet.add(impl); |
602 | // We don't want a declared variable that is used in an inner scope to be thought of as captured if |
603 | // that inner scope is both a lexical scope and not a function. Only inner functions and "catch" |
604 | // statements can cause variables to be captured. |
605 | if (shouldTrackClosedVariables && (nestedScope->m_isFunctionBoundary || !nestedScope->m_isLexicalScope)) |
606 | m_closedVariableCandidates.add(impl); |
607 | } |
608 | } |
609 | } |
610 | // Propagate closed variable candidates downwards within the same function. |
611 | // Cross function captures will be realized via m_usedVariables propagation. |
612 | if (shouldTrackClosedVariables && !nestedScope->m_isFunctionBoundary && nestedScope->m_closedVariableCandidates.size()) { |
613 | auto end = nestedScope->m_closedVariableCandidates.end(); |
614 | auto begin = nestedScope->m_closedVariableCandidates.begin(); |
615 | m_closedVariableCandidates.add(begin, end); |
616 | } |
617 | } |
618 | |
619 | void mergeInnerArrowFunctionFeatures(InnerArrowFunctionCodeFeatures arrowFunctionCodeFeatures) |
620 | { |
621 | m_innerArrowFunctionFeatures = m_innerArrowFunctionFeatures | arrowFunctionCodeFeatures; |
622 | } |
623 | |
624 | void getSloppyModeHoistedFunctions(UniquedStringImplPtrSet& sloppyModeHoistedFunctions) |
625 | { |
626 | for (UniquedStringImpl* function : m_sloppyModeHoistableFunctionCandidates) { |
627 | // ES6 Annex B.3.3. The only time we can't hoist a function is if a syntax error would |
628 | // be caused by declaring a var with that function's name or if we have a parameter with |
629 | // that function's name. Note that we would only cause a syntax error if we had a let/const/class |
630 | // variable with the same name. |
631 | if (!m_lexicalVariables.contains(function)) { |
632 | auto iter = m_declaredVariables.find(function); |
633 | bool isParameter = iter != m_declaredVariables.end() && iter->value.isParameter(); |
634 | if (!isParameter) { |
635 | auto addResult = m_declaredVariables.add(function); |
636 | addResult.iterator->value.setIsVar(); |
637 | addResult.iterator->value.setIsSloppyModeHoistingCandidate(); |
638 | sloppyModeHoistedFunctions.add(function); |
639 | } |
640 | } |
641 | } |
642 | } |
643 | |
644 | void getCapturedVars(IdentifierSet& capturedVariables) |
645 | { |
646 | if (m_needsFullActivation || m_usesEval) { |
647 | for (auto& entry : m_declaredVariables) |
648 | capturedVariables.add(entry.key); |
649 | return; |
650 | } |
651 | for (UniquedStringImpl* impl : m_closedVariableCandidates) { |
652 | // We refer to m_declaredVariables here directly instead of a hasDeclaredVariable because we want to mark the callee as captured. |
653 | if (!m_declaredVariables.contains(impl)) |
654 | continue; |
655 | capturedVariables.add(impl); |
656 | } |
657 | } |
658 | void setStrictMode() { m_strictMode = true; } |
659 | bool strictMode() const { return m_strictMode; } |
660 | bool isValidStrictMode() const { return m_isValidStrictMode; } |
661 | bool shadowsArguments() const { return m_shadowsArguments; } |
662 | void setHasNonSimpleParameterList() |
663 | { |
664 | m_isValidStrictMode = false; |
665 | m_hasNonSimpleParameterList = true; |
666 | } |
667 | bool hasNonSimpleParameterList() const { return m_hasNonSimpleParameterList; } |
668 | |
669 | void copyCapturedVariablesToVector(const UniquedStringImplPtrSet& usedVariables, Vector<UniquedStringImpl*, 8>& vector) |
670 | { |
671 | for (UniquedStringImpl* impl : usedVariables) { |
672 | if (m_declaredVariables.contains(impl) || m_lexicalVariables.contains(impl)) |
673 | continue; |
674 | vector.append(impl); |
675 | } |
676 | } |
677 | |
678 | void fillParametersForSourceProviderCache(SourceProviderCacheItemCreationParameters& parameters, const UniquedStringImplPtrSet& capturesFromParameterExpressions) |
679 | { |
680 | ASSERT(m_isFunction); |
681 | parameters.usesEval = m_usesEval; |
682 | parameters.strictMode = m_strictMode; |
683 | parameters.needsFullActivation = m_needsFullActivation; |
684 | parameters.innerArrowFunctionFeatures = m_innerArrowFunctionFeatures; |
685 | parameters.needsSuperBinding = m_needsSuperBinding; |
686 | for (const UniquedStringImplPtrSet& set : m_usedVariables) |
687 | copyCapturedVariablesToVector(set, parameters.usedVariables); |
688 | |
689 | // FIXME: https://bugs.webkit.org/show_bug.cgi?id=156962 |
690 | // We add these unconditionally because we currently don't keep a separate |
691 | // declaration scope for a function's parameters and its var/let/const declarations. |
692 | // This is somewhat unfortunate and we should refactor to do this at some point |
693 | // because parameters logically form a parent scope to var/let/const variables. |
694 | // But because we don't do this, we must grab capture candidates from a parameter |
695 | // list before we parse the body of a function because the body's declarations |
696 | // might make us believe something isn't actually a capture candidate when it really |
697 | // is. |
698 | for (UniquedStringImpl* impl : capturesFromParameterExpressions) |
699 | parameters.usedVariables.append(impl); |
700 | } |
701 | |
702 | void restoreFromSourceProviderCache(const SourceProviderCacheItem* info) |
703 | { |
704 | ASSERT(m_isFunction); |
705 | m_usesEval = info->usesEval; |
706 | m_strictMode = info->strictMode; |
707 | m_innerArrowFunctionFeatures = info->innerArrowFunctionFeatures; |
708 | m_needsFullActivation = info->needsFullActivation; |
709 | m_needsSuperBinding = info->needsSuperBinding; |
710 | UniquedStringImplPtrSet& destSet = m_usedVariables.last(); |
711 | for (unsigned i = 0; i < info->usedVariablesCount; ++i) |
712 | destSet.add(info->usedVariables()[i]); |
713 | } |
714 | |
715 | class MaybeParseAsGeneratorForScope; |
716 | |
717 | private: |
718 | void setIsFunction() |
719 | { |
720 | m_isFunction = true; |
721 | m_isFunctionBoundary = true; |
722 | m_hasArguments = true; |
723 | setIsLexicalScope(); |
724 | m_isGenerator = false; |
725 | m_isGeneratorBoundary = false; |
726 | m_isArrowFunctionBoundary = false; |
727 | m_isArrowFunction = false; |
728 | m_isAsyncFunction = false; |
729 | m_isAsyncFunctionBoundary = false; |
730 | } |
731 | |
732 | void setIsGeneratorFunction() |
733 | { |
734 | setIsFunction(); |
735 | m_isGenerator = true; |
736 | } |
737 | |
738 | void setIsGenerator() |
739 | { |
740 | setIsFunction(); |
741 | m_isGenerator = true; |
742 | m_isGeneratorBoundary = true; |
743 | m_hasArguments = false; |
744 | } |
745 | |
746 | void setIsArrowFunction() |
747 | { |
748 | setIsFunction(); |
749 | m_isArrowFunctionBoundary = true; |
750 | m_isArrowFunction = true; |
751 | } |
752 | |
753 | void setIsAsyncArrowFunction() |
754 | { |
755 | setIsArrowFunction(); |
756 | m_isAsyncFunction = true; |
757 | } |
758 | |
759 | void setIsAsyncFunction() |
760 | { |
761 | setIsFunction(); |
762 | m_isAsyncFunction = true; |
763 | } |
764 | |
765 | void setIsAsyncGeneratorFunction() |
766 | { |
767 | setIsFunction(); |
768 | m_isAsyncFunction = true; |
769 | m_isGenerator = true; |
770 | } |
771 | |
772 | void setIsAsyncGeneratorFunctionBody() |
773 | { |
774 | setIsFunction(); |
775 | m_hasArguments = false; |
776 | m_isGenerator = true; |
777 | m_isGeneratorBoundary = true; |
778 | m_isAsyncFunction = true; |
779 | m_isAsyncFunctionBoundary = true; |
780 | } |
781 | |
782 | void setIsAsyncFunctionBody() |
783 | { |
784 | setIsFunction(); |
785 | m_hasArguments = false; |
786 | m_isAsyncFunction = true; |
787 | m_isAsyncFunctionBoundary = true; |
788 | } |
789 | |
790 | void setIsAsyncArrowFunctionBody() |
791 | { |
792 | setIsArrowFunction(); |
793 | m_hasArguments = false; |
794 | m_isAsyncFunction = true; |
795 | m_isAsyncFunctionBoundary = true; |
796 | } |
797 | |
798 | const VM& m_vm; |
799 | bool m_shadowsArguments; |
800 | bool m_usesEval; |
801 | bool m_needsFullActivation; |
802 | bool m_hasDirectSuper; |
803 | bool m_needsSuperBinding; |
804 | bool m_allowsVarDeclarations; |
805 | bool m_allowsLexicalDeclarations; |
806 | bool m_strictMode; |
807 | bool m_isFunction; |
808 | bool m_isGenerator; |
809 | bool m_isGeneratorBoundary; |
810 | bool m_isArrowFunction; |
811 | bool m_isArrowFunctionBoundary; |
812 | bool m_isAsyncFunction; |
813 | bool m_isAsyncFunctionBoundary; |
814 | bool m_isLexicalScope; |
815 | bool m_isGlobalCodeScope; |
816 | bool m_isSimpleCatchParameterScope; |
817 | bool m_isFunctionBoundary; |
818 | bool m_isValidStrictMode; |
819 | bool m_hasArguments; |
820 | bool m_isEvalContext; |
821 | bool m_hasNonSimpleParameterList; |
822 | EvalContextType m_evalContextType; |
823 | unsigned m_constructorKind; |
824 | unsigned m_expectedSuperBinding; |
825 | int m_loopDepth; |
826 | int m_switchDepth; |
827 | InnerArrowFunctionCodeFeatures m_innerArrowFunctionFeatures; |
828 | |
829 | typedef Vector<ScopeLabelInfo, 2> LabelStack; |
830 | std::unique_ptr<LabelStack> m_labels; |
831 | UniquedStringImplPtrSet m_declaredParameters; |
832 | VariableEnvironment m_declaredVariables; |
833 | VariableEnvironment m_lexicalVariables; |
834 | Vector<UniquedStringImplPtrSet, 6> m_usedVariables; |
835 | UniquedStringImplPtrSet m_variablesBeingHoisted; |
836 | UniquedStringImplPtrSet m_sloppyModeHoistableFunctionCandidates; |
837 | HashSet<UniquedStringImpl*> m_closedVariableCandidates; |
838 | DeclarationStacks::FunctionStack m_functionDeclarations; |
839 | }; |
840 | |
841 | typedef Vector<Scope, 10> ScopeStack; |
842 | |
843 | struct ScopeRef { |
844 | ScopeRef(ScopeStack* scopeStack, unsigned index) |
845 | : m_scopeStack(scopeStack) |
846 | , m_index(index) |
847 | { |
848 | } |
849 | Scope* operator->() { return &m_scopeStack->at(m_index); } |
850 | unsigned index() const { return m_index; } |
851 | |
852 | bool hasContainingScope() |
853 | { |
854 | return m_index && !m_scopeStack->at(m_index).isFunctionBoundary(); |
855 | } |
856 | |
857 | ScopeRef containingScope() |
858 | { |
859 | ASSERT(hasContainingScope()); |
860 | return ScopeRef(m_scopeStack, m_index - 1); |
861 | } |
862 | |
863 | bool operator==(const ScopeRef& other) |
864 | { |
865 | ASSERT(other.m_scopeStack == m_scopeStack); |
866 | return m_index == other.m_index; |
867 | } |
868 | |
869 | bool operator!=(const ScopeRef& other) |
870 | { |
871 | return !(*this == other); |
872 | } |
873 | |
874 | private: |
875 | ScopeStack* m_scopeStack; |
876 | unsigned m_index; |
877 | }; |
878 | |
879 | enum class ArgumentType { Normal, Spread }; |
880 | enum class ParsingContext { Program, FunctionConstructor, Eval }; |
881 | |
882 | template <typename LexerType> |
883 | class Parser { |
884 | WTF_MAKE_NONCOPYABLE(Parser); |
885 | WTF_MAKE_FAST_ALLOCATED; |
886 | |
887 | public: |
888 | Parser(VM&, const SourceCode&, JSParserBuiltinMode, JSParserStrictMode, JSParserScriptMode, SourceParseMode, SuperBinding, ConstructorKind defaultConstructorKindForTopLevelFunction = ConstructorKind::None, DerivedContextType = DerivedContextType::None, bool isEvalContext = false, EvalContextType = EvalContextType::None, DebuggerParseData* = nullptr); |
889 | ~Parser(); |
890 | |
891 | template <class ParsedNode> |
892 | std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, SourceParseMode, ParsingContext, Optional<int> functionConstructorParametersEndPosition = WTF::nullopt); |
893 | |
894 | JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); } |
895 | JSTokenLocation locationBeforeLastToken() const { return m_lexer->lastTokenLocation(); } |
896 | |
897 | struct CallOrApplyDepthScope { |
898 | CallOrApplyDepthScope(Parser* parser) |
899 | : m_parser(parser) |
900 | , m_parent(parser->m_callOrApplyDepthScope) |
901 | , m_depth(m_parent ? m_parent->m_depth + 1 : 0) |
902 | , m_depthOfInnermostChild(m_depth) |
903 | { |
904 | parser->m_callOrApplyDepthScope = this; |
905 | } |
906 | |
907 | size_t distanceToInnermostChild() const |
908 | { |
909 | ASSERT(m_depthOfInnermostChild >= m_depth); |
910 | return m_depthOfInnermostChild - m_depth; |
911 | } |
912 | |
913 | ~CallOrApplyDepthScope() |
914 | { |
915 | if (m_parent) |
916 | m_parent->m_depthOfInnermostChild = std::max(m_depthOfInnermostChild, m_parent->m_depthOfInnermostChild); |
917 | m_parser->m_callOrApplyDepthScope = m_parent; |
918 | } |
919 | |
920 | private: |
921 | |
922 | Parser* m_parser; |
923 | CallOrApplyDepthScope* m_parent; |
924 | size_t m_depth; |
925 | size_t m_depthOfInnermostChild; |
926 | }; |
927 | |
928 | private: |
929 | struct AllowInOverride { |
930 | AllowInOverride(Parser* parser) |
931 | : m_parser(parser) |
932 | , m_oldAllowsIn(parser->m_allowsIn) |
933 | { |
934 | parser->m_allowsIn = true; |
935 | } |
936 | ~AllowInOverride() |
937 | { |
938 | m_parser->m_allowsIn = m_oldAllowsIn; |
939 | } |
940 | Parser* m_parser; |
941 | bool m_oldAllowsIn; |
942 | }; |
943 | |
944 | struct AutoPopScopeRef : public ScopeRef { |
945 | AutoPopScopeRef(Parser* parser, ScopeRef scope) |
946 | : ScopeRef(scope) |
947 | , m_parser(parser) |
948 | { |
949 | } |
950 | |
951 | ~AutoPopScopeRef() |
952 | { |
953 | if (m_parser) |
954 | m_parser->popScope(*this, false); |
955 | } |
956 | |
957 | void setPopped() |
958 | { |
959 | m_parser = 0; |
960 | } |
961 | |
962 | private: |
963 | Parser* m_parser; |
964 | }; |
965 | |
966 | struct AutoCleanupLexicalScope { |
967 | // We can allocate this object on the stack without actually knowing beforehand if we're |
968 | // going to create a new lexical scope. If we decide to create a new lexical scope, we |
969 | // can pass the scope into this obejct and it will take care of the cleanup for us if the parse fails. |
970 | // This is helpful if we may fail from syntax errors after creating a lexical scope conditionally. |
971 | AutoCleanupLexicalScope() |
972 | : m_scope(nullptr, UINT_MAX) |
973 | , m_parser(nullptr) |
974 | { |
975 | } |
976 | |
977 | ~AutoCleanupLexicalScope() |
978 | { |
979 | // This should only ever be called if we fail from a syntax error. Otherwise |
980 | // it's the intention that a user of this class pops this scope manually on a |
981 | // successful parse. |
982 | if (isValid()) |
983 | m_parser->popScope(*this, false); |
984 | } |
985 | |
986 | void setIsValid(ScopeRef& scope, Parser* parser) |
987 | { |
988 | RELEASE_ASSERT(scope->isLexicalScope()); |
989 | m_scope = scope; |
990 | m_parser = parser; |
991 | } |
992 | |
993 | bool isValid() const { return !!m_parser; } |
994 | |
995 | void setPopped() |
996 | { |
997 | m_parser = nullptr; |
998 | } |
999 | |
1000 | ScopeRef& scope() { return m_scope; } |
1001 | |
1002 | private: |
1003 | ScopeRef m_scope; |
1004 | Parser* m_parser; |
1005 | }; |
1006 | |
1007 | enum ExpressionErrorClass { |
1008 | ErrorIndicatesNothing = 0, |
1009 | ErrorIndicatesPattern, |
1010 | ErrorIndicatesAsyncArrowFunction |
1011 | }; |
1012 | |
1013 | struct ExpressionErrorClassifier { |
1014 | ExpressionErrorClassifier(Parser* parser) |
1015 | : m_class(ErrorIndicatesNothing) |
1016 | , m_previous(parser->m_expressionErrorClassifier) |
1017 | , m_parser(parser) |
1018 | { |
1019 | m_parser->m_expressionErrorClassifier = this; |
1020 | } |
1021 | |
1022 | ~ExpressionErrorClassifier() |
1023 | { |
1024 | m_parser->m_expressionErrorClassifier = m_previous; |
1025 | } |
1026 | |
1027 | void classifyExpressionError(ExpressionErrorClass classification) |
1028 | { |
1029 | if (m_class != ErrorIndicatesNothing) |
1030 | return; |
1031 | m_class = classification; |
1032 | } |
1033 | |
1034 | void forceClassifyExpressionError(ExpressionErrorClass classification) |
1035 | { |
1036 | m_class = classification; |
1037 | } |
1038 | |
1039 | void reclassifyExpressionError(ExpressionErrorClass oldClassification, ExpressionErrorClass classification) |
1040 | { |
1041 | if (m_class != oldClassification) |
1042 | return; |
1043 | m_class = classification; |
1044 | } |
1045 | |
1046 | void propagateExpressionErrorClass() |
1047 | { |
1048 | if (m_previous) |
1049 | m_previous->m_class = m_class; |
1050 | } |
1051 | |
1052 | bool indicatesPossiblePattern() const { return m_class == ErrorIndicatesPattern; } |
1053 | bool indicatesPossibleAsyncArrowFunction() const { return m_class == ErrorIndicatesAsyncArrowFunction; } |
1054 | |
1055 | private: |
1056 | ExpressionErrorClass m_class; |
1057 | ExpressionErrorClassifier* m_previous; |
1058 | Parser* m_parser; |
1059 | }; |
1060 | |
1061 | ALWAYS_INLINE void classifyExpressionError(ExpressionErrorClass classification) |
1062 | { |
1063 | if (m_expressionErrorClassifier) |
1064 | m_expressionErrorClassifier->classifyExpressionError(classification); |
1065 | } |
1066 | |
1067 | ALWAYS_INLINE void forceClassifyExpressionError(ExpressionErrorClass classification) |
1068 | { |
1069 | if (m_expressionErrorClassifier) |
1070 | m_expressionErrorClassifier->forceClassifyExpressionError(classification); |
1071 | } |
1072 | |
1073 | ALWAYS_INLINE void reclassifyExpressionError(ExpressionErrorClass oldClassification, ExpressionErrorClass classification) |
1074 | { |
1075 | if (m_expressionErrorClassifier) |
1076 | m_expressionErrorClassifier->reclassifyExpressionError(oldClassification, classification); |
1077 | } |
1078 | |
1079 | ALWAYS_INLINE DestructuringKind destructuringKindFromDeclarationType(DeclarationType type) |
1080 | { |
1081 | switch (type) { |
1082 | case DeclarationType::VarDeclaration: |
1083 | return DestructuringKind::DestructureToVariables; |
1084 | case DeclarationType::LetDeclaration: |
1085 | return DestructuringKind::DestructureToLet; |
1086 | case DeclarationType::ConstDeclaration: |
1087 | return DestructuringKind::DestructureToConst; |
1088 | } |
1089 | |
1090 | RELEASE_ASSERT_NOT_REACHED(); |
1091 | return DestructuringKind::DestructureToVariables; |
1092 | } |
1093 | |
1094 | ALWAYS_INLINE const char* declarationTypeToVariableKind(DeclarationType type) |
1095 | { |
1096 | switch (type) { |
1097 | case DeclarationType::VarDeclaration: |
1098 | return "variable name" ; |
1099 | case DeclarationType::LetDeclaration: |
1100 | case DeclarationType::ConstDeclaration: |
1101 | return "lexical variable name" ; |
1102 | } |
1103 | RELEASE_ASSERT_NOT_REACHED(); |
1104 | return "invalid" ; |
1105 | } |
1106 | |
1107 | ALWAYS_INLINE AssignmentContext assignmentContextFromDeclarationType(DeclarationType type) |
1108 | { |
1109 | switch (type) { |
1110 | case DeclarationType::ConstDeclaration: |
1111 | return AssignmentContext::ConstDeclarationStatement; |
1112 | default: |
1113 | return AssignmentContext::DeclarationStatement; |
1114 | } |
1115 | } |
1116 | |
1117 | ALWAYS_INLINE bool isEvalOrArguments(const Identifier* ident) { return isEvalOrArgumentsIdentifier(m_vm, ident); } |
1118 | |
1119 | ScopeRef upperScope(int n) |
1120 | { |
1121 | ASSERT(m_scopeStack.size() >= size_t(1 + n)); |
1122 | return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1 - n); |
1123 | } |
1124 | |
1125 | ScopeRef currentScope() |
1126 | { |
1127 | return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1); |
1128 | } |
1129 | |
1130 | ScopeRef currentVariableScope() |
1131 | { |
1132 | unsigned i = m_scopeStack.size() - 1; |
1133 | ASSERT(i < m_scopeStack.size()); |
1134 | while (!m_scopeStack[i].allowsVarDeclarations()) { |
1135 | i--; |
1136 | ASSERT(i < m_scopeStack.size()); |
1137 | } |
1138 | return ScopeRef(&m_scopeStack, i); |
1139 | } |
1140 | |
1141 | ScopeRef currentLexicalDeclarationScope() |
1142 | { |
1143 | unsigned i = m_scopeStack.size() - 1; |
1144 | ASSERT(i < m_scopeStack.size()); |
1145 | while (!m_scopeStack[i].allowsLexicalDeclarations()) { |
1146 | i--; |
1147 | ASSERT(i < m_scopeStack.size()); |
1148 | } |
1149 | |
1150 | return ScopeRef(&m_scopeStack, i); |
1151 | } |
1152 | |
1153 | ScopeRef currentFunctionScope() |
1154 | { |
1155 | unsigned i = m_scopeStack.size() - 1; |
1156 | ASSERT(i < m_scopeStack.size()); |
1157 | while (i && !m_scopeStack[i].isFunctionBoundary()) { |
1158 | i--; |
1159 | ASSERT(i < m_scopeStack.size()); |
1160 | } |
1161 | // When reaching the top level scope (it can be non function scope), we return it. |
1162 | return ScopeRef(&m_scopeStack, i); |
1163 | } |
1164 | |
1165 | ScopeRef closestParentOrdinaryFunctionNonLexicalScope() |
1166 | { |
1167 | unsigned i = m_scopeStack.size() - 1; |
1168 | ASSERT(i < m_scopeStack.size() && m_scopeStack.size()); |
1169 | while (i && (!m_scopeStack[i].isFunctionBoundary() || m_scopeStack[i].isGeneratorBoundary() || m_scopeStack[i].isAsyncFunctionBoundary() || m_scopeStack[i].isArrowFunctionBoundary())) |
1170 | i--; |
1171 | // When reaching the top level scope (it can be non ordinary function scope), we return it. |
1172 | return ScopeRef(&m_scopeStack, i); |
1173 | } |
1174 | |
1175 | ScopeRef pushScope() |
1176 | { |
1177 | bool isFunction = false; |
1178 | bool isStrict = false; |
1179 | bool isGenerator = false; |
1180 | bool isArrowFunction = false; |
1181 | bool isAsyncFunction = false; |
1182 | if (!m_scopeStack.isEmpty()) { |
1183 | isStrict = m_scopeStack.last().strictMode(); |
1184 | isFunction = m_scopeStack.last().isFunction(); |
1185 | isGenerator = m_scopeStack.last().isGenerator(); |
1186 | isArrowFunction = m_scopeStack.last().isArrowFunction(); |
1187 | isAsyncFunction = m_scopeStack.last().isAsyncFunction(); |
1188 | } |
1189 | m_scopeStack.constructAndAppend(m_vm, isFunction, isGenerator, isStrict, isArrowFunction, isAsyncFunction); |
1190 | return currentScope(); |
1191 | } |
1192 | |
1193 | void popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables) |
1194 | { |
1195 | EXCEPTION_ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1); |
1196 | ASSERT(m_scopeStack.size() > 1); |
1197 | m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables); |
1198 | |
1199 | if (m_scopeStack.last().isArrowFunction()) |
1200 | m_scopeStack.last().setInnerArrowFunctionUsesEvalAndUseArgumentsIfNeeded(); |
1201 | |
1202 | if (!(m_scopeStack.last().isFunctionBoundary() && !m_scopeStack.last().isArrowFunctionBoundary())) |
1203 | m_scopeStack[m_scopeStack.size() - 2].mergeInnerArrowFunctionFeatures(m_scopeStack.last().innerArrowFunctionFeatures()); |
1204 | |
1205 | if (!m_scopeStack.last().isFunctionBoundary() && m_scopeStack.last().needsFullActivation()) |
1206 | m_scopeStack[m_scopeStack.size() - 2].setNeedsFullActivation(); |
1207 | m_scopeStack.removeLast(); |
1208 | } |
1209 | |
1210 | ALWAYS_INLINE void popScope(ScopeRef& scope, bool shouldTrackClosedVariables) |
1211 | { |
1212 | popScopeInternal(scope, shouldTrackClosedVariables); |
1213 | } |
1214 | |
1215 | ALWAYS_INLINE void popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables) |
1216 | { |
1217 | scope.setPopped(); |
1218 | popScopeInternal(scope, shouldTrackClosedVariables); |
1219 | } |
1220 | |
1221 | ALWAYS_INLINE void popScope(AutoCleanupLexicalScope& cleanupScope, bool shouldTrackClosedVariables) |
1222 | { |
1223 | RELEASE_ASSERT(cleanupScope.isValid()); |
1224 | ScopeRef& scope = cleanupScope.scope(); |
1225 | cleanupScope.setPopped(); |
1226 | popScopeInternal(scope, shouldTrackClosedVariables); |
1227 | } |
1228 | |
1229 | NEVER_INLINE DeclarationResultMask declareHoistedVariable(const Identifier* ident) |
1230 | { |
1231 | unsigned i = m_scopeStack.size() - 1; |
1232 | ASSERT(i < m_scopeStack.size()); |
1233 | while (true) { |
1234 | // Annex B.3.5 exempts `try {} catch (e) { var e; }` from being a syntax error. |
1235 | if (m_scopeStack[i].hasLexicallyDeclaredVariable(*ident) && !m_scopeStack[i].isSimpleCatchParameterScope()) |
1236 | return DeclarationResult::InvalidDuplicateDeclaration; |
1237 | |
1238 | if (m_scopeStack[i].allowsVarDeclarations()) |
1239 | return m_scopeStack[i].declareVariable(ident); |
1240 | |
1241 | m_scopeStack[i].addVariableBeingHoisted(ident); |
1242 | |
1243 | i--; |
1244 | ASSERT(i < m_scopeStack.size()); |
1245 | } |
1246 | } |
1247 | |
1248 | DeclarationResultMask declareVariable(const Identifier* ident, DeclarationType type = DeclarationType::VarDeclaration, DeclarationImportType importType = DeclarationImportType::NotImported) |
1249 | { |
1250 | if (type == DeclarationType::VarDeclaration) |
1251 | return declareHoistedVariable(ident); |
1252 | |
1253 | ASSERT(type == DeclarationType::LetDeclaration || type == DeclarationType::ConstDeclaration); |
1254 | // Lexical variables declared at a top level scope that shadow arguments or vars are not allowed. |
1255 | if (!m_lexer->isReparsingFunction() && m_statementDepth == 1 && (hasDeclaredParameter(*ident) || hasDeclaredVariable(*ident))) |
1256 | return DeclarationResult::InvalidDuplicateDeclaration; |
1257 | |
1258 | return currentLexicalDeclarationScope()->declareLexicalVariable(ident, type == DeclarationType::ConstDeclaration, importType); |
1259 | } |
1260 | |
1261 | std::pair<DeclarationResultMask, ScopeRef> declareFunction(const Identifier* ident) |
1262 | { |
1263 | if ((m_statementDepth == 1) || (!strictMode() && !currentScope()->isFunction() && !closestParentOrdinaryFunctionNonLexicalScope()->isEvalContext())) { |
1264 | // Functions declared at the top-most scope (both in sloppy and strict mode) are declared as vars |
1265 | // for backwards compatibility. This allows us to declare functions with the same name more than once. |
1266 | // In sloppy mode, we always declare functions as vars. |
1267 | bool declareAsVar = true; |
1268 | bool isSloppyModeHoistingCandidate = false; |
1269 | ScopeRef variableScope = currentVariableScope(); |
1270 | return std::make_pair(variableScope->declareFunction(ident, declareAsVar, isSloppyModeHoistingCandidate), variableScope); |
1271 | } |
1272 | |
1273 | if (!strictMode()) { |
1274 | ASSERT(currentScope()->isFunction() || closestParentOrdinaryFunctionNonLexicalScope()->isEvalContext()); |
1275 | |
1276 | // Functions declared inside a function inside a nested block scope in sloppy mode are subject to this |
1277 | // crazy rule defined inside Annex B.3.3 in the ES6 spec. It basically states that we will create |
1278 | // the function as a local block scoped variable, but when we evaluate the block that the function is |
1279 | // contained in, we will assign the function to a "var" variable only if declaring such a "var" wouldn't |
1280 | // be a syntax error and if there isn't a parameter with the same name. (It would only be a syntax error if |
1281 | // there are is a let/class/const with the same name). Note that this mean we only do the "var" hoisting |
1282 | // binding if the block evaluates. For example, this means we wont won't perform the binding if it's inside |
1283 | // the untaken branch of an if statement. |
1284 | bool declareAsVar = false; |
1285 | bool isSloppyModeHoistingCandidate = true; |
1286 | ScopeRef lexicalVariableScope = currentLexicalDeclarationScope(); |
1287 | ScopeRef varScope = currentVariableScope(); |
1288 | varScope->addSloppyModeHoistableFunctionCandidate(ident); |
1289 | ASSERT(varScope != lexicalVariableScope); |
1290 | return std::make_pair(lexicalVariableScope->declareFunction(ident, declareAsVar, isSloppyModeHoistingCandidate), lexicalVariableScope); |
1291 | } |
1292 | |
1293 | bool declareAsVar = false; |
1294 | bool isSloppyModeHoistingCandidate = false; |
1295 | ScopeRef lexicalVariableScope = currentLexicalDeclarationScope(); |
1296 | return std::make_pair(lexicalVariableScope->declareFunction(ident, declareAsVar, isSloppyModeHoistingCandidate), lexicalVariableScope); |
1297 | } |
1298 | |
1299 | NEVER_INLINE bool hasDeclaredVariable(const Identifier& ident) |
1300 | { |
1301 | unsigned i = m_scopeStack.size() - 1; |
1302 | ASSERT(i < m_scopeStack.size()); |
1303 | while (!m_scopeStack[i].allowsVarDeclarations()) { |
1304 | i--; |
1305 | ASSERT(i < m_scopeStack.size()); |
1306 | } |
1307 | return m_scopeStack[i].hasDeclaredVariable(ident); |
1308 | } |
1309 | |
1310 | NEVER_INLINE bool hasDeclaredParameter(const Identifier& ident) |
1311 | { |
1312 | // FIXME: hasDeclaredParameter() is not valid during reparsing of generator or async function bodies, because their formal |
1313 | // parameters are declared in a scope unavailable during reparsing. Note that it is redundant to call this function during |
1314 | // reparsing anyways, as the function is already guaranteed to be valid by the original parsing. |
1315 | // https://bugs.webkit.org/show_bug.cgi?id=164087 |
1316 | ASSERT(!m_lexer->isReparsingFunction()); |
1317 | |
1318 | unsigned i = m_scopeStack.size() - 1; |
1319 | ASSERT(i < m_scopeStack.size()); |
1320 | while (!m_scopeStack[i].allowsVarDeclarations()) { |
1321 | i--; |
1322 | ASSERT(i < m_scopeStack.size()); |
1323 | } |
1324 | |
1325 | if (m_scopeStack[i].isGeneratorBoundary() || m_scopeStack[i].isAsyncFunctionBoundary()) { |
1326 | // The formal parameters which need to be verified for Generators and Async Function bodies occur |
1327 | // in the outer wrapper function, so pick the outer scope here. |
1328 | i--; |
1329 | ASSERT(i < m_scopeStack.size()); |
1330 | } |
1331 | return m_scopeStack[i].hasDeclaredParameter(ident); |
1332 | } |
1333 | |
1334 | bool exportName(const Identifier& ident) |
1335 | { |
1336 | ASSERT(currentScope().index() == 0); |
1337 | ASSERT(m_moduleScopeData); |
1338 | return m_moduleScopeData->exportName(ident); |
1339 | } |
1340 | |
1341 | ScopeStack m_scopeStack; |
1342 | |
1343 | const SourceProviderCacheItem* findCachedFunctionInfo(int openBracePos) |
1344 | { |
1345 | return m_functionCache ? m_functionCache->get(openBracePos) : 0; |
1346 | } |
1347 | |
1348 | Parser(); |
1349 | |
1350 | String parseInner(const Identifier&, SourceParseMode, ParsingContext, Optional<int> functionConstructorParametersEndPosition = WTF::nullopt); |
1351 | |
1352 | void didFinishParsing(SourceElements*, DeclarationStacks::FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, CodeFeatures, int); |
1353 | |
1354 | // Used to determine type of error to report. |
1355 | bool isFunctionMetadataNode(ScopeNode*) { return false; } |
1356 | bool isFunctionMetadataNode(FunctionMetadataNode*) { return true; } |
1357 | |
1358 | ALWAYS_INLINE void next(OptionSet<LexerFlags> lexerFlags = { }) |
1359 | { |
1360 | int lastLine = m_token.m_location.line; |
1361 | int lastTokenEnd = m_token.m_location.endOffset; |
1362 | int lastTokenLineStart = m_token.m_location.lineStartOffset; |
1363 | m_lastTokenEndPosition = JSTextPosition(lastLine, lastTokenEnd, lastTokenLineStart); |
1364 | m_lexer->setLastLineNumber(lastLine); |
1365 | m_token.m_type = m_lexer->lex(&m_token, lexerFlags, strictMode()); |
1366 | } |
1367 | |
1368 | ALWAYS_INLINE void nextWithoutClearingLineTerminator(OptionSet<LexerFlags> lexerFlags = { }) |
1369 | { |
1370 | int lastLine = m_token.m_location.line; |
1371 | int lastTokenEnd = m_token.m_location.endOffset; |
1372 | int lastTokenLineStart = m_token.m_location.lineStartOffset; |
1373 | m_lastTokenEndPosition = JSTextPosition(lastLine, lastTokenEnd, lastTokenLineStart); |
1374 | m_lexer->setLastLineNumber(lastLine); |
1375 | m_token.m_type = m_lexer->lexWithoutClearingLineTerminator(&m_token, lexerFlags, strictMode()); |
1376 | } |
1377 | |
1378 | ALWAYS_INLINE void nextExpectIdentifier(OptionSet<LexerFlags> lexerFlags = { }) |
1379 | { |
1380 | int lastLine = m_token.m_location.line; |
1381 | int lastTokenEnd = m_token.m_location.endOffset; |
1382 | int lastTokenLineStart = m_token.m_location.lineStartOffset; |
1383 | m_lastTokenEndPosition = JSTextPosition(lastLine, lastTokenEnd, lastTokenLineStart); |
1384 | m_lexer->setLastLineNumber(lastLine); |
1385 | m_token.m_type = m_lexer->lexExpectIdentifier(&m_token, lexerFlags, strictMode()); |
1386 | } |
1387 | |
1388 | ALWAYS_INLINE void lexCurrentTokenAgainUnderCurrentContext() |
1389 | { |
1390 | auto savePoint = createSavePoint(); |
1391 | restoreSavePoint(savePoint); |
1392 | } |
1393 | |
1394 | ALWAYS_INLINE bool nextTokenIsColon() |
1395 | { |
1396 | return m_lexer->nextTokenIsColon(); |
1397 | } |
1398 | |
1399 | ALWAYS_INLINE bool consume(JSTokenType expected, OptionSet<LexerFlags> flags = { }) |
1400 | { |
1401 | bool result = m_token.m_type == expected; |
1402 | if (result) |
1403 | next(flags); |
1404 | return result; |
1405 | } |
1406 | |
1407 | void printUnexpectedTokenText(WTF::PrintStream&); |
1408 | ALWAYS_INLINE StringView getToken() |
1409 | { |
1410 | return m_lexer->getToken(m_token); |
1411 | } |
1412 | |
1413 | ALWAYS_INLINE StringView getToken(const JSToken& token) |
1414 | { |
1415 | return m_lexer->getToken(token); |
1416 | } |
1417 | |
1418 | ALWAYS_INLINE bool match(JSTokenType expected) |
1419 | { |
1420 | return m_token.m_type == expected; |
1421 | } |
1422 | |
1423 | ALWAYS_INLINE bool matchContextualKeyword(const Identifier& identifier) |
1424 | { |
1425 | return m_token.m_type == IDENT && *m_token.m_data.ident == identifier && !m_token.m_data.escaped; |
1426 | } |
1427 | |
1428 | ALWAYS_INLINE bool matchIdentifierOrKeyword() |
1429 | { |
1430 | return isIdentifierOrKeyword(m_token); |
1431 | } |
1432 | |
1433 | ALWAYS_INLINE unsigned tokenStart() |
1434 | { |
1435 | return m_token.m_location.startOffset; |
1436 | } |
1437 | |
1438 | ALWAYS_INLINE const JSTextPosition& tokenStartPosition() |
1439 | { |
1440 | return m_token.m_startPosition; |
1441 | } |
1442 | |
1443 | ALWAYS_INLINE int tokenLine() |
1444 | { |
1445 | return m_token.m_location.line; |
1446 | } |
1447 | |
1448 | ALWAYS_INLINE int tokenColumn() |
1449 | { |
1450 | return tokenStart() - tokenLineStart(); |
1451 | } |
1452 | |
1453 | ALWAYS_INLINE const JSTextPosition& tokenEndPosition() |
1454 | { |
1455 | return m_token.m_endPosition; |
1456 | } |
1457 | |
1458 | ALWAYS_INLINE unsigned tokenLineStart() |
1459 | { |
1460 | return m_token.m_location.lineStartOffset; |
1461 | } |
1462 | |
1463 | ALWAYS_INLINE const JSTokenLocation& tokenLocation() |
1464 | { |
1465 | return m_token.m_location; |
1466 | } |
1467 | |
1468 | void setErrorMessage(const String& message) |
1469 | { |
1470 | ASSERT_WITH_MESSAGE(!message.isEmpty(), "Attempted to set the empty string as an error message. Likely caused by invalid UTF8 used when creating the message." ); |
1471 | m_errorMessage = message; |
1472 | if (m_errorMessage.isEmpty()) |
1473 | m_errorMessage = "Unparseable script"_s ; |
1474 | } |
1475 | |
1476 | NEVER_INLINE void logError(bool); |
1477 | template <typename... Args> |
1478 | NEVER_INLINE void logError(bool, Args&&...); |
1479 | |
1480 | NEVER_INLINE void updateErrorWithNameAndMessage(const char* beforeMessage, const String& name, const char* afterMessage) |
1481 | { |
1482 | m_errorMessage = makeString(beforeMessage, " '" , name, "' " , afterMessage); |
1483 | } |
1484 | |
1485 | NEVER_INLINE void updateErrorMessage(const char* msg) |
1486 | { |
1487 | ASSERT(msg); |
1488 | m_errorMessage = String(msg); |
1489 | ASSERT(!m_errorMessage.isNull()); |
1490 | } |
1491 | |
1492 | ALWAYS_INLINE void recordPauseLocation(const JSTextPosition&); |
1493 | ALWAYS_INLINE void recordFunctionEntryLocation(const JSTextPosition&); |
1494 | ALWAYS_INLINE void recordFunctionLeaveLocation(const JSTextPosition&); |
1495 | |
1496 | void startLoop() { currentScope()->startLoop(); } |
1497 | void endLoop() { currentScope()->endLoop(); } |
1498 | void startSwitch() { currentScope()->startSwitch(); } |
1499 | void endSwitch() { currentScope()->endSwitch(); } |
1500 | void setStrictMode() { currentScope()->setStrictMode(); } |
1501 | bool strictMode() { return currentScope()->strictMode(); } |
1502 | bool isValidStrictMode() |
1503 | { |
1504 | int i = m_scopeStack.size() - 1; |
1505 | if (!m_scopeStack[i].isValidStrictMode()) |
1506 | return false; |
1507 | |
1508 | // In the case of Generator or Async function bodies, also check the wrapper function, whose name or |
1509 | // arguments may be invalid. |
1510 | if (UNLIKELY((m_scopeStack[i].isGeneratorBoundary() || m_scopeStack[i].isAsyncFunctionBoundary()) && i)) |
1511 | return m_scopeStack[i - 1].isValidStrictMode(); |
1512 | return true; |
1513 | } |
1514 | DeclarationResultMask declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); } |
1515 | bool declareRestOrNormalParameter(const Identifier&, const Identifier**); |
1516 | |
1517 | bool breakIsValid() |
1518 | { |
1519 | ScopeRef current = currentScope(); |
1520 | while (!current->breakIsValid()) { |
1521 | if (!current.hasContainingScope()) |
1522 | return false; |
1523 | current = current.containingScope(); |
1524 | } |
1525 | return true; |
1526 | } |
1527 | bool continueIsValid() |
1528 | { |
1529 | ScopeRef current = currentScope(); |
1530 | while (!current->continueIsValid()) { |
1531 | if (!current.hasContainingScope()) |
1532 | return false; |
1533 | current = current.containingScope(); |
1534 | } |
1535 | return true; |
1536 | } |
1537 | void pushLabel(const Identifier* label, bool isLoop) { currentScope()->pushLabel(label, isLoop); } |
1538 | void popLabel(ScopeRef scope) { scope->popLabel(); } |
1539 | ScopeLabelInfo* getLabel(const Identifier* label) |
1540 | { |
1541 | ScopeRef current = currentScope(); |
1542 | ScopeLabelInfo* result = 0; |
1543 | while (!(result = current->getLabel(label))) { |
1544 | if (!current.hasContainingScope()) |
1545 | return 0; |
1546 | current = current.containingScope(); |
1547 | } |
1548 | return result; |
1549 | } |
1550 | |
1551 | // http://ecma-international.org/ecma-262/6.0/#sec-identifiers-static-semantics-early-errors |
1552 | ALWAYS_INLINE bool isLETMaskedAsIDENT() |
1553 | { |
1554 | return match(LET) && !strictMode(); |
1555 | } |
1556 | |
1557 | // http://ecma-international.org/ecma-262/6.0/#sec-identifiers-static-semantics-early-errors |
1558 | ALWAYS_INLINE bool isYIELDMaskedAsIDENT(bool inGenerator) |
1559 | { |
1560 | return match(YIELD) && !strictMode() && !inGenerator; |
1561 | } |
1562 | |
1563 | // http://ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions-static-semantics-early-errors |
1564 | ALWAYS_INLINE bool matchSpecIdentifier(bool inGenerator) |
1565 | { |
1566 | return match(IDENT) || isLETMaskedAsIDENT() || isYIELDMaskedAsIDENT(inGenerator) || isSafeContextualKeyword(m_token); |
1567 | } |
1568 | |
1569 | ALWAYS_INLINE bool matchSpecIdentifier() |
1570 | { |
1571 | return match(IDENT) || isLETMaskedAsIDENT() || isYIELDMaskedAsIDENT(currentScope()->isGenerator()) || isSafeContextualKeyword(m_token); |
1572 | } |
1573 | |
1574 | template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode); |
1575 | template <class TreeBuilder> TreeSourceElements parseGeneratorFunctionSourceElements(TreeBuilder&, const Identifier& name, SourceElementsMode); |
1576 | template <class TreeBuilder> TreeSourceElements parseAsyncFunctionSourceElements(TreeBuilder&, SourceParseMode, bool isArrowFunctionBodyExpression, SourceElementsMode); |
1577 | template <class TreeBuilder> TreeSourceElements parseAsyncGeneratorFunctionSourceElements(TreeBuilder&, SourceParseMode, bool isArrowFunctionBodyExpression, SourceElementsMode); |
1578 | template <class TreeBuilder> TreeSourceElements parseSingleFunction(TreeBuilder&, Optional<int> functionConstructorParametersEndPosition); |
1579 | template <class TreeBuilder> TreeStatement parseStatementListItem(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength); |
1580 | template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0); |
1581 | enum class ExportType { Exported, NotExported }; |
1582 | template <class TreeBuilder> TreeStatement parseClassDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard); |
1583 | template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard, Optional<int> functionConstructorParametersEndPosition = WTF::nullopt); |
1584 | template <class TreeBuilder> TreeStatement parseFunctionDeclarationStatement(TreeBuilder&, bool isAsync, bool parentAllowsFunctionDeclarationAsStatement); |
1585 | template <class TreeBuilder> TreeStatement parseAsyncFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard, Optional<int> functionConstructorParametersEndPosition = WTF::nullopt); |
1586 | template <class TreeBuilder> NEVER_INLINE bool maybeParseAsyncFunctionDeclarationStatement(TreeBuilder& context, TreeStatement& result, bool parentAllowsFunctionDeclarationAsStatement); |
1587 | template <class TreeBuilder> TreeStatement parseVariableDeclaration(TreeBuilder&, DeclarationType, ExportType = ExportType::NotExported); |
1588 | template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&); |
1589 | template <class TreeBuilder> TreeStatement parseWhileStatement(TreeBuilder&); |
1590 | template <class TreeBuilder> TreeStatement parseForStatement(TreeBuilder&); |
1591 | template <class TreeBuilder> TreeStatement parseBreakStatement(TreeBuilder&); |
1592 | template <class TreeBuilder> TreeStatement parseContinueStatement(TreeBuilder&); |
1593 | template <class TreeBuilder> TreeStatement parseReturnStatement(TreeBuilder&); |
1594 | template <class TreeBuilder> TreeStatement parseThrowStatement(TreeBuilder&); |
1595 | template <class TreeBuilder> TreeStatement parseWithStatement(TreeBuilder&); |
1596 | template <class TreeBuilder> TreeStatement parseSwitchStatement(TreeBuilder&); |
1597 | template <class TreeBuilder> TreeClauseList parseSwitchClauses(TreeBuilder&); |
1598 | template <class TreeBuilder> TreeClause parseSwitchDefaultClause(TreeBuilder&); |
1599 | template <class TreeBuilder> TreeStatement parseTryStatement(TreeBuilder&); |
1600 | template <class TreeBuilder> TreeStatement parseDebuggerStatement(TreeBuilder&); |
1601 | template <class TreeBuilder> TreeStatement parseExpressionStatement(TreeBuilder&); |
1602 | template <class TreeBuilder> TreeStatement parseExpressionOrLabelStatement(TreeBuilder&, bool allowFunctionDeclarationAsStatement); |
1603 | template <class TreeBuilder> TreeStatement parseIfStatement(TreeBuilder&); |
1604 | template <class TreeBuilder> TreeStatement parseBlockStatement(TreeBuilder&); |
1605 | template <class TreeBuilder> TreeExpression parseExpression(TreeBuilder&); |
1606 | template <class TreeBuilder> TreeExpression parseAssignmentExpression(TreeBuilder&, ExpressionErrorClassifier&); |
1607 | template <class TreeBuilder> TreeExpression parseAssignmentExpression(TreeBuilder&); |
1608 | template <class TreeBuilder> TreeExpression parseAssignmentExpressionOrPropagateErrorClass(TreeBuilder&); |
1609 | template <class TreeBuilder> TreeExpression parseYieldExpression(TreeBuilder&); |
1610 | template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseConditionalExpression(TreeBuilder&); |
1611 | template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseBinaryExpression(TreeBuilder&); |
1612 | template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseUnaryExpression(TreeBuilder&); |
1613 | template <class TreeBuilder> NEVER_INLINE TreeExpression parseAwaitExpression(TreeBuilder&); |
1614 | template <class TreeBuilder> TreeExpression parseMemberExpression(TreeBuilder&); |
1615 | template <class TreeBuilder> ALWAYS_INLINE TreeExpression parsePrimaryExpression(TreeBuilder&); |
1616 | template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArrayLiteral(TreeBuilder&); |
1617 | template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&); |
1618 | template <class TreeBuilder> ALWAYS_INLINE TreeClassExpression parseClassExpression(TreeBuilder&); |
1619 | template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseFunctionExpression(TreeBuilder&); |
1620 | template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseAsyncFunctionExpression(TreeBuilder&); |
1621 | template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&); |
1622 | template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArgument(TreeBuilder&, ArgumentType&); |
1623 | template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict); |
1624 | template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, SourceParseMode); |
1625 | template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind, ClassElementTag); |
1626 | template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, SyntaxChecker&, const JSTokenLocation&, int, int functionKeywordStart, int functionNameStart, int , ConstructorKind, SuperBinding, FunctionBodyType, unsigned, SourceParseMode); |
1627 | template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, bool isArrowFunction, bool isMethod, unsigned&); |
1628 | enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext }; |
1629 | template <class TreeBuilder> TreeExpression parseVariableDeclarationList(TreeBuilder&, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext, DeclarationType, ExportType, bool& forLoopConstDoesNotHaveInitializer); |
1630 | template <class TreeBuilder> TreeSourceElements parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder&); |
1631 | template <class TreeBuilder> TreeExpression parseArrowFunctionExpression(TreeBuilder&, bool isAsync); |
1632 | template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier&, JSToken, AssignmentContext, const Identifier** duplicateIdentifier); |
1633 | template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createAssignmentElement(TreeBuilder&, TreeExpression&, const JSTextPosition&, const JSTextPosition&); |
1634 | template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseObjectRestBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind, ExportType, const Identifier** duplicateIdentifier, AssignmentContext bindingContext); |
1635 | template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind, ExportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth); |
1636 | template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseObjectRestAssignmentElement(TreeBuilder& context); |
1637 | template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseAssignmentElement(TreeBuilder& context, DestructuringKind, ExportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth); |
1638 | template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseObjectRestElement(TreeBuilder&, DestructuringKind, ExportType, const Identifier** duplicateIdentifier = nullptr, AssignmentContext = AssignmentContext::DeclarationStatement); |
1639 | template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier** duplicateIdentifier = nullptr, bool* hasDestructuringPattern = nullptr, AssignmentContext = AssignmentContext::DeclarationStatement, int depth = 0); |
1640 | template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern tryParseDestructuringPatternExpression(TreeBuilder&, AssignmentContext); |
1641 | template <class TreeBuilder> NEVER_INLINE TreeExpression parseDefaultValueForDestructuringPattern(TreeBuilder&); |
1642 | template <class TreeBuilder> TreeSourceElements parseModuleSourceElements(TreeBuilder&, SourceParseMode); |
1643 | enum class ImportSpecifierType { NamespaceImport, NamedImport, DefaultImport }; |
1644 | template <class TreeBuilder> typename TreeBuilder::ImportSpecifier parseImportClauseItem(TreeBuilder&, ImportSpecifierType); |
1645 | template <class TreeBuilder> typename TreeBuilder::ModuleName parseModuleName(TreeBuilder&); |
1646 | template <class TreeBuilder> TreeStatement parseImportDeclaration(TreeBuilder&); |
1647 | template <class TreeBuilder> typename TreeBuilder::ExportSpecifier parseExportSpecifier(TreeBuilder& context, Vector<std::pair<const Identifier*, const Identifier*>>& maybeExportedLocalNames, bool& hasKeywordForLocalBindings); |
1648 | template <class TreeBuilder> TreeStatement parseExportDeclaration(TreeBuilder&); |
1649 | |
1650 | template <class TreeBuilder> ALWAYS_INLINE TreeExpression createResolveAndUseVariable(TreeBuilder&, const Identifier*, bool isEval, const JSTextPosition&, const JSTokenLocation&); |
1651 | |
1652 | enum class FunctionDefinitionType { Expression, Declaration, Method }; |
1653 | template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionNameRequirements, SourceParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionDefinitionType, Optional<int> functionConstructorParametersEndPosition = WTF::nullopt); |
1654 | |
1655 | ALWAYS_INLINE bool isArrowFunctionParameters(); |
1656 | |
1657 | template <class TreeBuilder, class FunctionInfoType> NEVER_INLINE typename TreeBuilder::FormalParameterList parseFunctionParameters(TreeBuilder&, SourceParseMode, FunctionInfoType&); |
1658 | template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::FormalParameterList createGeneratorParameters(TreeBuilder&, unsigned& parameterCount); |
1659 | |
1660 | template <class TreeBuilder> NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&, FunctionNameRequirements, ParserClassInfo<TreeBuilder>&); |
1661 | |
1662 | template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateString parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode, bool& elementIsTail); |
1663 | template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateLiteral parseTemplateLiteral(TreeBuilder&, typename LexerType::RawStringsBuildMode); |
1664 | |
1665 | template <class TreeBuilder> ALWAYS_INLINE bool shouldCheckPropertyForUnderscoreProtoDuplicate(TreeBuilder&, const TreeProperty&); |
1666 | |
1667 | template <class TreeBuilder> NEVER_INLINE const char* metaPropertyName(TreeBuilder&, TreeExpression); |
1668 | |
1669 | template <class TreeBuilder> ALWAYS_INLINE bool isSimpleAssignmentTarget(TreeBuilder&, TreeExpression); |
1670 | |
1671 | ALWAYS_INLINE int isBinaryOperator(JSTokenType); |
1672 | bool allowAutomaticSemicolon(); |
1673 | |
1674 | bool autoSemiColon() |
1675 | { |
1676 | if (m_token.m_type == SEMICOLON) { |
1677 | next(); |
1678 | return true; |
1679 | } |
1680 | return allowAutomaticSemicolon(); |
1681 | } |
1682 | |
1683 | bool canRecurse() |
1684 | { |
1685 | return m_vm.isSafeToRecurse(); |
1686 | } |
1687 | |
1688 | const JSTextPosition& lastTokenEndPosition() const |
1689 | { |
1690 | return m_lastTokenEndPosition; |
1691 | } |
1692 | |
1693 | bool hasError() const |
1694 | { |
1695 | return !m_errorMessage.isNull(); |
1696 | } |
1697 | |
1698 | bool isDisallowedIdentifierLet(const JSToken& token) |
1699 | { |
1700 | return token.m_type == LET && strictMode(); |
1701 | } |
1702 | |
1703 | bool isDisallowedIdentifierAwait(const JSToken& token) |
1704 | { |
1705 | return token.m_type == AWAIT && (!m_parserState.allowAwait || currentScope()->isAsyncFunctionBoundary() || m_scriptMode == JSParserScriptMode::Module); |
1706 | } |
1707 | |
1708 | bool isDisallowedIdentifierYield(const JSToken& token) |
1709 | { |
1710 | return token.m_type == YIELD && (strictMode() || currentScope()->isGenerator()); |
1711 | } |
1712 | |
1713 | ALWAYS_INLINE SuperBinding adjustSuperBindingForBaseConstructor(ConstructorKind constructorKind, SuperBinding superBinding, ScopeRef functionScope) |
1714 | { |
1715 | return adjustSuperBindingForBaseConstructor(constructorKind, superBinding, functionScope->needsSuperBinding(), functionScope->usesEval(), functionScope->innerArrowFunctionFeatures()); |
1716 | } |
1717 | |
1718 | ALWAYS_INLINE SuperBinding adjustSuperBindingForBaseConstructor(ConstructorKind constructorKind, SuperBinding superBinding, bool scopeNeedsSuperBinding, bool currentScopeUsesEval, InnerArrowFunctionCodeFeatures innerArrowFunctionFeatures) |
1719 | { |
1720 | SuperBinding methodSuperBinding = superBinding; |
1721 | |
1722 | if (constructorKind == ConstructorKind::Base) { |
1723 | bool isSuperUsedInInnerArrowFunction = innerArrowFunctionFeatures & SuperPropertyInnerArrowFunctionFeature; |
1724 | methodSuperBinding = (scopeNeedsSuperBinding || isSuperUsedInInnerArrowFunction || currentScopeUsesEval) ? SuperBinding::Needed : SuperBinding::NotNeeded; |
1725 | } |
1726 | |
1727 | return methodSuperBinding; |
1728 | } |
1729 | |
1730 | const char* disallowedIdentifierLetReason() |
1731 | { |
1732 | ASSERT(strictMode()); |
1733 | return "in strict mode" ; |
1734 | } |
1735 | |
1736 | const char* disallowedIdentifierAwaitReason() |
1737 | { |
1738 | if (!m_parserState.allowAwait || currentScope()->isAsyncFunctionBoundary()) |
1739 | return "in an async function" ; |
1740 | if (m_scriptMode == JSParserScriptMode::Module) |
1741 | return "in a module" ; |
1742 | RELEASE_ASSERT_NOT_REACHED(); |
1743 | return nullptr; |
1744 | } |
1745 | |
1746 | const char* disallowedIdentifierYieldReason() |
1747 | { |
1748 | if (strictMode()) |
1749 | return "in strict mode" ; |
1750 | if (currentScope()->isGenerator()) |
1751 | return "in a generator function" ; |
1752 | RELEASE_ASSERT_NOT_REACHED(); |
1753 | return nullptr; |
1754 | } |
1755 | |
1756 | enum class FunctionParsePhase { Parameters, Body }; |
1757 | struct ParserState { |
1758 | int assignmentCount { 0 }; |
1759 | int nonLHSCount { 0 }; |
1760 | int nonTrivialExpressionCount { 0 }; |
1761 | FunctionParsePhase functionParsePhase { FunctionParsePhase::Body }; |
1762 | const Identifier* lastIdentifier { nullptr }; |
1763 | const Identifier* lastFunctionName { nullptr }; |
1764 | bool allowAwait { true }; |
1765 | }; |
1766 | |
1767 | // If you're using this directly, you probably should be using |
1768 | // createSavePoint() instead. |
1769 | ALWAYS_INLINE ParserState internalSaveParserState() |
1770 | { |
1771 | return m_parserState; |
1772 | } |
1773 | |
1774 | ALWAYS_INLINE void restoreParserState(const ParserState& state) |
1775 | { |
1776 | m_parserState = state; |
1777 | } |
1778 | |
1779 | struct LexerState { |
1780 | int startOffset; |
1781 | unsigned oldLineStartOffset; |
1782 | unsigned oldLastLineNumber; |
1783 | unsigned oldLineNumber; |
1784 | bool hasLineTerminatorBeforeToken; |
1785 | }; |
1786 | |
1787 | // If you're using this directly, you probably should be using |
1788 | // createSavePoint() instead. |
1789 | // i.e, if you parse any kind of AssignmentExpression between |
1790 | // saving/restoring, you should definitely not be using this directly. |
1791 | ALWAYS_INLINE LexerState internalSaveLexerState() |
1792 | { |
1793 | LexerState result; |
1794 | result.startOffset = m_token.m_location.startOffset; |
1795 | result.oldLineStartOffset = m_token.m_location.lineStartOffset; |
1796 | result.oldLastLineNumber = m_lexer->lastLineNumber(); |
1797 | result.oldLineNumber = m_lexer->lineNumber(); |
1798 | result.hasLineTerminatorBeforeToken = m_lexer->hasLineTerminatorBeforeToken(); |
1799 | ASSERT(static_cast<unsigned>(result.startOffset) >= result.oldLineStartOffset); |
1800 | return result; |
1801 | } |
1802 | |
1803 | ALWAYS_INLINE void restoreLexerState(const LexerState& lexerState) |
1804 | { |
1805 | // setOffset clears lexer errors. |
1806 | m_lexer->setOffset(lexerState.startOffset, lexerState.oldLineStartOffset); |
1807 | m_lexer->setLineNumber(lexerState.oldLineNumber); |
1808 | m_lexer->setHasLineTerminatorBeforeToken(lexerState.hasLineTerminatorBeforeToken); |
1809 | nextWithoutClearingLineTerminator(); |
1810 | m_lexer->setLastLineNumber(lexerState.oldLastLineNumber); |
1811 | } |
1812 | |
1813 | struct SavePoint { |
1814 | ParserState parserState; |
1815 | LexerState lexerState; |
1816 | }; |
1817 | |
1818 | struct SavePointWithError : public SavePoint { |
1819 | bool lexerError; |
1820 | String lexerErrorMessage; |
1821 | String parserErrorMessage; |
1822 | }; |
1823 | |
1824 | ALWAYS_INLINE void internalSaveState(SavePoint& savePoint) |
1825 | { |
1826 | savePoint.parserState = internalSaveParserState(); |
1827 | savePoint.lexerState = internalSaveLexerState(); |
1828 | } |
1829 | |
1830 | ALWAYS_INLINE SavePointWithError createSavePointForError() |
1831 | { |
1832 | SavePointWithError savePoint; |
1833 | internalSaveState(savePoint); |
1834 | savePoint.lexerError = m_lexer->sawError(); |
1835 | savePoint.lexerErrorMessage = m_lexer->getErrorMessage(); |
1836 | savePoint.parserErrorMessage = m_errorMessage; |
1837 | return savePoint; |
1838 | } |
1839 | |
1840 | ALWAYS_INLINE SavePoint createSavePoint() |
1841 | { |
1842 | ASSERT(!hasError()); |
1843 | SavePoint savePoint; |
1844 | internalSaveState(savePoint); |
1845 | return savePoint; |
1846 | } |
1847 | |
1848 | ALWAYS_INLINE void internalRestoreState(const SavePoint& savePoint) |
1849 | { |
1850 | restoreLexerState(savePoint.lexerState); |
1851 | restoreParserState(savePoint.parserState); |
1852 | } |
1853 | |
1854 | ALWAYS_INLINE void restoreSavePointWithError(const SavePointWithError& savePoint) |
1855 | { |
1856 | internalRestoreState(savePoint); |
1857 | m_lexer->setSawError(savePoint.lexerError); |
1858 | m_lexer->setErrorMessage(savePoint.lexerErrorMessage); |
1859 | m_errorMessage = savePoint.parserErrorMessage; |
1860 | } |
1861 | |
1862 | ALWAYS_INLINE void restoreSavePoint(const SavePoint& savePoint) |
1863 | { |
1864 | internalRestoreState(savePoint); |
1865 | m_errorMessage = String(); |
1866 | } |
1867 | |
1868 | VM& m_vm; |
1869 | const SourceCode* m_source; |
1870 | ParserArena m_parserArena; |
1871 | std::unique_ptr<LexerType> m_lexer; |
1872 | FunctionParameters* m_parameters { nullptr }; |
1873 | |
1874 | ParserState m_parserState; |
1875 | |
1876 | bool m_hasStackOverflow; |
1877 | String m_errorMessage; |
1878 | JSToken m_token; |
1879 | bool m_allowsIn; |
1880 | JSTextPosition m_lastTokenEndPosition; |
1881 | int m_statementDepth; |
1882 | RefPtr<SourceProviderCache> m_functionCache; |
1883 | SourceElements* m_sourceElements; |
1884 | bool m_parsingBuiltin; |
1885 | JSParserScriptMode m_scriptMode; |
1886 | SuperBinding m_superBinding; |
1887 | ConstructorKind m_defaultConstructorKindForTopLevelFunction; |
1888 | VariableEnvironment m_varDeclarations; |
1889 | DeclarationStacks::FunctionStack m_funcDeclarations; |
1890 | UniquedStringImplPtrSet m_sloppyModeHoistedFunctions; |
1891 | CodeFeatures m_features; |
1892 | int m_numConstants; |
1893 | ExpressionErrorClassifier* m_expressionErrorClassifier; |
1894 | bool m_isEvalContext; |
1895 | bool m_immediateParentAllowsFunctionDeclarationInStatement; |
1896 | RefPtr<ModuleScopeData> m_moduleScopeData; |
1897 | DebuggerParseData* m_debuggerParseData; |
1898 | CallOrApplyDepthScope* m_callOrApplyDepthScope { nullptr }; |
1899 | bool m_seenTaggedTemplate { false }; |
1900 | }; |
1901 | |
1902 | |
1903 | template <typename LexerType> |
1904 | template <class ParsedNode> |
1905 | std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, Optional<int> functionConstructorParametersEndPosition) |
1906 | { |
1907 | int errLine; |
1908 | String errMsg; |
1909 | |
1910 | if (ParsedNode::scopeIsFunction) |
1911 | m_lexer->setIsReparsingFunction(); |
1912 | |
1913 | m_sourceElements = 0; |
1914 | |
1915 | errLine = -1; |
1916 | errMsg = String(); |
1917 | |
1918 | JSTokenLocation startLocation(tokenLocation()); |
1919 | ASSERT(m_source->startColumn() > OrdinalNumber::beforeFirst()); |
1920 | unsigned startColumn = m_source->startColumn().zeroBasedInt(); |
1921 | |
1922 | String parseError = parseInner(calleeName, parseMode, parsingContext, functionConstructorParametersEndPosition); |
1923 | |
1924 | int lineNumber = m_lexer->lineNumber(); |
1925 | bool lexError = m_lexer->sawError(); |
1926 | String lexErrorMessage = lexError ? m_lexer->getErrorMessage() : String(); |
1927 | ASSERT(lexErrorMessage.isNull() != lexError); |
1928 | m_lexer->clear(); |
1929 | |
1930 | if (!parseError.isNull() || lexError) { |
1931 | errLine = lineNumber; |
1932 | errMsg = !lexErrorMessage.isNull() ? lexErrorMessage : parseError; |
1933 | m_sourceElements = 0; |
1934 | } |
1935 | |
1936 | std::unique_ptr<ParsedNode> result; |
1937 | if (m_sourceElements) { |
1938 | JSTokenLocation endLocation; |
1939 | endLocation.line = m_lexer->lineNumber(); |
1940 | endLocation.lineStartOffset = m_lexer->currentLineStartOffset(); |
1941 | endLocation.startOffset = m_lexer->currentOffset(); |
1942 | unsigned endColumn = endLocation.startOffset - endLocation.lineStartOffset; |
1943 | result = makeUnique<ParsedNode>(m_parserArena, |
1944 | startLocation, |
1945 | endLocation, |
1946 | startColumn, |
1947 | endColumn, |
1948 | m_sourceElements, |
1949 | m_varDeclarations, |
1950 | WTFMove(m_funcDeclarations), |
1951 | currentScope()->finalizeLexicalEnvironment(), |
1952 | WTFMove(m_sloppyModeHoistedFunctions), |
1953 | m_parameters, |
1954 | *m_source, |
1955 | m_features, |
1956 | currentScope()->innerArrowFunctionFeatures(), |
1957 | m_numConstants, |
1958 | WTFMove(m_moduleScopeData)); |
1959 | result->setLoc(m_source->firstLine().oneBasedInt(), m_lexer->lineNumber(), m_lexer->currentOffset(), m_lexer->currentLineStartOffset()); |
1960 | result->setEndOffset(m_lexer->currentOffset()); |
1961 | |
1962 | if (!isFunctionParseMode(parseMode)) { |
1963 | m_source->provider()->setSourceURLDirective(m_lexer->sourceURLDirective()); |
1964 | m_source->provider()->setSourceMappingURLDirective(m_lexer->sourceMappingURLDirective()); |
1965 | } |
1966 | } else { |
1967 | // We can never see a syntax error when reparsing a function, since we should have |
1968 | // reported the error when parsing the containing program or eval code. So if we're |
1969 | // parsing a function body node, we assume that what actually happened here is that |
1970 | // we ran out of stack while parsing. If we see an error while parsing eval or program |
1971 | // code we assume that it was a syntax error since running out of stack is much less |
1972 | // likely, and we are currently unable to distinguish between the two cases. |
1973 | if (isFunctionMetadataNode(static_cast<ParsedNode*>(0)) || m_hasStackOverflow) |
1974 | error = ParserError(ParserError::StackOverflow, ParserError::SyntaxErrorNone, m_token); |
1975 | else { |
1976 | ParserError::SyntaxErrorType errorType = ParserError::SyntaxErrorIrrecoverable; |
1977 | if (m_token.m_type == EOFTOK) |
1978 | errorType = ParserError::SyntaxErrorRecoverable; |
1979 | else if (m_token.m_type & UnterminatedErrorTokenFlag) { |
1980 | // Treat multiline capable unterminated literals as recoverable. |
1981 | if (m_token.m_type == UNTERMINATED_MULTILINE_COMMENT_ERRORTOK || m_token.m_type == UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK) |
1982 | errorType = ParserError::SyntaxErrorRecoverable; |
1983 | else |
1984 | errorType = ParserError::SyntaxErrorUnterminatedLiteral; |
1985 | } |
1986 | |
1987 | if (isEvalNode<ParsedNode>()) |
1988 | error = ParserError(ParserError::EvalError, errorType, m_token, errMsg, errLine); |
1989 | else |
1990 | error = ParserError(ParserError::SyntaxError, errorType, m_token, errMsg, errLine); |
1991 | } |
1992 | } |
1993 | |
1994 | return result; |
1995 | } |
1996 | |
1997 | template <class ParsedNode> |
1998 | std::unique_ptr<ParsedNode> parse( |
1999 | VM& vm, const SourceCode& source, |
2000 | const Identifier& name, JSParserBuiltinMode builtinMode, |
2001 | JSParserStrictMode strictMode, JSParserScriptMode scriptMode, SourceParseMode parseMode, SuperBinding superBinding, |
2002 | ParserError& error, JSTextPosition* positionBeforeLastNewline = nullptr, |
2003 | ConstructorKind defaultConstructorKindForTopLevelFunction = ConstructorKind::None, |
2004 | DerivedContextType derivedContextType = DerivedContextType::None, |
2005 | EvalContextType evalContextType = EvalContextType::None, |
2006 | DebuggerParseData* debuggerParseData = nullptr) |
2007 | { |
2008 | ASSERT(!source.provider()->source().isNull()); |
2009 | |
2010 | MonotonicTime before; |
2011 | if (UNLIKELY(Options::reportParseTimes())) |
2012 | before = MonotonicTime::now(); |
2013 | |
2014 | std::unique_ptr<ParsedNode> result; |
2015 | if (source.provider()->source().is8Bit()) { |
2016 | Parser<Lexer<LChar>> parser(vm, source, builtinMode, strictMode, scriptMode, parseMode, superBinding, defaultConstructorKindForTopLevelFunction, derivedContextType, isEvalNode<ParsedNode>(), evalContextType, debuggerParseData); |
2017 | result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program); |
2018 | if (positionBeforeLastNewline) |
2019 | *positionBeforeLastNewline = parser.positionBeforeLastNewline(); |
2020 | if (builtinMode == JSParserBuiltinMode::Builtin) { |
2021 | if (!result) { |
2022 | ASSERT(error.isValid()); |
2023 | if (error.type() != ParserError::StackOverflow) |
2024 | dataLogLn("Unexpected error compiling builtin: " , error.message()); |
2025 | } |
2026 | } |
2027 | } else { |
2028 | ASSERT_WITH_MESSAGE(defaultConstructorKindForTopLevelFunction == ConstructorKind::None, "BuiltinExecutables's special constructors should always use a 8-bit string" ); |
2029 | Parser<Lexer<UChar>> parser(vm, source, builtinMode, strictMode, scriptMode, parseMode, superBinding, defaultConstructorKindForTopLevelFunction, derivedContextType, isEvalNode<ParsedNode>(), evalContextType, debuggerParseData); |
2030 | result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program); |
2031 | if (positionBeforeLastNewline) |
2032 | *positionBeforeLastNewline = parser.positionBeforeLastNewline(); |
2033 | } |
2034 | |
2035 | if (UNLIKELY(Options::countParseTimes())) |
2036 | globalParseCount++; |
2037 | |
2038 | if (UNLIKELY(Options::reportParseTimes())) { |
2039 | MonotonicTime after = MonotonicTime::now(); |
2040 | ParseHash hash(source); |
2041 | dataLogLn(result ? "Parsed #" : "Failed to parse #" , hash.hashForCall(), "/#" , hash.hashForConstruct(), " in " , (after - before).milliseconds(), " ms." ); |
2042 | } |
2043 | |
2044 | return result; |
2045 | } |
2046 | |
2047 | inline std::unique_ptr<ProgramNode> parseFunctionForFunctionConstructor(VM& vm, const SourceCode& source, ParserError& error, JSTextPosition* positionBeforeLastNewline, Optional<int> functionConstructorParametersEndPosition) |
2048 | { |
2049 | ASSERT(!source.provider()->source().isNull()); |
2050 | |
2051 | MonotonicTime before; |
2052 | if (UNLIKELY(Options::reportParseTimes())) |
2053 | before = MonotonicTime::now(); |
2054 | |
2055 | Identifier name; |
2056 | bool isEvalNode = false; |
2057 | std::unique_ptr<ProgramNode> result; |
2058 | if (source.provider()->source().is8Bit()) { |
2059 | Parser<Lexer<LChar>> parser(vm, source, JSParserBuiltinMode::NotBuiltin, JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, ConstructorKind::None, DerivedContextType::None, isEvalNode, EvalContextType::None, nullptr); |
2060 | result = parser.parse<ProgramNode>(error, name, SourceParseMode::ProgramMode, ParsingContext::FunctionConstructor, functionConstructorParametersEndPosition); |
2061 | if (positionBeforeLastNewline) |
2062 | *positionBeforeLastNewline = parser.positionBeforeLastNewline(); |
2063 | } else { |
2064 | Parser<Lexer<UChar>> parser(vm, source, JSParserBuiltinMode::NotBuiltin, JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, ConstructorKind::None, DerivedContextType::None, isEvalNode, EvalContextType::None, nullptr); |
2065 | result = parser.parse<ProgramNode>(error, name, SourceParseMode::ProgramMode, ParsingContext::FunctionConstructor, functionConstructorParametersEndPosition); |
2066 | if (positionBeforeLastNewline) |
2067 | *positionBeforeLastNewline = parser.positionBeforeLastNewline(); |
2068 | } |
2069 | |
2070 | if (UNLIKELY(Options::countParseTimes())) |
2071 | globalParseCount++; |
2072 | |
2073 | if (UNLIKELY(Options::reportParseTimes())) { |
2074 | MonotonicTime after = MonotonicTime::now(); |
2075 | ParseHash hash(source); |
2076 | dataLogLn(result ? "Parsed #" : "Failed to parse #" , hash.hashForCall(), "/#" , hash.hashForConstruct(), " in " , (after - before).milliseconds(), " ms." ); |
2077 | } |
2078 | |
2079 | return result; |
2080 | } |
2081 | |
2082 | |
2083 | } // namespace |
2084 | |