Skip to content

Commit d764dcc

Browse files
committed
chore(compartment-mapper): peer review edits
- fix for mermaid graph - fix for prePackageDependenciesFilter, plus comment - makePackagePolicy throws if falsy label provided
1 parent 8b83456 commit d764dcc

File tree

4 files changed

+199
-27
lines changed

4 files changed

+199
-27
lines changed

packages/compartment-mapper/src/hooks.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
[Type declarations for the hooks](./types/external.ts)
1212

1313
```mermaid
14+
1415
graph TB
1516
1617
exports((public exports))

packages/compartment-mapper/src/node-modules.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ const defaultUnknownCanonicalNameHandler = ({
104104
* Default filter for package dependencies based on policy.
105105
* Filters out dependencies not allowed by the package policy.
106106
*
107+
* **Note:** This filter is _only_ applied if a policy is provided.
108+
*
107109
* @param {object} params - The parameters object
108110
* @param {CanonicalName} params.canonicalName - The canonical name of the package
109111
* @param {Readonly<Set<CanonicalName>>} params.dependencies - The set of dependencies
@@ -116,6 +118,9 @@ const prePackageDependenciesFilter = (
116118
policy,
117119
) => {
118120
const packagePolicy = makePackagePolicy(canonicalName, { policy });
121+
if (!packagePolicy) {
122+
return { dependencies };
123+
}
119124
const filteredDependencies = new Set(
120125
[...dependencies].filter(dependency => {
121126
const allowed = dependencyAllowedByPolicy(dependency, packagePolicy);
@@ -128,9 +133,7 @@ const prePackageDependenciesFilter = (
128133
}),
129134
);
130135

131-
return filteredDependencies.size !== dependencies.size
132-
? { dependencies: filteredDependencies }
133-
: undefined;
136+
return { dependencies: filteredDependencies };
134137
};
135138

136139
/**
@@ -897,7 +900,7 @@ const translateGraph = (
897900

898901
// if "dependencies" are in here, then something changed the list.
899902
if (packageDependenciesHookResult?.dependencies) {
900-
const { size } = packageDependenciesHookResult.dependencies;
903+
const size = packageDependenciesHookResult.dependencies.size;
901904
if (typeof size === 'number' && size > 0) {
902905
// because the list of dependencies contains canonical names, we need to lookup any new ones.
903906
const nodesByCanonicalName = new Map(

packages/compartment-mapper/src/policy.js

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -129,35 +129,24 @@ export const dependencyAllowedByPolicy = (canonicalName, packagePolicy) => {
129129
};
130130

131131
/**
132-
* Generates the {@link SomePackagePolicy} value to be used in {@link CompartmentDescriptor.policy}
133-
* @overload
134-
* @param {CanonicalName | typeof ATTENUATORS_COMPARTMENT} label
135-
* @param {object} options Options
136-
* @param {SomePolicy} options.policy User-supplied policy
137-
* @param {SomePackagePolicy} [options.packagePolicy] Package policy, if already known
138-
* @returns {SomePackagePolicy} Package policy from `policy` or empty object; returns `params.packagePolicy` if provided
139-
*/
140-
/**
141-
* Generates the {@link SomePackagePolicy} value to be used in {@link CompartmentDescriptor.policy}
132+
* Generates the {@link SomePackagePolicy} value to be used in
133+
* {@link CompartmentDescriptor.policy}
142134
*
143-
* @overload
144-
* @param {CanonicalName | typeof ATTENUATORS_COMPARTMENT} label
135+
* @param {CanonicalName | typeof ATTENUATORS_COMPARTMENT | typeof ENTRY_COMPARTMENT} label
145136
* @param {object} [options] Options
146137
* @param {SomePolicy} [options.policy] User-supplied policy
147-
* @param {SomePackagePolicy} [options.packagePolicy] Package policy, if already known
148-
* @returns {SomePackagePolicy|undefined} Package policy from `policy` or empty object; returns `params.packagePolicy` if provided
149-
*/
150-
/**
151-
* Generates the {@link SomePackagePolicy} value to be used in {@link CompartmentDescriptor.policy}
152-
*
153-
* @param {CanonicalName | typeof ATTENUATORS_COMPARTMENT} label
154-
* @param {object} [options] Options
155-
* @param {SomePolicy} [options.policy] User-supplied policy
156-
* @returns {SomePackagePolicy|undefined} Package policy from `policy` or empty object; returns `params.packagePolicy` if provided
138+
* @returns {SomePackagePolicy|undefined} Package policy from `policy` or empty
139+
* object; returns `params.packagePolicy` if provided. If entry compartment,
140+
* returns the `entry` property of the policy verbatim.
157141
*/
158142
export const makePackagePolicy = (label, { policy } = {}) => {
159143
/** @type {SomePackagePolicy|undefined} */
160144
let packagePolicy;
145+
if (!label) {
146+
throw new TypeError(
147+
`Invalid arguments: label must be a non-empty string; got ${q(label)}`,
148+
);
149+
}
161150
if (policy) {
162151
if (label === ATTENUATORS_COMPARTMENT) {
163152
packagePolicy = {
@@ -166,6 +155,7 @@ export const makePackagePolicy = (label, { policy } = {}) => {
166155
};
167156
} else if (label === ENTRY_COMPARTMENT) {
168157
packagePolicy = policy.entry;
158+
return packagePolicy;
169159
} else if (label) {
170160
packagePolicy = policy.resources?.[label];
171161
}

packages/compartment-mapper/test/policy.test.js

Lines changed: 179 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33
import 'ses';
44
import test from 'ava';
55
import { moduleify, scaffold, sanitizePaths } from './scaffold.js';
6-
import { WILDCARD_POLICY_VALUE } from '../src/policy-format.js';
6+
import {
7+
WILDCARD_POLICY_VALUE,
8+
ATTENUATORS_COMPARTMENT,
9+
ENTRY_COMPARTMENT,
10+
} from '../src/policy-format.js';
11+
import { makePackagePolicy } from '../src/policy.js';
712

813
function combineAssertions(...assertionFunctions) {
914
return async (...args) => {
@@ -455,3 +460,176 @@ scaffold(
455460
policy: nestedAttenuator(policy),
456461
},
457462
);
463+
464+
// Unit tests for makePackagePolicy
465+
test('makePackagePolicy() - no policy provided', t => {
466+
t.is(makePackagePolicy('alice'), undefined);
467+
t.is(makePackagePolicy(ATTENUATORS_COMPARTMENT), undefined);
468+
t.is(makePackagePolicy(ENTRY_COMPARTMENT), undefined);
469+
t.is(makePackagePolicy('alice', {}), undefined);
470+
});
471+
472+
test('makePackagePolicy() - ATTENUATORS_COMPARTMENT label', t => {
473+
const testPolicy = {
474+
defaultAttenuator: 'myattenuator',
475+
entry: { packages: { alice: true } },
476+
resources: {},
477+
};
478+
479+
const result = makePackagePolicy(ATTENUATORS_COMPARTMENT, {
480+
policy: testPolicy,
481+
});
482+
483+
t.deepEqual(result, {
484+
defaultAttenuator: 'myattenuator',
485+
packages: WILDCARD_POLICY_VALUE,
486+
});
487+
});
488+
489+
test('makePackagePolicy() - ATTENUATORS_COMPARTMENT label without defaultAttenuator', t => {
490+
const testPolicy = {
491+
entry: { packages: { alice: true } },
492+
resources: {},
493+
};
494+
495+
const result = makePackagePolicy(ATTENUATORS_COMPARTMENT, {
496+
policy: testPolicy,
497+
});
498+
499+
t.deepEqual(result, {
500+
defaultAttenuator: undefined,
501+
packages: WILDCARD_POLICY_VALUE,
502+
});
503+
});
504+
505+
test('makePackagePolicy() - ENTRY_COMPARTMENT label', t => {
506+
const entryPolicy = {
507+
globals: { bluePill: true },
508+
packages: { alice: true },
509+
builtins: { builtin: { attenuate: 'myattenuator', params: ['a', 'b'] } },
510+
};
511+
const testPolicy = {
512+
defaultAttenuator: 'myattenuator',
513+
entry: entryPolicy,
514+
resources: {},
515+
};
516+
517+
const result = makePackagePolicy(ENTRY_COMPARTMENT, { policy: testPolicy });
518+
519+
t.is(result, entryPolicy);
520+
t.deepEqual(result, entryPolicy);
521+
});
522+
523+
test('makePackagePolicy() - ENTRY_COMPARTMENT label with undefined entry', t => {
524+
const testPolicy = {
525+
defaultAttenuator: 'myattenuator',
526+
resources: {},
527+
};
528+
529+
const result = makePackagePolicy(ENTRY_COMPARTMENT, { policy: testPolicy });
530+
531+
t.is(result, undefined);
532+
});
533+
534+
test('makePackagePolicy() - regular canonical name that exists in resources', t => {
535+
const resourcePolicy = {
536+
packages: { 'alice>carol': true },
537+
};
538+
const testPolicy = {
539+
entry: { packages: { alice: true } },
540+
resources: {
541+
alice: resourcePolicy,
542+
},
543+
};
544+
545+
const result = makePackagePolicy('alice', { policy: testPolicy });
546+
547+
t.is(result, resourcePolicy);
548+
t.deepEqual(result, resourcePolicy);
549+
});
550+
551+
test('makePackagePolicy() - regular canonical name that does not exist in resources', t => {
552+
const testPolicy = {
553+
entry: { packages: { alice: true } },
554+
resources: {
555+
alice: { globals: { santorum: true } },
556+
},
557+
};
558+
559+
const result = makePackagePolicy('nonexistent', { policy: testPolicy });
560+
561+
t.not(result, undefined);
562+
t.is(Object.getPrototypeOf(result), null);
563+
t.deepEqual(result, {});
564+
t.is(Object.keys(result).length, 0);
565+
});
566+
567+
test('makePackagePolicy() - regular canonical name with resources undefined', t => {
568+
const testPolicy = {
569+
entry: { packages: { alice: true } },
570+
};
571+
572+
const result = makePackagePolicy('alice', { policy: testPolicy });
573+
574+
t.not(result, undefined);
575+
t.is(Object.getPrototypeOf(result), null);
576+
t.deepEqual(result, {});
577+
t.is(Object.keys(result).length, 0);
578+
});
579+
580+
test('makePackagePolicy() - empty label throws', t => {
581+
const testPolicy = {
582+
entry: { packages: { alice: true } },
583+
resources: {
584+
alice: { globals: { santorum: true } },
585+
},
586+
};
587+
588+
t.throws(() => makePackagePolicy(null, { policy: testPolicy }), {
589+
message: /Invalid arguments: label must be a non-empty string; got null/i,
590+
});
591+
t.throws(() => makePackagePolicy(undefined, { policy: testPolicy }), {
592+
message:
593+
/Invalid arguments: label must be a non-empty string; got undefined/i,
594+
});
595+
t.throws(() => makePackagePolicy('', { policy: testPolicy }), {
596+
message: /Invalid arguments: label must be a non-empty string; got ""/i,
597+
});
598+
});
599+
600+
test('makePackagePolicy() - preserves object reference for entry', t => {
601+
const entryPolicy = { packages: { alice: true } };
602+
const testPolicy = {
603+
entry: entryPolicy,
604+
resources: {},
605+
};
606+
607+
const result = makePackagePolicy(ENTRY_COMPARTMENT, { policy: testPolicy });
608+
609+
t.is(result, entryPolicy);
610+
});
611+
612+
test('makePackagePolicy() - preserves object reference for resources', t => {
613+
const resourcePolicy = { globals: { redPill: true } };
614+
const testPolicy = {
615+
entry: { packages: { alice: true } },
616+
resources: {
617+
alice: resourcePolicy,
618+
},
619+
};
620+
621+
const result = makePackagePolicy('alice', { policy: testPolicy });
622+
623+
t.is(result, resourcePolicy);
624+
});
625+
626+
test('makePackagePolicy() - empty resources object returns empty package policy', t => {
627+
const testPolicy = {
628+
entry: { packages: { alice: true } },
629+
resources: {},
630+
};
631+
632+
const result = makePackagePolicy('alice', { policy: testPolicy });
633+
634+
t.deepEqual(result, {});
635+
});

0 commit comments

Comments
 (0)