GetWorkletBootstrapRuntimeModule.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author sheo13666q
  4. */
  5. "use strict";
  6. const RuntimeGlobals = require("../RuntimeGlobals");
  7. const RuntimeModule = require("../RuntimeModule");
  8. const Template = require("../Template");
  9. /** @import Compilation from "../Compilation" */
  10. /**
  11. * Provides a single object URL (one per base URI) for the worklet bootstrap
  12. * script. A worklet global scope has no `self` and no `location`; this script
  13. * sets them up before the emitted chunks — which assume a worker-like scope —
  14. * are added via `addModule`. Deduping by base URI avoids leaking a new object
  15. * URL per worklet.
  16. */
  17. class GetWorkletBootstrapRuntimeModule extends RuntimeModule {
  18. constructor() {
  19. super("get worklet bootstrap", RuntimeModule.STAGE_ATTACH);
  20. }
  21. /**
  22. * Returns true, if the runtime module should get it's own scope.
  23. * When false, `generate()` must emit complete statements ending with `;`
  24. * so a following runtime IIFE is not parsed as a call (ASI).
  25. * @returns {boolean} true, if the runtime module should get it's own scope
  26. */
  27. shouldIsolate() {
  28. return false;
  29. }
  30. /**
  31. * Generates runtime code for this runtime module.
  32. * @returns {string | null} runtime code
  33. */
  34. generate() {
  35. const { getWorkletBootstrap, baseURI } = RuntimeGlobals;
  36. const { runtimeTemplate } = /** @type {Compilation} */ (this.compilation);
  37. // The arrow inside the blob string is fine — it runs in the worklet (always
  38. // a module scope); the surrounding functions must respect `output.environment`.
  39. const getter = runtimeTemplate.basicFunction("", [
  40. `var base = ${baseURI};`,
  41. "if (!cache.has(base)) {",
  42. Template.indent([
  43. "var script = [",
  44. Template.indent([
  45. // worklet scopes have no `self`; chunks assume a worker-like scope.
  46. // `||=` is newer than worklets themselves, so it stays gated.
  47. `${JSON.stringify(
  48. `${runtimeTemplate.assignOr("globalThis.self", "globalThis")};`
  49. )},`,
  50. // some runtime modules read `location`; forward the document base
  51. '"globalThis.location = " + JSON.stringify(base) + ";"'
  52. ]),
  53. '].join("\\n");',
  54. 'cache.set(base, URL.createObjectURL(new Blob([script], { type: "text/javascript" })));'
  55. ]),
  56. "}",
  57. "return cache.get(base);"
  58. ]);
  59. return `${getWorkletBootstrap} = (${runtimeTemplate.basicFunction("", [
  60. "var cache = new Map();",
  61. `return ${getter};`
  62. ])})();`;
  63. }
  64. }
  65. module.exports = GetWorkletBootstrapRuntimeModule;