@remix-run/node-hmr 0.0.0 → 0.1.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/LICENSE +21 -0
- package/README.md +306 -2
- package/dist/index.d.ts +128 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +107 -0
- package/dist/lib/browser-events.d.ts +99 -0
- package/dist/lib/browser-events.d.ts.map +1 -0
- package/dist/lib/browser-events.js +11 -0
- package/dist/lib/events.d.ts +29 -0
- package/dist/lib/events.d.ts.map +1 -0
- package/dist/lib/events.js +32 -0
- package/dist/lib/hmr-analysis.d.ts +17 -0
- package/dist/lib/hmr-analysis.d.ts.map +1 -0
- package/dist/lib/hmr-analysis.js +130 -0
- package/dist/lib/module-store.d.ts +27 -0
- package/dist/lib/module-store.d.ts.map +1 -0
- package/dist/lib/module-store.js +161 -0
- package/dist/lib/process-state.d.ts +3 -0
- package/dist/lib/process-state.d.ts.map +1 -0
- package/dist/lib/process-state.js +7 -0
- package/dist/lib/runner.d.ts +62 -0
- package/dist/lib/runner.d.ts.map +1 -0
- package/dist/lib/runner.js +1046 -0
- package/dist/lib/runtime-api.d.ts +7 -0
- package/dist/lib/runtime-api.d.ts.map +1 -0
- package/dist/lib/runtime-api.js +1 -0
- package/dist/lib/runtime.d.ts +46 -0
- package/dist/lib/runtime.d.ts.map +1 -0
- package/dist/lib/runtime.js +374 -0
- package/dist/register.d.ts +2 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +317 -0
- package/dist/runtime.d.ts +26 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +32 -0
- package/dist/runtime.node-hmr.d.ts +27 -0
- package/dist/runtime.node-hmr.d.ts.map +1 -0
- package/dist/runtime.node-hmr.js +33 -0
- package/dist/types.d.ts +36 -0
- package/package.json +55 -5
- package/src/index.ts +244 -0
- package/src/lib/browser-events.ts +123 -0
- package/src/lib/events.ts +61 -0
- package/src/lib/hmr-analysis.ts +178 -0
- package/src/lib/module-store.ts +228 -0
- package/src/lib/process-state.ts +9 -0
- package/src/lib/runner.ts +1427 -0
- package/src/lib/runtime-api.ts +9 -0
- package/src/lib/runtime.ts +534 -0
- package/src/register.ts +401 -0
- package/src/runtime.node-hmr.ts +40 -0
- package/src/runtime.ts +40 -0
- package/src/types.d.ts +36 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type ServerHmrEvent = {
|
|
2
|
+
acceptedUrl?: string;
|
|
3
|
+
filePath: string;
|
|
4
|
+
timestamp: number;
|
|
5
|
+
type: 'update';
|
|
6
|
+
url: string;
|
|
7
|
+
} | {
|
|
8
|
+
filePath?: string;
|
|
9
|
+
reason?: string;
|
|
10
|
+
timestamp: number;
|
|
11
|
+
type: 'restart';
|
|
12
|
+
url?: string;
|
|
13
|
+
};
|
|
14
|
+
export interface ServerHmrEventSource {
|
|
15
|
+
subscribe(listener: (event: ServerHmrEvent) => void): () => void;
|
|
16
|
+
}
|
|
17
|
+
type ServerHmrEventListener = (event: ServerHmrEvent) => void;
|
|
18
|
+
declare class ServerHmrEvents implements ServerHmrEventSource {
|
|
19
|
+
#private;
|
|
20
|
+
subscribe(listener: ServerHmrEventListener): () => void;
|
|
21
|
+
emit(event: ServerHmrEvent): void;
|
|
22
|
+
}
|
|
23
|
+
export declare const serverHmrEvents: ServerHmrEvents;
|
|
24
|
+
export declare function emitServerHmrEvent(event: ServerHmrEvent): void;
|
|
25
|
+
export declare function emitServerHmrUpdate(event: Extract<ServerHmrEvent, {
|
|
26
|
+
type: 'update';
|
|
27
|
+
}>): void;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/lib/events.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,cAAc,GACtB;IACE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,QAAQ,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;CACZ,GACD;IACE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,SAAS,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAEL,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;CACjE;AAED,KAAK,sBAAsB,GAAG,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAA;AAE7D,cAAM,eAAgB,YAAW,oBAAoB;;IAGnD,SAAS,CAAC,QAAQ,EAAE,sBAAsB,GAAG,MAAM,IAAI,CAKtD;IAED,IAAI,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAIhC;CACF;AAED,eAAO,MAAM,eAAe,iBAAwB,CAAA;AAEpD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAE9D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,GAAG,IAAI,CAW5F"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
2
|
+
import { hasNodeHmrParentProcess } from './process-state.js';
|
|
3
|
+
class ServerHmrEvents {
|
|
4
|
+
#listeners = new Set();
|
|
5
|
+
subscribe(listener) {
|
|
6
|
+
this.#listeners.add(listener);
|
|
7
|
+
return () => {
|
|
8
|
+
this.#listeners.delete(listener);
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
emit(event) {
|
|
12
|
+
for (let listener of this.#listeners) {
|
|
13
|
+
listener(event);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export const serverHmrEvents = new ServerHmrEvents();
|
|
18
|
+
export function emitServerHmrEvent(event) {
|
|
19
|
+
serverHmrEvents.emit(event);
|
|
20
|
+
}
|
|
21
|
+
export function emitServerHmrUpdate(event) {
|
|
22
|
+
emitServerHmrEvent(event);
|
|
23
|
+
if (!hasNodeHmrParentProcess())
|
|
24
|
+
return;
|
|
25
|
+
process.send?.({
|
|
26
|
+
acceptedUrl: event.acceptedUrl,
|
|
27
|
+
filePath: event.filePath,
|
|
28
|
+
timestamp: event.timestamp,
|
|
29
|
+
type: 'node-hmr:child:hot-module-updated',
|
|
30
|
+
url: event.url,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface NodeHmrAnalysis {
|
|
2
|
+
acceptedDeps: NodeHmrAcceptedDependency[];
|
|
3
|
+
selfAccepting: boolean;
|
|
4
|
+
usesImportMetaHot: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface ResolvedNodeHmrAnalysis {
|
|
7
|
+
acceptedDeps: string[];
|
|
8
|
+
selfAccepting: boolean;
|
|
9
|
+
usesImportMetaHot: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface NodeHmrAcceptedDependency {
|
|
12
|
+
end: number;
|
|
13
|
+
specifier: string;
|
|
14
|
+
start: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function analyzeNodeHmrSource(importerUrl: string, source: string): NodeHmrAnalysis;
|
|
17
|
+
//# sourceMappingURL=hmr-analysis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hmr-analysis.d.ts","sourceRoot":"","sources":["../../src/lib/hmr-analysis.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,yBAAyB,EAAE,CAAA;IACzC,aAAa,EAAE,OAAO,CAAA;IACtB,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,aAAa,EAAE,OAAO,CAAA;IACtB,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd;AAKD,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,eAAe,CAoDzF"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { parseSync, visitorKeys } from 'oxc-parser';
|
|
2
|
+
const invalidAcceptMessage = 'import.meta.hot.accept() can only accept a callback, a string literal, or an array of string literals.';
|
|
3
|
+
export function analyzeNodeHmrSource(importerUrl, source) {
|
|
4
|
+
if (!source.includes('import.meta.hot')) {
|
|
5
|
+
return {
|
|
6
|
+
acceptedDeps: [],
|
|
7
|
+
selfAccepting: false,
|
|
8
|
+
usesImportMetaHot: false,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
let acceptedDeps = [];
|
|
12
|
+
let selfAccepting = false;
|
|
13
|
+
let usesImportMetaHot = false;
|
|
14
|
+
let parseResult = parseSync('node-hmr-analysis.js', source, {
|
|
15
|
+
lang: 'js',
|
|
16
|
+
sourceType: 'module',
|
|
17
|
+
});
|
|
18
|
+
if (parseResult.errors.length > 0) {
|
|
19
|
+
return {
|
|
20
|
+
acceptedDeps: [],
|
|
21
|
+
selfAccepting: false,
|
|
22
|
+
usesImportMetaHot: false,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
walkAst(parseResult.program, (node) => {
|
|
26
|
+
if (isImportMetaHotNode(node)) {
|
|
27
|
+
usesImportMetaHot = true;
|
|
28
|
+
}
|
|
29
|
+
if (node.type !== 'CallExpression')
|
|
30
|
+
return;
|
|
31
|
+
if (!isImportMetaHotAcceptCallee(node.callee))
|
|
32
|
+
return;
|
|
33
|
+
let [firstArgument] = node.arguments;
|
|
34
|
+
if (firstArgument === undefined || isSelfAcceptArgument(firstArgument)) {
|
|
35
|
+
selfAccepting = true;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
let deps = getAcceptedDependencies(firstArgument);
|
|
39
|
+
if (deps === null) {
|
|
40
|
+
throw new TypeError(invalidAcceptMessage);
|
|
41
|
+
}
|
|
42
|
+
acceptedDeps.push(...deps);
|
|
43
|
+
});
|
|
44
|
+
return {
|
|
45
|
+
acceptedDeps,
|
|
46
|
+
selfAccepting,
|
|
47
|
+
usesImportMetaHot,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function isImportMetaHotAcceptCallee(node) {
|
|
51
|
+
let callee = unwrapChainExpression(node);
|
|
52
|
+
if (callee.type !== 'MemberExpression')
|
|
53
|
+
return false;
|
|
54
|
+
if (callee.computed || !isIdentifierNode(callee.property, 'accept'))
|
|
55
|
+
return false;
|
|
56
|
+
return isImportMetaHotNode(callee.object);
|
|
57
|
+
}
|
|
58
|
+
function isImportMetaHotNode(node) {
|
|
59
|
+
let hot = unwrapChainExpression(node);
|
|
60
|
+
if (hot.type !== 'MemberExpression')
|
|
61
|
+
return false;
|
|
62
|
+
if (hot.computed || !isIdentifierNode(hot.property, 'hot'))
|
|
63
|
+
return false;
|
|
64
|
+
let meta = unwrapChainExpression(hot.object);
|
|
65
|
+
return (meta.type === 'MetaProperty' &&
|
|
66
|
+
isIdentifierNode(meta.meta, 'import') &&
|
|
67
|
+
isIdentifierNode(meta.property, 'meta'));
|
|
68
|
+
}
|
|
69
|
+
function unwrapChainExpression(node) {
|
|
70
|
+
return node.type === 'ChainExpression' ? node.expression : node;
|
|
71
|
+
}
|
|
72
|
+
function isIdentifierNode(node, name) {
|
|
73
|
+
return node.type === 'Identifier' && node.name === name;
|
|
74
|
+
}
|
|
75
|
+
function isSelfAcceptArgument(node) {
|
|
76
|
+
return (node.type === 'FunctionExpression' ||
|
|
77
|
+
node.type === 'ArrowFunctionExpression' ||
|
|
78
|
+
isIdentifierNode(node, 'undefined'));
|
|
79
|
+
}
|
|
80
|
+
function getAcceptedDependencies(node) {
|
|
81
|
+
if (isStringLiteralNode(node)) {
|
|
82
|
+
return [toAcceptedDependency(node)];
|
|
83
|
+
}
|
|
84
|
+
if (node.type !== 'ArrayExpression')
|
|
85
|
+
return null;
|
|
86
|
+
let deps = [];
|
|
87
|
+
for (let element of node.elements) {
|
|
88
|
+
if (!isStringLiteralNode(element))
|
|
89
|
+
return null;
|
|
90
|
+
deps.push(toAcceptedDependency(element));
|
|
91
|
+
}
|
|
92
|
+
return deps;
|
|
93
|
+
}
|
|
94
|
+
function toAcceptedDependency(node) {
|
|
95
|
+
return {
|
|
96
|
+
end: node.end - 1,
|
|
97
|
+
specifier: node.value,
|
|
98
|
+
start: node.start + 1,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function walkAst(node, visit) {
|
|
102
|
+
visit(node);
|
|
103
|
+
let keys = visitorKeys[node.type];
|
|
104
|
+
if (!keys)
|
|
105
|
+
return;
|
|
106
|
+
let walkableNode = node;
|
|
107
|
+
for (let key of keys) {
|
|
108
|
+
let value = walkableNode[key];
|
|
109
|
+
if (Array.isArray(value)) {
|
|
110
|
+
for (let child of value) {
|
|
111
|
+
if (isAstNode(child)) {
|
|
112
|
+
walkAst(child, visit);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (isAstNode(value)) {
|
|
118
|
+
walkAst(value, visit);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function isAstNode(value) {
|
|
123
|
+
return typeof value === 'object' && value !== null && 'type' in value;
|
|
124
|
+
}
|
|
125
|
+
function isStringLiteralNode(node) {
|
|
126
|
+
return (node?.type === 'Literal' &&
|
|
127
|
+
typeof node.end === 'number' &&
|
|
128
|
+
typeof node.start === 'number' &&
|
|
129
|
+
typeof node.value === 'string');
|
|
130
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface ModuleRecord {
|
|
2
|
+
filePath: string;
|
|
3
|
+
hmr: {
|
|
4
|
+
acceptedDeps: string[];
|
|
5
|
+
selfAccepting: boolean;
|
|
6
|
+
usesImportMetaHot: boolean;
|
|
7
|
+
};
|
|
8
|
+
url: string;
|
|
9
|
+
}
|
|
10
|
+
export interface HotUpdateBoundary {
|
|
11
|
+
acceptedDependencyUrl: string;
|
|
12
|
+
invalidatedUrls: Record<string, number>;
|
|
13
|
+
updateHandlerUrl: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ModuleStore {
|
|
16
|
+
addDependency(importerUrl: string, dependencyUrl: string): void;
|
|
17
|
+
findHotUpdateBoundaries(url: string, timestamp: number): HotUpdateBoundary[] | null;
|
|
18
|
+
findHotUpdateBoundariesFromImporters(url: string, timestamp: number): HotUpdateBoundary[] | null;
|
|
19
|
+
getModule(url: string): ModuleRecord | undefined;
|
|
20
|
+
getModulesForFile(filePath: string): readonly ModuleRecord[];
|
|
21
|
+
getReachableFilePaths(entryUrl: string): ReadonlySet<string>;
|
|
22
|
+
reset(): void;
|
|
23
|
+
setAcceptedDependencies(url: string, acceptedDependencies: string[]): void;
|
|
24
|
+
setModule(module: ModuleRecord): void;
|
|
25
|
+
}
|
|
26
|
+
export declare function createModuleStore(): ModuleStore;
|
|
27
|
+
//# sourceMappingURL=module-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-store.d.ts","sourceRoot":"","sources":["../../src/lib/module-store.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE;QACH,YAAY,EAAE,MAAM,EAAE,CAAA;QACtB,aAAa,EAAE,OAAO,CAAA;QACtB,iBAAiB,EAAE,OAAO,CAAA;KAC3B,CAAA;IACD,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,iBAAiB;IAChC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvC,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/D,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,iBAAiB,EAAE,GAAG,IAAI,CAAA;IACnF,oCAAoC,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,iBAAiB,EAAE,GAAG,IAAI,CAAA;IAChG,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAA;IAChD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,YAAY,EAAE,CAAA;IAC5D,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;IAC5D,KAAK,IAAI,IAAI,CAAA;IACb,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IAC1E,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;CACtC;AAED,wBAAgB,iBAAiB,IAAI,WAAW,CAoJ/C"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
export function createModuleStore() {
|
|
2
|
+
let modulesByUrl = new Map();
|
|
3
|
+
let modulesByFilePath = new Map();
|
|
4
|
+
let dependenciesByImporterUrl = new Map();
|
|
5
|
+
let importersByDependencyUrl = new Map();
|
|
6
|
+
return {
|
|
7
|
+
addDependency(importerUrl, dependencyUrl) {
|
|
8
|
+
addToIndexedSet(dependenciesByImporterUrl, importerUrl, dependencyUrl);
|
|
9
|
+
addToIndexedSet(importersByDependencyUrl, dependencyUrl, importerUrl);
|
|
10
|
+
},
|
|
11
|
+
findHotUpdateBoundaries(url, timestamp) {
|
|
12
|
+
return findPropagation(url, timestamp);
|
|
13
|
+
},
|
|
14
|
+
findHotUpdateBoundariesFromImporters(url, timestamp) {
|
|
15
|
+
return findPropagationFromImporters(url, timestamp, new Set([url]), [url]);
|
|
16
|
+
},
|
|
17
|
+
getModule(url) {
|
|
18
|
+
return modulesByUrl.get(url);
|
|
19
|
+
},
|
|
20
|
+
getModulesForFile(filePath) {
|
|
21
|
+
return [...(modulesByFilePath.get(filePath)?.values() ?? [])];
|
|
22
|
+
},
|
|
23
|
+
getReachableFilePaths(entryUrl) {
|
|
24
|
+
let reachableFilePaths = new Set();
|
|
25
|
+
let visitedUrls = new Set();
|
|
26
|
+
visit(entryUrl);
|
|
27
|
+
return reachableFilePaths;
|
|
28
|
+
function visit(url) {
|
|
29
|
+
if (visitedUrls.has(url))
|
|
30
|
+
return;
|
|
31
|
+
let module = modulesByUrl.get(url);
|
|
32
|
+
if (module === undefined)
|
|
33
|
+
return;
|
|
34
|
+
visitedUrls.add(url);
|
|
35
|
+
reachableFilePaths.add(module.filePath);
|
|
36
|
+
for (let dependencyUrl of dependenciesByImporterUrl.get(url) ?? []) {
|
|
37
|
+
visit(dependencyUrl);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
reset() {
|
|
42
|
+
modulesByUrl = new Map();
|
|
43
|
+
modulesByFilePath = new Map();
|
|
44
|
+
dependenciesByImporterUrl = new Map();
|
|
45
|
+
importersByDependencyUrl = new Map();
|
|
46
|
+
},
|
|
47
|
+
setAcceptedDependencies(url, acceptedDependencies) {
|
|
48
|
+
let module = modulesByUrl.get(url);
|
|
49
|
+
if (module !== undefined) {
|
|
50
|
+
module.hmr.acceptedDeps = acceptedDependencies;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
setModule(module) {
|
|
54
|
+
let previousModule = modulesByUrl.get(module.url);
|
|
55
|
+
if (previousModule !== undefined) {
|
|
56
|
+
removeModuleFromFileIndex(previousModule);
|
|
57
|
+
}
|
|
58
|
+
removeImporterDependencies(module.url);
|
|
59
|
+
modulesByUrl.set(module.url, module);
|
|
60
|
+
let fileModules = modulesByFilePath.get(module.filePath) ?? new Map();
|
|
61
|
+
fileModules.set(module.url, module);
|
|
62
|
+
modulesByFilePath.set(module.filePath, fileModules);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
function removeModuleFromFileIndex(module) {
|
|
66
|
+
let fileModules = modulesByFilePath.get(module.filePath);
|
|
67
|
+
if (fileModules === undefined)
|
|
68
|
+
return;
|
|
69
|
+
fileModules.delete(module.url);
|
|
70
|
+
if (fileModules.size === 0) {
|
|
71
|
+
modulesByFilePath.delete(module.filePath);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function removeImporterDependencies(importerUrl) {
|
|
75
|
+
let dependencies = dependenciesByImporterUrl.get(importerUrl);
|
|
76
|
+
if (dependencies === undefined)
|
|
77
|
+
return;
|
|
78
|
+
for (let dependencyUrl of dependencies) {
|
|
79
|
+
removeFromIndexedSet(importersByDependencyUrl, dependencyUrl, importerUrl);
|
|
80
|
+
}
|
|
81
|
+
dependenciesByImporterUrl.delete(importerUrl);
|
|
82
|
+
}
|
|
83
|
+
function findPropagation(url, timestamp, traversedUrls = new Set(), invalidatedUrls = [url]) {
|
|
84
|
+
if (traversedUrls.has(url))
|
|
85
|
+
return null;
|
|
86
|
+
let nextTraversedUrls = new Set(traversedUrls);
|
|
87
|
+
nextTraversedUrls.add(url);
|
|
88
|
+
let module = modulesByUrl.get(url);
|
|
89
|
+
if (module === undefined)
|
|
90
|
+
return null;
|
|
91
|
+
if (module.hmr.selfAccepting) {
|
|
92
|
+
return [createHotUpdateBoundary(url, url, invalidatedUrls, timestamp)];
|
|
93
|
+
}
|
|
94
|
+
return findPropagationFromImporters(url, timestamp, nextTraversedUrls, invalidatedUrls);
|
|
95
|
+
}
|
|
96
|
+
function findPropagationFromImporters(url, timestamp, traversedUrls, invalidatedUrls) {
|
|
97
|
+
let importerUrls = importersByDependencyUrl.get(url);
|
|
98
|
+
if (importerUrls === undefined || importerUrls.size === 0)
|
|
99
|
+
return null;
|
|
100
|
+
let importers = [...importerUrls]
|
|
101
|
+
.map((importerUrl) => modulesByUrl.get(importerUrl))
|
|
102
|
+
.filter((importer) => importer !== undefined);
|
|
103
|
+
if (importers.length === 0)
|
|
104
|
+
return null;
|
|
105
|
+
let boundaries = [];
|
|
106
|
+
for (let importer of importers) {
|
|
107
|
+
if (importer.hmr.acceptedDeps.includes(url)) {
|
|
108
|
+
boundaries.push(createHotUpdateBoundary(url, importer.url, invalidatedUrls, timestamp));
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
let importerUpdates = findPropagation(importer.url, timestamp, traversedUrls, [
|
|
112
|
+
...invalidatedUrls,
|
|
113
|
+
importer.url,
|
|
114
|
+
]);
|
|
115
|
+
if (importerUpdates === null)
|
|
116
|
+
return null;
|
|
117
|
+
boundaries.push(...importerUpdates);
|
|
118
|
+
}
|
|
119
|
+
return deduplicateHotUpdateBoundaries(boundaries);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function createHotUpdateBoundary(acceptedDependencyUrl, updateHandlerUrl, invalidatedUrls, timestamp) {
|
|
123
|
+
let invalidationTimestamps = {};
|
|
124
|
+
for (let invalidatedUrl of invalidatedUrls) {
|
|
125
|
+
invalidationTimestamps[invalidatedUrl] = timestamp;
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
acceptedDependencyUrl,
|
|
129
|
+
invalidatedUrls: invalidationTimestamps,
|
|
130
|
+
updateHandlerUrl,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function deduplicateHotUpdateBoundaries(boundaries) {
|
|
134
|
+
let boundaryByKey = new Map();
|
|
135
|
+
let result = [];
|
|
136
|
+
for (let boundary of boundaries) {
|
|
137
|
+
let key = `${boundary.updateHandlerUrl}\0${boundary.acceptedDependencyUrl}`;
|
|
138
|
+
let existingBoundary = boundaryByKey.get(key);
|
|
139
|
+
if (existingBoundary !== undefined) {
|
|
140
|
+
Object.assign(existingBoundary.invalidatedUrls, boundary.invalidatedUrls);
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
boundaryByKey.set(key, boundary);
|
|
144
|
+
result.push(boundary);
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
function addToIndexedSet(map, key, value) {
|
|
149
|
+
let values = map.get(key) ?? new Set();
|
|
150
|
+
values.add(value);
|
|
151
|
+
map.set(key, values);
|
|
152
|
+
}
|
|
153
|
+
function removeFromIndexedSet(map, key, value) {
|
|
154
|
+
let values = map.get(key);
|
|
155
|
+
if (values === undefined)
|
|
156
|
+
return;
|
|
157
|
+
values.delete(value);
|
|
158
|
+
if (values.size === 0) {
|
|
159
|
+
map.delete(key);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-state.d.ts","sourceRoot":"","sources":["../../src/lib/process-state.ts"],"names":[],"mappings":"AAEA,wBAAgB,uBAAuB,IAAI,OAAO,CAEjD;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Stats } from 'node:fs';
|
|
2
|
+
import { watch } from 'chokidar';
|
|
3
|
+
import { type BrowserHmrFileEvent } from './browser-events.ts';
|
|
4
|
+
export declare function normalizeBrowserHmrFilePath(filePath: string): string;
|
|
5
|
+
export declare function getBrowserHmrFileEventsForWatchedFiles(options: {
|
|
6
|
+
changedPaths: readonly string[];
|
|
7
|
+
restartPathEvents: ReadonlyMap<string, 'add' | 'unlink'>;
|
|
8
|
+
watchedFiles: ReadonlySet<string>;
|
|
9
|
+
}): BrowserHmrFileEvent[];
|
|
10
|
+
export declare function getWatchedDirectoriesForFiles(filePaths: Iterable<string>): Set<string>;
|
|
11
|
+
type FileChangeStats = Pick<Stats, 'birthtimeMs' | 'ctimeMs' | 'ino' | 'mtimeMs' | 'size'>;
|
|
12
|
+
export declare function createFileChangeEventDeduper(): (filePath: string, stats: FileChangeStats | undefined) => boolean;
|
|
13
|
+
export declare function getSupervisorChokidarWatcher(supervisor: object): ReturnType<typeof watch> | undefined;
|
|
14
|
+
interface BrowserHmrChannelOptions {
|
|
15
|
+
host?: string;
|
|
16
|
+
port?: number;
|
|
17
|
+
pathname?: string;
|
|
18
|
+
}
|
|
19
|
+
interface NodeHmrWatchOptions {
|
|
20
|
+
ignore?: readonly string[];
|
|
21
|
+
poll?: boolean;
|
|
22
|
+
pollInterval?: number;
|
|
23
|
+
}
|
|
24
|
+
interface ResolvedChokidarWatchOptions {
|
|
25
|
+
awaitWriteFinish: {
|
|
26
|
+
pollInterval: number;
|
|
27
|
+
stabilityThreshold: number;
|
|
28
|
+
};
|
|
29
|
+
depth: number;
|
|
30
|
+
ignorePermissionErrors: boolean;
|
|
31
|
+
ignored: string[];
|
|
32
|
+
ignoreInitial: boolean;
|
|
33
|
+
interval: number;
|
|
34
|
+
usePolling: boolean;
|
|
35
|
+
}
|
|
36
|
+
export declare function createHmrSupervisor(options: {
|
|
37
|
+
browserHmrChannel: BrowserHmrChannelOptions | null;
|
|
38
|
+
cwd: string;
|
|
39
|
+
entry: string;
|
|
40
|
+
entryArgs: string[];
|
|
41
|
+
env: NodeJS.ProcessEnv;
|
|
42
|
+
nodeArgs: string[];
|
|
43
|
+
registerPath: string;
|
|
44
|
+
watch?: NodeHmrWatchOptions;
|
|
45
|
+
}): {
|
|
46
|
+
readonly generation: number;
|
|
47
|
+
ready(): Promise<void>;
|
|
48
|
+
start(): Promise<void>;
|
|
49
|
+
stop(signal?: NodeJS.Signals): Promise<void>;
|
|
50
|
+
};
|
|
51
|
+
export declare function resolveChokidarWatchOptions(options?: NodeHmrWatchOptions): ResolvedChokidarWatchOptions;
|
|
52
|
+
export declare function buildChildProcessArgs(options: {
|
|
53
|
+
browserEventUrl?: string;
|
|
54
|
+
entry: string;
|
|
55
|
+
entryArgs: Array<string>;
|
|
56
|
+
nodeArgs: Array<string>;
|
|
57
|
+
registerPath: string;
|
|
58
|
+
rootPath?: string;
|
|
59
|
+
}): Array<string>;
|
|
60
|
+
export declare function buildChildProcessEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
61
|
+
export {};
|
|
62
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/lib/runner.ts"],"names":[],"mappings":"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"}
|