@vertz/ui-server 0.2.11 → 0.2.12

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.
@@ -7,6 +7,8 @@ type ContextScope = NonNullable<ReturnType<typeof getContextScope>>;
7
7
  interface SignalRef {
8
8
  peek(): unknown;
9
9
  value: unknown;
10
+ /** Optional HMR key for name-based signal matching (set by compiler). */
11
+ _hmrKey?: string;
10
12
  }
11
13
  /**
12
14
  * Register or update a component factory in the registry.
@@ -15,7 +17,7 @@ interface SignalRef {
15
17
  * On first load: creates a new record. On HMR re-evaluation: updates
16
18
  * the factory reference (instances are preserved for __$refreshPerform).
17
19
  */
18
- declare function __$refreshReg(moduleId: string, name: string, factory: (...args: unknown[]) => HTMLElement): void;
20
+ declare function __$refreshReg(moduleId: string, name: string, factory: (...args: unknown[]) => HTMLElement, hash?: string): void;
19
21
  /**
20
22
  * Track a live component instance for HMR replacement.
21
23
  *
@@ -32,14 +32,17 @@ function getModule(moduleId) {
32
32
  }
33
33
  return mod;
34
34
  }
35
- function __$refreshReg(moduleId, name, factory) {
35
+ function __$refreshReg(moduleId, name, factory, hash) {
36
36
  const mod = getModule(moduleId);
37
37
  const existing = mod.get(name);
38
38
  if (existing) {
39
+ if (hash && existing.hash === hash)
40
+ return;
39
41
  existing.factory = factory;
42
+ existing.hash = hash;
40
43
  dirtyModules.add(moduleId);
41
44
  } else {
42
- mod.set(name, { factory, instances: [] });
45
+ mod.set(name, { factory, instances: [], hash });
43
46
  }
44
47
  }
45
48
  function __$refreshTrack(moduleId, name, element, args, cleanups, contextScope, signals = []) {
@@ -93,21 +96,33 @@ function __$refreshPerform(moduleId) {
93
96
  updatedInstances.push(instance);
94
97
  continue;
95
98
  }
96
- if (savedValues.length > 0 && newSignals.length === savedValues.length) {
97
- for (let i = 0;i < newSignals.length; i++) {
98
- const sig = newSignals[i];
99
- if (sig)
100
- sig.value = savedValues[i];
99
+ try {
100
+ if (savedValues.length > 0) {
101
+ const namedSaved = new Map;
102
+ const unnamedSaved = [];
103
+ for (const s of oldSignals) {
104
+ if (s._hmrKey)
105
+ namedSaved.set(s._hmrKey, s.peek());
106
+ else
107
+ unnamedSaved.push(s.peek());
108
+ }
109
+ let unnamedIdx = 0;
110
+ for (const sig of newSignals) {
111
+ if (sig._hmrKey && namedSaved.has(sig._hmrKey)) {
112
+ sig.value = namedSaved.get(sig._hmrKey);
113
+ } else if (!sig._hmrKey && unnamedIdx < unnamedSaved.length) {
114
+ sig.value = unnamedSaved[unnamedIdx++];
115
+ }
116
+ }
101
117
  }
102
- } else if (savedValues.length > 0 && newSignals.length !== savedValues.length) {
103
- console.warn(`[vertz-hmr] Signal count changed in ${name} ` + `(${savedValues.length} \u2192 ${newSignals.length}). State reset.`);
104
- }
105
- popScope();
106
- runCleanups(cleanups);
107
- if (newCleanups.length > 0) {
108
- _tryOnCleanup(() => runCleanups(newCleanups));
118
+ popScope();
119
+ runCleanups(cleanups);
120
+ if (newCleanups.length > 0) {
121
+ _tryOnCleanup(() => runCleanups(newCleanups));
122
+ }
123
+ } finally {
124
+ setContextScope(prevScope);
109
125
  }
110
- setContextScope(prevScope);
111
126
  let domSnapshot = null;
112
127
  try {
113
128
  domSnapshot = captureDOMState(element);
@@ -41,12 +41,17 @@ function injectContextStableIds(source, sourceFile, relFilePath) {
41
41
  }
42
42
 
43
43
  // src/bun-plugin/fast-refresh-codegen.ts
44
- function generateRefreshPreamble(moduleId) {
44
+ function generateRefreshPreamble(moduleId, contentHash) {
45
45
  const escapedId = moduleId.replace(/['\\]/g, "\\$&");
46
- return `const __$fr = globalThis[Symbol.for('vertz:fast-refresh')];
46
+ let code = `const __$fr = globalThis[Symbol.for('vertz:fast-refresh')];
47
47
  ` + `const { __$refreshReg, __$refreshTrack, __$refreshPerform, ` + `pushScope: __$pushScope, popScope: __$popScope, ` + `_tryOnCleanup: __$tryCleanup, runCleanups: __$runCleanups, ` + `getContextScope: __$getCtx, setContextScope: __$setCtx, ` + `startSignalCollection: __$startSigCol, stopSignalCollection: __$stopSigCol } = __$fr;
48
48
  ` + `const __$moduleId = '${escapedId}';
49
49
  `;
50
+ if (contentHash) {
51
+ code += `const __$moduleHash = '${contentHash}';
52
+ `;
53
+ }
54
+ return code;
50
55
  }
51
56
  function generateRefreshWrapper(componentName) {
52
57
  return `
@@ -63,17 +68,17 @@ const __$orig_${componentName} = ${componentName};
63
68
  ` + ` }
64
69
  ` + ` return __$refreshTrack(__$moduleId, '${componentName}', __$ret, __$args, __$scope, __$ctx, __$sigs);
65
70
  ` + `};
66
- ` + `__$refreshReg(__$moduleId, '${componentName}', ${componentName});
71
+ ` + `__$refreshReg(__$moduleId, '${componentName}', ${componentName}, __$moduleHash);
67
72
  `;
68
73
  }
69
74
  function generateRefreshPerform() {
70
75
  return `__$refreshPerform(__$moduleId);
71
76
  `;
72
77
  }
73
- function generateRefreshCode(moduleId, components) {
78
+ function generateRefreshCode(moduleId, components, contentHash) {
74
79
  if (components.length === 0)
75
80
  return null;
76
- const preamble = generateRefreshPreamble(moduleId);
81
+ const preamble = generateRefreshPreamble(moduleId, contentHash);
77
82
  let epilogue = "";
78
83
  for (const comp of components) {
79
84
  epilogue += generateRefreshWrapper(comp.name);
@@ -159,7 +164,8 @@ function createVertzBunPlugin(options) {
159
164
  let refreshEpilogue = "";
160
165
  if (fastRefresh) {
161
166
  const components = componentAnalyzer.analyze(hydrationSourceFile);
162
- const refreshCode = generateRefreshCode(args.path, components);
167
+ const contentHash = Bun.hash(source).toString(36);
168
+ const refreshCode = generateRefreshCode(args.path, components, contentHash);
163
169
  if (refreshCode) {
164
170
  refreshPreamble = refreshCode.preamble;
165
171
  refreshEpilogue = refreshCode.epilogue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vertz/ui-server",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Vertz UI server-side rendering runtime",