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