Skip to content

Commit a116534

Browse files
authored
Merge pull request #1383 from endojs/cjs-bundling
feat(compartment-mapper): support bundling cjs
2 parents feb8599 + aa5e164 commit a116534

File tree

8 files changed

+234
-139
lines changed

8 files changed

+234
-139
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/** quotes strings */
2+
const q = JSON.stringify;
3+
4+
const exportsCellRecord = exportsList =>
5+
''.concat(
6+
...exportsList.map(
7+
exportName => `\
8+
${exportName}: cell(${q(exportName)}),
9+
`,
10+
),
11+
);
12+
13+
// This function is serialized and references variables from its destination scope.
14+
const runtime = function wrapCjsFunctor(num) {
15+
/* eslint-disable no-undef */
16+
return ({ imports = {} }) => {
17+
const cModule = Object.freeze(
18+
Object.defineProperty({}, 'exports', cells[num].default),
19+
);
20+
// TODO: specifier not found handling
21+
const requireImpl = specifier => cells[imports[specifier]].default.get();
22+
functors[num](Object.freeze(requireImpl), cModule.exports, cModule);
23+
Object.keys(cells[num])
24+
.filter(k => k !== 'default' && k !== '*')
25+
.map(k => cells[num][k].set(cModule.exports[k]));
26+
};
27+
/* eslint-enable no-undef */
28+
}.toString();
29+
30+
export default {
31+
runtime,
32+
getBundlerKit({
33+
index,
34+
indexedImports,
35+
record: { cjsFunctor, exports: exportsList = {} },
36+
}) {
37+
const importsMap = JSON.stringify(indexedImports);
38+
39+
return {
40+
getFunctor: () => `\
41+
// === functors[${index}] ===
42+
${cjsFunctor},
43+
`,
44+
getCells: () => `\
45+
{
46+
${exportsCellRecord(exportsList)}\
47+
},
48+
`,
49+
getReexportsWiring: () => '',
50+
getFunctorCall: () => `\
51+
wrapCjsFunctor(${index})({imports: ${importsMap}});
52+
`,
53+
};
54+
},
55+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/** quotes strings */
2+
const q = JSON.stringify;
3+
4+
const exportsCellRecord = exportMap =>
5+
''.concat(
6+
...Object.keys(exportMap).map(
7+
exportName => `\
8+
${exportName}: cell(${q(exportName)}),
9+
`,
10+
),
11+
);
12+
13+
const importsCellSetter = (exportMap, index) =>
14+
''.concat(
15+
...Object.entries(exportMap).map(
16+
([exportName, [importName]]) => `\
17+
${importName}: cells[${index}].${exportName}.set,
18+
`,
19+
),
20+
);
21+
22+
const adaptReexport = reexportMap => {
23+
if (!reexportMap) {
24+
return {};
25+
}
26+
const ret = Object.fromEntries(
27+
Object.values(reexportMap)
28+
.flat()
29+
.map(([local, exported]) => [exported, [local]]),
30+
);
31+
return ret;
32+
};
33+
34+
export const runtime = `\
35+
function observeImports(map, importName, importIndex) {
36+
for (const [name, observers] of map.get(importName)) {
37+
const cell = cells[importIndex][name];
38+
if (cell === undefined) {
39+
throw new ReferenceError(\`Cannot import name \${name}\`);
40+
}
41+
for (const observer of observers) {
42+
cell.observe(observer);
43+
}
44+
}
45+
}
46+
`;
47+
48+
export default {
49+
runtime,
50+
getBundlerKit({
51+
index,
52+
indexedImports,
53+
record: {
54+
__syncModuleProgram__,
55+
__fixedExportMap__ = {},
56+
__liveExportMap__ = {},
57+
__reexportMap__ = {},
58+
reexports,
59+
},
60+
}) {
61+
return {
62+
getFunctor: () => `\
63+
// === functors[${index}] ===
64+
${__syncModuleProgram__},
65+
`,
66+
getCells: () => `\
67+
{
68+
${exportsCellRecord(__fixedExportMap__)}${exportsCellRecord(
69+
__liveExportMap__,
70+
)}${exportsCellRecord(adaptReexport(__reexportMap__))}\
71+
},
72+
`,
73+
getReexportsWiring: () => {
74+
const mappings = reexports.map(
75+
importSpecifier => `\
76+
Object.defineProperties(cells[${index}], Object.getOwnPropertyDescriptors(cells[${indexedImports[importSpecifier]}]));
77+
`,
78+
);
79+
// Create references for export name as newname
80+
const namedReexportsToProcess = Object.entries(__reexportMap__);
81+
if (namedReexportsToProcess.length > 0) {
82+
mappings.push(`
83+
Object.defineProperties(cells[${index}], {${namedReexportsToProcess.map(
84+
([specifier, renames]) => {
85+
return renames.map(
86+
([localName, exportedName]) =>
87+
`${q(exportedName)}: { value: cells[${
88+
indexedImports[specifier]
89+
}][${q(localName)}] }`,
90+
);
91+
},
92+
)} });
93+
`);
94+
}
95+
return mappings.join('');
96+
},
97+
getFunctorCall: () => `\
98+
functors[${index}]({
99+
imports(entries) {
100+
const map = new Map(entries);
101+
${''.concat(
102+
...Object.entries(indexedImports).map(
103+
([importName, importIndex]) => `\
104+
observeImports(map, ${q(importName)}, ${importIndex});
105+
`,
106+
),
107+
)}\
108+
},
109+
liveVar: {
110+
${importsCellSetter(__liveExportMap__, index)}\
111+
},
112+
onceVar: {
113+
${importsCellSetter(__fixedExportMap__, index)}\
114+
},
115+
importMeta: {},
116+
});
117+
`,
118+
};
119+
},
120+
};

0 commit comments

Comments
 (0)