Skip to content

Commit 0456db1

Browse files
johnjenkinsJohn Jenkins
andauthored
feat(runtime): allow class extending (#6362)
* feat(runtime): allow class extending * chore: fix tests * feat: extend Stencil decorated classes! * chore: assign / reuse `foundSuper` * chore: fix test * chore: format * chore: fix test * chore: read all the extended tree class methods * chore: added some unit tests * chore: more unit tests * chore: wdio tests and bundleid fixing * chore: get tests to pass * chore: fix tests? * chore: try this * chore: silly me * chore: test 2 layer extends --------- Co-authored-by: John Jenkins <john.jenkins@nanoporetech.com>
1 parent 1a20bb5 commit 0456db1

74 files changed

Lines changed: 2235 additions & 224 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@
121121
"test.dist": "npm run ts scripts/index.ts -- --validate-build",
122122
"test.end-to-end": "cd test/end-to-end && npm ci && npm test && npm run test.dist",
123123
"test.jest": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js",
124-
"test.type-tests": "cd ./test/wdio && npm install && npm run build.main && cd ../../ && tsc -p test/type-tests/tsconfig.json",
124+
"test.type-tests": "cd ./test/wdio && npm install && npm run build.test-sibling && npm run build.main && cd ../../ && tsc -p test/type-tests/tsconfig.json",
125125
"test.wdio": "cd test/wdio && npm ci && npm run test",
126126
"test.wdio.testOnly": "cd test/wdio && npm ci && npm run wdio",
127127
"test.prod": "npm run test.dist && npm run test.end-to-end && npm run test.jest && npm run test.wdio && npm run test.testing && npm run test.analysis",

src/client/client-host-ref.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export const getHostRef = (ref: d.RuntimeRef): d.HostRef | undefined => {
2525
* @param hostRef that instances `HostRef` object
2626
*/
2727
export const registerInstance = (lazyInstance: any, hostRef: d.HostRef) => {
28+
if (!hostRef) return;
2829
lazyInstance.__stencil__getHostRef = () => hostRef;
2930
hostRef.$lazyInstance$ = lazyInstance;
3031

src/compiler/build/compiler-ctx.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ export const getModuleLegacy = (compilerCtx: d.CompilerCtx, sourceFilePath: stri
8888
sourceFilePath: sourceFilePath,
8989
jsFilePath: jsFilePath,
9090
cmps: [],
91+
isExtended: false,
92+
isMixin: false,
9193
coreRuntimeApis: [],
9294
outputTargetCoreRuntimeApis: {},
9395
collectionName: null,

src/compiler/bundle/typescript-plugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export const typescriptPlugin = (
5757
if (isAbsolute(id)) {
5858
const fsFilePath = normalizeFsPath(id);
5959
const mod = getModule(compilerCtx, fsFilePath);
60-
if (mod && mod.cmps.length > 0) {
60+
if (mod?.cmps) {
6161
const tsResult = ts.transpileModule(mod.staticSourceFileText, {
6262
compilerOptions: config.tsCompilerOptions,
6363
fileName: mod.sourceFilePath,

src/compiler/output-targets/dist-lazy/generate-cjs.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { OutputOptions, RollupBuild } from 'rollup';
44
import type * as d from '../../../declarations';
55
import { generateRollupOutput } from '../../app-core/bundle-app-core';
66
import { generateLazyModules } from './generate-lazy-module';
7+
import { lazyBundleIdPlugin } from './lazy-bundleid-plugin';
78

89
export const generateCjs = async (
910
config: d.ValidatedConfig,
@@ -22,6 +23,7 @@ export const generateCjs = async (
2223
entryFileNames: '[name].cjs.js',
2324
assetFileNames: '[name]-[hash][extname]',
2425
sourcemap: config.sourceMap,
26+
plugins: [lazyBundleIdPlugin(buildCtx, config, false, '.cjs')],
2527
};
2628

2729
if (!!config.extras.experimentalImportInjection || !!config.extras.enableImportInjection) {
@@ -44,7 +46,6 @@ export const generateCjs = async (
4446
results,
4547
'es2017',
4648
false,
47-
'.cjs',
4849
);
4950

5051
await generateShortcuts(compilerCtx, results, cjsOutputs);

src/compiler/output-targets/dist-lazy/generate-esm-browser.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { OutputOptions, RollupBuild } from 'rollup';
44
import type * as d from '../../../declarations';
55
import { generateRollupOutput } from '../../app-core/bundle-app-core';
66
import { generateLazyModules } from './generate-lazy-module';
7+
import { lazyBundleIdPlugin } from './lazy-bundleid-plugin';
78

89
export const generateEsmBrowser = async (
910
config: d.ValidatedConfig,
@@ -22,6 +23,7 @@ export const generateEsmBrowser = async (
2223
chunkFileNames: config.hashFileNames ? 'p-[hash].js' : '[name]-[hash].js',
2324
assetFileNames: config.hashFileNames ? 'p-[hash][extname]' : '[name]-[hash][extname]',
2425
sourcemap: config.sourceMap,
26+
plugins: [lazyBundleIdPlugin(buildCtx, config, config.hashFileNames, '')],
2527
};
2628

2729
const output = await generateRollupOutput(rollupBuild, esmOpts, config, buildCtx.entryModules);
@@ -39,7 +41,6 @@ export const generateEsmBrowser = async (
3941
output,
4042
'es2017',
4143
true,
42-
'',
4344
);
4445
}
4546
}

src/compiler/output-targets/dist-lazy/generate-esm.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type * as d from '../../../declarations';
55
import type { RollupResult } from '../../../declarations';
66
import { generateRollupOutput } from '../../app-core/bundle-app-core';
77
import { generateLazyModules } from './generate-lazy-module';
8+
import { lazyBundleIdPlugin } from './lazy-bundleid-plugin';
89

910
export const generateEsm = async (
1011
config: d.ValidatedConfig,
@@ -22,6 +23,7 @@ export const generateEsm = async (
2223
entryFileNames: '[name].js',
2324
assetFileNames: '[name]-[hash][extname]',
2425
sourcemap: config.sourceMap,
26+
plugins: [lazyBundleIdPlugin(buildCtx, config, false, '')],
2527
};
2628
const outputTargetType = esmOutputs[0].type;
2729
const output = await generateRollupOutput(rollupBuild, esmOpts, config, buildCtx.entryModules);
@@ -39,7 +41,6 @@ export const generateEsm = async (
3941
output,
4042
'es2017',
4143
false,
42-
'',
4344
);
4445

4546
const es5destinations = esmEs5Outputs
@@ -54,7 +55,6 @@ export const generateEsm = async (
5455
output,
5556
'es5',
5657
false,
57-
'',
5858
);
5959

6060
if (config.buildEs5) {

src/compiler/output-targets/dist-lazy/generate-lazy-module.ts

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export const generateLazyModules = async (
2121
results: d.RollupResult[],
2222
sourceTarget: d.SourceTarget,
2323
isBrowserBuild: boolean,
24-
sufix: string,
2524
): Promise<d.BundleModule[]> => {
2625
if (!Array.isArray(destinations) || destinations.length === 0) {
2726
return [];
@@ -43,7 +42,6 @@ export const generateLazyModules = async (
4342
sourceTarget,
4443
shouldMinify,
4544
isBrowserBuild,
46-
sufix,
4745
);
4846
}),
4947
);
@@ -190,10 +188,8 @@ const generateLazyEntryModule = async (
190188
sourceTarget: d.SourceTarget,
191189
shouldMinify: boolean,
192190
isBrowserBuild: boolean,
193-
sufix: string,
194191
): Promise<d.BundleModule> => {
195192
const entryModule = buildCtx.entryModules.find((entryModule) => entryModule.entryKey === rollupResult.entryKey);
196-
const shouldHash = config.hashFileNames && isBrowserBuild;
197193

198194
const { code, sourceMap } = await convertChunk(
199195
config,
@@ -207,17 +203,7 @@ const generateLazyEntryModule = async (
207203
rollupResult.map,
208204
);
209205

210-
const output = await writeLazyModule(
211-
config,
212-
compilerCtx,
213-
outputTargetType,
214-
destinations,
215-
entryModule,
216-
shouldHash,
217-
code,
218-
sourceMap,
219-
sufix,
220-
);
206+
const output = await writeLazyModule(compilerCtx, outputTargetType, destinations, code, sourceMap, rollupResult);
221207

222208
return {
223209
rollupResult,

src/compiler/output-targets/dist-lazy/generate-system.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type * as d from '../../../declarations';
55
import { getAppBrowserCorePolyfills } from '../../app-core/app-polyfills';
66
import { generateRollupOutput } from '../../app-core/bundle-app-core';
77
import { generateLazyModules } from './generate-lazy-module';
8+
import { lazyBundleIdPlugin } from './lazy-bundleid-plugin';
89

910
export const generateSystem = async (
1011
config: d.ValidatedConfig,
@@ -23,6 +24,7 @@ export const generateSystem = async (
2324
chunkFileNames: config.hashFileNames ? 'p-[hash].system.js' : '[name]-[hash].system.js',
2425
assetFileNames: config.hashFileNames ? 'p-[hash][extname]' : '[name]-[hash][extname]',
2526
sourcemap: config.sourceMap,
27+
plugins: [lazyBundleIdPlugin(buildCtx, config, config.hashFileNames, '.system')],
2628
};
2729
const results = await generateRollupOutput(rollupBuild, esmOpts, config, buildCtx.entryModules);
2830
if (results != null) {
@@ -38,7 +40,6 @@ export const generateSystem = async (
3840
results,
3941
'es5',
4042
true,
41-
'.system',
4243
);
4344

4445
await generateSystemLoaders(config, compilerCtx, results, systemOutputs);
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import MagicString from 'magic-string';
2+
3+
import type { OutputChunk, Plugin } from 'rollup';
4+
import type * as d from '../../../declarations';
5+
6+
/**
7+
* A Rollup plugin to generate unique bundle IDs for lazy-loaded modules.
8+
* @param buildCtx The build context
9+
* @param config The validated configuration
10+
* @param shouldHash Whether to hash the bundle ID
11+
* @param suffix The suffix to append to the bundle ID
12+
* @returns A Rollup plugin
13+
*/
14+
export const lazyBundleIdPlugin = (
15+
buildCtx: d.BuildCtx,
16+
config: d.ValidatedConfig,
17+
shouldHash: boolean,
18+
suffix: string,
19+
): Plugin => {
20+
const getBundleId = async (entryKey: string, code: string, suffix: string): Promise<string> => {
21+
if (shouldHash && config.sys?.generateContentHash) {
22+
const hash = await config.sys.generateContentHash(code, config.hashedFileNameLength);
23+
return `p-${hash}${suffix}`;
24+
}
25+
26+
const components = entryKey.split('.');
27+
let bundleId = components[0];
28+
if (components.length > 2) {
29+
bundleId = `${bundleId}_${components.length - 1}`;
30+
}
31+
32+
return bundleId + suffix;
33+
};
34+
35+
return {
36+
name: 'lazyBundleIdPlugin',
37+
async generateBundle(_, bundle) {
38+
const files = Object.entries<OutputChunk>(bundle as any);
39+
const map = new Map<string, string>();
40+
41+
for (const [_key, file] of files) {
42+
if (!file.isEntry) continue;
43+
44+
const entryModule = buildCtx.entryModules.find((em) => em.entryKey === file.name);
45+
if (!entryModule) continue;
46+
47+
map.set(file.fileName, (await getBundleId(file.name, file.code, suffix)) + '.entry.js');
48+
}
49+
50+
if (!map.size) return;
51+
52+
for (const [_key, file] of files) {
53+
if (!file.isEntry) continue;
54+
55+
file.facadeModuleId = map.get(file.fileName) || file.facadeModuleId;
56+
file.fileName = map.get(file.fileName) || file.fileName;
57+
58+
const magicString = new MagicString(file.code);
59+
60+
file.imports.forEach((imported: string, i) => {
61+
const replaced = map.get(imported);
62+
if (replaced) {
63+
magicString.replaceAll(imported, replaced);
64+
file.imports[i] = replaced;
65+
}
66+
});
67+
file.code = magicString.toString();
68+
69+
if (config.sourceMap) {
70+
file.map = magicString.generateMap();
71+
}
72+
}
73+
},
74+
};
75+
};

0 commit comments

Comments
 (0)