Backed out changeset 9d8b4c0b99ed (bug 1945683) for causing btime failures. CLOSED...
[gecko.git] / js / public / CompileOptions.h
blobe0c10b8d5b8f038a32632344c86de26d3f689c0b
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 * Options for JavaScript compilation.
9 * In the most common use case, a CompileOptions instance is allocated on the
10 * stack, and holds non-owning references to non-POD option values: strings,
11 * principals, objects, and so on. The code declaring the instance guarantees
12 * that such option values will outlive the CompileOptions itself: objects are
13 * otherwise rooted, principals have had their reference counts bumped, and
14 * strings won't be freed until the CompileOptions goes out of scope. In this
15 * situation, CompileOptions only refers to things others own, so it can be
16 * lightweight.
18 * In some cases, however, we need to hold compilation options with a
19 * non-stack-like lifetime. For example, JS::CompileOffThread needs to save
20 * compilation options where a worker thread can find them, then return
21 * immediately. The worker thread will come along at some later point, and use
22 * the options.
24 * The compiler itself just needs to be able to access a collection of options;
25 * it doesn't care who owns them, or what's keeping them alive. It does its
26 * own addrefs/copies/tracing/etc.
28 * Furthermore, in some cases compile options are propagated from one entity to
29 * another (e.g. from a script to a function defined in that script). This
30 * involves copying over some, but not all, of the options.
32 * So we have a class hierarchy that reflects these four use cases:
34 * - TransitiveCompileOptions is the common base class, representing options
35 * that should get propagated from a script to functions defined in that
36 * script. This class is abstract and is only ever used as a subclass.
38 * - ReadOnlyCompileOptions is the only subclass of TransitiveCompileOptions,
39 * representing a full set of compile options. It can be used by code that
40 * simply needs to access options set elsewhere, like the compiler. This
41 * class too is abstract and is only ever used as a subclass.
43 * - The usual CompileOptions class must be stack-allocated, and holds
44 * non-owning references to the filename, element, and so on. It's derived
45 * from ReadOnlyCompileOptions, so the compiler can use it.
47 * - OwningCompileOptions roots / copies / reference counts of all its values,
48 * and unroots / frees / releases them when it is destructed. It too is
49 * derived from ReadOnlyCompileOptions, so the compiler accepts it.
52 #ifndef js_CompileOptions_h
53 #define js_CompileOptions_h
55 #include "mozilla/Assertions.h" // MOZ_ASSERT
56 #include "mozilla/MemoryReporting.h" // mozilla::MallocSizeOf
58 #include <stddef.h> // size_t
59 #include <stdint.h> // uint8_t, uint32_t
61 #include "jstypes.h" // JS_PUBLIC_API
63 #include "js/CharacterEncoding.h" // JS::ConstUTF8CharsZ
64 #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin
65 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
66 # include "js/Prefs.h" // JS::Prefs::*
67 #endif
68 #include "js/TypeDecls.h" // JS::MutableHandle (fwd)
70 namespace js {
71 class FrontendContext;
72 } // namespace js
74 namespace JS {
75 using FrontendContext = js::FrontendContext;
77 enum class AsmJSOption : uint8_t {
78 Enabled,
79 DisabledByAsmJSPref,
80 DisabledByLinker,
81 DisabledByNoWasmCompiler,
82 DisabledByDebugger,
85 #define FOREACH_DELAZIFICATION_STRATEGY(_) \
86 /* Do not delazify anything eagerly. */ \
87 _(OnDemandOnly) \
89 /* \
90 * Compare the stencil produced by concurrent depth first delazification and \
91 * on-demand delazification. Any differences would crash SpiderMonkey with \
92 * an assertion. \
93 */ \
94 _(CheckConcurrentWithOnDemand) \
96 /* \
97 * Delazifiy functions in a depth first traversal of the functions. \
98 */ \
99 _(ConcurrentDepthFirst) \
101 /* \
102 * Delazifiy functions strating with the largest function first. \
103 */ \
104 _(ConcurrentLargeFirst) \
106 /* \
107 * Parse everything eagerly, from the first parse. \
109 * NOTE: Either the Realm configuration or specialized VM operating modes \
110 * may disallow syntax-parse altogether. These conditions are checked in the \
111 * CompileOptions constructor. \
112 */ \
113 _(ParseEverythingEagerly)
115 enum class DelazificationOption : uint8_t {
116 #define _ENUM_ENTRY(Name) Name,
117 FOREACH_DELAZIFICATION_STRATEGY(_ENUM_ENTRY)
118 #undef _ENUM_ENTRY
121 class JS_PUBLIC_API InstantiateOptions;
122 class JS_PUBLIC_API ReadOnlyDecodeOptions;
124 // Compilation-specific part of JS::ContextOptions which is supposed to be
125 // configured by user prefs.
126 class JS_PUBLIC_API PrefableCompileOptions {
127 public:
128 PrefableCompileOptions()
129 : importAttributes_(false),
130 sourcePragmas_(true),
131 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
132 explicitResourceManagement_(
133 JS::Prefs::experimental_explicit_resource_management()),
134 #endif
135 throwOnAsmJSValidationFailure_(false) {
138 bool importAttributes() const { return importAttributes_; }
139 PrefableCompileOptions& setImportAttributes(bool enabled) {
140 importAttributes_ = enabled;
141 return *this;
144 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
145 bool explicitResourceManagement() const {
146 return explicitResourceManagement_;
148 PrefableCompileOptions& setExplicitResourceManagement(bool enabled) {
149 explicitResourceManagement_ = enabled;
150 return *this;
152 #endif
154 // Enable/disable support for parsing '//(#@) source(Mapping)?URL=' pragmas.
155 bool sourcePragmas() const { return sourcePragmas_; }
156 PrefableCompileOptions& setSourcePragmas(bool flag) {
157 sourcePragmas_ = flag;
158 return *this;
161 AsmJSOption asmJSOption() const { return asmJSOption_; }
162 PrefableCompileOptions& setAsmJS(bool flag) {
163 asmJSOption_ =
164 flag ? AsmJSOption::Enabled : AsmJSOption::DisabledByAsmJSPref;
165 return *this;
167 PrefableCompileOptions& setAsmJSOption(AsmJSOption option) {
168 asmJSOption_ = option;
169 return *this;
172 bool throwOnAsmJSValidationFailure() const {
173 return throwOnAsmJSValidationFailure_;
175 PrefableCompileOptions& setThrowOnAsmJSValidationFailure(bool flag) {
176 throwOnAsmJSValidationFailure_ = flag;
177 return *this;
179 PrefableCompileOptions& toggleThrowOnAsmJSValidationFailure() {
180 throwOnAsmJSValidationFailure_ = !throwOnAsmJSValidationFailure_;
181 return *this;
184 #if defined(DEBUG) || defined(JS_JITSPEW)
185 template <typename Printer>
186 void dumpWith(Printer& print) const {
187 # define PrintFields_(Name) print(#Name, Name)
188 PrintFields_(importAttributes_);
189 PrintFields_(sourcePragmas_);
190 PrintFields_(throwOnAsmJSValidationFailure_);
191 # ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
192 PrintFields_(explicitResourceManagement_);
193 # endif
194 # undef PrintFields_
196 switch (asmJSOption_) {
197 case AsmJSOption::Enabled:
198 print("asmJSOption_", "AsmJSOption::Enabled");
199 break;
200 case AsmJSOption::DisabledByAsmJSPref:
201 print("asmJSOption_", "AsmJSOption::DisabledByAsmJSPref");
202 break;
203 case AsmJSOption::DisabledByLinker:
204 print("asmJSOption_", "AsmJSOption::DisabledByLinker");
205 break;
206 case AsmJSOption::DisabledByNoWasmCompiler:
207 print("asmJSOption_", "AsmJSOption::DisabledByNoWasmCompiler");
208 break;
209 case AsmJSOption::DisabledByDebugger:
210 print("asmJSOption_", "AsmJSOption::DisabledByDebugger");
211 break;
214 #endif // defined(DEBUG) || defined(JS_JITSPEW)
216 private:
217 // ==== Syntax-related options. ====
218 bool importAttributes_ : 1;
220 // The context has specified that source pragmas should be parsed.
221 bool sourcePragmas_ : 1;
223 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
224 // The context has specified that explicit resource management syntax
225 // should be parsed.
226 bool explicitResourceManagement_ : 1;
227 #endif
229 // ==== asm.js options. ====
230 bool throwOnAsmJSValidationFailure_ : 1;
232 AsmJSOption asmJSOption_ = AsmJSOption::DisabledByAsmJSPref;
236 * The common base class for the CompileOptions hierarchy.
238 * Use this in code that needs to propagate compile options from one
239 * compilation unit to another.
241 class JS_PUBLIC_API TransitiveCompileOptions {
242 friend class JS_PUBLIC_API ReadOnlyDecodeOptions;
244 protected:
245 // non-POD options:
247 JS::ConstUTF8CharsZ filename_;
249 JS::ConstUTF8CharsZ introducerFilename_;
251 const char16_t* sourceMapURL_ = nullptr;
253 // POD options:
254 // WARNING: When adding new fields, don't forget to add them to
255 // copyPODTransitiveOptions.
258 * The Web Platform allows scripts to be loaded from arbitrary cross-origin
259 * sources. This allows an attack by which a malicious website loads a
260 * sensitive file (say, a bank statement) cross-origin (using the user's
261 * cookies), and sniffs the generated syntax errors (via a window.onerror
262 * handler) for juicy morsels of its contents.
264 * To counter this attack, HTML5 specifies that script errors should be
265 * sanitized ("muted") when the script is not same-origin with the global
266 * for which it is loaded. Callers should set this flag for cross-origin
267 * scripts, and it will be propagated appropriately to child scripts and
268 * passed back in JSErrorReports.
270 bool mutedErrors_ = false;
272 // Either the Realm configuration or the compile request may force
273 // strict-mode.
274 bool forceStrictMode_ = false;
276 // The Realm of this script is configured to use fdlibm math library.
277 bool alwaysUseFdlibm_ = false;
279 // Flag used to bypass the filename validation callback.
280 // See also SetFilenameValidationCallback.
281 bool skipFilenameValidation_ = false;
283 bool hideScriptFromDebugger_ = false;
285 // If set, this script will be hidden from the debugger. The requirement
286 // is that once compilation is finished, a call to UpdateDebugMetadata will
287 // be made, which will update the SSO with the appropiate debug metadata,
288 // and expose the script to the debugger (if hideScriptFromDebugger_ isn't
289 // set)
290 bool deferDebugMetadata_ = false;
292 // Off-thread delazification strategy is used to tell off-thread tasks how the
293 // delazification should be performed. Multiple strategies are available in
294 // order to test different approaches to the concurrent delazification.
295 DelazificationOption eagerDelazificationStrategy_ =
296 DelazificationOption::OnDemandOnly;
298 friend class JS_PUBLIC_API InstantiateOptions;
300 public:
301 bool selfHostingMode = false;
302 bool discardSource = false;
303 bool sourceIsLazy = false;
304 bool allowHTMLComments = true;
305 bool nonSyntacticScope = false;
307 // Top-level await is enabled by default but is not supported for chrome
308 // modules loaded with ChromeUtils.importModule.
309 bool topLevelAwait = true;
311 // When decoding from XDR into a Stencil, directly reference data in the
312 // buffer (where possible) instead of copying it. This is an optional
313 // performance optimization, and may also reduce memory if the buffer is going
314 // remain alive anyways.
316 // NOTE: The XDR buffer must remain alive as long as the Stencil does. Special
317 // care must be taken that there are no addition shared references to
318 // the Stencil.
320 // NOTE: Instantiated GC things may still outlive the buffer as long as the
321 // Stencil was cleaned up. This is covers a typical case where a decoded
322 // Stencil is instantiated once and then thrown away.
323 bool borrowBuffer = false;
325 // Similar to `borrowBuffer`, but additionally the JSRuntime may directly
326 // reference data in the buffer for JS bytecode. The `borrowBuffer` flag must
327 // be set if this is set. This can be a memory optimization in multi-process
328 // architectures where a (read-only) XDR buffer is mapped into multiple
329 // processes.
331 // NOTE: When using this mode, the XDR buffer must live until JS_Shutdown is
332 // called. There is currently no mechanism to release the data sooner.
333 bool usePinnedBytecode = false;
335 PrefableCompileOptions prefableOptions_;
338 * |introductionType| is a statically allocated C string. See JSScript.h
339 * for more information.
341 const char* introductionType = nullptr;
343 unsigned introductionLineno = 0;
344 uint32_t introductionOffset = 0;
345 bool hasIntroductionInfo = false;
347 // WARNING: When adding new fields, don't forget to add them to
348 // copyPODTransitiveOptions.
350 protected:
351 TransitiveCompileOptions() = default;
353 // Set all POD options (those not requiring reference counts, copies,
354 // rooting, or other hand-holding) to their values in |rhs|.
355 void copyPODTransitiveOptions(const TransitiveCompileOptions& rhs);
357 bool isEagerDelazificationEqualTo(DelazificationOption val) const {
358 return eagerDelazificationStrategy() == val;
361 template <DelazificationOption... Values>
362 bool eagerDelazificationIsOneOf() const {
363 return (isEagerDelazificationEqualTo(Values) || ...);
366 public:
367 // Read-only accessors for non-POD options. The proper way to set these
368 // depends on the derived type.
369 bool mutedErrors() const { return mutedErrors_; }
370 bool alwaysUseFdlibm() const { return alwaysUseFdlibm_; }
371 bool forceFullParse() const {
372 return eagerDelazificationIsOneOf<
373 DelazificationOption::ParseEverythingEagerly>();
375 bool forceStrictMode() const { return forceStrictMode_; }
376 bool consumeDelazificationCache() const {
377 return eagerDelazificationIsOneOf<
378 DelazificationOption::ConcurrentDepthFirst,
379 DelazificationOption::ConcurrentLargeFirst>();
381 bool populateDelazificationCache() const {
382 return eagerDelazificationIsOneOf<
383 DelazificationOption::CheckConcurrentWithOnDemand,
384 DelazificationOption::ConcurrentDepthFirst,
385 DelazificationOption::ConcurrentLargeFirst>();
387 bool waitForDelazificationCache() const {
388 return eagerDelazificationIsOneOf<
389 DelazificationOption::CheckConcurrentWithOnDemand>();
391 bool checkDelazificationCache() const {
392 return eagerDelazificationIsOneOf<
393 DelazificationOption::CheckConcurrentWithOnDemand>();
395 DelazificationOption eagerDelazificationStrategy() const {
396 return eagerDelazificationStrategy_;
399 bool importAttributes() const { return prefableOptions_.importAttributes(); }
400 bool sourcePragmas() const { return prefableOptions_.sourcePragmas(); }
401 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
402 bool explicitResourceManagement() const {
403 return prefableOptions_.explicitResourceManagement();
405 #endif
406 bool throwOnAsmJSValidationFailure() const {
407 return prefableOptions_.throwOnAsmJSValidationFailure();
409 AsmJSOption asmJSOption() const { return prefableOptions_.asmJSOption(); }
410 void setAsmJSOption(AsmJSOption option) {
411 prefableOptions_.setAsmJSOption(option);
414 JS::ConstUTF8CharsZ filename() const { return filename_; }
415 JS::ConstUTF8CharsZ introducerFilename() const { return introducerFilename_; }
416 const char16_t* sourceMapURL() const { return sourceMapURL_; }
418 const PrefableCompileOptions& prefableOptions() const {
419 return prefableOptions_;
422 TransitiveCompileOptions(const TransitiveCompileOptions&) = delete;
423 TransitiveCompileOptions& operator=(const TransitiveCompileOptions&) = delete;
425 #if defined(DEBUG) || defined(JS_JITSPEW)
426 template <typename Printer>
427 void dumpWith(Printer& print) const {
428 # define PrintFields_(Name) print(#Name, Name)
429 PrintFields_(filename_);
430 PrintFields_(introducerFilename_);
431 PrintFields_(sourceMapURL_);
432 PrintFields_(mutedErrors_);
433 PrintFields_(forceStrictMode_);
434 PrintFields_(alwaysUseFdlibm_);
435 PrintFields_(skipFilenameValidation_);
436 PrintFields_(hideScriptFromDebugger_);
437 PrintFields_(deferDebugMetadata_);
438 PrintFields_(eagerDelazificationStrategy_);
439 PrintFields_(selfHostingMode);
440 PrintFields_(discardSource);
441 PrintFields_(sourceIsLazy);
442 PrintFields_(allowHTMLComments);
443 PrintFields_(nonSyntacticScope);
444 PrintFields_(topLevelAwait);
445 PrintFields_(borrowBuffer);
446 PrintFields_(usePinnedBytecode);
447 PrintFields_(introductionType);
448 PrintFields_(introductionLineno);
449 PrintFields_(introductionOffset);
450 PrintFields_(hasIntroductionInfo);
451 # undef PrintFields_
453 prefableOptions_.dumpWith(print);
455 #endif // defined(DEBUG) || defined(JS_JITSPEW)
459 * The class representing a full set of compile options.
461 * Use this in code that only needs to access compilation options created
462 * elsewhere, like the compiler. Don't instantiate this class (the constructor
463 * is protected anyway); instead, create instances only of the derived classes:
464 * CompileOptions and OwningCompileOptions.
466 class JS_PUBLIC_API ReadOnlyCompileOptions : public TransitiveCompileOptions {
467 public:
468 // POD options.
470 // Line number of the first character (1-origin).
471 uint32_t lineno = 1;
472 // Column number of the first character in UTF-16 code units.
473 JS::ColumnNumberOneOrigin column;
475 // The offset within the ScriptSource's full uncompressed text of the first
476 // character we're presenting for compilation with this CompileOptions.
478 // When we compile a lazy script, we pass the compiler only the substring of
479 // the source the lazy function occupies. With chunked decompression, we may
480 // not even have the complete uncompressed source present in memory. But parse
481 // node positions are offsets within the ScriptSource's full text, and
482 // BaseScript indicate their substring of the full source by its starting and
483 // ending offsets within the full text. This scriptSourceOffset field lets the
484 // frontend convert between these offsets and offsets within the substring
485 // presented for compilation.
486 unsigned scriptSourceOffset = 0;
488 // These only apply to non-function scripts.
489 bool isRunOnce = false;
490 bool noScriptRval = false;
492 protected:
493 ReadOnlyCompileOptions() = default;
495 void copyPODNonTransitiveOptions(const ReadOnlyCompileOptions& rhs);
497 ReadOnlyCompileOptions(const ReadOnlyCompileOptions&) = delete;
498 ReadOnlyCompileOptions& operator=(const ReadOnlyCompileOptions&) = delete;
500 public:
501 #if defined(DEBUG) || defined(JS_JITSPEW)
502 template <typename Printer>
503 void dumpWith(Printer& print) const {
504 this->TransitiveCompileOptions::dumpWith(print);
505 # define PrintFields_(Name) print(#Name, Name)
506 PrintFields_(lineno);
507 print("column", column.oneOriginValue());
508 PrintFields_(scriptSourceOffset);
509 PrintFields_(isRunOnce);
510 PrintFields_(noScriptRval);
511 # undef PrintFields_
513 #endif // defined(DEBUG) || defined(JS_JITSPEW)
516 class JS_PUBLIC_API OwningDecodeOptions;
519 * Compilation options, with dynamic lifetime. An instance of this type
520 * makes a copy of / holds / roots all dynamically allocated resources
521 * (principals; elements; strings) that it refers to. Its destructor frees
522 * / drops / unroots them. This is heavier than CompileOptions, below, but
523 * unlike CompileOptions, it can outlive any given stack frame.
525 * Note that this *roots* any JS values it refers to - they're live
526 * unconditionally. Thus, instances of this type can't be owned, directly
527 * or indirectly, by a JavaScript object: if any value that this roots ever
528 * comes to refer to the object that owns this, then the whole cycle, and
529 * anything else it entrains, will never be freed.
531 class JS_PUBLIC_API OwningCompileOptions final : public ReadOnlyCompileOptions {
532 public:
533 // A minimal constructor, for use with OwningCompileOptions::copy.
534 explicit OwningCompileOptions(JSContext* cx);
536 struct ForFrontendContext {};
537 explicit OwningCompileOptions(const ForFrontendContext&)
538 : ReadOnlyCompileOptions() {}
540 ~OwningCompileOptions();
542 private:
543 template <typename ContextT>
544 bool copyImpl(ContextT* cx, const ReadOnlyCompileOptions& rhs);
546 public:
547 /** Set this to a copy of |rhs|. Return false on OOM. */
548 bool copy(JSContext* cx, const ReadOnlyCompileOptions& rhs);
549 bool copy(JS::FrontendContext* fc, const ReadOnlyCompileOptions& rhs);
551 void steal(OwningCompileOptions&& rhs);
552 void steal(OwningDecodeOptions&& rhs);
554 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
556 OwningCompileOptions& setIsRunOnce(bool once) {
557 isRunOnce = once;
558 return *this;
561 OwningCompileOptions& setForceStrictMode() {
562 forceStrictMode_ = true;
563 return *this;
566 OwningCompileOptions& setModule() {
567 // ES6 10.2.1 Module code is always strict mode code.
568 setForceStrictMode();
569 setIsRunOnce(true);
570 allowHTMLComments = false;
571 return *this;
574 private:
575 void release();
577 OwningCompileOptions(const OwningCompileOptions&) = delete;
578 OwningCompileOptions& operator=(const OwningCompileOptions&) = delete;
582 * Compilation options stored on the stack. An instance of this type
583 * simply holds references to dynamically allocated resources (element;
584 * filename; source map URL) that are owned by something else. If you
585 * create an instance of this type, it's up to you to guarantee that
586 * everything you store in it will outlive it.
588 class MOZ_STACK_CLASS JS_PUBLIC_API CompileOptions final
589 : public ReadOnlyCompileOptions {
590 public:
591 // Default options determined using the JSContext.
592 explicit CompileOptions(JSContext* cx);
594 // Copy both the transitive and the non-transitive options from another
595 // options object.
596 CompileOptions(JSContext* cx, const ReadOnlyCompileOptions& rhs)
597 : ReadOnlyCompileOptions() {
598 copyPODNonTransitiveOptions(rhs);
599 copyPODTransitiveOptions(rhs);
601 filename_ = rhs.filename();
602 introducerFilename_ = rhs.introducerFilename();
603 sourceMapURL_ = rhs.sourceMapURL();
606 // Construct a CompileOption in the context where JSContext is not available.
607 // prefableOptions should reflect the compilation-specific user prefs.
608 explicit CompileOptions(const PrefableCompileOptions& prefableOptions)
609 : ReadOnlyCompileOptions() {
610 prefableOptions_ = prefableOptions;
613 CompileOptions& setFile(const char* f) {
614 filename_ = JS::ConstUTF8CharsZ(f);
615 return *this;
618 CompileOptions& setLine(uint32_t l) {
619 lineno = l;
620 return *this;
623 CompileOptions& setFileAndLine(const char* f, uint32_t l) {
624 filename_ = JS::ConstUTF8CharsZ(f);
625 lineno = l;
626 return *this;
629 CompileOptions& setSourceMapURL(const char16_t* s) {
630 sourceMapURL_ = s;
631 return *this;
634 CompileOptions& setMutedErrors(bool mute) {
635 mutedErrors_ = mute;
636 return *this;
639 CompileOptions& setColumn(JS::ColumnNumberOneOrigin c) {
640 column = c;
641 return *this;
644 CompileOptions& setScriptSourceOffset(unsigned o) {
645 scriptSourceOffset = o;
646 return *this;
649 CompileOptions& setIsRunOnce(bool once) {
650 isRunOnce = once;
651 return *this;
654 CompileOptions& setNoScriptRval(bool nsr) {
655 noScriptRval = nsr;
656 return *this;
659 CompileOptions& setSkipFilenameValidation(bool b) {
660 skipFilenameValidation_ = b;
661 return *this;
664 CompileOptions& setSelfHostingMode(bool shm) {
665 selfHostingMode = shm;
666 return *this;
669 CompileOptions& setSourceIsLazy(bool l) {
670 sourceIsLazy = l;
671 return *this;
674 CompileOptions& setNonSyntacticScope(bool n) {
675 nonSyntacticScope = n;
676 return *this;
679 CompileOptions& setIntroductionType(const char* t) {
680 introductionType = t;
681 return *this;
684 CompileOptions& setDeferDebugMetadata(bool v = true) {
685 deferDebugMetadata_ = v;
686 return *this;
689 CompileOptions& setHideScriptFromDebugger(bool v = true) {
690 hideScriptFromDebugger_ = v;
691 return *this;
694 CompileOptions& setIntroductionInfo(const char* introducerFn,
695 const char* intro, uint32_t line,
696 uint32_t offset) {
697 introducerFilename_ = JS::ConstUTF8CharsZ(introducerFn);
698 introductionType = intro;
699 introductionLineno = line;
700 introductionOffset = offset;
701 hasIntroductionInfo = true;
702 return *this;
705 // Set introduction information according to any currently executing script.
706 CompileOptions& setIntroductionInfoToCaller(
707 JSContext* cx, const char* introductionType,
708 JS::MutableHandle<JSScript*> introductionScript);
710 CompileOptions& setDiscardSource() {
711 discardSource = true;
712 return *this;
715 CompileOptions& setForceFullParse() {
716 eagerDelazificationStrategy_ = DelazificationOption::ParseEverythingEagerly;
717 return *this;
720 void warnAboutConflictingDelazification() const;
721 CompileOptions& setEagerDelazificationStrategy(
722 DelazificationOption strategy) {
723 const auto PEE = DelazificationOption::ParseEverythingEagerly;
724 if (eagerDelazificationStrategy_ == PEE && strategy != PEE) {
725 // Parse Everything Eagerly cannot be replaced, do noting.
726 warnAboutConflictingDelazification();
727 return *this;
730 eagerDelazificationStrategy_ = strategy;
731 return *this;
734 CompileOptions& setForceStrictMode() {
735 forceStrictMode_ = true;
736 return *this;
739 CompileOptions& setModule() {
740 // ES6 10.2.1 Module code is always strict mode code.
741 setForceStrictMode();
742 setIsRunOnce(true);
743 allowHTMLComments = false;
744 return *this;
747 CompileOptions(const CompileOptions& rhs) = delete;
748 CompileOptions& operator=(const CompileOptions& rhs) = delete;
752 * Subset of CompileOptions fields used while instantiating Stencils.
754 class JS_PUBLIC_API InstantiateOptions {
755 public:
756 bool skipFilenameValidation = false;
757 bool hideScriptFromDebugger = false;
758 bool deferDebugMetadata = false;
760 DelazificationOption eagerDelazificationStrategy_ =
761 DelazificationOption::OnDemandOnly;
763 InstantiateOptions();
765 explicit InstantiateOptions(const ReadOnlyCompileOptions& options)
766 : skipFilenameValidation(options.skipFilenameValidation_),
767 hideScriptFromDebugger(options.hideScriptFromDebugger_),
768 deferDebugMetadata(options.deferDebugMetadata_),
769 eagerDelazificationStrategy_(options.eagerDelazificationStrategy()) {}
771 void copyTo(CompileOptions& options) const {
772 options.skipFilenameValidation_ = skipFilenameValidation;
773 options.hideScriptFromDebugger_ = hideScriptFromDebugger;
774 options.deferDebugMetadata_ = deferDebugMetadata;
775 options.setEagerDelazificationStrategy(eagerDelazificationStrategy_);
778 bool hideFromNewScriptInitial() const {
779 return deferDebugMetadata || hideScriptFromDebugger;
782 #ifdef DEBUG
783 // Assert that all fields have default value.
785 // This can be used when instantiation is performed as separate step than
786 // compile-to-stencil, and CompileOptions isn't available there.
787 void assertDefault() const {
788 MOZ_ASSERT(skipFilenameValidation == false);
789 MOZ_ASSERT(hideScriptFromDebugger == false);
790 MOZ_ASSERT(deferDebugMetadata == false);
791 MOZ_ASSERT(eagerDelazificationStrategy_ ==
792 DelazificationOption::OnDemandOnly);
795 // Assert that all fields have values compatible with the default value.
797 // This can be used in the same way as assertDefault, in case the
798 // setForceFullParse() is used on the original compile options.
799 void assertCompatibleWithDefault() const {
800 MOZ_ASSERT(skipFilenameValidation == false);
801 MOZ_ASSERT(hideScriptFromDebugger == false);
802 MOZ_ASSERT(deferDebugMetadata == false);
804 // The instantiation step uses the eagerDelazificationStrategy_ field
805 // only for TransitiveCompileOptions::populateDelazificationCache().
807 // Both the default OnDemandOnly and
808 // the ParseEverythingEagerly from setForceFullParse() returns
809 // false, and they're are compatible.
810 MOZ_ASSERT(eagerDelazificationStrategy_ ==
811 DelazificationOption::OnDemandOnly ||
812 eagerDelazificationStrategy_ ==
813 DelazificationOption::ParseEverythingEagerly);
815 #endif
819 * Subset of CompileOptions fields used while decoding Stencils.
821 class JS_PUBLIC_API ReadOnlyDecodeOptions {
822 public:
823 bool borrowBuffer = false;
824 bool usePinnedBytecode = false;
826 protected:
827 JS::ConstUTF8CharsZ introducerFilename_;
829 public:
830 // See `TransitiveCompileOptions::introductionType` field for details.
831 const char* introductionType = nullptr;
833 uint32_t introductionLineno = 0;
834 uint32_t introductionOffset = 0;
836 protected:
837 ReadOnlyDecodeOptions() = default;
839 ReadOnlyDecodeOptions(const ReadOnlyDecodeOptions&) = delete;
840 ReadOnlyDecodeOptions& operator=(const ReadOnlyDecodeOptions&) = delete;
842 template <typename T>
843 void copyPODOptionsFrom(const T& options) {
844 borrowBuffer = options.borrowBuffer;
845 usePinnedBytecode = options.usePinnedBytecode;
846 introductionType = options.introductionType;
847 introductionLineno = options.introductionLineno;
848 introductionOffset = options.introductionOffset;
851 template <typename T>
852 void copyPODOptionsTo(T& options) const {
853 options.borrowBuffer = borrowBuffer;
854 options.usePinnedBytecode = usePinnedBytecode;
855 options.introductionType = introductionType;
856 options.introductionLineno = introductionLineno;
857 options.introductionOffset = introductionOffset;
860 public:
861 void copyTo(CompileOptions& options) const {
862 copyPODOptionsTo(options);
863 options.introducerFilename_ = introducerFilename_;
866 JS::ConstUTF8CharsZ introducerFilename() const { return introducerFilename_; }
869 class MOZ_STACK_CLASS JS_PUBLIC_API DecodeOptions final
870 : public ReadOnlyDecodeOptions {
871 public:
872 DecodeOptions() = default;
874 explicit DecodeOptions(const ReadOnlyCompileOptions& options) {
875 copyPODOptionsFrom(options);
877 introducerFilename_ = options.introducerFilename();
881 class JS_PUBLIC_API OwningDecodeOptions final : public ReadOnlyDecodeOptions {
882 friend class OwningCompileOptions;
884 public:
885 OwningDecodeOptions() = default;
887 ~OwningDecodeOptions();
889 bool copy(JS::FrontendContext* maybeFc, const ReadOnlyDecodeOptions& rhs);
890 void infallibleCopy(const ReadOnlyDecodeOptions& rhs);
892 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
894 private:
895 void release();
897 OwningDecodeOptions(const OwningDecodeOptions&) = delete;
898 OwningDecodeOptions& operator=(const OwningDecodeOptions&) = delete;
901 } // namespace JS
903 #endif /* js_CompileOptions_h */