CompileOptions.h (32523B)
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/. */ 5 6 /* 7 * Options for JavaScript compilation. 8 * 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. 17 * 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. 23 * 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. 27 * 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. 31 * 32 * So we have a class hierarchy that reflects these four use cases: 33 * 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. 37 * 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. 42 * 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. 46 * 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. 50 */ 51 52 #ifndef js_CompileOptions_h 53 #define js_CompileOptions_h 54 55 #include "mozilla/Assertions.h" // MOZ_ASSERT 56 #include "mozilla/MemoryReporting.h" // mozilla::MallocSizeOf 57 58 #include <stddef.h> // size_t 59 #include <stdint.h> // uint8_t, uint32_t 60 61 #include "jstypes.h" // JS_PUBLIC_API 62 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) 69 70 namespace js { 71 class FrontendContext; 72 } // namespace js 73 74 namespace JS { 75 using FrontendContext = js::FrontendContext; 76 77 enum class AsmJSOption : uint8_t { 78 Enabled, 79 DisabledByAsmJSPref, 80 DisabledByLinker, 81 DisabledByNoWasmCompiler, 82 DisabledByDebugger, 83 }; 84 85 #define FOREACH_DELAZIFICATION_STRATEGY(_) \ 86 /* Do not delazify anything eagerly. */ \ 87 _(OnDemandOnly) \ 88 \ 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) \ 95 \ 96 /* \ 97 * Delazifiy functions in a depth first traversal of the functions. \ 98 */ \ 99 _(ConcurrentDepthFirst) \ 100 \ 101 /* \ 102 * Delazifiy functions strating with the largest function first. \ 103 */ \ 104 _(ConcurrentLargeFirst) \ 105 \ 106 /* \ 107 * Parse everything eagerly, from the first parse. \ 108 * \ 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) 114 115 enum class DelazificationOption : uint8_t { 116 #define _ENUM_ENTRY(Name) Name, 117 FOREACH_DELAZIFICATION_STRATEGY(_ENUM_ENTRY) 118 #undef _ENUM_ENTRY 119 }; 120 121 enum class EagerBaselineOption : uint8_t { None, JitHints, Aggressive }; 122 123 class JS_PUBLIC_API InstantiateOptions; 124 class JS_PUBLIC_API ReadOnlyDecodeOptions; 125 126 // Compilation-specific part of JS::ContextOptions which is supposed to be 127 // configured by user prefs. 128 class JS_PUBLIC_API PrefableCompileOptions { 129 public: 130 PrefableCompileOptions() 131 : sourcePragmas_(true), 132 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 133 explicitResourceManagement_( 134 JS::Prefs::experimental_explicit_resource_management()), 135 #endif 136 throwOnAsmJSValidationFailure_(false) { 137 } 138 139 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 140 bool explicitResourceManagement() const { 141 return explicitResourceManagement_; 142 } 143 PrefableCompileOptions& setExplicitResourceManagement(bool enabled) { 144 explicitResourceManagement_ = enabled; 145 return *this; 146 } 147 #endif 148 149 // Enable/disable support for parsing '//(#@) source(Mapping)?URL=' pragmas. 150 bool sourcePragmas() const { return sourcePragmas_; } 151 PrefableCompileOptions& setSourcePragmas(bool flag) { 152 sourcePragmas_ = flag; 153 return *this; 154 } 155 156 AsmJSOption asmJSOption() const { return asmJSOption_; } 157 PrefableCompileOptions& setAsmJS(bool flag) { 158 asmJSOption_ = 159 flag ? AsmJSOption::Enabled : AsmJSOption::DisabledByAsmJSPref; 160 return *this; 161 } 162 PrefableCompileOptions& setAsmJSOption(AsmJSOption option) { 163 asmJSOption_ = option; 164 return *this; 165 } 166 167 bool throwOnAsmJSValidationFailure() const { 168 return throwOnAsmJSValidationFailure_; 169 } 170 PrefableCompileOptions& setThrowOnAsmJSValidationFailure(bool flag) { 171 throwOnAsmJSValidationFailure_ = flag; 172 return *this; 173 } 174 PrefableCompileOptions& toggleThrowOnAsmJSValidationFailure() { 175 throwOnAsmJSValidationFailure_ = !throwOnAsmJSValidationFailure_; 176 return *this; 177 } 178 179 #if defined(DEBUG) || defined(JS_JITSPEW) 180 template <typename Printer> 181 void dumpWith(Printer& print) const { 182 # define PrintFields_(Name) print(#Name, Name) 183 PrintFields_(sourcePragmas_); 184 PrintFields_(throwOnAsmJSValidationFailure_); 185 # ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 186 PrintFields_(explicitResourceManagement_); 187 # endif 188 # undef PrintFields_ 189 190 switch (asmJSOption_) { 191 case AsmJSOption::Enabled: 192 print("asmJSOption_", "AsmJSOption::Enabled"); 193 break; 194 case AsmJSOption::DisabledByAsmJSPref: 195 print("asmJSOption_", "AsmJSOption::DisabledByAsmJSPref"); 196 break; 197 case AsmJSOption::DisabledByLinker: 198 print("asmJSOption_", "AsmJSOption::DisabledByLinker"); 199 break; 200 case AsmJSOption::DisabledByNoWasmCompiler: 201 print("asmJSOption_", "AsmJSOption::DisabledByNoWasmCompiler"); 202 break; 203 case AsmJSOption::DisabledByDebugger: 204 print("asmJSOption_", "AsmJSOption::DisabledByDebugger"); 205 break; 206 } 207 } 208 #endif // defined(DEBUG) || defined(JS_JITSPEW) 209 210 private: 211 // ==== Syntax-related options. ==== 212 213 // The context has specified that source pragmas should be parsed. 214 bool sourcePragmas_ : 1; 215 216 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 217 // The context has specified that explicit resource management syntax 218 // should be parsed. 219 bool explicitResourceManagement_ : 1; 220 #endif 221 222 // ==== asm.js options. ==== 223 bool throwOnAsmJSValidationFailure_ : 1; 224 225 AsmJSOption asmJSOption_ = AsmJSOption::DisabledByAsmJSPref; 226 }; 227 228 /** 229 * The common base class for the CompileOptions hierarchy. 230 * 231 * Use this in code that needs to propagate compile options from one 232 * compilation unit to another. 233 */ 234 class JS_PUBLIC_API TransitiveCompileOptions { 235 friend class JS_PUBLIC_API ReadOnlyDecodeOptions; 236 237 protected: 238 // non-POD options: 239 240 JS::ConstUTF8CharsZ filename_; 241 242 JS::ConstUTF8CharsZ introducerFilename_; 243 244 const char16_t* sourceMapURL_ = nullptr; 245 246 // POD options: 247 // WARNING: When adding new fields, don't forget to add them to 248 // copyPODTransitiveOptions. 249 250 /** 251 * The Web Platform allows scripts to be loaded from arbitrary cross-origin 252 * sources. This allows an attack by which a malicious website loads a 253 * sensitive file (say, a bank statement) cross-origin (using the user's 254 * cookies), and sniffs the generated syntax errors (via a window.onerror 255 * handler) for juicy morsels of its contents. 256 * 257 * To counter this attack, HTML5 specifies that script errors should be 258 * sanitized ("muted") when the script is not same-origin with the global 259 * for which it is loaded. Callers should set this flag for cross-origin 260 * scripts, and it will be propagated appropriately to child scripts and 261 * passed back in JSErrorReports. 262 */ 263 bool mutedErrors_ = false; 264 265 // Either the Realm configuration or the compile request may force 266 // strict-mode. 267 bool forceStrictMode_ = false; 268 269 // The Realm of this script is configured to use fdlibm math library. 270 bool alwaysUseFdlibm_ = false; 271 272 // Flag used to bypass the filename validation callback. 273 // See also SetFilenameValidationCallback. 274 bool skipFilenameValidation_ = false; 275 276 bool hideScriptFromDebugger_ = false; 277 278 // If set, this script will be hidden from the debugger. The requirement 279 // is that once compilation is finished, a call to UpdateDebugMetadata will 280 // be made, which will update the SSO with the appropiate debug metadata, 281 // and expose the script to the debugger (if hideScriptFromDebugger_ isn't 282 // set) 283 bool deferDebugMetadata_ = false; 284 285 // Off-thread delazification strategy is used to tell off-thread tasks how the 286 // delazification should be performed. Multiple strategies are available in 287 // order to test different approaches to the concurrent delazification. 288 DelazificationOption eagerDelazificationStrategy_ = 289 DelazificationOption::OnDemandOnly; 290 291 // The eager baseline strategy option indicates whether functions should be 292 // OMT baseline compiled eagerly whenever bytecode is available and whether 293 // JitHints should be used or not. Eager baseline compilations are not 294 // currently enabled for delazifications, and explicitly set to None for 295 // delazifications. 296 EagerBaselineOption eagerBaselineStrategy_ = EagerBaselineOption::None; 297 298 friend class JS_PUBLIC_API InstantiateOptions; 299 300 public: 301 bool selfHostingMode = false; 302 bool discardSource = false; 303 bool sourceIsLazy = false; 304 bool allowHTMLComments = true; 305 bool nonSyntacticScope = false; 306 307 // Top-level await is enabled by default but is not supported for chrome 308 // modules loaded with ChromeUtils.importModule. 309 bool topLevelAwait = true; 310 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. 315 // 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. 319 // 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; 324 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. 330 // 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; 334 335 PrefableCompileOptions prefableOptions_; 336 337 /** 338 * |introductionType| is a statically allocated C string. See JSScript.h 339 * for more information. 340 */ 341 const char* introductionType = nullptr; 342 343 unsigned introductionLineno = 0; 344 uint32_t introductionOffset = 0; 345 bool hasIntroductionInfo = false; 346 347 // WARNING: When adding new fields, don't forget to add them to 348 // copyPODTransitiveOptions. 349 350 protected: 351 TransitiveCompileOptions() = default; 352 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); 356 357 bool isEagerDelazificationEqualTo(DelazificationOption val) const { 358 return eagerDelazificationStrategy() == val; 359 } 360 361 template <DelazificationOption... Values> 362 bool eagerDelazificationIsOneOf() const { 363 return (isEagerDelazificationEqualTo(Values) || ...); 364 } 365 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>(); 374 } 375 bool forceStrictMode() const { return forceStrictMode_; } 376 bool consumeDelazificationCache() const { 377 return eagerDelazificationIsOneOf< 378 DelazificationOption::ConcurrentDepthFirst, 379 DelazificationOption::ConcurrentLargeFirst>(); 380 } 381 bool populateDelazificationCache() const { 382 return eagerDelazificationIsOneOf< 383 DelazificationOption::CheckConcurrentWithOnDemand, 384 DelazificationOption::ConcurrentDepthFirst, 385 DelazificationOption::ConcurrentLargeFirst>(); 386 } 387 bool waitForDelazificationCache() const { 388 return eagerDelazificationIsOneOf< 389 DelazificationOption::CheckConcurrentWithOnDemand>(); 390 } 391 bool checkDelazificationCache() const { 392 return eagerDelazificationIsOneOf< 393 DelazificationOption::CheckConcurrentWithOnDemand>(); 394 } 395 DelazificationOption eagerDelazificationStrategy() const { 396 return eagerDelazificationStrategy_; 397 } 398 EagerBaselineOption eagerBaselineStrategy() const { 399 return eagerBaselineStrategy_; 400 } 401 402 bool sourcePragmas() const { return prefableOptions_.sourcePragmas(); } 403 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT 404 bool explicitResourceManagement() const { 405 return prefableOptions_.explicitResourceManagement(); 406 } 407 #endif 408 bool throwOnAsmJSValidationFailure() const { 409 return prefableOptions_.throwOnAsmJSValidationFailure(); 410 } 411 AsmJSOption asmJSOption() const { return prefableOptions_.asmJSOption(); } 412 void setAsmJSOption(AsmJSOption option) { 413 prefableOptions_.setAsmJSOption(option); 414 } 415 416 JS::ConstUTF8CharsZ filename() const { return filename_; } 417 JS::ConstUTF8CharsZ introducerFilename() const { return introducerFilename_; } 418 const char16_t* sourceMapURL() const { return sourceMapURL_; } 419 420 const PrefableCompileOptions& prefableOptions() const { 421 return prefableOptions_; 422 } 423 424 TransitiveCompileOptions(const TransitiveCompileOptions&) = delete; 425 TransitiveCompileOptions& operator=(const TransitiveCompileOptions&) = delete; 426 427 #if defined(DEBUG) || defined(JS_JITSPEW) 428 template <typename Printer> 429 void dumpWith(Printer& print) const { 430 # define PrintFields_(Name) print(#Name, Name) 431 PrintFields_(filename_); 432 PrintFields_(introducerFilename_); 433 PrintFields_(sourceMapURL_); 434 PrintFields_(mutedErrors_); 435 PrintFields_(forceStrictMode_); 436 PrintFields_(alwaysUseFdlibm_); 437 PrintFields_(skipFilenameValidation_); 438 PrintFields_(hideScriptFromDebugger_); 439 PrintFields_(deferDebugMetadata_); 440 PrintFields_(eagerDelazificationStrategy_); 441 PrintFields_(eagerBaselineStrategy_); 442 PrintFields_(selfHostingMode); 443 PrintFields_(discardSource); 444 PrintFields_(sourceIsLazy); 445 PrintFields_(allowHTMLComments); 446 PrintFields_(nonSyntacticScope); 447 PrintFields_(topLevelAwait); 448 PrintFields_(borrowBuffer); 449 PrintFields_(usePinnedBytecode); 450 PrintFields_(introductionType); 451 PrintFields_(introductionLineno); 452 PrintFields_(introductionOffset); 453 PrintFields_(hasIntroductionInfo); 454 # undef PrintFields_ 455 456 prefableOptions_.dumpWith(print); 457 } 458 #endif // defined(DEBUG) || defined(JS_JITSPEW) 459 }; 460 461 /** 462 * The class representing a full set of compile options. 463 * 464 * Use this in code that only needs to access compilation options created 465 * elsewhere, like the compiler. Don't instantiate this class (the constructor 466 * is protected anyway); instead, create instances only of the derived classes: 467 * CompileOptions and OwningCompileOptions. 468 */ 469 class JS_PUBLIC_API ReadOnlyCompileOptions : public TransitiveCompileOptions { 470 public: 471 // POD options. 472 473 // Line number of the first character (1-origin). 474 uint32_t lineno = 1; 475 // Column number of the first character in UTF-16 code units. 476 JS::ColumnNumberOneOrigin column; 477 478 // The offset within the ScriptSource's full uncompressed text of the first 479 // character we're presenting for compilation with this CompileOptions. 480 // 481 // When we compile a lazy script, we pass the compiler only the substring of 482 // the source the lazy function occupies. With chunked decompression, we may 483 // not even have the complete uncompressed source present in memory. But parse 484 // node positions are offsets within the ScriptSource's full text, and 485 // BaseScript indicate their substring of the full source by its starting and 486 // ending offsets within the full text. This scriptSourceOffset field lets the 487 // frontend convert between these offsets and offsets within the substring 488 // presented for compilation. 489 unsigned scriptSourceOffset = 0; 490 491 // These only apply to non-function scripts. 492 bool isRunOnce = false; 493 bool noScriptRval = false; 494 495 protected: 496 ReadOnlyCompileOptions() = default; 497 498 void copyPODNonTransitiveOptions(const ReadOnlyCompileOptions& rhs); 499 500 ReadOnlyCompileOptions(const ReadOnlyCompileOptions&) = delete; 501 ReadOnlyCompileOptions& operator=(const ReadOnlyCompileOptions&) = delete; 502 503 public: 504 #if defined(DEBUG) || defined(JS_JITSPEW) 505 template <typename Printer> 506 void dumpWith(Printer& print) const { 507 this->TransitiveCompileOptions::dumpWith(print); 508 # define PrintFields_(Name) print(#Name, Name) 509 PrintFields_(lineno); 510 print("column", column.oneOriginValue()); 511 PrintFields_(scriptSourceOffset); 512 PrintFields_(isRunOnce); 513 PrintFields_(noScriptRval); 514 # undef PrintFields_ 515 } 516 #endif // defined(DEBUG) || defined(JS_JITSPEW) 517 }; 518 519 class JS_PUBLIC_API OwningDecodeOptions; 520 521 /** 522 * Compilation options, with dynamic lifetime. An instance of this type 523 * makes a copy of / holds / roots all dynamically allocated resources 524 * (principals; elements; strings) that it refers to. Its destructor frees 525 * / drops / unroots them. This is heavier than CompileOptions, below, but 526 * unlike CompileOptions, it can outlive any given stack frame. 527 * 528 * Note that this *roots* any JS values it refers to - they're live 529 * unconditionally. Thus, instances of this type can't be owned, directly 530 * or indirectly, by a JavaScript object: if any value that this roots ever 531 * comes to refer to the object that owns this, then the whole cycle, and 532 * anything else it entrains, will never be freed. 533 */ 534 class JS_PUBLIC_API OwningCompileOptions final : public ReadOnlyCompileOptions { 535 public: 536 // A minimal constructor, for use with OwningCompileOptions::copy. 537 explicit OwningCompileOptions(JSContext* cx); 538 539 struct ForFrontendContext {}; 540 explicit OwningCompileOptions(const ForFrontendContext&) 541 : ReadOnlyCompileOptions() {} 542 543 ~OwningCompileOptions(); 544 545 private: 546 template <typename ContextT> 547 bool copyImpl(ContextT* cx, const ReadOnlyCompileOptions& rhs); 548 549 public: 550 /** Set this to a copy of |rhs|. Return false on OOM. */ 551 bool copy(JSContext* cx, const ReadOnlyCompileOptions& rhs); 552 bool copy(JS::FrontendContext* fc, const ReadOnlyCompileOptions& rhs); 553 554 void steal(OwningCompileOptions&& rhs); 555 void steal(OwningDecodeOptions&& rhs); 556 557 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; 558 559 OwningCompileOptions& setIsRunOnce(bool once) { 560 isRunOnce = once; 561 return *this; 562 } 563 564 OwningCompileOptions& setForceStrictMode() { 565 forceStrictMode_ = true; 566 return *this; 567 } 568 569 OwningCompileOptions& setModule() { 570 // ES6 10.2.1 Module code is always strict mode code. 571 setForceStrictMode(); 572 setIsRunOnce(true); 573 allowHTMLComments = false; 574 return *this; 575 } 576 577 private: 578 void release(); 579 580 OwningCompileOptions(const OwningCompileOptions&) = delete; 581 OwningCompileOptions& operator=(const OwningCompileOptions&) = delete; 582 }; 583 584 /** 585 * Compilation options stored on the stack. An instance of this type 586 * simply holds references to dynamically allocated resources (element; 587 * filename; source map URL) that are owned by something else. If you 588 * create an instance of this type, it's up to you to guarantee that 589 * everything you store in it will outlive it. 590 */ 591 class MOZ_STACK_CLASS JS_PUBLIC_API CompileOptions final 592 : public ReadOnlyCompileOptions { 593 public: 594 // Default options determined using the JSContext. 595 explicit CompileOptions(JSContext* cx); 596 597 // Copy both the transitive and the non-transitive options from another 598 // options object. 599 CompileOptions(JSContext* cx, const ReadOnlyCompileOptions& rhs) 600 : ReadOnlyCompileOptions() { 601 copyPODNonTransitiveOptions(rhs); 602 copyPODTransitiveOptions(rhs); 603 604 filename_ = rhs.filename(); 605 introducerFilename_ = rhs.introducerFilename(); 606 sourceMapURL_ = rhs.sourceMapURL(); 607 } 608 609 // Construct a CompileOption in the context where JSContext is not available. 610 // prefableOptions should reflect the compilation-specific user prefs. 611 explicit CompileOptions(const PrefableCompileOptions& prefableOptions) 612 : ReadOnlyCompileOptions() { 613 prefableOptions_ = prefableOptions; 614 } 615 616 CompileOptions& setFile(const char* f) { 617 filename_ = JS::ConstUTF8CharsZ(f); 618 return *this; 619 } 620 621 CompileOptions& setLine(uint32_t l) { 622 lineno = l; 623 return *this; 624 } 625 626 CompileOptions& setFileAndLine(const char* f, uint32_t l) { 627 filename_ = JS::ConstUTF8CharsZ(f); 628 lineno = l; 629 return *this; 630 } 631 632 CompileOptions& setSourceMapURL(const char16_t* s) { 633 sourceMapURL_ = s; 634 return *this; 635 } 636 637 CompileOptions& setMutedErrors(bool mute) { 638 mutedErrors_ = mute; 639 return *this; 640 } 641 642 CompileOptions& setColumn(JS::ColumnNumberOneOrigin c) { 643 column = c; 644 return *this; 645 } 646 647 CompileOptions& setScriptSourceOffset(unsigned o) { 648 scriptSourceOffset = o; 649 return *this; 650 } 651 652 CompileOptions& setIsRunOnce(bool once) { 653 isRunOnce = once; 654 return *this; 655 } 656 657 CompileOptions& setNoScriptRval(bool nsr) { 658 noScriptRval = nsr; 659 return *this; 660 } 661 662 CompileOptions& setSkipFilenameValidation(bool b) { 663 skipFilenameValidation_ = b; 664 return *this; 665 } 666 667 CompileOptions& setSelfHostingMode(bool shm) { 668 selfHostingMode = shm; 669 return *this; 670 } 671 672 CompileOptions& setSourceIsLazy(bool l) { 673 sourceIsLazy = l; 674 return *this; 675 } 676 677 CompileOptions& setNonSyntacticScope(bool n) { 678 nonSyntacticScope = n; 679 return *this; 680 } 681 682 CompileOptions& setIntroductionType(const char* t) { 683 introductionType = t; 684 return *this; 685 } 686 687 CompileOptions& setDeferDebugMetadata(bool v = true) { 688 deferDebugMetadata_ = v; 689 return *this; 690 } 691 692 CompileOptions& setHideScriptFromDebugger(bool v = true) { 693 hideScriptFromDebugger_ = v; 694 return *this; 695 } 696 697 CompileOptions& setIntroductionInfo(const char* introducerFn, 698 const char* intro, uint32_t line, 699 uint32_t offset) { 700 introducerFilename_ = JS::ConstUTF8CharsZ(introducerFn); 701 introductionType = intro; 702 introductionLineno = line; 703 introductionOffset = offset; 704 hasIntroductionInfo = true; 705 return *this; 706 } 707 708 // Set introduction information according to any currently executing script. 709 CompileOptions& setIntroductionInfoToCaller( 710 JSContext* cx, const char* introductionType, 711 JS::MutableHandle<JSScript*> introductionScript); 712 713 CompileOptions& setDiscardSource() { 714 discardSource = true; 715 return *this; 716 } 717 718 CompileOptions& setForceFullParse() { 719 eagerDelazificationStrategy_ = DelazificationOption::ParseEverythingEagerly; 720 return *this; 721 } 722 723 void warnAboutConflictingDelazification() const; 724 CompileOptions& setEagerDelazificationStrategy( 725 DelazificationOption strategy) { 726 const auto PEE = DelazificationOption::ParseEverythingEagerly; 727 if (eagerDelazificationStrategy_ == PEE && strategy != PEE) { 728 // Parse Everything Eagerly cannot be replaced, do noting. 729 warnAboutConflictingDelazification(); 730 return *this; 731 } 732 733 eagerDelazificationStrategy_ = strategy; 734 return *this; 735 } 736 737 CompileOptions& setEagerBaselineStrategy(EagerBaselineOption strategy) { 738 eagerBaselineStrategy_ = strategy; 739 return *this; 740 } 741 742 CompileOptions& setForceStrictMode() { 743 forceStrictMode_ = true; 744 return *this; 745 } 746 747 CompileOptions& setModule() { 748 // ES6 10.2.1 Module code is always strict mode code. 749 setForceStrictMode(); 750 setIsRunOnce(true); 751 allowHTMLComments = false; 752 return *this; 753 } 754 755 CompileOptions(const CompileOptions& rhs) = delete; 756 CompileOptions& operator=(const CompileOptions& rhs) = delete; 757 }; 758 759 /** 760 * Subset of CompileOptions fields used while instantiating Stencils. 761 */ 762 class JS_PUBLIC_API InstantiateOptions { 763 public: 764 bool skipFilenameValidation = false; 765 bool hideScriptFromDebugger = false; 766 bool deferDebugMetadata = false; 767 DelazificationOption eagerDelazificationStrategy_ = 768 DelazificationOption::OnDemandOnly; 769 770 EagerBaselineOption eagerBaselineStrategy_ = EagerBaselineOption::None; 771 772 InstantiateOptions(); 773 774 explicit InstantiateOptions(const ReadOnlyCompileOptions& options) 775 : skipFilenameValidation(options.skipFilenameValidation_), 776 hideScriptFromDebugger(options.hideScriptFromDebugger_), 777 deferDebugMetadata(options.deferDebugMetadata_), 778 eagerDelazificationStrategy_(options.eagerDelazificationStrategy()), 779 eagerBaselineStrategy_(options.eagerBaselineStrategy_) {} 780 781 void copyTo(CompileOptions& options) const { 782 options.skipFilenameValidation_ = skipFilenameValidation; 783 options.hideScriptFromDebugger_ = hideScriptFromDebugger; 784 options.deferDebugMetadata_ = deferDebugMetadata; 785 options.setEagerDelazificationStrategy(eagerDelazificationStrategy_); 786 options.setEagerBaselineStrategy(eagerBaselineStrategy_); 787 } 788 789 bool hideFromNewScriptInitial() const { 790 return deferDebugMetadata || hideScriptFromDebugger; 791 } 792 793 #ifdef DEBUG 794 // Assert that all fields have default value. 795 // 796 // This can be used when instantiation is performed as separate step than 797 // compile-to-stencil, and CompileOptions isn't available there. 798 void assertDefault() const { 799 MOZ_ASSERT(skipFilenameValidation == false); 800 MOZ_ASSERT(hideScriptFromDebugger == false); 801 MOZ_ASSERT(deferDebugMetadata == false); 802 MOZ_ASSERT(eagerDelazificationStrategy_ == 803 DelazificationOption::OnDemandOnly); 804 MOZ_ASSERT(eagerBaselineStrategy_ == EagerBaselineOption::None); 805 } 806 807 // Assert that all fields have values compatible with the default value. 808 // 809 // This can be used in the same way as assertDefault, in case the 810 // setForceFullParse() is used on the original compile options. 811 void assertCompatibleWithDefault() const { 812 MOZ_ASSERT(skipFilenameValidation == false); 813 MOZ_ASSERT(hideScriptFromDebugger == false); 814 MOZ_ASSERT(deferDebugMetadata == false); 815 816 // The instantiation step uses the eagerDelazificationStrategy_ field 817 // only for TransitiveCompileOptions::populateDelazificationCache(). 818 // 819 // Both the default OnDemandOnly and 820 // the ParseEverythingEagerly from setForceFullParse() returns 821 // false, and they're are compatible. 822 MOZ_ASSERT(eagerDelazificationStrategy_ == 823 DelazificationOption::OnDemandOnly || 824 eagerDelazificationStrategy_ == 825 DelazificationOption::ParseEverythingEagerly); 826 827 MOZ_ASSERT(eagerBaselineStrategy_ == EagerBaselineOption::None); 828 } 829 #endif 830 }; 831 832 /** 833 * Subset of CompileOptions fields used while decoding Stencils. 834 */ 835 class JS_PUBLIC_API ReadOnlyDecodeOptions { 836 public: 837 bool borrowBuffer = false; 838 bool usePinnedBytecode = false; 839 840 protected: 841 JS::ConstUTF8CharsZ introducerFilename_; 842 843 public: 844 // See `TransitiveCompileOptions::introductionType` field for details. 845 const char* introductionType = nullptr; 846 847 uint32_t introductionLineno = 0; 848 uint32_t introductionOffset = 0; 849 850 protected: 851 ReadOnlyDecodeOptions() = default; 852 853 ReadOnlyDecodeOptions(const ReadOnlyDecodeOptions&) = delete; 854 ReadOnlyDecodeOptions& operator=(const ReadOnlyDecodeOptions&) = delete; 855 856 template <typename T> 857 void copyPODOptionsFrom(const T& options) { 858 borrowBuffer = options.borrowBuffer; 859 usePinnedBytecode = options.usePinnedBytecode; 860 introductionType = options.introductionType; 861 introductionLineno = options.introductionLineno; 862 introductionOffset = options.introductionOffset; 863 } 864 865 template <typename T> 866 void copyPODOptionsTo(T& options) const { 867 options.borrowBuffer = borrowBuffer; 868 options.usePinnedBytecode = usePinnedBytecode; 869 options.introductionType = introductionType; 870 options.introductionLineno = introductionLineno; 871 options.introductionOffset = introductionOffset; 872 } 873 874 public: 875 void copyTo(CompileOptions& options) const { 876 copyPODOptionsTo(options); 877 options.introducerFilename_ = introducerFilename_; 878 } 879 880 JS::ConstUTF8CharsZ introducerFilename() const { return introducerFilename_; } 881 }; 882 883 class MOZ_STACK_CLASS JS_PUBLIC_API DecodeOptions final 884 : public ReadOnlyDecodeOptions { 885 public: 886 DecodeOptions() = default; 887 888 explicit DecodeOptions(const ReadOnlyCompileOptions& options) { 889 copyPODOptionsFrom(options); 890 891 introducerFilename_ = options.introducerFilename(); 892 } 893 }; 894 895 class JS_PUBLIC_API OwningDecodeOptions final : public ReadOnlyDecodeOptions { 896 friend class OwningCompileOptions; 897 898 public: 899 OwningDecodeOptions() = default; 900 901 ~OwningDecodeOptions(); 902 903 bool copy(JS::FrontendContext* maybeFc, const ReadOnlyDecodeOptions& rhs); 904 void infallibleCopy(const ReadOnlyDecodeOptions& rhs); 905 906 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; 907 908 private: 909 void release(); 910 911 OwningDecodeOptions(const OwningDecodeOptions&) = delete; 912 OwningDecodeOptions& operator=(const OwningDecodeOptions&) = delete; 913 }; 914 915 } // namespace JS 916 917 #endif /* js_CompileOptions_h */