@zeus-js/web-c-runtime 0.1.1-beta.13 → 0.1.1-beta.14

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.
@@ -1,4 +1,4 @@
1
- import { CustomElementPropSchema, CustomElementPropType } from '@zeus-js/runtime-dom';
1
+ import { NormalizedPropChange, CustomElementPropSchema, CustomElementPropType } from '@zeus-js/runtime-dom';
2
2
 
3
3
  export type ZeusPropType = CustomElementPropType;
4
4
  export interface ZeusPropMeta extends CustomElementPropSchema {
@@ -36,10 +36,15 @@ export interface HostRef {
36
36
  connected: boolean;
37
37
  loaded: boolean;
38
38
  loading?: Promise<void>;
39
+ readinessError?: Error;
40
+ exposedMethods: Record<string, Function>;
39
41
  instance?: ZeusComponentInstance;
40
42
  values: Map<string, unknown>;
43
+ propDefinitions: ZeusPropMeta[];
41
44
  attributeProps: Set<string>;
42
45
  reflectingAttrs: Set<string>;
46
+ preUpgradeAttributes: Map<string, string>;
47
+ pendingAttributes: Map<string, string | null>;
43
48
  pendingFormCallbacks: ZeusFormCallback[];
44
49
  readyWaiters: Array<{
45
50
  resolve(host: HTMLElement): void;
@@ -49,7 +54,7 @@ export interface HostRef {
49
54
  export interface ZeusComponentInstance {
50
55
  connected?(): void;
51
56
  disconnected?(): void;
52
- propertyChanged?(name: string, oldValue: unknown, newValue: unknown): void;
57
+ propertyChanged?(change: NormalizedPropChange): void;
53
58
  formAssociated?(form: HTMLFormElement | null): void;
54
59
  formDisabled?(disabled: boolean): void;
55
60
  formReset?(): void;
@@ -85,4 +90,7 @@ export declare function bootstrapLazy(components: ZeusLazyComponentMeta[], optio
85
90
 
86
91
  export declare function createLazyElementClass(meta: ZeusLazyComponentMeta): CustomElementConstructor;
87
92
 
93
+ /** Replace deferred codec markers with the implementation's real schema. */
94
+ export declare function resolveHostProperties(hostRef: HostRef, definitions: ZeusPropMeta[]): void;
95
+
88
96
 
@@ -1,9 +1,9 @@
1
1
  /**
2
- * web-c-runtime v0.1.1-beta.13
2
+ * web-c-runtime v0.1.1-beta.14
3
3
  * (c) 2026 baicie
4
4
  * Released under the MIT License.
5
5
  **/
6
- import { coerceCustomElementAttribute, findCustomElementPropByAttribute, getCustomElementAttributeName, getCustomElementObservedAttributes, reflectCustomElementProperty } from "@zeus-js/runtime-dom";
6
+ import { coerceCustomElementAttribute, findCustomElementPropByAttribute, getCustomElementAttributeName, getCustomElementObservedAttributes, isWithinRuntimeDomMove, reflectCustomElementProperty } from "@zeus-js/runtime-dom";
7
7
  //#region packages/web-c/web-c-runtime/src/form-callbacks.ts
8
8
  function invokeFormCallback(hostRef, callback) {
9
9
  switch (callback.type) {
@@ -37,10 +37,14 @@ function registerHost(host, meta) {
37
37
  connected: false,
38
38
  loaded: false,
39
39
  values: /* @__PURE__ */ new Map(),
40
+ propDefinitions: [...meta.props],
40
41
  attributeProps: /* @__PURE__ */ new Set(),
41
42
  reflectingAttrs: /* @__PURE__ */ new Set(),
43
+ preUpgradeAttributes: /* @__PURE__ */ new Map(),
44
+ pendingAttributes: /* @__PURE__ */ new Map(),
42
45
  pendingFormCallbacks: [],
43
- readyWaiters: []
46
+ readyWaiters: [],
47
+ exposedMethods: Object.create(null)
44
48
  };
45
49
  hostRefs.set(host, hostRef);
46
50
  return hostRef;
@@ -69,10 +73,12 @@ function installPropertyAccessors(proto, props) {
69
73
  if (Object.getOwnPropertyDescriptor(proto, prop.name)) continue;
70
74
  Object.defineProperty(proto, prop.name, {
71
75
  get() {
72
- return getPropValue(requireHostRef(this), prop);
76
+ const hostRef = requireHostRef(this);
77
+ return getPropValue(hostRef, findProp(hostRef, prop.name));
73
78
  },
74
79
  set(value) {
75
- setPropValue(requireHostRef(this), prop, value);
80
+ const hostRef = requireHostRef(this);
81
+ setPropValue(hostRef, findProp(hostRef, prop.name), value);
76
82
  },
77
83
  configurable: true,
78
84
  enumerable: true
@@ -85,36 +91,56 @@ function getPropValue(hostRef, prop) {
85
91
  }
86
92
  function setPropValue(hostRef, prop, value) {
87
93
  const oldValue = getPropValue(hostRef, prop);
88
- if (Object.is(oldValue, value)) return;
89
94
  hostRef.values.set(prop.name, value);
90
95
  hostRef.attributeProps.delete(prop.name);
96
+ hostRef.pendingAttributes.delete(prop.name);
91
97
  if (prop.reflect) reflectCustomElementProperty(hostRef.host, prop, value, hostRef.reflectingAttrs);
92
- if (hostRef.loaded) {
98
+ if (hostRef.loaded && !Object.is(oldValue, value)) {
93
99
  var _hostRef$instance, _hostRef$instance$pro;
94
- (_hostRef$instance = hostRef.instance) === null || _hostRef$instance === void 0 || (_hostRef$instance$pro = _hostRef$instance.propertyChanged) === null || _hostRef$instance$pro === void 0 || _hostRef$instance$pro.call(_hostRef$instance, prop.name, oldValue, value);
100
+ (_hostRef$instance = hostRef.instance) === null || _hostRef$instance === void 0 || (_hostRef$instance$pro = _hostRef$instance.propertyChanged) === null || _hostRef$instance$pro === void 0 || _hostRef$instance$pro.call(_hostRef$instance, {
101
+ name: prop.name,
102
+ value,
103
+ source: "property"
104
+ });
95
105
  }
96
106
  }
97
- function syncAttributeToProperty(hostRef, attrName, _oldValue, newValue) {
107
+ function syncAttributeToProperty(hostRef, attrName, oldValue, newValue) {
98
108
  const normalizedAttrName = normalizeAttrName(attrName);
99
109
  if (hostRef.reflectingAttrs.has(normalizedAttrName)) return;
100
- const prop = findCustomElementPropByAttribute(hostRef.meta.props, normalizedAttrName);
110
+ const initialValue = hostRef.preUpgradeAttributes.get(normalizedAttrName);
111
+ hostRef.preUpgradeAttributes.delete(normalizedAttrName);
112
+ if (oldValue === null && newValue === initialValue) return;
113
+ const prop = findCustomElementPropByAttribute(hostRef.propDefinitions, normalizedAttrName);
101
114
  if (!prop) return;
115
+ hostRef.attributeProps.add(prop.name);
116
+ if (prop.deserialize === true) {
117
+ hostRef.pendingAttributes.set(prop.name, newValue);
118
+ return;
119
+ }
102
120
  const oldPropValue = getPropValue(hostRef, prop);
103
121
  const newPropValue = coerceCustomElementAttribute(prop, newValue);
104
- if (Object.is(oldPropValue, newPropValue)) return;
105
122
  hostRef.values.set(prop.name, newPropValue);
106
- hostRef.attributeProps.add(prop.name);
107
- if (hostRef.loaded) {
123
+ if (hostRef.loaded && !Object.is(oldPropValue, newPropValue)) {
108
124
  var _hostRef$instance2, _hostRef$instance2$pr;
109
- (_hostRef$instance2 = hostRef.instance) === null || _hostRef$instance2 === void 0 || (_hostRef$instance2$pr = _hostRef$instance2.propertyChanged) === null || _hostRef$instance2$pr === void 0 || _hostRef$instance2$pr.call(_hostRef$instance2, prop.name, oldPropValue, newPropValue);
125
+ (_hostRef$instance2 = hostRef.instance) === null || _hostRef$instance2 === void 0 || (_hostRef$instance2$pr = _hostRef$instance2.propertyChanged) === null || _hostRef$instance2$pr === void 0 || _hostRef$instance2$pr.call(_hostRef$instance2, {
126
+ name: prop.name,
127
+ value: newPropValue,
128
+ source: "attribute",
129
+ rawAttributeValue: newValue
130
+ });
110
131
  }
111
132
  }
112
133
  function applyInitialValues(hostRef) {
113
134
  const host = hostRef.host;
114
- for (const prop of hostRef.meta.props) {
135
+ for (const prop of hostRef.propDefinitions) {
115
136
  if (hostRef.values.has(prop.name)) continue;
116
137
  const attrName = getCustomElementAttributeName(prop);
117
138
  if (attrName && host.hasAttribute(attrName)) {
139
+ if (prop.deserialize === true) {
140
+ hostRef.pendingAttributes.set(prop.name, host.getAttribute(attrName));
141
+ hostRef.attributeProps.add(prop.name);
142
+ continue;
143
+ }
118
144
  hostRef.values.set(prop.name, coerceCustomElementAttribute(prop, host.getAttribute(attrName)));
119
145
  hostRef.attributeProps.add(prop.name);
120
146
  continue;
@@ -122,6 +148,20 @@ function applyInitialValues(hostRef) {
122
148
  if ("default" in prop) hostRef.values.set(prop.name, prop.default);
123
149
  }
124
150
  }
151
+ /** Replace deferred codec markers with the implementation's real schema. */
152
+ function resolveHostProperties(hostRef, definitions) {
153
+ for (const previous of hostRef.propDefinitions) {
154
+ if (!hostRef.pendingAttributes.has(previous.name)) continue;
155
+ const definition = definitions.find((prop) => prop.name === previous.name);
156
+ const attrName = definition && getCustomElementAttributeName(definition);
157
+ if (definition && attrName) hostRef.values.set(previous.name, coerceCustomElementAttribute(definition, hostRef.pendingAttributes.get(previous.name)));
158
+ }
159
+ hostRef.propDefinitions = definitions;
160
+ hostRef.pendingAttributes.clear();
161
+ }
162
+ function findProp(hostRef, name) {
163
+ return hostRef.propDefinitions.find((prop) => prop.name === name);
164
+ }
125
165
  function getObservedAttributes(props) {
126
166
  return getCustomElementObservedAttributes(props);
127
167
  }
@@ -139,6 +179,9 @@ function upgradePreDefinedProperties(host, hostRef) {
139
179
  const descriptor = Object.getOwnPropertyDescriptor(target, prop.name);
140
180
  if ((descriptor === null || descriptor === void 0 ? void 0 : descriptor.configurable) === false) continue;
141
181
  const value = target[prop.name];
182
+ const attrName = getCustomElementAttributeName(prop);
183
+ const attrValue = attrName ? host.getAttribute(attrName) : null;
184
+ if (attrName && attrValue !== null) hostRef.preUpgradeAttributes.set(attrName, attrValue);
142
185
  delete target[prop.name];
143
186
  setPropValue(hostRef, prop, value);
144
187
  }
@@ -177,6 +220,7 @@ function _asyncToGenerator(n) {
177
220
  const moduleCache = /* @__PURE__ */ new WeakMap();
178
221
  function waitForComponentReady(hostRef) {
179
222
  if (hostRef.loaded) return Promise.resolve(hostRef.host);
223
+ if (hostRef.readinessError) return Promise.reject(hostRef.readinessError);
180
224
  return new Promise((resolve, reject) => {
181
225
  hostRef.readyWaiters.push({
182
226
  resolve,
@@ -184,6 +228,11 @@ function waitForComponentReady(hostRef) {
184
228
  });
185
229
  });
186
230
  }
231
+ function rejectComponentReady(hostRef, error) {
232
+ hostRef.readinessError = error;
233
+ for (const name of Object.keys(hostRef.exposedMethods)) delete hostRef.exposedMethods[name];
234
+ rejectReadyWaiters(hostRef, error);
235
+ }
187
236
  function initializeComponent(_x) {
188
237
  return _initializeComponent.apply(this, arguments);
189
238
  }
@@ -197,6 +246,7 @@ function _initializeComponent() {
197
246
  }
198
247
  if (hostRef.loading) {
199
248
  yield hostRef.loading;
249
+ if (hostRef.connected && !hostRef.loaded) yield initializeComponent(hostRef);
200
250
  return;
201
251
  }
202
252
  const loading = doInitializeComponent(hostRef);
@@ -204,7 +254,7 @@ function _initializeComponent() {
204
254
  try {
205
255
  yield loading;
206
256
  } catch (error) {
207
- rejectReadyWaiters(hostRef, error);
257
+ rejectComponentReady(hostRef, error instanceof Error ? error : new Error(String(error)));
208
258
  throw error;
209
259
  } finally {
210
260
  if (hostRef.loading === loading) hostRef.loading = void 0;
@@ -309,16 +359,21 @@ function createLazyElementClass(meta) {
309
359
  connectedCallback() {
310
360
  const hostRef = requireHostRef(this);
311
361
  hostRef.connected = true;
362
+ hostRef.readinessError = void 0;
312
363
  initializeComponent(hostRef).catch((error) => {
313
364
  reportInitializationError(meta.tagName, error);
314
365
  });
315
366
  }
316
367
  disconnectedCallback() {
368
+ if (isWithinRuntimeDomMove(this)) return;
317
369
  const hostRef = requireHostRef(this);
318
370
  hostRef.connected = false;
319
- if (hostRef.loaded) {
371
+ if (!hostRef.loaded) rejectComponentReady(hostRef, /* @__PURE__ */ new Error(`[ZEUS_WC_DISCONNECTED_BEFORE_READY] <${meta.tagName}> disconnected before initialization completed.`));
372
+ if (hostRef.loaded) try {
320
373
  var _hostRef$instance, _hostRef$instance$dis;
321
374
  (_hostRef$instance = hostRef.instance) === null || _hostRef$instance === void 0 || (_hostRef$instance$dis = _hostRef$instance.disconnected) === null || _hostRef$instance$dis === void 0 || _hostRef$instance$dis.call(_hostRef$instance);
375
+ } finally {
376
+ for (const name of Object.keys(hostRef.exposedMethods)) delete hostRef.exposedMethods[name];
322
377
  }
323
378
  }
324
379
  attributeChangedCallback(name, oldValue, newValue) {
@@ -378,7 +433,8 @@ function installMethodProxies(proto, methods) {
378
433
  const args = Array.prototype.slice.call(arguments);
379
434
  const hostRef = requireHostRef(host);
380
435
  return waitForComponentReady(hostRef).then((readyHost) => {
381
- const method = readyHost[name];
436
+ if (!hostRef.connected) throw new Error(`[ZEUS_WC_DISCONNECTED_BEFORE_READY] <${hostRef.meta.tagName}> is disconnected.`);
437
+ const method = hostRef.exposedMethods[name];
382
438
  if (typeof method !== "function") throw new Error(`[zeus:web-c] Method "${name}" is not exposed on <${hostRef.meta.tagName}>.`);
383
439
  return method.apply(readyHost, args);
384
440
  });
@@ -388,15 +444,21 @@ function installMethodProxies(proto, methods) {
388
444
  }
389
445
  //#endregion
390
446
  //#region packages/web-c/web-c-runtime/src/bootstrapLazy.ts
447
+ const definitions = /* @__PURE__ */ new WeakMap();
391
448
  function bootstrapLazy(components, options = {}) {
392
449
  var _options$registry;
393
450
  const registry = (_options$registry = options.registry) !== null && _options$registry !== void 0 ? _options$registry : typeof customElements === "undefined" ? void 0 : customElements;
394
451
  if (!registry) return;
395
452
  for (const meta of components) {
396
- if (registry.get(meta.tagName)) continue;
453
+ const existing = registry.get(meta.tagName);
454
+ if (existing) {
455
+ if (definitions.get(existing) === meta) continue;
456
+ throw new Error(`[ZEUS_WC_DUPLICATE_TAG] <${meta.tagName}> is already registered with a different definition.`);
457
+ }
397
458
  const LazyElement = createLazyElementClass(meta);
398
459
  registry.define(meta.tagName, LazyElement);
460
+ definitions.set(LazyElement, meta);
399
461
  }
400
462
  }
401
463
  //#endregion
402
- export { bootstrapLazy, createLazyElementClass };
464
+ export { bootstrapLazy, createLazyElementClass, resolveHostProperties };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zeus-js/web-c-runtime",
3
3
  "type": "module",
4
- "version": "0.1.1-beta.13",
4
+ "version": "0.1.1-beta.14",
5
5
  "description": "Zeus Web-C lazy-loading runtime",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -26,7 +26,7 @@
26
26
  "dist"
27
27
  ],
28
28
  "dependencies": {
29
- "@zeus-js/runtime-dom": "0.1.1-beta.13"
29
+ "@zeus-js/runtime-dom": "0.1.1-beta.14"
30
30
  },
31
31
  "author": "Baicie",
32
32
  "buildOptions": {