Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef frontend_SharedContext_h
8 : #define frontend_SharedContext_h
9 :
10 : #include "jsatom.h"
11 : #include "jsopcode.h"
12 : #include "jspubtd.h"
13 : #include "jsscript.h"
14 : #include "jstypes.h"
15 :
16 : #include "builtin/ModuleObject.h"
17 : #include "ds/InlineTable.h"
18 : #include "frontend/TokenStream.h"
19 : #include "vm/EnvironmentObject.h"
20 :
21 : namespace js {
22 : namespace frontend {
23 :
24 : class ParseNode;
25 :
26 : enum class StatementKind : uint8_t
27 : {
28 : Label,
29 : Block,
30 : If,
31 : Switch,
32 : With,
33 : Catch,
34 : Try,
35 : Finally,
36 : ForLoopLexicalHead,
37 : ForLoop,
38 : ForInLoop,
39 : ForOfLoop,
40 : DoLoop,
41 : WhileLoop,
42 : Class,
43 :
44 : // Used only by BytecodeEmitter.
45 : Spread
46 : };
47 :
48 : static inline bool
49 7294 : StatementKindIsLoop(StatementKind kind)
50 : {
51 5708 : return kind == StatementKind::ForLoop ||
52 5549 : kind == StatementKind::ForInLoop ||
53 4186 : kind == StatementKind::ForOfLoop ||
54 4126 : kind == StatementKind::DoLoop ||
55 10428 : kind == StatementKind::WhileLoop ||
56 7294 : kind == StatementKind::Spread;
57 : }
58 :
59 : static inline bool
60 3920 : StatementKindIsUnlabeledBreakTarget(StatementKind kind)
61 : {
62 3920 : return StatementKindIsLoop(kind) || kind == StatementKind::Switch;
63 : }
64 :
65 : // These flags apply to both global and function contexts.
66 : class AnyContextFlags
67 : {
68 : // This class's data is all private and so only visible to these friends.
69 : friend class SharedContext;
70 :
71 : // True if "use strict"; appears in the body instead of being inherited.
72 : bool hasExplicitUseStrict:1;
73 :
74 : // The (static) bindings of this script need to support dynamic name
75 : // read/write access. Here, 'dynamic' means dynamic dictionary lookup on
76 : // the scope chain for a dynamic set of keys. The primary examples are:
77 : // - direct eval
78 : // - function::
79 : // - with
80 : // since both effectively allow any name to be accessed. Non-examples are:
81 : // - upvars of nested functions
82 : // - function statement
83 : // since the set of assigned name is known dynamically.
84 : //
85 : // Note: access through the arguments object is not considered dynamic
86 : // binding access since it does not go through the normal name lookup
87 : // mechanism. This is debatable and could be changed (although care must be
88 : // taken not to turn off the whole 'arguments' optimization). To answer the
89 : // more general "is this argument aliased" question, script->needsArgsObj
90 : // should be tested (see JSScript::argIsAliased).
91 : bool bindingsAccessedDynamically:1;
92 :
93 : // Whether this script, or any of its inner scripts contains a debugger
94 : // statement which could potentially read or write anywhere along the
95 : // scope chain.
96 : bool hasDebuggerStatement:1;
97 :
98 : // A direct eval occurs in the body of the script.
99 : bool hasDirectEval:1;
100 :
101 : public:
102 7906 : AnyContextFlags()
103 7906 : : hasExplicitUseStrict(false),
104 : bindingsAccessedDynamically(false),
105 : hasDebuggerStatement(false),
106 7906 : hasDirectEval(false)
107 7906 : { }
108 : };
109 :
110 : class FunctionContextFlags
111 : {
112 : // This class's data is all private and so only visible to these friends.
113 : friend class FunctionBox;
114 :
115 : // This function does something that can extend the set of bindings in its
116 : // call objects --- it does a direct eval in non-strict code, or includes a
117 : // function statement (as opposed to a function definition).
118 : //
119 : // This flag is *not* inherited by enclosed or enclosing functions; it
120 : // applies only to the function in whose flags it appears.
121 : //
122 : bool hasExtensibleScope:1;
123 :
124 : // Technically, every function has a binding named 'arguments'. Internally,
125 : // this binding is only added when 'arguments' is mentioned by the function
126 : // body. This flag indicates whether 'arguments' has been bound either
127 : // through implicit use:
128 : // function f() { return arguments }
129 : // or explicit redeclaration:
130 : // function f() { var arguments; return arguments }
131 : //
132 : // Note 1: overwritten arguments (function() { arguments = 3 }) will cause
133 : // this flag to be set but otherwise require no special handling:
134 : // 'arguments' is just a local variable and uses of 'arguments' will just
135 : // read the local's current slot which may have been assigned. The only
136 : // special semantics is that the initial value of 'arguments' is the
137 : // arguments object (not undefined, like normal locals).
138 : //
139 : // Note 2: if 'arguments' is bound as a formal parameter, there will be an
140 : // 'arguments' in Bindings, but, as the "LOCAL" in the name indicates, this
141 : // flag will not be set. This is because, as a formal, 'arguments' will
142 : // have no special semantics: the initial value is unconditionally the
143 : // actual argument (or undefined if nactual < nformal).
144 : //
145 : bool argumentsHasLocalBinding:1;
146 :
147 : // In many cases where 'arguments' has a local binding (as described above)
148 : // we do not need to actually create an arguments object in the function
149 : // prologue: instead we can analyze how 'arguments' is used (using the
150 : // simple dataflow analysis in analyzeSSA) to determine that uses of
151 : // 'arguments' can just read from the stack frame directly. However, the
152 : // dataflow analysis only looks at how JSOP_ARGUMENTS is used, so it will
153 : // be unsound in several cases. The frontend filters out such cases by
154 : // setting this flag which eagerly sets script->needsArgsObj to true.
155 : //
156 : bool definitelyNeedsArgsObj:1;
157 :
158 : bool needsHomeObject:1;
159 : bool isDerivedClassConstructor:1;
160 :
161 : // Whether this function has a .this binding. If true, we need to emit
162 : // JSOP_FUNCTIONTHIS in the prologue to initialize it.
163 : bool hasThisBinding:1;
164 :
165 : // Whether this function has nested functions.
166 : bool hasInnerFunctions:1;
167 :
168 : public:
169 7633 : FunctionContextFlags()
170 7633 : : hasExtensibleScope(false),
171 : argumentsHasLocalBinding(false),
172 : definitelyNeedsArgsObj(false),
173 : needsHomeObject(false),
174 : isDerivedClassConstructor(false),
175 : hasThisBinding(false),
176 7633 : hasInnerFunctions(false)
177 7633 : { }
178 : };
179 :
180 : // List of directives that may be encountered in a Directive Prologue (ES5 15.1).
181 : class Directives
182 : {
183 : bool strict_;
184 : bool asmJS_;
185 :
186 : public:
187 1951 : explicit Directives(bool strict) : strict_(strict), asmJS_(false) {}
188 : explicit Directives(ParseContext* parent);
189 :
190 0 : void setStrict() { strict_ = true; }
191 7906 : bool strict() const { return strict_; }
192 :
193 0 : void setAsmJS() { asmJS_ = true; }
194 0 : bool asmJS() const { return asmJS_; }
195 :
196 0 : Directives& operator=(Directives rhs) {
197 0 : strict_ = rhs.strict_;
198 0 : asmJS_ = rhs.asmJS_;
199 0 : return *this;
200 : }
201 0 : bool operator==(const Directives& rhs) const {
202 0 : return strict_ == rhs.strict_ && asmJS_ == rhs.asmJS_;
203 : }
204 : bool operator!=(const Directives& rhs) const {
205 : return !(*this == rhs);
206 : }
207 : };
208 :
209 : // The kind of this-binding for the current scope. Note that arrow functions
210 : // (and generator expression lambdas) have a lexical this-binding so their
211 : // ThisBinding is the same as the ThisBinding of their enclosing scope and can
212 : // be any value.
213 : enum class ThisBinding { Global, Function, Module };
214 :
215 : class GlobalSharedContext;
216 : class EvalSharedContext;
217 : class ModuleSharedContext;
218 :
219 : /*
220 : * The struct SharedContext is part of the current parser context (see
221 : * ParseContext). It stores information that is reused between the parser and
222 : * the bytecode emitter.
223 : */
224 : class SharedContext
225 : {
226 : public:
227 : JSContext* const context;
228 : AnyContextFlags anyCxFlags;
229 : bool strictScript;
230 : bool localStrict;
231 : bool extraWarnings;
232 :
233 : protected:
234 : enum class Kind {
235 : FunctionBox,
236 : Global,
237 : Eval,
238 : Module
239 : };
240 :
241 : Kind kind_;
242 :
243 : ThisBinding thisBinding_;
244 :
245 : bool allowNewTarget_;
246 : bool allowSuperProperty_;
247 : bool allowSuperCall_;
248 : bool inWith_;
249 : bool needsThisTDZChecks_;
250 :
251 : void computeAllowSyntax(Scope* scope);
252 : void computeInWith(Scope* scope);
253 : void computeThisBinding(Scope* scope);
254 :
255 : public:
256 7906 : SharedContext(JSContext* cx, Kind kind, Directives directives, bool extraWarnings)
257 7906 : : context(cx),
258 : anyCxFlags(),
259 7906 : strictScript(directives.strict()),
260 : localStrict(false),
261 : extraWarnings(extraWarnings),
262 : kind_(kind),
263 : thisBinding_(ThisBinding::Global),
264 : allowNewTarget_(false),
265 : allowSuperProperty_(false),
266 : allowSuperCall_(false),
267 : inWith_(false),
268 15812 : needsThisTDZChecks_(false)
269 7906 : { }
270 :
271 : // If this is the outermost SharedContext, the Scope that encloses
272 : // it. Otherwise nullptr.
273 : virtual Scope* compilationEnclosingScope() const = 0;
274 :
275 747800 : bool isFunctionBox() const { return kind_ == Kind::FunctionBox; }
276 : inline FunctionBox* asFunctionBox();
277 3852 : bool isModuleContext() const { return kind_ == Kind::Module; }
278 : inline ModuleSharedContext* asModuleContext();
279 82873 : bool isGlobalContext() const { return kind_ == Kind::Global; }
280 : inline GlobalSharedContext* asGlobalContext();
281 3075 : bool isEvalContext() const { return kind_ == Kind::Eval; }
282 : inline EvalSharedContext* asEvalContext();
283 :
284 20306 : ThisBinding thisBinding() const { return thisBinding_; }
285 :
286 1564 : bool allowNewTarget() const { return allowNewTarget_; }
287 858 : bool allowSuperProperty() const { return allowSuperProperty_; }
288 847 : bool allowSuperCall() const { return allowSuperCall_; }
289 6219 : bool inWith() const { return inWith_; }
290 7807 : bool needsThisTDZChecks() const { return needsThisTDZChecks_; }
291 :
292 5680 : bool hasExplicitUseStrict() const { return anyCxFlags.hasExplicitUseStrict; }
293 30581 : bool bindingsAccessedDynamically() const { return anyCxFlags.bindingsAccessedDynamically; }
294 8252 : bool hasDebuggerStatement() const { return anyCxFlags.hasDebuggerStatement; }
295 8242 : bool hasDirectEval() const { return anyCxFlags.hasDirectEval; }
296 :
297 109 : void setExplicitUseStrict() { anyCxFlags.hasExplicitUseStrict = true; }
298 2 : void setBindingsAccessedDynamically() { anyCxFlags.bindingsAccessedDynamically = true; }
299 0 : void setHasDebuggerStatement() { anyCxFlags.hasDebuggerStatement = true; }
300 2 : void setHasDirectEval() { anyCxFlags.hasDirectEval = true; }
301 :
302 : inline bool allBindingsClosedOver();
303 :
304 104582 : bool strict() const {
305 104582 : return strictScript || localStrict;
306 : }
307 128 : bool setLocalStrictMode(bool strict) {
308 128 : bool retVal = localStrict;
309 128 : localStrict = strict;
310 128 : return retVal;
311 : }
312 :
313 : // JSOPTION_EXTRA_WARNINGS warnings or strict mode errors.
314 29110 : bool needStrictChecks() const {
315 29110 : return strict() || extraWarnings;
316 : }
317 :
318 : bool isDotVariable(JSAtom* atom) const {
319 : return atom == context->names().dotGenerator || atom == context->names().dotThis;
320 : }
321 : };
322 :
323 267 : class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext
324 : {
325 : ScopeKind scopeKind_;
326 :
327 : public:
328 : Rooted<GlobalScope::Data*> bindings;
329 :
330 267 : GlobalSharedContext(JSContext* cx, ScopeKind scopeKind, Directives directives,
331 : bool extraWarnings)
332 267 : : SharedContext(cx, Kind::Global, directives, extraWarnings),
333 : scopeKind_(scopeKind),
334 267 : bindings(cx)
335 : {
336 267 : MOZ_ASSERT(scopeKind == ScopeKind::Global || scopeKind == ScopeKind::NonSyntactic);
337 267 : thisBinding_ = ThisBinding::Global;
338 267 : }
339 :
340 266 : Scope* compilationEnclosingScope() const override {
341 266 : return nullptr;
342 : }
343 :
344 526 : ScopeKind scopeKind() const {
345 526 : return scopeKind_;
346 : }
347 : };
348 :
349 : inline GlobalSharedContext*
350 533 : SharedContext::asGlobalContext()
351 : {
352 533 : MOZ_ASSERT(isGlobalContext());
353 533 : return static_cast<GlobalSharedContext*>(this);
354 : }
355 :
356 2 : class MOZ_STACK_CLASS EvalSharedContext : public SharedContext
357 : {
358 : RootedScope enclosingScope_;
359 :
360 : public:
361 : Rooted<EvalScope::Data*> bindings;
362 :
363 : EvalSharedContext(JSContext* cx, JSObject* enclosingEnv, Scope* enclosingScope,
364 : Directives directives, bool extraWarnings);
365 :
366 2 : Scope* compilationEnclosingScope() const override {
367 2 : return enclosingScope_;
368 : }
369 : };
370 :
371 : inline EvalSharedContext*
372 4 : SharedContext::asEvalContext()
373 : {
374 4 : MOZ_ASSERT(isEvalContext());
375 4 : return static_cast<EvalSharedContext*>(this);
376 : }
377 :
378 : class FunctionBox : public ObjectBox, public SharedContext
379 : {
380 : // The parser handles tracing the fields below via the ObjectBox linked
381 : // list.
382 :
383 : Scope* enclosingScope_;
384 :
385 : // Names from the named lambda scope, if a named lambda.
386 : LexicalScope::Data* namedLambdaBindings_;
387 :
388 : // Names from the function scope.
389 : FunctionScope::Data* functionScopeBindings_;
390 :
391 : // Names from the extra 'var' scope of the function, if the parameter list
392 : // has expressions.
393 : VarScope::Data* extraVarScopeBindings_;
394 :
395 : void initWithEnclosingScope(Scope* enclosingScope);
396 :
397 : public:
398 : ParseNode* functionNode; /* back pointer used by asm.js for error messages */
399 : uint32_t bufStart;
400 : uint32_t bufEnd;
401 : uint32_t startLine;
402 : uint32_t startColumn;
403 : uint32_t toStringStart;
404 : uint32_t toStringEnd;
405 : uint16_t length;
406 :
407 : uint8_t generatorKindBits_; /* The GeneratorKind of this function. */
408 : uint8_t asyncKindBits_; /* The FunctionAsyncKind of this function. */
409 :
410 : bool isGenexpLambda:1; /* lambda from generator expression */
411 : bool hasDestructuringArgs:1; /* parameter list contains destructuring expression */
412 : bool hasParameterExprs:1; /* parameter list contains expressions */
413 : bool hasDirectEvalInParameterExpr:1; /* parameter list contains direct eval */
414 : bool hasDuplicateParameters:1; /* parameter list contains duplicate names */
415 : bool useAsm:1; /* see useAsmOrInsideUseAsm */
416 : bool insideUseAsm:1; /* see useAsmOrInsideUseAsm */
417 : bool isAnnexB:1; /* need to emit a synthesized Annex B assignment */
418 : bool wasEmitted:1; /* Bytecode has been emitted for this function. */
419 :
420 : // Fields for use in heuristics.
421 : bool declaredArguments:1; /* the Parser declared 'arguments' */
422 : bool usesArguments:1; /* contains a free use of 'arguments' */
423 : bool usesApply:1; /* contains an f.apply() call */
424 : bool usesThis:1; /* contains 'this' */
425 : bool usesReturn:1; /* contains a 'return' statement */
426 : bool hasRest_:1; /* has rest parameter */
427 : bool isExprBody_:1; /* arrow function with expression
428 : * body or expression closure:
429 : * function(x) x*x */
430 :
431 : FunctionContextFlags funCxFlags;
432 :
433 : FunctionBox(JSContext* cx, LifoAlloc& alloc, ObjectBox* traceListHead, JSFunction* fun,
434 : uint32_t toStringStart, Directives directives, bool extraWarnings,
435 : GeneratorKind generatorKind, FunctionAsyncKind asyncKind);
436 :
437 6973 : MutableHandle<LexicalScope::Data*> namedLambdaBindings() {
438 6973 : MOZ_ASSERT(context->keepAtoms);
439 6973 : return MutableHandle<LexicalScope::Data*>::fromMarkedLocation(&namedLambdaBindings_);
440 : }
441 :
442 16381 : MutableHandle<FunctionScope::Data*> functionScopeBindings() {
443 16381 : MOZ_ASSERT(context->keepAtoms);
444 16381 : return MutableHandle<FunctionScope::Data*>::fromMarkedLocation(&functionScopeBindings_);
445 : }
446 :
447 599 : MutableHandle<VarScope::Data*> extraVarScopeBindings() {
448 599 : MOZ_ASSERT(context->keepAtoms);
449 599 : return MutableHandle<VarScope::Data*>::fromMarkedLocation(&extraVarScopeBindings_);
450 : }
451 :
452 : void initFromLazyFunction();
453 : void initStandaloneFunction(Scope* enclosingScope);
454 : void initWithEnclosingParseContext(ParseContext* enclosing, FunctionSyntaxKind kind);
455 :
456 107004 : JSFunction* function() const { return &object->as<JSFunction>(); }
457 :
458 5319 : Scope* compilationEnclosingScope() const override {
459 : // This method is used to distinguish the outermost SharedContext. If
460 : // a FunctionBox is the outermost SharedContext, it must be a lazy
461 : // function.
462 5319 : MOZ_ASSERT_IF(function()->isInterpretedLazy(),
463 : enclosingScope_ == function()->lazyScript()->enclosingScope());
464 5319 : return enclosingScope_;
465 : }
466 :
467 5404 : bool needsCallObjectRegardlessOfBindings() const {
468 10806 : return hasExtensibleScope() ||
469 10791 : needsHomeObject() ||
470 10765 : isDerivedClassConstructor() ||
471 10737 : isStarGenerator() ||
472 16126 : isLegacyGenerator() ||
473 10765 : isAsync();
474 : }
475 :
476 10992 : bool hasExtraBodyVarScope() const {
477 11853 : return hasParameterExprs &&
478 786 : (extraVarScopeBindings_ ||
479 11229 : needsExtraBodyVarEnvironmentRegardlessOfBindings());
480 : }
481 :
482 341 : bool needsExtraBodyVarEnvironmentRegardlessOfBindings() const {
483 341 : MOZ_ASSERT(hasParameterExprs);
484 341 : return hasExtensibleScope() || needsDotGeneratorName();
485 : }
486 :
487 6009 : bool isLikelyConstructorWrapper() const {
488 6009 : return usesArguments && usesApply && usesThis && !usesReturn;
489 : }
490 :
491 118228 : GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); }
492 33724 : bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
493 40218 : bool isStarGenerator() const { return generatorKind() == StarGenerator; }
494 79512 : FunctionAsyncKind asyncKind() const { return AsyncKindFromBits(asyncKindBits_); }
495 :
496 11569 : bool needsFinalYield() const {
497 11569 : return isStarGenerator() || isLegacyGenerator() || isAsync();
498 : }
499 341 : bool needsDotGeneratorName() const {
500 341 : return isStarGenerator() || isLegacyGenerator() || isAsync();
501 : }
502 6306 : bool needsIteratorResult() const {
503 6306 : return isStarGenerator();
504 : }
505 :
506 72075 : bool isAsync() const { return asyncKind() == AsyncFunction; }
507 0 : bool isArrow() const { return function()->isArrow(); }
508 :
509 14063 : bool hasRest() const { return hasRest_; }
510 73 : void setHasRest() {
511 73 : hasRest_ = true;
512 73 : }
513 :
514 7445 : bool isExprBody() const { return isExprBody_; }
515 609 : void setIsExprBody() {
516 609 : isExprBody_ = true;
517 609 : }
518 :
519 0 : void setGeneratorKind(GeneratorKind kind) {
520 : // A generator kind can be set at initialization, or when "yield" is
521 : // first seen. In both cases the transition can only happen from
522 : // NotGenerator.
523 0 : MOZ_ASSERT(!isStarGenerator() && !isLegacyGenerator());
524 0 : generatorKindBits_ = GeneratorKindAsBits(kind);
525 0 : }
526 :
527 16475 : bool hasExtensibleScope() const { return funCxFlags.hasExtensibleScope; }
528 12837 : bool hasThisBinding() const { return funCxFlags.hasThisBinding; }
529 11162 : bool argumentsHasLocalBinding() const { return funCxFlags.argumentsHasLocalBinding; }
530 5405 : bool definitelyNeedsArgsObj() const { return funCxFlags.definitelyNeedsArgsObj; }
531 15810 : bool needsHomeObject() const { return funCxFlags.needsHomeObject; }
532 28164 : bool isDerivedClassConstructor() const { return funCxFlags.isDerivedClassConstructor; }
533 5405 : bool hasInnerFunctions() const { return funCxFlags.hasInnerFunctions; }
534 :
535 2 : void setHasExtensibleScope() { funCxFlags.hasExtensibleScope = true; }
536 3128 : void setHasThisBinding() { funCxFlags.hasThisBinding = true; }
537 270 : void setArgumentsHasLocalBinding() { funCxFlags.argumentsHasLocalBinding = true; }
538 3 : void setDefinitelyNeedsArgsObj() { MOZ_ASSERT(funCxFlags.argumentsHasLocalBinding);
539 3 : funCxFlags.definitelyNeedsArgsObj = true; }
540 19 : void setNeedsHomeObject() { MOZ_ASSERT(function()->allowSuperProperty());
541 19 : funCxFlags.needsHomeObject = true; }
542 19 : void setDerivedClassConstructor() { MOZ_ASSERT(function()->isClassConstructor());
543 19 : funCxFlags.isDerivedClassConstructor = true; }
544 1120 : void setHasInnerFunctions() { funCxFlags.hasInnerFunctions = true; }
545 :
546 1187 : bool hasSimpleParameterList() const {
547 1187 : return !hasRest() && !hasParameterExprs && !hasDestructuringArgs;
548 : }
549 :
550 5406 : bool hasMappedArgsObj() const {
551 5406 : return !strict() && hasSimpleParameterList();
552 : }
553 :
554 : // Return whether this or an enclosing function is being parsed and
555 : // validated as asm.js. Note: if asm.js validation fails, this will be false
556 : // while the function is being reparsed. This flag can be used to disable
557 : // certain parsing features that are necessary in general, but unnecessary
558 : // for validated asm.js.
559 124323 : bool useAsmOrInsideUseAsm() const {
560 124323 : return useAsm || insideUseAsm;
561 : }
562 :
563 7373 : void setStart(const TokenStream& tokenStream) {
564 : // Token positions are already offset from the start column in
565 : // CompileOptions. bufStart and toStringStart, however, refer to
566 : // absolute positions within the ScriptSource buffer, and need to
567 : // de-offset from the starting column.
568 7373 : uint32_t offset = tokenStream.currentToken().pos.begin;
569 7373 : uint32_t sourceStartColumn = tokenStream.options().sourceStartColumn;
570 :
571 7373 : MOZ_ASSERT(offset >= sourceStartColumn);
572 7373 : MOZ_ASSERT(toStringStart >= sourceStartColumn);
573 7373 : toStringStart -= sourceStartColumn;
574 7373 : bufStart = offset - sourceStartColumn;
575 7373 : tokenStream.srcCoords.lineNumAndColumnIndex(offset, &startLine, &startColumn);
576 7373 : }
577 :
578 7373 : void setEnd(const TokenStream& tokenStream) {
579 : // For all functions except class constructors, the buffer and
580 : // toString ending positions are the same. Class constructors override
581 : // the toString ending position with the end of the class definition.
582 : //
583 : // Offsets are de-offset for the same reason as in setStart above.
584 7373 : uint32_t offset = tokenStream.currentToken().pos.end;
585 7373 : uint32_t sourceStartColumn = tokenStream.options().sourceStartColumn;
586 :
587 7373 : MOZ_ASSERT(offset >= sourceStartColumn);
588 7373 : bufEnd = offset - sourceStartColumn;
589 7373 : toStringEnd = bufEnd;
590 7373 : }
591 :
592 : void trace(JSTracer* trc) override;
593 : };
594 :
595 : inline FunctionBox*
596 385724 : SharedContext::asFunctionBox()
597 : {
598 385724 : MOZ_ASSERT(isFunctionBox());
599 385724 : return static_cast<FunctionBox*>(this);
600 : }
601 :
602 0 : class MOZ_STACK_CLASS ModuleSharedContext : public SharedContext
603 : {
604 : RootedModuleObject module_;
605 : RootedScope enclosingScope_;
606 :
607 : public:
608 : Rooted<ModuleScope::Data*> bindings;
609 : ModuleBuilder& builder;
610 :
611 : ModuleSharedContext(JSContext* cx, ModuleObject* module, Scope* enclosingScope,
612 : ModuleBuilder& builder);
613 :
614 0 : HandleModuleObject module() const { return module_; }
615 0 : Scope* compilationEnclosingScope() const override { return enclosingScope_; }
616 : };
617 :
618 : inline ModuleSharedContext*
619 0 : SharedContext::asModuleContext()
620 : {
621 0 : MOZ_ASSERT(isModuleContext());
622 0 : return static_cast<ModuleSharedContext*>(this);
623 : }
624 :
625 : // In generators, we treat all bindings as closed so that they get stored on
626 : // the heap. This way there is less information to copy off the stack when
627 : // suspending, and back on when resuming. It also avoids the need to create
628 : // and invalidate DebugScope proxies for unaliased locals in a generator
629 : // frame, as the generator frame will be copied out to the heap and released
630 : // only by GC.
631 : inline bool
632 9131 : SharedContext::allBindingsClosedOver()
633 : {
634 18640 : return bindingsAccessedDynamically() ||
635 17945 : (isFunctionBox() &&
636 17587 : (asFunctionBox()->isStarGenerator() ||
637 17542 : asFunctionBox()->isLegacyGenerator() ||
638 17902 : asFunctionBox()->isAsync()));
639 : }
640 :
641 : } // namespace frontend
642 : } // namespace js
643 :
644 : #endif /* frontend_SharedContext_h */
|