jaclang 0.8.8__py3-none-any.whl → 0.8.10__py3-none-any.whl
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.
Potentially problematic release.
This version of jaclang might be problematic. Click here for more details.
- jaclang/cli/cli.py +194 -10
- jaclang/cli/cmdreg.py +144 -8
- jaclang/compiler/__init__.py +6 -1
- jaclang/compiler/codeinfo.py +16 -1
- jaclang/compiler/constant.py +33 -8
- jaclang/compiler/jac.lark +154 -62
- jaclang/compiler/larkparse/jac_parser.py +2 -2
- jaclang/compiler/parser.py +656 -149
- jaclang/compiler/passes/__init__.py +2 -1
- jaclang/compiler/passes/ast_gen/__init__.py +5 -0
- jaclang/compiler/passes/ast_gen/base_ast_gen_pass.py +54 -0
- jaclang/compiler/passes/ast_gen/jsx_processor.py +344 -0
- jaclang/compiler/passes/ecmascript/__init__.py +25 -0
- jaclang/compiler/passes/ecmascript/es_unparse.py +576 -0
- jaclang/compiler/passes/ecmascript/esast_gen_pass.py +2068 -0
- jaclang/compiler/passes/ecmascript/estree.py +972 -0
- jaclang/compiler/passes/ecmascript/tests/__init__.py +1 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/advanced_language_features.jac +170 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.impl.jac +30 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.jac +14 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/client_jsx.jac +89 -0
- jaclang/compiler/passes/ecmascript/tests/fixtures/core_language_features.jac +195 -0
- jaclang/compiler/passes/ecmascript/tests/test_esast_gen_pass.py +167 -0
- jaclang/compiler/passes/ecmascript/tests/test_js_generation.py +239 -0
- jaclang/compiler/passes/main/__init__.py +0 -3
- jaclang/compiler/passes/main/annex_pass.py +23 -1
- jaclang/compiler/passes/main/def_use_pass.py +1 -0
- jaclang/compiler/passes/main/pyast_gen_pass.py +413 -255
- jaclang/compiler/passes/main/pyast_load_pass.py +48 -11
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +2 -0
- jaclang/compiler/passes/main/sym_tab_build_pass.py +18 -1
- jaclang/compiler/passes/main/tests/fixtures/autoimpl.cl.jac +7 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +3 -0
- jaclang/compiler/passes/main/tests/fixtures/checker_class_construct.jac +33 -0
- jaclang/compiler/passes/main/tests/fixtures/defuse_modpath.jac +7 -0
- jaclang/compiler/passes/main/tests/fixtures/member_access_type_resolve.jac +2 -1
- jaclang/compiler/passes/main/tests/test_checker_pass.py +31 -3
- jaclang/compiler/passes/main/tests/test_def_use_pass.py +12 -0
- jaclang/compiler/passes/main/tests/test_import_pass.py +23 -4
- jaclang/compiler/passes/main/tests/test_predynamo_pass.py +13 -14
- jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +25 -0
- jaclang/compiler/passes/main/type_checker_pass.py +7 -0
- jaclang/compiler/passes/tool/doc_ir_gen_pass.py +219 -20
- jaclang/compiler/passes/tool/fuse_comments_pass.py +1 -10
- jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -2
- jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +7 -1
- jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +135 -29
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +4 -1
- jaclang/compiler/passes/transform.py +9 -1
- jaclang/compiler/passes/uni_pass.py +5 -7
- jaclang/compiler/program.py +27 -26
- jaclang/compiler/tests/test_client_codegen.py +113 -0
- jaclang/compiler/tests/test_importer.py +12 -10
- jaclang/compiler/tests/test_parser.py +249 -3
- jaclang/compiler/type_system/type_evaluator.jac +1078 -0
- jaclang/compiler/type_system/type_utils.py +1 -1
- jaclang/compiler/type_system/types.py +6 -0
- jaclang/compiler/unitree.py +438 -82
- jaclang/langserve/engine.jac +224 -288
- jaclang/langserve/sem_manager.jac +12 -8
- jaclang/langserve/server.jac +48 -48
- jaclang/langserve/tests/fixtures/greet.py +17 -0
- jaclang/langserve/tests/fixtures/md_path.jac +22 -0
- jaclang/langserve/tests/fixtures/user.jac +15 -0
- jaclang/langserve/tests/test_server.py +66 -371
- jaclang/lib.py +17 -0
- jaclang/runtimelib/archetype.py +25 -25
- jaclang/runtimelib/client_bundle.py +169 -0
- jaclang/runtimelib/client_runtime.jac +586 -0
- jaclang/runtimelib/constructs.py +4 -2
- jaclang/runtimelib/machine.py +308 -139
- jaclang/runtimelib/meta_importer.py +111 -22
- jaclang/runtimelib/mtp.py +15 -0
- jaclang/runtimelib/server.py +1089 -0
- jaclang/runtimelib/tests/fixtures/client_app.jac +18 -0
- jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
- jaclang/runtimelib/tests/fixtures/savable_object.jac +4 -5
- jaclang/runtimelib/tests/fixtures/serve_api.jac +75 -0
- jaclang/runtimelib/tests/test_client_bundle.py +55 -0
- jaclang/runtimelib/tests/test_client_render.py +63 -0
- jaclang/runtimelib/tests/test_serve.py +1069 -0
- jaclang/settings.py +0 -3
- jaclang/tests/fixtures/attr_pattern_case.jac +18 -0
- jaclang/tests/fixtures/funccall_genexpr.jac +7 -0
- jaclang/tests/fixtures/funccall_genexpr.py +5 -0
- jaclang/tests/fixtures/iife_functions.jac +142 -0
- jaclang/tests/fixtures/iife_functions_client.jac +143 -0
- jaclang/tests/fixtures/multistatement_lambda.jac +116 -0
- jaclang/tests/fixtures/multistatement_lambda_client.jac +113 -0
- jaclang/tests/fixtures/needs_import_dup.jac +6 -4
- jaclang/tests/fixtures/py2jac_empty.py +0 -0
- jaclang/tests/fixtures/py_run.py +7 -5
- jaclang/tests/fixtures/pyfunc_fstr.py +2 -2
- jaclang/tests/fixtures/simple_lambda_test.jac +12 -0
- jaclang/tests/test_cli.py +134 -18
- jaclang/tests/test_language.py +120 -32
- jaclang/tests/test_reference.py +20 -3
- jaclang/utils/NonGPT.py +375 -0
- jaclang/utils/helpers.py +64 -20
- jaclang/utils/lang_tools.py +31 -4
- jaclang/utils/tests/test_lang_tools.py +5 -16
- jaclang/utils/treeprinter.py +8 -3
- {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/METADATA +3 -3
- {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/RECORD +106 -71
- jaclang/compiler/passes/main/binder_pass.py +0 -594
- jaclang/compiler/passes/main/tests/fixtures/sym_binder.jac +0 -47
- jaclang/compiler/passes/main/tests/test_binder_pass.py +0 -111
- jaclang/compiler/type_system/type_evaluator.py +0 -844
- jaclang/langserve/tests/session.jac +0 -294
- jaclang/langserve/tests/test_dev_server.py +0 -80
- jaclang/runtimelib/importer.py +0 -351
- jaclang/tests/test_typecheck.py +0 -542
- {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/WHEEL +0 -0
- {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
"""Client-side runtime for Jac JSX and walker interactions."""
|
|
2
|
+
|
|
3
|
+
# JSX factory function
|
|
4
|
+
cl def __jacJsx(tag: any, props: dict = {}, children: list = []) -> dict {
|
|
5
|
+
return {"tag": tag, "props": props, "children": children};
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
# DOM rendering function
|
|
9
|
+
cl def renderJsxTree(node: any, container: any) -> None {
|
|
10
|
+
container.replaceChildren(__buildDom(node));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
# Internal: Build DOM from JSX tree
|
|
14
|
+
cl def __buildDom(node: any) -> any {
|
|
15
|
+
if node == None {
|
|
16
|
+
return document.createTextNode("");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if not __isObject(node) {
|
|
20
|
+
return document.createTextNode(String(node));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
# Handle component functions
|
|
24
|
+
tag = node.get("tag");
|
|
25
|
+
if __isFunction(tag) {
|
|
26
|
+
props = node.get("props", {});
|
|
27
|
+
return __buildDom(tag(props));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# Create element
|
|
31
|
+
element = document.createElement(tag if tag else "div");
|
|
32
|
+
|
|
33
|
+
# Apply properties
|
|
34
|
+
props = node.get("props", {});
|
|
35
|
+
for key in __objectKeys(props) {
|
|
36
|
+
value = props.get(key);
|
|
37
|
+
__applyProp(element, key, value);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# Render children
|
|
41
|
+
children = node.get("children", []);
|
|
42
|
+
for child in children {
|
|
43
|
+
childDom = __buildDom(child);
|
|
44
|
+
if childDom {
|
|
45
|
+
element.appendChild(childDom);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return element;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Internal: Apply property to DOM element
|
|
53
|
+
cl def __applyProp(element: any, key: str, value: any) -> None {
|
|
54
|
+
if key.startswith("on") {
|
|
55
|
+
# Event handler: onclick -> click
|
|
56
|
+
event = key[2:].lower();
|
|
57
|
+
element.addEventListener(event, value);
|
|
58
|
+
} elif key == "className" or key == "class" {
|
|
59
|
+
element.className = value;
|
|
60
|
+
} elif key == "style" and __isObject(value) {
|
|
61
|
+
# Style object
|
|
62
|
+
for styleKey in __objectKeys(value) {
|
|
63
|
+
element.style[styleKey] = value.get(styleKey);
|
|
64
|
+
}
|
|
65
|
+
} elif key != "children" {
|
|
66
|
+
element.setAttribute(key, String(value));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Walker spawn function
|
|
71
|
+
cl async def __jacSpawn(walker: str, fields: dict = {}) -> any {
|
|
72
|
+
token = __getLocalStorage("jac_token");
|
|
73
|
+
|
|
74
|
+
response = await fetch(
|
|
75
|
+
f"/walker/{walker}",
|
|
76
|
+
{
|
|
77
|
+
"method": "POST",
|
|
78
|
+
"headers": {
|
|
79
|
+
"Content-Type": "application/json",
|
|
80
|
+
"Authorization": f"Bearer {token}" if token else ""
|
|
81
|
+
},
|
|
82
|
+
"body": JSON.stringify({"nd": "root", **fields})
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
if not response.ok {
|
|
87
|
+
error_text = await response.text();
|
|
88
|
+
raise Exception(f"Walker {walker} failed: {error_text}");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return JSON.parse(await response.text());
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# Function call function - calls server-side functions from client
|
|
95
|
+
cl async def __jacCallFunction(function_name: str, args: dict = {}) -> any {
|
|
96
|
+
token = __getLocalStorage("jac_token");
|
|
97
|
+
|
|
98
|
+
response = await fetch(
|
|
99
|
+
f"/function/{function_name}",
|
|
100
|
+
{
|
|
101
|
+
"method": "POST",
|
|
102
|
+
"headers": {
|
|
103
|
+
"Content-Type": "application/json",
|
|
104
|
+
"Authorization": f"Bearer {token}" if token else ""
|
|
105
|
+
},
|
|
106
|
+
"body": JSON.stringify({"args": args})
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
if not response.ok {
|
|
111
|
+
error_text = await response.text();
|
|
112
|
+
raise Exception(f"Function {function_name} failed: {error_text}");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
data = JSON.parse(await response.text());
|
|
116
|
+
return data.get("result");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# Authentication helpers
|
|
120
|
+
cl async def jacSignup(username: str, password: str) -> dict {
|
|
121
|
+
response = await fetch(
|
|
122
|
+
"/user/create",
|
|
123
|
+
{
|
|
124
|
+
"method": "POST",
|
|
125
|
+
"headers": {"Content-Type": "application/json"},
|
|
126
|
+
"body": JSON.stringify({"username": username, "password": password})
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
if response.ok {
|
|
131
|
+
data = JSON.parse(await response.text());
|
|
132
|
+
token = data.get("token");
|
|
133
|
+
if token {
|
|
134
|
+
__setLocalStorage("jac_token", token);
|
|
135
|
+
return {"success": True, "token": token, "username": username};
|
|
136
|
+
}
|
|
137
|
+
return {"success": False, "error": "No token received"};
|
|
138
|
+
} else {
|
|
139
|
+
error_text = await response.text();
|
|
140
|
+
try {
|
|
141
|
+
error_data = JSON.parse(error_text);
|
|
142
|
+
return {"success": False, "error": error_data.get("error", "Signup failed")};
|
|
143
|
+
} except Exception {
|
|
144
|
+
return {"success": False, "error": error_text};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
cl async def jacLogin(username: str, password: str) -> bool {
|
|
150
|
+
response = await fetch(
|
|
151
|
+
"/user/login",
|
|
152
|
+
{
|
|
153
|
+
"method": "POST",
|
|
154
|
+
"headers": {"Content-Type": "application/json"},
|
|
155
|
+
"body": JSON.stringify({"username": username, "password": password})
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
if response.ok {
|
|
160
|
+
data = JSON.parse(await response.text());
|
|
161
|
+
token = data.get("token");
|
|
162
|
+
if token {
|
|
163
|
+
__setLocalStorage("jac_token", token);
|
|
164
|
+
return True;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return False;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
cl def jacLogout() -> None {
|
|
171
|
+
__removeLocalStorage("jac_token");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
cl def jacIsLoggedIn() -> bool {
|
|
175
|
+
token = __getLocalStorage("jac_token");
|
|
176
|
+
return token != None and token != "";
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
# Browser API shims
|
|
180
|
+
cl def __getLocalStorage(key: str) -> str {
|
|
181
|
+
storage = globalThis.localStorage;
|
|
182
|
+
return storage.getItem(key) if storage else "";
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
cl def __setLocalStorage(key: str, value: str) -> None {
|
|
186
|
+
storage = globalThis.localStorage;
|
|
187
|
+
if storage {
|
|
188
|
+
storage.setItem(key, value);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
cl def __removeLocalStorage(key: str) -> None {
|
|
193
|
+
storage = globalThis.localStorage;
|
|
194
|
+
if storage {
|
|
195
|
+
storage.removeItem(key);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
cl def __isObject(value: any) -> bool {
|
|
200
|
+
if value == None {
|
|
201
|
+
return False;
|
|
202
|
+
}
|
|
203
|
+
return Object.prototype.toString.call(value) == "[object Object]";
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
cl def __isFunction(value: any) -> bool {
|
|
207
|
+
return Object.prototype.toString.call(value) == "[object Function]";
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
cl def __objectKeys(obj: any) -> list {
|
|
211
|
+
if obj == None {
|
|
212
|
+
return [];
|
|
213
|
+
}
|
|
214
|
+
return Object.keys(obj);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
# Low-level helpers
|
|
218
|
+
cl def __jacHasOwn(obj: any, key: any) -> bool {
|
|
219
|
+
try {
|
|
220
|
+
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
221
|
+
} except Exception {
|
|
222
|
+
return False;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
# Internal polyfill for Python-style dict.get on plain JS objects
|
|
227
|
+
cl def __jacEnsureObjectGetPolyfill() -> None {
|
|
228
|
+
proto = Object.prototype;
|
|
229
|
+
if proto.get {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
# Define the polyfill function inline
|
|
234
|
+
def get_polyfill(key: any, defaultValue: any = None) -> any {
|
|
235
|
+
if __jacHasOwn(this, key) {
|
|
236
|
+
return this[key];
|
|
237
|
+
}
|
|
238
|
+
if defaultValue != None {
|
|
239
|
+
return defaultValue;
|
|
240
|
+
}
|
|
241
|
+
return None;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
Object.defineProperty(
|
|
245
|
+
proto,
|
|
246
|
+
"get",
|
|
247
|
+
{
|
|
248
|
+
"value": get_polyfill,
|
|
249
|
+
"configurable": True,
|
|
250
|
+
"writable": True
|
|
251
|
+
}
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
# Common utility helpers
|
|
256
|
+
cl def __jacGetDocument(scope: any) -> any {
|
|
257
|
+
try {
|
|
258
|
+
return scope.document;
|
|
259
|
+
} except Exception {
|
|
260
|
+
return None;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
cl def __jacParseJsonObject(text: str) -> any {
|
|
265
|
+
try {
|
|
266
|
+
parsed = JSON.parse(text);
|
|
267
|
+
if __isObject(parsed) {
|
|
268
|
+
return parsed;
|
|
269
|
+
}
|
|
270
|
+
console.error("[Jac] Hydration payload is not an object");
|
|
271
|
+
return None;
|
|
272
|
+
} except Exception as err {
|
|
273
|
+
console.error("[Jac] Failed to parse hydration payload", err);
|
|
274
|
+
return None;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
cl def __jacBuildOrderedArgs(order: list, argsDict: dict) -> list {
|
|
279
|
+
result = [];
|
|
280
|
+
if not order {
|
|
281
|
+
return result;
|
|
282
|
+
}
|
|
283
|
+
values = argsDict if __isObject(argsDict) else {};
|
|
284
|
+
for name in order {
|
|
285
|
+
result.push(values.get(name));
|
|
286
|
+
}
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
cl def __jacResolveRenderer(scope: any) -> any {
|
|
291
|
+
if scope.renderJsxTree {
|
|
292
|
+
return scope.renderJsxTree;
|
|
293
|
+
}
|
|
294
|
+
if __isFunction(renderJsxTree) {
|
|
295
|
+
return renderJsxTree;
|
|
296
|
+
}
|
|
297
|
+
return None;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
cl def __jacResolveTarget(
|
|
301
|
+
moduleRecord: dict,
|
|
302
|
+
registry: dict,
|
|
303
|
+
name: str
|
|
304
|
+
) -> any {
|
|
305
|
+
moduleFunctions = (
|
|
306
|
+
moduleRecord.moduleFunctions
|
|
307
|
+
if moduleRecord and moduleRecord.moduleFunctions
|
|
308
|
+
else {}
|
|
309
|
+
);
|
|
310
|
+
if __jacHasOwn(moduleFunctions, name) {
|
|
311
|
+
return moduleFunctions[name];
|
|
312
|
+
}
|
|
313
|
+
registryFunctions = (
|
|
314
|
+
registry.functions
|
|
315
|
+
if registry and registry.functions
|
|
316
|
+
else {}
|
|
317
|
+
);
|
|
318
|
+
if __jacHasOwn(registryFunctions, name) {
|
|
319
|
+
return registryFunctions[name];
|
|
320
|
+
}
|
|
321
|
+
return None;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
cl def __jacSafeCallTarget(
|
|
325
|
+
target: any,
|
|
326
|
+
scope: any,
|
|
327
|
+
orderedArgs: list,
|
|
328
|
+
targetName: str
|
|
329
|
+
) -> dict {
|
|
330
|
+
try {
|
|
331
|
+
result = target.apply(scope, orderedArgs);
|
|
332
|
+
return {"ok": True, "value": result};
|
|
333
|
+
} except Exception as err {
|
|
334
|
+
console.error("[Jac] Error executing client function " + targetName, err);
|
|
335
|
+
return {"ok": False, "value": None};
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
# Runtime support helpers for client module registration / hydration
|
|
340
|
+
cl def __jacGlobalScope() -> any {
|
|
341
|
+
try {
|
|
342
|
+
return globalThis;
|
|
343
|
+
} except Exception {}
|
|
344
|
+
try {
|
|
345
|
+
return window;
|
|
346
|
+
} except Exception {}
|
|
347
|
+
try {
|
|
348
|
+
return self;
|
|
349
|
+
} except Exception {}
|
|
350
|
+
return {};
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
cl def __jacEnsureRegistry() -> dict {
|
|
354
|
+
scope = __jacGlobalScope();
|
|
355
|
+
registry = scope.__jacClient;
|
|
356
|
+
if not registry {
|
|
357
|
+
registry = {
|
|
358
|
+
"functions": {},
|
|
359
|
+
"globals": {},
|
|
360
|
+
"modules": {},
|
|
361
|
+
"state": {"globals": {}},
|
|
362
|
+
"__hydration": {"registered": False},
|
|
363
|
+
"lastModule": None
|
|
364
|
+
};
|
|
365
|
+
scope.__jacClient = registry;
|
|
366
|
+
return registry;
|
|
367
|
+
}
|
|
368
|
+
if not registry.functions {
|
|
369
|
+
registry.functions = {};
|
|
370
|
+
}
|
|
371
|
+
if not registry.globals {
|
|
372
|
+
registry.globals = {};
|
|
373
|
+
}
|
|
374
|
+
if not registry.modules {
|
|
375
|
+
registry.modules = {};
|
|
376
|
+
}
|
|
377
|
+
if not registry.state {
|
|
378
|
+
registry.state = {"globals": {}};
|
|
379
|
+
} elif not registry.state.globals {
|
|
380
|
+
registry.state.globals = {};
|
|
381
|
+
}
|
|
382
|
+
if not registry.__hydration {
|
|
383
|
+
registry.__hydration = {"registered": False};
|
|
384
|
+
}
|
|
385
|
+
return registry;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
cl def __jacApplyRender(renderer: any, container: any, node: any) -> None {
|
|
389
|
+
if not renderer or not container {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
try {
|
|
393
|
+
renderer(node, container);
|
|
394
|
+
} except Exception as err {
|
|
395
|
+
console.error("[Jac] Failed to render JSX tree", err);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
cl def __jacHydrateFromDom(defaultModuleName: str) -> None {
|
|
400
|
+
__jacEnsureObjectGetPolyfill();
|
|
401
|
+
scope = __jacGlobalScope();
|
|
402
|
+
documentRef = __jacGetDocument(scope);
|
|
403
|
+
if not documentRef {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
initEl = documentRef.getElementById("__jac_init__");
|
|
408
|
+
rootEl = documentRef.getElementById("__jac_root");
|
|
409
|
+
if not initEl or not rootEl {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
dataset = initEl.dataset if initEl.dataset else None;
|
|
414
|
+
if dataset and dataset.jacHydrated == "true" {
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
if dataset {
|
|
418
|
+
dataset.jacHydrated = "true";
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
payloadText = initEl.textContent if initEl.textContent else "{}";
|
|
422
|
+
payload = __jacParseJsonObject(payloadText);
|
|
423
|
+
if not payload {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
targetName = payload.get("function");
|
|
428
|
+
if not targetName {
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
fallbackModule = defaultModuleName if defaultModuleName else "";
|
|
433
|
+
moduleCandidate = payload.get("module");
|
|
434
|
+
moduleName = moduleCandidate if moduleCandidate else fallbackModule;
|
|
435
|
+
|
|
436
|
+
registry = __jacEnsureRegistry();
|
|
437
|
+
modulesStore = registry.modules if registry.modules else {};
|
|
438
|
+
moduleRecord = modulesStore[moduleName] if __jacHasOwn(modulesStore, moduleName) else None;
|
|
439
|
+
if not moduleRecord {
|
|
440
|
+
console.error("[Jac] Client module not registered: " + moduleName);
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
argOrderRaw = payload.get("argOrder", []);
|
|
445
|
+
argOrder = argOrderRaw if Array.isArray(argOrderRaw) else [];
|
|
446
|
+
argsDictRaw = payload.get("args", {});
|
|
447
|
+
argsDict = argsDictRaw if __isObject(argsDictRaw) else {};
|
|
448
|
+
orderedArgs = __jacBuildOrderedArgs(argOrder, argsDict);
|
|
449
|
+
|
|
450
|
+
payloadGlobalsRaw = payload.get("globals", {});
|
|
451
|
+
payloadGlobals = payloadGlobalsRaw if __isObject(payloadGlobalsRaw) else {};
|
|
452
|
+
registry.state.globals[moduleName] = payloadGlobals;
|
|
453
|
+
for gName in __objectKeys(payloadGlobals) {
|
|
454
|
+
gValue = payloadGlobals[gName];
|
|
455
|
+
scope[gName] = gValue;
|
|
456
|
+
registry.globals[gName] = gValue;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
target = __jacResolveTarget(moduleRecord, registry, targetName);
|
|
460
|
+
if not target {
|
|
461
|
+
console.error("[Jac] Client function not found: " + targetName);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
renderer = __jacResolveRenderer(scope);
|
|
466
|
+
if not renderer {
|
|
467
|
+
console.warn("[Jac] renderJsxTree is not available in client bundle");
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
callOutcome = __jacSafeCallTarget(target, scope, orderedArgs, targetName);
|
|
471
|
+
if not callOutcome or not callOutcome.get("ok") {
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
value = callOutcome.get("value");
|
|
475
|
+
|
|
476
|
+
if value and __isObject(value) and __isFunction(value.then) {
|
|
477
|
+
value.then(
|
|
478
|
+
lambda node: any -> None {
|
|
479
|
+
__jacApplyRender(renderer, rootEl, node);
|
|
480
|
+
}
|
|
481
|
+
).catch(
|
|
482
|
+
lambda err: any -> None {
|
|
483
|
+
console.error("[Jac] Error resolving client function promise", err);
|
|
484
|
+
}
|
|
485
|
+
);
|
|
486
|
+
} else {
|
|
487
|
+
__jacApplyRender(renderer, rootEl, value);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
cl def __jacExecuteHydration() -> None {
|
|
492
|
+
registry = __jacEnsureRegistry();
|
|
493
|
+
defaultModule = registry.lastModule if registry.lastModule else "";
|
|
494
|
+
__jacHydrateFromDom(defaultModule);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
cl def __jacEnsureHydration(moduleName: str) -> None {
|
|
498
|
+
__jacEnsureObjectGetPolyfill();
|
|
499
|
+
registry = __jacEnsureRegistry();
|
|
500
|
+
registry.lastModule = moduleName;
|
|
501
|
+
|
|
502
|
+
existingHydration = registry.__hydration if registry.__hydration else None;
|
|
503
|
+
hydration = existingHydration if existingHydration else {"registered": False};
|
|
504
|
+
registry.__hydration = hydration;
|
|
505
|
+
|
|
506
|
+
scope = __jacGlobalScope();
|
|
507
|
+
documentRef = __jacGetDocument(scope);
|
|
508
|
+
if not documentRef {
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
alreadyRegistered = hydration.registered if hydration.registered else False;
|
|
513
|
+
if not alreadyRegistered {
|
|
514
|
+
hydration.registered = True;
|
|
515
|
+
documentRef.addEventListener(
|
|
516
|
+
"DOMContentLoaded",
|
|
517
|
+
lambda _event: any -> None {
|
|
518
|
+
__jacExecuteHydration();
|
|
519
|
+
},
|
|
520
|
+
{"once": True}
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
if documentRef.readyState != "loading" {
|
|
525
|
+
__jacExecuteHydration();
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
cl def __jacRegisterClientModule(
|
|
530
|
+
moduleName: str,
|
|
531
|
+
clientFunctions: list = [],
|
|
532
|
+
clientGlobals: dict = {}
|
|
533
|
+
) -> None {
|
|
534
|
+
__jacEnsureObjectGetPolyfill();
|
|
535
|
+
scope = __jacGlobalScope();
|
|
536
|
+
registry = __jacEnsureRegistry();
|
|
537
|
+
|
|
538
|
+
moduleFunctions = {};
|
|
539
|
+
registeredFunctions = [];
|
|
540
|
+
if clientFunctions {
|
|
541
|
+
for funcName in clientFunctions {
|
|
542
|
+
funcRef = scope[funcName];
|
|
543
|
+
if not funcRef {
|
|
544
|
+
console.error("[Jac] Client function not found during registration: " + funcName);
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
moduleFunctions[funcName] = funcRef;
|
|
548
|
+
registry.functions[funcName] = funcRef;
|
|
549
|
+
scope[funcName] = funcRef;
|
|
550
|
+
registeredFunctions.push(funcName);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
moduleGlobals = {};
|
|
555
|
+
globalNames = [];
|
|
556
|
+
globalsMap = clientGlobals if clientGlobals else {};
|
|
557
|
+
for gName in __objectKeys(globalsMap) {
|
|
558
|
+
globalNames.push(gName);
|
|
559
|
+
defaultValue = globalsMap[gName];
|
|
560
|
+
existing = scope[gName];
|
|
561
|
+
if existing == None {
|
|
562
|
+
scope[gName] = defaultValue;
|
|
563
|
+
moduleGlobals[gName] = defaultValue;
|
|
564
|
+
} else {
|
|
565
|
+
moduleGlobals[gName] = existing;
|
|
566
|
+
}
|
|
567
|
+
registry.globals[gName] = scope[gName];
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
modulesStore = registry.modules if registry.modules else {};
|
|
571
|
+
existingRecord = modulesStore[moduleName] if __jacHasOwn(modulesStore, moduleName) else None;
|
|
572
|
+
moduleRecord = existingRecord if existingRecord else {};
|
|
573
|
+
moduleRecord.moduleFunctions = moduleFunctions;
|
|
574
|
+
moduleRecord.moduleGlobals = moduleGlobals;
|
|
575
|
+
moduleRecord.functions = registeredFunctions;
|
|
576
|
+
moduleRecord.globals = globalNames;
|
|
577
|
+
moduleRecord.defaults = globalsMap;
|
|
578
|
+
registry.modules[moduleName] = moduleRecord;
|
|
579
|
+
|
|
580
|
+
stateGlobals = registry.state.globals;
|
|
581
|
+
if not __jacHasOwn(stateGlobals, moduleName) {
|
|
582
|
+
stateGlobals[moduleName] = {};
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
__jacEnsureHydration(moduleName);
|
|
586
|
+
}
|
jaclang/runtimelib/constructs.py
CHANGED
|
@@ -7,17 +7,18 @@ from .archetype import (
|
|
|
7
7
|
AccessLevel,
|
|
8
8
|
Anchor,
|
|
9
9
|
Archetype,
|
|
10
|
-
DataSpatialFunction,
|
|
11
10
|
EdgeAnchor,
|
|
12
11
|
EdgeArchetype,
|
|
13
12
|
GenericEdge,
|
|
14
13
|
NodeAnchor,
|
|
15
14
|
NodeArchetype,
|
|
15
|
+
ObjectSpatialFunction,
|
|
16
16
|
Root,
|
|
17
17
|
WalkerAnchor,
|
|
18
18
|
WalkerArchetype,
|
|
19
19
|
)
|
|
20
20
|
from .memory import Memory, ShelfStorage
|
|
21
|
+
from .mtp import MTIR
|
|
21
22
|
from .test import JacTestCheck, JacTestResult, JacTextTestRunner
|
|
22
23
|
|
|
23
24
|
__all__ = [
|
|
@@ -32,7 +33,8 @@ __all__ = [
|
|
|
32
33
|
"WalkerArchetype",
|
|
33
34
|
"GenericEdge",
|
|
34
35
|
"Root",
|
|
35
|
-
"
|
|
36
|
+
"MTIR",
|
|
37
|
+
"ObjectSpatialFunction",
|
|
36
38
|
"Memory",
|
|
37
39
|
"ShelfStorage",
|
|
38
40
|
"JacTestResult",
|