browser-module-runtime 0.0.0-stage → 0.0.1
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/README.md +65 -2
- package/html.d.ts +3 -0
- package/index.d.ts +107 -0
- package/package.json +35 -4
- package/src/build/analyze.js +54 -0
- package/src/build/pipeline.js +62 -0
- package/src/engine/compile-cache.js +379 -0
- package/src/engine/errors.js +41 -0
- package/src/engine/events.js +63 -0
- package/src/engine/package-resolution/index.js +179 -0
- package/src/engine/runtime.js +2044 -0
- package/src/engine/url-backend.js +40 -0
- package/src/html/index.d.ts +1 -0
- package/src/html/index.js +48 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +93 -0
- package/src/plugins/package-entries.js +30 -0
- package/src/resources/styles.js +18 -0
package/README.md
CHANGED
|
@@ -1,3 +1,66 @@
|
|
|
1
|
-
#
|
|
1
|
+
# browser-module-runtime
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A framework-neutral browser module runtime with a native ESM linker, independent module registries, package-source and version resolution, a pre/compile/post build pipeline, caching, and optional HTML rendering.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install browser-module-runtime@0.0.1
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Define, import and update modules
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import { createRuntime } from 'browser-module-runtime';
|
|
15
|
+
|
|
16
|
+
const runtime = createRuntime({
|
|
17
|
+
packages: {provider: 'esm.sh', versions: {'just-versions': '0.0.1'}},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
runtime.define('/math.js', 'export const double = n => n * 2;');
|
|
21
|
+
const {double} = await runtime.import('/math.js');
|
|
22
|
+
console.log(double(21)); // 42
|
|
23
|
+
|
|
24
|
+
await runtime.dispose();
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The factory is synchronous; asynchronous plugin setup is exposed as `runtime.ready`. The `import`, `compile`, `mount`, and `loadSource` methods await readiness. `dispose()` is async.
|
|
28
|
+
|
|
29
|
+
## Modules and package sources
|
|
30
|
+
|
|
31
|
+
The core supports `define`, `defineMany`, `defineModule`, `defineUrl`, `import`, `compile`, `update`, `invalidate`, `remove`, and `clear`, plus graph inspection and subscriptions. Runtime-specific package selections support esm.sh, jsDelivr, npm versions, and supported GitHub/PR locators:
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
const runtime = createRuntime({
|
|
35
|
+
packages: {
|
|
36
|
+
provider: 'esm.sh',
|
|
37
|
+
versions: {
|
|
38
|
+
'just-versions': '0.0.2',
|
|
39
|
+
'lodash-es': 'jsdelivr:4.17.21',
|
|
40
|
+
versioning: 'esm.sh:gh/mizulu/versioning@0.0.1',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Package-root mappings include supported subpath imports (for example `lodash-es/debounce`), subject to the source/provider's rules.
|
|
47
|
+
|
|
48
|
+
## Compilers and rendering
|
|
49
|
+
|
|
50
|
+
The default source format is JavaScript. Additional formats and rendering are opt-in through plugins such as `browser-runtime-solid`, `browser-runtime-svelte`, and `browser-runtime-octane`.
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
const runtime = createRuntime({plugins: [myCompilerAndRenderer]});
|
|
54
|
+
runtime.define('/Widget.sample', source, {type: 'sample'});
|
|
55
|
+
const handle = await runtime.mount({module: '/Widget.sample', target: '#app'});
|
|
56
|
+
await handle.dispose();
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Public exports
|
|
60
|
+
|
|
61
|
+
- `browser-module-runtime`: runtime, build pipeline, cache and resolver utilities
|
|
62
|
+
- `browser-module-runtime/html`: `registerHTML` and generic `<runtime-render>` integration
|
|
63
|
+
- `browser-module-runtime/packages`: package policy utilities
|
|
64
|
+
- `browser-module-runtime/cache`: compile-cache implementations
|
|
65
|
+
|
|
66
|
+
`<runtime-render>` mounts framework plugins into its own element. This new generic API is distinct from the older `solid-tag-runtime` and `<solid-render>` APIs; use those packages for applications requiring their existing behavior.
|
package/html.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type {Runtime} from './index.js';
|
|
2
|
+
export interface HTMLController {readonly name:string;readonly runtime:Runtime;registerExisting():Promise<void>;scan():Promise<void>;disconnect():Promise<void>}
|
|
3
|
+
export declare function registerHTML(runtime:Runtime,options?:{name?:string;root?:Document|Element;observe?:boolean}):HTMLController;
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
export type ScriptType = string;
|
|
2
|
+
export type Diagnostic = { message?: string; code?: string; [key: string]: unknown };
|
|
3
|
+
export type EmittedAsset = { type: 'css' | 'asset'; id?: string; content: string };
|
|
4
|
+
export interface ModuleSource { id: string; source: string; type?: string; format?: string; imports?: Record<string, unknown> }
|
|
5
|
+
export interface BuildState { code: string; assets?: EmittedAsset[]; diagnostics?: Diagnostic[]; map?: string }
|
|
6
|
+
export interface BuildContext { id: string; type: string; format: string; plugin: string }
|
|
7
|
+
export type TransformHook = (input: BuildState, context: BuildContext) => void | string | BuildState | Promise<void | string | BuildState>;
|
|
8
|
+
export interface CompilerAdapter {
|
|
9
|
+
types: string[];
|
|
10
|
+
extensions?: string[];
|
|
11
|
+
compile(source: string, context: BuildContext): string | BuildState | Promise<string | BuildState>;
|
|
12
|
+
analyze?(code: string, context: BuildContext): Array<{specifier:string;start:number;end:number;kind:string}> | Promise<Array<{specifier:string;start:number;end:number;kind:string}>>;
|
|
13
|
+
}
|
|
14
|
+
export interface MountContext<Props = Record<string, unknown>> {
|
|
15
|
+
component: unknown;
|
|
16
|
+
target: Element;
|
|
17
|
+
props: Props;
|
|
18
|
+
runtime: Runtime;
|
|
19
|
+
id: string;
|
|
20
|
+
}
|
|
21
|
+
export interface RendererAdapter {
|
|
22
|
+
name?: string;
|
|
23
|
+
types: string[];
|
|
24
|
+
mount(input: MountContext): Promise<RendererHandle> | RendererHandle;
|
|
25
|
+
}
|
|
26
|
+
export interface RendererHandle {
|
|
27
|
+
dispose(): void | Promise<void>;
|
|
28
|
+
updateProps?(props: Record<string, unknown>): void | Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
export interface MountHandle {
|
|
31
|
+
ready: Promise<void>;
|
|
32
|
+
capabilities: {updateProps: boolean};
|
|
33
|
+
updateProps(props: Record<string, unknown>): Promise<void>;
|
|
34
|
+
dispose(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
export interface RuntimePlugin {
|
|
37
|
+
name: string;
|
|
38
|
+
version: string;
|
|
39
|
+
cacheKey?: string;
|
|
40
|
+
/** Framework-owned exact package roots merged into the runtime package policy. */
|
|
41
|
+
packageEntries?: NonNullable<PackageOptions['entries']>;
|
|
42
|
+
compilers?: CompilerAdapter[];
|
|
43
|
+
renderers?: RendererAdapter[];
|
|
44
|
+
preprocess?: TransformHook[];
|
|
45
|
+
postprocess?: TransformHook[];
|
|
46
|
+
load?(options: {id: string; url: string; type?: string}, context: {runtime: Runtime}): string | {code: string} | undefined | Promise<string | {code:string} | undefined>;
|
|
47
|
+
configure?(context: {runtime: Runtime; pipeline: unknown}): void | Promise<void>;
|
|
48
|
+
dispose?(): void | Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
export type PackageOptions = {
|
|
51
|
+
provider?: 'esm.sh' | 'esm' | 'jsdelivr' | 'jsDelivr';
|
|
52
|
+
versions?: Record<string,string>;
|
|
53
|
+
entries?: Record<string, {provider?: string;source?:string;version?:string;repository?:string;package?:string;ref?:string;url?:string;subpaths?:boolean}>;
|
|
54
|
+
};
|
|
55
|
+
export interface RuntimeOptions {
|
|
56
|
+
plugins?: RuntimePlugin[];
|
|
57
|
+
defaultType?: string;
|
|
58
|
+
packages?: PackageOptions;
|
|
59
|
+
modules?: Record<string, object>;
|
|
60
|
+
urls?: Record<string,string>;
|
|
61
|
+
compileCache?: boolean | Record<string,unknown>;
|
|
62
|
+
allowNativeImports?: boolean;
|
|
63
|
+
resolve?(specifier:string,importer?:string):string | undefined;
|
|
64
|
+
fallbackResolve?(specifier:string,importer?:string):string | undefined;
|
|
65
|
+
}
|
|
66
|
+
export interface Runtime {
|
|
67
|
+
ready: Promise<void>;
|
|
68
|
+
define(id:string,source:string,config?:{type?:string;format?:string;imports?:Record<string,unknown>}):string;
|
|
69
|
+
defineMany(definitions:ModuleSource[]):string[];
|
|
70
|
+
update(id:string,source:string,config?:{type?:string;format?:string;imports?:Record<string,unknown>}):string;
|
|
71
|
+
defineModule(id:string, namespace:object | Function):string;
|
|
72
|
+
defineUrl(id:string,url:string):string;
|
|
73
|
+
loadSource(id:string,options?:{type?:string;url?:string}):Promise<string>;
|
|
74
|
+
import(id:string):Promise<Record<string,any>>;
|
|
75
|
+
compile(id:string,options?:Record<string,unknown>):Promise<{id:string;code?:string;url?:string;dependencies:string[];diagnostics:Diagnostic[];assets?:EmittedAsset[]}>;
|
|
76
|
+
mount(options:{module:string;export?:string;target:Element|string;props?:Record<string,unknown>}):Promise<MountHandle>;
|
|
77
|
+
remove(id:string,opts?:Record<string,unknown>):boolean;
|
|
78
|
+
clear(opts?:Record<string,unknown>):string[];
|
|
79
|
+
has(id:string):boolean;
|
|
80
|
+
invalidate(id:string,opts?:Record<string,unknown>):string[];
|
|
81
|
+
resolve(specifier:string,importer?:string):string;
|
|
82
|
+
inspectPackageResolution(specifier:string):Record<string,unknown>|undefined;
|
|
83
|
+
subscribe(listener:(event:Record<string,unknown>)=>void):()=>void;
|
|
84
|
+
modules():Array<Record<string,unknown>>;
|
|
85
|
+
dependencies(id:string):string[];
|
|
86
|
+
dependents(id:string):string[];
|
|
87
|
+
getModuleInfo(id:string):Record<string,unknown>|undefined;
|
|
88
|
+
getSourceType(id:string):string|undefined;
|
|
89
|
+
getSupportedTypes():string[];
|
|
90
|
+
getBuildArtifact(id:string):BuildState|undefined;
|
|
91
|
+
compileCache: Record<string,unknown>;
|
|
92
|
+
dispose():Promise<void>;
|
|
93
|
+
}
|
|
94
|
+
export declare function createRuntime(options?:RuntimeOptions):Runtime;
|
|
95
|
+
export declare function analyzeImports(source:string):Array<{specifier:string;start:number;end:number;kind:string}>;
|
|
96
|
+
export declare class BuildPhaseError extends Error {phase:string;id:string;plugin?:string;cause:unknown}
|
|
97
|
+
export declare function createBuildPipeline(options?:{plugins?:RuntimePlugin[];defaultType?:string}):{compile(source:string,ctx:{id:string;format:string}):Promise<BuildState>;detectType(id:string,explicit?:string):string;formats:string[]};
|
|
98
|
+
export declare function createStyleManager():{acquire(asset:{id:string;content:string},target?:Document|ShadowRoot):()=>void;dispose():void;readonly size:number};
|
|
99
|
+
export declare class PackageVersionResolutionError extends Error {code:string}
|
|
100
|
+
export declare function parsePackageSpecifier(specifier:string):{packageName:string;subpath:string}|undefined;
|
|
101
|
+
export declare function createPackagePolicy(options?:PackageOptions):unknown;
|
|
102
|
+
export declare function createMemoryCompileCache(options?:Record<string,unknown>):unknown;
|
|
103
|
+
export declare function createLocalStorageCompileCache(options?:Record<string,unknown>):unknown;
|
|
104
|
+
export declare function createIndexedDBCompileCache(options?:Record<string,unknown>):unknown;
|
|
105
|
+
export declare function createDefaultModuleUrlBackend():unknown;
|
|
106
|
+
export declare function createBlobModuleUrlBackend():unknown;
|
|
107
|
+
export declare function createDataModuleUrlBackend():unknown;
|
package/package.json
CHANGED
|
@@ -1,6 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browser-module-runtime",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./index.d.ts",
|
|
8
|
+
"import": "./src/index.js"
|
|
9
|
+
},
|
|
10
|
+
"./html": {
|
|
11
|
+
"types": "./html.d.ts",
|
|
12
|
+
"import": "./src/html/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./packages": "./src/engine/package-resolution/index.js",
|
|
15
|
+
"./cache": "./src/engine/compile-cache.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"src",
|
|
19
|
+
"index.d.ts",
|
|
20
|
+
"html.d.ts",
|
|
21
|
+
"README.md"
|
|
22
|
+
],
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=20"
|
|
25
|
+
},
|
|
26
|
+
"description": "Browser-native module runtime with scoped imports, package resolution, compilation pipelines, and declarative HTML rendering.",
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"browser",
|
|
32
|
+
"esm",
|
|
33
|
+
"runtime",
|
|
34
|
+
"modules",
|
|
35
|
+
"compiler"
|
|
36
|
+
]
|
|
37
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** Tiny dependency lexer for executable ESM. It does not transform source text.
|
|
2
|
+
* String offsets include quote delimiters, matching the linker ABI.
|
|
3
|
+
* Dynamic imports with non-literal arguments are deliberately left native.
|
|
4
|
+
* This lexer is not a full JS/TS parser. A production compiler may provide an
|
|
5
|
+
* `imports` array based on its own AST; see docs/BUILD_PIPELINE.md.
|
|
6
|
+
*/
|
|
7
|
+
export function analyzeImports(code) {
|
|
8
|
+
const tokens = lex(String(code));
|
|
9
|
+
const imports = [];
|
|
10
|
+
function push(t, kind) {
|
|
11
|
+
if (t?.type === 'string') imports.push({specifier:t.value,start:t.start,end:t.end,kind});
|
|
12
|
+
}
|
|
13
|
+
for (let i=0; i<tokens.length; i++) {
|
|
14
|
+
const t = tokens[i];
|
|
15
|
+
if (t.value === 'import') {
|
|
16
|
+
const next = tokens[i+1];
|
|
17
|
+
if (next?.value === '.' ) continue; // import.meta
|
|
18
|
+
if (next?.value === '(') { push(tokens[i+2], 'dynamic'); continue; }
|
|
19
|
+
if (next?.type === 'string') { push(next,'static'); continue; }
|
|
20
|
+
for (let j=i+1; j<tokens.length; j++) {
|
|
21
|
+
if (tokens[j].value === 'from' && tokens[j+1]?.type === 'string') {push(tokens[j+1],'static');break;}
|
|
22
|
+
if (tokens[j].value === ';' || tokens[j].value === 'import' || tokens[j].value === 'export') break;
|
|
23
|
+
}
|
|
24
|
+
} else if (t.value === 'export') {
|
|
25
|
+
for (let j=i+1;j<tokens.length;j++) {
|
|
26
|
+
if (tokens[j].value === 'from' && tokens[j+1]?.type === 'string') {push(tokens[j+1],'export');break;}
|
|
27
|
+
if (tokens[j].value === ';' || tokens[j].value === 'import' || tokens[j].value === 'export') break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return imports.sort((a,b)=>a.start-b.start).filter((t,i,a)=>i===0||t.start!==a[i-1].start);
|
|
32
|
+
}
|
|
33
|
+
function lex(code) {
|
|
34
|
+
const result=[]; let i=0; const len=code.length;
|
|
35
|
+
while(i<len) {
|
|
36
|
+
const start=i, c=code[i], n=code[i+1];
|
|
37
|
+
if (/\s/.test(c)) {i++;continue;}
|
|
38
|
+
if(c==='/'&&n==='/'){i+=2;while(i<len&&code[i]!=='\n')i++;continue;}
|
|
39
|
+
if(c==='/'&&n==='*'){i+=2;while(i<len&&!(code[i]==='*'&&code[i+1]==='/'))i++;i=Math.min(len,i+2);continue;}
|
|
40
|
+
if(c==='\''||c==='"') {
|
|
41
|
+
const quote=c; i++; let value='';
|
|
42
|
+
while(i<len) {let x=code[i++];if(x==='\\'){const escaped=code[i++]; value += escaped==='n'?'\n':escaped==='r'?'\r':escaped==='t'?'\t':escaped??'';continue;}if(x===quote)break; value+=x;}
|
|
43
|
+
result.push({type:'string',value,start,end:i});continue;
|
|
44
|
+
}
|
|
45
|
+
if(c==='`') { i++;while(i<len) {if(code[i]==='\\'){i+=2;continue;}if(code[i++]==='`')break;}continue; }
|
|
46
|
+
if(/[A-Za-z_$]/.test(c)){i++;while(i<len&&/[\w$]/.test(code[i]))i++;result.push({type:'word',value:code.slice(start,i),start,end:i});continue;}
|
|
47
|
+
if(c==='/'&®exPrefix(result.at(-1))) {i++; let inClass=false;while(i<len) {if(code[i]==='\\'){i+=2;continue;}if(code[i]==='[')inClass=true;if(code[i]===']')inClass=false;if(code[i++]==='/'&&!inClass)break;}while(i<len&&/[a-z]/i.test(code[i]))i++;continue;}
|
|
48
|
+
result.push({type:'symbol',value:c,start,end:++i});
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
function regexPrefix(previous) {
|
|
53
|
+
return !previous || ['=','(', '[', '{', ':', ',', ';', '!', '?', 'return', '=>'].includes(previous.value);
|
|
54
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {analyzeImports} from './analyze.js';
|
|
2
|
+
|
|
3
|
+
export class BuildPhaseError extends Error {
|
|
4
|
+
constructor(phase, id, plugin, cause){super(`${phase} failed for ${id}${plugin?` in ${plugin}`:''}: ${cause?.message||cause}`,{cause});this.name='BuildPhaseError';this.phase=phase;this.id=id;this.plugin=plugin;}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function createBuildPipeline({plugins=[],defaultType='javascript',onArtifact=()=>{}}={}) {
|
|
8
|
+
const byType=new Map([['javascript',{type:'javascript',plugin:'native',compiler: {compile(source){return {code:source};}}}], ['js',{type:'js',plugin:'native',compiler:{compile(source){return {code:source};}}}]]);
|
|
9
|
+
const formatsByExtension=new Map([['.js','javascript'],['.mjs','javascript']]);
|
|
10
|
+
for(const plugin of plugins){
|
|
11
|
+
if(!plugin?.name||!plugin.version)throw new TypeError('Plugins must declare name and stable version.');
|
|
12
|
+
for(const compiler of plugin.compilers||[]){
|
|
13
|
+
if(typeof compiler.compile!=='function')throw new TypeError(`Compiler in ${plugin.name} needs compile()`);
|
|
14
|
+
for(const type of compiler.types||[]) {
|
|
15
|
+
if(byType.has(type))throw new Error(`Compiler type ${type} registered twice`);
|
|
16
|
+
byType.set(type,{type,plugin:plugin.name,pluginVersion:plugin.version,compiler});
|
|
17
|
+
}
|
|
18
|
+
for(const ext of compiler.extensions||[]){if(formatsByExtension.has(ext)) formatsByExtension.set(ext,null);else formatsByExtension.set(ext,compiler.types?.[0]);}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const phases=['preprocess','postprocess'];
|
|
22
|
+
const hooks=Object.fromEntries(phases.map(phase=>[phase,plugins.flatMap(p=>(p[phase]||[]).map(fn=>({name:p.name,run:fn}))) ]));
|
|
23
|
+
function detectType(id,explicit){
|
|
24
|
+
if(explicit)return explicit;
|
|
25
|
+
const ext=/\.[A-Za-z0-9]+$/.exec(id)?.[0]?.toLowerCase();
|
|
26
|
+
const detected=ext&&formatsByExtension.get(ext);
|
|
27
|
+
if(ext&&formatsByExtension.has(ext)&&!detected)throw new Error(`Ambiguous extension ${ext}; provide an explicit type.`);
|
|
28
|
+
return detected||defaultType;
|
|
29
|
+
}
|
|
30
|
+
async function stage(phase,p,src,ctx){
|
|
31
|
+
try {const out=await p.run(src,ctx);return normalizeStage(out,src);}catch(error){throw new BuildPhaseError(phase,ctx.id,p.name,error);}
|
|
32
|
+
}
|
|
33
|
+
async function compile(source,{id,format:type='javascript'}={}) {
|
|
34
|
+
const chosen=byType.get(type);
|
|
35
|
+
if(!chosen)throw new BuildPhaseError('compile',id,null,new Error(`No compiler registered for script type ${type}`));
|
|
36
|
+
const ctx={id,format:type,type,plugin:chosen.plugin};let state={code:String(source),assets:[],diagnostics:[]};
|
|
37
|
+
for(const hook of hooks.preprocess)state=await stage('preprocess',hook,state,ctx);
|
|
38
|
+
try {state=normalizeStage(await chosen.compiler.compile(state.code,ctx),state);}catch(error){throw new BuildPhaseError('compile',id,chosen.plugin,error);}
|
|
39
|
+
for(const hook of hooks.postprocess)state=await stage('postprocess',hook,state,ctx);
|
|
40
|
+
let imports;
|
|
41
|
+
try {
|
|
42
|
+
imports=typeof chosen.compiler.analyze==='function'
|
|
43
|
+
? await chosen.compiler.analyze(state.code,ctx)
|
|
44
|
+
: analyzeImports(state.code);
|
|
45
|
+
if(!Array.isArray(imports))throw new TypeError('Compiler analyze() must return an array of import references');
|
|
46
|
+
}catch(error){throw new BuildPhaseError('analyze',id,chosen.plugin,error);}
|
|
47
|
+
const artifact={code:state.code,imports, diagnostics:state.diagnostics, ...(state.map?{sourceMap:state.map}:{}),assets:state.assets};
|
|
48
|
+
onArtifact(id,artifact);
|
|
49
|
+
return artifact;
|
|
50
|
+
}
|
|
51
|
+
function fingerprint(ctx={}) {
|
|
52
|
+
const signature=plugins.map(p=>[p.name,p.version,p.cacheKey??''].join(':')).join('|');
|
|
53
|
+
return `browser-module-runtime:pipeline:v1:${signature}:${ctx.format||''}`;
|
|
54
|
+
}
|
|
55
|
+
return {compile,fingerprint,detectType,formats:[...byType.keys()],owners:byType,plugins};
|
|
56
|
+
}
|
|
57
|
+
function normalizeStage(result,prior) {
|
|
58
|
+
if(result==null)return prior;
|
|
59
|
+
if(typeof result==='string')return {...prior,code:result};
|
|
60
|
+
if(!result||typeof result.code!=='string')throw new TypeError('Processor must return code string, artifact with code, or undefined.');
|
|
61
|
+
return {...prior,...result,assets:[...(prior.assets||[]),...(result.assets||[])],diagnostics:[...(prior.diagnostics||[]),...(result.diagnostics||[])]};
|
|
62
|
+
}
|