@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.
- package/dist/browserify/iframe/bundle.js +6435 -0
- package/dist/{webpack → browserify}/iframe/index.html +1411 -178
- package/dist/browserify/node-process/bundle.js +15135 -0
- package/dist/browserify/node-thread/bundle.js +15135 -0
- package/dist/browserify/offscreen/bundle.js +2266 -0
- package/dist/{webpack → browserify}/offscreen/index.html +1411 -178
- package/dist/common/endowments/commonEndowmentFactory.d.ts +1 -0
- package/dist/common/endowments/commonEndowmentFactory.js +9 -3
- package/dist/common/endowments/commonEndowmentFactory.js.map +1 -1
- package/dist/common/endowments/index.d.ts +0 -7
- package/dist/common/endowments/index.js +4 -24
- package/dist/common/endowments/index.js.map +1 -1
- package/dist/common/lockdown/lockdown-events.d.ts +4 -0
- package/dist/common/lockdown/lockdown-events.js +60 -0
- package/dist/common/lockdown/lockdown-events.js.map +1 -0
- package/dist/iframe/index.js +3 -2
- package/dist/iframe/index.js.map +1 -1
- package/dist/node-process/index.js +1 -2
- package/dist/node-process/index.js.map +1 -1
- package/dist/node-thread/index.js +1 -2
- package/dist/node-thread/index.js.map +1 -1
- package/dist/offscreen/index.js +3 -2
- package/dist/offscreen/index.js.map +1 -1
- package/package.json +18 -18
- package/dist/webpack/iframe/bundle.js +0 -2
- package/dist/webpack/iframe/bundle.js.LICENSE.txt +0 -14
- package/dist/webpack/node-process/bundle.js +0 -111579
- package/dist/webpack/node-process/lockdown.umd.min.js +0 -1
- package/dist/webpack/node-thread/bundle.js +0 -111579
- package/dist/webpack/node-thread/lockdown.umd.min.js +0 -1
- package/dist/webpack/offscreen/bundle.js +0 -2
- 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 {
|
|
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
|
-
//
|
|
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 {
|
|
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 {
|
|
2424
|
-
|
|
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
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
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
|
-
|
|
4394
|
-
|
|
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
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
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[
|
|
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 [
|
|
5113
|
-
if( !notifiers[
|
|
5114
|
-
notifiers[
|
|
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[
|
|
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 {
|
|
5313
|
-
|
|
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 {
|
|
6567
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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 {
|
|
9014
|
-
|
|
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 {
|
|
9121
|
-
|
|
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
|
-
|
|
9355
|
+
function cell(name, value = undefined) {
|
|
9313
9356
|
const observers = [];
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
9643
|
-
|
|
9644
|
-
|
|
9645
|
-
|
|
9646
|
-
|
|
9647
|
-
|
|
9648
|
-
|
|
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
|
-
|
|
10427
|
-
|
|
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>
|