@metamask/snaps-execution-environments 0.31.0 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/browserify/iframe/bundle.js +6435 -0
  2. package/dist/{webpack → browserify}/iframe/index.html +1411 -178
  3. package/dist/browserify/node-process/bundle.js +15135 -0
  4. package/dist/browserify/node-thread/bundle.js +15135 -0
  5. package/dist/browserify/offscreen/bundle.js +2266 -0
  6. package/dist/{webpack → browserify}/offscreen/index.html +1411 -178
  7. package/dist/common/endowments/commonEndowmentFactory.d.ts +1 -0
  8. package/dist/common/endowments/commonEndowmentFactory.js +9 -3
  9. package/dist/common/endowments/commonEndowmentFactory.js.map +1 -1
  10. package/dist/common/endowments/index.d.ts +0 -7
  11. package/dist/common/endowments/index.js +4 -24
  12. package/dist/common/endowments/index.js.map +1 -1
  13. package/dist/common/lockdown/lockdown-events.d.ts +4 -0
  14. package/dist/common/lockdown/lockdown-events.js +60 -0
  15. package/dist/common/lockdown/lockdown-events.js.map +1 -0
  16. package/dist/iframe/index.js +3 -2
  17. package/dist/iframe/index.js.map +1 -1
  18. package/dist/node-process/index.js +1 -2
  19. package/dist/node-process/index.js.map +1 -1
  20. package/dist/node-thread/index.js +1 -2
  21. package/dist/node-thread/index.js.map +1 -1
  22. package/dist/offscreen/index.js +3 -2
  23. package/dist/offscreen/index.js.map +1 -1
  24. package/package.json +18 -18
  25. package/dist/webpack/iframe/bundle.js +0 -2
  26. package/dist/webpack/iframe/bundle.js.LICENSE.txt +0 -14
  27. package/dist/webpack/node-process/bundle.js +0 -111579
  28. package/dist/webpack/node-process/lockdown.umd.min.js +0 -1
  29. package/dist/webpack/node-thread/bundle.js +0 -111579
  30. package/dist/webpack/node-thread/lockdown.umd.min.js +0 -1
  31. package/dist/webpack/offscreen/bundle.js +0 -2
  32. package/dist/webpack/offscreen/bundle.js.LICENSE.txt +0 -12
