@mulanjs/mulanjs 1.0.1-dev.20260227135307 → 1.0.1-dev.20260227173253
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/dist/compiler/ast-parser.d.ts +48 -0
- package/dist/compiler/ast-parser.js +54 -9
- package/dist/compiler/compiler.d.ts +9 -0
- package/dist/compiler/compiler.js +45 -2
- package/dist/compiler/dom-compiler.d.ts +7 -0
- package/dist/compiler/dom-compiler.js +90 -33
- package/dist/compiler/script-compiler.d.ts +11 -0
- package/dist/compiler/script-compiler.js +108 -116
- package/dist/compiler/sfc-parser.d.ts +21 -0
- package/dist/compiler/ssr-compiler.d.ts +7 -0
- package/dist/compiler/ssr-compiler.js +142 -0
- package/dist/compiler/style-compiler.d.ts +8 -0
- package/dist/compiler/template-compiler.d.ts +8 -0
- package/dist/components/bloch-sphere.js +9 -3
- package/dist/components/infinity-list.js +7 -1
- package/dist/core/component.js +66 -15
- package/dist/core/hooks.js +53 -29
- package/dist/core/quantum.js +30 -17
- package/dist/core/query.js +11 -6
- package/dist/core/reactive.js +88 -7
- package/dist/core/renderer.js +9 -8
- package/dist/core/ssr.js +50 -0
- package/dist/core/surge.js +7 -2
- package/dist/core/vault.js +9 -5
- package/dist/index.js +63 -27
- package/dist/mulan.esm.js +187 -19
- package/dist/mulan.esm.js.map +1 -1
- package/dist/mulan.js +1890 -1590
- package/dist/mulan.js.map +1 -1
- package/dist/router/index.js +17 -10
- package/dist/security/sanitizer.js +5 -1
- package/dist/store/index.js +9 -5
- package/dist/types/ast-parser.d.ts +2 -0
- package/dist/types/compiler/ast-parser.d.ts +2 -0
- package/dist/types/compiler/compiler.d.ts +1 -0
- package/dist/types/compiler/ssr-compiler.d.ts +7 -0
- package/dist/types/compiler.d.ts +1 -0
- package/dist/types/components/bloch-sphere.d.ts +3 -1
- package/dist/types/components/infinity-list.d.ts +3 -1
- package/dist/types/core/component.d.ts +14 -0
- package/dist/types/core/reactive.d.ts +5 -1
- package/dist/types/core/renderer.d.ts +0 -1
- package/dist/types/core/ssr.d.ts +9 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/ssr-compiler.d.ts +7 -0
- package/package.json +1 -1
- package/src/compiler/ast-parser.ts +62 -10
- package/src/compiler/compiler.ts +46 -1
- package/src/compiler/dom-compiler.ts +100 -34
- package/src/compiler/script-compiler.ts +117 -126
- package/src/compiler/ssr-compiler.ts +157 -0
- package/src/loader/index.js +12 -19
package/dist/core/ssr.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderToString = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Renders a Mulan component to a static HTML string with a resumability envelope.
|
|
6
|
+
*/
|
|
7
|
+
function renderToString(ComponentClass, props = {}) {
|
|
8
|
+
// 1. Initialize component in a virtual container (not used for DOM)
|
|
9
|
+
// On server, we mock the container or just pass a dummy object
|
|
10
|
+
const dummyContainer = {
|
|
11
|
+
querySelector: () => null,
|
|
12
|
+
querySelectorAll: () => [],
|
|
13
|
+
appendChild: () => { },
|
|
14
|
+
removeChild: () => { },
|
|
15
|
+
getAttribute: () => null
|
|
16
|
+
};
|
|
17
|
+
const instance = new ComponentClass(dummyContainer);
|
|
18
|
+
// Pass props
|
|
19
|
+
Object.assign(instance, props);
|
|
20
|
+
// 2. Render to HTML
|
|
21
|
+
if (typeof instance.renderToString !== 'function') {
|
|
22
|
+
throw new Error(`Component ${ComponentClass.name} was not compiled for SSR.`);
|
|
23
|
+
}
|
|
24
|
+
const html = instance.renderToString();
|
|
25
|
+
// 3. Extract State for Resumability
|
|
26
|
+
// We only want to serialize data that was exposed in setup()
|
|
27
|
+
// For now, we'll serialize any property on the instance that isn't internal
|
|
28
|
+
const state = {};
|
|
29
|
+
for (const key in instance) {
|
|
30
|
+
if (key.startsWith('_') || key === 'container' || key === 'state' || typeof instance[key] === 'function')
|
|
31
|
+
continue;
|
|
32
|
+
const value = instance[key];
|
|
33
|
+
// Handle signals specifically
|
|
34
|
+
if (value && typeof value === 'object' && 'value' in value) {
|
|
35
|
+
state[key] = value.value;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
state[key] = value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// 4. Construct Resumability Envelope
|
|
42
|
+
const stateScript = `<script type="mulan/state" data-mu-uid="${instance.$uid}">${JSON.stringify(state)}</script>`;
|
|
43
|
+
const envelope = `<div data-mu-root="${instance.$uid}">${html}${stateScript}</div>`;
|
|
44
|
+
return {
|
|
45
|
+
html,
|
|
46
|
+
state,
|
|
47
|
+
envelope
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
exports.renderToString = renderToString;
|
package/dist/core/surge.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.muSurge = exports.muBurst = void 0;
|
|
1
4
|
/**
|
|
2
5
|
* muBurst - Adaptive Non-blocking Iterator
|
|
3
6
|
* Processes large arrays in batches within a frame budget (typically 8-16ms)
|
|
4
7
|
* to keep the UI responsive while executing at near-native loop speeds.
|
|
5
8
|
*/
|
|
6
|
-
|
|
9
|
+
function muBurst(array, callback, options = {}) {
|
|
7
10
|
const { chunkSize = 1000, timeout = 8, onProgress } = options;
|
|
8
11
|
return new Promise((resolve) => {
|
|
9
12
|
let index = 0;
|
|
@@ -31,12 +34,13 @@ export function muBurst(array, callback, options = {}) {
|
|
|
31
34
|
process();
|
|
32
35
|
});
|
|
33
36
|
}
|
|
37
|
+
exports.muBurst = muBurst;
|
|
34
38
|
/**
|
|
35
39
|
* muSurge - Truly Parallel Execution
|
|
36
40
|
* Distributes work across CPU cores using Web Workers.
|
|
37
41
|
* Logic must be serializable.
|
|
38
42
|
*/
|
|
39
|
-
|
|
43
|
+
function muSurge(array, taskFn, onProgress) {
|
|
40
44
|
const n = navigator.hardwareConcurrency || 4;
|
|
41
45
|
const chunkSize = Math.ceil(array.length / n);
|
|
42
46
|
const results = new Array(array.length);
|
|
@@ -85,3 +89,4 @@ export function muSurge(array, taskFn, onProgress) {
|
|
|
85
89
|
}
|
|
86
90
|
});
|
|
87
91
|
}
|
|
92
|
+
exports.muSurge = muSurge;
|
package/dist/core/vault.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.persistent = void 0;
|
|
4
|
+
const hooks_1 = require("./hooks");
|
|
5
|
+
const reactive_1 = require("./reactive");
|
|
3
6
|
/**
|
|
4
7
|
* Mulan Vault: The World's First Native Persistent State Primitive.
|
|
5
8
|
*/
|
|
6
|
-
|
|
9
|
+
function persistent(key, initialValue, options = {}) {
|
|
7
10
|
const storage = options.storage || window.localStorage;
|
|
8
11
|
// 1. Load from Storage
|
|
9
12
|
const stored = storage.getItem(key);
|
|
@@ -18,9 +21,9 @@ export function persistent(key, initialValue, options = {}) {
|
|
|
18
21
|
}
|
|
19
22
|
// 2. Create Reactive State (Follow muState pattern for consistency)
|
|
20
23
|
const isObject = typeof startVal === 'object' && startVal !== null;
|
|
21
|
-
const state = isObject ? reactive(startVal) : reactive({ value: startVal });
|
|
24
|
+
const state = isObject ? (0, reactive_1.reactive)(startVal) : (0, reactive_1.reactive)({ value: startVal });
|
|
22
25
|
// 3. Auto-Save on Change
|
|
23
|
-
muEffect(() => {
|
|
26
|
+
(0, hooks_1.muEffect)(() => {
|
|
24
27
|
try {
|
|
25
28
|
const payload = isObject ? state : state.value;
|
|
26
29
|
const toSave = JSON.stringify(payload);
|
|
@@ -55,3 +58,4 @@ export function persistent(key, initialValue, options = {}) {
|
|
|
55
58
|
}
|
|
56
59
|
return state;
|
|
57
60
|
}
|
|
61
|
+
exports.persistent = persistent;
|
package/dist/index.js
CHANGED
|
@@ -1,30 +1,66 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
19
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
20
|
+
};
|
|
21
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
22
|
+
if (mod && mod.__esModule) return mod;
|
|
23
|
+
var result = {};
|
|
24
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
25
|
+
__setModuleDefault(result, mod);
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.MuStore = exports.Router = exports.MuRouter = exports.defineComponent = exports.Component = exports.MuComponent = void 0;
|
|
30
|
+
__exportStar(require("./core/reactive"), exports);
|
|
31
|
+
var component_1 = require("./core/component");
|
|
32
|
+
Object.defineProperty(exports, "MuComponent", { enumerable: true, get: function () { return component_1.MuComponent; } });
|
|
33
|
+
Object.defineProperty(exports, "Component", { enumerable: true, get: function () { return component_1.MuComponent; } });
|
|
34
|
+
Object.defineProperty(exports, "defineComponent", { enumerable: true, get: function () { return component_1.defineComponent; } });
|
|
35
|
+
__exportStar(require("./core/renderer"), exports);
|
|
36
|
+
var index_1 = require("./router/index");
|
|
37
|
+
Object.defineProperty(exports, "MuRouter", { enumerable: true, get: function () { return index_1.MuRouter; } });
|
|
38
|
+
Object.defineProperty(exports, "Router", { enumerable: true, get: function () { return index_1.MuRouter; } });
|
|
39
|
+
var index_2 = require("./store/index");
|
|
40
|
+
Object.defineProperty(exports, "MuStore", { enumerable: true, get: function () { return index_2.MuStore; } });
|
|
41
|
+
__exportStar(require("./security/sanitizer"), exports);
|
|
42
|
+
__exportStar(require("./core/hooks"), exports);
|
|
43
|
+
__exportStar(require("./core/query"), exports);
|
|
44
|
+
__exportStar(require("./core/vault"), exports);
|
|
45
|
+
__exportStar(require("./core/quantum"), exports);
|
|
46
|
+
__exportStar(require("./core/surge"), exports);
|
|
47
|
+
__exportStar(require("./components/bloch-sphere"), exports);
|
|
48
|
+
__exportStar(require("./components/infinity-list"), exports);
|
|
49
|
+
__exportStar(require("./core/ssr"), exports);
|
|
14
50
|
// Global Mulan Object for non-module usage
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const Mulan = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ reactive,
|
|
27
|
-
effect, Component: MuComponent, defineComponent, Router: MuRouter, createRouter, Store: MuStore, Security: Security }, Hooks), Query), Quantum), Surge), InfinityList), { render,
|
|
51
|
+
const reactive_1 = require("./core/reactive");
|
|
52
|
+
const component_2 = require("./core/component");
|
|
53
|
+
const index_3 = require("./router/index");
|
|
54
|
+
const index_4 = require("./store/index");
|
|
55
|
+
const sanitizer_1 = require("./security/sanitizer");
|
|
56
|
+
const Hooks = __importStar(require("./core/hooks"));
|
|
57
|
+
const Query = __importStar(require("./core/query"));
|
|
58
|
+
const renderer_1 = require("./core/renderer");
|
|
59
|
+
const Quantum = __importStar(require("./core/quantum"));
|
|
60
|
+
const Surge = __importStar(require("./core/surge"));
|
|
61
|
+
const InfinityList = __importStar(require("./components/infinity-list"));
|
|
62
|
+
const Mulan = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ reactive: reactive_1.reactive,
|
|
63
|
+
effect: reactive_1.effect, Component: component_2.MuComponent, defineComponent: component_2.defineComponent, Router: index_3.MuRouter, createRouter: index_3.createRouter, Store: index_4.MuStore, Security: sanitizer_1.Security }, Hooks), Query), Quantum), Surge), InfinityList), { render: renderer_1.render,
|
|
28
64
|
// MULAN INSIGHT: Branded Logging
|
|
29
65
|
log: (msg, ...args) => {
|
|
30
66
|
console.log(`%c[MulanJS]%c ${msg}`, "color: #ff3e00; font-weight: bold; background: #222; padding: 2px 4px; border-radius: 3px;", "", ...args);
|
|
@@ -56,4 +92,4 @@ if (typeof window !== 'undefined') {
|
|
|
56
92
|
if (typeof window !== 'undefined') {
|
|
57
93
|
window.Mulan = Mulan;
|
|
58
94
|
}
|
|
59
|
-
|
|
95
|
+
exports.default = Mulan;
|
package/dist/mulan.esm.js
CHANGED
|
@@ -106,6 +106,59 @@ __webpack_require__.d(infinity_list_namespaceObject, {
|
|
|
106
106
|
let activeEffect = null;
|
|
107
107
|
let activeEffectRunner = null;
|
|
108
108
|
const targetMap = new WeakMap();
|
|
109
|
+
// --- Mulan Quantum Scheduler (Time-Slicing) ---
|
|
110
|
+
// Assign unique IDs to effects for basic topological sorting (lower IDs run first)
|
|
111
|
+
let effectIdCounter = 0;
|
|
112
|
+
const pendingEffects = new Set();
|
|
113
|
+
let isScheduling = false;
|
|
114
|
+
const TIME_BUDGET = 8; // 8ms frame budget for 60FPS lock
|
|
115
|
+
function runScheduler() {
|
|
116
|
+
if (pendingEffects.size === 0) {
|
|
117
|
+
isScheduling = false;
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const start = typeof performance !== 'undefined' ? performance.now() : Date.now();
|
|
121
|
+
// Convert to array and sort to ensure parent effects run before children (Topological Push-Pull approximation)
|
|
122
|
+
const sortedEffects = Array.from(pendingEffects).sort((a, b) => {
|
|
123
|
+
return (a._id || 0) - (b._id || 0);
|
|
124
|
+
});
|
|
125
|
+
for (const fn of sortedEffects) {
|
|
126
|
+
pendingEffects.delete(fn);
|
|
127
|
+
fn();
|
|
128
|
+
const now = typeof performance !== 'undefined' ? performance.now() : Date.now();
|
|
129
|
+
if (now - start > TIME_BUDGET) {
|
|
130
|
+
break; // Yield to browser
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (pendingEffects.size > 0) {
|
|
134
|
+
if (typeof MessageChannel !== 'undefined') {
|
|
135
|
+
const channel = new MessageChannel();
|
|
136
|
+
channel.port1.onmessage = runScheduler;
|
|
137
|
+
channel.port2.postMessage(null);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
setTimeout(runScheduler, 0);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
isScheduling = false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function queueEffect(fn) {
|
|
148
|
+
pendingEffects.add(fn);
|
|
149
|
+
if (!isScheduling) {
|
|
150
|
+
isScheduling = true;
|
|
151
|
+
if (typeof Promise !== 'undefined') {
|
|
152
|
+
Promise.resolve().then(runScheduler);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
setTimeout(runScheduler, 0);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function nextTick() {
|
|
160
|
+
return Promise.resolve();
|
|
161
|
+
}
|
|
109
162
|
// --- Signal Core (The Engine) ---
|
|
110
163
|
class Signal {
|
|
111
164
|
constructor(initialValue) {
|
|
@@ -125,17 +178,25 @@ class Signal {
|
|
|
125
178
|
}
|
|
126
179
|
}
|
|
127
180
|
notify() {
|
|
128
|
-
this._subscribers.forEach(fn =>
|
|
181
|
+
this._subscribers.forEach(fn => {
|
|
182
|
+
if (fn._sync) {
|
|
183
|
+
fn();
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
queueEffect(fn);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
129
189
|
}
|
|
130
190
|
}
|
|
131
191
|
// --- Compatibility Layer (The Surface) ---
|
|
132
|
-
function effect(fn, targetNode) {
|
|
192
|
+
function effect(fn, targetNode, options = {}) {
|
|
133
193
|
let stopped = false;
|
|
194
|
+
const id = ++effectIdCounter;
|
|
134
195
|
const run = () => {
|
|
135
196
|
if (stopped)
|
|
136
197
|
return;
|
|
137
198
|
const prevRunner = activeEffectRunner;
|
|
138
|
-
activeEffectRunner = { run, node: targetNode };
|
|
199
|
+
activeEffectRunner = { run, node: targetNode, id };
|
|
139
200
|
try {
|
|
140
201
|
fn();
|
|
141
202
|
}
|
|
@@ -143,9 +204,13 @@ function effect(fn, targetNode) {
|
|
|
143
204
|
activeEffectRunner = prevRunner;
|
|
144
205
|
}
|
|
145
206
|
};
|
|
207
|
+
// Attach ID for topological sorting
|
|
208
|
+
run._id = id;
|
|
209
|
+
run._sync = options.sync;
|
|
146
210
|
run();
|
|
147
211
|
return () => {
|
|
148
212
|
stopped = true;
|
|
213
|
+
pendingEffects.delete(run);
|
|
149
214
|
};
|
|
150
215
|
}
|
|
151
216
|
function track(target, key) {
|
|
@@ -167,7 +232,14 @@ function trigger(target, key) {
|
|
|
167
232
|
return;
|
|
168
233
|
const dep = depsMap.get(key);
|
|
169
234
|
if (dep) {
|
|
170
|
-
dep.forEach((fn) =>
|
|
235
|
+
dep.forEach((fn) => {
|
|
236
|
+
if (fn._sync) {
|
|
237
|
+
fn(); // Run synchronously if explicitly requested (e.g. for muMemo)
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
queueEffect(fn); // Push to Quantum Scheduler
|
|
241
|
+
}
|
|
242
|
+
});
|
|
171
243
|
}
|
|
172
244
|
}
|
|
173
245
|
/**
|
|
@@ -311,11 +383,6 @@ function hydrate(template, container) {
|
|
|
311
383
|
}
|
|
312
384
|
// Future: Attach event listeners here if we had a mechanism for it.
|
|
313
385
|
}
|
|
314
|
-
function renderToString(template) {
|
|
315
|
-
// SSR Function: returns the HTML string for the server to send.
|
|
316
|
-
// Can include additional sanitization or metadata injection here.
|
|
317
|
-
return template;
|
|
318
|
-
}
|
|
319
386
|
function sanitize(str) {
|
|
320
387
|
// Check if we are in a browser environment
|
|
321
388
|
if (typeof document !== 'undefined') {
|
|
@@ -775,6 +842,8 @@ class MuComponent {
|
|
|
775
842
|
this._effects = [];
|
|
776
843
|
this._domEffects = [];
|
|
777
844
|
this._isDestroyed = false;
|
|
845
|
+
this._isResuming = false; // Quantum Resumability Flag
|
|
846
|
+
this._resumeRoot = null;
|
|
778
847
|
this._propsQueue = [];
|
|
779
848
|
this._eventQueue = [];
|
|
780
849
|
// --- MulanJS List Reconciliation Engine (No-VDOM) ---
|
|
@@ -786,6 +855,26 @@ class MuComponent {
|
|
|
786
855
|
this.container = container;
|
|
787
856
|
this.state = {};
|
|
788
857
|
this.$uid = 'mu_' + Math.random().toString(36).substr(2, 9);
|
|
858
|
+
// MULAN INSIGHT: Quantum Resumability Detection
|
|
859
|
+
if (typeof window !== 'undefined' && container) {
|
|
860
|
+
const rootAttr = container.getAttribute('data-mu-root');
|
|
861
|
+
const stateScript = container.querySelector('script[type="mulan/state"]');
|
|
862
|
+
if (rootAttr || stateScript) {
|
|
863
|
+
console.log(`%c[Mulan Quantum]%c Resuming component from server state...`, "color: #00ffcc; font-weight: bold;", "");
|
|
864
|
+
this._isResuming = true;
|
|
865
|
+
this.$uid = rootAttr || this.$uid;
|
|
866
|
+
if (stateScript) {
|
|
867
|
+
try {
|
|
868
|
+
const serverState = JSON.parse(stateScript.textContent || '{}');
|
|
869
|
+
// Inject server state into this instance
|
|
870
|
+
Object.assign(this, serverState);
|
|
871
|
+
}
|
|
872
|
+
catch (e) {
|
|
873
|
+
console.error("[Mulan Quantum] Failed to parse server state:", e);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
}
|
|
789
878
|
// MULAN INSIGHT: Global Registry for Debugging
|
|
790
879
|
if (typeof window !== 'undefined') {
|
|
791
880
|
const global = window;
|
|
@@ -846,14 +935,38 @@ class MuComponent {
|
|
|
846
935
|
}
|
|
847
936
|
mount() {
|
|
848
937
|
console.log(`[Mulan Cycle] Mounting component ${this.$uid}`);
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
console.log(`[Mulan
|
|
852
|
-
this.
|
|
853
|
-
}
|
|
854
|
-
|
|
938
|
+
if (this._isResuming) {
|
|
939
|
+
// Quantum Resumability: Skip initial render, just attach effects to existing DOM
|
|
940
|
+
console.log(`[Mulan Quantum] Skipping initial render, recovering DOM nodes...`);
|
|
941
|
+
this._resume();
|
|
942
|
+
}
|
|
943
|
+
else {
|
|
944
|
+
// Standard Hydration/Mount
|
|
945
|
+
const stop = effect(() => {
|
|
946
|
+
console.log(`[Mulan Reactivity] Triggering macro-update for ${this.$uid}`);
|
|
947
|
+
this.update();
|
|
948
|
+
});
|
|
949
|
+
this._effects.push(stop);
|
|
950
|
+
}
|
|
855
951
|
this.onMount();
|
|
856
952
|
}
|
|
953
|
+
/**
|
|
954
|
+
* Internal method to execute the resumability pass.
|
|
955
|
+
* Overridden by compiler-generated code.
|
|
956
|
+
*/
|
|
957
|
+
_resume() {
|
|
958
|
+
// Clear queues
|
|
959
|
+
this._propsQueue = [];
|
|
960
|
+
this._eventQueue = [];
|
|
961
|
+
// Call the template with resumption context
|
|
962
|
+
// In a real implementation, the compiler will inject 'recovery' instructions
|
|
963
|
+
this._recoveryMode = true;
|
|
964
|
+
this.template();
|
|
965
|
+
this._recoveryMode = false;
|
|
966
|
+
// Flush bindings (events/props) to existing nodes
|
|
967
|
+
this.flushProps();
|
|
968
|
+
this.flushEvents();
|
|
969
|
+
}
|
|
857
970
|
// New helper for the compiler to register a fine-grained DOM property effect
|
|
858
971
|
_bindEffect(fn, targetNode) {
|
|
859
972
|
const stop = effect(fn, targetNode);
|
|
@@ -1349,8 +1462,10 @@ const createRouter = (options) => {
|
|
|
1349
1462
|
};
|
|
1350
1463
|
// --- Web Component: <mu-link> ---
|
|
1351
1464
|
// Usage: <mu-link to="/about">About Us</mu-link>
|
|
1465
|
+
const MuLinkBase = typeof HTMLElement !== 'undefined' ? HTMLElement : class {
|
|
1466
|
+
};
|
|
1352
1467
|
if (typeof window !== 'undefined' && !customElements.get('mu-link')) {
|
|
1353
|
-
class MuLink extends
|
|
1468
|
+
class MuLink extends MuLinkBase {
|
|
1354
1469
|
constructor() {
|
|
1355
1470
|
super();
|
|
1356
1471
|
this.addEventListener('click', (e) => {
|
|
@@ -1953,7 +2068,9 @@ function muSurge(array, taskFn, onProgress) {
|
|
|
1953
2068
|
|
|
1954
2069
|
;// ./src/components/bloch-sphere.ts
|
|
1955
2070
|
|
|
1956
|
-
|
|
2071
|
+
const MuBlochBase = typeof HTMLElement !== 'undefined' ? HTMLElement : class {
|
|
2072
|
+
};
|
|
2073
|
+
class MuBlochSphereElement extends MuBlochBase {
|
|
1957
2074
|
static get observedAttributes() {
|
|
1958
2075
|
return ['size'];
|
|
1959
2076
|
}
|
|
@@ -2206,7 +2323,9 @@ if (typeof customElements !== 'undefined') {
|
|
|
2206
2323
|
}
|
|
2207
2324
|
|
|
2208
2325
|
;// ./src/components/infinity-list.ts
|
|
2209
|
-
|
|
2326
|
+
const MuInfinityBase = typeof HTMLElement !== 'undefined' ? HTMLElement : class {
|
|
2327
|
+
};
|
|
2328
|
+
class MuInfinity extends MuInfinityBase {
|
|
2210
2329
|
constructor() {
|
|
2211
2330
|
super();
|
|
2212
2331
|
this._items = [];
|
|
@@ -2317,6 +2436,54 @@ if (typeof customElements !== 'undefined' && !customElements.get('mu-infinity'))
|
|
|
2317
2436
|
customElements.define('mu-infinity', MuInfinity);
|
|
2318
2437
|
}
|
|
2319
2438
|
|
|
2439
|
+
;// ./src/core/ssr.ts
|
|
2440
|
+
/**
|
|
2441
|
+
* Renders a Mulan component to a static HTML string with a resumability envelope.
|
|
2442
|
+
*/
|
|
2443
|
+
function renderToString(ComponentClass, props = {}) {
|
|
2444
|
+
// 1. Initialize component in a virtual container (not used for DOM)
|
|
2445
|
+
// On server, we mock the container or just pass a dummy object
|
|
2446
|
+
const dummyContainer = {
|
|
2447
|
+
querySelector: () => null,
|
|
2448
|
+
querySelectorAll: () => [],
|
|
2449
|
+
appendChild: () => { },
|
|
2450
|
+
removeChild: () => { },
|
|
2451
|
+
getAttribute: () => null
|
|
2452
|
+
};
|
|
2453
|
+
const instance = new ComponentClass(dummyContainer);
|
|
2454
|
+
// Pass props
|
|
2455
|
+
Object.assign(instance, props);
|
|
2456
|
+
// 2. Render to HTML
|
|
2457
|
+
if (typeof instance.renderToString !== 'function') {
|
|
2458
|
+
throw new Error(`Component ${ComponentClass.name} was not compiled for SSR.`);
|
|
2459
|
+
}
|
|
2460
|
+
const html = instance.renderToString();
|
|
2461
|
+
// 3. Extract State for Resumability
|
|
2462
|
+
// We only want to serialize data that was exposed in setup()
|
|
2463
|
+
// For now, we'll serialize any property on the instance that isn't internal
|
|
2464
|
+
const state = {};
|
|
2465
|
+
for (const key in instance) {
|
|
2466
|
+
if (key.startsWith('_') || key === 'container' || key === 'state' || typeof instance[key] === 'function')
|
|
2467
|
+
continue;
|
|
2468
|
+
const value = instance[key];
|
|
2469
|
+
// Handle signals specifically
|
|
2470
|
+
if (value && typeof value === 'object' && 'value' in value) {
|
|
2471
|
+
state[key] = value.value;
|
|
2472
|
+
}
|
|
2473
|
+
else {
|
|
2474
|
+
state[key] = value;
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
// 4. Construct Resumability Envelope
|
|
2478
|
+
const stateScript = `<script type="mulan/state" data-mu-uid="${instance.$uid}">${JSON.stringify(state)}</script>`;
|
|
2479
|
+
const envelope = `<div data-mu-root="${instance.$uid}">${html}${stateScript}</div>`;
|
|
2480
|
+
return {
|
|
2481
|
+
html,
|
|
2482
|
+
state,
|
|
2483
|
+
envelope
|
|
2484
|
+
};
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2320
2487
|
;// ./src/index.ts
|
|
2321
2488
|
|
|
2322
2489
|
|
|
@@ -2331,6 +2498,7 @@ if (typeof customElements !== 'undefined' && !customElements.get('mu-infinity'))
|
|
|
2331
2498
|
|
|
2332
2499
|
|
|
2333
2500
|
|
|
2501
|
+
|
|
2334
2502
|
// Global Mulan Object for non-module usage
|
|
2335
2503
|
|
|
2336
2504
|
|
|
@@ -2378,6 +2546,6 @@ if (typeof window !== 'undefined') {
|
|
|
2378
2546
|
}
|
|
2379
2547
|
/* harmony default export */ const src = (Mulan);
|
|
2380
2548
|
|
|
2381
|
-
export { MuComponent as Component, MuBlochSphereElement, MuComponent, MuInfinity, MuRouter, MuStore, MuRouter as Router, Security, Signal, activeControls, src as default, defineComponent, effect, getCurrentInstance, hydrate, muBurst, muControl, muDebounced, muEffect, muEntangle, muGate, muGeom, muHistory, muMeasure, muMemo, muParallel, muPulse, muQubit, muRegister, muSearch, muState, muSurge, muSuspense, muSwitch, muTeleport, muThrottled, muVault, onMuDestroy, onMuIdle, onMuInit, onMuMount, onMuPanic, onMuResume, onMuShake, onMuVisibility, onMuVoice, persistent, reactive, ref, render, renderToString, sanitize, setCurrentInstance, useMutation, useQuery };
|
|
2549
|
+
export { MuComponent as Component, MuBlochSphereElement, MuComponent, MuInfinity, MuRouter, MuStore, MuRouter as Router, Security, Signal, activeControls, src as default, defineComponent, effect, getCurrentInstance, hydrate, muBurst, muControl, muDebounced, muEffect, muEntangle, muGate, muGeom, muHistory, muMeasure, muMemo, muParallel, muPulse, muQubit, muRegister, muSearch, muState, muSurge, muSuspense, muSwitch, muTeleport, muThrottled, muVault, nextTick, onMuDestroy, onMuIdle, onMuInit, onMuMount, onMuPanic, onMuResume, onMuShake, onMuVisibility, onMuVoice, persistent, queueEffect, reactive, ref, render, renderToString, sanitize, setCurrentInstance, useMutation, useQuery };
|
|
2382
2550
|
|
|
2383
2551
|
//# sourceMappingURL=mulan.esm.js.map
|