ziex 0.1.0-dev.460 → 0.1.0-dev.517
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 +6 -5
- package/index.js +1 -1
- package/package.json +3 -3
- package/react/dom.d.ts +72 -45
- package/react/index.d.ts +1 -1
- package/react/index.js +93 -8
- package/react/types.d.ts +11 -14
- package/wasm/index.d.ts +4 -2
- package/wasm/index.js +5 -7
package/README.md
CHANGED
|
@@ -89,9 +89,10 @@ const zx = @import("zx");
|
|
|
89
89
|
- [x] Virtual DOM and diffing
|
|
90
90
|
- [x] Rendering only changed nodes
|
|
91
91
|
- [x] `on`event handler
|
|
92
|
-
- [
|
|
93
|
-
- [
|
|
92
|
+
- [x] State managment
|
|
93
|
+
- [x] Hydration
|
|
94
94
|
- [ ] Lifecycle hook
|
|
95
|
+
- [ ] Server Actions
|
|
95
96
|
- [x] Client Side Rendering (CSR) via React
|
|
96
97
|
- [x] Routing
|
|
97
98
|
- [x] File-system Routing
|
|
@@ -116,7 +117,7 @@ const zx = @import("zx");
|
|
|
116
117
|
- [x] HTML (optimized by default)
|
|
117
118
|
- [ ] Middleware (_cancalled_)
|
|
118
119
|
- [ ] Caching (configurable)
|
|
119
|
-
- [
|
|
120
|
+
- [x] Component
|
|
120
121
|
- [ ] Layout
|
|
121
122
|
- [x] Page
|
|
122
123
|
- [ ] Assets
|
|
@@ -144,8 +145,8 @@ const zx = @import("zx");
|
|
|
144
145
|
- [x] `update` Update the version of ZX dependency
|
|
145
146
|
- [x] `upgrade` Upgrade the version of ZX CLI
|
|
146
147
|
- [ ] Platform
|
|
147
|
-
- [x]
|
|
148
|
-
- [x]
|
|
148
|
+
- [x] Server
|
|
149
|
+
- [x] Browser
|
|
149
150
|
- [ ] iOS
|
|
150
151
|
- [ ] Android
|
|
151
152
|
- [ ] macOS
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ziex",
|
|
3
|
-
"version": "0.1.0-dev.
|
|
3
|
+
"version": "0.1.0-dev.517",
|
|
4
4
|
"description": "ZX is a framework for building web applications with Zig.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"homepage": "https://github.com/nurulhudaapon/zx",
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
|
-
"url": "
|
|
15
|
+
"url": "https://github.com/nurulhudaapon/zx.git"
|
|
16
16
|
},
|
|
17
17
|
"keywords": [
|
|
18
18
|
"zx",
|
|
@@ -30,4 +30,4 @@
|
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"module": "index.js",
|
|
32
32
|
"types": "index.d.ts"
|
|
33
|
-
}
|
|
33
|
+
}
|
package/react/dom.d.ts
CHANGED
|
@@ -8,14 +8,15 @@ export type PreparedComponent = {
|
|
|
8
8
|
/**
|
|
9
9
|
* The HTML element where the component should be rendered.
|
|
10
10
|
*
|
|
11
|
-
* This is
|
|
12
|
-
*
|
|
13
|
-
* React will hydrate this element, replacing its contents with the interactive component.
|
|
11
|
+
* This is a container element created between the comment markers. The server-rendered
|
|
12
|
+
* content is moved into this container, and React will hydrate it with the interactive component.
|
|
14
13
|
*
|
|
15
14
|
* @example
|
|
16
15
|
* ```tsx
|
|
17
|
-
* //
|
|
18
|
-
* //
|
|
16
|
+
* // Server-rendered HTML with comment markers:
|
|
17
|
+
* // <!--$zx-abc123-0 CounterComponent {"max_count":10}-->
|
|
18
|
+
* // <button>0</button>
|
|
19
|
+
* // <!--/$zx-abc123-0-->
|
|
19
20
|
*
|
|
20
21
|
* const { domNode } = await prepareComponent(component);
|
|
21
22
|
* createRoot(domNode).render(<Component {...props} />);
|
|
@@ -23,42 +24,28 @@ export type PreparedComponent = {
|
|
|
23
24
|
*/
|
|
24
25
|
domNode: HTMLElement;
|
|
25
26
|
/**
|
|
26
|
-
* Component props parsed from the
|
|
27
|
+
* Component props parsed from the comment marker.
|
|
27
28
|
*
|
|
28
|
-
* Props are extracted from the
|
|
29
|
-
*
|
|
30
|
-
* `dangerouslySetInnerHTML` for React compatibility.
|
|
29
|
+
* Props are extracted from the start comment marker content. The comment format is:
|
|
30
|
+
* `<!--$id name props-->` where props is JSON-encoded.
|
|
31
31
|
*
|
|
32
32
|
* @example
|
|
33
33
|
* ```tsx
|
|
34
34
|
* // Server-rendered HTML:
|
|
35
|
-
* //
|
|
35
|
+
* // <!--$zx-abc123-0 CounterComponent {"max_count":10,"label":"Counter"}-->
|
|
36
|
+
* // <button>0</button>
|
|
37
|
+
* // <!--/$zx-abc123-0-->
|
|
36
38
|
*
|
|
37
39
|
* const { props } = await prepareComponent(component);
|
|
38
|
-
* // props = {
|
|
39
|
-
* // max_count: 10,
|
|
40
|
-
* // label: "Counter",
|
|
41
|
-
* // dangerouslySetInnerHTML: { __html: "<span>0</span>" }
|
|
42
|
-
* // }
|
|
40
|
+
* // props = { max_count: 10, label: "Counter" }
|
|
43
41
|
* ```
|
|
44
42
|
*/
|
|
45
43
|
props: Record<string, any> & {
|
|
46
44
|
/**
|
|
47
45
|
* React's special prop for setting inner HTML directly.
|
|
48
46
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* @example
|
|
53
|
-
* ```tsx
|
|
54
|
-
* // In ZX file:
|
|
55
|
-
* <MyComponent @rendering={.react}>
|
|
56
|
-
* <p>Child content</p>
|
|
57
|
-
* </MyComponent>
|
|
58
|
-
*
|
|
59
|
-
* // Results in:
|
|
60
|
-
* // props.dangerouslySetInnerHTML = { __html: "<p>Child content</p>" }
|
|
61
|
-
* ```
|
|
47
|
+
* May be used when the component has server-rendered children that should
|
|
48
|
+
* be preserved during hydration.
|
|
62
49
|
*/
|
|
63
50
|
dangerouslySetInnerHTML?: {
|
|
64
51
|
__html: string;
|
|
@@ -85,12 +72,12 @@ export type PreparedComponent = {
|
|
|
85
72
|
Component: (props: any) => React.ReactElement;
|
|
86
73
|
};
|
|
87
74
|
/**
|
|
88
|
-
* Prepares a client-side component for hydration by locating its
|
|
89
|
-
* props
|
|
75
|
+
* Prepares a client-side component for hydration by locating its comment markers, extracting
|
|
76
|
+
* props from the marker content, and lazy-loading the component module.
|
|
90
77
|
*
|
|
91
78
|
* This function bridges server-rendered HTML (from ZX's Zig transpiler) and client-side React
|
|
92
|
-
* components. It
|
|
93
|
-
*
|
|
79
|
+
* components. It searches for comment markers in the format `<!--$id name props-->...<!--/$id-->`
|
|
80
|
+
* and extracts the component data from the marker content.
|
|
94
81
|
*
|
|
95
82
|
* @param component - The component metadata containing ID, import function, and other metadata
|
|
96
83
|
* needed to locate and load the component
|
|
@@ -98,8 +85,8 @@ export type PreparedComponent = {
|
|
|
98
85
|
* @returns A Promise that resolves to a `PreparedComponent` object containing the DOM node,
|
|
99
86
|
* parsed props, and the loaded React component function
|
|
100
87
|
*
|
|
101
|
-
* @throws {Error} If the component's
|
|
102
|
-
* happens if the component ID doesn't match any
|
|
88
|
+
* @throws {Error} If the component's comment markers cannot be found in the DOM. This typically
|
|
89
|
+
* happens if the component ID doesn't match any marker, the script runs before
|
|
103
90
|
* the HTML is loaded, or there's a mismatch between server and client metadata
|
|
104
91
|
*
|
|
105
92
|
* @example
|
|
@@ -118,18 +105,58 @@ export type PreparedComponent = {
|
|
|
118
105
|
*
|
|
119
106
|
* @example
|
|
120
107
|
* ```tsx
|
|
121
|
-
* //
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* createRoot(domNode).render(<Component {...props} />);
|
|
126
|
-
* } catch (error) {
|
|
127
|
-
* console.error(`Failed to hydrate ${component.name}:`, error);
|
|
128
|
-
* }
|
|
129
|
-
* }
|
|
130
|
-
*
|
|
131
|
-
* Promise.all(components.map(hydrateComponent));
|
|
108
|
+
* // Server-rendered HTML with comment markers:
|
|
109
|
+
* // <!--$zx-abc123-0 CounterComponent {"max_count":10}-->
|
|
110
|
+
* // <button>0</button>
|
|
111
|
+
* // <!--/$zx-abc123-0-->
|
|
132
112
|
* ```
|
|
133
113
|
*/
|
|
134
114
|
export declare function prepareComponent(component: ComponentMetadata): Promise<PreparedComponent>;
|
|
135
115
|
export declare function filterComponents(components: ComponentMetadata[]): ComponentMetadata[];
|
|
116
|
+
/**
|
|
117
|
+
* Discovered component from DOM traversal.
|
|
118
|
+
* Contains all metadata needed to hydrate the component.
|
|
119
|
+
*/
|
|
120
|
+
export type DiscoveredComponent = {
|
|
121
|
+
id: string;
|
|
122
|
+
name: string;
|
|
123
|
+
props: Record<string, any>;
|
|
124
|
+
container: HTMLElement;
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Finds all React component markers in the DOM and returns their metadata.
|
|
128
|
+
*
|
|
129
|
+
* This is a DOM-first approach that:
|
|
130
|
+
* 1. Walks the DOM once to find all `<!--$id-->` markers
|
|
131
|
+
* 2. Reads metadata from companion `<script data-zx="id">` elements
|
|
132
|
+
* 3. Creates containers for React to render into
|
|
133
|
+
*
|
|
134
|
+
* @returns Array of discovered components with their containers and props
|
|
135
|
+
*/
|
|
136
|
+
export declare function discoverComponents(): DiscoveredComponent[];
|
|
137
|
+
/**
|
|
138
|
+
* Component registry mapping component names to their import functions.
|
|
139
|
+
*/
|
|
140
|
+
export type ComponentRegistry = Record<string, () => Promise<(props: any) => React.ReactElement>>;
|
|
141
|
+
/**
|
|
142
|
+
* Hydrates all React components found in the DOM.
|
|
143
|
+
*
|
|
144
|
+
* This is the simplest way to hydrate React islands - it automatically:
|
|
145
|
+
* 1. Discovers all component markers in the DOM
|
|
146
|
+
* 2. Looks up components by name in the registry
|
|
147
|
+
* 3. Renders each component into its container
|
|
148
|
+
*
|
|
149
|
+
* @param registry - Map of component names to import functions
|
|
150
|
+
* @param render - Function to render a component (e.g., `(el, Component, props) => createRoot(el).render(<Component {...props} />)`)
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```ts
|
|
154
|
+
* import { hydrateAll } from "ziex/react";
|
|
155
|
+
*
|
|
156
|
+
* hydrateAll({
|
|
157
|
+
* CounterComponent: () => import("./Counter"),
|
|
158
|
+
* ToggleComponent: () => import("./Toggle"),
|
|
159
|
+
* });
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
export declare function hydrateAll(registry: ComponentRegistry, render: (container: HTMLElement, Component: (props: any) => React.ReactElement, props: Record<string, any>) => void): Promise<void>;
|
package/react/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { prepareComponent, filterComponents, type PreparedComponent } from "./dom";
|
|
1
|
+
export { prepareComponent, filterComponents, discoverComponents, hydrateAll, type PreparedComponent, type DiscoveredComponent, type ComponentRegistry, } from "./dom";
|
|
2
2
|
export type { ComponentMetadata } from "./types";
|
package/react/index.js
CHANGED
|
@@ -1,13 +1,56 @@
|
|
|
1
1
|
// src/react/dom.ts
|
|
2
|
+
function findCommentMarker(id) {
|
|
3
|
+
const startMarker = `$${id}`;
|
|
4
|
+
const endMarker = `/$${id}`;
|
|
5
|
+
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_COMMENT, null);
|
|
6
|
+
let startComment = null;
|
|
7
|
+
let endComment = null;
|
|
8
|
+
let node;
|
|
9
|
+
while (node = walker.nextNode()) {
|
|
10
|
+
const text = node.textContent?.trim() || "";
|
|
11
|
+
if (text === startMarker) {
|
|
12
|
+
startComment = node;
|
|
13
|
+
}
|
|
14
|
+
if (text === endMarker) {
|
|
15
|
+
endComment = node;
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (startComment && endComment) {
|
|
20
|
+
return { startComment, endComment };
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
function getComponentMetadata(id) {
|
|
25
|
+
const script = document.querySelector(`script[data-zx="${id}"]`);
|
|
26
|
+
if (script?.textContent) {
|
|
27
|
+
try {
|
|
28
|
+
const data = JSON.parse(script.textContent);
|
|
29
|
+
return { name: data.name || "", props: data.props || {} };
|
|
30
|
+
} catch {}
|
|
31
|
+
}
|
|
32
|
+
return { name: "", props: {} };
|
|
33
|
+
}
|
|
34
|
+
function createContainerBetweenMarkers(startComment, endComment) {
|
|
35
|
+
const container = document.createElement("div");
|
|
36
|
+
container.style.display = "contents";
|
|
37
|
+
let current = startComment.nextSibling;
|
|
38
|
+
while (current && current !== endComment) {
|
|
39
|
+
const next = current.nextSibling;
|
|
40
|
+
container.appendChild(current);
|
|
41
|
+
current = next;
|
|
42
|
+
}
|
|
43
|
+
endComment.parentNode?.insertBefore(container, endComment);
|
|
44
|
+
return container;
|
|
45
|
+
}
|
|
2
46
|
async function prepareComponent(component) {
|
|
3
|
-
const
|
|
4
|
-
if (!
|
|
5
|
-
throw new Error(`
|
|
6
|
-
const props = JSON.parse(domNode.getAttribute("data-props") || "{}");
|
|
7
|
-
const htmlChildren = domNode.getAttribute("data-children") ?? undefined;
|
|
8
|
-
if (htmlChildren) {
|
|
9
|
-
props.dangerouslySetInnerHTML = { __html: htmlChildren };
|
|
47
|
+
const marker = findCommentMarker(component.id);
|
|
48
|
+
if (!marker) {
|
|
49
|
+
throw new Error(`Comment marker for ${component.id} not found`, { cause: component });
|
|
10
50
|
}
|
|
51
|
+
const metadata = getComponentMetadata(component.id);
|
|
52
|
+
const props = metadata.props;
|
|
53
|
+
const domNode = createContainerBetweenMarkers(marker.startComment, marker.endComment);
|
|
11
54
|
const Component = await component.import();
|
|
12
55
|
return { domNode, props, Component };
|
|
13
56
|
}
|
|
@@ -15,7 +58,49 @@ function filterComponents(components) {
|
|
|
15
58
|
const currentPath = window.location.pathname;
|
|
16
59
|
return components.filter((component) => component.route === currentPath || !component.route);
|
|
17
60
|
}
|
|
61
|
+
function discoverComponents() {
|
|
62
|
+
const components = [];
|
|
63
|
+
const scripts = Array.from(document.querySelectorAll("script[data-zx]"));
|
|
64
|
+
for (const script of scripts) {
|
|
65
|
+
const id = script.getAttribute("data-zx");
|
|
66
|
+
if (!id)
|
|
67
|
+
continue;
|
|
68
|
+
let name = "";
|
|
69
|
+
let props = {};
|
|
70
|
+
try {
|
|
71
|
+
const data = JSON.parse(script.textContent || "{}");
|
|
72
|
+
name = data.name || "";
|
|
73
|
+
props = data.props || {};
|
|
74
|
+
} catch {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const marker = findCommentMarker(id);
|
|
78
|
+
if (!marker)
|
|
79
|
+
continue;
|
|
80
|
+
const container = createContainerBetweenMarkers(marker.startComment, marker.endComment);
|
|
81
|
+
components.push({ id, name, props, container });
|
|
82
|
+
}
|
|
83
|
+
return components;
|
|
84
|
+
}
|
|
85
|
+
async function hydrateAll(registry, render) {
|
|
86
|
+
const components = discoverComponents();
|
|
87
|
+
await Promise.all(components.map(async ({ name, props, container }) => {
|
|
88
|
+
const importer = registry[name];
|
|
89
|
+
if (!importer) {
|
|
90
|
+
console.warn(`Component "${name}" not found in registry`);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const Component = await importer();
|
|
95
|
+
render(container, Component, props);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.error(`Failed to hydrate "${name}":`, error);
|
|
98
|
+
}
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
18
101
|
export {
|
|
19
102
|
prepareComponent,
|
|
20
|
-
|
|
103
|
+
hydrateAll,
|
|
104
|
+
filterComponents,
|
|
105
|
+
discoverComponents
|
|
21
106
|
};
|
package/react/types.d.ts
CHANGED
|
@@ -85,17 +85,16 @@ export type ComponentMetadata = {
|
|
|
85
85
|
*/
|
|
86
86
|
route: string | null;
|
|
87
87
|
/**
|
|
88
|
-
* A unique
|
|
88
|
+
* A unique identifier for the component's hydration boundary.
|
|
89
89
|
*
|
|
90
90
|
* This ID is generated by hashing the component's path and name using MD5, then formatting it
|
|
91
|
-
* as a hex string with the "zx-" prefix. The ID is used to locate the
|
|
92
|
-
*
|
|
91
|
+
* as a hex string with the "zx-" prefix and a counter suffix. The ID is used to locate the
|
|
92
|
+
* component's comment markers in the DOM during client-side hydration.
|
|
93
93
|
*
|
|
94
|
-
* The ID format is: `zx-{32 hex characters}` (e.g., `zx-dcde04c415da9d1b15ca2690d8b497ae`)
|
|
94
|
+
* The ID format is: `zx-{32 hex characters}-{counter}` (e.g., `zx-dcde04c415da9d1b15ca2690d8b497ae-0`)
|
|
95
95
|
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* and `data-children` attributes to hydrate the component with the correct props and children.
|
|
96
|
+
* The ZX runtime renders components with comment markers in the format:
|
|
97
|
+
* `<!--$id name props-->...<!--/$id-->`
|
|
99
98
|
*
|
|
100
99
|
* @example
|
|
101
100
|
* ```tsx
|
|
@@ -103,15 +102,13 @@ export type ComponentMetadata = {
|
|
|
103
102
|
* {
|
|
104
103
|
* name: "CounterComponent",
|
|
105
104
|
* path: "./components/Counter.tsx",
|
|
106
|
-
* id: "zx-dcde04c415da9d1b15ca2690d8b497ae"
|
|
105
|
+
* id: "zx-dcde04c415da9d1b15ca2690d8b497ae-0"
|
|
107
106
|
* }
|
|
108
107
|
*
|
|
109
|
-
* // Generated HTML:
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* <!-- Server-rendered content -->
|
|
114
|
-
* </div>
|
|
108
|
+
* // Generated HTML with comment markers:
|
|
109
|
+
* <!--$zx-dcde04c415da9d1b15ca2690d8b497ae-0 CounterComponent {"max_count":10}-->
|
|
110
|
+
* <button>0</button>
|
|
111
|
+
* <!--/$zx-dcde04c415da9d1b15ca2690d8b497ae-0-->
|
|
115
112
|
* ```
|
|
116
113
|
*/
|
|
117
114
|
id: string;
|
package/wasm/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ZigJS } from "../../../../vendor/jsz/js/src";
|
|
2
|
+
export declare const jsz: ZigJS;
|
|
1
3
|
declare class ZXInstance {
|
|
2
4
|
#private;
|
|
3
5
|
exports: WebAssembly.Exports;
|
|
@@ -10,15 +12,15 @@ declare class ZXInstance {
|
|
|
10
12
|
* and uses __zx_ref to look up the corresponding VElement in WASM
|
|
11
13
|
*/
|
|
12
14
|
initEventDelegation(rootSelector?: string): void;
|
|
13
|
-
/** Get the VElement ID from a DOM element */
|
|
14
15
|
getZxRef(element: HTMLElement): number | undefined;
|
|
15
16
|
}
|
|
16
|
-
export declare function init(options?: InitOptions): Promise<
|
|
17
|
+
export declare function init(options?: InitOptions): Promise<WebAssembly.WebAssemblyInstantiatedSource>;
|
|
17
18
|
export type InitOptions = {
|
|
18
19
|
/** URL to the WASM file (default: /assets/main.wasm) */
|
|
19
20
|
url?: string;
|
|
20
21
|
/** CSS selector for the event delegation root element (default: 'body') */
|
|
21
22
|
eventDelegationRoot?: string;
|
|
23
|
+
importObject?: WebAssembly.Imports;
|
|
22
24
|
};
|
|
23
25
|
type ZXInstanceOptions = {
|
|
24
26
|
exports: ZXInstance['exports'];
|
package/wasm/index.js
CHANGED
|
@@ -214,8 +214,6 @@ var EVENT_TYPE_MAP = {
|
|
|
214
214
|
};
|
|
215
215
|
var jsz = new ZigJS;
|
|
216
216
|
var importObject = {
|
|
217
|
-
module: {},
|
|
218
|
-
env: {},
|
|
219
217
|
...jsz.importObject()
|
|
220
218
|
};
|
|
221
219
|
|
|
@@ -237,17 +235,14 @@ class ZXInstance {
|
|
|
237
235
|
if (this.#eventDelegationInitialized)
|
|
238
236
|
return;
|
|
239
237
|
const root = document.querySelector(rootSelector);
|
|
240
|
-
if (!root)
|
|
241
|
-
console.warn(`[ZX] Event delegation root "${rootSelector}" not found`);
|
|
238
|
+
if (!root)
|
|
242
239
|
return;
|
|
243
|
-
}
|
|
244
240
|
for (const eventType of DELEGATED_EVENTS) {
|
|
245
241
|
root.addEventListener(eventType, (event) => {
|
|
246
242
|
this.#handleDelegatedEvent(eventType, event);
|
|
247
243
|
}, { passive: eventType.startsWith("touch") || eventType === "scroll" });
|
|
248
244
|
}
|
|
249
245
|
this.#eventDelegationInitialized = true;
|
|
250
|
-
console.debug("[ZX] Event delegation initialized on", rootSelector);
|
|
251
246
|
}
|
|
252
247
|
#handleDelegatedEvent(eventType, event) {
|
|
253
248
|
let target = event.target;
|
|
@@ -271,14 +266,17 @@ class ZXInstance {
|
|
|
271
266
|
}
|
|
272
267
|
async function init(options = {}) {
|
|
273
268
|
const url = options?.url ?? DEFAULT_URL;
|
|
274
|
-
const
|
|
269
|
+
const wasmInstiatedSource = await WebAssembly.instantiateStreaming(fetch(url), Object.assign({}, importObject, options.importObject));
|
|
270
|
+
const { instance } = wasmInstiatedSource;
|
|
275
271
|
jsz.memory = instance.exports.memory;
|
|
276
272
|
window._zx = new ZXInstance({ exports: instance.exports });
|
|
277
273
|
window._zx.initEventDelegation(options.eventDelegationRoot ?? "body");
|
|
278
274
|
const main = instance.exports.mainClient;
|
|
279
275
|
if (typeof main === "function")
|
|
280
276
|
main();
|
|
277
|
+
return wasmInstiatedSource;
|
|
281
278
|
}
|
|
282
279
|
export {
|
|
280
|
+
jsz,
|
|
283
281
|
init
|
|
284
282
|
};
|