@mulanjs/mulanjs 1.0.1-dev.20260227172006 → 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/mulan.esm.js +1624 -1763
- package/dist/mulan.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/mulan.esm.js
CHANGED
|
@@ -1,504 +1,484 @@
|
|
|
1
|
-
/******/
|
|
1
|
+
/******/ // The require scope
|
|
2
|
+
/******/ var __webpack_require__ = {};
|
|
3
|
+
/******/
|
|
4
|
+
/************************************************************************/
|
|
5
|
+
/******/ /* webpack/runtime/define property getters */
|
|
6
|
+
/******/ (() => {
|
|
7
|
+
/******/ // define getter functions for harmony exports
|
|
8
|
+
/******/ __webpack_require__.d = (exports, definition) => {
|
|
9
|
+
/******/ for(var key in definition) {
|
|
10
|
+
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
11
|
+
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
12
|
+
/******/ }
|
|
13
|
+
/******/ }
|
|
14
|
+
/******/ };
|
|
15
|
+
/******/ })();
|
|
16
|
+
/******/
|
|
17
|
+
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
|
18
|
+
/******/ (() => {
|
|
19
|
+
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
|
20
|
+
/******/ })();
|
|
21
|
+
/******/
|
|
22
|
+
/******/ /* webpack/runtime/make namespace object */
|
|
23
|
+
/******/ (() => {
|
|
24
|
+
/******/ // define __esModule on exports
|
|
25
|
+
/******/ __webpack_require__.r = (exports) => {
|
|
26
|
+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
27
|
+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
28
|
+
/******/ }
|
|
29
|
+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
30
|
+
/******/ };
|
|
31
|
+
/******/ })();
|
|
32
|
+
/******/
|
|
33
|
+
/************************************************************************/
|
|
34
|
+
var __webpack_exports__ = {};
|
|
35
|
+
|
|
36
|
+
// NAMESPACE OBJECT: ./src/core/hooks.ts
|
|
37
|
+
var hooks_namespaceObject = {};
|
|
38
|
+
__webpack_require__.r(hooks_namespaceObject);
|
|
39
|
+
__webpack_require__.d(hooks_namespaceObject, {
|
|
40
|
+
getCurrentInstance: () => (getCurrentInstance),
|
|
41
|
+
muDebounced: () => (muDebounced),
|
|
42
|
+
muEffect: () => (muEffect),
|
|
43
|
+
muGeom: () => (muGeom),
|
|
44
|
+
muHistory: () => (muHistory),
|
|
45
|
+
muMemo: () => (muMemo),
|
|
46
|
+
muPulse: () => (muPulse),
|
|
47
|
+
muState: () => (muState),
|
|
48
|
+
muSuspense: () => (muSuspense),
|
|
49
|
+
muThrottled: () => (muThrottled),
|
|
50
|
+
muVault: () => (muVault),
|
|
51
|
+
onMuDestroy: () => (onMuDestroy),
|
|
52
|
+
onMuIdle: () => (onMuIdle),
|
|
53
|
+
onMuInit: () => (onMuInit),
|
|
54
|
+
onMuMount: () => (onMuMount),
|
|
55
|
+
onMuPanic: () => (onMuPanic),
|
|
56
|
+
onMuResume: () => (onMuResume),
|
|
57
|
+
onMuShake: () => (onMuShake),
|
|
58
|
+
onMuVisibility: () => (onMuVisibility),
|
|
59
|
+
onMuVoice: () => (onMuVoice),
|
|
60
|
+
setCurrentInstance: () => (setCurrentInstance)
|
|
61
|
+
});
|
|
2
62
|
|
|
3
|
-
|
|
4
|
-
|
|
63
|
+
// NAMESPACE OBJECT: ./src/core/query.ts
|
|
64
|
+
var query_namespaceObject = {};
|
|
65
|
+
__webpack_require__.r(query_namespaceObject);
|
|
66
|
+
__webpack_require__.d(query_namespaceObject, {
|
|
67
|
+
useMutation: () => (useMutation),
|
|
68
|
+
useQuery: () => (useQuery)
|
|
69
|
+
});
|
|
5
70
|
|
|
71
|
+
// NAMESPACE OBJECT: ./src/core/quantum.ts
|
|
72
|
+
var quantum_namespaceObject = {};
|
|
73
|
+
__webpack_require__.r(quantum_namespaceObject);
|
|
74
|
+
__webpack_require__.d(quantum_namespaceObject, {
|
|
75
|
+
activeControls: () => (activeControls),
|
|
76
|
+
muControl: () => (muControl),
|
|
77
|
+
muEntangle: () => (muEntangle),
|
|
78
|
+
muGate: () => (muGate),
|
|
79
|
+
muMeasure: () => (muMeasure),
|
|
80
|
+
muParallel: () => (muParallel),
|
|
81
|
+
muQubit: () => (muQubit),
|
|
82
|
+
muRegister: () => (muRegister),
|
|
83
|
+
muSearch: () => (muSearch),
|
|
84
|
+
muSwitch: () => (muSwitch),
|
|
85
|
+
muTeleport: () => (muTeleport)
|
|
86
|
+
});
|
|
6
87
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
console.log(`%c[Mulan Quantum]%c Resuming component from server state...`, "color: #00ffcc; font-weight: bold;", "");
|
|
39
|
-
this._isResuming = true;
|
|
40
|
-
this.$uid = rootAttr || this.$uid;
|
|
41
|
-
if (stateScript) {
|
|
42
|
-
try {
|
|
43
|
-
const serverState = JSON.parse(stateScript.textContent || '{}');
|
|
44
|
-
// Inject server state into this instance
|
|
45
|
-
Object.assign(this, serverState);
|
|
46
|
-
}
|
|
47
|
-
catch (e) {
|
|
48
|
-
console.error("[Mulan Quantum] Failed to parse server state:", e);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
// MULAN INSIGHT: Global Registry for Debugging
|
|
54
|
-
if (typeof window !== 'undefined') {
|
|
55
|
-
const global = window;
|
|
56
|
-
global.__MULAN_INSIGHT__ = global.__MULAN_INSIGHT__ || { components: new Map() };
|
|
57
|
-
global.__MULAN_INSIGHT__.components.set(this.$uid, this);
|
|
58
|
-
}
|
|
59
|
-
// Setup context for hooks
|
|
60
|
-
(0, hooks_1.setCurrentInstance)(this);
|
|
61
|
-
this.setup();
|
|
62
|
-
(0, hooks_1.setCurrentInstance)(null);
|
|
63
|
-
}
|
|
64
|
-
// Optional setup method for class components wanting to use hooks
|
|
65
|
-
setup() { }
|
|
66
|
-
onMount() {
|
|
67
|
-
var _a, _c;
|
|
68
|
-
// Mulan Cycle: Init
|
|
69
|
-
(_a = this._hooks.onMuInit) === null || _a === void 0 ? void 0 : _a.forEach(fn => fn());
|
|
70
|
-
// Mulan Cycle: Mount (Simulated immediately after init for now in this version)
|
|
71
|
-
(_c = this._hooks.onMuMount) === null || _c === void 0 ? void 0 : _c.forEach(fn => fn());
|
|
88
|
+
// NAMESPACE OBJECT: ./src/core/surge.ts
|
|
89
|
+
var surge_namespaceObject = {};
|
|
90
|
+
__webpack_require__.r(surge_namespaceObject);
|
|
91
|
+
__webpack_require__.d(surge_namespaceObject, {
|
|
92
|
+
muBurst: () => (muBurst),
|
|
93
|
+
muSurge: () => (muSurge)
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// NAMESPACE OBJECT: ./src/components/infinity-list.ts
|
|
97
|
+
var infinity_list_namespaceObject = {};
|
|
98
|
+
__webpack_require__.r(infinity_list_namespaceObject);
|
|
99
|
+
__webpack_require__.d(infinity_list_namespaceObject, {
|
|
100
|
+
MuInfinity: () => (MuInfinity)
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
;// ./src/core/reactive.ts
|
|
104
|
+
// MulanJS 2.0: Signal-Powered Reactivity Engine
|
|
105
|
+
// "Compatible Surface, World-Class Engine"
|
|
106
|
+
let activeEffect = null;
|
|
107
|
+
let activeEffectRunner = null;
|
|
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;
|
|
72
119
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
|
84
131
|
}
|
|
85
|
-
// Mulan Cycle: Stop all effects to prevent leaks
|
|
86
|
-
console.log(`[Mulan Cycle] Stopping ${this._effects.length} effects for ${this.$uid}`);
|
|
87
|
-
this._effects.forEach(stop => stop());
|
|
88
|
-
this._effects = [];
|
|
89
|
-
console.log(`[Mulan Cycle] Stopping ${this._domEffects.length} DOM effects for ${this.$uid}`);
|
|
90
|
-
this._domEffects.forEach(stop => stop());
|
|
91
|
-
this._domEffects = [];
|
|
92
|
-
// Mulan Cycle: Destroy hooks
|
|
93
|
-
(_c = this._hooks.onMuDestroy) === null || _c === void 0 ? void 0 : _c.forEach(fn => fn());
|
|
94
|
-
}
|
|
95
|
-
// Helper for compiler to register property bindings
|
|
96
|
-
_b(id, prop, value) {
|
|
97
|
-
this._propsQueue.push([id, prop, value]);
|
|
98
|
-
return "";
|
|
99
132
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
+
}
|
|
104
142
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const id = 'ev_' + Math.random().toString(36).substr(2, 9);
|
|
108
|
-
this._e(id, type, handler);
|
|
109
|
-
return `data-mu-id="${id}"`;
|
|
143
|
+
else {
|
|
144
|
+
isScheduling = false;
|
|
110
145
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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);
|
|
117
153
|
}
|
|
118
154
|
else {
|
|
119
|
-
|
|
120
|
-
const stop = (0, reactive_1.effect)(() => {
|
|
121
|
-
console.log(`[Mulan Reactivity] Triggering macro-update for ${this.$uid}`);
|
|
122
|
-
this.update();
|
|
123
|
-
});
|
|
124
|
-
this._effects.push(stop);
|
|
155
|
+
setTimeout(runScheduler, 0);
|
|
125
156
|
}
|
|
126
|
-
this.onMount();
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Internal method to execute the resumability pass.
|
|
130
|
-
* Overridden by compiler-generated code.
|
|
131
|
-
*/
|
|
132
|
-
_resume() {
|
|
133
|
-
// Clear queues
|
|
134
|
-
this._propsQueue = [];
|
|
135
|
-
this._eventQueue = [];
|
|
136
|
-
// Call the template with resumption context
|
|
137
|
-
// In a real implementation, the compiler will inject 'recovery' instructions
|
|
138
|
-
this._recoveryMode = true;
|
|
139
|
-
this.template();
|
|
140
|
-
this._recoveryMode = false;
|
|
141
|
-
// Flush bindings (events/props) to existing nodes
|
|
142
|
-
this.flushProps();
|
|
143
|
-
this.flushEvents();
|
|
144
157
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
158
|
+
}
|
|
159
|
+
function nextTick() {
|
|
160
|
+
return Promise.resolve();
|
|
161
|
+
}
|
|
162
|
+
// --- Signal Core (The Engine) ---
|
|
163
|
+
class Signal {
|
|
164
|
+
constructor(initialValue) {
|
|
165
|
+
this._subscribers = new Set();
|
|
166
|
+
this._value = initialValue;
|
|
150
167
|
}
|
|
151
|
-
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
return;
|
|
168
|
+
get value() {
|
|
169
|
+
if (activeEffectRunner) {
|
|
170
|
+
this._subscribers.add(activeEffectRunner.run);
|
|
155
171
|
}
|
|
156
|
-
|
|
157
|
-
this._propsQueue = [];
|
|
158
|
-
this._eventQueue = [];
|
|
159
|
-
const template = this.template();
|
|
160
|
-
// Render HTML
|
|
161
|
-
(0, renderer_1.render)(template, this.container);
|
|
162
|
-
// Flush Side Effects
|
|
163
|
-
this.flushProps();
|
|
164
|
-
this.flushEvents();
|
|
165
|
-
this.onUpdate();
|
|
172
|
+
return this._value;
|
|
166
173
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
// @ts-ignore
|
|
172
|
-
el[prop] = value;
|
|
173
|
-
}
|
|
174
|
+
set value(newValue) {
|
|
175
|
+
if (newValue !== this._value) {
|
|
176
|
+
this._value = newValue;
|
|
177
|
+
this.notify();
|
|
174
178
|
}
|
|
175
|
-
this._propsQueue = [];
|
|
176
179
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
// Bind handler to this component instance to ensure 'this' works in methods
|
|
182
|
-
el.addEventListener(type, handler.bind(this));
|
|
180
|
+
notify() {
|
|
181
|
+
this._subscribers.forEach(fn => {
|
|
182
|
+
if (fn._sync) {
|
|
183
|
+
fn();
|
|
183
184
|
}
|
|
184
|
-
|
|
185
|
-
|
|
185
|
+
else {
|
|
186
|
+
queueEffect(fn);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
186
189
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const cache = this._listCaches.get(listId);
|
|
200
|
-
const newKeys = new Set();
|
|
201
|
-
const parent = anchorToken.parentNode;
|
|
202
|
-
if (!parent)
|
|
203
|
-
return;
|
|
204
|
-
// 1. Array Iteration: Match against cache or Create
|
|
205
|
-
// Use a DocumentFragment to batch new node insertions natively
|
|
206
|
-
const collectorFrag = document.createDocumentFragment();
|
|
207
|
-
const newOrderNodes = [];
|
|
208
|
-
const newOrderKeys = [];
|
|
209
|
-
let requiresSwap = false;
|
|
210
|
-
let lastCachedIndex = -1;
|
|
211
|
-
for (let i = 0; i < array.length; i++) {
|
|
212
|
-
const item = array[i];
|
|
213
|
-
const key = keyProp ? item[keyProp] : i; // fallback to index if no key
|
|
214
|
-
newKeys.add(key);
|
|
215
|
-
newOrderKeys.push(key);
|
|
216
|
-
let cached = cache.get(key);
|
|
217
|
-
if (!cached) {
|
|
218
|
-
// Not in cache, Render a brand new row structure
|
|
219
|
-
const { fragment, effects } = renderRow(item, i);
|
|
220
|
-
// Track actual DOM nodes
|
|
221
|
-
const createdNodes = Array.from(fragment.childNodes);
|
|
222
|
-
cached = { nodes: createdNodes, effects, index: i }; // Store index for fast swap detection
|
|
223
|
-
cache.set(key, cached);
|
|
224
|
-
// Batch append to our in-memory fragment!
|
|
225
|
-
// This eliminates thousands of live DOM reflows on creation.
|
|
226
|
-
collectorFrag.appendChild(fragment);
|
|
227
|
-
newOrderNodes.push(...createdNodes);
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
// Exists in cache
|
|
231
|
-
// Batch append to the in-memory array for index tracking
|
|
232
|
-
newOrderNodes.push(...cached.nodes);
|
|
233
|
-
// Fast-Path Swap Detection: If the cached index is physically out of numerical sequence,
|
|
234
|
-
// we know the array order was unsynchronized and needs reconciliation.
|
|
235
|
-
if (cached.index < lastCachedIndex) {
|
|
236
|
-
requiresSwap = true;
|
|
237
|
-
}
|
|
238
|
-
cached.index = i;
|
|
239
|
-
lastCachedIndex = i;
|
|
240
|
-
}
|
|
190
|
+
}
|
|
191
|
+
// --- Compatibility Layer (The Surface) ---
|
|
192
|
+
function effect(fn, targetNode, options = {}) {
|
|
193
|
+
let stopped = false;
|
|
194
|
+
const id = ++effectIdCounter;
|
|
195
|
+
const run = () => {
|
|
196
|
+
if (stopped)
|
|
197
|
+
return;
|
|
198
|
+
const prevRunner = activeEffectRunner;
|
|
199
|
+
activeEffectRunner = { run, node: targetNode, id };
|
|
200
|
+
try {
|
|
201
|
+
fn();
|
|
241
202
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
parent.insertBefore(collectorFrag, anchorToken.nextSibling);
|
|
203
|
+
finally {
|
|
204
|
+
activeEffectRunner = prevRunner;
|
|
245
205
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
206
|
+
};
|
|
207
|
+
// Attach ID for topological sorting
|
|
208
|
+
run._id = id;
|
|
209
|
+
run._sync = options.sync;
|
|
210
|
+
run();
|
|
211
|
+
return () => {
|
|
212
|
+
stopped = true;
|
|
213
|
+
pendingEffects.delete(run);
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function track(target, key) {
|
|
217
|
+
if (activeEffectRunner) {
|
|
218
|
+
let depsMap = targetMap.get(target);
|
|
219
|
+
if (!depsMap) {
|
|
220
|
+
targetMap.set(target, (depsMap = new Map()));
|
|
261
221
|
}
|
|
262
|
-
|
|
263
|
-
if (
|
|
264
|
-
|
|
265
|
-
if (!newKeys.has(key)) {
|
|
266
|
-
// Remove from DOM
|
|
267
|
-
cached.nodes.forEach((node) => {
|
|
268
|
-
if (node.parentNode === parent) {
|
|
269
|
-
parent.removeChild(node);
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
// Stop any targeted effects tied to these nodes
|
|
273
|
-
cached.effects.forEach((stop) => stop());
|
|
274
|
-
// Delete from cache tracking
|
|
275
|
-
cache.delete(key);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
222
|
+
let dep = depsMap.get(key);
|
|
223
|
+
if (!dep) {
|
|
224
|
+
depsMap.set(key, (dep = new Set()));
|
|
278
225
|
}
|
|
226
|
+
dep.add(activeEffectRunner.run);
|
|
279
227
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
if (!cached.isMounted) {
|
|
291
|
-
// We need to render and mount it
|
|
292
|
-
let nodesToMount;
|
|
293
|
-
if (cached.nodes.length === 0) {
|
|
294
|
-
// First time render
|
|
295
|
-
const { fragment, effects } = renderBlock();
|
|
296
|
-
nodesToMount = Array.from(fragment.childNodes);
|
|
297
|
-
cached.nodes = nodesToMount;
|
|
298
|
-
cached.effects = effects;
|
|
299
|
-
}
|
|
300
|
-
else {
|
|
301
|
-
// Re-mounting previously cached nodes
|
|
302
|
-
nodesToMount = cached.nodes;
|
|
303
|
-
}
|
|
304
|
-
cached.isMounted = true;
|
|
305
|
-
const parent = anchorToken.parentNode;
|
|
306
|
-
if (!parent)
|
|
307
|
-
return;
|
|
308
|
-
const targetSibling = anchorToken.nextSibling;
|
|
309
|
-
nodesToMount.forEach(node => {
|
|
310
|
-
parent.insertBefore(node, targetSibling);
|
|
311
|
-
});
|
|
228
|
+
}
|
|
229
|
+
function trigger(target, key) {
|
|
230
|
+
const depsMap = targetMap.get(target);
|
|
231
|
+
if (!depsMap)
|
|
232
|
+
return;
|
|
233
|
+
const dep = depsMap.get(key);
|
|
234
|
+
if (dep) {
|
|
235
|
+
dep.forEach((fn) => {
|
|
236
|
+
if (fn._sync) {
|
|
237
|
+
fn(); // Run synchronously if explicitly requested (e.g. for muMemo)
|
|
312
238
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
// Should NOT be mounted
|
|
316
|
-
if (cached.isMounted) {
|
|
317
|
-
// Unmount nodes but keep them in cache
|
|
318
|
-
cached.nodes.forEach(node => {
|
|
319
|
-
if (node.parentNode) {
|
|
320
|
-
node.parentNode.removeChild(node);
|
|
321
|
-
}
|
|
322
|
-
});
|
|
323
|
-
cached.isMounted = false;
|
|
324
|
-
// Note: We deliberately do NOT destroy the effects here, they stay active in memory!
|
|
239
|
+
else {
|
|
240
|
+
queueEffect(fn); // Push to Quantum Scheduler
|
|
325
241
|
}
|
|
326
|
-
}
|
|
242
|
+
});
|
|
327
243
|
}
|
|
328
244
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
function
|
|
334
|
-
return
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
setup() {
|
|
340
|
-
let setupResult;
|
|
341
|
-
if (typeof optionsOrSetup === 'function') {
|
|
342
|
-
// It's a setup function returning render fn
|
|
343
|
-
setupResult = optionsOrSetup.call(this);
|
|
344
|
-
}
|
|
345
|
-
else if (typeof optionsOrSetup === 'object' && optionsOrSetup.setup) {
|
|
346
|
-
// It's an options object with setup()
|
|
347
|
-
setupResult = optionsOrSetup.setup.call(this);
|
|
245
|
+
/**
|
|
246
|
+
* Creates a reactive proxy object (Vue-compatible).
|
|
247
|
+
* Now optimized to respect Mulan Cycle.
|
|
248
|
+
*/
|
|
249
|
+
function reactive(target) {
|
|
250
|
+
return new Proxy(target, {
|
|
251
|
+
get(obj, prop, receiver) {
|
|
252
|
+
// IRON FORTRESS: Prototype Pollution Protection (Read)
|
|
253
|
+
if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') {
|
|
254
|
+
return undefined;
|
|
348
255
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
256
|
+
track(obj, prop);
|
|
257
|
+
const val = Reflect.get(obj, prop, receiver);
|
|
258
|
+
if (val !== null && typeof val === 'object') {
|
|
259
|
+
return reactive(val);
|
|
353
260
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
261
|
+
return val;
|
|
262
|
+
},
|
|
263
|
+
set(obj, prop, value, receiver) {
|
|
264
|
+
// IRON FORTRESS: Prototype Pollution Protection
|
|
265
|
+
if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') {
|
|
266
|
+
console.warn(`[Iron Fortress] Blocked attempt to modify dangerous property: ${String(prop)}`);
|
|
267
|
+
return false;
|
|
358
268
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
return
|
|
362
|
-
}
|
|
363
|
-
};
|
|
269
|
+
const result = Reflect.set(obj, prop, value, receiver);
|
|
270
|
+
trigger(obj, prop);
|
|
271
|
+
return result;
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Creates a standalone reactive reference.
|
|
277
|
+
* Backed by the Mulan Signal Engine.
|
|
278
|
+
*/
|
|
279
|
+
function ref(value) {
|
|
280
|
+
return new Signal(value);
|
|
364
281
|
}
|
|
365
|
-
exports.defineComponent = defineComponent;
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
/***/ },
|
|
369
|
-
|
|
370
|
-
/***/ 156
|
|
371
|
-
(__unused_webpack_module, exports, __webpack_require__) {
|
|
372
|
-
|
|
373
282
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
const reactive_1 = __webpack_require__(359);
|
|
424
|
-
const component_2 = __webpack_require__(37);
|
|
425
|
-
const index_3 = __webpack_require__(580);
|
|
426
|
-
const index_4 = __webpack_require__(482);
|
|
427
|
-
const sanitizer_1 = __webpack_require__(500);
|
|
428
|
-
const Hooks = __importStar(__webpack_require__(166));
|
|
429
|
-
const Query = __importStar(__webpack_require__(598));
|
|
430
|
-
const renderer_1 = __webpack_require__(619);
|
|
431
|
-
const Quantum = __importStar(__webpack_require__(679));
|
|
432
|
-
const Surge = __importStar(__webpack_require__(172));
|
|
433
|
-
const InfinityList = __importStar(__webpack_require__(382));
|
|
434
|
-
const Mulan = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ reactive: reactive_1.reactive,
|
|
435
|
-
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,
|
|
436
|
-
// MULAN INSIGHT: Branded Logging
|
|
437
|
-
log: (msg, ...args) => {
|
|
438
|
-
console.log(`%c[MulanJS]%c ${msg}`, "color: #ff3e00; font-weight: bold; background: #222; padding: 2px 4px; border-radius: 3px;", "", ...args);
|
|
439
|
-
}, warn: (msg, ...args) => {
|
|
440
|
-
console.warn(`%c[MulanJS]%c ${msg}`, "color: #ffcc00; font-weight: bold; background: #222; padding: 2px 4px; border-radius: 3px;", "", ...args);
|
|
441
|
-
}, error: (msg, ...args) => {
|
|
442
|
-
console.error(`%c[MulanJS]%c ${msg}`, "color: #ff0000; font-weight: bold; background: #222; padding: 2px 4px; border-radius: 3px;", "", ...args);
|
|
443
|
-
} });
|
|
444
|
-
// Security: Freeze the object to prevent runtime tampering
|
|
445
|
-
Object.freeze(Mulan);
|
|
446
|
-
Object.freeze(Mulan.Security);
|
|
447
|
-
// MULAN INSIGHT: Initialize Global Registry
|
|
448
|
-
if (typeof window !== 'undefined') {
|
|
449
|
-
window.__MULAN_INSIGHT__ = window.__MULAN_INSIGHT__ || { components: new Map() };
|
|
450
|
-
// MULAN INSIGHT: HMR Support
|
|
451
|
-
window.__MULAN_REFRESH__ = () => {
|
|
452
|
-
var _a;
|
|
453
|
-
const components = (_a = window.__MULAN_INSIGHT__) === null || _a === void 0 ? void 0 : _a.components;
|
|
454
|
-
if (components) {
|
|
455
|
-
components.forEach((comp) => {
|
|
456
|
-
if (comp && typeof comp.update === 'function') {
|
|
457
|
-
// Force refresh
|
|
458
|
-
comp.update();
|
|
283
|
+
;// ./src/core/renderer.ts
|
|
284
|
+
function render(template, container) {
|
|
285
|
+
// Focus Preservation (The "Mulan Glance" Technique)
|
|
286
|
+
let focusedId = null;
|
|
287
|
+
let selectionStart = null;
|
|
288
|
+
let selectionEnd = null;
|
|
289
|
+
let preservedValue = null;
|
|
290
|
+
if (document.activeElement && container.contains(document.activeElement)) {
|
|
291
|
+
const el = document.activeElement;
|
|
292
|
+
if (el.hasAttribute('data-mu-id')) {
|
|
293
|
+
focusedId = el.getAttribute('data-mu-id');
|
|
294
|
+
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
|
|
295
|
+
selectionStart = el.selectionStart;
|
|
296
|
+
selectionEnd = el.selectionEnd;
|
|
297
|
+
preservedValue = el.value;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// [Anima] 1. Pre-Update: Snapshot positions of animated elements
|
|
302
|
+
const animationSnapshots = new Map();
|
|
303
|
+
// Only query if we might have animations to save perf
|
|
304
|
+
if (typeof template === 'string' && template.includes('mu-animate')) {
|
|
305
|
+
const animatedEls = container.querySelectorAll('[mu-animate]');
|
|
306
|
+
animatedEls.forEach(el => {
|
|
307
|
+
const key = el.getAttribute('mu-key') || el.id;
|
|
308
|
+
if (key) {
|
|
309
|
+
animationSnapshots.set(key, el.getBoundingClientRect());
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
if (typeof template === 'string') {
|
|
314
|
+
container.innerHTML = template;
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
container.innerHTML = '';
|
|
318
|
+
container.appendChild(template);
|
|
319
|
+
}
|
|
320
|
+
// Restore Focus and Value
|
|
321
|
+
if (focusedId) {
|
|
322
|
+
const el = container.querySelector(`[data-mu-id="${focusedId}"]`);
|
|
323
|
+
if (el) {
|
|
324
|
+
// Restore value first to ensure cursor positioning works correctly
|
|
325
|
+
if (preservedValue !== null && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)) {
|
|
326
|
+
el.value = preservedValue;
|
|
327
|
+
}
|
|
328
|
+
el.focus();
|
|
329
|
+
if ((el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) && selectionStart !== null) {
|
|
330
|
+
try {
|
|
331
|
+
el.setSelectionRange(selectionStart, selectionEnd);
|
|
459
332
|
}
|
|
460
|
-
|
|
333
|
+
catch (e) {
|
|
334
|
+
// input types that don't support selection (e.g. number/email) might throw
|
|
335
|
+
}
|
|
336
|
+
}
|
|
461
337
|
}
|
|
462
|
-
}
|
|
338
|
+
}
|
|
339
|
+
// [Anima] 2. Post-Update: FLIP (First, Last, Invert, Play)
|
|
340
|
+
if (animationSnapshots.size > 0) {
|
|
341
|
+
const newAnimatedEls = container.querySelectorAll('[mu-animate]');
|
|
342
|
+
newAnimatedEls.forEach(el => {
|
|
343
|
+
const key = el.getAttribute('mu-key') || el.id;
|
|
344
|
+
if (key && animationSnapshots.has(key)) {
|
|
345
|
+
const oldRect = animationSnapshots.get(key);
|
|
346
|
+
const newRect = el.getBoundingClientRect();
|
|
347
|
+
const dx = oldRect.left - newRect.left;
|
|
348
|
+
const dy = oldRect.top - newRect.top;
|
|
349
|
+
// Only animate if moved
|
|
350
|
+
if (dx !== 0 || dy !== 0) {
|
|
351
|
+
const htmlEl = el;
|
|
352
|
+
// INVERT: Move it back to where it was instantly
|
|
353
|
+
htmlEl.style.transform = `translate(${dx}px, ${dy}px)`;
|
|
354
|
+
htmlEl.style.transition = 'none';
|
|
355
|
+
// PLAY: Animate to zero (new position)
|
|
356
|
+
requestAnimationFrame(() => {
|
|
357
|
+
// Force reflow
|
|
358
|
+
// void htmlEl.offsetWidth;
|
|
359
|
+
htmlEl.style.transition = 'transform 500ms cubic-bezier(0.25, 0.8, 0.25, 1)';
|
|
360
|
+
htmlEl.style.transform = '';
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
}
|
|
463
366
|
}
|
|
464
|
-
|
|
465
|
-
|
|
367
|
+
function hydrate(template, container) {
|
|
368
|
+
// In a string-based framework, hydration is often just "take over".
|
|
369
|
+
// For now, we'll verify if the server content matches (simple check)
|
|
370
|
+
// and then assume control. In a more advanced version, we'd attach listeners without re-rendering.
|
|
371
|
+
if (typeof template === 'string') {
|
|
372
|
+
if (container.innerHTML.trim() !== template.trim()) {
|
|
373
|
+
console.warn('Hydration Mismatch: Server rendered content differs from Client.');
|
|
374
|
+
container.innerHTML = template; // Fallback to full render
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
// console.log('Hydration Successful.');
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
container.innerHTML = '';
|
|
382
|
+
container.appendChild(template);
|
|
383
|
+
}
|
|
384
|
+
// Future: Attach event listeners here if we had a mechanism for it.
|
|
385
|
+
}
|
|
386
|
+
function sanitize(str) {
|
|
387
|
+
// Check if we are in a browser environment
|
|
388
|
+
if (typeof document !== 'undefined') {
|
|
389
|
+
const temp = document.createElement('div');
|
|
390
|
+
temp.textContent = str;
|
|
391
|
+
return temp.innerHTML;
|
|
392
|
+
}
|
|
393
|
+
// Simple SSR fallback sanitizer (rudimentary)
|
|
394
|
+
return str.replace(/&/g, "&")
|
|
395
|
+
.replace(/</g, "<")
|
|
396
|
+
.replace(/>/g, ">")
|
|
397
|
+
.replace(/"/g, """)
|
|
398
|
+
.replace(/'/g, "'");
|
|
466
399
|
}
|
|
467
|
-
exports["default"] = Mulan;
|
|
468
400
|
|
|
401
|
+
;// ./src/core/vault.ts
|
|
469
402
|
|
|
470
|
-
/***/ },
|
|
471
403
|
|
|
472
|
-
|
|
473
|
-
|
|
404
|
+
/**
|
|
405
|
+
* Mulan Vault: The World's First Native Persistent State Primitive.
|
|
406
|
+
*/
|
|
407
|
+
function persistent(key, initialValue, options = {}) {
|
|
408
|
+
const storage = options.storage || window.localStorage;
|
|
409
|
+
// 1. Load from Storage
|
|
410
|
+
const stored = storage.getItem(key);
|
|
411
|
+
let startVal = initialValue;
|
|
412
|
+
if (stored) {
|
|
413
|
+
try {
|
|
414
|
+
startVal = JSON.parse(stored);
|
|
415
|
+
}
|
|
416
|
+
catch (e) {
|
|
417
|
+
console.warn(`[Mulan Vault] Corrupt persistent data for key "${key}", resetting.`);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
// 2. Create Reactive State (Follow muState pattern for consistency)
|
|
421
|
+
const isObject = typeof startVal === 'object' && startVal !== null;
|
|
422
|
+
const state = isObject ? reactive(startVal) : reactive({ value: startVal });
|
|
423
|
+
// 3. Auto-Save on Change
|
|
424
|
+
muEffect(() => {
|
|
425
|
+
try {
|
|
426
|
+
const payload = isObject ? state : state.value;
|
|
427
|
+
const toSave = JSON.stringify(payload);
|
|
428
|
+
// Non-obfuscated persistence to satisfy security audits
|
|
429
|
+
storage.setItem(key, toSave);
|
|
430
|
+
}
|
|
431
|
+
catch (e) {
|
|
432
|
+
console.error(`[Mulan Vault] Failed to save key "${key}"`);
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
// 4. Sync across Tabs
|
|
436
|
+
const sync = (e) => {
|
|
437
|
+
if (e.key === key && e.newValue) {
|
|
438
|
+
try {
|
|
439
|
+
const newVal = JSON.parse(e.newValue);
|
|
440
|
+
if (isObject) {
|
|
441
|
+
Object.assign(state, newVal);
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
state.value = newVal;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
catch (e) { }
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
window.addEventListener('storage', sync);
|
|
451
|
+
// Explicit cleanup if provided by the environment (e.g. Mulan Hooks)
|
|
452
|
+
if (options.onCleanup) {
|
|
453
|
+
options.onCleanup(() => {
|
|
454
|
+
window.removeEventListener('storage', sync);
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
return state;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
;// ./src/core/hooks.ts
|
|
474
461
|
|
|
475
462
|
|
|
476
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
477
|
-
exports.muHistory = exports.onMuPanic = exports.muThrottled = exports.muDebounced = exports.onMuVisibility = exports.muSuspense = exports.muVault = exports.muPulse = exports.muGeom = exports.onMuVoice = exports.onMuShake = exports.onMuResume = exports.onMuIdle = exports.onMuDestroy = exports.onMuMount = exports.onMuInit = exports.muEffect = exports.muMemo = exports.muState = exports.getCurrentInstance = exports.setCurrentInstance = void 0;
|
|
478
|
-
const reactive_1 = __webpack_require__(359);
|
|
479
|
-
const vault_1 = __webpack_require__(234);
|
|
480
463
|
// Global context to track the current component instance
|
|
481
464
|
let currentInstance = null;
|
|
482
465
|
function setCurrentInstance(instance) {
|
|
483
466
|
currentInstance = instance;
|
|
484
467
|
}
|
|
485
|
-
exports.setCurrentInstance = setCurrentInstance;
|
|
486
468
|
function getCurrentInstance() {
|
|
487
469
|
return currentInstance;
|
|
488
470
|
}
|
|
489
|
-
exports.getCurrentInstance = getCurrentInstance;
|
|
490
471
|
// --- Mulan Unique Reactivity Hooks ---
|
|
491
472
|
function muState(initialValue) {
|
|
492
473
|
if (typeof initialValue === 'object' && initialValue !== null) {
|
|
493
|
-
return
|
|
474
|
+
return reactive(initialValue);
|
|
494
475
|
}
|
|
495
476
|
// Core reactive state container for primitives
|
|
496
|
-
return
|
|
477
|
+
return reactive({ value: initialValue });
|
|
497
478
|
}
|
|
498
|
-
exports.muState = muState;
|
|
499
479
|
function muMemo(computeFn) {
|
|
500
|
-
const signal =
|
|
501
|
-
const stop =
|
|
480
|
+
const signal = reactive({ value: undefined });
|
|
481
|
+
const stop = effect(() => {
|
|
502
482
|
signal.value = computeFn();
|
|
503
483
|
});
|
|
504
484
|
const instance = getCurrentInstance();
|
|
@@ -509,9 +489,8 @@ function muMemo(computeFn) {
|
|
|
509
489
|
}
|
|
510
490
|
return signal;
|
|
511
491
|
}
|
|
512
|
-
exports.muMemo = muMemo;
|
|
513
492
|
function muEffect(fn) {
|
|
514
|
-
const stop =
|
|
493
|
+
const stop = effect(fn);
|
|
515
494
|
const instance = getCurrentInstance();
|
|
516
495
|
if (instance) {
|
|
517
496
|
if (!instance._effects)
|
|
@@ -519,7 +498,6 @@ function muEffect(fn) {
|
|
|
519
498
|
instance._effects.push(stop);
|
|
520
499
|
}
|
|
521
500
|
}
|
|
522
|
-
exports.muEffect = muEffect;
|
|
523
501
|
// --- The "Mulan Cycle" (Lifecycle) ---
|
|
524
502
|
function onMuInit(fn) {
|
|
525
503
|
const instance = getCurrentInstance();
|
|
@@ -534,7 +512,6 @@ function onMuInit(fn) {
|
|
|
534
512
|
console.warn('onMuInit called outside of component setup context.');
|
|
535
513
|
}
|
|
536
514
|
}
|
|
537
|
-
exports.onMuInit = onMuInit;
|
|
538
515
|
function onMuMount(fn) {
|
|
539
516
|
// New hook for when component is actually in DOM (simulated for now via update)
|
|
540
517
|
const instance = getCurrentInstance();
|
|
@@ -546,7 +523,6 @@ function onMuMount(fn) {
|
|
|
546
523
|
instance._hooks.onMuMount.push(fn);
|
|
547
524
|
}
|
|
548
525
|
}
|
|
549
|
-
exports.onMuMount = onMuMount;
|
|
550
526
|
function onMuDestroy(fn) {
|
|
551
527
|
const instance = getCurrentInstance();
|
|
552
528
|
if (instance) {
|
|
@@ -557,7 +533,6 @@ function onMuDestroy(fn) {
|
|
|
557
533
|
instance._hooks.onMuDestroy.push(fn);
|
|
558
534
|
}
|
|
559
535
|
}
|
|
560
|
-
exports.onMuDestroy = onMuDestroy;
|
|
561
536
|
/**
|
|
562
537
|
* onMuIdle - The "Environment Life" Hook.
|
|
563
538
|
* Executes heavy logic ONLY when the browser is taking a nap (idle).
|
|
@@ -586,7 +561,6 @@ function onMuIdle(fn) {
|
|
|
586
561
|
});
|
|
587
562
|
}
|
|
588
563
|
}
|
|
589
|
-
exports.onMuIdle = onMuIdle;
|
|
590
564
|
/**
|
|
591
565
|
* onMuResume - The "Tab Life" Hook.
|
|
592
566
|
* Executes when the user switches BACK to this tab.
|
|
@@ -601,7 +575,6 @@ function onMuResume(fn) {
|
|
|
601
575
|
document.addEventListener('visibilitychange', handler);
|
|
602
576
|
onMuDestroy(() => document.removeEventListener('visibilitychange', handler));
|
|
603
577
|
}
|
|
604
|
-
exports.onMuResume = onMuResume;
|
|
605
578
|
/**
|
|
606
579
|
* onMuShake - The "Physical Life" Hook.
|
|
607
580
|
* Executes when the device is shaken.
|
|
@@ -640,7 +613,6 @@ function onMuShake(fn) {
|
|
|
640
613
|
console.warn("[MulanJS] Device Motion not supported on this device.");
|
|
641
614
|
}
|
|
642
615
|
}
|
|
643
|
-
exports.onMuShake = onMuShake;
|
|
644
616
|
/**
|
|
645
617
|
* onMuVoice - The "Sound Life" Hook.
|
|
646
618
|
* Executes when a specific word is spoken.
|
|
@@ -676,7 +648,6 @@ function onMuVoice(command, fn) {
|
|
|
676
648
|
recognition.stop();
|
|
677
649
|
});
|
|
678
650
|
}
|
|
679
|
-
exports.onMuVoice = onMuVoice;
|
|
680
651
|
// --- "Outside The Box" Hooks (Mulan Exclusives) ---
|
|
681
652
|
/**
|
|
682
653
|
* muGeom - Tracks window or element dimensions reactively.
|
|
@@ -694,7 +665,6 @@ function muGeom() {
|
|
|
694
665
|
});
|
|
695
666
|
return dims;
|
|
696
667
|
}
|
|
697
|
-
exports.muGeom = muGeom;
|
|
698
668
|
/**
|
|
699
669
|
* muPulse - Reactive network status.
|
|
700
670
|
*/
|
|
@@ -710,15 +680,13 @@ function muPulse() {
|
|
|
710
680
|
});
|
|
711
681
|
return status;
|
|
712
682
|
}
|
|
713
|
-
exports.muPulse = muPulse;
|
|
714
683
|
/**
|
|
715
684
|
* muVault - Secure reactive LocalStorage wrapper.
|
|
716
685
|
* Powered by the Iron Fortress persistent primitive.
|
|
717
686
|
*/
|
|
718
687
|
function muVault(key, initial, options = {}) {
|
|
719
|
-
return
|
|
688
|
+
return persistent(key, initial, Object.assign(Object.assign({}, options), { onCleanup: (fn) => onMuDestroy(fn) }));
|
|
720
689
|
}
|
|
721
|
-
exports.muVault = muVault;
|
|
722
690
|
// --- Next-Gen MulanJS Hooks ---
|
|
723
691
|
/**
|
|
724
692
|
* muSuspense - The Asynchronous Barrier.
|
|
@@ -742,7 +710,6 @@ function muSuspense(promiseFn) {
|
|
|
742
710
|
});
|
|
743
711
|
return state;
|
|
744
712
|
}
|
|
745
|
-
exports.muSuspense = muSuspense;
|
|
746
713
|
/**
|
|
747
714
|
* onMuVisibility - The Intersection Observer Hook.
|
|
748
715
|
* Triggers when the component enters/leaves the viewport.
|
|
@@ -764,7 +731,6 @@ function onMuVisibility(callback, options = { threshold: 0.1 }) {
|
|
|
764
731
|
});
|
|
765
732
|
});
|
|
766
733
|
}
|
|
767
|
-
exports.onMuVisibility = onMuVisibility;
|
|
768
734
|
/**
|
|
769
735
|
* muDebounced - High-performance debouncing built directly into a reactive signal.
|
|
770
736
|
*/
|
|
@@ -783,7 +749,6 @@ function muDebounced(initialValue, delayMs) {
|
|
|
783
749
|
}
|
|
784
750
|
};
|
|
785
751
|
}
|
|
786
|
-
exports.muDebounced = muDebounced;
|
|
787
752
|
/**
|
|
788
753
|
* muThrottled - High-performance throttling built directly into a reactive signal.
|
|
789
754
|
*/
|
|
@@ -803,7 +768,6 @@ function muThrottled(initialValue, delayMs) {
|
|
|
803
768
|
}
|
|
804
769
|
};
|
|
805
770
|
}
|
|
806
|
-
exports.muThrottled = muThrottled;
|
|
807
771
|
/**
|
|
808
772
|
* onMuPanic - The Iron Fortress Error Boundary.
|
|
809
773
|
* Catches unhandled exceptions within the component scope.
|
|
@@ -827,7 +791,6 @@ function onMuPanic(fallbackFn) {
|
|
|
827
791
|
window.removeEventListener('unhandledrejection', handler);
|
|
828
792
|
});
|
|
829
793
|
}
|
|
830
|
-
exports.onMuPanic = onMuPanic;
|
|
831
794
|
/**
|
|
832
795
|
* muHistory - State with built-in Undo/Redo tracking.
|
|
833
796
|
*/
|
|
@@ -866,554 +829,365 @@ function muHistory(initialValue) {
|
|
|
866
829
|
get future() { return historyTracker.log.slice(pointer.value + 1); }
|
|
867
830
|
};
|
|
868
831
|
}
|
|
869
|
-
exports.muHistory = muHistory;
|
|
870
832
|
|
|
833
|
+
;// ./src/core/component.ts
|
|
871
834
|
|
|
872
|
-
/***/ },
|
|
873
835
|
|
|
874
|
-
/***/ 172
|
|
875
|
-
(__unused_webpack_module, exports) {
|
|
876
836
|
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
837
|
+
// Or a simple component that returns an object of state/methods used by template?
|
|
838
|
+
// For Mulan 2.0, let's say functional component returns a template string render function explicitly.
|
|
839
|
+
class MuComponent {
|
|
840
|
+
constructor(container) {
|
|
841
|
+
this._hooks = {};
|
|
842
|
+
this._effects = [];
|
|
843
|
+
this._domEffects = [];
|
|
844
|
+
this._isDestroyed = false;
|
|
845
|
+
this._isResuming = false; // Quantum Resumability Flag
|
|
846
|
+
this._resumeRoot = null;
|
|
847
|
+
this._propsQueue = [];
|
|
848
|
+
this._eventQueue = [];
|
|
849
|
+
// --- MulanJS List Reconciliation Engine (No-VDOM) ---
|
|
850
|
+
// Cache to store generated DOM rows by mu-key
|
|
851
|
+
this._listCaches = new Map();
|
|
852
|
+
// --- MulanJS Conditional Engine (No-VDOM) ---
|
|
853
|
+
// Cache to store conditionally toggled blocks
|
|
854
|
+
this._ifCaches = new Map();
|
|
855
|
+
this.container = container;
|
|
856
|
+
this.state = {};
|
|
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
|
+
}
|
|
898
875
|
}
|
|
899
876
|
}
|
|
900
|
-
if (onProgress) {
|
|
901
|
-
onProgress((index / total) * 100);
|
|
902
|
-
}
|
|
903
|
-
if (index < total) {
|
|
904
|
-
requestAnimationFrame(process);
|
|
905
|
-
}
|
|
906
|
-
else {
|
|
907
|
-
resolve();
|
|
908
|
-
}
|
|
909
877
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
* muSurge - Truly Parallel Execution
|
|
916
|
-
* Distributes work across CPU cores using Web Workers.
|
|
917
|
-
* Logic must be serializable.
|
|
918
|
-
*/
|
|
919
|
-
function muSurge(array, taskFn, onProgress) {
|
|
920
|
-
const n = navigator.hardwareConcurrency || 4;
|
|
921
|
-
const chunkSize = Math.ceil(array.length / n);
|
|
922
|
-
const results = new Array(array.length);
|
|
923
|
-
let completedChunks = 0;
|
|
924
|
-
let completedItems = 0;
|
|
925
|
-
// Convert function to string if it isn't already
|
|
926
|
-
const fnStr = typeof taskFn === 'function' ? taskFn.toString() : taskFn;
|
|
927
|
-
const workerPart1 = `const taskFn = ${fnStr};`;
|
|
928
|
-
const workerPart2 = `self.onmessage = function(e) {`;
|
|
929
|
-
const workerPart3 = ` const { chunk, startIndex } = e.data;`;
|
|
930
|
-
const workerPart4 = ` try { const results = chunk.map(taskFn); self.postMessage({ results, startIndex }); }`;
|
|
931
|
-
const workerPart5 = ` catch (err) { self.postMessage({ error: err.message, startIndex }); }`;
|
|
932
|
-
const workerPart6 = `};`;
|
|
933
|
-
const workerCode = [workerPart1, workerPart2, workerPart3, workerPart4, workerPart5, workerPart6].join('\n');
|
|
934
|
-
const blob = new Blob([workerCode], { type: 'application/javascript' });
|
|
935
|
-
const workerUrl = URL.createObjectURL(blob);
|
|
936
|
-
return new Promise((resolve) => {
|
|
937
|
-
if (array.length === 0)
|
|
938
|
-
return resolve([]);
|
|
939
|
-
for (let i = 0; i < n; i++) {
|
|
940
|
-
const start = i * chunkSize;
|
|
941
|
-
const end = Math.min(start + chunkSize, array.length);
|
|
942
|
-
if (start >= end) {
|
|
943
|
-
completedChunks++;
|
|
944
|
-
continue;
|
|
945
|
-
}
|
|
946
|
-
const chunk = array.slice(start, end);
|
|
947
|
-
const worker = new Worker(workerUrl);
|
|
948
|
-
worker.onmessage = (e) => {
|
|
949
|
-
const { results: chunkResults, startIndex } = e.data;
|
|
950
|
-
// Merge results back into main array
|
|
951
|
-
for (let j = 0; j < chunkResults.length; j++) {
|
|
952
|
-
results[startIndex + j] = chunkResults[j];
|
|
953
|
-
}
|
|
954
|
-
completedChunks++;
|
|
955
|
-
completedItems += chunkResults.length;
|
|
956
|
-
if (onProgress)
|
|
957
|
-
onProgress((completedItems / array.length) * 100);
|
|
958
|
-
worker.terminate();
|
|
959
|
-
if (completedChunks === n) {
|
|
960
|
-
URL.revokeObjectURL(workerUrl);
|
|
961
|
-
resolve(results);
|
|
962
|
-
}
|
|
963
|
-
};
|
|
964
|
-
worker.postMessage({ chunk, startIndex: start, fnStr });
|
|
965
|
-
}
|
|
966
|
-
});
|
|
967
|
-
}
|
|
968
|
-
exports.muSurge = muSurge;
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
/***/ },
|
|
972
|
-
|
|
973
|
-
/***/ 234
|
|
974
|
-
(__unused_webpack_module, exports, __webpack_require__) {
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
978
|
-
exports.persistent = void 0;
|
|
979
|
-
const hooks_1 = __webpack_require__(166);
|
|
980
|
-
const reactive_1 = __webpack_require__(359);
|
|
981
|
-
/**
|
|
982
|
-
* Mulan Vault: The World's First Native Persistent State Primitive.
|
|
983
|
-
*/
|
|
984
|
-
function persistent(key, initialValue, options = {}) {
|
|
985
|
-
const storage = options.storage || window.localStorage;
|
|
986
|
-
// 1. Load from Storage
|
|
987
|
-
const stored = storage.getItem(key);
|
|
988
|
-
let startVal = initialValue;
|
|
989
|
-
if (stored) {
|
|
990
|
-
try {
|
|
991
|
-
startVal = JSON.parse(stored);
|
|
992
|
-
}
|
|
993
|
-
catch (e) {
|
|
994
|
-
console.warn(`[Mulan Vault] Corrupt persistent data for key "${key}", resetting.`);
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
// 2. Create Reactive State (Follow muState pattern for consistency)
|
|
998
|
-
const isObject = typeof startVal === 'object' && startVal !== null;
|
|
999
|
-
const state = isObject ? (0, reactive_1.reactive)(startVal) : (0, reactive_1.reactive)({ value: startVal });
|
|
1000
|
-
// 3. Auto-Save on Change
|
|
1001
|
-
(0, hooks_1.muEffect)(() => {
|
|
1002
|
-
try {
|
|
1003
|
-
const payload = isObject ? state : state.value;
|
|
1004
|
-
const toSave = JSON.stringify(payload);
|
|
1005
|
-
// Non-obfuscated persistence to satisfy security audits
|
|
1006
|
-
storage.setItem(key, toSave);
|
|
1007
|
-
}
|
|
1008
|
-
catch (e) {
|
|
1009
|
-
console.error(`[Mulan Vault] Failed to save key "${key}"`);
|
|
1010
|
-
}
|
|
1011
|
-
});
|
|
1012
|
-
// 4. Sync across Tabs
|
|
1013
|
-
const sync = (e) => {
|
|
1014
|
-
if (e.key === key && e.newValue) {
|
|
1015
|
-
try {
|
|
1016
|
-
const newVal = JSON.parse(e.newValue);
|
|
1017
|
-
if (isObject) {
|
|
1018
|
-
Object.assign(state, newVal);
|
|
1019
|
-
}
|
|
1020
|
-
else {
|
|
1021
|
-
state.value = newVal;
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
catch (e) { }
|
|
878
|
+
// MULAN INSIGHT: Global Registry for Debugging
|
|
879
|
+
if (typeof window !== 'undefined') {
|
|
880
|
+
const global = window;
|
|
881
|
+
global.__MULAN_INSIGHT__ = global.__MULAN_INSIGHT__ || { components: new Map() };
|
|
882
|
+
global.__MULAN_INSIGHT__.components.set(this.$uid, this);
|
|
1025
883
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
options.onCleanup(() => {
|
|
1031
|
-
window.removeEventListener('storage', sync);
|
|
1032
|
-
});
|
|
884
|
+
// Setup context for hooks
|
|
885
|
+
setCurrentInstance(this);
|
|
886
|
+
this.setup();
|
|
887
|
+
setCurrentInstance(null);
|
|
1033
888
|
}
|
|
1034
|
-
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
(__unused_webpack_module, exports) {
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
// MulanJS 2.0: Signal-Powered Reactivity Engine
|
|
1046
|
-
// "Compatible Surface, World-Class Engine"
|
|
1047
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1048
|
-
exports.ref = exports.reactive = exports.effect = exports.Signal = exports.nextTick = exports.queueEffect = void 0;
|
|
1049
|
-
let activeEffect = null;
|
|
1050
|
-
let activeEffectRunner = null;
|
|
1051
|
-
const targetMap = new WeakMap();
|
|
1052
|
-
// --- Mulan Quantum Scheduler (Time-Slicing) ---
|
|
1053
|
-
// Assign unique IDs to effects for basic topological sorting (lower IDs run first)
|
|
1054
|
-
let effectIdCounter = 0;
|
|
1055
|
-
const pendingEffects = new Set();
|
|
1056
|
-
let isScheduling = false;
|
|
1057
|
-
const TIME_BUDGET = 8; // 8ms frame budget for 60FPS lock
|
|
1058
|
-
function runScheduler() {
|
|
1059
|
-
if (pendingEffects.size === 0) {
|
|
1060
|
-
isScheduling = false;
|
|
1061
|
-
return;
|
|
889
|
+
// Optional setup method for class components wanting to use hooks
|
|
890
|
+
setup() { }
|
|
891
|
+
onMount() {
|
|
892
|
+
var _a, _c;
|
|
893
|
+
// Mulan Cycle: Init
|
|
894
|
+
(_a = this._hooks.onMuInit) === null || _a === void 0 ? void 0 : _a.forEach(fn => fn());
|
|
895
|
+
// Mulan Cycle: Mount (Simulated immediately after init for now in this version)
|
|
896
|
+
(_c = this._hooks.onMuMount) === null || _c === void 0 ? void 0 : _c.forEach(fn => fn());
|
|
1062
897
|
}
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
898
|
+
onUpdate() { }
|
|
899
|
+
onDestroy() {
|
|
900
|
+
var _a, _c;
|
|
901
|
+
if (this._isDestroyed)
|
|
902
|
+
return;
|
|
903
|
+
this._isDestroyed = true;
|
|
904
|
+
console.log(`[Mulan Cycle] Destroying component ${this.$uid} (${this.constructor.name})`);
|
|
905
|
+
// MULAN INSIGHT: Cleanup
|
|
906
|
+
if (typeof window !== 'undefined') {
|
|
907
|
+
const global = window;
|
|
908
|
+
(_a = global.__MULAN_INSIGHT__) === null || _a === void 0 ? void 0 : _a.components.delete(this.$uid);
|
|
1074
909
|
}
|
|
910
|
+
// Mulan Cycle: Stop all effects to prevent leaks
|
|
911
|
+
console.log(`[Mulan Cycle] Stopping ${this._effects.length} effects for ${this.$uid}`);
|
|
912
|
+
this._effects.forEach(stop => stop());
|
|
913
|
+
this._effects = [];
|
|
914
|
+
console.log(`[Mulan Cycle] Stopping ${this._domEffects.length} DOM effects for ${this.$uid}`);
|
|
915
|
+
this._domEffects.forEach(stop => stop());
|
|
916
|
+
this._domEffects = [];
|
|
917
|
+
// Mulan Cycle: Destroy hooks
|
|
918
|
+
(_c = this._hooks.onMuDestroy) === null || _c === void 0 ? void 0 : _c.forEach(fn => fn());
|
|
1075
919
|
}
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
channel.port2.postMessage(null);
|
|
1081
|
-
}
|
|
1082
|
-
else {
|
|
1083
|
-
setTimeout(runScheduler, 0);
|
|
1084
|
-
}
|
|
920
|
+
// Helper for compiler to register property bindings
|
|
921
|
+
_b(id, prop, value) {
|
|
922
|
+
this._propsQueue.push([id, prop, value]);
|
|
923
|
+
return "";
|
|
1085
924
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
925
|
+
// Helper for compiler to register event bindings
|
|
926
|
+
_e(id, type, handler) {
|
|
927
|
+
this._eventQueue.push([id, type, handler]);
|
|
928
|
+
return "";
|
|
1088
929
|
}
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
930
|
+
// Manual binding helper for template literals
|
|
931
|
+
bind(handler, type = 'click') {
|
|
932
|
+
const id = 'ev_' + Math.random().toString(36).substr(2, 9);
|
|
933
|
+
this._e(id, type, handler);
|
|
934
|
+
return `data-mu-id="${id}"`;
|
|
935
|
+
}
|
|
936
|
+
mount() {
|
|
937
|
+
console.log(`[Mulan Cycle] Mounting component ${this.$uid}`);
|
|
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();
|
|
1096
942
|
}
|
|
1097
943
|
else {
|
|
1098
|
-
|
|
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);
|
|
1099
950
|
}
|
|
951
|
+
this.onMount();
|
|
1100
952
|
}
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
this.
|
|
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();
|
|
1112
969
|
}
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
return
|
|
970
|
+
// New helper for the compiler to register a fine-grained DOM property effect
|
|
971
|
+
_bindEffect(fn, targetNode) {
|
|
972
|
+
const stop = effect(fn, targetNode);
|
|
973
|
+
this._domEffects.push(stop);
|
|
974
|
+
return stop;
|
|
1118
975
|
}
|
|
1119
|
-
|
|
1120
|
-
if (
|
|
1121
|
-
this.
|
|
1122
|
-
|
|
976
|
+
update() {
|
|
977
|
+
if (this._isDestroyed) {
|
|
978
|
+
console.warn(`[Mulan Warning] Update called on destroyed component ${this.$uid}. Blocking render.`);
|
|
979
|
+
return;
|
|
1123
980
|
}
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
this.
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
981
|
+
// Clear queues before render
|
|
982
|
+
this._propsQueue = [];
|
|
983
|
+
this._eventQueue = [];
|
|
984
|
+
const template = this.template();
|
|
985
|
+
// Render HTML
|
|
986
|
+
render(template, this.container);
|
|
987
|
+
// Flush Side Effects
|
|
988
|
+
this.flushProps();
|
|
989
|
+
this.flushEvents();
|
|
990
|
+
this.onUpdate();
|
|
991
|
+
}
|
|
992
|
+
flushProps() {
|
|
993
|
+
for (const [id, prop, value] of this._propsQueue) {
|
|
994
|
+
const el = this.container.querySelector(`[data-mu-id="${id}"]`);
|
|
995
|
+
if (el) {
|
|
996
|
+
// @ts-ignore
|
|
997
|
+
el[prop] = value;
|
|
1132
998
|
}
|
|
1133
|
-
}
|
|
999
|
+
}
|
|
1000
|
+
this._propsQueue = [];
|
|
1134
1001
|
}
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1002
|
+
flushEvents() {
|
|
1003
|
+
for (const [id, type, handler] of this._eventQueue) {
|
|
1004
|
+
const el = this.container.querySelector(`[data-mu-id="${id}"]`);
|
|
1005
|
+
if (el) {
|
|
1006
|
+
// Bind handler to this component instance to ensure 'this' works in methods
|
|
1007
|
+
el.addEventListener(type, handler.bind(this));
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
this._eventQueue = [];
|
|
1011
|
+
}
|
|
1012
|
+
/**
|
|
1013
|
+
* Reconciles a list of bound data to an existing DOM parent segment.
|
|
1014
|
+
* @param listId Unique ID for this specific mu-for directive Block
|
|
1015
|
+
* @param container The DOM Element or Fragment where children are attached
|
|
1016
|
+
* @param array The current state array
|
|
1017
|
+
* @param keyProp The property to extract from each item to use as a unique key (e.g. 'id')
|
|
1018
|
+
* @param renderRow A function that takes an item and returns a new { fragment, effects }
|
|
1019
|
+
*/
|
|
1020
|
+
_reconcileList(listId, anchorToken, array, keyProp, renderRow) {
|
|
1021
|
+
if (!this._listCaches.has(listId)) {
|
|
1022
|
+
this._listCaches.set(listId, new Map());
|
|
1023
|
+
}
|
|
1024
|
+
const cache = this._listCaches.get(listId);
|
|
1025
|
+
const newKeys = new Set();
|
|
1026
|
+
const parent = anchorToken.parentNode;
|
|
1027
|
+
if (!parent)
|
|
1143
1028
|
return;
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1029
|
+
// 1. Array Iteration: Match against cache or Create
|
|
1030
|
+
// Use a DocumentFragment to batch new node insertions natively
|
|
1031
|
+
const collectorFrag = document.createDocumentFragment();
|
|
1032
|
+
const newOrderNodes = [];
|
|
1033
|
+
const newOrderKeys = [];
|
|
1034
|
+
let requiresSwap = false;
|
|
1035
|
+
let lastCachedIndex = -1;
|
|
1036
|
+
for (let i = 0; i < array.length; i++) {
|
|
1037
|
+
const item = array[i];
|
|
1038
|
+
const key = keyProp ? item[keyProp] : i; // fallback to index if no key
|
|
1039
|
+
newKeys.add(key);
|
|
1040
|
+
newOrderKeys.push(key);
|
|
1041
|
+
let cached = cache.get(key);
|
|
1042
|
+
if (!cached) {
|
|
1043
|
+
// Not in cache, Render a brand new row structure
|
|
1044
|
+
const { fragment, effects } = renderRow(item, i);
|
|
1045
|
+
// Track actual DOM nodes
|
|
1046
|
+
const createdNodes = Array.from(fragment.childNodes);
|
|
1047
|
+
cached = { nodes: createdNodes, effects, index: i }; // Store index for fast swap detection
|
|
1048
|
+
cache.set(key, cached);
|
|
1049
|
+
// Batch append to our in-memory fragment!
|
|
1050
|
+
// This eliminates thousands of live DOM reflows on creation.
|
|
1051
|
+
collectorFrag.appendChild(fragment);
|
|
1052
|
+
newOrderNodes.push(...createdNodes);
|
|
1053
|
+
}
|
|
1054
|
+
else {
|
|
1055
|
+
// Exists in cache
|
|
1056
|
+
// Batch append to the in-memory array for index tracking
|
|
1057
|
+
newOrderNodes.push(...cached.nodes);
|
|
1058
|
+
// Fast-Path Swap Detection: If the cached index is physically out of numerical sequence,
|
|
1059
|
+
// we know the array order was unsynchronized and needs reconciliation.
|
|
1060
|
+
if (cached.index < lastCachedIndex) {
|
|
1061
|
+
requiresSwap = true;
|
|
1062
|
+
}
|
|
1063
|
+
cached.index = i;
|
|
1064
|
+
lastCachedIndex = i;
|
|
1065
|
+
}
|
|
1148
1066
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
1067
|
+
// 2. Fragment Batch Insertion (O(1) Live DOM Reflow for Creations)
|
|
1068
|
+
if (collectorFrag.childNodes.length > 0) {
|
|
1069
|
+
parent.insertBefore(collectorFrag, anchorToken.nextSibling);
|
|
1151
1070
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
targetMap.set(target, (depsMap = new Map()));
|
|
1071
|
+
// 3. Bidirectional Swap Sync (O(K) isolated shifts instead of O(N) cascades)
|
|
1072
|
+
if (requiresSwap) {
|
|
1073
|
+
let currentSibling = anchorToken.nextSibling;
|
|
1074
|
+
// We iterate through our guaranteed physical newOrderNodes list
|
|
1075
|
+
for (let j = 0; j < newOrderNodes.length; j++) {
|
|
1076
|
+
const targetNode = newOrderNodes[j];
|
|
1077
|
+
if (targetNode !== currentSibling) {
|
|
1078
|
+
// The physical live DOM is out of sync. Move targetNode to where it belongs immediately.
|
|
1079
|
+
parent.insertBefore(targetNode, currentSibling);
|
|
1080
|
+
}
|
|
1081
|
+
else {
|
|
1082
|
+
// Node is correctly positioned, simply advance the sliding logical pointer
|
|
1083
|
+
currentSibling = currentSibling.nextSibling;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1168
1086
|
}
|
|
1169
|
-
|
|
1170
|
-
if (
|
|
1171
|
-
|
|
1087
|
+
// 4. Cleanup Phase: Rapidly detach unmounted nodes
|
|
1088
|
+
if (cache.size > newKeys.size) {
|
|
1089
|
+
for (const [key, cached] of cache.entries()) {
|
|
1090
|
+
if (!newKeys.has(key)) {
|
|
1091
|
+
// Remove from DOM
|
|
1092
|
+
cached.nodes.forEach((node) => {
|
|
1093
|
+
if (node.parentNode === parent) {
|
|
1094
|
+
parent.removeChild(node);
|
|
1095
|
+
}
|
|
1096
|
+
});
|
|
1097
|
+
// Stop any targeted effects tied to these nodes
|
|
1098
|
+
cached.effects.forEach((stop) => stop());
|
|
1099
|
+
// Delete from cache tracking
|
|
1100
|
+
cache.delete(key);
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1172
1103
|
}
|
|
1173
|
-
dep.add(activeEffectRunner.run);
|
|
1174
1104
|
}
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1105
|
+
/**
|
|
1106
|
+
* Reconciles a conditional block (mu-if) to an existing DOM parent segment.
|
|
1107
|
+
*/
|
|
1108
|
+
_reconcileIf(ifId, anchorToken, condition, renderBlock) {
|
|
1109
|
+
if (!this._ifCaches.has(ifId)) {
|
|
1110
|
+
this._ifCaches.set(ifId, { isMounted: false, nodes: [], effects: [] });
|
|
1111
|
+
}
|
|
1112
|
+
let cached = this._ifCaches.get(ifId);
|
|
1113
|
+
if (condition) {
|
|
1114
|
+
// Should be mounted
|
|
1115
|
+
if (!cached.isMounted) {
|
|
1116
|
+
// We need to render and mount it
|
|
1117
|
+
let nodesToMount;
|
|
1118
|
+
if (cached.nodes.length === 0) {
|
|
1119
|
+
// First time render
|
|
1120
|
+
const { fragment, effects } = renderBlock();
|
|
1121
|
+
nodesToMount = Array.from(fragment.childNodes);
|
|
1122
|
+
cached.nodes = nodesToMount;
|
|
1123
|
+
cached.effects = effects;
|
|
1124
|
+
}
|
|
1125
|
+
else {
|
|
1126
|
+
// Re-mounting previously cached nodes
|
|
1127
|
+
nodesToMount = cached.nodes;
|
|
1128
|
+
}
|
|
1129
|
+
cached.isMounted = true;
|
|
1130
|
+
const parent = anchorToken.parentNode;
|
|
1131
|
+
if (!parent)
|
|
1132
|
+
return;
|
|
1133
|
+
const targetSibling = anchorToken.nextSibling;
|
|
1134
|
+
nodesToMount.forEach(node => {
|
|
1135
|
+
parent.insertBefore(node, targetSibling);
|
|
1136
|
+
});
|
|
1185
1137
|
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1138
|
+
}
|
|
1139
|
+
else {
|
|
1140
|
+
// Should NOT be mounted
|
|
1141
|
+
if (cached.isMounted) {
|
|
1142
|
+
// Unmount nodes but keep them in cache
|
|
1143
|
+
cached.nodes.forEach(node => {
|
|
1144
|
+
if (node.parentNode) {
|
|
1145
|
+
node.parentNode.removeChild(node);
|
|
1146
|
+
}
|
|
1147
|
+
});
|
|
1148
|
+
cached.isMounted = false;
|
|
1149
|
+
// Note: We deliberately do NOT destroy the effects here, they stay active in memory!
|
|
1188
1150
|
}
|
|
1189
|
-
}
|
|
1151
|
+
}
|
|
1190
1152
|
}
|
|
1191
1153
|
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
//
|
|
1200
|
-
|
|
1201
|
-
|
|
1154
|
+
// Helper to create functional components wrapped in the class system
|
|
1155
|
+
// Helper to create functional components wrapped in the class system
|
|
1156
|
+
// Supports both () => render and { setup() } signatures
|
|
1157
|
+
function defineComponent(optionsOrSetup) {
|
|
1158
|
+
return class UniversalComponent extends MuComponent {
|
|
1159
|
+
constructor(container) {
|
|
1160
|
+
super(container);
|
|
1161
|
+
// setup() is called by super constructor
|
|
1162
|
+
}
|
|
1163
|
+
setup() {
|
|
1164
|
+
let setupResult;
|
|
1165
|
+
if (typeof optionsOrSetup === 'function') {
|
|
1166
|
+
// It's a setup function returning render fn
|
|
1167
|
+
setupResult = optionsOrSetup.call(this);
|
|
1202
1168
|
}
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
return reactive(val);
|
|
1169
|
+
else if (typeof optionsOrSetup === 'object' && optionsOrSetup.setup) {
|
|
1170
|
+
// It's an options object with setup()
|
|
1171
|
+
setupResult = optionsOrSetup.setup.call(this);
|
|
1207
1172
|
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') {
|
|
1213
|
-
console.warn(`[Iron Fortress] Blocked attempt to modify dangerous property: ${String(prop)}`);
|
|
1214
|
-
return false;
|
|
1173
|
+
// Handle result
|
|
1174
|
+
if (typeof setupResult === 'function') {
|
|
1175
|
+
// It's a render function
|
|
1176
|
+
this.template = setupResult;
|
|
1215
1177
|
}
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
});
|
|
1221
|
-
}
|
|
1222
|
-
exports.reactive = reactive;
|
|
1223
|
-
/**
|
|
1224
|
-
* Creates a standalone reactive reference.
|
|
1225
|
-
* Backed by the Mulan Signal Engine.
|
|
1226
|
-
*/
|
|
1227
|
-
function ref(value) {
|
|
1228
|
-
return new Signal(value);
|
|
1229
|
-
}
|
|
1230
|
-
exports.ref = ref;
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
/***/ },
|
|
1234
|
-
|
|
1235
|
-
/***/ 382
|
|
1236
|
-
(__unused_webpack_module, exports) {
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1240
|
-
exports.MuInfinity = void 0;
|
|
1241
|
-
const MuInfinityBase = typeof HTMLElement !== 'undefined' ? HTMLElement : class {
|
|
1242
|
-
};
|
|
1243
|
-
class MuInfinity extends MuInfinityBase {
|
|
1244
|
-
constructor() {
|
|
1245
|
-
super();
|
|
1246
|
-
this._items = [];
|
|
1247
|
-
this._itemHeight = 50; // Default height
|
|
1248
|
-
this._template = '';
|
|
1249
|
-
this.attachShadow({ mode: 'open' });
|
|
1250
|
-
// Structure:
|
|
1251
|
-
// :host { overflow-y: auto; display: block; height: 100%; }
|
|
1252
|
-
// .spacer { height: totalHeight; position: relative; }
|
|
1253
|
-
// .content { position: absolute; top: padding; width: 100%; }
|
|
1254
|
-
this.shadowRoot.innerHTML = `
|
|
1255
|
-
<style>
|
|
1256
|
-
:host {
|
|
1257
|
-
display: block;
|
|
1258
|
-
overflow-y: auto;
|
|
1259
|
-
height: 100%;
|
|
1260
|
-
position: relative;
|
|
1261
|
-
}
|
|
1262
|
-
.spacer {
|
|
1263
|
-
position: relative;
|
|
1264
|
-
width: 100%;
|
|
1265
|
-
}
|
|
1266
|
-
.content {
|
|
1267
|
-
position: absolute;
|
|
1268
|
-
top: 0;
|
|
1269
|
-
left: 0;
|
|
1270
|
-
width: 100%;
|
|
1271
|
-
}
|
|
1272
|
-
</style>
|
|
1273
|
-
<div class="spacer">
|
|
1274
|
-
<div class="content"></div>
|
|
1275
|
-
</div>
|
|
1276
|
-
`;
|
|
1277
|
-
this.container = this.shadowRoot.host; // The host itself scrolls
|
|
1278
|
-
this.spacer = this.shadowRoot.querySelector('.spacer');
|
|
1279
|
-
this.content = this.shadowRoot.querySelector('.content');
|
|
1280
|
-
this.onScroll = this.onScroll.bind(this);
|
|
1281
|
-
}
|
|
1282
|
-
static get observedAttributes() {
|
|
1283
|
-
return ['item-height'];
|
|
1284
|
-
}
|
|
1285
|
-
attributeChangedCallback(name, oldValue, newValue) {
|
|
1286
|
-
if (name === 'item-height') {
|
|
1287
|
-
this._itemHeight = parseInt(newValue, 10) || 50;
|
|
1288
|
-
this.renderVisible();
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
connectedCallback() {
|
|
1292
|
-
// Find the template provided by the user (Support both standard and branded tags)
|
|
1293
|
-
const templateTag = this.querySelector('template') || this.querySelector('mu-template');
|
|
1294
|
-
if (templateTag) {
|
|
1295
|
-
this._template = templateTag.innerHTML;
|
|
1296
|
-
}
|
|
1297
|
-
this.addEventListener('scroll', this.onScroll);
|
|
1298
|
-
// Wait for next frame to get initial height if not set
|
|
1299
|
-
requestAnimationFrame(() => this.renderVisible());
|
|
1300
|
-
}
|
|
1301
|
-
disconnectedCallback() {
|
|
1302
|
-
this.removeEventListener('scroll', this.onScroll);
|
|
1303
|
-
}
|
|
1304
|
-
set items(value) {
|
|
1305
|
-
this._items = value;
|
|
1306
|
-
this.renderVisible();
|
|
1307
|
-
}
|
|
1308
|
-
get items() { return this._items; }
|
|
1309
|
-
onScroll() {
|
|
1310
|
-
requestAnimationFrame(() => this.renderVisible());
|
|
1311
|
-
}
|
|
1312
|
-
renderVisible() {
|
|
1313
|
-
if (!this._items.length)
|
|
1314
|
-
return;
|
|
1315
|
-
const scrollTop = this.scrollTop;
|
|
1316
|
-
const hostHeight = this.clientHeight || 400; // Default fallback if not sized
|
|
1317
|
-
const totalHeight = this._items.length * this._itemHeight;
|
|
1318
|
-
this.spacer.style.height = `${totalHeight}px`;
|
|
1319
|
-
// Windowing Math
|
|
1320
|
-
const startIndex = Math.floor(scrollTop / this._itemHeight);
|
|
1321
|
-
const buffer = 5;
|
|
1322
|
-
const visibleCount = Math.ceil(hostHeight / this._itemHeight);
|
|
1323
|
-
const renderStart = Math.max(0, startIndex - buffer);
|
|
1324
|
-
const renderEnd = Math.min(this._items.length, startIndex + visibleCount + buffer);
|
|
1325
|
-
const startOffset = renderStart * this._itemHeight;
|
|
1326
|
-
this.content.style.transform = `translateY(${startOffset}px)`;
|
|
1327
|
-
// Render specific slice
|
|
1328
|
-
const visibleItems = this._items.slice(renderStart, renderEnd);
|
|
1329
|
-
// Simple string replacement template engine for the demo
|
|
1330
|
-
// In a real Mulan compilation, this would be an optimized ASTR render
|
|
1331
|
-
let html = '';
|
|
1332
|
-
visibleItems.forEach((item, index) => {
|
|
1333
|
-
const absoluteIndex = renderStart + index;
|
|
1334
|
-
// Basic mustache replacement {{ item.prop }}
|
|
1335
|
-
let rowHtml = this._template
|
|
1336
|
-
.replace(/{{\s*item\s*}}/g, String(item)) // {{ item }}
|
|
1337
|
-
.replace(/{{\s*index\s*}}/g, String(absoluteIndex)); // {{ index }}
|
|
1338
|
-
// Handle object properties: {{ item.name }}
|
|
1339
|
-
if (typeof item === 'object' && item !== null) {
|
|
1340
|
-
rowHtml = rowHtml.replace(/{{\s*item\.(\w+)\s*}}/g, (_, prop) => {
|
|
1341
|
-
return String(item[prop] || '');
|
|
1342
|
-
});
|
|
1343
|
-
}
|
|
1344
|
-
html += `<div style="height: ${this._itemHeight}px; overflow: hidden;">${rowHtml}</div>`;
|
|
1345
|
-
});
|
|
1346
|
-
this.content.innerHTML = html;
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1349
|
-
exports.MuInfinity = MuInfinity;
|
|
1350
|
-
// Register
|
|
1351
|
-
if (typeof customElements !== 'undefined' && !customElements.get('mu-infinity')) {
|
|
1352
|
-
customElements.define('mu-infinity', MuInfinity);
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
/***/ },
|
|
1357
|
-
|
|
1358
|
-
/***/ 482
|
|
1359
|
-
(__unused_webpack_module, exports, __webpack_require__) {
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1363
|
-
exports.MuStore = void 0;
|
|
1364
|
-
const reactive_1 = __webpack_require__(359);
|
|
1365
|
-
class MuStore {
|
|
1366
|
-
constructor(initialState, options) {
|
|
1367
|
-
this.subscribers = [];
|
|
1368
|
-
// Load from local storage if persist is true
|
|
1369
|
-
let loadedState = initialState;
|
|
1370
|
-
if (options === null || options === void 0 ? void 0 : options.persist) {
|
|
1371
|
-
const key = options.key || 'mulan-store';
|
|
1372
|
-
try {
|
|
1373
|
-
const stored = localStorage.getItem(key);
|
|
1374
|
-
if (stored) {
|
|
1375
|
-
loadedState = Object.assign(Object.assign({}, initialState), JSON.parse(stored));
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
catch (e) {
|
|
1379
|
-
console.error("Failed to load state", e);
|
|
1178
|
+
else if (setupResult && typeof setupResult === 'object') {
|
|
1179
|
+
// It's bindings
|
|
1180
|
+
Object.assign(this, setupResult);
|
|
1181
|
+
// We assume template is assigned to prototype by compiler
|
|
1380
1182
|
}
|
|
1381
|
-
// Auto-save effect
|
|
1382
|
-
(0, reactive_1.effect)(() => {
|
|
1383
|
-
localStorage.setItem(key, JSON.stringify(this.state));
|
|
1384
|
-
});
|
|
1385
1183
|
}
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
// Subscribe to changes
|
|
1389
|
-
subscribe(fn) {
|
|
1390
|
-
this.subscribers.push(fn);
|
|
1391
|
-
(0, reactive_1.effect)(() => {
|
|
1392
|
-
fn(this.state);
|
|
1393
|
-
});
|
|
1394
|
-
}
|
|
1395
|
-
// Action dispatcher pattern
|
|
1396
|
-
dispatch(action) {
|
|
1397
|
-
const result = action(this.state);
|
|
1398
|
-
if (result instanceof Promise) {
|
|
1399
|
-
result.then(() => {
|
|
1400
|
-
// Optional: Notify subscribers of async completion if needed manually?
|
|
1401
|
-
// But reactive() handles updates automatically.
|
|
1402
|
-
});
|
|
1184
|
+
template() {
|
|
1185
|
+
return '';
|
|
1403
1186
|
}
|
|
1404
|
-
}
|
|
1187
|
+
};
|
|
1405
1188
|
}
|
|
1406
|
-
exports.MuStore = MuStore;
|
|
1407
1189
|
|
|
1408
|
-
|
|
1409
|
-
/***/ },
|
|
1410
|
-
|
|
1411
|
-
/***/ 500
|
|
1412
|
-
(__unused_webpack_module, exports) {
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1416
|
-
exports.Security = void 0;
|
|
1190
|
+
;// ./src/security/sanitizer.ts
|
|
1417
1191
|
class Security {
|
|
1418
1192
|
/**
|
|
1419
1193
|
* IRON FORTRESS PROTOCOL
|
|
@@ -1466,16 +1240,9 @@ class Security {
|
|
|
1466
1240
|
});
|
|
1467
1241
|
}
|
|
1468
1242
|
}
|
|
1469
|
-
exports.Security = Security;
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
/***/ },
|
|
1473
|
-
|
|
1474
|
-
/***/ 580
|
|
1475
|
-
(__unused_webpack_module, exports, __webpack_require__) {
|
|
1476
|
-
|
|
1477
1243
|
|
|
1478
|
-
|
|
1244
|
+
;// ./src/router/index.ts
|
|
1245
|
+
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
1479
1246
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
1480
1247
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
1481
1248
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
@@ -1484,10 +1251,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
1484
1251
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1485
1252
|
});
|
|
1486
1253
|
};
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
const renderer_1 = __webpack_require__(619);
|
|
1490
|
-
const sanitizer_1 = __webpack_require__(500);
|
|
1254
|
+
|
|
1255
|
+
|
|
1491
1256
|
class MuRouter {
|
|
1492
1257
|
constructor(routes, rootContainer = null) {
|
|
1493
1258
|
this.currentPath = '';
|
|
@@ -1550,7 +1315,7 @@ class MuRouter {
|
|
|
1550
1315
|
const params = {};
|
|
1551
1316
|
paramNames.forEach((name, i) => {
|
|
1552
1317
|
// SECURE: Automatically sanitize all route parameters
|
|
1553
|
-
params[name] =
|
|
1318
|
+
params[name] = Security.sanitize(match[i + 1]);
|
|
1554
1319
|
});
|
|
1555
1320
|
return { route: r, params };
|
|
1556
1321
|
}
|
|
@@ -1565,7 +1330,7 @@ class MuRouter {
|
|
|
1565
1330
|
const hash = window.location.hash.slice(1) || '/';
|
|
1566
1331
|
const { route, params } = this.matchRoute(hash);
|
|
1567
1332
|
// Security Check: Validate URL to prevent malicious hash injection
|
|
1568
|
-
if (hash !== '/' && !
|
|
1333
|
+
if (hash !== '/' && !Security.validateUrl('http://dummy.com' + hash)) {
|
|
1569
1334
|
console.error("Security Alert: Malformed URL detected.");
|
|
1570
1335
|
return;
|
|
1571
1336
|
}
|
|
@@ -1634,19 +1399,19 @@ class MuRouter {
|
|
|
1634
1399
|
// Object Component (Simple SFC without script or Options API)
|
|
1635
1400
|
const html = componentToRender.template();
|
|
1636
1401
|
if (this.rootContainer)
|
|
1637
|
-
|
|
1402
|
+
render(html, this.rootContainer);
|
|
1638
1403
|
this.currentComponent = null;
|
|
1639
1404
|
}
|
|
1640
1405
|
else {
|
|
1641
1406
|
// Simple HTML string/template
|
|
1642
1407
|
if (this.rootContainer)
|
|
1643
|
-
|
|
1408
|
+
render(componentToRender, this.rootContainer);
|
|
1644
1409
|
this.currentComponent = null; // String templates don't have lifecycle instances
|
|
1645
1410
|
}
|
|
1646
1411
|
}
|
|
1647
1412
|
else {
|
|
1648
1413
|
if (this.rootContainer)
|
|
1649
|
-
|
|
1414
|
+
render('<div style="text-align:center; padding:50px;"><h1>404</h1><p>Page Not Found</p></div>', this.rootContainer);
|
|
1650
1415
|
}
|
|
1651
1416
|
});
|
|
1652
1417
|
}
|
|
@@ -1686,7 +1451,6 @@ class MuRouter {
|
|
|
1686
1451
|
}
|
|
1687
1452
|
}
|
|
1688
1453
|
}
|
|
1689
|
-
exports.MuRouter = MuRouter;
|
|
1690
1454
|
// --- Factory for Easy Usage ---
|
|
1691
1455
|
const createRouter = (options) => {
|
|
1692
1456
|
// Expose the router instance globally for <mu-link> to access
|
|
@@ -1696,7 +1460,6 @@ const createRouter = (options) => {
|
|
|
1696
1460
|
}
|
|
1697
1461
|
return router;
|
|
1698
1462
|
};
|
|
1699
|
-
exports.createRouter = createRouter;
|
|
1700
1463
|
// --- Web Component: <mu-link> ---
|
|
1701
1464
|
// Usage: <mu-link to="/about">About Us</mu-link>
|
|
1702
1465
|
const MuLinkBase = typeof HTMLElement !== 'undefined' ? HTMLElement : class {
|
|
@@ -1744,14 +1507,52 @@ if (typeof window !== 'undefined' && !customElements.get('mu-link')) {
|
|
|
1744
1507
|
customElements.define('mu-link', MuLink);
|
|
1745
1508
|
}
|
|
1746
1509
|
|
|
1510
|
+
;// ./src/store/index.ts
|
|
1747
1511
|
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1512
|
+
class MuStore {
|
|
1513
|
+
constructor(initialState, options) {
|
|
1514
|
+
this.subscribers = [];
|
|
1515
|
+
// Load from local storage if persist is true
|
|
1516
|
+
let loadedState = initialState;
|
|
1517
|
+
if (options === null || options === void 0 ? void 0 : options.persist) {
|
|
1518
|
+
const key = options.key || 'mulan-store';
|
|
1519
|
+
try {
|
|
1520
|
+
const stored = localStorage.getItem(key);
|
|
1521
|
+
if (stored) {
|
|
1522
|
+
loadedState = Object.assign(Object.assign({}, initialState), JSON.parse(stored));
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
catch (e) {
|
|
1526
|
+
console.error("Failed to load state", e);
|
|
1527
|
+
}
|
|
1528
|
+
// Auto-save effect
|
|
1529
|
+
effect(() => {
|
|
1530
|
+
localStorage.setItem(key, JSON.stringify(this.state));
|
|
1531
|
+
});
|
|
1532
|
+
}
|
|
1533
|
+
this.state = reactive(loadedState);
|
|
1534
|
+
}
|
|
1535
|
+
// Subscribe to changes
|
|
1536
|
+
subscribe(fn) {
|
|
1537
|
+
this.subscribers.push(fn);
|
|
1538
|
+
effect(() => {
|
|
1539
|
+
fn(this.state);
|
|
1540
|
+
});
|
|
1541
|
+
}
|
|
1542
|
+
// Action dispatcher pattern
|
|
1543
|
+
dispatch(action) {
|
|
1544
|
+
const result = action(this.state);
|
|
1545
|
+
if (result instanceof Promise) {
|
|
1546
|
+
result.then(() => {
|
|
1547
|
+
// Optional: Notify subscribers of async completion if needed manually?
|
|
1548
|
+
// But reactive() handles updates automatically.
|
|
1549
|
+
});
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1753
1553
|
|
|
1754
|
-
|
|
1554
|
+
;// ./src/core/query.ts
|
|
1555
|
+
var query_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
1755
1556
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
1756
1557
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
1757
1558
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
@@ -1760,16 +1561,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
1760
1561
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1761
1562
|
});
|
|
1762
1563
|
};
|
|
1763
|
-
|
|
1764
|
-
exports.useMutation = exports.useQuery = void 0;
|
|
1765
|
-
const reactive_1 = __webpack_require__(359);
|
|
1564
|
+
|
|
1766
1565
|
function useQuery(queryFn, options = { enabled: true }) {
|
|
1767
|
-
const state =
|
|
1566
|
+
const state = reactive({
|
|
1768
1567
|
data: null,
|
|
1769
1568
|
isLoading: false,
|
|
1770
1569
|
error: null
|
|
1771
1570
|
});
|
|
1772
|
-
const execute = () =>
|
|
1571
|
+
const execute = () => query_awaiter(this, void 0, void 0, function* () {
|
|
1773
1572
|
state.isLoading = true;
|
|
1774
1573
|
state.error = null;
|
|
1775
1574
|
try {
|
|
@@ -1785,7 +1584,7 @@ function useQuery(queryFn, options = { enabled: true }) {
|
|
|
1785
1584
|
});
|
|
1786
1585
|
if (options.enabled) {
|
|
1787
1586
|
// Run automatically
|
|
1788
|
-
|
|
1587
|
+
effect(() => {
|
|
1789
1588
|
// Basic effect wrapper to allow reactivity if queryFn relies on signals
|
|
1790
1589
|
execute();
|
|
1791
1590
|
});
|
|
@@ -1797,14 +1596,13 @@ function useQuery(queryFn, options = { enabled: true }) {
|
|
|
1797
1596
|
refetch: execute
|
|
1798
1597
|
};
|
|
1799
1598
|
}
|
|
1800
|
-
exports.useQuery = useQuery;
|
|
1801
1599
|
function useMutation(mutationFn) {
|
|
1802
|
-
const state =
|
|
1600
|
+
const state = reactive({
|
|
1803
1601
|
data: null,
|
|
1804
1602
|
isLoading: false,
|
|
1805
1603
|
error: null
|
|
1806
1604
|
});
|
|
1807
|
-
const mutate = (args) =>
|
|
1605
|
+
const mutate = (args) => query_awaiter(this, void 0, void 0, function* () {
|
|
1808
1606
|
state.isLoading = true;
|
|
1809
1607
|
state.error = null;
|
|
1810
1608
|
try {
|
|
@@ -1827,675 +1625,212 @@ function useMutation(mutationFn) {
|
|
|
1827
1625
|
mutate
|
|
1828
1626
|
};
|
|
1829
1627
|
}
|
|
1830
|
-
exports.useMutation = useMutation;
|
|
1831
|
-
|
|
1832
1628
|
|
|
1833
|
-
|
|
1629
|
+
;// ./src/core/quantum.ts
|
|
1834
1630
|
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1631
|
+
/**
|
|
1632
|
+
* Mulan Quantum (ASTR-Q+) Core
|
|
1633
|
+
* Advanced Simulation Engine for multi-qubit registers and entanglement.
|
|
1634
|
+
*/
|
|
1635
|
+
// -- GLOBAL CONTEXT FOR QUANTUM CONTROL --
|
|
1636
|
+
// Defined at top to ensure visibility for muGate
|
|
1637
|
+
let activeControls = [];
|
|
1638
|
+
/**
|
|
1639
|
+
* Creates a quantum register of size n.
|
|
1640
|
+
* State vector will have 2^n amplitudes.
|
|
1641
|
+
*/
|
|
1642
|
+
function muRegister(n) {
|
|
1643
|
+
const numStates = Math.pow(2, n);
|
|
1644
|
+
const amplitudes = new Array(numStates).fill(0).map((_, i) => ({
|
|
1645
|
+
re: i === 0 ? 1 : 0,
|
|
1646
|
+
im: 0
|
|
1647
|
+
}));
|
|
1648
|
+
return muState({
|
|
1649
|
+
value: {
|
|
1650
|
+
size: n,
|
|
1651
|
+
amplitudes
|
|
1652
|
+
}
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
/**
|
|
1656
|
+
* Backward compatible muQubit (Single Qubit Register)
|
|
1657
|
+
*/
|
|
1658
|
+
function muQubit(initial = 0) {
|
|
1659
|
+
const q = muRegister(1);
|
|
1660
|
+
if (initial === 1) {
|
|
1661
|
+
muGate(q, 'X', 0);
|
|
1847
1662
|
}
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1663
|
+
// Add compatibility properties for Phase 1 components
|
|
1664
|
+
// These properties are getters that dynamically access the amplitudes array
|
|
1665
|
+
Object.defineProperty(q.value, 'alpha', { get: () => q.value.amplitudes[0] });
|
|
1666
|
+
Object.defineProperty(q.value, 'beta', { get: () => q.value.amplitudes[1] });
|
|
1667
|
+
return q;
|
|
1668
|
+
}
|
|
1669
|
+
/**
|
|
1670
|
+
* Internal helper to update register state while maintaining compatibility
|
|
1671
|
+
*/
|
|
1672
|
+
function updateState(reg, newState) {
|
|
1673
|
+
if (newState.size === 1) {
|
|
1674
|
+
// Re-inject compatibility getters for muQubit users
|
|
1675
|
+
Object.defineProperty(newState, 'alpha', {
|
|
1676
|
+
get: () => newState.amplitudes[0],
|
|
1677
|
+
configurable: true,
|
|
1678
|
+
enumerable: true
|
|
1679
|
+
});
|
|
1680
|
+
Object.defineProperty(newState, 'beta', {
|
|
1681
|
+
get: () => newState.amplitudes[1],
|
|
1682
|
+
configurable: true,
|
|
1683
|
+
enumerable: true
|
|
1684
|
+
});
|
|
1857
1685
|
}
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1686
|
+
reg.value = newState;
|
|
1687
|
+
}
|
|
1688
|
+
function muGate(reg, type, target = 0, control) {
|
|
1689
|
+
const state = reg.value;
|
|
1690
|
+
const n = state.size;
|
|
1691
|
+
const amplitudes = state.amplitudes;
|
|
1692
|
+
const newAmps = amplitudes.map(a => (Object.assign({}, a)));
|
|
1693
|
+
// Prepare Effective Control (Explicit Arguments + Global Context)
|
|
1694
|
+
const effectiveControl = [...(control === undefined ? [] : (Array.isArray(control) ? control : [control])), ...activeControls];
|
|
1695
|
+
// Helper: Check if all control bits are 1
|
|
1696
|
+
const checkControl = (index, ctrl) => {
|
|
1697
|
+
if (ctrl === undefined || (Array.isArray(ctrl) && ctrl.length === 0))
|
|
1698
|
+
return true;
|
|
1699
|
+
const ctrls = Array.isArray(ctrl) ? ctrl : [ctrl];
|
|
1700
|
+
return ctrls.every(c => ((index >> c) & 1) === 1);
|
|
1701
|
+
};
|
|
1702
|
+
// SWAP Gate (Unique case: affects 2 targets)
|
|
1703
|
+
if (type === 'SWAP') {
|
|
1704
|
+
const t1 = target;
|
|
1705
|
+
const t2 = control; // SWAP uses control arg as second target
|
|
1706
|
+
// Iterate only half to avoid double swapping
|
|
1707
|
+
for (let i = 0; i < amplitudes.length; i++) {
|
|
1708
|
+
// Check active controls for SWAP too
|
|
1709
|
+
if (activeControls.length > 0 && !checkControl(i, activeControls))
|
|
1710
|
+
continue;
|
|
1711
|
+
const bit1 = (i >> t1) & 1;
|
|
1712
|
+
const bit2 = (i >> t2) & 1;
|
|
1713
|
+
if (bit1 !== bit2) {
|
|
1714
|
+
// Determine the swap partner index
|
|
1715
|
+
// If i has (0,1), partner has (1,0) at those positions
|
|
1716
|
+
const partner = i ^ (1 << t1) ^ (1 << t2);
|
|
1717
|
+
if (i < partner) {
|
|
1718
|
+
const temp = newAmps[i];
|
|
1719
|
+
newAmps[i] = newAmps[partner];
|
|
1720
|
+
newAmps[partner] = temp;
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1862
1723
|
}
|
|
1724
|
+
updateState(reg, Object.assign(Object.assign({}, state), { amplitudes: newAmps }));
|
|
1725
|
+
return;
|
|
1863
1726
|
}
|
|
1864
|
-
//
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1727
|
+
// Standard Single-Qubit & Controlled Gates
|
|
1728
|
+
if (type === 'H') {
|
|
1729
|
+
const s = 1 / Math.sqrt(2);
|
|
1730
|
+
const processed = new Set();
|
|
1731
|
+
for (let i = 0; i < state.amplitudes.length; i++) {
|
|
1732
|
+
if (processed.has(i))
|
|
1733
|
+
continue;
|
|
1734
|
+
// Check Controls first
|
|
1735
|
+
if (!checkControl(i, effectiveControl))
|
|
1736
|
+
continue;
|
|
1737
|
+
const targetBit = (i >> target) & 1;
|
|
1738
|
+
const pairedIndex = targetBit ? (i & ~(1 << target)) : (i | (1 << target));
|
|
1739
|
+
const a = state.amplitudes[i];
|
|
1740
|
+
const b = state.amplitudes[pairedIndex];
|
|
1741
|
+
if (targetBit === 0) {
|
|
1742
|
+
newAmps[i] = { re: s * (a.re + b.re), im: s * (a.im + b.im) };
|
|
1743
|
+
newAmps[pairedIndex] = { re: s * (a.re - b.re), im: s * (a.im - b.im) };
|
|
1744
|
+
}
|
|
1745
|
+
else {
|
|
1746
|
+
newAmps[pairedIndex] = { re: s * (b.re + a.re), im: s * (b.im + a.im) };
|
|
1747
|
+
newAmps[i] = { re: s * (b.re - a.re), im: s * (b.im - a.im) };
|
|
1748
|
+
}
|
|
1749
|
+
processed.add(i);
|
|
1750
|
+
processed.add(pairedIndex);
|
|
1751
|
+
}
|
|
1871
1752
|
}
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1753
|
+
else if (type === 'X' || type === 'CNOT') {
|
|
1754
|
+
// CNOT is just Controlled-X
|
|
1755
|
+
for (let i = 0; i < amplitudes.length; i++) {
|
|
1756
|
+
if (!checkControl(i, effectiveControl))
|
|
1757
|
+
continue;
|
|
1758
|
+
const targetBit = (i >> target) & 1;
|
|
1759
|
+
const pairedIndex = targetBit ? (i & ~(1 << target)) : (i | (1 << target));
|
|
1760
|
+
if (i < pairedIndex) {
|
|
1761
|
+
const temp = newAmps[i];
|
|
1762
|
+
newAmps[i] = newAmps[pairedIndex];
|
|
1763
|
+
newAmps[pairedIndex] = temp;
|
|
1764
|
+
}
|
|
1876
1765
|
}
|
|
1877
1766
|
}
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
return;
|
|
1888
|
-
// Assume Single Qubit for Visualizer (Index 0 if passed a register)
|
|
1889
|
-
// If passed a register, we visualize the first qubit's logical projection (partial trace simplified)
|
|
1890
|
-
// Or assume input IS a specific qubit projection?
|
|
1891
|
-
// For simplified demo, we assume the register is size 1 OR we visualize Q0 of the register.
|
|
1892
|
-
const amps = state.amplitudes;
|
|
1893
|
-
// Support 1-qubit visualization from N-qubit register requires partial trace.
|
|
1894
|
-
// For now, let's assume the user passes a 1-qubit register OR we visualize index 0.
|
|
1895
|
-
// |psi> = a|0> + b|1>
|
|
1896
|
-
// a = amps[0] (re, im)
|
|
1897
|
-
// b = amps[1] (re, im)
|
|
1898
|
-
// Dealing with multi-qubit registers (naive projection for visualization):
|
|
1899
|
-
// We sum up probabilities for 0xxxx vs 1xxxx to get Z-axis.
|
|
1900
|
-
// This is "marginal probability".
|
|
1901
|
-
let p0 = 0;
|
|
1902
|
-
let p1 = 0;
|
|
1903
|
-
// Calculate Probabilities
|
|
1904
|
-
for (let i = 0; i < amps.length; i++) {
|
|
1905
|
-
const mag = amps[i].re * amps[i].re + amps[i].im * amps[i].im;
|
|
1906
|
-
if ((i & 1) === 0)
|
|
1907
|
-
p0 += mag;
|
|
1908
|
-
else
|
|
1909
|
-
p1 += mag;
|
|
1767
|
+
else if (type === 'Z' || type === 'CZ') {
|
|
1768
|
+
// Z and CZ are Phase Flips
|
|
1769
|
+
for (let i = 0; i < amplitudes.length; i++) {
|
|
1770
|
+
if (!checkControl(i, effectiveControl))
|
|
1771
|
+
continue;
|
|
1772
|
+
const targetBit = (i >> target) & 1;
|
|
1773
|
+
// Z Gate acts on |1>
|
|
1774
|
+
if (targetBit === 1) {
|
|
1775
|
+
newAmps[i] = { re: -amplitudes[i].re, im: -amplitudes[i].im };
|
|
1910
1776
|
}
|
|
1911
|
-
|
|
1912
|
-
// P0 = cos^2(theta/2) -> theta = 2 * acos(sqrt(P0))
|
|
1913
|
-
const theta = 2 * Math.acos(Math.min(1, Math.sqrt(p0)));
|
|
1914
|
-
// Phi?
|
|
1915
|
-
// Phase is relative phase between |0> and |1>.
|
|
1916
|
-
// We can look at the phase of the '1' component relative to '0'.
|
|
1917
|
-
// Simple approach: Look at amps[1] phase vs amps[0] phase.
|
|
1918
|
-
// But with entanglement, pure state phase is tricky.
|
|
1919
|
-
// Let's implement full density matrix if needed, but for now:
|
|
1920
|
-
// naive: atan2(amps[1].im, amps[1].re) - atan2(amps[0].im, amps[0].re)
|
|
1921
|
-
// We use the first pair (0 and 1) as proxy if multiple.
|
|
1922
|
-
const a0 = amps[0];
|
|
1923
|
-
const a1 = amps[1]; // Valid for N>=1
|
|
1924
|
-
const phase0 = Math.atan2(a0.im, a0.re);
|
|
1925
|
-
const phase1 = Math.atan2(a1.im, a1.re);
|
|
1926
|
-
let phi = phase1 - phase0;
|
|
1927
|
-
// Update Arrow
|
|
1928
|
-
this.updateArrow(theta, phi);
|
|
1929
|
-
});
|
|
1777
|
+
}
|
|
1930
1778
|
}
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
// Bloch X+ (|+>) -> CSS Z+ (Front)
|
|
1949
|
-
// Transform:
|
|
1950
|
-
// rotateY(phi) ? No, phi rotates around Z-axis (Vertical).
|
|
1951
|
-
// theta rotates from Z-axis down.
|
|
1952
|
-
// CSS:
|
|
1953
|
-
// rotateY(phi) -> Rotates around Vertical axis.
|
|
1954
|
-
// rotateZ(theta) -> Rotates "down" from up?
|
|
1955
|
-
// Let's simplify:
|
|
1956
|
-
// transform: rotateY(${phi}rad) rotateZ(${theta}rad)
|
|
1957
|
-
// Note: CSS rotations order matters.
|
|
1958
|
-
const degTheta = theta * (180 / Math.PI);
|
|
1959
|
-
const degPhi = phi * (180 / Math.PI);
|
|
1960
|
-
// Adjustment for visual alignment
|
|
1961
|
-
this._arrow.style.transform = `rotateY(${degPhi}deg) rotateZ(${degTheta}deg)`;
|
|
1962
|
-
// Color based on state
|
|
1963
|
-
const isSuperposition = Math.abs(theta - Math.PI / 2) < 0.1;
|
|
1964
|
-
this._arrow.style.backgroundColor = isSuperposition ? '#00ffff' : '#ff00ff';
|
|
1965
|
-
}
|
|
1966
|
-
render() {
|
|
1967
|
-
if (!this.shadowRoot)
|
|
1968
|
-
return;
|
|
1969
|
-
const size = this.getAttribute('size') || '200';
|
|
1970
|
-
this.shadowRoot.innerHTML = `
|
|
1971
|
-
<style>
|
|
1972
|
-
:host {
|
|
1973
|
-
display: inline-block;
|
|
1974
|
-
perspective: 1000px;
|
|
1975
|
-
}
|
|
1976
|
-
.sphere-container {
|
|
1977
|
-
width: ${size}px;
|
|
1978
|
-
height: ${size}px;
|
|
1979
|
-
position: relative;
|
|
1980
|
-
transform-style: preserve-3d;
|
|
1981
|
-
margin: 0 auto;
|
|
1982
|
-
}
|
|
1983
|
-
.sphere {
|
|
1984
|
-
width: 100%;
|
|
1985
|
-
height: 100%;
|
|
1986
|
-
border-radius: 50%;
|
|
1987
|
-
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
1988
|
-
position: absolute;
|
|
1989
|
-
background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.1), rgba(0, 0, 0, 0.8));
|
|
1990
|
-
box-shadow: inset 0 0 20px rgba(255, 255, 255, 0.05);
|
|
1991
|
-
transform: rotateX(15deg) rotateY(15deg); /* Initial tilt for view */
|
|
1992
|
-
}
|
|
1993
|
-
/* Equator Ring */
|
|
1994
|
-
.equator {
|
|
1995
|
-
position: absolute;
|
|
1996
|
-
top: 50%;
|
|
1997
|
-
left: 0;
|
|
1998
|
-
width: 100%;
|
|
1999
|
-
height: 100%;
|
|
2000
|
-
border: 1px dashed rgba(255, 255, 255, 0.3);
|
|
2001
|
-
border-radius: 50%;
|
|
2002
|
-
transform: rotateX(90deg);
|
|
2003
|
-
pointer-events: none;
|
|
2004
|
-
}
|
|
2005
|
-
/* Axis Lines */
|
|
2006
|
-
.axis {
|
|
2007
|
-
position: absolute;
|
|
2008
|
-
background: rgba(255, 255, 255, 0.1);
|
|
2009
|
-
}
|
|
2010
|
-
.z-axis { width: 2px; height: 100%; left: 50%; top: 0; }
|
|
2011
|
-
|
|
2012
|
-
/* The Quantum Arrow */
|
|
2013
|
-
.arrow-container {
|
|
2014
|
-
position: absolute;
|
|
2015
|
-
top: 50%;
|
|
2016
|
-
left: 50%;
|
|
2017
|
-
width: 0;
|
|
2018
|
-
height: 0;
|
|
2019
|
-
transform-style: preserve-3d;
|
|
2020
|
-
transform: rotateX(15deg) rotateY(15deg); /* Match sphere tilt */
|
|
2021
|
-
}
|
|
2022
|
-
|
|
2023
|
-
.arrow-pivot {
|
|
2024
|
-
position: absolute;
|
|
2025
|
-
top: 0;
|
|
2026
|
-
left: 0;
|
|
2027
|
-
width: 4px;
|
|
2028
|
-
height: 50%; /* Length of radius */
|
|
2029
|
-
/* Pivot logic: we want to rotate around the center point */
|
|
2030
|
-
/* CSS Default transform-origin is 50% 50% */
|
|
2031
|
-
/* We construct the arrow such that it points UP from center */
|
|
2032
|
-
}
|
|
2033
|
-
|
|
2034
|
-
.arrow-rod {
|
|
2035
|
-
width: 4px;
|
|
2036
|
-
height: ${parseInt(size) / 2 - 10}px;
|
|
2037
|
-
background: #ff00ff;
|
|
2038
|
-
position: absolute;
|
|
2039
|
-
bottom: 0;
|
|
2040
|
-
left: -2px;
|
|
2041
|
-
transform-origin: bottom center;
|
|
2042
|
-
transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275), background-color 0.3s;
|
|
2043
|
-
border-radius: 2px;
|
|
2044
|
-
box-shadow: 0 0 10px currentColor;
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
|
-
.arrow-head {
|
|
2048
|
-
width: 0;
|
|
2049
|
-
height: 0;
|
|
2050
|
-
border-left: 6px solid transparent;
|
|
2051
|
-
border-right: 6px solid transparent;
|
|
2052
|
-
border-bottom: 12px solid #ff00ff;
|
|
2053
|
-
position: absolute;
|
|
2054
|
-
top: -10px;
|
|
2055
|
-
left: -6px;
|
|
2056
|
-
}
|
|
2057
|
-
|
|
2058
|
-
.label {
|
|
2059
|
-
position: absolute;
|
|
2060
|
-
color: #aaa;
|
|
2061
|
-
font-family: monospace;
|
|
2062
|
-
font-size: 10px;
|
|
2063
|
-
}
|
|
2064
|
-
.label-0 { top: 5px; left: 50%; transform: translateX(-50%); }
|
|
2065
|
-
.label-1 { bottom: 5px; left: 50%; transform: translateX(-50%); }
|
|
2066
|
-
</style>
|
|
2067
|
-
|
|
2068
|
-
<div class="sphere-container">
|
|
2069
|
-
<div class="sphere">
|
|
2070
|
-
<div class="equator"></div>
|
|
2071
|
-
<div class="axis z-axis"></div>
|
|
2072
|
-
<div class="label label-0">|0></div>
|
|
2073
|
-
<div class="label label-1">|1></div>
|
|
2074
|
-
</div>
|
|
2075
|
-
|
|
2076
|
-
<div class="arrow-container">
|
|
2077
|
-
<!-- The rod is the actual rotating element -->
|
|
2078
|
-
<div class="arrow-rod">
|
|
2079
|
-
<div class="arrow-head"></div>
|
|
2080
|
-
</div>
|
|
2081
|
-
</div>
|
|
2082
|
-
</div>
|
|
2083
|
-
`;
|
|
2084
|
-
this._container = this.shadowRoot.querySelector('.sphere-container');
|
|
2085
|
-
this._arrow = this.shadowRoot.querySelector('.arrow-rod');
|
|
2086
|
-
// Re-init reactivity if qubit was set before render
|
|
2087
|
-
if (this._qubit)
|
|
2088
|
-
this.initReactivity();
|
|
2089
|
-
}
|
|
2090
|
-
}
|
|
2091
|
-
exports.MuBlochSphereElement = MuBlochSphereElement;
|
|
2092
|
-
// Register the custom element
|
|
2093
|
-
if (typeof customElements !== 'undefined') {
|
|
2094
|
-
customElements.define('mu-bloch-sphere', MuBlochSphereElement);
|
|
2095
|
-
}
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
/***/ },
|
|
2099
|
-
|
|
2100
|
-
/***/ 619
|
|
2101
|
-
(__unused_webpack_module, exports) {
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2105
|
-
exports.sanitize = exports.hydrate = exports.render = void 0;
|
|
2106
|
-
function render(template, container) {
|
|
2107
|
-
// Focus Preservation (The "Mulan Glance" Technique)
|
|
2108
|
-
let focusedId = null;
|
|
2109
|
-
let selectionStart = null;
|
|
2110
|
-
let selectionEnd = null;
|
|
2111
|
-
let preservedValue = null;
|
|
2112
|
-
if (document.activeElement && container.contains(document.activeElement)) {
|
|
2113
|
-
const el = document.activeElement;
|
|
2114
|
-
if (el.hasAttribute('data-mu-id')) {
|
|
2115
|
-
focusedId = el.getAttribute('data-mu-id');
|
|
2116
|
-
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
|
|
2117
|
-
selectionStart = el.selectionStart;
|
|
2118
|
-
selectionEnd = el.selectionEnd;
|
|
2119
|
-
preservedValue = el.value;
|
|
2120
|
-
}
|
|
2121
|
-
}
|
|
2122
|
-
}
|
|
2123
|
-
// [Anima] 1. Pre-Update: Snapshot positions of animated elements
|
|
2124
|
-
const animationSnapshots = new Map();
|
|
2125
|
-
// Only query if we might have animations to save perf
|
|
2126
|
-
if (typeof template === 'string' && template.includes('mu-animate')) {
|
|
2127
|
-
const animatedEls = container.querySelectorAll('[mu-animate]');
|
|
2128
|
-
animatedEls.forEach(el => {
|
|
2129
|
-
const key = el.getAttribute('mu-key') || el.id;
|
|
2130
|
-
if (key) {
|
|
2131
|
-
animationSnapshots.set(key, el.getBoundingClientRect());
|
|
2132
|
-
}
|
|
2133
|
-
});
|
|
2134
|
-
}
|
|
2135
|
-
if (typeof template === 'string') {
|
|
2136
|
-
container.innerHTML = template;
|
|
2137
|
-
}
|
|
2138
|
-
else {
|
|
2139
|
-
container.innerHTML = '';
|
|
2140
|
-
container.appendChild(template);
|
|
2141
|
-
}
|
|
2142
|
-
// Restore Focus and Value
|
|
2143
|
-
if (focusedId) {
|
|
2144
|
-
const el = container.querySelector(`[data-mu-id="${focusedId}"]`);
|
|
2145
|
-
if (el) {
|
|
2146
|
-
// Restore value first to ensure cursor positioning works correctly
|
|
2147
|
-
if (preservedValue !== null && (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)) {
|
|
2148
|
-
el.value = preservedValue;
|
|
2149
|
-
}
|
|
2150
|
-
el.focus();
|
|
2151
|
-
if ((el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) && selectionStart !== null) {
|
|
2152
|
-
try {
|
|
2153
|
-
el.setSelectionRange(selectionStart, selectionEnd);
|
|
2154
|
-
}
|
|
2155
|
-
catch (e) {
|
|
2156
|
-
// input types that don't support selection (e.g. number/email) might throw
|
|
2157
|
-
}
|
|
2158
|
-
}
|
|
2159
|
-
}
|
|
2160
|
-
}
|
|
2161
|
-
// [Anima] 2. Post-Update: FLIP (First, Last, Invert, Play)
|
|
2162
|
-
if (animationSnapshots.size > 0) {
|
|
2163
|
-
const newAnimatedEls = container.querySelectorAll('[mu-animate]');
|
|
2164
|
-
newAnimatedEls.forEach(el => {
|
|
2165
|
-
const key = el.getAttribute('mu-key') || el.id;
|
|
2166
|
-
if (key && animationSnapshots.has(key)) {
|
|
2167
|
-
const oldRect = animationSnapshots.get(key);
|
|
2168
|
-
const newRect = el.getBoundingClientRect();
|
|
2169
|
-
const dx = oldRect.left - newRect.left;
|
|
2170
|
-
const dy = oldRect.top - newRect.top;
|
|
2171
|
-
// Only animate if moved
|
|
2172
|
-
if (dx !== 0 || dy !== 0) {
|
|
2173
|
-
const htmlEl = el;
|
|
2174
|
-
// INVERT: Move it back to where it was instantly
|
|
2175
|
-
htmlEl.style.transform = `translate(${dx}px, ${dy}px)`;
|
|
2176
|
-
htmlEl.style.transition = 'none';
|
|
2177
|
-
// PLAY: Animate to zero (new position)
|
|
2178
|
-
requestAnimationFrame(() => {
|
|
2179
|
-
// Force reflow
|
|
2180
|
-
// void htmlEl.offsetWidth;
|
|
2181
|
-
htmlEl.style.transition = 'transform 500ms cubic-bezier(0.25, 0.8, 0.25, 1)';
|
|
2182
|
-
htmlEl.style.transform = '';
|
|
2183
|
-
});
|
|
2184
|
-
}
|
|
2185
|
-
}
|
|
2186
|
-
});
|
|
1779
|
+
else if (type === 'Y') {
|
|
1780
|
+
// Y: |0> -> i|1>, |1> -> -i|0>
|
|
1781
|
+
for (let i = 0; i < amplitudes.length; i++) {
|
|
1782
|
+
if (!checkControl(i, effectiveControl))
|
|
1783
|
+
continue;
|
|
1784
|
+
const targetBit = (i >> target) & 1;
|
|
1785
|
+
const pairedIndex = targetBit ? (i & ~(1 << target)) : (i | (1 << target));
|
|
1786
|
+
if (i < pairedIndex) {
|
|
1787
|
+
// We process pairs (i, pairedIndex) where i has 0 at target, paired has 1
|
|
1788
|
+
const a = newAmps[i]; // Coeff of |0>
|
|
1789
|
+
const b = newAmps[pairedIndex]; // Coeff of |1>
|
|
1790
|
+
// New |0> = -i * Old |1>
|
|
1791
|
+
newAmps[i] = { re: b.im, im: -b.re };
|
|
1792
|
+
// New |1> = i * Old |0>
|
|
1793
|
+
newAmps[pairedIndex] = { re: -a.im, im: a.re };
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
2187
1796
|
}
|
|
1797
|
+
updateState(reg, Object.assign(Object.assign({}, state), { amplitudes: newAmps }));
|
|
2188
1798
|
}
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
1799
|
+
/**
|
|
1800
|
+
* Mulan Search Logic (Grover's Operator)
|
|
1801
|
+
* Automatically constructs a multi-controlled Phase Flip (Z) for a specific target state.
|
|
1802
|
+
* This is the core of the "Quantum Switch" or "Quantum Search" capability.
|
|
1803
|
+
* @param reg Quantum Register
|
|
1804
|
+
* @param targetState The integer state to "search" and mark (e.g. 2 for |10>)
|
|
1805
|
+
*/
|
|
1806
|
+
function muSearch(reg, targetState) {
|
|
1807
|
+
const n = reg.value.size;
|
|
1808
|
+
const controls = [];
|
|
1809
|
+
// 1. Identify which bits are 0 and need wrapping with X gates
|
|
1810
|
+
// Logic: To mark |010>, we want C-C-Z to trigger on 111.
|
|
1811
|
+
// So we apply X to bits that are 0, then C-C-Z, then X again.
|
|
1812
|
+
// We treat the last bit as the 'target' for the Z gate, rest as controls
|
|
1813
|
+
const targetQubit = n - 1;
|
|
1814
|
+
for (let i = 0; i < n; i++) {
|
|
1815
|
+
const bit = (targetState >> i) & 1;
|
|
1816
|
+
if (i === targetQubit) {
|
|
1817
|
+
// If target bit logic requires 0, we flip it to 1 for the Z gate to work
|
|
1818
|
+
if (bit === 0)
|
|
1819
|
+
muGate(reg, 'X', i);
|
|
2198
1820
|
}
|
|
2199
1821
|
else {
|
|
2200
|
-
|
|
1822
|
+
controls.push(i);
|
|
1823
|
+
if (bit === 0)
|
|
1824
|
+
muGate(reg, 'X', i);
|
|
2201
1825
|
}
|
|
2202
1826
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
function sanitize(str) {
|
|
2211
|
-
// Check if we are in a browser environment
|
|
2212
|
-
if (typeof document !== 'undefined') {
|
|
2213
|
-
const temp = document.createElement('div');
|
|
2214
|
-
temp.textContent = str;
|
|
2215
|
-
return temp.innerHTML;
|
|
2216
|
-
}
|
|
2217
|
-
// Simple SSR fallback sanitizer (rudimentary)
|
|
2218
|
-
return str.replace(/&/g, "&")
|
|
2219
|
-
.replace(/</g, "<")
|
|
2220
|
-
.replace(/>/g, ">")
|
|
2221
|
-
.replace(/"/g, """)
|
|
2222
|
-
.replace(/'/g, "'");
|
|
2223
|
-
}
|
|
2224
|
-
exports.sanitize = sanitize;
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
/***/ },
|
|
2228
|
-
|
|
2229
|
-
/***/ 678
|
|
2230
|
-
(__unused_webpack_module, exports) {
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2234
|
-
exports.renderToString = void 0;
|
|
2235
|
-
/**
|
|
2236
|
-
* Renders a Mulan component to a static HTML string with a resumability envelope.
|
|
2237
|
-
*/
|
|
2238
|
-
function renderToString(ComponentClass, props = {}) {
|
|
2239
|
-
// 1. Initialize component in a virtual container (not used for DOM)
|
|
2240
|
-
// On server, we mock the container or just pass a dummy object
|
|
2241
|
-
const dummyContainer = {
|
|
2242
|
-
querySelector: () => null,
|
|
2243
|
-
querySelectorAll: () => [],
|
|
2244
|
-
appendChild: () => { },
|
|
2245
|
-
removeChild: () => { },
|
|
2246
|
-
getAttribute: () => null
|
|
2247
|
-
};
|
|
2248
|
-
const instance = new ComponentClass(dummyContainer);
|
|
2249
|
-
// Pass props
|
|
2250
|
-
Object.assign(instance, props);
|
|
2251
|
-
// 2. Render to HTML
|
|
2252
|
-
if (typeof instance.renderToString !== 'function') {
|
|
2253
|
-
throw new Error(`Component ${ComponentClass.name} was not compiled for SSR.`);
|
|
2254
|
-
}
|
|
2255
|
-
const html = instance.renderToString();
|
|
2256
|
-
// 3. Extract State for Resumability
|
|
2257
|
-
// We only want to serialize data that was exposed in setup()
|
|
2258
|
-
// For now, we'll serialize any property on the instance that isn't internal
|
|
2259
|
-
const state = {};
|
|
2260
|
-
for (const key in instance) {
|
|
2261
|
-
if (key.startsWith('_') || key === 'container' || key === 'state' || typeof instance[key] === 'function')
|
|
2262
|
-
continue;
|
|
2263
|
-
const value = instance[key];
|
|
2264
|
-
// Handle signals specifically
|
|
2265
|
-
if (value && typeof value === 'object' && 'value' in value) {
|
|
2266
|
-
state[key] = value.value;
|
|
2267
|
-
}
|
|
2268
|
-
else {
|
|
2269
|
-
state[key] = value;
|
|
2270
|
-
}
|
|
2271
|
-
}
|
|
2272
|
-
// 4. Construct Resumability Envelope
|
|
2273
|
-
const stateScript = `<script type="mulan/state" data-mu-uid="${instance.$uid}">${JSON.stringify(state)}</script>`;
|
|
2274
|
-
const envelope = `<div data-mu-root="${instance.$uid}">${html}${stateScript}</div>`;
|
|
2275
|
-
return {
|
|
2276
|
-
html,
|
|
2277
|
-
state,
|
|
2278
|
-
envelope
|
|
2279
|
-
};
|
|
2280
|
-
}
|
|
2281
|
-
exports.renderToString = renderToString;
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
/***/ },
|
|
2285
|
-
|
|
2286
|
-
/***/ 679
|
|
2287
|
-
(__unused_webpack_module, exports, __webpack_require__) {
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2291
|
-
exports.muSwitch = exports.muControl = exports.muParallel = exports.muMeasure = exports.muTeleport = exports.muEntangle = exports.muSearch = exports.muGate = exports.muQubit = exports.muRegister = exports.activeControls = void 0;
|
|
2292
|
-
const hooks_1 = __webpack_require__(166);
|
|
2293
|
-
/**
|
|
2294
|
-
* Mulan Quantum (ASTR-Q+) Core
|
|
2295
|
-
* Advanced Simulation Engine for multi-qubit registers and entanglement.
|
|
2296
|
-
*/
|
|
2297
|
-
// -- GLOBAL CONTEXT FOR QUANTUM CONTROL --
|
|
2298
|
-
// Defined at top to ensure visibility for muGate
|
|
2299
|
-
exports.activeControls = [];
|
|
2300
|
-
/**
|
|
2301
|
-
* Creates a quantum register of size n.
|
|
2302
|
-
* State vector will have 2^n amplitudes.
|
|
2303
|
-
*/
|
|
2304
|
-
function muRegister(n) {
|
|
2305
|
-
const numStates = Math.pow(2, n);
|
|
2306
|
-
const amplitudes = new Array(numStates).fill(0).map((_, i) => ({
|
|
2307
|
-
re: i === 0 ? 1 : 0,
|
|
2308
|
-
im: 0
|
|
2309
|
-
}));
|
|
2310
|
-
return (0, hooks_1.muState)({
|
|
2311
|
-
value: {
|
|
2312
|
-
size: n,
|
|
2313
|
-
amplitudes
|
|
2314
|
-
}
|
|
2315
|
-
});
|
|
2316
|
-
}
|
|
2317
|
-
exports.muRegister = muRegister;
|
|
2318
|
-
/**
|
|
2319
|
-
* Backward compatible muQubit (Single Qubit Register)
|
|
2320
|
-
*/
|
|
2321
|
-
function muQubit(initial = 0) {
|
|
2322
|
-
const q = muRegister(1);
|
|
2323
|
-
if (initial === 1) {
|
|
2324
|
-
muGate(q, 'X', 0);
|
|
2325
|
-
}
|
|
2326
|
-
// Add compatibility properties for Phase 1 components
|
|
2327
|
-
// These properties are getters that dynamically access the amplitudes array
|
|
2328
|
-
Object.defineProperty(q.value, 'alpha', { get: () => q.value.amplitudes[0] });
|
|
2329
|
-
Object.defineProperty(q.value, 'beta', { get: () => q.value.amplitudes[1] });
|
|
2330
|
-
return q;
|
|
2331
|
-
}
|
|
2332
|
-
exports.muQubit = muQubit;
|
|
2333
|
-
/**
|
|
2334
|
-
* Internal helper to update register state while maintaining compatibility
|
|
2335
|
-
*/
|
|
2336
|
-
function updateState(reg, newState) {
|
|
2337
|
-
if (newState.size === 1) {
|
|
2338
|
-
// Re-inject compatibility getters for muQubit users
|
|
2339
|
-
Object.defineProperty(newState, 'alpha', {
|
|
2340
|
-
get: () => newState.amplitudes[0],
|
|
2341
|
-
configurable: true,
|
|
2342
|
-
enumerable: true
|
|
2343
|
-
});
|
|
2344
|
-
Object.defineProperty(newState, 'beta', {
|
|
2345
|
-
get: () => newState.amplitudes[1],
|
|
2346
|
-
configurable: true,
|
|
2347
|
-
enumerable: true
|
|
2348
|
-
});
|
|
2349
|
-
}
|
|
2350
|
-
reg.value = newState;
|
|
2351
|
-
}
|
|
2352
|
-
function muGate(reg, type, target = 0, control) {
|
|
2353
|
-
const state = reg.value;
|
|
2354
|
-
const n = state.size;
|
|
2355
|
-
const amplitudes = state.amplitudes;
|
|
2356
|
-
const newAmps = amplitudes.map(a => (Object.assign({}, a)));
|
|
2357
|
-
// Prepare Effective Control (Explicit Arguments + Global Context)
|
|
2358
|
-
const effectiveControl = [...(control === undefined ? [] : (Array.isArray(control) ? control : [control])), ...exports.activeControls];
|
|
2359
|
-
// Helper: Check if all control bits are 1
|
|
2360
|
-
const checkControl = (index, ctrl) => {
|
|
2361
|
-
if (ctrl === undefined || (Array.isArray(ctrl) && ctrl.length === 0))
|
|
2362
|
-
return true;
|
|
2363
|
-
const ctrls = Array.isArray(ctrl) ? ctrl : [ctrl];
|
|
2364
|
-
return ctrls.every(c => ((index >> c) & 1) === 1);
|
|
2365
|
-
};
|
|
2366
|
-
// SWAP Gate (Unique case: affects 2 targets)
|
|
2367
|
-
if (type === 'SWAP') {
|
|
2368
|
-
const t1 = target;
|
|
2369
|
-
const t2 = control; // SWAP uses control arg as second target
|
|
2370
|
-
// Iterate only half to avoid double swapping
|
|
2371
|
-
for (let i = 0; i < amplitudes.length; i++) {
|
|
2372
|
-
// Check active controls for SWAP too
|
|
2373
|
-
if (exports.activeControls.length > 0 && !checkControl(i, exports.activeControls))
|
|
2374
|
-
continue;
|
|
2375
|
-
const bit1 = (i >> t1) & 1;
|
|
2376
|
-
const bit2 = (i >> t2) & 1;
|
|
2377
|
-
if (bit1 !== bit2) {
|
|
2378
|
-
// Determine the swap partner index
|
|
2379
|
-
// If i has (0,1), partner has (1,0) at those positions
|
|
2380
|
-
const partner = i ^ (1 << t1) ^ (1 << t2);
|
|
2381
|
-
if (i < partner) {
|
|
2382
|
-
const temp = newAmps[i];
|
|
2383
|
-
newAmps[i] = newAmps[partner];
|
|
2384
|
-
newAmps[partner] = temp;
|
|
2385
|
-
}
|
|
2386
|
-
}
|
|
2387
|
-
}
|
|
2388
|
-
updateState(reg, Object.assign(Object.assign({}, state), { amplitudes: newAmps }));
|
|
2389
|
-
return;
|
|
2390
|
-
}
|
|
2391
|
-
// Standard Single-Qubit & Controlled Gates
|
|
2392
|
-
if (type === 'H') {
|
|
2393
|
-
const s = 1 / Math.sqrt(2);
|
|
2394
|
-
const processed = new Set();
|
|
2395
|
-
for (let i = 0; i < state.amplitudes.length; i++) {
|
|
2396
|
-
if (processed.has(i))
|
|
2397
|
-
continue;
|
|
2398
|
-
// Check Controls first
|
|
2399
|
-
if (!checkControl(i, effectiveControl))
|
|
2400
|
-
continue;
|
|
2401
|
-
const targetBit = (i >> target) & 1;
|
|
2402
|
-
const pairedIndex = targetBit ? (i & ~(1 << target)) : (i | (1 << target));
|
|
2403
|
-
const a = state.amplitudes[i];
|
|
2404
|
-
const b = state.amplitudes[pairedIndex];
|
|
2405
|
-
if (targetBit === 0) {
|
|
2406
|
-
newAmps[i] = { re: s * (a.re + b.re), im: s * (a.im + b.im) };
|
|
2407
|
-
newAmps[pairedIndex] = { re: s * (a.re - b.re), im: s * (a.im - b.im) };
|
|
2408
|
-
}
|
|
2409
|
-
else {
|
|
2410
|
-
newAmps[pairedIndex] = { re: s * (b.re + a.re), im: s * (b.im + a.im) };
|
|
2411
|
-
newAmps[i] = { re: s * (b.re - a.re), im: s * (b.im - a.im) };
|
|
2412
|
-
}
|
|
2413
|
-
processed.add(i);
|
|
2414
|
-
processed.add(pairedIndex);
|
|
2415
|
-
}
|
|
2416
|
-
}
|
|
2417
|
-
else if (type === 'X' || type === 'CNOT') {
|
|
2418
|
-
// CNOT is just Controlled-X
|
|
2419
|
-
for (let i = 0; i < amplitudes.length; i++) {
|
|
2420
|
-
if (!checkControl(i, effectiveControl))
|
|
2421
|
-
continue;
|
|
2422
|
-
const targetBit = (i >> target) & 1;
|
|
2423
|
-
const pairedIndex = targetBit ? (i & ~(1 << target)) : (i | (1 << target));
|
|
2424
|
-
if (i < pairedIndex) {
|
|
2425
|
-
const temp = newAmps[i];
|
|
2426
|
-
newAmps[i] = newAmps[pairedIndex];
|
|
2427
|
-
newAmps[pairedIndex] = temp;
|
|
2428
|
-
}
|
|
2429
|
-
}
|
|
2430
|
-
}
|
|
2431
|
-
else if (type === 'Z' || type === 'CZ') {
|
|
2432
|
-
// Z and CZ are Phase Flips
|
|
2433
|
-
for (let i = 0; i < amplitudes.length; i++) {
|
|
2434
|
-
if (!checkControl(i, effectiveControl))
|
|
2435
|
-
continue;
|
|
2436
|
-
const targetBit = (i >> target) & 1;
|
|
2437
|
-
// Z Gate acts on |1>
|
|
2438
|
-
if (targetBit === 1) {
|
|
2439
|
-
newAmps[i] = { re: -amplitudes[i].re, im: -amplitudes[i].im };
|
|
2440
|
-
}
|
|
2441
|
-
}
|
|
2442
|
-
}
|
|
2443
|
-
else if (type === 'Y') {
|
|
2444
|
-
// Y: |0> -> i|1>, |1> -> -i|0>
|
|
2445
|
-
for (let i = 0; i < amplitudes.length; i++) {
|
|
2446
|
-
if (!checkControl(i, effectiveControl))
|
|
2447
|
-
continue;
|
|
2448
|
-
const targetBit = (i >> target) & 1;
|
|
2449
|
-
const pairedIndex = targetBit ? (i & ~(1 << target)) : (i | (1 << target));
|
|
2450
|
-
if (i < pairedIndex) {
|
|
2451
|
-
// We process pairs (i, pairedIndex) where i has 0 at target, paired has 1
|
|
2452
|
-
const a = newAmps[i]; // Coeff of |0>
|
|
2453
|
-
const b = newAmps[pairedIndex]; // Coeff of |1>
|
|
2454
|
-
// New |0> = -i * Old |1>
|
|
2455
|
-
newAmps[i] = { re: b.im, im: -b.re };
|
|
2456
|
-
// New |1> = i * Old |0>
|
|
2457
|
-
newAmps[pairedIndex] = { re: -a.im, im: a.re };
|
|
2458
|
-
}
|
|
2459
|
-
}
|
|
2460
|
-
}
|
|
2461
|
-
updateState(reg, Object.assign(Object.assign({}, state), { amplitudes: newAmps }));
|
|
2462
|
-
}
|
|
2463
|
-
exports.muGate = muGate;
|
|
2464
|
-
/**
|
|
2465
|
-
* Mulan Search Logic (Grover's Operator)
|
|
2466
|
-
* Automatically constructs a multi-controlled Phase Flip (Z) for a specific target state.
|
|
2467
|
-
* This is the core of the "Quantum Switch" or "Quantum Search" capability.
|
|
2468
|
-
* @param reg Quantum Register
|
|
2469
|
-
* @param targetState The integer state to "search" and mark (e.g. 2 for |10>)
|
|
2470
|
-
*/
|
|
2471
|
-
function muSearch(reg, targetState) {
|
|
2472
|
-
const n = reg.value.size;
|
|
2473
|
-
const controls = [];
|
|
2474
|
-
// 1. Identify which bits are 0 and need wrapping with X gates
|
|
2475
|
-
// Logic: To mark |010>, we want C-C-Z to trigger on 111.
|
|
2476
|
-
// So we apply X to bits that are 0, then C-C-Z, then X again.
|
|
2477
|
-
// We treat the last bit as the 'target' for the Z gate, rest as controls
|
|
2478
|
-
const targetQubit = n - 1;
|
|
2479
|
-
for (let i = 0; i < n; i++) {
|
|
2480
|
-
const bit = (targetState >> i) & 1;
|
|
2481
|
-
if (i === targetQubit) {
|
|
2482
|
-
// If target bit logic requires 0, we flip it to 1 for the Z gate to work
|
|
2483
|
-
if (bit === 0)
|
|
2484
|
-
muGate(reg, 'X', i);
|
|
2485
|
-
}
|
|
2486
|
-
else {
|
|
2487
|
-
controls.push(i);
|
|
2488
|
-
if (bit === 0)
|
|
2489
|
-
muGate(reg, 'X', i);
|
|
2490
|
-
}
|
|
2491
|
-
}
|
|
2492
|
-
// 2. Apply Multi-Controlled Z
|
|
2493
|
-
muGate(reg, 'Z', targetQubit, controls);
|
|
2494
|
-
// 3. Uncompute (Restore 0s)
|
|
2495
|
-
for (let i = 0; i < n; i++) {
|
|
2496
|
-
const bit = (targetState >> i) & 1;
|
|
2497
|
-
if (bit === 0)
|
|
2498
|
-
muGate(reg, 'X', i);
|
|
1827
|
+
// 2. Apply Multi-Controlled Z
|
|
1828
|
+
muGate(reg, 'Z', targetQubit, controls);
|
|
1829
|
+
// 3. Uncompute (Restore 0s)
|
|
1830
|
+
for (let i = 0; i < n; i++) {
|
|
1831
|
+
const bit = (targetState >> i) & 1;
|
|
1832
|
+
if (bit === 0)
|
|
1833
|
+
muGate(reg, 'X', i);
|
|
2499
1834
|
}
|
|
2500
1835
|
// --- GROVER DIFFUSER (Amplification) ---
|
|
2501
1836
|
// This flips the probability amplitudes around the mean, boosting the target state.
|
|
@@ -2519,12 +1854,10 @@ function muSearch(reg, targetState) {
|
|
|
2519
1854
|
for (let i = 0; i < n; i++)
|
|
2520
1855
|
muGate(reg, 'H', i);
|
|
2521
1856
|
}
|
|
2522
|
-
exports.muSearch = muSearch;
|
|
2523
1857
|
function muEntangle(reg, i, j) {
|
|
2524
1858
|
muGate(reg, 'H', i);
|
|
2525
1859
|
muGate(reg, 'CNOT', j, i);
|
|
2526
1860
|
}
|
|
2527
|
-
exports.muEntangle = muEntangle;
|
|
2528
1861
|
/**
|
|
2529
1862
|
* Quantum Teleportation Protocol
|
|
2530
1863
|
* Transfers the state of `msgIdx` to `targetIdx` using `ancillaIdx` as a resource.
|
|
@@ -2550,7 +1883,6 @@ function muTeleport(reg, msgIdx, ancillaIdx, targetIdx) {
|
|
|
2550
1883
|
if (m1 === 1)
|
|
2551
1884
|
muGate(reg, 'Z', targetIdx);
|
|
2552
1885
|
}
|
|
2553
|
-
exports.muTeleport = muTeleport;
|
|
2554
1886
|
/**
|
|
2555
1887
|
* Measures a specific qubit in the register, collapsing the superposition.
|
|
2556
1888
|
* @param reg Quantum Register
|
|
@@ -2568,123 +1900,652 @@ function muMeasure(reg, target = 0) {
|
|
|
2568
1900
|
prob0 += (a.re * a.re) + (a.im * a.im);
|
|
2569
1901
|
}
|
|
2570
1902
|
}
|
|
2571
|
-
// 2. Determine Outcome
|
|
2572
|
-
const result = Math.random() < prob0 ? 0 : 1;
|
|
2573
|
-
const resultProb = result === 0 ? prob0 : (1 - prob0);
|
|
2574
|
-
const normFactor = resultProb > 0 ? (1 / Math.sqrt(resultProb)) : 0;
|
|
2575
|
-
// 3. Collapse the State (Wavefunction Collapse)
|
|
2576
|
-
const newAmps = amplitudes.map((a, i) => {
|
|
2577
|
-
const bit = (i >> target) & 1;
|
|
2578
|
-
if (bit !== result) {
|
|
2579
|
-
return { re: 0, im: 0 };
|
|
1903
|
+
// 2. Determine Outcome
|
|
1904
|
+
const result = Math.random() < prob0 ? 0 : 1;
|
|
1905
|
+
const resultProb = result === 0 ? prob0 : (1 - prob0);
|
|
1906
|
+
const normFactor = resultProb > 0 ? (1 / Math.sqrt(resultProb)) : 0;
|
|
1907
|
+
// 3. Collapse the State (Wavefunction Collapse)
|
|
1908
|
+
const newAmps = amplitudes.map((a, i) => {
|
|
1909
|
+
const bit = (i >> target) & 1;
|
|
1910
|
+
if (bit !== result) {
|
|
1911
|
+
return { re: 0, im: 0 };
|
|
1912
|
+
}
|
|
1913
|
+
else {
|
|
1914
|
+
return { re: a.re * normFactor, im: a.im * normFactor };
|
|
1915
|
+
}
|
|
1916
|
+
});
|
|
1917
|
+
// We need to call updateState to ensure reactivity if specialized getters exist
|
|
1918
|
+
// But since this file has updateState internal, we can just call it.
|
|
1919
|
+
// However, the internal updateState function needs to be in scope.
|
|
1920
|
+
// It is defined at line 60. So we are good.
|
|
1921
|
+
updateState(reg, Object.assign(Object.assign({}, state), { amplitudes: newAmps }));
|
|
1922
|
+
return result;
|
|
1923
|
+
}
|
|
1924
|
+
/**
|
|
1925
|
+
* Quantum Loop: Parallel Execution
|
|
1926
|
+
* Applies a gate to multiple qubits "simultaneously" (in simulation steps).
|
|
1927
|
+
* Ideal for initialization (Hadamard Transform) or global operations.
|
|
1928
|
+
* @param reg Quantum Register
|
|
1929
|
+
* @param qubits Array of qubit indices
|
|
1930
|
+
* @param gate Gate type to apply (e.g. 'H', 'X')
|
|
1931
|
+
*/
|
|
1932
|
+
function muParallel(reg, qubits, gate) {
|
|
1933
|
+
if (gate === 'SWAP') {
|
|
1934
|
+
throw new Error("SWAP cannot be applied in parallel (requires pairs).");
|
|
1935
|
+
}
|
|
1936
|
+
// In a real quantum computer, these happen at t=0.
|
|
1937
|
+
// Here, we loop, but logical time is constant.
|
|
1938
|
+
qubits.forEach(q => muGate(reg, gate, q));
|
|
1939
|
+
}
|
|
1940
|
+
/**
|
|
1941
|
+
* Applies a block of operations controlled by specific qubits.
|
|
1942
|
+
* Enables "Quantum If/Else".
|
|
1943
|
+
*/
|
|
1944
|
+
function muControl(reg, controlQubit, inverse, block) {
|
|
1945
|
+
// 1. Setup Context
|
|
1946
|
+
if (inverse) {
|
|
1947
|
+
muGate(reg, 'X', controlQubit); // Flip 0 to 1 to activate
|
|
1948
|
+
}
|
|
1949
|
+
activeControls.push(controlQubit);
|
|
1950
|
+
try {
|
|
1951
|
+
block();
|
|
1952
|
+
}
|
|
1953
|
+
finally {
|
|
1954
|
+
activeControls.pop();
|
|
1955
|
+
// Uncompute (Restore 0)
|
|
1956
|
+
if (inverse) {
|
|
1957
|
+
muGate(reg, 'X', controlQubit);
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
/**
|
|
1962
|
+
* Quantum Switch: conditional Logic on Superposition
|
|
1963
|
+
* Executes different logic branches based on the state of control qubits.
|
|
1964
|
+
* Because the register can be in a superposition of states (e.g. |0> + |1>),
|
|
1965
|
+
* MULTIPLE branches can execute effectively simultaneously on different subspaces.
|
|
1966
|
+
*
|
|
1967
|
+
* @param reg Quantum Register
|
|
1968
|
+
* @param controlQubit The qubit controlling the switch (Single control for v1)
|
|
1969
|
+
* @param cases Object mapping state (0 or 1) to a function executing quantum operations
|
|
1970
|
+
*/
|
|
1971
|
+
function muSwitch(reg, controlQubit, cases) {
|
|
1972
|
+
if (cases[0]) {
|
|
1973
|
+
muControl(reg, controlQubit, true, cases[0]);
|
|
1974
|
+
}
|
|
1975
|
+
if (cases[1]) {
|
|
1976
|
+
muControl(reg, controlQubit, false, cases[1]);
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
;// ./src/core/surge.ts
|
|
1981
|
+
/**
|
|
1982
|
+
* muBurst - Adaptive Non-blocking Iterator
|
|
1983
|
+
* Processes large arrays in batches within a frame budget (typically 8-16ms)
|
|
1984
|
+
* to keep the UI responsive while executing at near-native loop speeds.
|
|
1985
|
+
*/
|
|
1986
|
+
function muBurst(array, callback, options = {}) {
|
|
1987
|
+
const { chunkSize = 1000, timeout = 8, onProgress } = options;
|
|
1988
|
+
return new Promise((resolve) => {
|
|
1989
|
+
let index = 0;
|
|
1990
|
+
const total = array.length;
|
|
1991
|
+
function process() {
|
|
1992
|
+
const start = performance.now();
|
|
1993
|
+
// Tight loop for high-speed processing
|
|
1994
|
+
while (index < total && (performance.now() - start) < timeout) {
|
|
1995
|
+
// Process in smaller bursts to allow more frequent time checks if needed
|
|
1996
|
+
const endBurst = Math.min(index + chunkSize, total);
|
|
1997
|
+
for (; index < endBurst; index++) {
|
|
1998
|
+
callback(array[index], index);
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
if (onProgress) {
|
|
2002
|
+
onProgress((index / total) * 100);
|
|
2003
|
+
}
|
|
2004
|
+
if (index < total) {
|
|
2005
|
+
requestAnimationFrame(process);
|
|
2006
|
+
}
|
|
2007
|
+
else {
|
|
2008
|
+
resolve();
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
process();
|
|
2012
|
+
});
|
|
2013
|
+
}
|
|
2014
|
+
/**
|
|
2015
|
+
* muSurge - Truly Parallel Execution
|
|
2016
|
+
* Distributes work across CPU cores using Web Workers.
|
|
2017
|
+
* Logic must be serializable.
|
|
2018
|
+
*/
|
|
2019
|
+
function muSurge(array, taskFn, onProgress) {
|
|
2020
|
+
const n = navigator.hardwareConcurrency || 4;
|
|
2021
|
+
const chunkSize = Math.ceil(array.length / n);
|
|
2022
|
+
const results = new Array(array.length);
|
|
2023
|
+
let completedChunks = 0;
|
|
2024
|
+
let completedItems = 0;
|
|
2025
|
+
// Convert function to string if it isn't already
|
|
2026
|
+
const fnStr = typeof taskFn === 'function' ? taskFn.toString() : taskFn;
|
|
2027
|
+
const workerPart1 = `const taskFn = ${fnStr};`;
|
|
2028
|
+
const workerPart2 = `self.onmessage = function(e) {`;
|
|
2029
|
+
const workerPart3 = ` const { chunk, startIndex } = e.data;`;
|
|
2030
|
+
const workerPart4 = ` try { const results = chunk.map(taskFn); self.postMessage({ results, startIndex }); }`;
|
|
2031
|
+
const workerPart5 = ` catch (err) { self.postMessage({ error: err.message, startIndex }); }`;
|
|
2032
|
+
const workerPart6 = `};`;
|
|
2033
|
+
const workerCode = [workerPart1, workerPart2, workerPart3, workerPart4, workerPart5, workerPart6].join('\n');
|
|
2034
|
+
const blob = new Blob([workerCode], { type: 'application/javascript' });
|
|
2035
|
+
const workerUrl = URL.createObjectURL(blob);
|
|
2036
|
+
return new Promise((resolve) => {
|
|
2037
|
+
if (array.length === 0)
|
|
2038
|
+
return resolve([]);
|
|
2039
|
+
for (let i = 0; i < n; i++) {
|
|
2040
|
+
const start = i * chunkSize;
|
|
2041
|
+
const end = Math.min(start + chunkSize, array.length);
|
|
2042
|
+
if (start >= end) {
|
|
2043
|
+
completedChunks++;
|
|
2044
|
+
continue;
|
|
2045
|
+
}
|
|
2046
|
+
const chunk = array.slice(start, end);
|
|
2047
|
+
const worker = new Worker(workerUrl);
|
|
2048
|
+
worker.onmessage = (e) => {
|
|
2049
|
+
const { results: chunkResults, startIndex } = e.data;
|
|
2050
|
+
// Merge results back into main array
|
|
2051
|
+
for (let j = 0; j < chunkResults.length; j++) {
|
|
2052
|
+
results[startIndex + j] = chunkResults[j];
|
|
2053
|
+
}
|
|
2054
|
+
completedChunks++;
|
|
2055
|
+
completedItems += chunkResults.length;
|
|
2056
|
+
if (onProgress)
|
|
2057
|
+
onProgress((completedItems / array.length) * 100);
|
|
2058
|
+
worker.terminate();
|
|
2059
|
+
if (completedChunks === n) {
|
|
2060
|
+
URL.revokeObjectURL(workerUrl);
|
|
2061
|
+
resolve(results);
|
|
2062
|
+
}
|
|
2063
|
+
};
|
|
2064
|
+
worker.postMessage({ chunk, startIndex: start, fnStr });
|
|
2065
|
+
}
|
|
2066
|
+
});
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
;// ./src/components/bloch-sphere.ts
|
|
2070
|
+
|
|
2071
|
+
const MuBlochBase = typeof HTMLElement !== 'undefined' ? HTMLElement : class {
|
|
2072
|
+
};
|
|
2073
|
+
class MuBlochSphereElement extends MuBlochBase {
|
|
2074
|
+
static get observedAttributes() {
|
|
2075
|
+
return ['size'];
|
|
2076
|
+
}
|
|
2077
|
+
constructor() {
|
|
2078
|
+
super();
|
|
2079
|
+
this._arrow = null;
|
|
2080
|
+
this._container = null;
|
|
2081
|
+
this._disposeEffect = null;
|
|
2082
|
+
this.attachShadow({ mode: 'open' });
|
|
2083
|
+
}
|
|
2084
|
+
connectedCallback() {
|
|
2085
|
+
this.render();
|
|
2086
|
+
}
|
|
2087
|
+
disconnectedCallback() {
|
|
2088
|
+
if (this._disposeEffect) {
|
|
2089
|
+
this._disposeEffect();
|
|
2090
|
+
this._disposeEffect = null;
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
// Property setter for 'qubit' (passed as .qubit="${q}" in Mulan)
|
|
2094
|
+
set qubit(val) {
|
|
2095
|
+
this._qubit = val;
|
|
2096
|
+
this.initReactivity();
|
|
2097
|
+
}
|
|
2098
|
+
get qubit() {
|
|
2099
|
+
return this._qubit;
|
|
2100
|
+
}
|
|
2101
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
2102
|
+
if (name === 'size' && this._container) {
|
|
2103
|
+
this._container.style.width = newValue + 'px';
|
|
2104
|
+
this._container.style.height = newValue + 'px';
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
initReactivity() {
|
|
2108
|
+
if (this._disposeEffect)
|
|
2109
|
+
this._disposeEffect();
|
|
2110
|
+
if (!this._qubit)
|
|
2111
|
+
return;
|
|
2112
|
+
// MulanJS Effect: Run whenever the qubit state changes
|
|
2113
|
+
this._disposeEffect = effect(() => {
|
|
2114
|
+
const state = this._qubit.value; // Access reactive proxy
|
|
2115
|
+
if (!state || !state.amplitudes)
|
|
2116
|
+
return;
|
|
2117
|
+
// Assume Single Qubit for Visualizer (Index 0 if passed a register)
|
|
2118
|
+
// If passed a register, we visualize the first qubit's logical projection (partial trace simplified)
|
|
2119
|
+
// Or assume input IS a specific qubit projection?
|
|
2120
|
+
// For simplified demo, we assume the register is size 1 OR we visualize Q0 of the register.
|
|
2121
|
+
const amps = state.amplitudes;
|
|
2122
|
+
// Support 1-qubit visualization from N-qubit register requires partial trace.
|
|
2123
|
+
// For now, let's assume the user passes a 1-qubit register OR we visualize index 0.
|
|
2124
|
+
// |psi> = a|0> + b|1>
|
|
2125
|
+
// a = amps[0] (re, im)
|
|
2126
|
+
// b = amps[1] (re, im)
|
|
2127
|
+
// Dealing with multi-qubit registers (naive projection for visualization):
|
|
2128
|
+
// We sum up probabilities for 0xxxx vs 1xxxx to get Z-axis.
|
|
2129
|
+
// This is "marginal probability".
|
|
2130
|
+
let p0 = 0;
|
|
2131
|
+
let p1 = 0;
|
|
2132
|
+
// Calculate Probabilities
|
|
2133
|
+
for (let i = 0; i < amps.length; i++) {
|
|
2134
|
+
const mag = amps[i].re * amps[i].re + amps[i].im * amps[i].im;
|
|
2135
|
+
if ((i & 1) === 0)
|
|
2136
|
+
p0 += mag;
|
|
2137
|
+
else
|
|
2138
|
+
p1 += mag;
|
|
2139
|
+
}
|
|
2140
|
+
// Theta from Z-projection
|
|
2141
|
+
// P0 = cos^2(theta/2) -> theta = 2 * acos(sqrt(P0))
|
|
2142
|
+
const theta = 2 * Math.acos(Math.min(1, Math.sqrt(p0)));
|
|
2143
|
+
// Phi?
|
|
2144
|
+
// Phase is relative phase between |0> and |1>.
|
|
2145
|
+
// We can look at the phase of the '1' component relative to '0'.
|
|
2146
|
+
// Simple approach: Look at amps[1] phase vs amps[0] phase.
|
|
2147
|
+
// But with entanglement, pure state phase is tricky.
|
|
2148
|
+
// Let's implement full density matrix if needed, but for now:
|
|
2149
|
+
// naive: atan2(amps[1].im, amps[1].re) - atan2(amps[0].im, amps[0].re)
|
|
2150
|
+
// We use the first pair (0 and 1) as proxy if multiple.
|
|
2151
|
+
const a0 = amps[0];
|
|
2152
|
+
const a1 = amps[1]; // Valid for N>=1
|
|
2153
|
+
const phase0 = Math.atan2(a0.im, a0.re);
|
|
2154
|
+
const phase1 = Math.atan2(a1.im, a1.re);
|
|
2155
|
+
let phi = phase1 - phase0;
|
|
2156
|
+
// Update Arrow
|
|
2157
|
+
this.updateArrow(theta, phi);
|
|
2158
|
+
});
|
|
2159
|
+
}
|
|
2160
|
+
updateArrow(theta, phi) {
|
|
2161
|
+
if (!this._arrow)
|
|
2162
|
+
return;
|
|
2163
|
+
// Convert Quantum Coords (Theta, Phi) to CSS Transforms
|
|
2164
|
+
// Theta 0 = Top (|0>)
|
|
2165
|
+
// Theta PI = Bottom (|1>)
|
|
2166
|
+
// Theta PI/2 = Equator
|
|
2167
|
+
// CSS Rotate sequence:
|
|
2168
|
+
// 1. Start pointing UP (Y or Z axis in CSS?)
|
|
2169
|
+
// Let's say Arrow starts pointing UP (Y-).
|
|
2170
|
+
// Rotate Z by Phi (Azimuth)
|
|
2171
|
+
// Rotate X by Theta (Polar) - No, that's not standard Euler.
|
|
2172
|
+
// Standard Physics:
|
|
2173
|
+
// Z is Up (in Bloch), but CSS 3D Y is usually 'Down' or 'Up'.
|
|
2174
|
+
// Let's Map:
|
|
2175
|
+
// Bloch Z+ (|0>) -> CSS Y- (Top)
|
|
2176
|
+
// Bloch Z- (|1>) -> CSS Y+ (Bottom)
|
|
2177
|
+
// Bloch X+ (|+>) -> CSS Z+ (Front)
|
|
2178
|
+
// Transform:
|
|
2179
|
+
// rotateY(phi) ? No, phi rotates around Z-axis (Vertical).
|
|
2180
|
+
// theta rotates from Z-axis down.
|
|
2181
|
+
// CSS:
|
|
2182
|
+
// rotateY(phi) -> Rotates around Vertical axis.
|
|
2183
|
+
// rotateZ(theta) -> Rotates "down" from up?
|
|
2184
|
+
// Let's simplify:
|
|
2185
|
+
// transform: rotateY(${phi}rad) rotateZ(${theta}rad)
|
|
2186
|
+
// Note: CSS rotations order matters.
|
|
2187
|
+
const degTheta = theta * (180 / Math.PI);
|
|
2188
|
+
const degPhi = phi * (180 / Math.PI);
|
|
2189
|
+
// Adjustment for visual alignment
|
|
2190
|
+
this._arrow.style.transform = `rotateY(${degPhi}deg) rotateZ(${degTheta}deg)`;
|
|
2191
|
+
// Color based on state
|
|
2192
|
+
const isSuperposition = Math.abs(theta - Math.PI / 2) < 0.1;
|
|
2193
|
+
this._arrow.style.backgroundColor = isSuperposition ? '#00ffff' : '#ff00ff';
|
|
2194
|
+
}
|
|
2195
|
+
render() {
|
|
2196
|
+
if (!this.shadowRoot)
|
|
2197
|
+
return;
|
|
2198
|
+
const size = this.getAttribute('size') || '200';
|
|
2199
|
+
this.shadowRoot.innerHTML = `
|
|
2200
|
+
<style>
|
|
2201
|
+
:host {
|
|
2202
|
+
display: inline-block;
|
|
2203
|
+
perspective: 1000px;
|
|
2204
|
+
}
|
|
2205
|
+
.sphere-container {
|
|
2206
|
+
width: ${size}px;
|
|
2207
|
+
height: ${size}px;
|
|
2208
|
+
position: relative;
|
|
2209
|
+
transform-style: preserve-3d;
|
|
2210
|
+
margin: 0 auto;
|
|
2211
|
+
}
|
|
2212
|
+
.sphere {
|
|
2213
|
+
width: 100%;
|
|
2214
|
+
height: 100%;
|
|
2215
|
+
border-radius: 50%;
|
|
2216
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
2217
|
+
position: absolute;
|
|
2218
|
+
background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.1), rgba(0, 0, 0, 0.8));
|
|
2219
|
+
box-shadow: inset 0 0 20px rgba(255, 255, 255, 0.05);
|
|
2220
|
+
transform: rotateX(15deg) rotateY(15deg); /* Initial tilt for view */
|
|
2221
|
+
}
|
|
2222
|
+
/* Equator Ring */
|
|
2223
|
+
.equator {
|
|
2224
|
+
position: absolute;
|
|
2225
|
+
top: 50%;
|
|
2226
|
+
left: 0;
|
|
2227
|
+
width: 100%;
|
|
2228
|
+
height: 100%;
|
|
2229
|
+
border: 1px dashed rgba(255, 255, 255, 0.3);
|
|
2230
|
+
border-radius: 50%;
|
|
2231
|
+
transform: rotateX(90deg);
|
|
2232
|
+
pointer-events: none;
|
|
2233
|
+
}
|
|
2234
|
+
/* Axis Lines */
|
|
2235
|
+
.axis {
|
|
2236
|
+
position: absolute;
|
|
2237
|
+
background: rgba(255, 255, 255, 0.1);
|
|
2238
|
+
}
|
|
2239
|
+
.z-axis { width: 2px; height: 100%; left: 50%; top: 0; }
|
|
2240
|
+
|
|
2241
|
+
/* The Quantum Arrow */
|
|
2242
|
+
.arrow-container {
|
|
2243
|
+
position: absolute;
|
|
2244
|
+
top: 50%;
|
|
2245
|
+
left: 50%;
|
|
2246
|
+
width: 0;
|
|
2247
|
+
height: 0;
|
|
2248
|
+
transform-style: preserve-3d;
|
|
2249
|
+
transform: rotateX(15deg) rotateY(15deg); /* Match sphere tilt */
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
.arrow-pivot {
|
|
2253
|
+
position: absolute;
|
|
2254
|
+
top: 0;
|
|
2255
|
+
left: 0;
|
|
2256
|
+
width: 4px;
|
|
2257
|
+
height: 50%; /* Length of radius */
|
|
2258
|
+
/* Pivot logic: we want to rotate around the center point */
|
|
2259
|
+
/* CSS Default transform-origin is 50% 50% */
|
|
2260
|
+
/* We construct the arrow such that it points UP from center */
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
.arrow-rod {
|
|
2264
|
+
width: 4px;
|
|
2265
|
+
height: ${parseInt(size) / 2 - 10}px;
|
|
2266
|
+
background: #ff00ff;
|
|
2267
|
+
position: absolute;
|
|
2268
|
+
bottom: 0;
|
|
2269
|
+
left: -2px;
|
|
2270
|
+
transform-origin: bottom center;
|
|
2271
|
+
transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275), background-color 0.3s;
|
|
2272
|
+
border-radius: 2px;
|
|
2273
|
+
box-shadow: 0 0 10px currentColor;
|
|
2274
|
+
}
|
|
2275
|
+
|
|
2276
|
+
.arrow-head {
|
|
2277
|
+
width: 0;
|
|
2278
|
+
height: 0;
|
|
2279
|
+
border-left: 6px solid transparent;
|
|
2280
|
+
border-right: 6px solid transparent;
|
|
2281
|
+
border-bottom: 12px solid #ff00ff;
|
|
2282
|
+
position: absolute;
|
|
2283
|
+
top: -10px;
|
|
2284
|
+
left: -6px;
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
|
+
.label {
|
|
2288
|
+
position: absolute;
|
|
2289
|
+
color: #aaa;
|
|
2290
|
+
font-family: monospace;
|
|
2291
|
+
font-size: 10px;
|
|
2292
|
+
}
|
|
2293
|
+
.label-0 { top: 5px; left: 50%; transform: translateX(-50%); }
|
|
2294
|
+
.label-1 { bottom: 5px; left: 50%; transform: translateX(-50%); }
|
|
2295
|
+
</style>
|
|
2296
|
+
|
|
2297
|
+
<div class="sphere-container">
|
|
2298
|
+
<div class="sphere">
|
|
2299
|
+
<div class="equator"></div>
|
|
2300
|
+
<div class="axis z-axis"></div>
|
|
2301
|
+
<div class="label label-0">|0></div>
|
|
2302
|
+
<div class="label label-1">|1></div>
|
|
2303
|
+
</div>
|
|
2304
|
+
|
|
2305
|
+
<div class="arrow-container">
|
|
2306
|
+
<!-- The rod is the actual rotating element -->
|
|
2307
|
+
<div class="arrow-rod">
|
|
2308
|
+
<div class="arrow-head"></div>
|
|
2309
|
+
</div>
|
|
2310
|
+
</div>
|
|
2311
|
+
</div>
|
|
2312
|
+
`;
|
|
2313
|
+
this._container = this.shadowRoot.querySelector('.sphere-container');
|
|
2314
|
+
this._arrow = this.shadowRoot.querySelector('.arrow-rod');
|
|
2315
|
+
// Re-init reactivity if qubit was set before render
|
|
2316
|
+
if (this._qubit)
|
|
2317
|
+
this.initReactivity();
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
// Register the custom element
|
|
2321
|
+
if (typeof customElements !== 'undefined') {
|
|
2322
|
+
customElements.define('mu-bloch-sphere', MuBlochSphereElement);
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2325
|
+
;// ./src/components/infinity-list.ts
|
|
2326
|
+
const MuInfinityBase = typeof HTMLElement !== 'undefined' ? HTMLElement : class {
|
|
2327
|
+
};
|
|
2328
|
+
class MuInfinity extends MuInfinityBase {
|
|
2329
|
+
constructor() {
|
|
2330
|
+
super();
|
|
2331
|
+
this._items = [];
|
|
2332
|
+
this._itemHeight = 50; // Default height
|
|
2333
|
+
this._template = '';
|
|
2334
|
+
this.attachShadow({ mode: 'open' });
|
|
2335
|
+
// Structure:
|
|
2336
|
+
// :host { overflow-y: auto; display: block; height: 100%; }
|
|
2337
|
+
// .spacer { height: totalHeight; position: relative; }
|
|
2338
|
+
// .content { position: absolute; top: padding; width: 100%; }
|
|
2339
|
+
this.shadowRoot.innerHTML = `
|
|
2340
|
+
<style>
|
|
2341
|
+
:host {
|
|
2342
|
+
display: block;
|
|
2343
|
+
overflow-y: auto;
|
|
2344
|
+
height: 100%;
|
|
2345
|
+
position: relative;
|
|
2346
|
+
}
|
|
2347
|
+
.spacer {
|
|
2348
|
+
position: relative;
|
|
2349
|
+
width: 100%;
|
|
2350
|
+
}
|
|
2351
|
+
.content {
|
|
2352
|
+
position: absolute;
|
|
2353
|
+
top: 0;
|
|
2354
|
+
left: 0;
|
|
2355
|
+
width: 100%;
|
|
2356
|
+
}
|
|
2357
|
+
</style>
|
|
2358
|
+
<div class="spacer">
|
|
2359
|
+
<div class="content"></div>
|
|
2360
|
+
</div>
|
|
2361
|
+
`;
|
|
2362
|
+
this.container = this.shadowRoot.host; // The host itself scrolls
|
|
2363
|
+
this.spacer = this.shadowRoot.querySelector('.spacer');
|
|
2364
|
+
this.content = this.shadowRoot.querySelector('.content');
|
|
2365
|
+
this.onScroll = this.onScroll.bind(this);
|
|
2366
|
+
}
|
|
2367
|
+
static get observedAttributes() {
|
|
2368
|
+
return ['item-height'];
|
|
2369
|
+
}
|
|
2370
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
2371
|
+
if (name === 'item-height') {
|
|
2372
|
+
this._itemHeight = parseInt(newValue, 10) || 50;
|
|
2373
|
+
this.renderVisible();
|
|
2580
2374
|
}
|
|
2581
|
-
|
|
2582
|
-
|
|
2375
|
+
}
|
|
2376
|
+
connectedCallback() {
|
|
2377
|
+
// Find the template provided by the user (Support both standard and branded tags)
|
|
2378
|
+
const templateTag = this.querySelector('template') || this.querySelector('mu-template');
|
|
2379
|
+
if (templateTag) {
|
|
2380
|
+
this._template = templateTag.innerHTML;
|
|
2583
2381
|
}
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
// However, the internal updateState function needs to be in scope.
|
|
2588
|
-
// It is defined at line 60. So we are good.
|
|
2589
|
-
updateState(reg, Object.assign(Object.assign({}, state), { amplitudes: newAmps }));
|
|
2590
|
-
return result;
|
|
2591
|
-
}
|
|
2592
|
-
exports.muMeasure = muMeasure;
|
|
2593
|
-
/**
|
|
2594
|
-
* Quantum Loop: Parallel Execution
|
|
2595
|
-
* Applies a gate to multiple qubits "simultaneously" (in simulation steps).
|
|
2596
|
-
* Ideal for initialization (Hadamard Transform) or global operations.
|
|
2597
|
-
* @param reg Quantum Register
|
|
2598
|
-
* @param qubits Array of qubit indices
|
|
2599
|
-
* @param gate Gate type to apply (e.g. 'H', 'X')
|
|
2600
|
-
*/
|
|
2601
|
-
function muParallel(reg, qubits, gate) {
|
|
2602
|
-
if (gate === 'SWAP') {
|
|
2603
|
-
throw new Error("SWAP cannot be applied in parallel (requires pairs).");
|
|
2382
|
+
this.addEventListener('scroll', this.onScroll);
|
|
2383
|
+
// Wait for next frame to get initial height if not set
|
|
2384
|
+
requestAnimationFrame(() => this.renderVisible());
|
|
2604
2385
|
}
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
qubits.forEach(q => muGate(reg, gate, q));
|
|
2608
|
-
}
|
|
2609
|
-
exports.muParallel = muParallel;
|
|
2610
|
-
/**
|
|
2611
|
-
* Applies a block of operations controlled by specific qubits.
|
|
2612
|
-
* Enables "Quantum If/Else".
|
|
2613
|
-
*/
|
|
2614
|
-
function muControl(reg, controlQubit, inverse, block) {
|
|
2615
|
-
// 1. Setup Context
|
|
2616
|
-
if (inverse) {
|
|
2617
|
-
muGate(reg, 'X', controlQubit); // Flip 0 to 1 to activate
|
|
2386
|
+
disconnectedCallback() {
|
|
2387
|
+
this.removeEventListener('scroll', this.onScroll);
|
|
2618
2388
|
}
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2389
|
+
set items(value) {
|
|
2390
|
+
this._items = value;
|
|
2391
|
+
this.renderVisible();
|
|
2622
2392
|
}
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2393
|
+
get items() { return this._items; }
|
|
2394
|
+
onScroll() {
|
|
2395
|
+
requestAnimationFrame(() => this.renderVisible());
|
|
2396
|
+
}
|
|
2397
|
+
renderVisible() {
|
|
2398
|
+
if (!this._items.length)
|
|
2399
|
+
return;
|
|
2400
|
+
const scrollTop = this.scrollTop;
|
|
2401
|
+
const hostHeight = this.clientHeight || 400; // Default fallback if not sized
|
|
2402
|
+
const totalHeight = this._items.length * this._itemHeight;
|
|
2403
|
+
this.spacer.style.height = `${totalHeight}px`;
|
|
2404
|
+
// Windowing Math
|
|
2405
|
+
const startIndex = Math.floor(scrollTop / this._itemHeight);
|
|
2406
|
+
const buffer = 5;
|
|
2407
|
+
const visibleCount = Math.ceil(hostHeight / this._itemHeight);
|
|
2408
|
+
const renderStart = Math.max(0, startIndex - buffer);
|
|
2409
|
+
const renderEnd = Math.min(this._items.length, startIndex + visibleCount + buffer);
|
|
2410
|
+
const startOffset = renderStart * this._itemHeight;
|
|
2411
|
+
this.content.style.transform = `translateY(${startOffset}px)`;
|
|
2412
|
+
// Render specific slice
|
|
2413
|
+
const visibleItems = this._items.slice(renderStart, renderEnd);
|
|
2414
|
+
// Simple string replacement template engine for the demo
|
|
2415
|
+
// In a real Mulan compilation, this would be an optimized ASTR render
|
|
2416
|
+
let html = '';
|
|
2417
|
+
visibleItems.forEach((item, index) => {
|
|
2418
|
+
const absoluteIndex = renderStart + index;
|
|
2419
|
+
// Basic mustache replacement {{ item.prop }}
|
|
2420
|
+
let rowHtml = this._template
|
|
2421
|
+
.replace(/{{\s*item\s*}}/g, String(item)) // {{ item }}
|
|
2422
|
+
.replace(/{{\s*index\s*}}/g, String(absoluteIndex)); // {{ index }}
|
|
2423
|
+
// Handle object properties: {{ item.name }}
|
|
2424
|
+
if (typeof item === 'object' && item !== null) {
|
|
2425
|
+
rowHtml = rowHtml.replace(/{{\s*item\.(\w+)\s*}}/g, (_, prop) => {
|
|
2426
|
+
return String(item[prop] || '');
|
|
2427
|
+
});
|
|
2428
|
+
}
|
|
2429
|
+
html += `<div style="height: ${this._itemHeight}px; overflow: hidden;">${rowHtml}</div>`;
|
|
2430
|
+
});
|
|
2431
|
+
this.content.innerHTML = html;
|
|
2629
2432
|
}
|
|
2630
2433
|
}
|
|
2631
|
-
|
|
2434
|
+
// Register
|
|
2435
|
+
if (typeof customElements !== 'undefined' && !customElements.get('mu-infinity')) {
|
|
2436
|
+
customElements.define('mu-infinity', MuInfinity);
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
;// ./src/core/ssr.ts
|
|
2632
2440
|
/**
|
|
2633
|
-
*
|
|
2634
|
-
* Executes different logic branches based on the state of control qubits.
|
|
2635
|
-
* Because the register can be in a superposition of states (e.g. |0> + |1>),
|
|
2636
|
-
* MULTIPLE branches can execute effectively simultaneously on different subspaces.
|
|
2637
|
-
*
|
|
2638
|
-
* @param reg Quantum Register
|
|
2639
|
-
* @param controlQubit The qubit controlling the switch (Single control for v1)
|
|
2640
|
-
* @param cases Object mapping state (0 or 1) to a function executing quantum operations
|
|
2441
|
+
* Renders a Mulan component to a static HTML string with a resumability envelope.
|
|
2641
2442
|
*/
|
|
2642
|
-
function
|
|
2643
|
-
|
|
2644
|
-
|
|
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.`);
|
|
2645
2459
|
}
|
|
2646
|
-
|
|
2647
|
-
|
|
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
|
+
}
|
|
2648
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
|
+
};
|
|
2649
2485
|
}
|
|
2650
|
-
exports.muSwitch = muSwitch;
|
|
2651
2486
|
|
|
2487
|
+
;// ./src/index.ts
|
|
2652
2488
|
|
|
2653
|
-
/***/ }
|
|
2654
2489
|
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2490
|
+
|
|
2491
|
+
|
|
2492
|
+
|
|
2493
|
+
|
|
2494
|
+
|
|
2495
|
+
|
|
2496
|
+
|
|
2497
|
+
|
|
2498
|
+
|
|
2499
|
+
|
|
2500
|
+
|
|
2501
|
+
|
|
2502
|
+
// Global Mulan Object for non-module usage
|
|
2503
|
+
|
|
2504
|
+
|
|
2505
|
+
|
|
2506
|
+
|
|
2507
|
+
|
|
2508
|
+
|
|
2509
|
+
|
|
2510
|
+
|
|
2511
|
+
|
|
2512
|
+
|
|
2513
|
+
|
|
2514
|
+
const Mulan = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ reactive: reactive,
|
|
2515
|
+
effect: effect, Component: MuComponent, defineComponent: defineComponent, Router: MuRouter, createRouter: createRouter, Store: MuStore, Security: Security }, hooks_namespaceObject), query_namespaceObject), quantum_namespaceObject), surge_namespaceObject), infinity_list_namespaceObject), { render: render,
|
|
2516
|
+
// MULAN INSIGHT: Branded Logging
|
|
2517
|
+
log: (msg, ...args) => {
|
|
2518
|
+
console.log(`%c[MulanJS]%c ${msg}`, "color: #ff3e00; font-weight: bold; background: #222; padding: 2px 4px; border-radius: 3px;", "", ...args);
|
|
2519
|
+
}, warn: (msg, ...args) => {
|
|
2520
|
+
console.warn(`%c[MulanJS]%c ${msg}`, "color: #ffcc00; font-weight: bold; background: #222; padding: 2px 4px; border-radius: 3px;", "", ...args);
|
|
2521
|
+
}, error: (msg, ...args) => {
|
|
2522
|
+
console.error(`%c[MulanJS]%c ${msg}`, "color: #ff0000; font-weight: bold; background: #222; padding: 2px 4px; border-radius: 3px;", "", ...args);
|
|
2523
|
+
} });
|
|
2524
|
+
// Security: Freeze the object to prevent runtime tampering
|
|
2525
|
+
Object.freeze(Mulan);
|
|
2526
|
+
Object.freeze(Mulan.Security);
|
|
2527
|
+
// MULAN INSIGHT: Initialize Global Registry
|
|
2528
|
+
if (typeof window !== 'undefined') {
|
|
2529
|
+
window.__MULAN_INSIGHT__ = window.__MULAN_INSIGHT__ || { components: new Map() };
|
|
2530
|
+
// MULAN INSIGHT: HMR Support
|
|
2531
|
+
window.__MULAN_REFRESH__ = () => {
|
|
2532
|
+
var _a;
|
|
2533
|
+
const components = (_a = window.__MULAN_INSIGHT__) === null || _a === void 0 ? void 0 : _a.components;
|
|
2534
|
+
if (components) {
|
|
2535
|
+
components.forEach((comp) => {
|
|
2536
|
+
if (comp && typeof comp.update === 'function') {
|
|
2537
|
+
// Force refresh
|
|
2538
|
+
comp.update();
|
|
2539
|
+
}
|
|
2540
|
+
});
|
|
2541
|
+
}
|
|
2542
|
+
};
|
|
2543
|
+
}
|
|
2544
|
+
if (typeof window !== 'undefined') {
|
|
2545
|
+
window.Mulan = Mulan;
|
|
2546
|
+
}
|
|
2547
|
+
/* harmony default export */ const src = (Mulan);
|
|
2548
|
+
|
|
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 };
|
|
2689
2550
|
|
|
2690
2551
|
//# sourceMappingURL=mulan.esm.js.map
|