@endo/compartment-mapper 1.6.3 → 2.0.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/package.json +12 -16
- package/src/archive-lite.d.ts +7 -7
- package/src/archive-lite.d.ts.map +1 -1
- package/src/archive-lite.js +78 -27
- package/src/archive.d.ts.map +1 -1
- package/src/archive.js +7 -0
- package/src/bundle-lite.d.ts +3 -3
- package/src/bundle-lite.d.ts.map +1 -1
- package/src/bundle-lite.js +19 -24
- package/src/bundle.d.ts +3 -3
- package/src/bundle.d.ts.map +1 -1
- package/src/bundle.js +19 -24
- package/src/capture-lite.d.ts +2 -2
- package/src/capture-lite.d.ts.map +1 -1
- package/src/capture-lite.js +217 -25
- package/src/compartment-map.d.ts +9 -2
- package/src/compartment-map.d.ts.map +1 -1
- package/src/compartment-map.js +737 -254
- package/src/digest.d.ts +22 -2
- package/src/digest.d.ts.map +1 -1
- package/src/digest.js +179 -56
- package/src/generic-graph.d.ts.map +1 -1
- package/src/generic-graph.js +8 -3
- package/src/guards.d.ts +18 -0
- package/src/guards.d.ts.map +1 -0
- package/src/guards.js +109 -0
- package/src/hooks.md +124 -0
- package/src/import-archive-lite.d.ts.map +1 -1
- package/src/import-archive-lite.js +15 -11
- package/src/import-archive.d.ts +5 -19
- package/src/import-archive.d.ts.map +1 -1
- package/src/import-archive.js +7 -27
- package/src/import-hook.d.ts +4 -3
- package/src/import-hook.d.ts.map +1 -1
- package/src/import-hook.js +138 -69
- package/src/import-lite.d.ts +6 -6
- package/src/import-lite.d.ts.map +1 -1
- package/src/import-lite.js +8 -5
- package/src/import.d.ts +3 -3
- package/src/import.d.ts.map +1 -1
- package/src/import.js +16 -6
- package/src/infer-exports.d.ts.map +1 -1
- package/src/infer-exports.js +16 -6
- package/src/link.d.ts +4 -3
- package/src/link.d.ts.map +1 -1
- package/src/link.js +70 -58
- package/src/node-modules.d.ts +4 -3
- package/src/node-modules.d.ts.map +1 -1
- package/src/node-modules.js +482 -114
- package/src/parse-cjs-shared-export-wrapper.d.ts.map +1 -1
- package/src/parse-cjs-shared-export-wrapper.js +3 -1
- package/src/policy-format.d.ts +22 -5
- package/src/policy-format.d.ts.map +1 -1
- package/src/policy-format.js +342 -108
- package/src/policy.d.ts +13 -28
- package/src/policy.d.ts.map +1 -1
- package/src/policy.js +161 -106
- package/src/types/canonical-name.d.ts +97 -0
- package/src/types/canonical-name.d.ts.map +1 -0
- package/src/types/canonical-name.ts +151 -0
- package/src/types/compartment-map-schema.d.ts +114 -35
- package/src/types/compartment-map-schema.d.ts.map +1 -1
- package/src/types/compartment-map-schema.ts +202 -37
- package/src/types/external.d.ts +168 -28
- package/src/types/external.d.ts.map +1 -1
- package/src/types/external.ts +215 -26
- package/src/types/internal.d.ts +23 -42
- package/src/types/internal.d.ts.map +1 -1
- package/src/types/internal.ts +51 -50
- package/src/types/node-modules.d.ts +71 -10
- package/src/types/node-modules.d.ts.map +1 -1
- package/src/types/node-modules.ts +107 -9
- package/src/types/policy-schema.d.ts +26 -11
- package/src/types/policy-schema.d.ts.map +1 -1
- package/src/types/policy-schema.ts +29 -16
- package/src/types/policy.d.ts +6 -2
- package/src/types/policy.d.ts.map +1 -1
- package/src/types/policy.ts +7 -2
- package/src/types/typescript.d.ts +28 -0
- package/src/types/typescript.d.ts.map +1 -1
- package/src/types/typescript.ts +37 -1
package/src/node-modules.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-underscore-dangle */
|
|
1
2
|
/**
|
|
2
3
|
* Provides functions for constructing a compartment map that has a
|
|
3
4
|
* compartment descriptor corresponding to every reachable package from an
|
|
@@ -16,12 +17,13 @@
|
|
|
16
17
|
import { inferExportsAndAliases } from './infer-exports.js';
|
|
17
18
|
import { parseLocatedJson } from './json.js';
|
|
18
19
|
import { join } from './node-module-specifier.js';
|
|
19
|
-
import { assertPolicy } from './policy-format.js';
|
|
20
20
|
import {
|
|
21
|
+
assertPolicy,
|
|
21
22
|
ATTENUATORS_COMPARTMENT,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
} from './policy.js';
|
|
23
|
+
ENTRY_COMPARTMENT,
|
|
24
|
+
generateCanonicalName,
|
|
25
|
+
} from './policy-format.js';
|
|
26
|
+
import { dependencyAllowedByPolicy, makePackagePolicy } from './policy.js';
|
|
25
27
|
import { unpackReadPowers } from './powers.js';
|
|
26
28
|
import { search, searchDescriptor } from './search.js';
|
|
27
29
|
import { GenericGraph, makeShortestPath } from './generic-graph.js';
|
|
@@ -41,8 +43,16 @@ import { GenericGraph, makeShortestPath } from './generic-graph.js';
|
|
|
41
43
|
* PackageDescriptor,
|
|
42
44
|
* ReadFn,
|
|
43
45
|
* ReadPowers,
|
|
44
|
-
* SomePackagePolicy,
|
|
45
46
|
* SomePolicy,
|
|
47
|
+
* LogFn,
|
|
48
|
+
* CompartmentModuleConfiguration,
|
|
49
|
+
* PackageCompartmentDescriptor,
|
|
50
|
+
* PackageCompartmentMapDescriptor,
|
|
51
|
+
* ScopeDescriptor,
|
|
52
|
+
* CanonicalName,
|
|
53
|
+
* SomePackagePolicy,
|
|
54
|
+
* PackageCompartmentDescriptorName,
|
|
55
|
+
* PackageData,
|
|
46
56
|
* } from './types.js'
|
|
47
57
|
* @import {
|
|
48
58
|
* Graph,
|
|
@@ -54,21 +64,78 @@ import { GenericGraph, makeShortestPath } from './generic-graph.js';
|
|
|
54
64
|
* GraphPackagesOptions,
|
|
55
65
|
* LogicalPathGraph,
|
|
56
66
|
* PackageDetails,
|
|
67
|
+
* FinalGraph,
|
|
68
|
+
* CanonicalNameMap,
|
|
69
|
+
* FinalNode,
|
|
70
|
+
TranslateGraphOptions,
|
|
57
71
|
* } from './types/node-modules.js'
|
|
58
72
|
*/
|
|
59
73
|
|
|
60
|
-
const { assign, create, keys, values, entries } = Object;
|
|
74
|
+
const { assign, create, keys, values, entries, freeze } = Object;
|
|
61
75
|
|
|
62
76
|
const decoder = new TextDecoder();
|
|
63
77
|
|
|
64
78
|
// q, as in quote, for enquoting strings in error messages.
|
|
65
|
-
const q =
|
|
79
|
+
const { quote: q } = assert;
|
|
66
80
|
|
|
67
81
|
/**
|
|
68
82
|
* Default logger that does nothing.
|
|
69
83
|
*/
|
|
70
84
|
const noop = () => {};
|
|
71
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Default handler for unknown canonical names found in policy.
|
|
88
|
+
* Logs a warning when a canonical name from policy is not found in the compartment map.
|
|
89
|
+
*
|
|
90
|
+
* @param {object} params
|
|
91
|
+
* @param {CanonicalName} params.canonicalName
|
|
92
|
+
* @param {string} params.message
|
|
93
|
+
* @param {LogFn} params.log
|
|
94
|
+
*/
|
|
95
|
+
const defaultUnknownCanonicalNameHandler = ({
|
|
96
|
+
canonicalName,
|
|
97
|
+
message,
|
|
98
|
+
log,
|
|
99
|
+
}) => {
|
|
100
|
+
log(`WARN: Invalid resource ${q(canonicalName)} in policy: ${message}`);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Default filter for package dependencies based on policy.
|
|
105
|
+
* Filters out dependencies not allowed by the package policy.
|
|
106
|
+
*
|
|
107
|
+
* **Note:** This filter is _only_ applied if a policy is provided.
|
|
108
|
+
*
|
|
109
|
+
* @param {object} params - The parameters object
|
|
110
|
+
* @param {CanonicalName} params.canonicalName - The canonical name of the package
|
|
111
|
+
* @param {Readonly<Set<CanonicalName>>} params.dependencies - The set of dependencies
|
|
112
|
+
* @param {LogFn} params.log - The logging function
|
|
113
|
+
* @param {SomePolicy} policy - The policy to check against
|
|
114
|
+
* @returns {Partial<{ dependencies: Set<CanonicalName> }> | void}
|
|
115
|
+
*/
|
|
116
|
+
const prePackageDependenciesFilter = (
|
|
117
|
+
{ canonicalName, dependencies, log },
|
|
118
|
+
policy,
|
|
119
|
+
) => {
|
|
120
|
+
const packagePolicy = makePackagePolicy(canonicalName, { policy });
|
|
121
|
+
if (!packagePolicy) {
|
|
122
|
+
return { dependencies };
|
|
123
|
+
}
|
|
124
|
+
const filteredDependencies = new Set(
|
|
125
|
+
[...dependencies].filter(dependency => {
|
|
126
|
+
const allowed = dependencyAllowedByPolicy(dependency, packagePolicy);
|
|
127
|
+
if (!allowed) {
|
|
128
|
+
log(
|
|
129
|
+
`Excluding dependency ${q(dependency)} of package ${q(canonicalName)} per policy`,
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
return allowed;
|
|
133
|
+
}),
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
return { dependencies: filteredDependencies };
|
|
137
|
+
};
|
|
138
|
+
|
|
72
139
|
/**
|
|
73
140
|
* Given a relative path andd URL, return a fully qualified URL string.
|
|
74
141
|
*
|
|
@@ -368,7 +435,7 @@ const calculatePackageWeight = packageName => {
|
|
|
368
435
|
* @param {LanguageOptions} languageOptions
|
|
369
436
|
* @param {boolean} strict
|
|
370
437
|
* @param {LogicalPathGraph} logicalPathGraph
|
|
371
|
-
* @param {GraphPackageOptions}
|
|
438
|
+
* @param {GraphPackageOptions} options
|
|
372
439
|
* @returns {Promise<undefined>}
|
|
373
440
|
*/
|
|
374
441
|
const graphPackage = async (
|
|
@@ -382,7 +449,12 @@ const graphPackage = async (
|
|
|
382
449
|
languageOptions,
|
|
383
450
|
strict,
|
|
384
451
|
logicalPathGraph,
|
|
385
|
-
{
|
|
452
|
+
{
|
|
453
|
+
commonDependencyDescriptors = {},
|
|
454
|
+
log = noop,
|
|
455
|
+
packageDependenciesHook,
|
|
456
|
+
policy,
|
|
457
|
+
} = {},
|
|
386
458
|
) => {
|
|
387
459
|
if (graph[packageLocation] !== undefined) {
|
|
388
460
|
// Returning the promise here would create a causal cycle and stall recursion.
|
|
@@ -397,7 +469,7 @@ const graphPackage = async (
|
|
|
397
469
|
});
|
|
398
470
|
}
|
|
399
471
|
|
|
400
|
-
const result = /** @type {Node} */ ({});
|
|
472
|
+
const result = /** @type {Node} */ ({ location: packageLocation });
|
|
401
473
|
graph[packageLocation] = result;
|
|
402
474
|
|
|
403
475
|
/** @type {Node['dependencyLocations']} */
|
|
@@ -461,7 +533,6 @@ const graphPackage = async (
|
|
|
461
533
|
|
|
462
534
|
for (const dependencyName of [...allDependencies].sort()) {
|
|
463
535
|
const optional = optionals.has(dependencyName);
|
|
464
|
-
const childLogicalPath = [...logicalPath, dependencyName];
|
|
465
536
|
children.push(
|
|
466
537
|
// Mutual recursion ahead:
|
|
467
538
|
// eslint-disable-next-line no-use-before-define
|
|
@@ -477,10 +548,11 @@ const graphPackage = async (
|
|
|
477
548
|
strict,
|
|
478
549
|
logicalPathGraph,
|
|
479
550
|
{
|
|
480
|
-
childLogicalPath,
|
|
481
551
|
optional,
|
|
482
552
|
commonDependencyDescriptors,
|
|
483
553
|
log,
|
|
554
|
+
packageDependenciesHook,
|
|
555
|
+
policy,
|
|
484
556
|
},
|
|
485
557
|
),
|
|
486
558
|
);
|
|
@@ -522,9 +594,9 @@ const graphPackage = async (
|
|
|
522
594
|
|
|
523
595
|
const sourceDirname = basename(packageLocation);
|
|
524
596
|
|
|
525
|
-
|
|
597
|
+
/** @type {Partial<Node>} */
|
|
598
|
+
const partialNode = {
|
|
526
599
|
name,
|
|
527
|
-
path: logicalPath,
|
|
528
600
|
label: `${name}${version ? `-v${version}` : ''}`,
|
|
529
601
|
sourceDirname,
|
|
530
602
|
explicitExports: exportsDescriptor !== undefined,
|
|
@@ -533,7 +605,9 @@ const graphPackage = async (
|
|
|
533
605
|
dependencyLocations,
|
|
534
606
|
types,
|
|
535
607
|
parsers,
|
|
536
|
-
|
|
608
|
+
packageDescriptor,
|
|
609
|
+
};
|
|
610
|
+
assign(result, partialNode);
|
|
537
611
|
|
|
538
612
|
await Promise.all(
|
|
539
613
|
values(result.externalAliases).map(async item => {
|
|
@@ -605,10 +679,11 @@ const gatherDependency = async (
|
|
|
605
679
|
strict,
|
|
606
680
|
logicalPathGraph,
|
|
607
681
|
{
|
|
608
|
-
childLogicalPath = [],
|
|
609
682
|
optional = false,
|
|
610
683
|
commonDependencyDescriptors = {},
|
|
611
684
|
log = noop,
|
|
685
|
+
packageDependenciesHook,
|
|
686
|
+
policy,
|
|
612
687
|
} = {},
|
|
613
688
|
) => {
|
|
614
689
|
const dependency = await findPackage(
|
|
@@ -617,6 +692,7 @@ const gatherDependency = async (
|
|
|
617
692
|
packageLocation,
|
|
618
693
|
name,
|
|
619
694
|
);
|
|
695
|
+
|
|
620
696
|
if (dependency === undefined) {
|
|
621
697
|
// allow the dependency to be missing if optional
|
|
622
698
|
if (optional || !strict) {
|
|
@@ -624,6 +700,7 @@ const gatherDependency = async (
|
|
|
624
700
|
}
|
|
625
701
|
throw Error(`Cannot find dependency ${name} for ${packageLocation}`);
|
|
626
702
|
}
|
|
703
|
+
|
|
627
704
|
dependencyLocations[name] = dependency.packageLocation;
|
|
628
705
|
|
|
629
706
|
logicalPathGraph.addEdge(
|
|
@@ -645,8 +722,9 @@ const gatherDependency = async (
|
|
|
645
722
|
logicalPathGraph,
|
|
646
723
|
{
|
|
647
724
|
commonDependencyDescriptors,
|
|
648
|
-
logicalPath: childLogicalPath,
|
|
649
725
|
log,
|
|
726
|
+
packageDependenciesHook,
|
|
727
|
+
policy,
|
|
650
728
|
},
|
|
651
729
|
);
|
|
652
730
|
};
|
|
@@ -669,7 +747,7 @@ const gatherDependency = async (
|
|
|
669
747
|
* @param {LanguageOptions} languageOptions
|
|
670
748
|
* @param {boolean} strict
|
|
671
749
|
* @param {LogicalPathGraph} logicalPathGraph
|
|
672
|
-
* @param {GraphPackagesOptions}
|
|
750
|
+
* @param {GraphPackagesOptions} options
|
|
673
751
|
* @returns {Promise<Graph>}
|
|
674
752
|
*/
|
|
675
753
|
const graphPackages = async (
|
|
@@ -683,7 +761,7 @@ const graphPackages = async (
|
|
|
683
761
|
languageOptions,
|
|
684
762
|
strict,
|
|
685
763
|
logicalPathGraph,
|
|
686
|
-
{ log = noop } = {},
|
|
764
|
+
{ log = noop, packageDependenciesHook, policy } = {},
|
|
687
765
|
) => {
|
|
688
766
|
const memo = create(null);
|
|
689
767
|
/**
|
|
@@ -749,6 +827,8 @@ const graphPackages = async (
|
|
|
749
827
|
{
|
|
750
828
|
commonDependencyDescriptors,
|
|
751
829
|
log,
|
|
830
|
+
packageDependenciesHook,
|
|
831
|
+
policy,
|
|
752
832
|
},
|
|
753
833
|
);
|
|
754
834
|
return graph;
|
|
@@ -763,19 +843,101 @@ const graphPackages = async (
|
|
|
763
843
|
* @param {Graph} graph
|
|
764
844
|
* @param {Set<string>} conditions - build conditions about the target environment
|
|
765
845
|
* for selecting relevant exports, e.g., "browser" or "node".
|
|
766
|
-
* @param {
|
|
767
|
-
* @returns {
|
|
846
|
+
* @param {TranslateGraphOptions} [options]
|
|
847
|
+
* @returns {PackageCompartmentMapDescriptor}
|
|
768
848
|
*/
|
|
769
849
|
const translateGraph = (
|
|
770
850
|
entryPackageLocation,
|
|
771
851
|
entryModuleSpecifier,
|
|
772
852
|
graph,
|
|
773
853
|
conditions,
|
|
774
|
-
policy,
|
|
854
|
+
{ policy, log = noop, packageDependenciesHook } = {},
|
|
775
855
|
) => {
|
|
776
|
-
/** @type {
|
|
856
|
+
/** @type {Record<PackageCompartmentDescriptorName, PackageCompartmentDescriptor>} */
|
|
777
857
|
const compartments = create(null);
|
|
778
858
|
|
|
859
|
+
/**
|
|
860
|
+
* Execute package dependencies hooks: default first (if policy exists), then user-provided.
|
|
861
|
+
*
|
|
862
|
+
* @param {CanonicalName} label
|
|
863
|
+
* @param {Record<string, FileUrlString>} dependencyLocations
|
|
864
|
+
* @returns {Record<string, FileUrlString>}
|
|
865
|
+
*/
|
|
866
|
+
const executePackageDependenciesHook = (label, dependencyLocations) => {
|
|
867
|
+
const dependencies = new Set(
|
|
868
|
+
values(dependencyLocations).map(
|
|
869
|
+
dependencyLocation => graph[dependencyLocation].label,
|
|
870
|
+
),
|
|
871
|
+
);
|
|
872
|
+
|
|
873
|
+
const packageDependenciesHookInput = {
|
|
874
|
+
canonicalName: label,
|
|
875
|
+
dependencies: new Set(dependencies),
|
|
876
|
+
log,
|
|
877
|
+
};
|
|
878
|
+
|
|
879
|
+
// Call default filter first if policy exists
|
|
880
|
+
let packageDependenciesHookResult;
|
|
881
|
+
if (policy) {
|
|
882
|
+
packageDependenciesHookResult = prePackageDependenciesFilter(
|
|
883
|
+
packageDependenciesHookInput,
|
|
884
|
+
policy,
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
// Then call user-provided hook if it exists
|
|
889
|
+
if (packageDependenciesHook) {
|
|
890
|
+
const userResult = packageDependenciesHook(packageDependenciesHookInput);
|
|
891
|
+
// If user hook also returned a result, use it (overrides default)
|
|
892
|
+
if (userResult?.dependencies) {
|
|
893
|
+
packageDependenciesHookResult = userResult;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
// if "dependencies" are in here, then something changed the list.
|
|
898
|
+
if (packageDependenciesHookResult?.dependencies) {
|
|
899
|
+
const size = packageDependenciesHookResult.dependencies.size;
|
|
900
|
+
if (typeof size === 'number' && size > 0) {
|
|
901
|
+
// because the list of dependencies contains canonical names, we need to lookup any new ones.
|
|
902
|
+
const nodesByCanonicalName = new Map(
|
|
903
|
+
entries(graph).map(([location, node]) => [
|
|
904
|
+
node.label,
|
|
905
|
+
{
|
|
906
|
+
...node,
|
|
907
|
+
packageLocation: /** @type {FileUrlString} */ (location),
|
|
908
|
+
},
|
|
909
|
+
]),
|
|
910
|
+
);
|
|
911
|
+
|
|
912
|
+
/** @type {typeof dependencyLocations} */
|
|
913
|
+
const newDependencyLocations = {};
|
|
914
|
+
try {
|
|
915
|
+
for (const label of packageDependenciesHookResult.dependencies) {
|
|
916
|
+
const { name, packageLocation } =
|
|
917
|
+
nodesByCanonicalName.get(label) ?? create(null);
|
|
918
|
+
if (name && packageLocation) {
|
|
919
|
+
newDependencyLocations[name] = packageLocation;
|
|
920
|
+
} else {
|
|
921
|
+
log(
|
|
922
|
+
`WARNING: packageDependencies hook returned unknown package with label ${q(label)}`,
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
return newDependencyLocations;
|
|
927
|
+
} catch {
|
|
928
|
+
log(
|
|
929
|
+
`WARNING: packageDependencies hook returned invalid value ${q(
|
|
930
|
+
packageDependenciesHookResult,
|
|
931
|
+
)}; using original dependencies`,
|
|
932
|
+
);
|
|
933
|
+
}
|
|
934
|
+
} else {
|
|
935
|
+
dependencyLocations = create(null);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
return dependencyLocations;
|
|
939
|
+
};
|
|
940
|
+
|
|
779
941
|
// For each package, build a map of all the external modules the package can
|
|
780
942
|
// import from other packages.
|
|
781
943
|
// The keys of this map are the full specifiers of those modules from the
|
|
@@ -785,36 +947,24 @@ const translateGraph = (
|
|
|
785
947
|
// The full map includes every exported module from every dependencey
|
|
786
948
|
// package and is a complete list of every external module that the
|
|
787
949
|
// corresponding compartment can import.
|
|
788
|
-
for (const dependeeLocation of
|
|
950
|
+
for (const dependeeLocation of /** @type {PackageCompartmentDescriptorName[]} */ (
|
|
951
|
+
keys(graph).sort()
|
|
952
|
+
)) {
|
|
789
953
|
const {
|
|
790
954
|
name,
|
|
791
|
-
path,
|
|
792
955
|
label,
|
|
793
956
|
sourceDirname,
|
|
794
|
-
dependencyLocations,
|
|
795
957
|
internalAliases,
|
|
796
958
|
parsers,
|
|
797
959
|
types,
|
|
960
|
+
packageDescriptor,
|
|
798
961
|
} = graph[dependeeLocation];
|
|
799
|
-
/** @type {
|
|
962
|
+
/** @type {Record<string, CompartmentModuleConfiguration>} */
|
|
800
963
|
const moduleDescriptors = create(null);
|
|
801
|
-
/** @type {
|
|
964
|
+
/** @type {Record<string, ScopeDescriptor<PackageCompartmentDescriptorName>>} */
|
|
802
965
|
const scopes = create(null);
|
|
803
966
|
|
|
804
|
-
|
|
805
|
-
* List of all the compartments (by name) that this compartment can import from.
|
|
806
|
-
*
|
|
807
|
-
* @type {Set<string>}
|
|
808
|
-
*/
|
|
809
|
-
const compartmentNames = new Set();
|
|
810
|
-
const packagePolicy = getPolicyForPackage(
|
|
811
|
-
{
|
|
812
|
-
isEntry: dependeeLocation === entryPackageLocation,
|
|
813
|
-
name,
|
|
814
|
-
path,
|
|
815
|
-
},
|
|
816
|
-
policy,
|
|
817
|
-
);
|
|
967
|
+
const packagePolicy = makePackagePolicy(label, { policy });
|
|
818
968
|
|
|
819
969
|
/* c8 ignore next */
|
|
820
970
|
if (policy && !packagePolicy) {
|
|
@@ -822,34 +972,29 @@ const translateGraph = (
|
|
|
822
972
|
throw new TypeError('Unexpectedly falsy package policy');
|
|
823
973
|
}
|
|
824
974
|
|
|
975
|
+
let dependencyLocations = graph[dependeeLocation].dependencyLocations;
|
|
976
|
+
dependencyLocations = executePackageDependenciesHook(
|
|
977
|
+
label,
|
|
978
|
+
dependencyLocations,
|
|
979
|
+
);
|
|
980
|
+
|
|
825
981
|
/**
|
|
826
982
|
* @param {string} dependencyName
|
|
827
|
-
* @param {
|
|
983
|
+
* @param {PackageCompartmentDescriptorName} packageLocation
|
|
828
984
|
*/
|
|
829
985
|
const digestExternalAliases = (dependencyName, packageLocation) => {
|
|
830
|
-
const { externalAliases, explicitExports
|
|
831
|
-
graph[packageLocation];
|
|
986
|
+
const { externalAliases, explicitExports } = graph[packageLocation];
|
|
832
987
|
for (const exportPath of keys(externalAliases).sort()) {
|
|
833
988
|
const targetPath = externalAliases[exportPath];
|
|
834
989
|
// dependency name may be different from package's name,
|
|
835
|
-
// as in the case of browser field dependency replacements
|
|
990
|
+
// as in the case of browser field dependency replacements.
|
|
991
|
+
// note that policy still applies
|
|
836
992
|
const localPath = join(dependencyName, exportPath);
|
|
837
|
-
if
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
name,
|
|
843
|
-
path,
|
|
844
|
-
},
|
|
845
|
-
packagePolicy,
|
|
846
|
-
))
|
|
847
|
-
) {
|
|
848
|
-
moduleDescriptors[localPath] = {
|
|
849
|
-
compartment: packageLocation,
|
|
850
|
-
module: targetPath,
|
|
851
|
-
};
|
|
852
|
-
}
|
|
993
|
+
// if we have policy, this has already been vetted
|
|
994
|
+
moduleDescriptors[localPath] = {
|
|
995
|
+
compartment: packageLocation,
|
|
996
|
+
module: targetPath,
|
|
997
|
+
};
|
|
853
998
|
}
|
|
854
999
|
// if the exports field is not present, then all modules must be accessible
|
|
855
1000
|
if (!explicitExports) {
|
|
@@ -864,7 +1009,6 @@ const translateGraph = (
|
|
|
864
1009
|
for (const dependencyName of keys(dependencyLocations).sort()) {
|
|
865
1010
|
const dependencyLocation = dependencyLocations[dependencyName];
|
|
866
1011
|
digestExternalAliases(dependencyName, dependencyLocation);
|
|
867
|
-
compartmentNames.add(dependencyLocation);
|
|
868
1012
|
}
|
|
869
1013
|
// digest own internal aliases
|
|
870
1014
|
for (const modulePath of keys(internalAliases).sort()) {
|
|
@@ -881,9 +1025,9 @@ const translateGraph = (
|
|
|
881
1025
|
}
|
|
882
1026
|
|
|
883
1027
|
compartments[dependeeLocation] = {
|
|
1028
|
+
version: packageDescriptor.version ? packageDescriptor.version : '',
|
|
884
1029
|
label,
|
|
885
1030
|
name,
|
|
886
|
-
path,
|
|
887
1031
|
location: dependeeLocation,
|
|
888
1032
|
sourceDirname,
|
|
889
1033
|
modules: moduleDescriptors,
|
|
@@ -891,7 +1035,6 @@ const translateGraph = (
|
|
|
891
1035
|
parsers,
|
|
892
1036
|
types,
|
|
893
1037
|
policy: /** @type {SomePackagePolicy} */ (packagePolicy),
|
|
894
|
-
compartments: compartmentNames,
|
|
895
1038
|
};
|
|
896
1039
|
}
|
|
897
1040
|
|
|
@@ -900,7 +1043,7 @@ const translateGraph = (
|
|
|
900
1043
|
// https://github.com/endojs/endo/issues/2388
|
|
901
1044
|
tags: [...conditions],
|
|
902
1045
|
entry: {
|
|
903
|
-
compartment: entryPackageLocation,
|
|
1046
|
+
compartment: /** @type {FileUrlString} */ (entryPackageLocation),
|
|
904
1047
|
module: entryModuleSpecifier,
|
|
905
1048
|
},
|
|
906
1049
|
compartments,
|
|
@@ -974,23 +1117,200 @@ const makeLanguageOptions = ({
|
|
|
974
1117
|
workspaceModuleLanguageForExtension,
|
|
975
1118
|
};
|
|
976
1119
|
};
|
|
1120
|
+
/**
|
|
1121
|
+
* Creates a `Node` in `graph` corresponding to the "attenuators" Compartment.
|
|
1122
|
+
*
|
|
1123
|
+
* Only does so if `policy` is provided.
|
|
1124
|
+
*
|
|
1125
|
+
* @param {Graph} graph Graph
|
|
1126
|
+
* @param {Node} entryNode Entry node of the grpah
|
|
1127
|
+
* @param {SomePolicy} [policy]
|
|
1128
|
+
* @throws If there's already a `Node` in `graph` for the "attenuators"
|
|
1129
|
+
* Compartment
|
|
1130
|
+
* @returns {void}
|
|
1131
|
+
*/
|
|
1132
|
+
const makeAttenuatorsNode = (graph, entryNode, policy) => {
|
|
1133
|
+
if (policy) {
|
|
1134
|
+
assertPolicy(policy);
|
|
1135
|
+
|
|
1136
|
+
assert(
|
|
1137
|
+
graph[ATTENUATORS_COMPARTMENT] === undefined,
|
|
1138
|
+
`${q(ATTENUATORS_COMPARTMENT)} is a reserved compartment name`,
|
|
1139
|
+
);
|
|
1140
|
+
|
|
1141
|
+
graph[ATTENUATORS_COMPARTMENT] = {
|
|
1142
|
+
...entryNode,
|
|
1143
|
+
internalAliases: {},
|
|
1144
|
+
externalAliases: {},
|
|
1145
|
+
packageDescriptor: { name: ATTENUATORS_COMPARTMENT },
|
|
1146
|
+
name: ATTENUATORS_COMPARTMENT,
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1149
|
+
};
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* Transforms a `Graph` into a readonly `FinalGraph`, in preparation for
|
|
1153
|
+
* conversion to a `CompartmentDescriptor`.
|
|
1154
|
+
*
|
|
1155
|
+
* @param {Graph} graph Graph
|
|
1156
|
+
* @param {LogicalPathGraph} logicalPathGraph Logical path graph
|
|
1157
|
+
* @param {FileUrlString} entryPackageLocation Entry package location
|
|
1158
|
+
* @param {CanonicalNameMap} canonicalNameMap Mapping of canonical names to `Node` names (keys in `graph`)
|
|
1159
|
+
* @returns {Readonly<FinalGraph>}
|
|
1160
|
+
*/
|
|
1161
|
+
const finalizeGraph = (
|
|
1162
|
+
graph,
|
|
1163
|
+
logicalPathGraph,
|
|
1164
|
+
entryPackageLocation,
|
|
1165
|
+
canonicalNameMap,
|
|
1166
|
+
) => {
|
|
1167
|
+
const shortestPath = makeShortestPath(logicalPathGraph);
|
|
1168
|
+
|
|
1169
|
+
// neither the entry package nor the attenuators compartment have a path; omit
|
|
1170
|
+
const {
|
|
1171
|
+
[ATTENUATORS_COMPARTMENT]: attenuatorsNode,
|
|
1172
|
+
[entryPackageLocation]: entryNode,
|
|
1173
|
+
...subgraph
|
|
1174
|
+
} = graph;
|
|
1175
|
+
|
|
1176
|
+
/** @type {FinalGraph} */
|
|
1177
|
+
const finalGraph = create(null);
|
|
1178
|
+
|
|
1179
|
+
/** @type {Readonly<FinalNode>} */
|
|
1180
|
+
finalGraph[entryPackageLocation] = freeze({
|
|
1181
|
+
...entryNode,
|
|
1182
|
+
label: generateCanonicalName({
|
|
1183
|
+
isEntry: true,
|
|
1184
|
+
path: [],
|
|
1185
|
+
}),
|
|
1186
|
+
});
|
|
1187
|
+
|
|
1188
|
+
canonicalNameMap.set(ENTRY_COMPARTMENT, entryPackageLocation);
|
|
1189
|
+
|
|
1190
|
+
if (attenuatorsNode) {
|
|
1191
|
+
/** @type {Readonly<FinalNode>} */
|
|
1192
|
+
finalGraph[ATTENUATORS_COMPARTMENT] = freeze({
|
|
1193
|
+
...attenuatorsNode,
|
|
1194
|
+
label: generateCanonicalName({
|
|
1195
|
+
name: ATTENUATORS_COMPARTMENT,
|
|
1196
|
+
path: [],
|
|
1197
|
+
}),
|
|
1198
|
+
});
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
const subgraphEntries = /** @type {[FileUrlString, Node][]} */ (
|
|
1202
|
+
entries(subgraph)
|
|
1203
|
+
);
|
|
1204
|
+
|
|
1205
|
+
for (const [location, node] of subgraphEntries) {
|
|
1206
|
+
const shortestLogicalPath = shortestPath(entryPackageLocation, location);
|
|
1207
|
+
|
|
1208
|
+
// the first element will always be the root package location; this is omitted from the path.
|
|
1209
|
+
shortestLogicalPath.shift();
|
|
1210
|
+
|
|
1211
|
+
const path = shortestLogicalPath.map(location => graph[location].name);
|
|
1212
|
+
const canonicalName = generateCanonicalName({ path });
|
|
1213
|
+
|
|
1214
|
+
/** @type {Readonly<FinalNode>} */
|
|
1215
|
+
const finalNode = freeze({
|
|
1216
|
+
...node,
|
|
1217
|
+
label: canonicalName,
|
|
1218
|
+
});
|
|
1219
|
+
|
|
1220
|
+
canonicalNameMap.set(canonicalName, location);
|
|
1221
|
+
|
|
1222
|
+
finalGraph[location] = finalNode;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
for (const node of values(finalGraph)) {
|
|
1226
|
+
Object.freeze(node);
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
return freeze(finalGraph);
|
|
1230
|
+
};
|
|
1231
|
+
|
|
1232
|
+
/**
|
|
1233
|
+
* Returns an array of "issue" objects if any resources referenced in `policy`
|
|
1234
|
+
* are unknown.
|
|
1235
|
+
*
|
|
1236
|
+
* @param {Set<CanonicalName>} canonicalNames Set of all known canonical names
|
|
1237
|
+
* @param {SomePolicy} policy Policy to validate
|
|
1238
|
+
* @returns {Array<{canonicalName: CanonicalName, message: string, path:
|
|
1239
|
+
* string[], suggestion?: CanonicalName}>} Array of issue objects, or `undefined` if no issues were
|
|
1240
|
+
* found
|
|
1241
|
+
*/
|
|
1242
|
+
const validatePolicyResources = (canonicalNames, policy) => {
|
|
1243
|
+
/**
|
|
1244
|
+
* Finds a suggestion for `badName` if it is a suffix of any
|
|
1245
|
+
* canonical name in `canonicalNames`.
|
|
1246
|
+
*
|
|
1247
|
+
* @param {string} badName Unknown canonical name
|
|
1248
|
+
* @returns {CanonicalName | undefined}
|
|
1249
|
+
*/
|
|
1250
|
+
const findSuggestion = badName => {
|
|
1251
|
+
for (const canonicalName of canonicalNames) {
|
|
1252
|
+
if (canonicalName.endsWith(`>${badName}`)) {
|
|
1253
|
+
return canonicalName;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
return undefined;
|
|
1257
|
+
};
|
|
1258
|
+
|
|
1259
|
+
/** @type {Array<{canonicalName: CanonicalName, message: string, path: string[], suggestion?: CanonicalName}>} */
|
|
1260
|
+
const issues = [];
|
|
1261
|
+
for (const [resourceName, resourcePolicy] of entries(
|
|
1262
|
+
policy.resources ?? {},
|
|
1263
|
+
)) {
|
|
1264
|
+
if (!canonicalNames.has(resourceName)) {
|
|
1265
|
+
const issueMessage = `Resource ${q(resourceName)} was not found`;
|
|
1266
|
+
const suggestion = findSuggestion(resourceName);
|
|
1267
|
+
const issue = {
|
|
1268
|
+
canonicalName: resourceName,
|
|
1269
|
+
message: issueMessage,
|
|
1270
|
+
path: ['resources', resourceName],
|
|
1271
|
+
};
|
|
1272
|
+
if (suggestion) {
|
|
1273
|
+
issue.suggestion = suggestion;
|
|
1274
|
+
}
|
|
1275
|
+
issues.push(issue);
|
|
1276
|
+
}
|
|
1277
|
+
if (typeof resourcePolicy?.packages === 'object') {
|
|
1278
|
+
for (const packageName of keys(resourcePolicy.packages)) {
|
|
1279
|
+
if (!canonicalNames.has(packageName)) {
|
|
1280
|
+
const issueMessage = `Resource ${q(packageName)} from resource ${q(resourceName)} was not found`;
|
|
1281
|
+
const suggestion = findSuggestion(packageName);
|
|
1282
|
+
const issue = {
|
|
1283
|
+
canonicalName: packageName,
|
|
1284
|
+
message: issueMessage,
|
|
1285
|
+
path: ['resources', resourceName, 'packages', packageName],
|
|
1286
|
+
};
|
|
1287
|
+
if (suggestion) {
|
|
1288
|
+
issue.suggestion = suggestion;
|
|
1289
|
+
}
|
|
1290
|
+
issues.push(issue);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
return issues;
|
|
1297
|
+
};
|
|
977
1298
|
|
|
978
1299
|
/**
|
|
979
1300
|
* @param {ReadFn | ReadPowers<FileUrlString> | MaybeReadPowers<FileUrlString>} readPowers
|
|
980
|
-
* @param {FileUrlString}
|
|
1301
|
+
* @param {FileUrlString} entryPackageLocation
|
|
981
1302
|
* @param {Set<string>} conditionsOption
|
|
982
1303
|
* @param {PackageDescriptor} packageDescriptor
|
|
983
|
-
* @param {string}
|
|
1304
|
+
* @param {string} entryModuleSpecifier
|
|
984
1305
|
* @param {CompartmentMapForNodeModulesOptions} [options]
|
|
985
|
-
* @returns {Promise<
|
|
986
|
-
* @deprecated Use {@link mapNodeModules} instead.
|
|
1306
|
+
* @returns {Promise<PackageCompartmentMapDescriptor>}
|
|
987
1307
|
*/
|
|
988
|
-
export const
|
|
1308
|
+
export const compartmentMapForNodeModules_ = async (
|
|
989
1309
|
readPowers,
|
|
990
|
-
|
|
1310
|
+
entryPackageLocation,
|
|
991
1311
|
conditionsOption,
|
|
992
1312
|
packageDescriptor,
|
|
993
|
-
|
|
1313
|
+
entryModuleSpecifier,
|
|
994
1314
|
options = {},
|
|
995
1315
|
) => {
|
|
996
1316
|
const {
|
|
@@ -999,6 +1319,9 @@ export const compartmentMapForNodeModules = async (
|
|
|
999
1319
|
policy,
|
|
1000
1320
|
strict = false,
|
|
1001
1321
|
log = noop,
|
|
1322
|
+
unknownCanonicalNameHook,
|
|
1323
|
+
packageDataHook,
|
|
1324
|
+
packageDependenciesHook,
|
|
1002
1325
|
} = options;
|
|
1003
1326
|
const { maybeRead, canonical } = unpackReadPowers(readPowers);
|
|
1004
1327
|
const languageOptions = makeLanguageOptions(options);
|
|
@@ -1021,7 +1344,7 @@ export const compartmentMapForNodeModules = async (
|
|
|
1021
1344
|
const graph = await graphPackages(
|
|
1022
1345
|
maybeRead,
|
|
1023
1346
|
canonical,
|
|
1024
|
-
|
|
1347
|
+
entryPackageLocation,
|
|
1025
1348
|
conditions,
|
|
1026
1349
|
packageDescriptor,
|
|
1027
1350
|
dev || (conditions && conditions.has('development')),
|
|
@@ -1029,52 +1352,76 @@ export const compartmentMapForNodeModules = async (
|
|
|
1029
1352
|
languageOptions,
|
|
1030
1353
|
strict,
|
|
1031
1354
|
logicalPathGraph,
|
|
1032
|
-
{ log },
|
|
1355
|
+
{ log, policy, packageDependenciesHook },
|
|
1033
1356
|
);
|
|
1034
1357
|
|
|
1035
|
-
|
|
1036
|
-
assertPolicy(policy);
|
|
1037
|
-
|
|
1038
|
-
assert(
|
|
1039
|
-
graph[ATTENUATORS_COMPARTMENT] === undefined,
|
|
1040
|
-
`${q(ATTENUATORS_COMPARTMENT)} is a reserved compartment name`,
|
|
1041
|
-
);
|
|
1358
|
+
makeAttenuatorsNode(graph, graph[entryPackageLocation], policy);
|
|
1042
1359
|
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
name: ATTENUATORS_COMPARTMENT,
|
|
1048
|
-
};
|
|
1049
|
-
}
|
|
1360
|
+
/**
|
|
1361
|
+
* @type {CanonicalNameMap}
|
|
1362
|
+
*/
|
|
1363
|
+
const canonicalNameMap = new Map();
|
|
1050
1364
|
|
|
1051
|
-
const
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
} = graph;
|
|
1365
|
+
const finalGraph = finalizeGraph(
|
|
1366
|
+
graph,
|
|
1367
|
+
logicalPathGraph,
|
|
1368
|
+
entryPackageLocation,
|
|
1369
|
+
canonicalNameMap,
|
|
1370
|
+
);
|
|
1058
1371
|
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
);
|
|
1372
|
+
// if policy exists, cross-reference the policy "resources" against the list
|
|
1373
|
+
// of known canonical names and fire the `unknownCanonicalName` hook for each
|
|
1374
|
+
// unknown resource, if found
|
|
1375
|
+
if (policy) {
|
|
1376
|
+
const canonicalNames = new Set(canonicalNameMap.keys());
|
|
1377
|
+
const issues = validatePolicyResources(canonicalNames, policy) ?? [];
|
|
1378
|
+
// Call default handler first if policy exists
|
|
1379
|
+
for (const { message, canonicalName, path, suggestion } of issues) {
|
|
1380
|
+
const hookInput = {
|
|
1381
|
+
canonicalName,
|
|
1382
|
+
message,
|
|
1383
|
+
path,
|
|
1384
|
+
log,
|
|
1385
|
+
};
|
|
1386
|
+
if (suggestion) {
|
|
1387
|
+
hookInput.suggestion = suggestion;
|
|
1388
|
+
}
|
|
1389
|
+
defaultUnknownCanonicalNameHandler(hookInput);
|
|
1390
|
+
// Then call user-provided hook if it exists
|
|
1391
|
+
if (unknownCanonicalNameHook) {
|
|
1392
|
+
unknownCanonicalNameHook(hookInput);
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1065
1396
|
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1397
|
+
// Fire packageData hook with all package data before translateGraph
|
|
1398
|
+
if (packageDataHook) {
|
|
1399
|
+
const packageData =
|
|
1400
|
+
/** @type {Map<PackageCompartmentDescriptorName, PackageData>} */ (
|
|
1401
|
+
new Map(
|
|
1402
|
+
values(finalGraph).map(node => [
|
|
1403
|
+
node.label,
|
|
1404
|
+
{
|
|
1405
|
+
name: node.name,
|
|
1406
|
+
packageDescriptor: node.packageDescriptor,
|
|
1407
|
+
location: node.location,
|
|
1408
|
+
canonicalName: node.label,
|
|
1409
|
+
},
|
|
1410
|
+
]),
|
|
1411
|
+
)
|
|
1412
|
+
);
|
|
1413
|
+
packageDataHook({
|
|
1414
|
+
packageData,
|
|
1415
|
+
log,
|
|
1416
|
+
});
|
|
1070
1417
|
}
|
|
1071
1418
|
|
|
1072
1419
|
const compartmentMap = translateGraph(
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1420
|
+
entryPackageLocation,
|
|
1421
|
+
entryModuleSpecifier,
|
|
1422
|
+
finalGraph,
|
|
1076
1423
|
conditions,
|
|
1077
|
-
policy,
|
|
1424
|
+
{ policy, log, packageDependenciesHook },
|
|
1078
1425
|
);
|
|
1079
1426
|
|
|
1080
1427
|
return compartmentMap;
|
|
@@ -1089,12 +1436,21 @@ export const compartmentMapForNodeModules = async (
|
|
|
1089
1436
|
* @param {ReadFn | ReadPowers<FileUrlString> | MaybeReadPowers<FileUrlString>} readPowers
|
|
1090
1437
|
* @param {string} moduleLocation
|
|
1091
1438
|
* @param {MapNodeModulesOptions} [options]
|
|
1092
|
-
* @returns {Promise<
|
|
1439
|
+
* @returns {Promise<PackageCompartmentMapDescriptor>}
|
|
1093
1440
|
*/
|
|
1094
1441
|
export const mapNodeModules = async (
|
|
1095
1442
|
readPowers,
|
|
1096
1443
|
moduleLocation,
|
|
1097
|
-
{
|
|
1444
|
+
{
|
|
1445
|
+
tags = new Set(),
|
|
1446
|
+
conditions = tags,
|
|
1447
|
+
log = noop,
|
|
1448
|
+
unknownCanonicalNameHook,
|
|
1449
|
+
packageDataHook,
|
|
1450
|
+
packageDependenciesHook,
|
|
1451
|
+
policy,
|
|
1452
|
+
...otherOptions
|
|
1453
|
+
} = {},
|
|
1098
1454
|
) => {
|
|
1099
1455
|
const {
|
|
1100
1456
|
packageLocation,
|
|
@@ -1110,12 +1466,24 @@ export const mapNodeModules = async (
|
|
|
1110
1466
|
assertPackageDescriptor(packageDescriptor);
|
|
1111
1467
|
assertFileUrlString(packageLocation);
|
|
1112
1468
|
|
|
1113
|
-
return
|
|
1469
|
+
return compartmentMapForNodeModules_(
|
|
1114
1470
|
readPowers,
|
|
1115
1471
|
packageLocation,
|
|
1116
1472
|
conditions,
|
|
1117
1473
|
packageDescriptor,
|
|
1118
1474
|
moduleSpecifier,
|
|
1119
|
-
{
|
|
1475
|
+
{
|
|
1476
|
+
log,
|
|
1477
|
+
policy,
|
|
1478
|
+
unknownCanonicalNameHook,
|
|
1479
|
+
packageDependenciesHook,
|
|
1480
|
+
packageDataHook,
|
|
1481
|
+
...otherOptions,
|
|
1482
|
+
},
|
|
1120
1483
|
);
|
|
1121
1484
|
};
|
|
1485
|
+
|
|
1486
|
+
/**
|
|
1487
|
+
* @deprecated Use {@link mapNodeModules} instead.
|
|
1488
|
+
*/
|
|
1489
|
+
export const compartmentMapForNodeModules = compartmentMapForNodeModules_;
|