@@ -1,31 +1,122 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8">
5
- <title>MetaMask Snaps Execution Environment</title>
6
- <meta name="viewport" content="width=device-width, initial-scale=1"></head>
7
- <body>
8
- <script>/******/ (() => { // webpackBootstrap
9
- /******/ "use strict";
10
- /******/ // The require scope
11
- /******/ var __webpack_require__ = {};
12
- /******/
13
- /************************************************************************/
14
- /******/ /* webpack/runtime/make namespace object */
15
- /******/ (() => {
16
- /******/ // define __esModule on exports
17
- /******/ __webpack_require__.r = (exports) => {
18
- /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
19
- /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
20
- /******/ }
21
- /******/ Object.defineProperty(exports, '__esModule', { value: true });
22
- /******/ };
23
- /******/ })();
24
- /******/
25
- /************************************************************************/
26
- var __webpack_exports__ = {};
27
- __webpack_require__.r(__webpack_exports__);
28
1
 
2
+ <!DOCTYPE html>
3
+ <html>
4
+ <head>
5
+ <meta charset="utf-8" />
6
+ <title>MetaMask Snaps Iframe Execution Environment</title>
7
+ <script>;(function() {
8
+ // this runtime template code is destined to wrap LavaMoat entirely,
9
+ // therefore this is our way of capturing access to basic APIs LavaMoat
10
+ // uses to still be accessible only to LavaMoat after scuttling occurs
11
+ const {
12
+ RegExp,
13
+ Reflect,
14
+ Object,
15
+ Error,
16
+ Array,
17
+ Set,
18
+ Math,
19
+ Date,
20
+ console,
21
+ } = globalThis
22
+
23
+ const moduleRegistry = new Map()
24
+ const lavamoatPolicy = { resources: {} }
25
+ const debugMode = false
26
+ const statsMode = false
27
+
28
+ // initialize the kernel
29
+ const reportStatsHook = statsMode ? (function makeInitStatsHook ({ onStatsReady }) {
30
+ let statModuleStack = []
31
+ return reportStatsHook
32
+
33
+ function reportStatsHook (event, moduleId) {
34
+ if (event === 'start') {
35
+ // record start
36
+ const startTime = Date.now()
37
+ // console.log(`loaded module ${moduleId}`)
38
+ const statRecord = {
39
+ 'name': moduleId,
40
+ 'value': null,
41
+ 'children': [],
42
+ 'startTime': startTime,
43
+ 'endTime': null,
44
+ }
45
+ // add as child to current
46
+ if (statModuleStack.length > 0) {
47
+ const currentStat = statModuleStack[statModuleStack.length - 1]
48
+ currentStat.children.push(statRecord)
49
+ }
50
+ // set as current
51
+ statModuleStack.push(statRecord)
52
+ } else if (event === 'end') {
53
+ const endTime = Date.now()
54
+ const currentStat = statModuleStack[statModuleStack.length - 1]
55
+ // sanity check, should only get an end for the current top of stack
56
+ if (currentStat.name !== moduleId) {
57
+ console.error(`stats hook misaligned "${currentStat.name}", "${moduleId}" ${statModuleStack.map(e => e.name).join()}`)
58
+ }
59
+ currentStat.endTime = endTime
60
+ const startTime = currentStat.startTime
61
+ const duration = endTime - startTime
62
+ currentStat.value = duration
63
+ // console.log(`loaded module ${moduleId} in ${duration}ms`)
64
+ // check if totally done
65
+ if (statModuleStack.length === 1) {
66
+ currentStat.version = 1
67
+ onStatsReady(currentStat)
68
+ }
69
+ statModuleStack.pop()
70
+ }
71
+ }
72
+
73
+ })({ onStatsReady }) : () => {}
74
+ const createKernel = // LavaMoat Prelude
75
+ (function () {
76
+ return createKernel
77
+
78
+ function createKernel ({
79
+ lavamoatConfig,
80
+ loadModuleData,
81
+ getRelativeModuleId,
82
+ prepareModuleInitializerArgs,
83
+ getExternalCompartment,
84
+ globalThisRefs,
85
+ runWithPrecompiledModules,
86
+ reportStatsHook,
87
+ }) {
88
+ // debug options are hard-coded at build time
89
+ const {
90
+ debugMode,
91
+ } = {"debugMode":false}
92
+ // security options are hard-coded at build time
93
+ const {
94
+ scuttleGlobalThis,
95
+ scuttleGlobalThisExceptions,
96
+ } = {"scuttleGlobalThis":true,"scuttleGlobalThisExceptions":["postMessage","removeEventListener"]}
97
+
98
+ // identify the globalRef
99
+ const globalRef = (typeof globalThis !== 'undefined') ? globalThis : (typeof self !== 'undefined') ? self : (typeof global !== 'undefined') ? global : undefined
100
+ if (!globalRef) {
101
+ throw new Error('Lavamoat - unable to identify globalRef')
102
+ }
103
+
104
+ // polyfill globalThis
105
+ if (globalRef && !globalRef.globalThis) {
106
+ globalRef.globalThis = globalRef
107
+ }
108
+
109
+ // create the SES rootRealm
110
+ // "templateRequire" calls are inlined in "generateKernel"
111
+ // load-bearing semi-colon, do not remove
112
+ ;// define ses
113
+ (function(){
114
+ const global = globalRef
115
+ const exports = {}
116
+ const module = { exports }
117
+ ;(function(){
118
+ // START of injected code from ses
119
+ 'use strict';
29
120
  (() => {
30
121
  const functors = [
31
122
  // === functors[0] ===
@@ -594,7 +685,7 @@ freeze(bestEffortStringify);
594
685
  */
595
686
 
596
687
  /**
597
- * @typedef {object} AssertMakeErrorOptions
688
+ * @typedef {Object} AssertMakeErrorOptions
598
689
  * @property {string=} errorName
599
690
  */
600
691
 
@@ -641,65 +732,51 @@ freeze(bestEffortStringify);
641
732
  */
642
733
 
643
734
  // Type all the overloads of the assertTypeof function.
644
- // There may eventually be a better way to do this, but
645
- // thems the breaks with Typescript 4.0.
735
+ // There may eventually be a better way to do this, but they break with
736
+ // Typescript 4.0.
646
737
  /**
647
738
  * @callback AssertTypeofBigint
648
739
  * @param {any} specimen
649
740
  * @param {'bigint'} typename
650
741
  * @param {Details=} optDetails
651
742
  * @returns {asserts specimen is bigint}
652
- */
653
-
654
- /**
743
+ *
655
744
  * @callback AssertTypeofBoolean
656
745
  * @param {any} specimen
657
746
  * @param {'boolean'} typename
658
747
  * @param {Details=} optDetails
659
748
  * @returns {asserts specimen is boolean}
660
- */
661
-
662
- /**
749
+ *
663
750
  * @callback AssertTypeofFunction
664
751
  * @param {any} specimen
665
752
  * @param {'function'} typename
666
753
  * @param {Details=} optDetails
667
754
  * @returns {asserts specimen is Function}
668
- */
669
-
670
- /**
755
+ *
671
756
  * @callback AssertTypeofNumber
672
757
  * @param {any} specimen
673
758
  * @param {'number'} typename
674
759
  * @param {Details=} optDetails
675
760
  * @returns {asserts specimen is number}
676
- */
677
-
678
- /**
761
+ *
679
762
  * @callback AssertTypeofObject
680
763
  * @param {any} specimen
681
764
  * @param {'object'} typename
682
765
  * @param {Details=} optDetails
683
766
  * @returns {asserts specimen is Record<any, any> | null}
684
- */
685
-
686
- /**
767
+ *
687
768
  * @callback AssertTypeofString
688
769
  * @param {any} specimen
689
770
  * @param {'string'} typename
690
771
  * @param {Details=} optDetails
691
772
  * @returns {asserts specimen is string}
692
- */
693
-
694
- /**
773
+ *
695
774
  * @callback AssertTypeofSymbol
696
775
  * @param {any} specimen
697
776
  * @param {'symbol'} typename
698
777
  * @param {Details=} optDetails
699
778
  * @returns {asserts specimen is symbol}
700
- */
701
-
702
- /**
779
+ *
703
780
  * @callback AssertTypeofUndefined
704
781
  * @param {any} specimen
705
782
  * @param {'undefined'} typename
@@ -753,7 +830,7 @@ freeze(bestEffortStringify);
753
830
  */
754
831
 
755
832
  /**
756
- * @typedef {object} StringablePayload
833
+ * @typedef {Object} StringablePayload
757
834
  * Holds the payload passed to quote so that its printed form is visible.
758
835
  * @property {() => string} toString How to print the payload
759
836
  */
@@ -2420,8 +2497,10 @@ const makeSafeEvaluator= ({
2420
2497
 
2421
2498
 
2422
2499
  const provideCompartmentEvaluator= (compartmentFields, options)=> {
2423
- const { sloppyGlobalsMode= false, __moduleShimLexicals__= undefined}=
2424
- options;
2500
+ const {
2501
+ sloppyGlobalsMode= false,
2502
+ __moduleShimLexicals__= undefined}=
2503
+ options;
2425
2504
 
2426
2505
  let safeEvaluate;
2427
2506
 
@@ -4214,7 +4293,7 @@ $h‍_once.makeAlias(makeAlias);const resolveAll=(imports,resolveHook,fullReferr
4214
4293
  return freeze(resolvedImports);
4215
4294
  };
4216
4295
 
4217
- const loadRecord= (
4296
+ const loadRecord= async(
4218
4297
  compartmentPrivateFields,
4219
4298
  moduleAliases,
4220
4299
  compartment,
@@ -4335,64 +4414,27 @@ const loadWithoutErrorAnnotation= async(
4335
4414
  } in compartment ${q(compartment.name)}`;
4336
4415
  }
4337
4416
 
4338
- // check if record is a RedirectStaticModuleInterface
4339
- if( staticModuleRecord.specifier!== undefined) {
4340
- // check if this redirect with an explicit record
4341
- if( staticModuleRecord.record!== undefined) {
4342
- // ensure expected record shape
4343
- if( staticModuleRecord.compartment!== undefined) {
4344
- throw new TypeError(
4345
- 'Cannot redirect to an explicit record with a specified compartment');
4346
-
4347
- }
4348
- const {
4349
- compartment: aliasCompartment= compartment,
4350
- specifier: aliasSpecifier= moduleSpecifier,
4351
- record: aliasModuleRecord,
4352
- importMeta}=
4353
- staticModuleRecord;
4354
-
4355
- const aliasRecord= loadRecord(
4356
- compartmentPrivateFields,
4357
- moduleAliases,
4358
- aliasCompartment,
4359
- aliasSpecifier,
4360
- aliasModuleRecord,
4361
- pendingJobs,
4362
- moduleLoads,
4363
- errors,
4364
- importMeta);
4365
-
4366
- mapSet(moduleRecords, moduleSpecifier, aliasRecord);
4367
- return aliasRecord;
4368
- }
4369
-
4370
- // check if this redirect with an explicit compartment
4371
- if( staticModuleRecord.compartment!== undefined) {
4372
- // ensure expected record shape
4373
- if( staticModuleRecord.importMeta!== undefined) {
4374
- throw new TypeError(
4375
- 'Cannot redirect to an implicit record with a specified importMeta');
4376
-
4377
- }
4378
- // Behold: recursion.
4379
- // eslint-disable-next-line no-use-before-define
4380
- const aliasRecord= await memoizedLoadWithErrorAnnotation(
4381
- compartmentPrivateFields,
4382
- moduleAliases,
4383
- staticModuleRecord.compartment,
4384
- staticModuleRecord.specifier,
4385
- pendingJobs,
4386
- moduleLoads,
4387
- errors);
4388
-
4389
- mapSet(moduleRecords, moduleSpecifier, aliasRecord);
4390
- return aliasRecord;
4391
- }
4417
+ if( staticModuleRecord.record!== undefined) {
4418
+ const {
4419
+ compartment: aliasCompartment= compartment,
4420
+ specifier: aliasSpecifier= moduleSpecifier,
4421
+ record: aliasModuleRecord,
4422
+ importMeta}=
4423
+ staticModuleRecord;
4392
4424
 
4393
- throw new TypeError(
4394
- 'Unnexpected RedirectStaticModuleInterface record shape');
4425
+ const aliasRecord= await loadRecord(
4426
+ compartmentPrivateFields,
4427
+ moduleAliases,
4428
+ aliasCompartment,
4429
+ aliasSpecifier,
4430
+ aliasModuleRecord,
4431
+ pendingJobs,
4432
+ moduleLoads,
4433
+ errors,
4434
+ importMeta);
4395
4435
 
4436
+ mapSet(moduleRecords, moduleSpecifier, aliasRecord);
4437
+ return aliasRecord;
4396
4438
  }
4397
4439
 
4398
4440
  return loadRecord(
@@ -4835,7 +4877,6 @@ $h‍_once.makeThirdPartyModuleInstance(makeThirdPartyModuleInstance);const make
4835
4877
  __syncModuleProgram__: functorSource,
4836
4878
  __fixedExportMap__: fixedExportMap= {},
4837
4879
  __liveExportMap__: liveExportMap= {},
4838
- __reexportMap__: reexportMap= {},
4839
4880
  __needsImportMeta__: needsImportMeta= false}=
4840
4881
  staticModuleRecord;
4841
4882
 
@@ -5089,35 +5130,26 @@ $h‍_once.makeThirdPartyModuleInstance(makeThirdPartyModuleInstance);const make
5089
5130
  }
5090
5131
  if( arrayIncludes(exportAlls, specifier)) {
5091
5132
  // Make all these imports candidates.
5092
- // Note names don't change in reexporting all
5093
- for( const [importAndExportName, importNotify]of entries(
5094
- importNotifiers))
5095
- {
5096
- if( candidateAll[importAndExportName]=== undefined) {
5097
- candidateAll[importAndExportName]= importNotify;
5133
+ for( const [importName, importNotify]of entries(importNotifiers)) {
5134
+ if( candidateAll[importName]=== undefined) {
5135
+ candidateAll[importName]= importNotify;
5098
5136
  }else {
5099
5137
  // Already a candidate: remove ambiguity.
5100
- candidateAll[importAndExportName]= false;
5138
+ candidateAll[importName]= false;
5101
5139
  }
5102
5140
  }
5103
5141
  }
5104
- if( reexportMap[specifier]) {
5105
- // Make named reexports candidates too.
5106
- for( const [localName, exportedName]of reexportMap[specifier]) {
5107
- candidateAll[exportedName]= importNotifiers[localName];
5108
- }
5109
- }
5110
5142
  }
5111
5143
 
5112
- for( const [exportName, notify]of entries(candidateAll)) {
5113
- if( !notifiers[exportName]&& notify!== false) {
5114
- notifiers[exportName]= notify;
5144
+ for( const [importName, notify]of entries(candidateAll)) {
5145
+ if( !notifiers[importName]&& notify!== false) {
5146
+ notifiers[importName]= notify;
5115
5147
 
5116
5148
  // exported live binding state
5117
5149
  let value;
5118
5150
  const update= (newValue)=> value= newValue;
5119
5151
  notify(update);
5120
- exportsProps[exportName]= {
5152
+ exportsProps[importName]= {
5121
5153
  get() {
5122
5154
  return value;
5123
5155
  },
@@ -5309,8 +5341,12 @@ const instantiate= (
5309
5341
  moduleAliases,
5310
5342
  moduleRecord)=>
5311
5343
  {
5312
- const { compartment, moduleSpecifier, resolvedImports, staticModuleRecord}=
5313
- moduleRecord;
5344
+ const {
5345
+ compartment,
5346
+ moduleSpecifier,
5347
+ resolvedImports,
5348
+ staticModuleRecord}=
5349
+ moduleRecord;
5314
5350
  const { instances}= weakmapGet(compartmentPrivateFields, compartment);
5315
5351
 
5316
5352
  // Memoize.
@@ -6563,8 +6599,12 @@ freeze(ErrorInfo);
6563
6599
 
6564
6600
  /** @type {MakeCausalConsole} */
6565
6601
  const makeCausalConsole= (baseConsole, loggedErrorHandler)=> {
6566
- const { getStackString, tagError, takeMessageLogArgs, takeNoteLogArgsArray}=
6567
- loggedErrorHandler;
6602
+ const {
6603
+ getStackString,
6604
+ tagError,
6605
+ takeMessageLogArgs,
6606
+ takeNoteLogArgsArray}=
6607
+ loggedErrorHandler;
6568
6608
 
6569
6609
  /**
6570
6610
  * @param {ReadonlyArray<any>} logArgs
@@ -7678,10 +7718,8 @@ const getAnonymousIntrinsics= ()=> {
7678
7718
 
7679
7719
  // 9.2.4.1 %ThrowTypeError%
7680
7720
 
7681
- const ThrowTypeError= getOwnPropertyDescriptor(
7682
- makeArguments(),
7683
- 'callee').
7684
- get;
7721
+ const ThrowTypeError= getOwnPropertyDescriptor(makeArguments(), 'callee').
7722
+ get;
7685
7723
 
7686
7724
  // 21.1.5.2 The %StringIteratorPrototype% Object
7687
7725
 
@@ -8183,8 +8221,7 @@ function tameDomains(domainTaming= 'safe') {
8183
8221
  })
8184
8222
  ,
8185
8223
  // === functors[36] ===
8186
- (({ imports: $h‍_imports, liveVar: $h‍_live, onceVar: $h‍_once, importMeta: $h‍____meta, }) => { let FERAL_FUNCTION,SyntaxError,TypeError,defineProperties,getPrototypeOf,setPrototypeOf,freeze;$h‍_imports([["./commons.js", [["FERAL_FUNCTION", [$h‍_a => (FERAL_FUNCTION = $h‍_a)]],["SyntaxError", [$h‍_a => (SyntaxError = $h‍_a)]],["TypeError", [$h‍_a => (TypeError = $h‍_a)]],["defineProperties", [$h‍_a => (defineProperties = $h‍_a)]],["getPrototypeOf", [$h‍_a => (getPrototypeOf = $h‍_a)]],["setPrototypeOf", [$h‍_a => (setPrototypeOf = $h‍_a)]],["freeze", [$h‍_a => (freeze = $h‍_a)]]]]]);
8187
-
8224
+ (({ imports: $h‍_imports, liveVar: $h‍_live, onceVar: $h‍_once, importMeta: $h‍____meta, }) => { let FERAL_FUNCTION,SyntaxError,TypeError,defineProperties,getPrototypeOf,setPrototypeOf;$h‍_imports([["./commons.js", [["FERAL_FUNCTION", [$h‍_a => (FERAL_FUNCTION = $h‍_a)]],["SyntaxError", [$h‍_a => (SyntaxError = $h‍_a)]],["TypeError", [$h‍_a => (TypeError = $h‍_a)]],["defineProperties", [$h‍_a => (defineProperties = $h‍_a)]],["getPrototypeOf", [$h‍_a => (getPrototypeOf = $h‍_a)]],["setPrototypeOf", [$h‍_a => (setPrototypeOf = $h‍_a)]]]]]);
8188
8225
 
8189
8226
 
8190
8227
 
@@ -8235,7 +8272,7 @@ function tameFunctionConstructors() {
8235
8272
  FERAL_FUNCTION.prototype.constructor('return 1');
8236
8273
  }catch( ignore) {
8237
8274
  // Throws, no need to patch.
8238
- return freeze({});
8275
+ return harden({});
8239
8276
  }
8240
8277
 
8241
8278
  const newIntrinsics= {};
@@ -8268,7 +8305,7 @@ function tameFunctionConstructors() {
8268
8305
  // Prevents the evaluation of source when calling constructor on the
8269
8306
  // prototype of functions.
8270
8307
  // eslint-disable-next-line func-names
8271
- const InertConstructor= function() {
8308
+ const InertConstructor= function() {
8272
8309
  throw new TypeError(
8273
8310
  'Function.prototype.constructor is not a valid constructor.');
8274
8311
 
@@ -8474,8 +8511,9 @@ function tameMathObject(mathTaming= 'safe') {
8474
8511
  const originalMath= Math;
8475
8512
  const initialMath= originalMath; // to follow the naming pattern
8476
8513
 
8477
- const { random: _, ...otherDescriptors}=
8478
- getOwnPropertyDescriptors(originalMath);
8514
+ const { random: _, ...otherDescriptors}= getOwnPropertyDescriptors(
8515
+ originalMath);
8516
+
8479
8517
 
8480
8518
  const sharedMath= create(objectPrototype, otherDescriptors);
8481
8519
 
@@ -9010,8 +9048,10 @@ const repairIntrinsics= (options= {})=> {
9010
9048
  // [`stackFiltering` options](https://github.com/Agoric/SES-shim/blob/master/packages/ses/lockdown-options.md#stackfiltering-options)
9011
9049
  // for an explanation.
9012
9050
 
9013
- const { getEnvironmentOption: getenv, getCapturedEnvironmentOptionNames}=
9014
- makeEnvironmentCaptor(globalThis);
9051
+ const {
9052
+ getEnvironmentOption: getenv,
9053
+ getCapturedEnvironmentOptionNames}=
9054
+ makeEnvironmentCaptor(globalThis);
9015
9055
 
9016
9056
  const {
9017
9057
  errorTaming= getenv('LOCKDOWN_ERROR_TAMING', 'safe'),
@@ -9117,8 +9157,11 @@ const repairIntrinsics= (options= {})=> {
9117
9157
 
9118
9158
  tameDomains(domainTaming);
9119
9159
 
9120
- const { addIntrinsics, completePrototypes, finalIntrinsics}=
9121
- makeIntrinsicsCollector();
9160
+ const {
9161
+ addIntrinsics,
9162
+ completePrototypes,
9163
+ finalIntrinsics}=
9164
+ makeIntrinsicsCollector();
9122
9165
 
9123
9166
  addIntrinsics({ harden});
9124
9167
 
@@ -9309,25 +9352,23 @@ assign(globalThis, {
9309
9352
  ,
9310
9353
  ]; // functors end
9311
9354
 
9312
- const cell = (name, value = undefined) => {
9355
+ function cell(name, value = undefined) {
9313
9356
  const observers = [];
9314
- return Object.freeze({
9315
- get: Object.freeze(() => {
9316
- return value;
9317
- }),
9318
- set: Object.freeze((newValue) => {
9319
- value = newValue;
9320
- for (const observe of observers) {
9321
- observe(value);
9322
- }
9323
- }),
9324
- observe: Object.freeze((observe) => {
9325
- observers.push(observe);
9357
+ function set(newValue) {
9358
+ value = newValue;
9359
+ for (const observe of observers) {
9326
9360
  observe(value);
9327
- }),
9328
- enumerable: true,
9329
- });
9330
- };
9361
+ }
9362
+ }
9363
+ function get() {
9364
+ return value;
9365
+ }
9366
+ function observe(observe) {
9367
+ observers.push(observe);
9368
+ observe(value);
9369
+ }
9370
+ return { get, set, observe, enumerable: true };
9371
+ }
9331
9372
 
9332
9373
  const cells = [
9333
9374
  {
@@ -9632,24 +9673,23 @@ assign(globalThis, {
9632
9673
  ];
9633
9674
 
9634
9675
 
9635
- const namespaces = cells.map(cells => Object.freeze(Object.create(null, cells)));
9676
+ const namespaces = cells.map(cells => Object.create(null, cells));
9636
9677
 
9637
9678
  for (let index = 0; index < namespaces.length; index += 1) {
9638
9679
  cells[index]['*'] = cell('*', namespaces[index]);
9639
9680
  }
9640
9681
 
9641
- function observeImports(map, importName, importIndex) {
9642
- for (const [name, observers] of map.get(importName)) {
9643
- const cell = cells[importIndex][name];
9644
- if (cell === undefined) {
9645
- throw new ReferenceError(`Cannot import name ${name}`);
9646
- }
9647
- for (const observer of observers) {
9648
- cell.observe(observer);
9682
+ function observeImports(map, importName, importIndex) {
9683
+ for (const [name, observers] of map.get(importName)) {
9684
+ const cell = cells[importIndex][name];
9685
+ if (cell === undefined) {
9686
+ throw new ReferenceError(`Cannot import name ${name}`);
9687
+ }
9688
+ for (const observer of observers) {
9689
+ cell.observe(observer);
9690
+ }
9649
9691
  }
9650
9692
  }
9651
- }
9652
-
9653
9693
 
9654
9694
  functors[0]({
9655
9695
  imports(entries) {
@@ -10422,6 +10462,1199 @@ function observeImports(map, importName, importIndex) {
10422
10462
  return cells[cells.length - 1]['*'].get();
10423
10463
  })();
10424
10464
 
10425
- /******/ })()
10426
- ;</script><script src="bundle.js"></script></body>
10427
- </html>
10465
+ // END of injected code from ses
10466
+ })()
10467
+ return module.exports
10468
+ })()
10469
+
10470
+ const lockdownOptions = {
10471
+ // gives a semi-high resolution timer
10472
+ dateTaming: 'unsafe',
10473
+ // this is introduces non-determinism, but is otherwise safe
10474
+ mathTaming: 'unsafe',
10475
+ // lets code observe call stack, but easier debuggability
10476
+ errorTaming: 'unsafe',
10477
+ // shows the full call stack
10478
+ stackFiltering: 'verbose',
10479
+ // deep stacks
10480
+ consoleTaming: 'unsafe',
10481
+ }
10482
+
10483
+ lockdown(lockdownOptions)
10484
+
10485
+ // initialize the kernel
10486
+ const createKernelCore = (function () {
10487
+ 'use strict'
10488
+ return createKernelCore
10489
+
10490
+ function createKernelCore ({
10491
+ // the platform api global
10492
+ globalRef,
10493
+ // package policy object
10494
+ lavamoatConfig,
10495
+ // kernel configuration
10496
+ loadModuleData,
10497
+ getRelativeModuleId,
10498
+ prepareModuleInitializerArgs,
10499
+ getExternalCompartment,
10500
+ globalThisRefs,
10501
+ // security options
10502
+ scuttleGlobalThis,
10503
+ scuttleGlobalThisExceptions,
10504
+ debugMode,
10505
+ runWithPrecompiledModules,
10506
+ reportStatsHook,
10507
+ }) {
10508
+ // prepare the LavaMoat kernel-core factory
10509
+ // factory is defined within a Compartment
10510
+ // unless "runWithPrecompiledModules" is enabled
10511
+ let makeKernelCore
10512
+ if (runWithPrecompiledModules) {
10513
+ makeKernelCore = unsafeMakeKernelCore
10514
+ } else {
10515
+ // endowments:
10516
+ // - console is included for convenience
10517
+ // - Math is for untamed Math.random
10518
+ // - Date is for untamed Date.now
10519
+ const kernelCompartment = new Compartment({ console, Math, Date })
10520
+ makeKernelCore = kernelCompartment.evaluate(`(${unsafeMakeKernelCore})\n//# sourceURL=LavaMoat/core/kernel`)
10521
+ }
10522
+ const lavamoatKernel = makeKernelCore({
10523
+ globalRef,
10524
+ lavamoatConfig,
10525
+ loadModuleData,
10526
+ getRelativeModuleId,
10527
+ prepareModuleInitializerArgs,
10528
+ getExternalCompartment,
10529
+ globalThisRefs,
10530
+ scuttleGlobalThis,
10531
+ scuttleGlobalThisExceptions,
10532
+ debugMode,
10533
+ runWithPrecompiledModules,
10534
+ reportStatsHook,
10535
+ })
10536
+
10537
+ return lavamoatKernel
10538
+ }
10539
+
10540
+ // this is serialized and run in a SES Compartment when "runWithPrecompiledModules" is false
10541
+ // mostly just exists to expose variables to internalRequire and loadBundle
10542
+ function unsafeMakeKernelCore ({
10543
+ globalRef,
10544
+ lavamoatConfig,
10545
+ loadModuleData,
10546
+ getRelativeModuleId,
10547
+ prepareModuleInitializerArgs,
10548
+ getExternalCompartment,
10549
+ globalThisRefs = ['globalThis'],
10550
+ scuttleGlobalThis = false,
10551
+ scuttleGlobalThisExceptions = [],
10552
+ debugMode = false,
10553
+ runWithPrecompiledModules = false,
10554
+ reportStatsHook = () => {},
10555
+ }) {
10556
+ // "templateRequire" calls are inlined in "generateKernel"
10557
+ const generalUtils = // define makeGeneralUtils
10558
+ (function(){
10559
+ const global = globalRef
10560
+ const exports = {}
10561
+ const module = { exports }
10562
+ ;(function(){
10563
+ // START of injected code from makeGeneralUtils
10564
+ module.exports = makeGeneralUtils
10565
+
10566
+ function makeGeneralUtils () {
10567
+ return {
10568
+ createFunctionWrapper,
10569
+ }
10570
+
10571
+ function createFunctionWrapper (sourceValue, unwrapTest, unwrapTo) {
10572
+ const newValue = function (...args) {
10573
+ if (new.target) {
10574
+ // handle constructor calls
10575
+ return Reflect.construct(sourceValue, args, new.target)
10576
+ } else {
10577
+ // handle function calls
10578
+ // unwrap to target value if this value is the source package compartment's globalThis
10579
+ const thisRef = unwrapTest(this) ? unwrapTo : this
10580
+ return Reflect.apply(sourceValue, thisRef, args)
10581
+ }
10582
+ }
10583
+ Object.defineProperties(newValue, Object.getOwnPropertyDescriptors(sourceValue))
10584
+ return newValue
10585
+ }
10586
+ }
10587
+
10588
+ // END of injected code from makeGeneralUtils
10589
+ })()
10590
+ return module.exports
10591
+ })()()
10592
+ const { getEndowmentsForConfig, makeMinimalViewOfRef, applyEndowmentPropDescTransforms } = // define makeGetEndowmentsForConfig
10593
+ (function(){
10594
+ const global = globalRef
10595
+ const exports = {}
10596
+ const module = { exports }
10597
+ ;(function(){
10598
+ // START of injected code from makeGetEndowmentsForConfig
10599
+ // the contents of this file will be copied into the prelude template
10600
+ // this module has been written so that it required directly or copied and added to the template with a small wrapper
10601
+ module.exports = makeGetEndowmentsForConfig
10602
+
10603
+ // utilities for generating the endowments object based on a globalRef and a config
10604
+
10605
+ // The config uses a period-deliminated path notation to pull out deep values from objects
10606
+ // These utilities help create an object populated with only the deep properties specified in the config
10607
+
10608
+ function makeGetEndowmentsForConfig ({ createFunctionWrapper }) {
10609
+ return {
10610
+ getEndowmentsForConfig,
10611
+ makeMinimalViewOfRef,
10612
+ copyValueAtPath,
10613
+ applyGetSetPropDescTransforms,
10614
+ applyEndowmentPropDescTransforms,
10615
+ }
10616
+
10617
+ /**
10618
+ *
10619
+ * @function getEndowmentsForConfig
10620
+ * @param {object} sourceRef - Object from which to copy properties
10621
+ * @param {object} config - LavaMoat package config
10622
+ * @param {object} unwrapTo - For getters and setters, when the this-value is unwrapFrom, is replaced as unwrapTo
10623
+ * @param {object} unwrapFrom - For getters and setters, the this-value to replace (default: targetRef)
10624
+ * @return {object} - The targetRef
10625
+ *
10626
+ */
10627
+ function getEndowmentsForConfig (sourceRef, config, unwrapTo, unwrapFrom) {
10628
+ if (!config.globals) {
10629
+ return {}
10630
+ }
10631
+ // validate read access from config
10632
+ const whitelistedReads = []
10633
+ const explicitlyBanned = []
10634
+ Object.entries(config.globals).forEach(([path, configValue]) => {
10635
+ const pathParts = path.split('.')
10636
+ // disallow dunder proto in path
10637
+ const pathContainsDunderProto = pathParts.some(pathPart => pathPart === '__proto__')
10638
+ if (pathContainsDunderProto) {
10639
+ throw new Error(`Lavamoat - "__proto__" disallowed when creating minial view. saw "${path}"`)
10640
+ }
10641
+ // false means no access. It's necessary so that overrides can also be used to tighten the policy
10642
+ if (configValue === false) {
10643
+ explicitlyBanned.push(path)
10644
+ return
10645
+ }
10646
+ // write access handled elsewhere
10647
+ if (configValue === 'write') {
10648
+ return
10649
+ }
10650
+ if (configValue !== true) {
10651
+ throw new Error(`LavaMoat - unrecognizable policy value (${typeof configValue}) for path "${path}"`)
10652
+ }
10653
+ whitelistedReads.push(path)
10654
+ })
10655
+ return makeMinimalViewOfRef(sourceRef, whitelistedReads, unwrapTo, unwrapFrom, explicitlyBanned)
10656
+ }
10657
+
10658
+ function makeMinimalViewOfRef (sourceRef, paths, unwrapTo, unwrapFrom, explicitlyBanned = []) {
10659
+ const targetRef = {}
10660
+ paths.forEach(path => {
10661
+ copyValueAtPath('', path.split('.'), explicitlyBanned, sourceRef, targetRef, unwrapTo, unwrapFrom)
10662
+ })
10663
+ return targetRef
10664
+ }
10665
+
10666
+ function extendPath(visited, next) {
10667
+ if (!visited || visited.length === 0) {
10668
+ return next
10669
+ }
10670
+ return `${visited}.${next}`
10671
+ }
10672
+
10673
+ function copyValueAtPath (visitedPath, pathParts, explicitlyBanned, sourceRef, targetRef, unwrapTo = sourceRef, unwrapFrom = targetRef) {
10674
+ if (pathParts.length === 0) {
10675
+ throw new Error('unable to copy, must have pathParts, was empty')
10676
+ }
10677
+ const [nextPart, ...remainingParts] = pathParts
10678
+ const currentPath = extendPath(visitedPath, nextPart)
10679
+ // get the property from any depth in the property chain
10680
+ const { prop: sourcePropDesc } = getPropertyDescriptorDeep(sourceRef, nextPart)
10681
+
10682
+ // if source missing the value to copy, just skip it
10683
+ if (!sourcePropDesc) {
10684
+ return
10685
+ }
10686
+
10687
+ // if target already has a value, it must be extensible
10688
+ const targetPropDesc = Reflect.getOwnPropertyDescriptor(targetRef, nextPart)
10689
+ if (targetPropDesc) {
10690
+ // dont attempt to extend a getter or trigger a setter
10691
+ if (!('value' in targetPropDesc)) {
10692
+ throw new Error(`unable to copy on to targetRef, targetRef has a getter at "${nextPart}"`)
10693
+ }
10694
+ // value must be extensible (cant write properties onto it)
10695
+ const targetValue = targetPropDesc.value
10696
+ const valueType = typeof targetValue
10697
+ if (valueType !== 'object' && valueType !== 'function') {
10698
+ throw new Error(`unable to copy on to targetRef, targetRef value is not an obj or func "${nextPart}"`)
10699
+ }
10700
+ }
10701
+
10702
+ // if this is not the last path in the assignment, walk into the containing reference
10703
+ if (remainingParts.length > 0) {
10704
+ const { sourceValue, sourceWritable } = getSourceValue()
10705
+ const nextSourceRef = sourceValue
10706
+ let nextTargetRef
10707
+ // check if value exists on target and does not need selective treatment
10708
+ if (targetPropDesc && !explicitlyBanned.includes(currentPath)) {
10709
+ // a value already exists, we should walk into it
10710
+ nextTargetRef = targetPropDesc.value
10711
+ } else {
10712
+ // its not populated so lets write to it
10713
+ // put an object to serve as a container
10714
+ const containerRef = {}
10715
+ const newPropDesc = {
10716
+ value: containerRef,
10717
+ writable: sourceWritable,
10718
+ enumerable: sourcePropDesc.enumerable,
10719
+ configurable: sourcePropDesc.configurable,
10720
+ }
10721
+ Reflect.defineProperty(targetRef, nextPart, newPropDesc)
10722
+ // the newly created container will be the next target
10723
+ nextTargetRef = containerRef
10724
+ }
10725
+ copyValueAtPath(currentPath, remainingParts, explicitlyBanned, nextSourceRef, nextTargetRef)
10726
+ return
10727
+ }
10728
+
10729
+ // If conflicting rules exist, opt for the negative one. This should never happen
10730
+ if (explicitlyBanned.includes(currentPath)) {
10731
+ console.warn(`LavaMoat - conflicting rules exist for "${currentPath}"`)
10732
+ return
10733
+ }
10734
+
10735
+ // this is the last part of the path, the value we're trying to actually copy
10736
+ // if has getter/setter - apply this-value unwrapping
10737
+ if (!('value' in sourcePropDesc)) {
10738
+ // wrapper setter/getter with correct receiver
10739
+ const wrapperPropDesc = applyGetSetPropDescTransforms(sourcePropDesc, unwrapFrom, unwrapTo)
10740
+ Reflect.defineProperty(targetRef, nextPart, wrapperPropDesc)
10741
+ return
10742
+ }
10743
+
10744
+ // need to determine the value type in order to copy it with
10745
+ // this-value unwrapping support
10746
+ const { sourceValue, sourceWritable } = getSourceValue()
10747
+
10748
+ // not a function - copy as is
10749
+ if (typeof sourceValue !== 'function') {
10750
+ Reflect.defineProperty(targetRef, nextPart, sourcePropDesc)
10751
+ return
10752
+ }
10753
+ // otherwise add workaround for functions to swap back to the sourceal "this" reference
10754
+ const unwrapTest = thisValue => thisValue === unwrapFrom
10755
+ const newValue = createFunctionWrapper(sourceValue, unwrapTest, unwrapTo)
10756
+ const newPropDesc = {
10757
+ value: newValue,
10758
+ writable: sourceWritable,
10759
+ enumerable: sourcePropDesc.enumerable,
10760
+ configurable: sourcePropDesc.configurable,
10761
+ }
10762
+ Reflect.defineProperty(targetRef, nextPart, newPropDesc)
10763
+
10764
+ function getSourceValue () {
10765
+ // determine the source value, this coerces getters to values
10766
+ // im deeply sorry, respecting getters was complicated and
10767
+ // my brain is not very good
10768
+ let sourceValue, sourceWritable
10769
+ if ('value' in sourcePropDesc) {
10770
+ sourceValue = sourcePropDesc.value
10771
+ sourceWritable = sourcePropDesc.writable
10772
+ } else if ('get' in sourcePropDesc) {
10773
+ sourceValue = sourcePropDesc.get.call(unwrapTo)
10774
+ sourceWritable = 'set' in sourcePropDesc
10775
+ } else {
10776
+ throw new Error('getEndowmentsForConfig - property descriptor missing a getter')
10777
+ }
10778
+ return { sourceValue, sourceWritable }
10779
+ }
10780
+ }
10781
+
10782
+ function applyEndowmentPropDescTransforms (propDesc, unwrapFromCompartment, unwrapToGlobalThis) {
10783
+ let newPropDesc = propDesc
10784
+ newPropDesc = applyFunctionPropDescTransform(newPropDesc, unwrapFromCompartment, unwrapToGlobalThis)
10785
+ newPropDesc = applyGetSetPropDescTransforms(newPropDesc, unwrapFromCompartment.globalThis, unwrapToGlobalThis)
10786
+ return newPropDesc
10787
+ }
10788
+
10789
+ function applyGetSetPropDescTransforms (sourcePropDesc, unwrapFromGlobalThis, unwrapToGlobalThis) {
10790
+ const wrappedPropDesc = { ...sourcePropDesc }
10791
+ if (sourcePropDesc.get) {
10792
+ wrappedPropDesc.get = function () {
10793
+ const receiver = this
10794
+ // replace the "receiver" value if it points to fake parent
10795
+ const receiverRef = receiver === unwrapFromGlobalThis ? unwrapToGlobalThis : receiver
10796
+ // sometimes getters replace themselves with static properties, as seen wih the FireFox runtime
10797
+ const result = Reflect.apply(sourcePropDesc.get, receiverRef, [])
10798
+ if (typeof result === 'function') {
10799
+ // functions must be wrapped to ensure a good this-value.
10800
+ // lockdown causes some propDescs to go to value -> getter,
10801
+ // eg "Function.prototype.bind". we need to wrap getter results
10802
+ // as well in order to ensure they have their this-value wrapped correctly
10803
+ // if this ends up being problematic we can maybe take advantage of lockdown's
10804
+ // "getter.originalValue" property being available
10805
+ return createFunctionWrapper(result, (thisValue) => thisValue === unwrapFromGlobalThis, unwrapToGlobalThis)
10806
+ } else {
10807
+ return result
10808
+ }
10809
+ }
10810
+ }
10811
+ if (sourcePropDesc.set) {
10812
+ wrappedPropDesc.set = function (value) {
10813
+ // replace the "receiver" value if it points to fake parent
10814
+ const receiver = this
10815
+ const receiverRef = receiver === unwrapFromGlobalThis ? unwrapToGlobalThis : receiver
10816
+ return Reflect.apply(sourcePropDesc.set, receiverRef, [value])
10817
+ }
10818
+ }
10819
+ return wrappedPropDesc
10820
+ }
10821
+
10822
+ function applyFunctionPropDescTransform (propDesc, unwrapFromCompartment, unwrapToGlobalThis) {
10823
+ if (!('value' in propDesc && typeof propDesc.value === 'function')) {
10824
+ return propDesc
10825
+ }
10826
+ const unwrapTest = (thisValue) => {
10827
+ // unwrap function calls this-value to unwrapToGlobalThis when:
10828
+ // this value is globalThis ex. globalThis.abc()
10829
+ // scope proxy leak workaround ex. abc()
10830
+ return thisValue === unwrapFromCompartment.globalThis
10831
+ }
10832
+ const newFn = createFunctionWrapper(propDesc.value, unwrapTest, unwrapToGlobalThis)
10833
+ return { ...propDesc, value: newFn }
10834
+ }
10835
+ }
10836
+
10837
+ function getPropertyDescriptorDeep (target, key) {
10838
+ let receiver = target
10839
+ while (true) {
10840
+ // abort if this is the end of the prototype chain.
10841
+ if (!receiver) {
10842
+ return { prop: null, receiver: null }
10843
+ }
10844
+ // support lookup on objects and primitives
10845
+ const typeofReceiver = typeof receiver
10846
+ if (typeofReceiver === 'object' || typeofReceiver === 'function') {
10847
+ const prop = Reflect.getOwnPropertyDescriptor(receiver, key)
10848
+ if (prop) {
10849
+ return { receiver, prop }
10850
+ }
10851
+ // try next in the prototype chain
10852
+ receiver = Reflect.getPrototypeOf(receiver)
10853
+ } else {
10854
+ // prototype lookup for primitives
10855
+ // eslint-disable-next-line no-proto
10856
+ receiver = receiver.__proto__
10857
+ }
10858
+ }
10859
+ }
10860
+
10861
+ // END of injected code from makeGetEndowmentsForConfig
10862
+ })()
10863
+ return module.exports
10864
+ })()(generalUtils)
10865
+ const { prepareCompartmentGlobalFromConfig } = // define makePrepareRealmGlobalFromConfig
10866
+ (function(){
10867
+ const global = globalRef
10868
+ const exports = {}
10869
+ const module = { exports }
10870
+ ;(function(){
10871
+ // START of injected code from makePrepareRealmGlobalFromConfig
10872
+ // the contents of this file will be copied into the prelude template
10873
+ // this module has been written so that it required directly or copied and added to the template with a small wrapper
10874
+ module.exports = makePrepareRealmGlobalFromConfig
10875
+
10876
+ // utilities for exposing configuring the exposed endowments on the container global
10877
+
10878
+ // The config uses a period-deliminated path notation to pull out deep values from objects
10879
+ // These utilities help modify the container global to expose the allowed globals from the globalStore OR the platform global
10880
+
10881
+ function makePrepareRealmGlobalFromConfig ({ createFunctionWrapper }) {
10882
+ return {
10883
+ prepareCompartmentGlobalFromConfig,
10884
+ getTopLevelReadAccessFromPackageConfig,
10885
+ getTopLevelWriteAccessFromPackageConfig,
10886
+ }
10887
+
10888
+ function getTopLevelReadAccessFromPackageConfig (globalsConfig) {
10889
+ const result = Object.entries(globalsConfig)
10890
+ .filter(([key, value]) => value === 'read' || value === true || (value === 'write' && key.split('.').length > 1))
10891
+ .map(([key]) => key.split('.')[0])
10892
+ // return unique array
10893
+ return Array.from(new Set(result))
10894
+ }
10895
+
10896
+ function getTopLevelWriteAccessFromPackageConfig (globalsConfig) {
10897
+ const result = Object.entries(globalsConfig)
10898
+ .filter(([key, value]) => value === 'write' && key.split('.').length === 1)
10899
+ .map(([key]) => key)
10900
+ return result
10901
+ }
10902
+
10903
+ function prepareCompartmentGlobalFromConfig (packageCompartment, globalsConfig, endowments, globalStore, globalThisRefs) {
10904
+ const packageCompartmentGlobal = packageCompartment.globalThis
10905
+ // lookup top level read + write access keys
10906
+ const topLevelWriteAccessKeys = getTopLevelWriteAccessFromPackageConfig(globalsConfig)
10907
+ const topLevelReadAccessKeys = getTopLevelReadAccessFromPackageConfig(globalsConfig)
10908
+
10909
+ // define accessors
10910
+
10911
+ // allow read access via globalStore or packageCompartmentGlobal
10912
+ topLevelReadAccessKeys.forEach(key => {
10913
+ Object.defineProperty(packageCompartmentGlobal, key, {
10914
+ get () {
10915
+ if (globalStore.has(key)) {
10916
+ return globalStore.get(key)
10917
+ } else {
10918
+ return Reflect.get(endowments, key, this)
10919
+ }
10920
+ },
10921
+ set () {
10922
+ // TODO: there should be a config to throw vs silently ignore
10923
+ console.warn(`LavaMoat: ignoring write attempt to read-access global "${key}"`)
10924
+ },
10925
+ })
10926
+ })
10927
+
10928
+ // allow write access to globalStore
10929
+ // read access via globalStore or packageCompartmentGlobal
10930
+ topLevelWriteAccessKeys.forEach(key => {
10931
+ Object.defineProperty(packageCompartmentGlobal, key, {
10932
+ get () {
10933
+ if (globalStore.has(key)) {
10934
+ return globalStore.get(key)
10935
+ } else {
10936
+ return endowments[key]
10937
+ }
10938
+ },
10939
+ set (value) {
10940
+ globalStore.set(key, value)
10941
+ },
10942
+ enumerable: true,
10943
+ configurable: true,
10944
+ })
10945
+ })
10946
+
10947
+ // set circular globalRefs
10948
+ globalThisRefs.forEach(key => {
10949
+ // if globalRef is actually an endowment, ignore
10950
+ if (topLevelReadAccessKeys.includes(key)) {
10951
+ return
10952
+ }
10953
+ if (topLevelWriteAccessKeys.includes(key)) {
10954
+ return
10955
+ }
10956
+ // set circular ref to global
10957
+ packageCompartmentGlobal[key] = packageCompartmentGlobal
10958
+ })
10959
+
10960
+ // bind Function constructor this value to globalThis
10961
+ // legacy globalThis shim
10962
+ const origFunction = packageCompartmentGlobal.Function
10963
+ const newFunction = function (...args) {
10964
+ const fn = origFunction(...args)
10965
+ const unwrapTest = thisValue => thisValue === undefined
10966
+ return createFunctionWrapper(fn, unwrapTest, packageCompartmentGlobal)
10967
+ }
10968
+ Object.defineProperties(newFunction, Object.getOwnPropertyDescriptors(origFunction))
10969
+ packageCompartmentGlobal.Function = newFunction
10970
+ }
10971
+ }
10972
+
10973
+ // END of injected code from makePrepareRealmGlobalFromConfig
10974
+ })()
10975
+ return module.exports
10976
+ })()(generalUtils)
10977
+ const { strictScopeTerminator } = // define strict-scope-terminator
10978
+ (function(){
10979
+ const global = globalRef
10980
+ const exports = {}
10981
+ const module = { exports }
10982
+ ;(function(){
10983
+ // START of injected code from strict-scope-terminator
10984
+ // import {
10985
+ // Proxy,
10986
+ // String,
10987
+ // TypeError,
10988
+ // ReferenceError,
10989
+ // create,
10990
+ // freeze,
10991
+ // getOwnPropertyDescriptors,
10992
+ // globalThis,
10993
+ // immutableObject,
10994
+ // } from './commons.js';
10995
+ const { freeze, create, getOwnPropertyDescriptors } = Object;
10996
+ const immutableObject = freeze(create(null));
10997
+
10998
+ // import { assert } from './error/assert.js';
10999
+ const assert = {
11000
+ fail: (msg) => {
11001
+ throw new Error(msg);
11002
+ }
11003
+ }
11004
+
11005
+ // const { details: d, quote: q } = assert;
11006
+ const d = (strings, args) => strings.join() + args.join();
11007
+ const q = (arg) => arg
11008
+
11009
+ /**
11010
+ * alwaysThrowHandler
11011
+ * This is an object that throws if any property is called. It's used as
11012
+ * a proxy handler which throws on any trap called.
11013
+ * It's made from a proxy with a get trap that throws. It's safe to
11014
+ * create one and share it between all Proxy handlers.
11015
+ */
11016
+ const alwaysThrowHandler = new Proxy(
11017
+ immutableObject,
11018
+ freeze({
11019
+ get(_shadow, prop) {
11020
+ // eslint-disable-next-line @endo/no-polymorphic-call
11021
+ assert.fail(
11022
+ d`Please report unexpected scope handler trap: ${q(String(prop))}`,
11023
+ );
11024
+ },
11025
+ }),
11026
+ );
11027
+
11028
+ /*
11029
+ * scopeProxyHandlerProperties
11030
+ * scopeTerminatorHandler manages a strictScopeTerminator Proxy which serves as
11031
+ * the final scope boundary that will always return "undefined" in order
11032
+ * to prevent access to "start compartment globals".
11033
+ */
11034
+ const scopeProxyHandlerProperties = {
11035
+ get(_shadow, _prop) {
11036
+ return undefined;
11037
+ },
11038
+
11039
+ set(_shadow, prop, _value) {
11040
+ // We should only hit this if the has() hook returned true matches the v8
11041
+ // ReferenceError message "Uncaught ReferenceError: xyz is not defined"
11042
+ throw new ReferenceError(`${String(prop)} is not defined`);
11043
+ },
11044
+
11045
+ has(_shadow, prop) {
11046
+ // we must at least return true for all properties on the realm globalThis
11047
+ return prop in globalThis;
11048
+ },
11049
+
11050
+ // note: this is likely a bug of safari
11051
+ // https://bugs.webkit.org/show_bug.cgi?id=195534
11052
+ getPrototypeOf() {
11053
+ return null;
11054
+ },
11055
+
11056
+ // Chip has seen this happen single stepping under the Chrome/v8 debugger.
11057
+ // TODO record how to reliably reproduce, and to test if this fix helps.
11058
+ // TODO report as bug to v8 or Chrome, and record issue link here.
11059
+ getOwnPropertyDescriptor(_target, prop) {
11060
+ // Coerce with `String` in case prop is a symbol.
11061
+ const quotedProp = q(String(prop));
11062
+ // eslint-disable-next-line @endo/no-polymorphic-call
11063
+ console.warn(
11064
+ `getOwnPropertyDescriptor trap on scopeTerminatorHandler for ${quotedProp}`,
11065
+ new TypeError().stack,
11066
+ );
11067
+ return undefined;
11068
+ },
11069
+ };
11070
+
11071
+ // The scope handler's prototype is a proxy that throws if any trap other
11072
+ // than get/set/has are run (like getOwnPropertyDescriptors, apply,
11073
+ // getPrototypeOf).
11074
+ const strictScopeTerminatorHandler = freeze(
11075
+ create(
11076
+ alwaysThrowHandler,
11077
+ getOwnPropertyDescriptors(scopeProxyHandlerProperties),
11078
+ ),
11079
+ );
11080
+
11081
+ const strictScopeTerminator = new Proxy(
11082
+ immutableObject,
11083
+ strictScopeTerminatorHandler,
11084
+ );
11085
+
11086
+ module.exports = {
11087
+ alwaysThrowHandler,
11088
+ strictScopeTerminatorHandler,
11089
+ strictScopeTerminator,
11090
+ }
11091
+
11092
+ // END of injected code from strict-scope-terminator
11093
+ })()
11094
+ return module.exports
11095
+ })()
11096
+
11097
+ const moduleCache = new Map()
11098
+ const packageCompartmentCache = new Map()
11099
+ const globalStore = new Map()
11100
+
11101
+ const rootPackageName = '$root$'
11102
+ const rootPackageCompartment = createRootPackageCompartment(globalRef)
11103
+
11104
+ // scuttle globalThis right after we used it to create the root package compartment
11105
+ if (scuttleGlobalThis) {
11106
+ if (!Array.isArray(scuttleGlobalThisExceptions)) {
11107
+ throw new Error(`LavaMoat - scuttleGlobalThisExceptions must be an array, got "${typeof scuttleGlobalThisExceptions}"`)
11108
+ }
11109
+ performScuttleGlobalThis(globalRef, scuttleGlobalThisExceptions)
11110
+ }
11111
+
11112
+ const kernel = {
11113
+ internalRequire,
11114
+ }
11115
+ if (debugMode) {
11116
+ kernel._getPolicyForPackage = getPolicyForPackage
11117
+ kernel._getCompartmentForPackage = getCompartmentForPackage
11118
+ }
11119
+ Object.freeze(kernel)
11120
+ return kernel
11121
+
11122
+ function performScuttleGlobalThis (globalRef, extraPropsToAvoid = new Array()) {
11123
+ const props = new Array()
11124
+ getPrototypeChain(globalRef)
11125
+ .forEach(proto =>
11126
+ props.push(...Object.getOwnPropertyNames(proto)))
11127
+
11128
+ for (let i = 0; i < extraPropsToAvoid.length; i++) {
11129
+ const prop = extraPropsToAvoid[i]
11130
+ if (!prop.startsWith('/')) {
11131
+ continue
11132
+ }
11133
+ const parts = prop.split('/')
11134
+ const pattern = parts.slice(1, -1).join('/')
11135
+ const flags = parts[parts.length - 1]
11136
+ extraPropsToAvoid[i] = new RegExp(pattern, flags)
11137
+ }
11138
+
11139
+ // support LM,SES exported APIs and polyfills
11140
+ const avoidForLavaMoatCompatibility = ['Compartment', 'Error', 'globalThis']
11141
+ const propsToAvoid = new Set([...avoidForLavaMoatCompatibility, ...extraPropsToAvoid])
11142
+
11143
+ for (const prop of props) {
11144
+ if (shouldAvoidProp(propsToAvoid, prop)) {
11145
+ continue
11146
+ }
11147
+ if (Object.getOwnPropertyDescriptor(globalRef, prop)?.configurable === false) {
11148
+ continue
11149
+ }
11150
+ const desc = {
11151
+ set: () => {
11152
+ console.warn(
11153
+ `LavaMoat - property "${prop}" of globalThis cannot be set under scuttling mode. ` +
11154
+ 'To learn more visit https://github.com/LavaMoat/LavaMoat/pull/360.',
11155
+ )
11156
+ },
11157
+ get: () => {
11158
+ throw new Error(
11159
+ `LavaMoat - property "${prop}" of globalThis is inaccessible under scuttling mode. ` +
11160
+ 'To learn more visit https://github.com/LavaMoat/LavaMoat/pull/360.',
11161
+ )
11162
+ },
11163
+ configurable: false,
11164
+ }
11165
+ Object.defineProperty(globalRef, prop, desc)
11166
+ }
11167
+ }
11168
+
11169
+ // this function instantiaties a module from a moduleId.
11170
+ // 1. loads the module metadata and policy
11171
+ // 2. prepares the execution environment
11172
+ // 3. instantiates the module, recursively instantiating dependencies
11173
+ // 4. returns the module exports
11174
+ function internalRequire (moduleId) {
11175
+ // use cached module.exports if module is already instantiated
11176
+ if (moduleCache.has(moduleId)) {
11177
+ const moduleExports = moduleCache.get(moduleId).exports
11178
+ return moduleExports
11179
+ }
11180
+
11181
+ reportStatsHook('start', moduleId)
11182
+
11183
+ try {
11184
+ // load and validate module metadata
11185
+ // if module metadata is missing, throw an error
11186
+ const moduleData = loadModuleData(moduleId)
11187
+ if (!moduleData) {
11188
+ const err = new Error('Cannot find module \'' + moduleId + '\'')
11189
+ err.code = 'MODULE_NOT_FOUND'
11190
+ throw err
11191
+ }
11192
+ if (moduleData.id === undefined) {
11193
+ throw new Error('LavaMoat - moduleId is not defined correctly.')
11194
+ }
11195
+
11196
+ // parse and validate module data
11197
+ const { package: packageName, source: moduleSource } = moduleData
11198
+ if (!packageName) {
11199
+ throw new Error(`LavaMoat - missing packageName for module "${moduleId}"`)
11200
+ }
11201
+ const packagePolicy = getPolicyForPackage(lavamoatConfig, packageName)
11202
+
11203
+ // create the moduleObj and initializer
11204
+ const { moduleInitializer, moduleObj } = prepareModuleInitializer(moduleData, packagePolicy)
11205
+
11206
+ // cache moduleObj here
11207
+ // this is important to inf loops when hitting cycles in the dep graph
11208
+ // must cache before running the moduleInitializer
11209
+ moduleCache.set(moduleId, moduleObj)
11210
+
11211
+ // validate moduleInitializer
11212
+ if (typeof moduleInitializer !== 'function') {
11213
+ throw new Error(`LavaMoat - moduleInitializer is not defined correctly. got "${typeof moduleInitializer}"\n${moduleSource}`)
11214
+ }
11215
+
11216
+ // initialize the module with the correct context
11217
+ const initializerArgs = prepareModuleInitializerArgs(requireRelativeWithContext, moduleObj, moduleData)
11218
+ moduleInitializer.apply(moduleObj.exports, initializerArgs)
11219
+ const moduleExports = moduleObj.exports
11220
+ return moduleExports
11221
+
11222
+ // this is passed to the module initializer
11223
+ // it adds the context of the parent module
11224
+ // this could be replaced via "Function.prototype.bind" if its more performant
11225
+ function requireRelativeWithContext (requestedName) {
11226
+ const parentModuleExports = moduleObj.exports
11227
+ const parentModuleData = moduleData
11228
+ const parentPackagePolicy = packagePolicy
11229
+ const parentModuleId = moduleId
11230
+ return requireRelative({ requestedName, parentModuleExports, parentModuleData, parentPackagePolicy, parentModuleId })
11231
+ }
11232
+ } finally {
11233
+ reportStatsHook('end', moduleId)
11234
+ }
11235
+ }
11236
+
11237
+ // this resolves a module given a requestedName (eg relative path to parent) and a parentModule context
11238
+ // the exports are processed via "protectExportsRequireTime" per the module's configuration
11239
+ function requireRelative ({ requestedName, parentModuleExports, parentModuleData, parentPackagePolicy, parentModuleId }) {
11240
+ const parentModulePackageName = parentModuleData.package
11241
+ const parentPackagesWhitelist = parentPackagePolicy.packages
11242
+ const parentBuiltinsWhitelist = Object.entries(parentPackagePolicy.builtin)
11243
+ .filter(([_, allowed]) => allowed === true)
11244
+ .map(([packagePath, allowed]) => packagePath.split('.')[0])
11245
+
11246
+ // resolve the moduleId from the requestedName
11247
+ const moduleId = getRelativeModuleId(parentModuleId, requestedName)
11248
+
11249
+ // browserify goop:
11250
+ // recursive requires dont hit cache so it inf loops, so we shortcircuit
11251
+ // this only seems to happen with a few browserify builtins (nodejs builtin module polyfills)
11252
+ // we could likely allow any requestedName since it can only refer to itself
11253
+ if (moduleId === parentModuleId) {
11254
+ if (['timers', 'buffer'].includes(requestedName) === false) {
11255
+ throw new Error(`LavaMoat - recursive require detected: "${requestedName}"`)
11256
+ }
11257
+ return parentModuleExports
11258
+ }
11259
+
11260
+ // load module
11261
+ let moduleExports = internalRequire(moduleId)
11262
+
11263
+ // look up config for module
11264
+ const moduleData = loadModuleData(moduleId)
11265
+ const packageName = moduleData.package
11266
+
11267
+ // disallow requiring packages that are not in the parent's whitelist
11268
+ const isSamePackage = packageName === parentModulePackageName
11269
+ const parentIsEntryModule = parentModulePackageName === rootPackageName
11270
+ let isInParentWhitelist = false
11271
+ if (moduleData.type === 'builtin') {
11272
+ isInParentWhitelist = parentBuiltinsWhitelist.includes(packageName)
11273
+ } else {
11274
+ isInParentWhitelist = (parentPackagesWhitelist[packageName] === true)
11275
+ }
11276
+
11277
+ // validate that the import is allowed
11278
+ if (!parentIsEntryModule && !isSamePackage && !isInParentWhitelist) {
11279
+ let typeText = ' '
11280
+ if (moduleData.type === 'builtin') {
11281
+ typeText = ' node builtin '
11282
+ }
11283
+ throw new Error(`LavaMoat - required${typeText}package not in allowlist: package "${parentModulePackageName}" requested "${packageName}" as "${requestedName}"`)
11284
+ }
11285
+
11286
+ // create minimal selection if its a builtin and the whole path is not selected for
11287
+ if (!parentIsEntryModule && moduleData.type === 'builtin' && !parentPackagePolicy.builtin[moduleId]) {
11288
+ const builtinPaths = (
11289
+ Object.entries(parentPackagePolicy.builtin)
11290
+ // grab all allowed builtin paths that match this package
11291
+ .filter(([packagePath, allowed]) => allowed === true && moduleId === packagePath.split('.')[0])
11292
+ // only include the paths after the packageName
11293
+ .map(([packagePath, allowed]) => packagePath.split('.').slice(1).join('.'))
11294
+ .sort()
11295
+ )
11296
+ moduleExports = makeMinimalViewOfRef(moduleExports, builtinPaths)
11297
+ }
11298
+
11299
+ return moduleExports
11300
+ }
11301
+
11302
+ function prepareModuleInitializer (moduleData, packagePolicy) {
11303
+ const { moduleInitializer, precompiledInitializer, package: packageName, id: moduleId, source: moduleSource } = moduleData
11304
+
11305
+ // moduleInitializer may be set by loadModuleData (e.g. builtin + native modules)
11306
+ if (moduleInitializer) {
11307
+ // if an external moduleInitializer is set, ensure it is allowed
11308
+ if (moduleData.type === 'native') {
11309
+ // ensure package is allowed to have native modules
11310
+ if (packagePolicy.native !== true) {
11311
+ throw new Error(`LavaMoat - "native" module type not permitted for package "${packageName}", module "${moduleId}"`)
11312
+ }
11313
+ } else if (moduleData.type !== 'builtin') {
11314
+ // builtin module types dont have policy configurations
11315
+ // but the packages that can import them are constrained elsewhere
11316
+ // here we just ensure that the module type is the only other type with a external moduleInitializer
11317
+ throw new Error(`LavaMoat - invalid external moduleInitializer for module type "${moduleData.type}" in package "${packageName}", module "${moduleId}"`)
11318
+ }
11319
+ // moduleObj must be from the same Realm as the moduleInitializer (eg dart2js runtime requirement)
11320
+ // here we are assuming the provided moduleInitializer is from the same Realm as this kernel
11321
+ const moduleObj = { exports: {} }
11322
+ return { moduleInitializer, moduleObj }
11323
+ }
11324
+
11325
+ // setup initializer from moduleSource and compartment.
11326
+ // execute in package compartment with globalThis populated per package policy
11327
+ const packageCompartment = getCompartmentForPackage(packageName, packagePolicy)
11328
+
11329
+ try {
11330
+ let moduleObj
11331
+ let moduleInitializer
11332
+ if (runWithPrecompiledModules) {
11333
+ if (!precompiledInitializer) {
11334
+ throw new Error(`LavaMoat - precompiledInitializer missing for "${moduleId}" from package "${packageName}"`)
11335
+ }
11336
+ // moduleObj must be from the same Realm as the moduleInitializer (eg dart2js runtime requirement)
11337
+ // here we are assuming the provided moduleInitializer is from the same Realm as this kernel
11338
+ moduleObj = { exports: {} }
11339
+ const evalKit = {
11340
+ globalThis: packageCompartment.globalThis,
11341
+ scopeTerminator: strictScopeTerminator,
11342
+ }
11343
+ // this invokes the with-proxy wrapper
11344
+ const moduleInitializerFactory = precompiledInitializer.call(evalKit)
11345
+ // this ensures strict mode
11346
+ moduleInitializer = moduleInitializerFactory()
11347
+ } else {
11348
+ if (typeof moduleSource !== 'string') {
11349
+ throw new Error(`LavaMoat - moduleSource not a string for "${moduleId}" from package "${packageName}"`)
11350
+ }
11351
+ const sourceURL = moduleData.file || `modules/${moduleId}`
11352
+ if (sourceURL.includes('\n')) {
11353
+ throw new Error(`LavaMoat - Newlines not allowed in filenames: ${JSON.stringify(sourceURL)}`)
11354
+ }
11355
+ // moduleObj must be from the same Realm as the moduleInitializer (eg dart2js runtime requirement)
11356
+ moduleObj = packageCompartment.evaluate('({ exports: {} })')
11357
+ // TODO: move all source mutations elsewhere
11358
+ moduleInitializer = packageCompartment.evaluate(`${moduleSource}\n//# sourceURL=${sourceURL}`)
11359
+ }
11360
+ return { moduleInitializer, moduleObj }
11361
+ } catch (err) {
11362
+ console.warn(`LavaMoat - Error evaluating module "${moduleId}" from package "${packageName}" \n${err.stack}`)
11363
+ throw err
11364
+ }
11365
+ }
11366
+
11367
+ function createRootPackageCompartment (globalRef) {
11368
+ if (packageCompartmentCache.has(rootPackageName)) {
11369
+ throw new Error('LavaMoat - createRootPackageCompartment called more than once')
11370
+ }
11371
+ // prepare the root package's SES Compartment
11372
+ // endowments:
11373
+ // - Math is for untamed Math.random
11374
+ // - Date is for untamed Date.now
11375
+ const rootPackageCompartment = new Compartment({ Math, Date })
11376
+ // find the relevant endowment sources
11377
+ const globalProtoChain = getPrototypeChain(globalRef)
11378
+ // the index for the common prototypal ancestor, Object.prototype
11379
+ // this should always be the last index, but we check just in case
11380
+ const commonPrototypeIndex = globalProtoChain.findIndex(globalProtoChainEntry => globalProtoChainEntry === Object.prototype)
11381
+ if (commonPrototypeIndex === -1) {
11382
+ throw new Error('Lavamoat - unable to find common prototype between Compartment and globalRef')
11383
+ }
11384
+ // we will copy endowments from all entries in the prototype chain, excluding Object.prototype
11385
+ const endowmentSources = globalProtoChain.slice(0, commonPrototypeIndex)
11386
+
11387
+ // call all getters, in case of behavior change (such as with FireFox lazy getters)
11388
+ // call on contents of endowmentsSources directly instead of in new array instances. If there is a lazy getter it only changes the original prop desc.
11389
+ endowmentSources.forEach(source => {
11390
+ const descriptors = Object.getOwnPropertyDescriptors(source)
11391
+ Object.values(descriptors).forEach(desc => {
11392
+ if ('get' in desc) {
11393
+ try {
11394
+ Reflect.apply(desc.get, globalRef, [])
11395
+ }catch{}
11396
+ }
11397
+ })
11398
+ })
11399
+
11400
+ const endowmentSourceDescriptors = endowmentSources.map(globalProtoChainEntry => Object.getOwnPropertyDescriptors(globalProtoChainEntry))
11401
+ // flatten propDesc collections with precedence for globalThis-end of the prototype chain
11402
+ const endowmentDescriptorsFlat = Object.assign(Object.create(null), ...endowmentSourceDescriptors.reverse())
11403
+ // expose all own properties of globalRef, including non-enumerable
11404
+ Object.entries(endowmentDescriptorsFlat)
11405
+ // ignore properties already defined on compartment global
11406
+ .filter(([key]) => !(key in rootPackageCompartment.globalThis))
11407
+ // ignore circular globalThis refs
11408
+ .filter(([key]) => !(globalThisRefs.includes(key)))
11409
+ // define property on compartment global
11410
+ .forEach(([key, desc]) => {
11411
+ // unwrap functions, setters/getters & apply scope proxy workaround
11412
+ const wrappedPropDesc = applyEndowmentPropDescTransforms(desc, rootPackageCompartment, globalRef)
11413
+ Reflect.defineProperty(rootPackageCompartment.globalThis, key, wrappedPropDesc)
11414
+ })
11415
+ // global circular references otherwise added by prepareCompartmentGlobalFromConfig
11416
+ // Add all circular refs to root package compartment globalThis
11417
+ for (const ref of globalThisRefs) {
11418
+ if (ref in rootPackageCompartment.globalThis) {
11419
+ continue
11420
+ }
11421
+ rootPackageCompartment.globalThis[ref] = rootPackageCompartment.globalThis
11422
+ }
11423
+
11424
+ // save the compartment for use by other modules in the package
11425
+ packageCompartmentCache.set(rootPackageName, rootPackageCompartment)
11426
+
11427
+ return rootPackageCompartment
11428
+ }
11429
+
11430
+ function getCompartmentForPackage (packageName, packagePolicy) {
11431
+ // compartment may have already been created
11432
+ let packageCompartment = packageCompartmentCache.get(packageName)
11433
+ if (packageCompartment) {
11434
+ return packageCompartment
11435
+ }
11436
+
11437
+ // prepare Compartment
11438
+ if (getExternalCompartment && packagePolicy.env) {
11439
+ // external compartment can be provided by the platform (eg lavamoat-node)
11440
+ packageCompartment = getExternalCompartment(packageName, packagePolicy)
11441
+ } else {
11442
+ // prepare the module's SES Compartment
11443
+ // endowments:
11444
+ // - Math is for untamed Math.random
11445
+ // - Date is for untamed Date.now
11446
+ packageCompartment = new Compartment({ Math, Date })
11447
+ }
11448
+ // prepare endowments
11449
+ let endowments
11450
+ try {
11451
+ endowments = getEndowmentsForConfig(
11452
+ // source reference
11453
+ rootPackageCompartment.globalThis,
11454
+ // policy
11455
+ packagePolicy,
11456
+ // unwrap to
11457
+ globalRef,
11458
+ // unwrap from
11459
+ packageCompartment.globalThis,
11460
+ )
11461
+ } catch (err) {
11462
+ const errMsg = `Lavamoat - failed to prepare endowments for package "${packageName}":\n${err.stack}`
11463
+ throw new Error(errMsg)
11464
+ }
11465
+
11466
+ // transform functions, getters & setters on prop descs. Solves SES scope proxy bug
11467
+ Object.entries(Object.getOwnPropertyDescriptors(endowments))
11468
+ // ignore non-configurable properties because we are modifying endowments in place
11469
+ .filter(([key, propDesc]) => propDesc.configurable)
11470
+ .forEach(([key, propDesc]) => {
11471
+ const wrappedPropDesc = applyEndowmentPropDescTransforms(propDesc, packageCompartment, rootPackageCompartment.globalThis)
11472
+ Reflect.defineProperty(endowments, key, wrappedPropDesc)
11473
+ })
11474
+
11475
+ // sets up read/write access as configured
11476
+ const globalsConfig = packagePolicy.globals
11477
+ prepareCompartmentGlobalFromConfig(packageCompartment, globalsConfig, endowments, globalStore, globalThisRefs)
11478
+
11479
+ // save the compartment for use by other modules in the package
11480
+ packageCompartmentCache.set(packageName, packageCompartment)
11481
+
11482
+ return packageCompartment
11483
+ }
11484
+
11485
+ // this gets the lavaMoat config for a module by packageName
11486
+ // if there were global defaults (e.g. everything gets "console") they could be applied here
11487
+ function getPolicyForPackage (config, packageName) {
11488
+ const packageConfig = (config.resources || {})[packageName] || {}
11489
+ packageConfig.globals = packageConfig.globals || {}
11490
+ packageConfig.packages = packageConfig.packages || {}
11491
+ packageConfig.builtin = packageConfig.builtin || {}
11492
+ return packageConfig
11493
+ }
11494
+
11495
+ // util for getting the prototype chain as an array
11496
+ // includes the provided value in the result
11497
+ function getPrototypeChain (value) {
11498
+ const protoChain = []
11499
+ let current = value
11500
+ while (current && (typeof current === 'object' || typeof current === 'function')) {
11501
+ protoChain.push(current)
11502
+ current = Reflect.getPrototypeOf(current)
11503
+ }
11504
+ return protoChain
11505
+ }
11506
+
11507
+ function shouldAvoidProp(propsToAvoid, prop) {
11508
+ for (const avoid of propsToAvoid) {
11509
+ if (avoid instanceof RegExp && avoid.test(prop)) {
11510
+ return true
11511
+ }
11512
+ if (propsToAvoid.has(prop)) {
11513
+ return true
11514
+ }
11515
+ }
11516
+ return false
11517
+ }
11518
+ }
11519
+ })()
11520
+
11521
+ const kernel = createKernelCore({
11522
+ lavamoatConfig,
11523
+ loadModuleData,
11524
+ getRelativeModuleId,
11525
+ prepareModuleInitializerArgs,
11526
+ getExternalCompartment,
11527
+ globalRef,
11528
+ globalThisRefs,
11529
+ scuttleGlobalThis,
11530
+ scuttleGlobalThisExceptions,
11531
+ debugMode,
11532
+ runWithPrecompiledModules,
11533
+ reportStatsHook,
11534
+ })
11535
+ return kernel
11536
+ }
11537
+ })()
11538
+
11539
+ const kernel = createKernel({
11540
+ runWithPrecompiledModules: true,
11541
+ lavamoatConfig: lavamoatPolicy,
11542
+ loadModuleData,
11543
+ getRelativeModuleId,
11544
+ prepareModuleInitializerArgs,
11545
+ globalThisRefs: ['window', 'self', 'global', 'globalThis'],
11546
+ debugMode,
11547
+ reportStatsHook,
11548
+ })
11549
+ const { internalRequire } = kernel
11550
+
11551
+ // create a lavamoat pulic API for loading modules over multiple files
11552
+ const LavaPack = Object.freeze({
11553
+ loadPolicy: Object.freeze(loadPolicy),
11554
+ loadBundle: Object.freeze(loadBundle),
11555
+ runModule: Object.freeze(runModule),
11556
+ })
11557
+ // in debug mode, expose the kernel on the LavaPack API
11558
+ if (debugMode) {
11559
+ LavaPack._kernel = kernel
11560
+ }
11561
+
11562
+ Object.defineProperty(globalThis, 'LavaPack', {value: LavaPack})
11563
+ return
11564
+
11565
+
11566
+ function loadModuleData (moduleId) {
11567
+ if (typeof window === 'undefined' && require('node:module').isBuiltin(moduleId)) {
11568
+ return {
11569
+ type: 'builtin',
11570
+ package: moduleId,
11571
+ id: moduleId,
11572
+ // Using unprotected require
11573
+ moduleInitializer: (_, module) => {
11574
+ module.exports = require(moduleId);
11575
+ },
11576
+ }
11577
+ }
11578
+ if (!moduleRegistry.has(moduleId)) {
11579
+ throw new Error(`no module registered for "${moduleId}" (${typeof moduleId})`)
11580
+ }
11581
+ return moduleRegistry.get(moduleId)
11582
+ }
11583
+
11584
+ function getRelativeModuleId (parentModuleId, requestedName) {
11585
+ const parentModuleData = loadModuleData(parentModuleId)
11586
+ if (!(requestedName in parentModuleData.deps)) {
11587
+ console.warn(`missing dep: ${parentModuleData.package} requested ${requestedName}`)
11588
+ }
11589
+ return parentModuleData.deps[requestedName] || requestedName
11590
+ }
11591
+
11592
+ function prepareModuleInitializerArgs (requireRelativeWithContext, moduleObj, moduleData) {
11593
+ const require = requireRelativeWithContext
11594
+ const module = moduleObj
11595
+ const exports = moduleObj.exports
11596
+ // bify direct module instantiation disabled ("arguments[4]")
11597
+ return [require, module, exports, null, null]
11598
+ }
11599
+
11600
+ // it is called by the policy loader or modules collection
11601
+ function loadPolicy (bundlePolicy) {
11602
+ // verify + load config
11603
+ Object.entries(bundlePolicy.resources || {}).forEach(([packageName, packageConfig]) => {
11604
+ if (packageName in lavamoatPolicy) {
11605
+ throw new Error(`LavaMoat - loadBundle encountered redundant config definition for package "${packageName}"`)
11606
+ }
11607
+ lavamoatPolicy.resources[packageName] = packageConfig
11608
+ })
11609
+ }
11610
+
11611
+ // it is called by the modules collection
11612
+ function loadBundle (newModules, entryPoints, bundlePolicy) {
11613
+ // verify + load config
11614
+ if (bundlePolicy) {
11615
+ loadPolicy(bundlePolicy)
11616
+ }
11617
+ // verify + load in each module
11618
+ for (const [moduleId, moduleDeps, initFn, { package: packageName, type }] of newModules) {
11619
+ // verify that module is new
11620
+ if (moduleRegistry.has(moduleId)) {
11621
+ throw new Error(`LavaMoat - loadBundle encountered redundant module definition for id "${moduleId}"`)
11622
+ }
11623
+ // add the module
11624
+ moduleRegistry.set(moduleId, {
11625
+ type: type || 'js',
11626
+ id: moduleId,
11627
+ deps: moduleDeps,
11628
+ // source: `(${initFn})`,
11629
+ precompiledInitializer: initFn,
11630
+ package: packageName,
11631
+ })
11632
+ }
11633
+ // run each of entryPoints
11634
+ const entryExports = Array.prototype.map.call(entryPoints, (entryId) => {
11635
+ return runModule(entryId)
11636
+ })
11637
+ // webpack compat: return the first module's exports
11638
+ return entryExports[0]
11639
+ }
11640
+
11641
+ function runModule (moduleId) {
11642
+ if (!moduleRegistry.has(moduleId)) {
11643
+ throw new Error(`no module registered for "${moduleId}" (${typeof moduleId})`)
11644
+ }
11645
+ return internalRequire(moduleId)
11646
+ }
11647
+
11648
+ // called by reportStatsHook
11649
+ function onStatsReady (moduleGraphStatsObj) {
11650
+ const graphId = Date.now()
11651
+ console.warn(`completed module graph init "${graphId}" in ${moduleGraphStatsObj.value}ms ("${moduleGraphStatsObj.name}")`)
11652
+ console.warn('logging module init stats object:')
11653
+ console.warn(JSON.stringify(moduleGraphStatsObj, null, 2))
11654
+ }
11655
+
11656
+ })()
11657
+ </script>
11658
+ <script src="bundle.js"></script>
11659
+ </head>
11660
+ </html>