/src/moddable/xs/sources/xsModule.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2016-2017 Moddable Tech, Inc. |
3 | | * |
4 | | * This file is part of the Moddable SDK Runtime. |
5 | | * |
6 | | * The Moddable SDK Runtime is free software: you can redistribute it and/or modify |
7 | | * it under the terms of the GNU Lesser General Public License as published by |
8 | | * the Free Software Foundation, either version 3 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * The Moddable SDK Runtime is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public License |
17 | | * along with the Moddable SDK Runtime. If not, see <http://www.gnu.org/licenses/>. |
18 | | * |
19 | | * This file incorporates work covered by the following copyright and |
20 | | * permission notice: |
21 | | * |
22 | | * Copyright (C) 2010-2016 Marvell International Ltd. |
23 | | * Copyright (C) 2002-2010 Kinoma, Inc. |
24 | | * |
25 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
26 | | * you may not use this file except in compliance with the License. |
27 | | * You may obtain a copy of the License at |
28 | | * |
29 | | * http://www.apache.org/licenses/LICENSE-2.0 |
30 | | * |
31 | | * Unless required by applicable law or agreed to in writing, software |
32 | | * distributed under the License is distributed on an "AS IS" BASIS, |
33 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
34 | | * See the License for the specific language governing permissions and |
35 | | * limitations under the License. |
36 | | */ |
37 | | |
38 | | #include "xsAll.h" |
39 | | |
40 | | #ifndef mxReport |
41 | | #define mxReport 0 |
42 | | #endif |
43 | | |
44 | | static void fxCheckModuleFlag(txMachine* the, txID moduleID, txFlag moduleFlag, txFlag requestFlag); |
45 | | static txFlag fxCheckModuleOptions(txMachine* the, txSlot* options); |
46 | | static void fxPushModuleOptions(txMachine* the, txFlag moduleFlag); |
47 | | static void fxCompleteModule(txMachine* the, txSlot* module, txSlot* exception); |
48 | | static void fxDuplicateModuleTransfers(txMachine* the, txSlot* srcModule, txSlot* dstModule); |
49 | | |
50 | | static void fxExecuteModules(txMachine* the, txSlot* queue); |
51 | | static txID fxExecuteModulesFrom(txMachine* the, txSlot* queue, txSlot* module, txSlot** exception); |
52 | | |
53 | | static txSlot* fxGetModule(txMachine* the, txSlot* realm, txID moduleID, txFlag moduleFlag); |
54 | | |
55 | | static void fxLinkCircularities(txMachine* the, txSlot* module, txSlot* circularities, txSlot* exports); |
56 | | static void fxLinkExports(txMachine* the, txSlot* module); |
57 | | static void fxLinkLocals(txMachine* the, txSlot* module); |
58 | | static void fxLinkModules(txMachine* the, txSlot* queue); |
59 | | static void fxLinkNamespace(txMachine* the, txSlot* module, txSlot* transfer); |
60 | | static void fxLinkTransfer(txMachine* the, txSlot* module, txID importID, txSlot* transfer); |
61 | | |
62 | | static void fxLoadModules(txMachine* the, txSlot* queue); |
63 | | static void fxLoadModulesFrom(txMachine* the, txSlot* queue, txSlot* module, txBoolean now); |
64 | | |
65 | | static txBoolean fxMapModule(txMachine* the, txSlot* realm, txID moduleID, txSlot* module, txSlot* queue, txSlot* result); |
66 | | static void fxMapModuleDescriptor(txMachine* the, txSlot* realm, txID moduleID, txSlot* module, txSlot* queue, txSlot* result, txSlot* descriptor); |
67 | | static void fxNewModule(txMachine* the, txSlot* realm, txID moduleID, txFlag moduleFlag, txSlot* module); |
68 | | static void fxOrderModule(txMachine* the, txSlot* queue, txSlot* order, txSlot* module); |
69 | | static void fxOverrideModule(txMachine* the, txSlot* queue, txSlot* list, txSlot* result, txSlot* module, txSlot* record); |
70 | | static txBoolean fxQueueModule(txMachine* the, txSlot* queue, txSlot* module); |
71 | | |
72 | | static txID fxResolveSpecifier(txMachine* the, txSlot* realm, txID moduleID, txSlot* name); |
73 | | |
74 | | static txSlot* fxRunImportAux(txMachine* the, txSlot* realm, txSlot* referrer, txSlot* specifier, txSlot* options, txBoolean now); |
75 | | static void fxRunImportFulfilled(txMachine* the, txSlot* module, txSlot* with); |
76 | | static void fxRunImportRejected(txMachine* the, txSlot* module, txSlot* with); |
77 | | |
78 | | static void fxRunImportNow(txMachine* the, txSlot* realm, txSlot* referrer); |
79 | | |
80 | | static txBoolean fxModuleDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot, txFlag mask); |
81 | | static txBoolean fxModuleDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index); |
82 | | static txSlot* fxModuleFindProperty(txMachine* the, txSlot* instance, txID id, txIndex index); |
83 | | static txBoolean fxModuleGetOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot); |
84 | | static txSlot* fxModuleGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag); |
85 | | static txBoolean fxModuleGetPropertyValue(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* receiver, txSlot* value); |
86 | | static txBoolean fxModuleGetPrototype(txMachine* the, txSlot* instance, txSlot* result); |
87 | | static txBoolean fxModuleHasProperty(txMachine* the, txSlot* instance, txID id, txIndex index); |
88 | | static txBoolean fxModuleIsExtensible(txMachine* the, txSlot* instance); |
89 | | static void fxModuleOwnKeys(txMachine* the, txSlot* instance, txFlag flag, txSlot* keys); |
90 | | static int fxModuleOwnKeysCompare(const void* p, const void* q); |
91 | | static txBoolean fxModulePreventExtensions(txMachine* the, txSlot* instance); |
92 | | static txSlot* fxModuleSetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag); |
93 | | static txBoolean fxModuleSetPropertyValue(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* value, txSlot* receiver); |
94 | | static txBoolean fxModuleSetPrototype(txMachine* the, txSlot* instance, txSlot* prototype); |
95 | | |
96 | | static txSlot* fxCheckCompartmentInstance(txMachine* the, txSlot* slot); |
97 | | static void fxPrepareCompartmentFunction(txMachine* the, txSlot* program, txSlot* instance); |
98 | | |
99 | | static txSlot* fxCheckModuleSourceInstance(txMachine* the, txSlot* slot); |
100 | | static txSlot* fxNewModuleSourceInstance(txMachine* the); |
101 | | |
102 | | #if mxModuleStuff |
103 | | static txSlot* fxCheckModuleStuffInstance(txMachine* the, txSlot* slot); |
104 | | static txSlot* fxImportModuleStuff(txMachine* the, txSlot* realm, txSlot* queue, txSlot* reference, txSlot* name, txBoolean now); |
105 | | static txBoolean fxLoadModuleStuffFrom(txMachine* the, txSlot* queue, txSlot* module, txBoolean now); |
106 | | static void fxLoadModuleStuff(txMachine* the, txSlot* queue, txSlot* module, txSlot* stuff); |
107 | | static void fxLoadModuleStuffFulfilled(txMachine* the); |
108 | | static void fxLoadModuleStuffRejected(txMachine* the); |
109 | | #endif |
110 | | |
111 | | const txBehavior ICACHE_FLASH_ATTR gxModuleBehavior = { |
112 | | fxModuleGetProperty, |
113 | | fxModuleSetProperty, |
114 | | fxOrdinaryCall, |
115 | | fxOrdinaryConstruct, |
116 | | fxModuleDefineOwnProperty, |
117 | | fxModuleDeleteProperty, |
118 | | fxModuleGetOwnProperty, |
119 | | fxModuleGetPropertyValue, |
120 | | fxModuleGetPrototype, |
121 | | fxModuleHasProperty, |
122 | | fxModuleIsExtensible, |
123 | | fxModuleOwnKeys, |
124 | | fxModulePreventExtensions, |
125 | | fxModuleSetPropertyValue, |
126 | | fxModuleSetPrototype, |
127 | | }; |
128 | | |
129 | | enum { |
130 | | XS_MODULE_STATUS_NEW = 0, |
131 | | XS_MODULE_STATUS_LOADING, |
132 | | XS_MODULE_STATUS_LOADED, |
133 | | XS_MODULE_STATUS_LINKING, |
134 | | XS_MODULE_STATUS_LINKED, |
135 | | XS_MODULE_STATUS_EXECUTING, |
136 | | XS_MODULE_STATUS_EXECUTED, |
137 | | XS_MODULE_STATUS_ERROR, |
138 | | }; |
139 | | |
140 | | |
141 | | #define mxIsModule(THE_SLOT) \ |
142 | 7 | (((THE_SLOT)->next) && ((THE_SLOT)->next->flag & XS_INTERNAL_FLAG) && ((THE_SLOT)->next->kind == XS_MODULE_KIND)) |
143 | | #define mxIsModuleSource(THE_SLOT) \ |
144 | 166 | (((THE_SLOT)->next) && ((THE_SLOT)->next->flag & XS_INTERNAL_FLAG) && ((THE_SLOT)->next->kind == XS_MODULE_SOURCE_KIND)) |
145 | | |
146 | 12.4k | #define mxModuleInstanceStatus(MODULE) ((MODULE)->next->next->ID) |
147 | 12.0k | #define mxModuleStatus(MODULE) mxModuleInstanceStatus((MODULE)->value.reference) |
148 | | |
149 | | #if mxReport |
150 | | #define mxModuleName(ID) c_strrchr(fxGetKeyName(the, (ID)), '/') |
151 | | #define mxReportModuleQueue(LABEL) fxReportModuleQueue(the, queue, LABEL) |
152 | | static void fxReportModuleQueue(txMachine* the, txSlot* queue, txString label) |
153 | | { |
154 | | static txString STATUS[8] = { |
155 | | "NEW", |
156 | | "LOADING", |
157 | | "LOADED", |
158 | | "LINKING", |
159 | | "LINKED", |
160 | | "EXECUTING", |
161 | | "EXECUTED", |
162 | | "ERROR", |
163 | | }; |
164 | | txSlot* module = queue->next; |
165 | | fprintf(stderr, "%s %p\n", label, queue); |
166 | | while (module) { |
167 | | txString name = (module->ID != XS_NO_ID) ? fxGetKeyName(the, module->ID) : "?"; |
168 | | fprintf(stderr, "\t'%s' %p %s\n", name, module->value.reference, STATUS[mxModuleStatus(module)]); |
169 | | module = module->next; |
170 | | } |
171 | | } |
172 | | #else |
173 | | #define mxReportModuleQueue(LABEL) |
174 | | #endif |
175 | | |
176 | | void fxBuildModule(txMachine* the) |
177 | 24.8k | { |
178 | 24.8k | txSlot* slot; |
179 | | |
180 | 24.8k | fxNewHostFunction(the, mxCallback(fxModuleGetter), 0, XS_NO_ID, XS_NO_ID); |
181 | 24.8k | mxPushUndefined(); |
182 | 24.8k | the->stack->flag = XS_DONT_DELETE_FLAG; |
183 | 24.8k | the->stack->kind = XS_ACCESSOR_KIND; |
184 | 24.8k | the->stack->value.accessor.getter = (the->stack + 1)->value.reference; |
185 | 24.8k | the->stack->value.accessor.setter = C_NULL; |
186 | 24.8k | mxPull(mxModuleAccessor); |
187 | 24.8k | the->stack += 1; |
188 | | |
189 | 24.8k | mxPush(mxObjectPrototype); |
190 | 24.8k | slot = fxLastProperty(the, fxNewObjectInstance(the)); |
191 | 24.8k | slot = fxNextStringXProperty(the, slot, "Module", mxID(_Symbol_toStringTag), XS_GET_ONLY); |
192 | 24.8k | mxModulePrototype = *the->stack; |
193 | 24.8k | mxPop(); |
194 | | |
195 | 24.8k | mxPush(mxObjectPrototype); |
196 | 24.8k | fxNewObjectInstance(the); |
197 | 24.8k | mxTransferPrototype = *the->stack; |
198 | 24.8k | mxPop(); |
199 | | |
200 | 24.8k | mxPush(mxObjectPrototype); |
201 | 24.8k | slot = fxLastProperty(the, fxNewObjectInstance(the)); |
202 | 24.8k | slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_Compartment_prototype_get_globalThis), C_NULL, mxID(_globalThis), XS_DONT_ENUM_FLAG); |
203 | 24.8k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Compartment_prototype_evaluate), 1, mxID(_evaluate), XS_DONT_ENUM_FLAG); |
204 | 24.8k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Compartment_prototype_import), 1, mxID(_import), XS_DONT_ENUM_FLAG); |
205 | 24.8k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Compartment_prototype_importNow), 1, mxID(_importNow), XS_DONT_ENUM_FLAG); |
206 | | // slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Compartment_prototype_module), 1, mxID(_module), XS_DONT_ENUM_FLAG); |
207 | 24.8k | slot = fxNextStringXProperty(the, slot, "Compartment", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); |
208 | 24.8k | mxCompartmentPrototype = *the->stack; |
209 | 24.8k | slot = fxBuildHostConstructor(the, mxCallback(fx_Compartment), 1, mxID(_Compartment)); |
210 | 24.8k | mxCompartmentConstructor = *the->stack; |
211 | 24.8k | mxPop(); |
212 | | |
213 | 24.8k | mxPush(mxObjectPrototype); |
214 | 24.8k | slot = fxLastProperty(the, fxNewObjectInstance(the)); |
215 | 24.8k | slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_ModuleSource_prototype_get_bindings), C_NULL, mxID(_bindings), XS_DONT_ENUM_FLAG); |
216 | 24.8k | slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_ModuleSource_prototype_get_needsImport), C_NULL, mxID(_needsImport), XS_DONT_ENUM_FLAG); |
217 | 24.8k | slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_ModuleSource_prototype_get_needsImportMeta), C_NULL, mxID(_needsImportMeta), XS_DONT_ENUM_FLAG); |
218 | 24.8k | #if mxECMAScript2025 |
219 | 24.8k | slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_ModuleSource_prototype_get_options), C_NULL, mxID(_options), XS_DONT_ENUM_FLAG); |
220 | 24.8k | #endif |
221 | 24.8k | slot = fxNextStringXProperty(the, slot, "ModuleSource", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); |
222 | 24.8k | mxModuleSourcePrototype = *the->stack; |
223 | 24.8k | slot = fxBuildHostConstructor(the, mxCallback(fx_ModuleSource), 1, mxID(_ModuleSource)); |
224 | 24.8k | mxModuleSourceConstructor = *the->stack; |
225 | 24.8k | mxPop(); |
226 | | |
227 | 24.8k | #if mxModuleStuff |
228 | 24.8k | mxPush(mxObjectPrototype); |
229 | 24.8k | slot = fxLastProperty(the, fxNewObjectInstance(the)); |
230 | 24.8k | slot = fxNextStringXProperty(the, slot, "ModuleStuff", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); |
231 | 24.8k | mxModuleStuffPrototype = *the->stack; |
232 | 24.8k | slot = fxBuildHostConstructor(the, mxCallback(fx_ModuleStuff), 1, mxID(_ModuleStuff)); |
233 | 24.8k | mxModuleStuffConstructor = *the->stack; |
234 | 24.8k | mxPop(); |
235 | 24.8k | #endif |
236 | 24.8k | } |
237 | | |
238 | | void fxCheckModuleFlag(txMachine* the, txID moduleID, txFlag moduleFlag, txFlag requestFlag) |
239 | 6.51k | { |
240 | 6.51k | #ifndef mxLink |
241 | 6.51k | if (moduleFlag & XS_JSON_MODULE_FLAG) { |
242 | 0 | if (!(requestFlag & XS_JSON_MODULE_FLAG)) { |
243 | 0 | fxIDToString(the, moduleID, the->nameBuffer, sizeof(the->nameBuffer)); |
244 | 0 | fxThrowMessage(the, C_NULL, 0, XS_TYPE_ERROR, "%s: JSON module", the->nameBuffer); |
245 | 0 | } |
246 | 0 | } |
247 | 6.51k | else { |
248 | 6.51k | if (requestFlag & XS_JSON_MODULE_FLAG) { |
249 | 0 | fxIDToString(the, moduleID, the->nameBuffer, sizeof(the->nameBuffer)); |
250 | 0 | fxThrowMessage(the, C_NULL, 0, XS_TYPE_ERROR, "%s: not a JSON module", the->nameBuffer); |
251 | 0 | } |
252 | 6.51k | } |
253 | 6.51k | #endif |
254 | 6.51k | } |
255 | | |
256 | | void fxPushModuleOptions(txMachine* the, txFlag moduleFlag) |
257 | 60 | { |
258 | 60 | #if mxECMAScript2025 |
259 | 60 | if (moduleFlag & XS_JSON_MODULE_FLAG) { |
260 | 0 | txSlot* optionsInstance = fxNewObject(the); |
261 | 0 | txSlot* withInstance = fxNewObject(the); |
262 | 0 | fxNextSlotProperty(the, optionsInstance, the->stack, mxID(_with), XS_NO_FLAG); |
263 | 0 | mxPop(); |
264 | 0 | fxNextStringProperty(the, withInstance, "json", mxID(_type), XS_NO_FLAG); |
265 | 0 | } |
266 | 60 | else |
267 | 60 | #endif |
268 | 60 | mxPushUndefined(); |
269 | 60 | } |
270 | | |
271 | | txFlag fxCheckModuleOptions(txMachine* the, txSlot* options) |
272 | 6.57k | { |
273 | 6.57k | txFlag moduleFlag = XS_NO_FLAG; |
274 | 6.57k | #if mxECMAScript2025 |
275 | 6.57k | if (!mxIsUndefined(options)) { |
276 | 4 | txSlot* with; |
277 | 4 | if (!mxIsReference(options)) |
278 | 1 | mxTypeError("options: not an object"); |
279 | 3 | mxPushSlot(options); |
280 | 3 | mxGetID(mxID(_with)); |
281 | 3 | with = the->stack; |
282 | 3 | if (!mxIsUndefined(with)) { |
283 | 2 | txSlot* key; |
284 | 2 | txSlot* property; |
285 | 2 | txSlot* value; |
286 | 2 | txInteger count = 0; |
287 | 2 | if (!mxIsReference(with)) |
288 | 0 | mxTypeError("options.with: not an object"); |
289 | 2 | key = fxNewInstance(the); |
290 | 2 | mxBehaviorOwnKeys(the, with->value.reference, XS_EACH_NAME_FLAG, key); |
291 | 2 | mxTemporary(property); |
292 | 6 | while ((key = key->next)) { |
293 | 4 | if (mxBehaviorGetOwnProperty(the, with->value.reference, key->value.at.id, key->value.at.index, property) && !(property->flag & XS_DONT_ENUM_FLAG)) { |
294 | 0 | mxPushSlot(with); |
295 | 0 | mxGetAll(key->value.at.id, key->value.at.index); |
296 | 0 | value = the->stack; |
297 | 0 | count++; |
298 | 0 | if ((value->kind != XS_STRING_KIND) && (value->kind != XS_STRING_X_KIND)) { |
299 | 0 | mxPop(); |
300 | 0 | break; |
301 | 0 | } |
302 | 0 | if ((key->value.at.id == mxID(_type)) && (!c_strcmp(value->value.string, "json"))) { |
303 | 0 | count--; |
304 | 0 | moduleFlag |= XS_JSON_MODULE_FLAG; |
305 | 0 | } |
306 | 0 | mxPop(); |
307 | 0 | } |
308 | 4 | } |
309 | 2 | mxPop(); |
310 | 2 | mxPop(); |
311 | 2 | if (count > 0) |
312 | 0 | mxTypeError("options.with: invalid attributes"); |
313 | 2 | } |
314 | 3 | mxPop(); |
315 | 3 | } |
316 | 6.57k | #endif |
317 | 6.57k | return moduleFlag; |
318 | 6.57k | } |
319 | | |
320 | | void fxCompleteModule(txMachine* the, txSlot* module, txSlot* exception) |
321 | 348 | { |
322 | 348 | if (exception) { |
323 | 258 | txSlot* exports = mxModuleInstanceExports(module); |
324 | 258 | txSlot* meta = mxModuleInstanceMeta(module); |
325 | 258 | if (exports->kind == XS_REFERENCE_KIND) { |
326 | 64 | exports->value.reference->next = C_NULL; |
327 | 64 | } |
328 | 194 | else { |
329 | 194 | fxNewInstance(the); |
330 | 194 | mxPullSlot(exports); |
331 | 194 | } |
332 | 258 | meta->value = exception->value; |
333 | 258 | meta->kind = exception->kind; |
334 | 258 | mxModuleInstanceStatus(module) = XS_MODULE_STATUS_ERROR; |
335 | 258 | } |
336 | 90 | else { |
337 | 90 | mxModuleInstanceStatus(module) = XS_MODULE_STATUS_EXECUTED; |
338 | 90 | } |
339 | 348 | } |
340 | | |
341 | | void fxDuplicateModuleTransfers(txMachine* the, txSlot* srcModule, txSlot* dstModule) |
342 | 113 | { |
343 | 113 | txSlot* srcSlot; |
344 | 113 | txSlot* dstSlot; |
345 | 113 | txSlot* transfer; |
346 | 113 | txSlot* aliases; |
347 | 113 | txSlot* function; |
348 | 113 | srcSlot = mxModuleInternal(srcModule); |
349 | 113 | dstSlot = mxModuleInternal(dstModule); |
350 | 113 | dstSlot->flag |= (srcSlot->flag & (XS_IMPORT_FLAG | XS_IMPORT_META_FLAG)); |
351 | 113 | srcSlot = mxModuleTransfers(srcModule); |
352 | 113 | dstSlot = mxModuleTransfers(dstModule); |
353 | 113 | fxDuplicateInstance(the, srcSlot->value.reference); |
354 | 113 | mxPullSlot(dstSlot); |
355 | 113 | transfer = dstSlot->value.reference->next; |
356 | 334 | while (transfer) { |
357 | 221 | fxDuplicateInstance(the, transfer->value.reference); |
358 | 221 | mxPullSlot(transfer); |
359 | 221 | aliases = mxTransferAliases(transfer); |
360 | 221 | if (aliases->kind == XS_REFERENCE_KIND) { |
361 | 179 | fxDuplicateInstance(the, aliases->value.reference); |
362 | 179 | mxPullSlot(aliases); |
363 | 179 | } |
364 | 221 | transfer = transfer->next; |
365 | 221 | } |
366 | 113 | srcSlot = mxModuleInitialize(srcModule); |
367 | 113 | dstSlot = mxModuleInitialize(dstModule); |
368 | 113 | if (srcSlot->kind == XS_REFERENCE_KIND) { |
369 | 1 | function = fxDuplicateInstance(the, srcSlot->value.reference); |
370 | 1 | mxPullSlot(dstSlot); |
371 | 1 | mxFunctionInstanceHome(function)->value.home.module = dstModule->value.reference; |
372 | 1 | } |
373 | 112 | else { |
374 | 112 | dstSlot->kind = srcSlot->kind; |
375 | 112 | dstSlot->value = srcSlot->value; |
376 | 112 | } |
377 | 113 | srcSlot = mxModuleExecute(srcModule); |
378 | 113 | dstSlot = mxModuleExecute(dstModule); |
379 | 113 | function = fxDuplicateInstance(the, srcSlot->value.reference); |
380 | 113 | mxPullSlot(dstSlot); |
381 | 113 | mxFunctionInstanceHome(function)->value.home.module = dstModule->value.reference; |
382 | 113 | } |
383 | | |
384 | | void fxExecuteModules(txMachine* the, txSlot* queue) |
385 | 177 | { |
386 | 177 | txBoolean done = 1; |
387 | 177 | txSlot* module = queue->next; |
388 | 177 | mxReportModuleQueue("INIT"); |
389 | 452 | while (module) { |
390 | 275 | txID status = mxModuleStatus(module); |
391 | 275 | if (status == XS_MODULE_STATUS_LINKED) { |
392 | 73 | txSlot* exception; |
393 | 73 | txID fromStatus = fxExecuteModulesFrom(the, queue, module, &exception); |
394 | 73 | if (fromStatus == XS_MODULE_STATUS_ERROR) { |
395 | 5 | fxCompleteModule(the, module->value.reference, exception); |
396 | 5 | fxRunImportRejected(the, module->value.reference, module->value.reference); |
397 | 5 | } |
398 | 68 | else if (fromStatus == XS_MODULE_STATUS_LINKED) { |
399 | 68 | mxModuleStatus(module) = XS_MODULE_STATUS_EXECUTING; |
400 | 68 | mxPushSlot(mxModuleHosts(module)); |
401 | 68 | mxPull(mxHosts); |
402 | 68 | { |
403 | 68 | mxTry(the) { |
404 | 68 | txSlot* result; |
405 | 68 | mxPushUndefined(); |
406 | 68 | mxPushSlot(mxModuleExecute(module)); |
407 | 68 | mxCall(); |
408 | 68 | mxRunCount(0); |
409 | 68 | result = the->stack; |
410 | 68 | if (mxIsReference(result) && mxIsPromise(result->value.reference)) { |
411 | 8 | txSlot* function; |
412 | 8 | txSlot* home; |
413 | 8 | txSlot* resolveExecuteFunction; |
414 | 8 | txSlot* rejectExecuteFunction; |
415 | | |
416 | 8 | function = fxNewHostFunction(the, fxExecuteModulesFulfilled, 1, XS_NO_ID, mxExecuteModulesFulfilledProfileID); |
417 | 8 | home = mxFunctionInstanceHome(function); |
418 | 8 | home->value.home.object = queue; |
419 | 8 | home->value.home.module = module->value.reference; |
420 | 8 | resolveExecuteFunction = the->stack; |
421 | | |
422 | 8 | function = fxNewHostFunction(the, fxExecuteModulesRejected, 1, XS_NO_ID, mxExecuteModulesRejectedProfileID); |
423 | 8 | home = mxFunctionInstanceHome(function); |
424 | 8 | home->value.home.object = queue; |
425 | 8 | home->value.home.module = module->value.reference; |
426 | 8 | rejectExecuteFunction = the->stack; |
427 | | |
428 | 8 | fxPromiseThen(the, result->value.reference, resolveExecuteFunction, rejectExecuteFunction, C_NULL, C_NULL); |
429 | | |
430 | 8 | mxPop(); |
431 | 8 | mxPop(); |
432 | 8 | mxPop(); |
433 | 8 | done = 0; |
434 | 8 | } |
435 | 60 | else { |
436 | 60 | mxPop(); |
437 | 60 | fxCompleteModule(the, module->value.reference, C_NULL); |
438 | 60 | fxRunImportFulfilled(the, module->value.reference, module->value.reference); |
439 | 60 | } |
440 | 68 | } |
441 | 68 | mxCatch(the) { |
442 | 10 | mxPush(mxException); |
443 | 10 | mxException = mxUndefined; |
444 | 10 | fxCompleteModule(the, module->value.reference, the->stack); |
445 | 10 | fxRunImportRejected(the, module->value.reference, module->value.reference); |
446 | 10 | mxPop(); |
447 | 10 | } |
448 | 68 | } |
449 | 68 | mxPushUndefined(); |
450 | 68 | mxPull(mxHosts); |
451 | 68 | } |
452 | 0 | else |
453 | 0 | done = 0; |
454 | 73 | } |
455 | 202 | else if (status < XS_MODULE_STATUS_EXECUTED) |
456 | 0 | done = 0; |
457 | 275 | module = module->next; |
458 | 275 | } |
459 | 177 | if (done) { |
460 | 169 | queue->next = C_NULL; |
461 | 169 | mxReportModuleQueue("DONE"); |
462 | 169 | } |
463 | 177 | } |
464 | | |
465 | | txID fxExecuteModulesFrom(txMachine* the, txSlot* queue, txSlot* module, txSlot** exception) |
466 | 73 | { |
467 | 73 | txSlot* fromModules = mxModuleTransfers(module)->value.reference; |
468 | 73 | txSlot* fromModule; |
469 | 73 | if (mxModuleTransfers(module)->kind == XS_NULL_KIND) |
470 | 48 | return XS_MODULE_STATUS_LINKED; |
471 | 25 | fromModule = fromModules->next; |
472 | 46 | while (fromModule) { |
473 | 26 | if (mxModuleStatus(fromModule) == XS_MODULE_STATUS_ERROR) { |
474 | 5 | *exception = mxModuleMeta(fromModule); |
475 | 5 | return XS_MODULE_STATUS_ERROR; |
476 | 5 | } |
477 | 21 | fromModule = fromModule->next; |
478 | 21 | } |
479 | 20 | fromModule = fromModules->next; |
480 | 40 | while (fromModule) { |
481 | 20 | if (mxModuleStatus(fromModule) == XS_MODULE_STATUS_EXECUTING) { |
482 | 0 | return XS_MODULE_STATUS_EXECUTING; |
483 | 0 | } |
484 | 20 | fromModule = fromModule->next; |
485 | 20 | } |
486 | 20 | fromModule = fromModules->next; |
487 | 40 | while (fromModule) { |
488 | 20 | if (mxModuleStatus(fromModule) == XS_MODULE_STATUS_LINKED) { |
489 | 0 | txSlot* waitingModule = queue->next; |
490 | 0 | while (waitingModule) { |
491 | 0 | if (module->value.reference == waitingModule->value.reference) |
492 | 0 | break; |
493 | 0 | if (fromModule->value.reference == waitingModule->value.reference) |
494 | 0 | return XS_MODULE_STATUS_EXECUTING; |
495 | 0 | waitingModule = waitingModule->next; |
496 | 0 | } |
497 | 0 | } |
498 | 20 | fromModule = fromModule->next; |
499 | 20 | } |
500 | 20 | return XS_MODULE_STATUS_LINKED; |
501 | 20 | } |
502 | | |
503 | | void fxExecuteModulesFulfilled(txMachine* the) |
504 | 1 | { |
505 | 1 | txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference); |
506 | 1 | txSlot* queue = home->value.home.object; |
507 | 1 | txSlot* module = home->value.home.module; |
508 | 1 | fxCompleteModule(the, module, C_NULL); |
509 | 1 | fxRunImportFulfilled(the, module, module); |
510 | 1 | fxExecuteModules(the, queue); |
511 | 1 | } |
512 | | |
513 | | void fxExecuteModulesRejected(txMachine* the) |
514 | 2 | { |
515 | 2 | txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference); |
516 | 2 | txSlot* queue = home->value.home.object; |
517 | 2 | txSlot* module = home->value.home.module; |
518 | 2 | fxCompleteModule(the, module, mxArgv(0)); |
519 | 2 | fxRunImportRejected(the, module, module); |
520 | 2 | fxExecuteModules(the, queue); |
521 | 2 | } |
522 | | |
523 | | void fxExecuteVirtualModuleSource(txMachine* the) |
524 | 24 | { |
525 | 24 | txSlot* instance = mxFunction->value.reference; |
526 | 24 | txSlot* function = fxLastProperty(the, instance); |
527 | 24 | txSlot* home = mxFunctionInstanceHome(instance); |
528 | 24 | txSlot* module = home->value.home.module; |
529 | 24 | txSlot* internal = mxModuleInstanceInternal(module); |
530 | 24 | txSlot* meta = mxModuleInstanceMeta(module); |
531 | 24 | txSlot* closures = mxFunctionInstanceCode(instance)->value.callback.closures; |
532 | 24 | txSlot* property; |
533 | 24 | if (mxIsUndefined(function)) |
534 | 4 | return; |
535 | 20 | closures->flag |= XS_DONT_PATCH_FLAG; |
536 | 20 | closures->value.instance.prototype = C_NULL; |
537 | 20 | property = closures->next->next; |
538 | 47 | while (property) { |
539 | 27 | property->flag |= XS_DONT_DELETE_FLAG; |
540 | 27 | property = property->next; |
541 | 27 | } |
542 | | /* THIS */ |
543 | 20 | mxPushReference(home->value.home.object); |
544 | | /* FUNCTION */ |
545 | 20 | mxPushSlot(function); |
546 | 20 | mxCall(); |
547 | | /* ARGUMENTS */ |
548 | 20 | mxPushReference(closures); |
549 | 20 | if (internal->flag & XS_IMPORT_FLAG) { |
550 | 1 | function = fxNewHostFunction(the, fxExecuteVirtualModuleSourceImport, 1, XS_NO_ID, mxExecuteVirtualModuleSourceImportProfileID); |
551 | 1 | mxFunctionInstanceHome(function)->value.home.module = module; |
552 | 1 | } |
553 | 19 | else |
554 | 19 | mxPushUndefined(); |
555 | 20 | if (internal->flag & XS_IMPORT_META_FLAG) |
556 | 1 | mxPushSlot(meta); |
557 | 19 | else |
558 | 19 | mxPushUndefined(); |
559 | 20 | mxRunCount(3); |
560 | 20 | mxPullSlot(mxResult); |
561 | 20 | } |
562 | | |
563 | | txSlot* fxGetModule(txMachine* the, txSlot* realm, txID moduleID, txFlag moduleFlag) |
564 | 6.71k | { |
565 | 6.71k | txSlot* result = mxBehaviorGetProperty(the, mxOwnModules(realm)->value.reference, moduleID, 0, XS_ANY); |
566 | 6.71k | if (result) |
567 | 6.33k | fxCheckModuleFlag(the, moduleID, mxModuleInternal(result)->flag, moduleFlag); |
568 | 6.71k | return result; |
569 | 6.71k | } |
570 | | |
571 | | void fxLinkCircularities(txMachine* the, txSlot* module, txSlot* circularities, txSlot* exports) |
572 | 147 | { |
573 | 147 | txSlot* circularitiesInstance; |
574 | 147 | txSlot* circularity; |
575 | 147 | txSlot* transfers; |
576 | 147 | txSlot* exportsInstance; |
577 | 147 | txSlot* export; |
578 | 147 | txSlot* transfer; |
579 | 147 | txSlot* aliases; |
580 | 147 | txSlot* alias; |
581 | 147 | txSlot* circularitiesCopy; |
582 | 147 | txSlot* circularityCopy; |
583 | 147 | txSlot* from; |
584 | 147 | txSlot* stars; |
585 | 147 | txSlot* star; |
586 | 147 | circularitiesInstance = circularities->value.reference; |
587 | 147 | circularity = circularitiesInstance->next; |
588 | 147 | while (circularity) { |
589 | 0 | if (circularity->value.reference == module->value.reference) |
590 | 0 | return; |
591 | 0 | circularity = circularity->next; |
592 | 0 | } |
593 | 147 | circularity = fxDuplicateSlot(the, module); |
594 | 147 | circularity->next = circularitiesInstance->next; |
595 | 147 | circularitiesInstance->next = circularity; |
596 | 147 | exportsInstance = exports->value.reference; |
597 | 147 | export = exportsInstance; |
598 | 147 | transfers = mxModuleExports(module); |
599 | 147 | if (transfers->kind == XS_REFERENCE_KIND) { |
600 | 0 | transfer = transfers->value.reference->next; |
601 | 0 | while (transfer) { |
602 | 0 | export = export->next = fxNewSlot(the); |
603 | 0 | export->ID = transfer->ID; |
604 | 0 | export->kind = transfer->kind; |
605 | 0 | export->value = transfer->value; |
606 | 0 | transfer = transfer->next; |
607 | 0 | } |
608 | 0 | return; |
609 | 0 | } |
610 | 147 | transfers = mxModuleTransfers(module); |
611 | 147 | if (transfers->kind == XS_REFERENCE_KIND) { |
612 | 147 | txBoolean starFlag = 0; |
613 | 147 | transfer = transfers->value.reference->next; |
614 | 517 | while (transfer) { |
615 | 370 | aliases = mxTransferAliases(transfer); |
616 | 370 | if (aliases->kind == XS_REFERENCE_KIND) { |
617 | 271 | alias = aliases->value.reference->next; |
618 | 271 | if (alias) { |
619 | 547 | while (alias) { |
620 | 276 | export = export->next = fxNewSlot(the); |
621 | 276 | export->ID = alias->value.symbol; |
622 | 276 | export->kind = transfer->kind; |
623 | 276 | export->value = transfer->value; |
624 | 276 | alias = alias->next; |
625 | 276 | } |
626 | 271 | } |
627 | 0 | else { |
628 | 0 | mxCheck(the, mxTransferLocal(transfer)->kind == XS_NULL_KIND); |
629 | 0 | starFlag = 1; |
630 | 0 | } |
631 | 271 | } |
632 | 370 | transfer = transfer->next; |
633 | 370 | } |
634 | 147 | if (starFlag) { |
635 | 0 | txSlot* reexportsInstance; |
636 | 0 | txSlot* reexport; |
637 | 0 | fxNewInstance(the); |
638 | 0 | reexportsInstance = the->stack->value.reference; |
639 | 0 | reexport = reexportsInstance; |
640 | 0 | transfer = transfers->value.reference->next; |
641 | 0 | while (transfer) { |
642 | 0 | aliases = mxTransferAliases(transfer); |
643 | 0 | if ((aliases->kind == XS_REFERENCE_KIND) && (aliases->value.reference->next == C_NULL)) { |
644 | 0 | from = mxTransferFrom(transfer); |
645 | 0 | fxNewInstance(the); |
646 | 0 | circularitiesCopy = the->stack; |
647 | 0 | circularity = circularitiesInstance->next; |
648 | 0 | circularityCopy = circularitiesCopy->value.reference; |
649 | 0 | while (circularity) { |
650 | 0 | circularityCopy = circularityCopy->next = fxDuplicateSlot(the, circularity); |
651 | 0 | circularity = circularity->next; |
652 | 0 | } |
653 | 0 | fxNewInstance(the); |
654 | 0 | stars = the->stack; |
655 | 0 | fxLinkCircularities(the, from, circularitiesCopy, stars); |
656 | 0 | star = stars->value.reference->next; |
657 | 0 | while (star) { |
658 | 0 | if (star->ID != mxID(_default)) { |
659 | 0 | txSlot* ambiguous = mxBehaviorGetProperty(the, exportsInstance, star->ID, 0, XS_OWN); |
660 | 0 | if (!ambiguous) { |
661 | 0 | ambiguous = mxBehaviorGetProperty(the, reexportsInstance, star->ID, 0, XS_OWN); |
662 | 0 | if (ambiguous) { |
663 | 0 | txSlot* ambiguousModule; |
664 | 0 | txSlot* starModule; |
665 | 0 | if (ambiguous->kind == XS_EXPORT_KIND) |
666 | 0 | ambiguousModule = ambiguous->value.export.module; |
667 | 0 | else { |
668 | 0 | txSlot* ambiguousClosure = mxTransferClosure(ambiguous); |
669 | 0 | if (ambiguousClosure->kind == XS_EXPORT_KIND) |
670 | 0 | ambiguousModule = ambiguousClosure->value.export.module; |
671 | 0 | else { |
672 | 0 | txSlot* ambiguousFrom = mxTransferFrom(ambiguous); |
673 | 0 | if (ambiguousFrom->kind == XS_REFERENCE_KIND) |
674 | 0 | ambiguousModule = ambiguousFrom->value.reference; |
675 | 0 | else |
676 | 0 | ambiguousModule = C_NULL; |
677 | 0 | } |
678 | 0 | } |
679 | 0 | if (star->kind == XS_EXPORT_KIND) |
680 | 0 | starModule = star->value.export.module; |
681 | 0 | else { |
682 | 0 | txSlot* starClosure = mxTransferClosure(star); |
683 | 0 | if (starClosure->kind == XS_EXPORT_KIND) |
684 | 0 | starModule = starClosure->value.export.module; |
685 | 0 | else { |
686 | 0 | txSlot* starFrom = mxTransferFrom(star); |
687 | 0 | if (starFrom->kind == XS_REFERENCE_KIND) |
688 | 0 | starModule = starFrom->value.reference; |
689 | 0 | else |
690 | 0 | starModule = C_NULL; |
691 | 0 | } |
692 | 0 | } |
693 | 0 | if (ambiguousModule != starModule) { |
694 | 0 | ambiguous->kind = XS_EXPORT_KIND; |
695 | 0 | ambiguous->value.export.closure = C_NULL; |
696 | 0 | ambiguous->value.export.module = C_NULL; |
697 | 0 | } |
698 | 0 | } |
699 | 0 | else { |
700 | 0 | reexport = reexport->next = fxNewSlot(the); |
701 | 0 | reexport->ID = star->ID; |
702 | 0 | reexport->kind = star->kind; |
703 | 0 | reexport->value = star->value; |
704 | 0 | } |
705 | 0 | } |
706 | 0 | } |
707 | 0 | star = star->next; |
708 | 0 | } |
709 | 0 | mxPop(); |
710 | 0 | mxPop(); |
711 | 0 | } |
712 | 0 | transfer = transfer->next; |
713 | 0 | } |
714 | 0 | export->next = reexportsInstance->next; |
715 | 0 | reexportsInstance->next = C_NULL; |
716 | 0 | mxPop(); |
717 | 0 | } |
718 | 147 | } |
719 | 147 | } |
720 | | |
721 | | void fxLinkExports(txMachine* the, txSlot* module) |
722 | 147 | { |
723 | 147 | txSlot* exports; |
724 | 147 | txSlot* transfer; |
725 | 147 | txSlot* from; |
726 | 147 | txSlot* import; |
727 | 147 | txSlot* closure; |
728 | | |
729 | 147 | exports = mxModuleExports(module)->value.reference; |
730 | 147 | exports->flag |= XS_DONT_PATCH_FLAG; |
731 | 147 | transfer = exports->next; |
732 | 410 | while (transfer) { |
733 | 263 | if (transfer->kind != XS_EXPORT_KIND) { |
734 | 263 | from = mxTransferFrom(transfer); |
735 | 263 | if (from->kind != XS_NULL_KIND) { |
736 | 28 | import = mxTransferImport(transfer); |
737 | 28 | if (import->kind != XS_NULL_KIND) |
738 | 21 | fxLinkTransfer(the, from, import->value.symbol, transfer); |
739 | 7 | else |
740 | 7 | fxLinkNamespace(the, from, transfer); |
741 | 28 | } |
742 | 263 | closure = mxTransferClosure(transfer); |
743 | 263 | transfer->kind = closure->kind; |
744 | 263 | transfer->value = closure->value; |
745 | 263 | } |
746 | 263 | transfer->flag |= XS_DONT_DELETE_FLAG | XS_DONT_SET_FLAG; |
747 | 263 | transfer = transfer->next; |
748 | 263 | } |
749 | 147 | } |
750 | | |
751 | | void fxLinkLocals(txMachine* the, txSlot* module) |
752 | 132 | { |
753 | 132 | txSlot* transfer; |
754 | 132 | txSlot* local; |
755 | 132 | txSlot* from; |
756 | 132 | txSlot* import; |
757 | 132 | txSlot* closure; |
758 | | |
759 | 132 | transfer = mxModuleTransfers(module)->value.reference->next; |
760 | 383 | while (transfer) { |
761 | 251 | local = mxTransferLocal(transfer); |
762 | 251 | if (local->kind != XS_NULL_KIND) { |
763 | 233 | from = mxTransferFrom(transfer); |
764 | 233 | if (from->kind != XS_NULL_KIND) { |
765 | 56 | import = mxTransferImport(transfer); |
766 | 56 | if (import->kind != XS_NULL_KIND) |
767 | 54 | fxLinkTransfer(the, from, import->value.symbol, transfer); |
768 | 2 | else |
769 | 2 | fxLinkNamespace(the, from, transfer); |
770 | 56 | closure = mxTransferClosure(transfer); |
771 | 56 | closure->flag |= XS_DONT_SET_FLAG; |
772 | 56 | } |
773 | 233 | } |
774 | 251 | transfer = transfer->next; |
775 | 251 | } |
776 | 132 | } |
777 | | |
778 | | void fxLinkModules(txMachine* the, txSlot* queue) |
779 | 206 | { |
780 | 206 | txSlot* module; |
781 | 206 | txSlot* order; |
782 | 206 | txSlot* transfer; |
783 | 206 | txSlot* local; |
784 | 206 | txSlot* from; |
785 | 206 | txSlot* import; |
786 | 206 | txSlot* aliases; |
787 | 206 | txSlot* closure; |
788 | 206 | txSlot* property; |
789 | 206 | txSlot* circularities; |
790 | 206 | txSlot* exports; |
791 | 206 | txSlot* realm; |
792 | 206 | txSlot* closures; |
793 | 206 | txSlot* export; |
794 | | |
795 | 206 | order = fxNewInstance(the); |
796 | 414 | while ((module = queue->next)) |
797 | 208 | fxOrderModule(the, queue, order, module); |
798 | 206 | queue->next = order->next; |
799 | 206 | order->next = C_NULL; |
800 | 206 | mxPop(); |
801 | | |
802 | 206 | mxReportModuleQueue("LINK"); |
803 | 206 | module = queue->next; |
804 | 514 | while (module) { |
805 | 308 | if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) { |
806 | 147 | transfer = mxModuleTransfers(module)->value.reference->next; |
807 | 517 | while (transfer) { |
808 | 370 | local = mxTransferLocal(transfer); |
809 | 370 | from = mxTransferFrom(transfer); |
810 | 370 | import = mxTransferImport(transfer); |
811 | 370 | aliases = mxTransferAliases(transfer); |
812 | 370 | if (local->kind != XS_NULL_KIND) { |
813 | 317 | if ((from->kind == XS_NULL_KIND) || (import->kind == XS_NULL_KIND)) { |
814 | 250 | closure = mxTransferClosure(transfer); |
815 | 250 | closure->value.export.closure = fxNewSlot(the); |
816 | 250 | closure->value.export.closure->kind = XS_UNINITIALIZED_KIND; |
817 | 250 | closure->value.export.module = module->value.reference; |
818 | 250 | closure->kind = XS_EXPORT_KIND; |
819 | 250 | } |
820 | 317 | } |
821 | 53 | else { |
822 | 53 | if ((from->kind != XS_NULL_KIND) && (import->kind == XS_NULL_KIND) && (aliases->kind != XS_NULL_KIND)) { |
823 | 13 | closure = mxTransferClosure(transfer); |
824 | 13 | closure->value.export.closure = fxNewSlot(the); |
825 | 13 | closure->value.export.closure->kind = XS_UNINITIALIZED_KIND; |
826 | 13 | closure->value.export.module = module->value.reference; |
827 | 13 | closure->kind = XS_EXPORT_KIND; |
828 | 13 | } |
829 | 53 | } |
830 | 370 | transfer = transfer->next; |
831 | 370 | } |
832 | 147 | } |
833 | 308 | module = module->next; |
834 | 308 | } |
835 | | |
836 | 206 | module = queue->next; |
837 | 514 | while (module) { |
838 | 308 | if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) { |
839 | 147 | fxNewInstance(the); |
840 | 147 | circularities = the->stack; |
841 | 147 | fxNewInstance(the); |
842 | 147 | exports = the->stack; |
843 | 147 | fxLinkCircularities(the, module, circularities, exports); |
844 | 147 | mxModuleExports(module)->kind = XS_REFERENCE_KIND; |
845 | 147 | mxModuleExports(module)->value.reference = exports->value.reference; |
846 | 147 | mxPop(); |
847 | 147 | mxPop(); |
848 | 147 | } |
849 | 308 | module = module->next; |
850 | 308 | } |
851 | | |
852 | 206 | module = queue->next; |
853 | 514 | while (module) { |
854 | 308 | if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) |
855 | 147 | fxLinkExports(the, module); |
856 | 308 | module = module->next; |
857 | 308 | } |
858 | 206 | module = queue->next; |
859 | 477 | while (module) { |
860 | 271 | if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) |
861 | 132 | fxLinkLocals(the, module); |
862 | 271 | module = module->next; |
863 | 271 | } |
864 | | |
865 | 206 | module = queue->next; |
866 | 432 | while (module) { |
867 | 226 | if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) { |
868 | 110 | txInteger count = 0; |
869 | 110 | mxPushUndefined(); |
870 | 110 | realm = mxModuleInternal(module)->value.module.realm; |
871 | 110 | closures = fxNewEnvironmentInstance(the, mxRealmClosures(realm)); |
872 | 110 | closure = closures->next; |
873 | 110 | transfer = mxModuleTransfers(module)->value.reference->next; |
874 | 294 | while (transfer) { |
875 | 184 | local = mxTransferLocal(transfer); |
876 | 184 | if (local->kind != XS_NULL_KIND) { |
877 | 168 | export = mxTransferClosure(transfer); |
878 | 168 | mxCheck(the, export->kind == XS_EXPORT_KIND); |
879 | 168 | closure = closure->next = fxNewSlot(the); |
880 | 168 | closure->ID = local->value.symbol; |
881 | 168 | closure->flag = export->flag; |
882 | 168 | closure->kind = XS_CLOSURE_KIND; |
883 | 168 | closure->value.closure = export->value.export.closure; |
884 | 168 | } |
885 | 184 | from = mxTransferFrom(transfer); |
886 | 184 | if (from->kind != XS_NULL_KIND) |
887 | 55 | count++; |
888 | 184 | transfer = transfer->next; |
889 | 184 | } |
890 | 110 | property = mxModuleInitialize(module); |
891 | 110 | if (property->kind == XS_REFERENCE_KIND) { |
892 | 0 | property = property->value.reference->next; |
893 | 0 | if ((property->kind == XS_CODE_KIND) || (property->kind == XS_CODE_X_KIND)) |
894 | 0 | property->value.code.closures = closures; |
895 | 0 | else if (property->kind == XS_CALLBACK_KIND) |
896 | 0 | property->value.callback.closures = closures; |
897 | 0 | } |
898 | 110 | property = mxModuleExecute(module); |
899 | 110 | if (property->kind == XS_REFERENCE_KIND) { |
900 | 110 | property = property->value.reference->next; |
901 | 110 | if ((property->kind == XS_CODE_KIND) || (property->kind == XS_CODE_X_KIND)) |
902 | 84 | property->value.code.closures = closures; |
903 | 26 | else if (property->kind == XS_CALLBACK_KIND) |
904 | 26 | property->value.callback.closures = closures; |
905 | 110 | } |
906 | 110 | mxPop(); |
907 | 110 | if (count > 0) { |
908 | 38 | txSlot* instance = fxNewInstance(the); |
909 | 38 | transfer = mxModuleTransfers(module)->value.reference->next; |
910 | 141 | while (transfer) { |
911 | 103 | from = mxTransferFrom(transfer); |
912 | 103 | if (from->kind != XS_NULL_KIND) { |
913 | 55 | txSlot** address = &(instance->next); |
914 | 55 | txSlot* slot; |
915 | 62 | while ((slot = *address)) { |
916 | 20 | if (slot->value.reference == from->value.reference) |
917 | 13 | break; |
918 | 7 | address = &slot->next; |
919 | 7 | } |
920 | 55 | if (!slot) |
921 | 42 | slot = *address = fxDuplicateSlot(the, from); |
922 | 55 | } |
923 | 103 | transfer = transfer->next; |
924 | 103 | } |
925 | 38 | mxModuleTransfers(module)->value.reference = instance; |
926 | 38 | mxPop(); |
927 | 38 | } |
928 | 72 | else |
929 | 72 | mxModuleTransfers(module)->kind = XS_NULL_KIND; |
930 | 110 | } |
931 | 226 | module = module->next; |
932 | 226 | } |
933 | | |
934 | 206 | module = queue->next; |
935 | 432 | while (module) { |
936 | 226 | if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) { |
937 | 110 | mxModuleStatus(module) = XS_MODULE_STATUS_LINKED; |
938 | 110 | property = mxModuleInitialize(module); |
939 | 110 | if (property->kind == XS_REFERENCE_KIND) { |
940 | 0 | mxPushSlot(mxModuleHosts(module)); |
941 | 0 | mxPull(mxHosts); |
942 | 0 | mxPushUndefined(); |
943 | 0 | mxPushSlot(property); |
944 | 0 | mxCall(); |
945 | 0 | mxRunCount(0); |
946 | 0 | mxPop(); |
947 | 0 | mxPushUndefined(); |
948 | 0 | mxPull(mxHosts); |
949 | 0 | } |
950 | 110 | } |
951 | 226 | module = module->next; |
952 | 226 | } |
953 | 206 | } |
954 | | |
955 | | void fxLinkNamespace(txMachine* the, txSlot* module, txSlot* transfer) |
956 | 9 | { |
957 | 9 | txSlot* export = mxTransferClosure(transfer); |
958 | 9 | mxCheck(the, export->kind == XS_EXPORT_KIND); |
959 | 9 | export->value.export.closure = fxDuplicateSlot(the, module); |
960 | 9 | export->value.export.closure->ID = XS_NO_ID; |
961 | 9 | } |
962 | | |
963 | | void fxLinkTransfer(txMachine* the, txSlot* module, txID importID, txSlot* transfer) |
964 | 75 | { |
965 | 75 | txSlot* export; |
966 | 75 | txSlot* exportClosure; |
967 | 75 | txSlot* transferClosure; |
968 | 75 | txSlot* from; |
969 | 75 | txSlot* import; |
970 | | |
971 | 75 | export = mxBehaviorGetProperty(the, mxModuleExports(module)->value.reference, importID, 0, XS_OWN); |
972 | 75 | if (export) { |
973 | 51 | if (export->kind == XS_EXPORT_KIND) { |
974 | 51 | if (export->value.export.closure == C_NULL) { |
975 | 0 | txString path = C_NULL; |
976 | 0 | txInteger line = 0; |
977 | 0 | #ifdef mxDebug |
978 | 0 | txSlot* slot = mxTransferClosure(transfer)->next; |
979 | 0 | if (slot) { |
980 | 0 | path = slot->value.string; |
981 | 0 | line = slot->next->value.integer; |
982 | 0 | } |
983 | 0 | #endif |
984 | 0 | fxIDToString(the, importID, the->nameBuffer, sizeof(the->nameBuffer)); |
985 | 0 | fxThrowMessage(the, path, line, XS_SYNTAX_ERROR, "import %s ambiguous", the->nameBuffer); |
986 | 0 | } |
987 | 51 | transferClosure = mxTransferClosure(transfer); |
988 | 51 | transferClosure->value = export->value; |
989 | 51 | transferClosure->kind = export->kind; |
990 | 51 | } |
991 | 0 | else { |
992 | 0 | exportClosure = mxTransferClosure(export); |
993 | 0 | if (exportClosure->kind != XS_NULL_KIND) { |
994 | 0 | transferClosure = mxTransferClosure(transfer); |
995 | 0 | transferClosure->value = exportClosure->value; |
996 | 0 | transferClosure->kind = exportClosure->kind; |
997 | 0 | } |
998 | 0 | else { |
999 | 0 | from = mxTransferFrom(export); |
1000 | 0 | import = mxTransferImport(export); |
1001 | 0 | if (((from->value.reference == module->value.reference) && (import->value.symbol == importID)) |
1002 | 0 | || ((from->value.reference == mxTransferFrom(transfer)->value.reference) && (import->value.symbol == mxTransferImport(transfer)->value.symbol))) { |
1003 | 0 | txString path = C_NULL; |
1004 | 0 | txInteger line = 0; |
1005 | 0 | #ifdef mxDebug |
1006 | 0 | txSlot* slot = mxTransferClosure(transfer)->next; |
1007 | 0 | if (slot) { |
1008 | 0 | path = slot->value.string; |
1009 | 0 | line = slot->next->value.integer; |
1010 | 0 | } |
1011 | 0 | #endif |
1012 | 0 | fxIDToString(the, importID, the->nameBuffer, sizeof(the->nameBuffer)); |
1013 | 0 | fxThrowMessage(the, path, line, XS_SYNTAX_ERROR, "import %s circular", the->nameBuffer); |
1014 | 0 | } |
1015 | 0 | fxCheckCStack(the); |
1016 | 0 | fxLinkTransfer(the, from, import->value.symbol, transfer); |
1017 | 0 | } |
1018 | 0 | } |
1019 | 51 | } |
1020 | 24 | else { |
1021 | 24 | txString path = C_NULL; |
1022 | 24 | txInteger line = 0; |
1023 | 24 | #ifdef mxDebug |
1024 | 24 | txSlot* slot = mxTransferClosure(transfer)->next; |
1025 | 24 | if (slot) { |
1026 | 0 | path = slot->value.string; |
1027 | 0 | line = slot->next->value.integer; |
1028 | 0 | } |
1029 | 24 | #endif |
1030 | 24 | fxIDToString(the, importID, the->nameBuffer, sizeof(the->nameBuffer)); |
1031 | 24 | fxThrowMessage(the, path, line, XS_SYNTAX_ERROR, "import %s not found", the->nameBuffer); |
1032 | 24 | } |
1033 | 75 | } |
1034 | | |
1035 | | void fxLoadModulesPromise(txMachine* the, txSlot* queue, txSlot* module, txSlot* promise, txCallback fulfilled, txCallback rejected) |
1036 | 31 | { |
1037 | 31 | txSlot* function; |
1038 | 31 | txSlot* home; |
1039 | 31 | txSlot* resolveLoadFunction; |
1040 | 31 | txSlot* rejectLoadFunction; |
1041 | | |
1042 | 31 | mxPushUndefined(); |
1043 | 31 | mxPush(mxPromiseConstructor); |
1044 | 31 | mxPushSlot(promise); |
1045 | 31 | fx_Promise_resolveAux(the); |
1046 | 31 | mxPop(); |
1047 | 31 | mxPop(); |
1048 | 31 | promise = the->stack; |
1049 | | |
1050 | 31 | function = fxNewHostFunction(the, fulfilled, 1, XS_NO_ID, mxLoadModulesFulfilledProfileID); |
1051 | 31 | home = mxFunctionInstanceHome(function); |
1052 | 31 | home->value.home.object = queue; |
1053 | 31 | home->value.home.module = module->value.reference; |
1054 | 31 | resolveLoadFunction = the->stack; |
1055 | | |
1056 | 31 | function = fxNewHostFunction(the, rejected, 1, XS_NO_ID, mxLoadModulesRejectedProfileID); |
1057 | 31 | home = mxFunctionInstanceHome(function); |
1058 | 31 | home->value.home.object = queue; |
1059 | 31 | home->value.home.module = module->value.reference; |
1060 | 31 | rejectLoadFunction = the->stack; |
1061 | | |
1062 | 31 | fxPromiseThen(the, promise->value.reference, resolveLoadFunction, rejectLoadFunction, C_NULL, C_NULL); |
1063 | | |
1064 | 31 | mxPop(); |
1065 | 31 | mxPop(); |
1066 | 31 | } |
1067 | | |
1068 | | void fxLoadModules(txMachine* the, txSlot* queue) |
1069 | 229 | { |
1070 | 229 | txSlot* module = queue->next; |
1071 | 229 | txBoolean done = 1; |
1072 | 229 | if (queue->flag & XS_LEVEL_FLAG) |
1073 | 0 | return; |
1074 | 229 | queue->flag |= XS_LEVEL_FLAG; |
1075 | 229 | mxReportModuleQueue("LOAD"); |
1076 | 797 | while (module) { |
1077 | 690 | if (mxModuleStatus(module) == XS_MODULE_STATUS_NEW) { |
1078 | 311 | txSlot* loader = mxModuleLoader(module); |
1079 | 311 | txID moduleID = loader->value.module.id; |
1080 | 311 | txSlot* realm = loader->value.module.realm; |
1081 | 311 | mxTry(the) { |
1082 | 311 | if (fxMapModule(the, realm, moduleID, module, queue, C_NULL)) { |
1083 | 127 | module = queue; |
1084 | 127 | done = 0; |
1085 | 127 | } |
1086 | 184 | else { |
1087 | 184 | txSlot* loadHook = mxLoadHook(realm); |
1088 | 184 | mxModuleStatus(module) = XS_MODULE_STATUS_LOADING; |
1089 | 184 | if (mxIsUndefined(loadHook)) { |
1090 | 122 | if (realm != mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm) |
1091 | 60 | mxTypeError("no loadHook"); |
1092 | 62 | fxLoadModule(the, module, moduleID); |
1093 | 62 | if (mxModuleExecute(module)->kind == XS_NULL_KIND) |
1094 | 62 | mxTypeError("no module"); |
1095 | 0 | mxModuleStatus(module) = XS_MODULE_STATUS_LOADED; |
1096 | 0 | module = queue; |
1097 | 0 | done = 1; |
1098 | 0 | mxReportModuleQueue("LOAD"); |
1099 | 0 | } |
1100 | 62 | else { |
1101 | 62 | done = 0; |
1102 | 62 | mxModuleStatus(module) = XS_MODULE_STATUS_LOADING; |
1103 | | |
1104 | 62 | mxPushUndefined(); |
1105 | 62 | mxPushSlot(loadHook); |
1106 | 62 | mxCall(); |
1107 | 62 | fxPushKeyString(the, moduleID, C_NULL); |
1108 | 62 | fxPushModuleOptions(the, loader->flag); |
1109 | 62 | mxRunCount(2); |
1110 | | |
1111 | 62 | fxLoadModulesPromise(the, queue, module, the->stack, fxLoadModulesFulfilled, fxLoadModulesRejected); |
1112 | | |
1113 | 62 | mxPop(); |
1114 | 62 | } |
1115 | 184 | } |
1116 | 311 | } |
1117 | 189 | mxCatch(the) { |
1118 | 153 | mxPush(mxException); |
1119 | 153 | mxException = mxUndefined; |
1120 | 153 | fxCompleteModule(the, module->value.reference, the->stack); |
1121 | 153 | fxRunImportRejected(the, module->value.reference, module->value.reference); |
1122 | 153 | } |
1123 | 311 | } |
1124 | 379 | else if (mxModuleStatus(module) == XS_MODULE_STATUS_LOADING) { |
1125 | 26 | done = 0; |
1126 | 26 | } |
1127 | 353 | else if (mxModuleStatus(module) == XS_MODULE_STATUS_LOADED) { |
1128 | 115 | mxTry(the) { |
1129 | 115 | #if mxModuleStuff |
1130 | 115 | if (!fxLoadModuleStuffFrom(the, queue, module->value.reference, 0)) |
1131 | 115 | #endif |
1132 | 115 | fxLoadModulesFrom(the, queue, module->value.reference, 0); |
1133 | 115 | mxModuleStatus(module) = XS_MODULE_STATUS_LINKING; |
1134 | 115 | module = queue; |
1135 | 115 | done = 1; |
1136 | 115 | } |
1137 | 115 | mxCatch(the) { |
1138 | 6 | mxPush(mxException); |
1139 | 6 | mxException = mxUndefined; |
1140 | 6 | fxCompleteModule(the, module->value.reference, the->stack); |
1141 | 6 | fxRunImportRejected(the, module->value.reference, module->value.reference); |
1142 | 6 | } |
1143 | 115 | } |
1144 | 568 | module = module->next; |
1145 | 568 | } |
1146 | 107 | queue->flag &= ~XS_LEVEL_FLAG; |
1147 | 174 | if (done) { |
1148 | 174 | mxTry(the) { |
1149 | 174 | fxLinkModules(the, queue); |
1150 | 174 | } |
1151 | 174 | mxCatch(the) { |
1152 | 23 | mxPush(mxException); |
1153 | 23 | mxException = mxUndefined; |
1154 | 23 | module = queue->next; |
1155 | 104 | while (module) { |
1156 | 81 | if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) { |
1157 | 36 | fxCompleteModule(the, module->value.reference, the->stack); |
1158 | 36 | fxRunImportRejected(the, module->value.reference, module->value.reference); |
1159 | 36 | } |
1160 | 81 | module = module->next; |
1161 | 81 | } |
1162 | 23 | mxPop(); |
1163 | 23 | } |
1164 | 174 | fxExecuteModules(the, queue); |
1165 | 174 | } |
1166 | 107 | } |
1167 | | |
1168 | | void fxLoadModulesFrom(txMachine* the, txSlot* queue, txSlot* module, txBoolean now) |
1169 | 156 | { |
1170 | 156 | txSlot* internal = mxModuleInstanceInternal(module); |
1171 | 156 | txID moduleID = internal->value.module.id; |
1172 | 156 | txSlot* realm = internal->value.module.realm; |
1173 | 156 | txSlot* transfer = mxModuleInstanceTransfers(module)->value.reference->next; |
1174 | 156 | txSlot* already = the->stack; |
1175 | 540 | while (transfer) { |
1176 | 384 | txSlot* from = mxTransferFrom(transfer); |
1177 | 384 | if (from->kind != XS_NULL_KIND) { |
1178 | 147 | txID importModuleID = XS_NO_ID; |
1179 | 147 | txSlot* importModule; |
1180 | 147 | txID status; |
1181 | 147 | txSlot* former = the->stack; |
1182 | 234 | while (former < already) { |
1183 | 124 | if (!c_strcmp(former->value.string, from->value.string)) { |
1184 | 37 | importModuleID = former->ID; |
1185 | 37 | break; |
1186 | 37 | } |
1187 | 87 | former++; |
1188 | 87 | } |
1189 | 147 | if (importModuleID == XS_NO_ID) { |
1190 | 110 | mxPushSlot(from); |
1191 | 110 | importModuleID = fxResolveSpecifier(the, realm, moduleID, from); |
1192 | 110 | the->stack->ID = importModuleID; |
1193 | 110 | } |
1194 | 147 | importModule = fxGetModule(the, realm, importModuleID, from->flag & XS_JSON_MODULE_FLAG); |
1195 | 147 | if (!importModule) { |
1196 | 103 | importModule = mxBehaviorSetProperty(the, mxOwnModules(realm)->value.reference, importModuleID, 0, XS_OWN); |
1197 | 103 | fxNewModule(the, realm, importModuleID, from->flag & XS_JSON_MODULE_FLAG, importModule); |
1198 | 103 | } |
1199 | 147 | from->kind = XS_REFERENCE_KIND; |
1200 | 147 | from->value.reference = importModule->value.reference; |
1201 | 147 | status = mxModuleStatus(importModule); |
1202 | 147 | if ((status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADED)) { |
1203 | 141 | fxQueueModule(the, queue, importModule); |
1204 | 141 | } |
1205 | 6 | else if (now) { |
1206 | 0 | if (status == XS_MODULE_STATUS_LINKING) { |
1207 | 0 | txSlot* slot = queue->next; |
1208 | 0 | while (slot) { |
1209 | 0 | if (slot->value.reference == importModule->value.reference) |
1210 | 0 | break; |
1211 | 0 | slot= slot->next; |
1212 | 0 | } |
1213 | 0 | if (!slot) |
1214 | 0 | mxTypeError("async module"); |
1215 | 0 | } |
1216 | 0 | else if (status == XS_MODULE_STATUS_ERROR) { |
1217 | 0 | mxPushSlot(mxModuleInstanceMeta(module)); |
1218 | 0 | mxPull(mxException); |
1219 | 0 | fxJump(the); |
1220 | 0 | } |
1221 | 0 | else if (status != XS_MODULE_STATUS_EXECUTED) { |
1222 | 0 | mxTypeError("async module"); |
1223 | 0 | } |
1224 | 0 | } |
1225 | 147 | } |
1226 | 384 | transfer = transfer->next; |
1227 | 384 | } |
1228 | 156 | the->stack = already; |
1229 | 156 | } |
1230 | | |
1231 | | void fxLoadModulesFulfilled(txMachine* the) |
1232 | 10 | { |
1233 | 10 | txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference); |
1234 | 10 | txSlot* queue = home->value.home.object; |
1235 | 10 | txSlot* module = home->value.home.module; |
1236 | 10 | txSlot* internal = mxModuleInstanceInternal(module); |
1237 | 10 | txSlot* realm = internal->value.module.realm; |
1238 | 10 | txID moduleID = internal->value.module.id; |
1239 | 10 | mxTry(the) { |
1240 | 10 | mxPushReference(module); |
1241 | 10 | fxMapModuleDescriptor(the, realm, moduleID, the->stack, queue, C_NULL, mxArgv(0)); |
1242 | 10 | mxPop(); // module |
1243 | 10 | } |
1244 | 10 | mxCatch(the) { |
1245 | 3 | mxPush(mxException); |
1246 | 3 | mxException = mxUndefined; |
1247 | 3 | fxCompleteModule(the, module, the->stack); |
1248 | 3 | fxRunImportRejected(the, module, module); |
1249 | 3 | mxPop(); |
1250 | 3 | } |
1251 | 10 | fxLoadModules(the, queue); |
1252 | 10 | } |
1253 | | |
1254 | | void fxLoadModulesRejected(txMachine* the) |
1255 | 2 | { |
1256 | 2 | txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference); |
1257 | 2 | txSlot* queue = home->value.home.object; |
1258 | 2 | txSlot* module = home->value.home.module; |
1259 | 2 | fxCompleteModule(the, module, mxArgv(0)); |
1260 | 2 | fxRunImportRejected(the, module, module); |
1261 | 2 | fxLoadModules(the, queue); |
1262 | 2 | } |
1263 | | |
1264 | | void fxLoadVirtualModuleNamespace(txMachine* the, txSlot* object, txSlot* module) |
1265 | 7 | { |
1266 | 7 | txSlot* exports = fxNewInstance(the); |
1267 | 7 | txSlot* export = exports; |
1268 | 7 | txSlot* at; |
1269 | 7 | txSlot* property; |
1270 | 7 | at = fxNewInstance(the); |
1271 | 7 | mxBehaviorOwnKeys(the, object, XS_EACH_NAME_FLAG, at); |
1272 | 7 | mxTemporary(property); |
1273 | 34 | while ((at = at->next)) { |
1274 | 27 | if (at->value.at.id != XS_NO_ID) { |
1275 | 27 | if (mxBehaviorGetOwnProperty(the, object, at->value.at.id, at->value.at.index, property) && !(property->flag & XS_DONT_ENUM_FLAG)) { |
1276 | 16 | mxPushReference(object); |
1277 | 16 | mxGetAll(at->value.at.id, at->value.at.index); |
1278 | 16 | export = export->next = fxNewSlot(the); |
1279 | 16 | export->ID = at->value.at.id; |
1280 | 16 | export->value.export.closure = fxNewSlot(the); |
1281 | 16 | export->value.export.closure->kind = the->stack->kind; |
1282 | 16 | export->value.export.closure->value = the->stack->value; |
1283 | 16 | export->value.export.module = module; |
1284 | 16 | export->kind = XS_EXPORT_KIND; |
1285 | 16 | mxPop(); |
1286 | 16 | } |
1287 | 27 | } |
1288 | 27 | } |
1289 | 7 | mxPop(); |
1290 | 7 | mxPop(); |
1291 | 7 | mxPullSlot(mxModuleInstanceExports(module)); |
1292 | 7 | } |
1293 | | |
1294 | | void fxLoadVirtualModuleSource(txMachine* the, txSlot* record, txSlot* instance) |
1295 | 53 | { |
1296 | 53 | txSlot* slot; |
1297 | 53 | txSlot* function; |
1298 | 53 | txSlot* property; |
1299 | 53 | txSlot* transfers; |
1300 | 53 | txSlot* transfer; |
1301 | | |
1302 | 53 | mxPushSlot(record); |
1303 | 53 | mxGetID(fxID(the, "execute")); |
1304 | 53 | slot = the->stack; |
1305 | 53 | if (!mxIsUndefined(slot)) { |
1306 | 46 | if (!fxIsCallable(the, slot)) |
1307 | 0 | mxTypeError("execute: not a function"); |
1308 | 46 | } |
1309 | 53 | function = fxNewHostFunction(the, fxExecuteVirtualModuleSource, 0, XS_NO_ID, mxExecuteVirtualModuleSourceProfileID); |
1310 | 53 | property = mxFunctionInstanceHome(function); |
1311 | 53 | property->value.home.object = fxToInstance(the, record); |
1312 | 53 | property->value.home.module = instance; |
1313 | 53 | property = fxLastProperty(the, function); |
1314 | 53 | property = fxNextSlotProperty(the, property, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
1315 | 53 | mxPullSlot(mxModuleInstanceExecute(instance)); |
1316 | 53 | mxPop(); // initialize |
1317 | | |
1318 | 53 | mxPush(mxObjectPrototype); |
1319 | 53 | transfers = fxNewObjectInstance(the); |
1320 | 53 | transfer = fxLastProperty(the, transfers); |
1321 | | |
1322 | 53 | mxPushSlot(record); |
1323 | 53 | mxGetID(mxID(_bindings)); |
1324 | 53 | if (!mxIsUndefined(the->stack)) { |
1325 | 38 | txSlot* array; |
1326 | 38 | txInteger length, index; |
1327 | | |
1328 | 38 | array = the->stack; |
1329 | 38 | mxPushSlot(array); |
1330 | 38 | mxGetID(mxID(_length)); |
1331 | 38 | length = fxToInteger(the, the->stack); |
1332 | 38 | mxPop(); |
1333 | | |
1334 | 242 | for (index = 0; index < length; index++) { |
1335 | 212 | txSlot* item; |
1336 | 212 | txSlot* temporary; |
1337 | 212 | txInteger from = 0; |
1338 | 212 | txInteger export = 0; |
1339 | 212 | txInteger import = 0; |
1340 | 212 | txID nameID, asID; |
1341 | 212 | txSlot* specifier = C_NULL; |
1342 | 212 | txSlot* former; |
1343 | | |
1344 | 212 | mxPushSlot(array); |
1345 | 212 | mxGetIndex(index); |
1346 | 212 | item = the->stack; |
1347 | | |
1348 | 212 | mxTemporary(temporary); |
1349 | | |
1350 | 212 | mxPushSlot(item); |
1351 | 212 | mxGetID(mxID(_from)); |
1352 | 212 | if (!mxIsUndefined(the->stack)) { |
1353 | 73 | from++; |
1354 | 73 | fxToString(the, the->stack); |
1355 | 73 | mxPullSlot(temporary); |
1356 | 73 | specifier = temporary; |
1357 | 73 | } |
1358 | 139 | else |
1359 | 139 | mxPop(); |
1360 | | |
1361 | 212 | mxPushSlot(item); |
1362 | 212 | mxGetID(fxID(the, "exportAllFrom")); |
1363 | 212 | if (!mxIsUndefined(the->stack)) { |
1364 | 26 | from++; |
1365 | 26 | export++; |
1366 | 26 | fxToString(the, the->stack); |
1367 | 26 | mxPullSlot(temporary); |
1368 | 26 | specifier = temporary; |
1369 | 26 | nameID = XS_NO_ID; |
1370 | 26 | } |
1371 | 186 | else |
1372 | 186 | mxPop(); |
1373 | | |
1374 | 212 | mxPushSlot(item); |
1375 | 212 | mxGetID(fxID(the, "importAllFrom")); |
1376 | 212 | if (!mxIsUndefined(the->stack)) { |
1377 | 22 | from++; |
1378 | 22 | import++; |
1379 | 22 | fxToString(the, the->stack); |
1380 | 22 | mxPullSlot(temporary); |
1381 | 22 | specifier = temporary; |
1382 | 22 | nameID = XS_NO_ID; |
1383 | 22 | } |
1384 | 190 | else |
1385 | 190 | mxPop(); |
1386 | | |
1387 | 212 | mxPushSlot(item); |
1388 | 212 | mxGetID(mxID(_export)); |
1389 | 212 | if (!mxIsUndefined(the->stack)) { |
1390 | 119 | export++; |
1391 | 119 | nameID = fxToID(the, the->stack); |
1392 | 119 | } |
1393 | 212 | mxPop(); |
1394 | | |
1395 | 212 | mxPushSlot(item); |
1396 | 212 | mxGetID(mxID(_import)); |
1397 | 212 | if (!mxIsUndefined(the->stack)) { |
1398 | 43 | import++; |
1399 | 43 | nameID = fxToID(the, the->stack); |
1400 | 43 | } |
1401 | 212 | mxPop(); |
1402 | | |
1403 | 212 | mxPushSlot(item); |
1404 | 212 | mxGetID(mxID(_as)); |
1405 | 212 | if (!mxIsUndefined(the->stack)) { |
1406 | 98 | asID = fxToID(the, the->stack); |
1407 | 98 | } |
1408 | 114 | else |
1409 | 114 | asID = nameID; |
1410 | 212 | mxPop(); |
1411 | | |
1412 | 212 | if (from > 1) |
1413 | 1 | mxSyntaxError("too many from"); |
1414 | 211 | else if (export > 1) |
1415 | 0 | mxSyntaxError("too many export"); |
1416 | 211 | else if (import > 1) |
1417 | 0 | mxSyntaxError("too many import"); |
1418 | 211 | else if (export && import) |
1419 | 1 | mxSyntaxError("export and import"); |
1420 | 210 | else if (!export && !import) |
1421 | 3 | mxSyntaxError("neither export nor import"); |
1422 | | |
1423 | 207 | if (export) { |
1424 | 144 | if (asID != XS_NO_ID) { |
1425 | 131 | former = transfers->next; |
1426 | 408 | while (former) { |
1427 | 278 | txSlot* aliases = mxTransferAliases(former); |
1428 | 278 | if (!mxIsNull(aliases)) { |
1429 | 208 | txSlot* alias = aliases->value.reference->next; |
1430 | 432 | while (alias) { |
1431 | 225 | if (alias->value.symbol == asID) { |
1432 | 1 | fxIDToString(the, asID, the->nameBuffer, sizeof(the->nameBuffer)); |
1433 | 1 | mxSyntaxError("duplicate export %s", the->nameBuffer); |
1434 | 1 | } |
1435 | 224 | alias = alias->next; |
1436 | 224 | } |
1437 | 208 | } |
1438 | 277 | former = former->next; |
1439 | 277 | } |
1440 | 130 | if (specifier) { |
1441 | 44 | former = transfers->next; |
1442 | 209 | while (former) { |
1443 | 165 | txSlot* aliases = mxTransferAliases(former); |
1444 | 165 | if (!mxIsNull(aliases)) { |
1445 | 115 | txSlot* local = mxTransferLocal(former); |
1446 | 115 | if (mxIsNull(local)) { |
1447 | 31 | txSlot* from = mxTransferFrom(former); |
1448 | 31 | if (!mxIsNull(from) && !c_strcmp(from->value.string, specifier->value.string)) { |
1449 | 15 | txSlot* import = mxTransferImport(former); |
1450 | 15 | if (mxIsNull(import)) { |
1451 | 0 | if (nameID == XS_NO_ID) |
1452 | 0 | break; |
1453 | 0 | } |
1454 | 15 | else { |
1455 | 15 | if (nameID == import->value.symbol) |
1456 | 0 | break; |
1457 | 15 | } |
1458 | 15 | } |
1459 | 31 | } |
1460 | 115 | } |
1461 | 165 | former = former->next; |
1462 | 165 | } |
1463 | 44 | } |
1464 | 86 | else { |
1465 | 86 | former = transfers->next; |
1466 | 187 | while (former) { |
1467 | 111 | txSlot* local = mxTransferLocal(former); |
1468 | 111 | if ((local->kind == XS_SYMBOL_KIND) && (local->value.symbol == nameID)) |
1469 | 10 | break; |
1470 | 101 | former = former->next; |
1471 | 101 | } |
1472 | 86 | } |
1473 | 130 | if (former) { |
1474 | 10 | txSlot* aliases = mxTransferAliases(former); |
1475 | 10 | txSlot* alias; |
1476 | 10 | if (mxIsNull(aliases)) { |
1477 | 0 | mxPush(mxObjectPrototype); |
1478 | 0 | alias = fxLastProperty(the, fxNewObjectInstance(the)); |
1479 | 0 | mxPullSlot(mxTransferAliases(former)); |
1480 | 0 | } |
1481 | 10 | else { |
1482 | 10 | alias = fxLastProperty(the, aliases->value.reference); |
1483 | 10 | } |
1484 | 10 | fxNextSymbolProperty(the, alias, asID, XS_NO_ID, XS_DONT_ENUM_FLAG); |
1485 | 10 | } |
1486 | 120 | else if (specifier) { |
1487 | 44 | mxPushNull(); |
1488 | 44 | mxPushSlot(specifier); |
1489 | 44 | if ((nameID != XS_NO_ID) || (asID != XS_NO_ID)) { |
1490 | 44 | if (nameID != XS_NO_ID) |
1491 | 31 | mxPushSymbol(nameID); |
1492 | 13 | else |
1493 | 13 | mxPushNull(); |
1494 | 44 | if (asID != XS_NO_ID) |
1495 | 44 | mxPushSymbol(asID); |
1496 | 0 | else |
1497 | 0 | mxPushSymbol(nameID); |
1498 | 44 | mxPushInteger(4); |
1499 | 44 | } |
1500 | 0 | else { |
1501 | 0 | mxPushNull(); |
1502 | 0 | mxPushInteger(3); |
1503 | 0 | } |
1504 | 44 | fxPrepareTransfer(the, XS_NO_FLAG); |
1505 | 44 | transfer = fxNextSlotProperty(the, transfer, the->stack, XS_NO_ID, XS_DONT_ENUM_FLAG); |
1506 | 44 | mxPop(); // transfer |
1507 | 44 | } |
1508 | 76 | else { |
1509 | 76 | mxPushSymbol(nameID); |
1510 | 76 | mxPushNull(); |
1511 | 76 | mxPushNull(); |
1512 | 76 | mxPushSymbol(asID); |
1513 | 76 | mxPushInteger(4); |
1514 | 76 | fxPrepareTransfer(the, XS_NO_FLAG); |
1515 | 76 | transfer = fxNextSlotProperty(the, transfer, the->stack, XS_NO_ID, XS_DONT_ENUM_FLAG); |
1516 | 76 | mxPop(); // transfer |
1517 | 76 | } |
1518 | 130 | } |
1519 | 13 | else if (specifier) { |
1520 | 13 | former = transfers->next; |
1521 | 83 | while (former) { |
1522 | 70 | txSlot* from = mxTransferFrom(former); |
1523 | 70 | if (!mxIsNull(from) && !c_strcmp(from->value.string, specifier->value.string)) { |
1524 | 8 | txSlot* local = mxTransferLocal(former); |
1525 | 8 | if (mxIsNull(local)) { |
1526 | 1 | txSlot* import = mxTransferImport(former); |
1527 | 1 | if (mxIsNull(import)) { |
1528 | 0 | txSlot* aliases = mxTransferAliases(former); |
1529 | 0 | if (mxIsNull(aliases)) { |
1530 | 0 | mxSyntaxError("duplicate export *"); |
1531 | 0 | } |
1532 | 0 | } |
1533 | 1 | } |
1534 | 8 | } |
1535 | 70 | former = former->next; |
1536 | 70 | } |
1537 | 13 | mxPushNull(); |
1538 | 13 | mxPushSlot(specifier); |
1539 | 13 | mxPushNull(); |
1540 | 13 | mxPushInteger(3); |
1541 | 13 | fxPrepareTransfer(the, XS_NO_FLAG); |
1542 | 13 | transfer = fxNextSlotProperty(the, transfer, the->stack, XS_NO_ID, XS_DONT_ENUM_FLAG); |
1543 | 13 | mxPop(); // transfer |
1544 | 13 | } |
1545 | 0 | else |
1546 | 0 | mxSyntaxError("invalid export *"); |
1547 | 144 | } |
1548 | 63 | else { |
1549 | 63 | if (!specifier) { |
1550 | 1 | if (asID == XS_NO_ID) |
1551 | 0 | mxSyntaxError("invalid import *"); |
1552 | 1 | else { |
1553 | 1 | fxIDToString(the, asID, the->nameBuffer, sizeof(the->nameBuffer)); |
1554 | 1 | mxSyntaxError("invalid import %s", the->nameBuffer); |
1555 | 1 | } |
1556 | 1 | } |
1557 | 62 | else if (asID == XS_NO_ID) |
1558 | 1 | mxSyntaxError("invalid import * from %s", specifier->value.string); |
1559 | | |
1560 | 61 | former = transfers->next; |
1561 | 265 | while (former) { |
1562 | 204 | txSlot* local = mxTransferLocal(former); |
1563 | 204 | if ((local->kind == XS_SYMBOL_KIND) && (local->value.symbol == asID)) { |
1564 | 0 | txSlot* from = mxTransferFrom(former); |
1565 | 0 | if (!mxIsNull(from)) { |
1566 | 0 | fxIDToString(the, asID, the->nameBuffer, sizeof(the->nameBuffer)); |
1567 | 0 | mxSyntaxError("duplicate import %s", the->nameBuffer); |
1568 | 0 | } |
1569 | 0 | break; |
1570 | 0 | } |
1571 | 204 | former = former->next; |
1572 | 204 | } |
1573 | 61 | if (former) { |
1574 | 0 | txSlot* from = mxTransferFrom(former); |
1575 | 0 | mxPushSlot(specifier); |
1576 | 0 | mxPullSlot(from); |
1577 | 0 | if (nameID != XS_NO_ID) { |
1578 | 0 | txSlot* import = mxTransferImport(former); |
1579 | 0 | import->kind = XS_SYMBOL_KIND; |
1580 | 0 | import->value.symbol = nameID; |
1581 | 0 | } |
1582 | 0 | } |
1583 | 61 | else { |
1584 | 61 | mxPushSymbol(asID); |
1585 | 61 | mxPushSlot(specifier); |
1586 | 61 | if (nameID != XS_NO_ID) |
1587 | 40 | mxPushSymbol(nameID); |
1588 | 21 | else |
1589 | 21 | mxPushNull(); |
1590 | 61 | mxPushInteger(3); |
1591 | 61 | fxPrepareTransfer(the, XS_NO_FLAG); |
1592 | 61 | transfer = fxNextSlotProperty(the, transfer, the->stack, XS_NO_ID, XS_DONT_ENUM_FLAG); |
1593 | 61 | mxPop(); // transfer |
1594 | 61 | } |
1595 | 61 | } |
1596 | | |
1597 | 204 | mxPop(); // temporary |
1598 | 204 | mxPop(); // item |
1599 | 204 | } |
1600 | 38 | } |
1601 | 45 | mxPop(); // bindings |
1602 | | |
1603 | | #if mxReport |
1604 | | { |
1605 | | fxIDToString(the, mxModuleInstanceInternal(instance)->value.module.id, the->nameBuffer, sizeof(the->nameBuffer)); |
1606 | | fprintf(stderr, "### %s\n", the->nameBuffer); |
1607 | | txSlot* transfer = the->stack->value.reference->next; |
1608 | | while (transfer) { |
1609 | | txSlot* local = mxTransferLocal(transfer); |
1610 | | txSlot* from = mxTransferFrom(transfer); |
1611 | | txSlot* import = mxTransferImport(transfer); |
1612 | | txSlot* aliases = mxTransferAliases(transfer); |
1613 | | if (local->kind != XS_NULL_KIND) { |
1614 | | fxIDToString(the, local->value.symbol, the->nameBuffer, sizeof(the->nameBuffer)); |
1615 | | fprintf(stderr, " local %s", the->nameBuffer); |
1616 | | } |
1617 | | if (from->kind != XS_NULL_KIND) { |
1618 | | fprintf(stderr, " from %s", from->value.string); |
1619 | | } |
1620 | | if (import->kind != XS_NULL_KIND) { |
1621 | | fxIDToString(the, import->value.symbol, the->nameBuffer, sizeof(the->nameBuffer)); |
1622 | | fprintf(stderr, " import %s", the->nameBuffer); |
1623 | | } |
1624 | | if (!mxIsNull(aliases)) { |
1625 | | txSlot* alias = aliases->value.reference->next; |
1626 | | while (alias) { |
1627 | | fxIDToString(the, alias->value.symbol, the->nameBuffer, sizeof(the->nameBuffer)); |
1628 | | fprintf(stderr, " alias %s", the->nameBuffer); |
1629 | | alias = alias->next; |
1630 | | } |
1631 | | } |
1632 | | fprintf(stderr, "\n"); |
1633 | | transfer = transfer->next; |
1634 | | } |
1635 | | } |
1636 | | #endif |
1637 | | |
1638 | 45 | mxPullSlot(mxModuleInstanceTransfers(instance)); |
1639 | | |
1640 | 45 | mxPushSlot(record); |
1641 | 45 | mxGetID(mxID(_needsImport)); |
1642 | 45 | if (!mxIsUndefined(the->stack)) { |
1643 | 3 | if (fxToBoolean(the, the->stack)) { |
1644 | 2 | txSlot* internal = mxModuleInstanceInternal(instance); |
1645 | 2 | internal->flag |= XS_IMPORT_FLAG; |
1646 | 2 | } |
1647 | 3 | } |
1648 | 45 | mxPop(); // needsImport |
1649 | | |
1650 | 45 | mxPushSlot(record); |
1651 | 45 | mxGetID(mxID(_needsImportMeta)); |
1652 | 45 | if (!mxIsUndefined(the->stack)) { |
1653 | 2 | if (fxToBoolean(the, the->stack)) { |
1654 | 1 | txSlot* internal = mxModuleInstanceInternal(instance); |
1655 | 1 | internal->flag |= XS_IMPORT_META_FLAG; |
1656 | 1 | } |
1657 | 2 | } |
1658 | 45 | mxPop(); // _needsImportMeta |
1659 | 45 | } |
1660 | | |
1661 | | txBoolean fxMapModule(txMachine* the, txSlot* realm, txID moduleID, txSlot* module, txSlot* queue, txSlot* result) |
1662 | 404 | { |
1663 | 404 | txSlot* moduleMap = mxModuleMap(realm); |
1664 | 404 | txSlot* descriptor = moduleMap->value.reference->next; |
1665 | 638 | while (descriptor) { |
1666 | 431 | if (descriptor->ID == moduleID) { |
1667 | 197 | fxMapModuleDescriptor(the, realm, moduleID, module, queue, result,descriptor); |
1668 | 197 | return 1; |
1669 | 197 | } |
1670 | 234 | descriptor = descriptor->next; |
1671 | 234 | } |
1672 | 207 | return 0; |
1673 | 404 | } |
1674 | | |
1675 | | void fxMapModuleDescriptor(txMachine* the, txSlot* realm, txID moduleID, txSlot* module, txSlot* queue, txSlot* result, txSlot* descriptor) |
1676 | 232 | { |
1677 | 232 | txSlot* property; |
1678 | 232 | if (!mxIsReference(descriptor)) |
1679 | 12 | mxTypeError("descriptor: not an object"); |
1680 | | |
1681 | 220 | mxPushSlot(descriptor); |
1682 | 220 | mxGetID(fxID(the, "namespace")); |
1683 | 220 | property = the->stack; |
1684 | 220 | if (!mxIsUndefined(property)) { |
1685 | 38 | if ((property->kind == XS_STRING_KIND) || (property->kind == XS_STRING_X_KIND)) { |
1686 | 28 | txSlot* aliasRealm; |
1687 | 28 | txSlot* aliasOwn; |
1688 | 28 | txID aliasModuleID; |
1689 | 28 | txSlot* aliasModule; |
1690 | 28 | mxPushSlot(descriptor); |
1691 | 28 | mxGetID(fxID(the, "compartment")); |
1692 | 28 | if (!mxIsUndefined(the->stack)) { |
1693 | 23 | txSlot* program = fxCheckCompartmentInstance(the, the->stack); |
1694 | 23 | aliasRealm = mxModuleInstanceInternal(program)->value.module.realm; |
1695 | 23 | } |
1696 | 5 | else { |
1697 | 5 | aliasRealm = mxRealmParent(realm)->value.reference; |
1698 | 5 | } |
1699 | 28 | aliasOwn = mxOwnModules(aliasRealm)->value.reference; |
1700 | 28 | mxPop(); |
1701 | 28 | aliasModuleID = fxResolveSpecifier(the, aliasRealm, XS_NO_ID, property); |
1702 | | // if ((aliasRealm == realm) && (aliasModuleID == moduleID)) |
1703 | | // mxTypeError("descriptor.specifier is circular"); |
1704 | | |
1705 | 28 | aliasModule = mxBehaviorGetProperty(the, aliasOwn, aliasModuleID, 0, XS_ANY); |
1706 | 28 | if (aliasModule) { |
1707 | 18 | property = aliasModule; |
1708 | 18 | } |
1709 | 10 | else { |
1710 | 10 | property = mxBehaviorSetProperty(the, aliasOwn, aliasModuleID, 0, XS_OWN); |
1711 | 10 | fxNewModule(the, aliasRealm, aliasModuleID, XS_NO_FLAG, property); |
1712 | 10 | } |
1713 | 28 | goto namespace; |
1714 | 28 | } |
1715 | 10 | else { |
1716 | 10 | txSlot* instance = module->value.reference; |
1717 | 10 | if (!mxIsReference(property)) |
1718 | 3 | mxTypeError("descriptor.namespace: not an object"); |
1719 | 7 | if (mxIsModule(property->value.reference)) |
1720 | 0 | goto namespace; |
1721 | 7 | fxLoadVirtualModuleNamespace(the, property->value.reference, instance); |
1722 | 7 | txID status = mxModuleInstanceStatus(instance); |
1723 | 7 | if ((status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADING)) { |
1724 | 6 | mxModuleInstanceStatus(instance) = XS_MODULE_STATUS_EXECUTED; |
1725 | 6 | if (result) { |
1726 | | |
1727 | 0 | } |
1728 | 6 | else { |
1729 | 6 | fxCompleteModule(the, instance, C_NULL); |
1730 | 6 | fxRunImportFulfilled(the, instance, instance); |
1731 | 6 | } |
1732 | 6 | } |
1733 | 7 | goto done; |
1734 | 7 | } |
1735 | | |
1736 | 28 | namespace: |
1737 | 28 | if (module->kind == XS_UNDEFINED_KIND) { |
1738 | 0 | module->kind = property->kind; |
1739 | 0 | module->value = property->value; |
1740 | 0 | } |
1741 | 28 | else { |
1742 | 28 | txID status = mxModuleStatus(module); |
1743 | 28 | mxCheck(the, (status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADING)); |
1744 | 28 | mxPushSlot(module); |
1745 | 28 | realm = mxModuleInternal(module)->value.module.realm; |
1746 | 28 | fxOverrideModule(the, queue, mxOwnModules(realm), result, module->value.reference, property->value.reference); |
1747 | 28 | status = mxModuleStatus(property); |
1748 | 28 | if (result) { |
1749 | 21 | if (status == XS_MODULE_STATUS_ERROR) { |
1750 | 4 | mxPushSlot(mxModuleMeta(property)); |
1751 | 4 | mxPull(mxException); |
1752 | 4 | fxJump(the); |
1753 | 4 | } |
1754 | 17 | else if (status == XS_MODULE_STATUS_EXECUTED) { |
1755 | 7 | } |
1756 | 10 | else { |
1757 | 10 | fxQueueModule(the, queue, property); |
1758 | 10 | } |
1759 | 21 | } |
1760 | 7 | else { |
1761 | 7 | if (status == XS_MODULE_STATUS_ERROR) { |
1762 | 3 | fxCompleteModule(the, module->value.reference, C_NULL); |
1763 | 3 | fxRunImportRejected(the, module->value.reference, property->value.reference); |
1764 | 3 | } |
1765 | 4 | else if (status == XS_MODULE_STATUS_EXECUTED) { |
1766 | 3 | fxCompleteModule(the, module->value.reference, C_NULL); |
1767 | 3 | fxRunImportFulfilled(the, module->value.reference, property->value.reference); |
1768 | 3 | } |
1769 | 1 | else { |
1770 | 1 | txSlot* srcSlot = mxModuleFulfill(module); |
1771 | 1 | txSlot* dstSlot = fxLastProperty(the, property->value.reference); |
1772 | 3 | while (srcSlot) { |
1773 | 2 | dstSlot = fxNextSlotProperty(the, dstSlot, srcSlot, XS_NO_ID, XS_NO_FLAG); |
1774 | 2 | srcSlot = srcSlot->next; |
1775 | 2 | } |
1776 | 1 | fxQueueModule(the, queue, property); |
1777 | 1 | } |
1778 | 7 | } |
1779 | 24 | mxPop(); |
1780 | 24 | } |
1781 | 24 | goto done; |
1782 | 28 | } |
1783 | 182 | mxPop(); // property; |
1784 | | |
1785 | 182 | if (module->kind == XS_UNDEFINED_KIND) |
1786 | 0 | fxNewModule(the, realm, moduleID, XS_NO_FLAG, module); |
1787 | 182 | else { |
1788 | 182 | txID status = mxModuleStatus(module); |
1789 | 182 | mxCheck(the, (status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADING)); |
1790 | 182 | } |
1791 | | |
1792 | 182 | mxPushSlot(descriptor); |
1793 | 182 | mxGetID(fxID(the, "archive")); |
1794 | 182 | property = the->stack; |
1795 | 182 | if (!mxIsUndefined(property)) { |
1796 | 0 | void* archive = fxGetHostData(the, property); |
1797 | 0 | txString path; |
1798 | 0 | void* code; |
1799 | 0 | size_t size; |
1800 | 0 | txScript script; |
1801 | 0 | mxPushSlot(descriptor); |
1802 | 0 | mxGetID(fxID(the, "path")); |
1803 | 0 | property = the->stack; |
1804 | 0 | path = fxToString(the, property); |
1805 | 0 | code = fxGetArchiveCode(the, archive, path, &size); |
1806 | 0 | if (code == C_NULL) |
1807 | 0 | mxURIError("module not found: %s", path); |
1808 | 0 | mxPop(); |
1809 | 0 | script.callback = NULL; |
1810 | 0 | script.symbolsBuffer = NULL; |
1811 | 0 | script.symbolsSize = 0; |
1812 | 0 | script.codeBuffer = code; |
1813 | 0 | script.codeSize = (txSize)size; |
1814 | 0 | script.hostsBuffer = NULL; |
1815 | 0 | script.hostsSize = 0; |
1816 | 0 | script.path = path; |
1817 | 0 | script.version[0] = XS_MAJOR_VERSION; |
1818 | 0 | script.version[1] = XS_MINOR_VERSION; |
1819 | 0 | script.version[2] = XS_PATCH_VERSION; |
1820 | 0 | script.version[3] = 0; |
1821 | 0 | fxRunScript(the, &script, module, C_NULL, C_NULL, C_NULL, module->value.reference); |
1822 | | |
1823 | | // mxPushClosure(module); |
1824 | 0 | mxPop(); |
1825 | | // mxPop(); // path |
1826 | 0 | if (mxModuleExecute(module)->kind == XS_NULL_KIND) |
1827 | 0 | mxTypeError("no module"); |
1828 | 0 | goto importMeta; |
1829 | 0 | } |
1830 | 182 | mxPop(); // property; |
1831 | | |
1832 | 182 | mxPushSlot(descriptor); |
1833 | 182 | mxGetID(fxID(the, "source")); |
1834 | 182 | property = the->stack; |
1835 | 182 | if (!mxIsUndefined(property)) { |
1836 | 178 | if ((property->kind == XS_STRING_KIND) || (property->kind == XS_STRING_X_KIND)) { |
1837 | 11 | txSlot* loader = mxModuleLoader(module); |
1838 | 11 | loader->value.module.realm = mxRealmParent(realm)->value.reference; |
1839 | 11 | if (property->kind == XS_STRING_X_KIND) |
1840 | 0 | loader->value.module.id = fxNewNameX(the, property->value.string); |
1841 | 11 | else |
1842 | 11 | loader->value.module.id = fxNewName(the, property); |
1843 | 11 | mxModuleStatus(module) = XS_MODULE_STATUS_NEW; |
1844 | 11 | goto done; |
1845 | 11 | } |
1846 | 167 | if (!mxIsReference(property)) |
1847 | 1 | mxTypeError("descriptor.source: not an object"); |
1848 | 166 | if (mxIsModuleSource(property->value.reference)) |
1849 | 113 | fxDuplicateModuleTransfers(the, property, module); |
1850 | 53 | else |
1851 | | // mxTypeError("descriptor.source is object"); |
1852 | 53 | fxLoadVirtualModuleSource(the, property, module->value.reference); |
1853 | 166 | goto importMeta; |
1854 | 167 | } |
1855 | 4 | mxPop(); // property |
1856 | | |
1857 | 4 | mxTypeError("invalid descriptor"); |
1858 | | |
1859 | 156 | importMeta: |
1860 | 156 | mxPop(); // property |
1861 | 156 | mxModuleStatus(module) = XS_MODULE_STATUS_LOADED; |
1862 | | |
1863 | 156 | mxPushSlot(descriptor); |
1864 | 156 | mxGetID(fxID(the, "importMeta")); |
1865 | 156 | property = the->stack; |
1866 | 156 | if (!mxIsUndefined(property)) { |
1867 | 66 | if (!mxIsReference(property)) |
1868 | 0 | mxTypeError("descriptor.importMeta: not an object"); |
1869 | 66 | txSlot* meta = mxModuleMeta(module); |
1870 | 66 | if (mxIsNull(meta)) { |
1871 | 66 | txSlot* instance = fxNewInstance(the); |
1872 | 66 | meta->value.reference = instance; |
1873 | 66 | meta->kind = XS_REFERENCE_KIND; |
1874 | 66 | } |
1875 | 66 | meta->value.reference->flag &= ~XS_DONT_PATCH_FLAG; |
1876 | 66 | mxPushUndefined(); |
1877 | 66 | mxPush(mxAssignObjectFunction); |
1878 | 66 | mxCall(); |
1879 | 66 | mxPushSlot(meta); |
1880 | 66 | mxPushSlot(property); |
1881 | 66 | mxRunCount(2); |
1882 | 66 | mxPop(); |
1883 | 66 | meta->value.reference->flag |= XS_DONT_PATCH_FLAG; |
1884 | 66 | } |
1885 | 156 | mxPop(); // property |
1886 | | |
1887 | 156 | mxPushSlot(descriptor); |
1888 | 156 | mxGetID(fxID(the, "specifier")); |
1889 | 156 | property = the->stack; |
1890 | 156 | if (!mxIsUndefined(property)) { |
1891 | 4 | txSlot* internal = mxModuleInternal(module); |
1892 | 4 | fxToString(the, property); |
1893 | 4 | if (property->kind == XS_STRING_X_KIND) |
1894 | 0 | internal->value.module.id = fxNewNameX(the, property->value.string); |
1895 | 4 | else |
1896 | 4 | internal->value.module.id = fxNewName(the, property); |
1897 | 4 | } |
1898 | | |
1899 | 156 | goto done; |
1900 | | |
1901 | 197 | done: |
1902 | 197 | mxPop(); // property |
1903 | 197 | } |
1904 | | |
1905 | | |
1906 | | void fxNewModule(txMachine* the, txSlot* realm, txID moduleID, txFlag moduleFlag, txSlot* module) |
1907 | 393 | { |
1908 | 393 | txSlot* slot; |
1909 | | |
1910 | 393 | mxPush(mxModulePrototype); |
1911 | 393 | slot = fxNewObjectInstance(the); |
1912 | 393 | slot->flag |= XS_EXOTIC_FLAG | XS_DONT_PATCH_FLAG; |
1913 | | /* HOST */ |
1914 | 393 | slot = slot->next = fxNewSlot(the); |
1915 | 393 | slot->ID = XS_MODULE_BEHAVIOR; |
1916 | 393 | slot->flag = XS_INTERNAL_FLAG | moduleFlag; |
1917 | 393 | slot->kind = XS_MODULE_KIND; |
1918 | 393 | slot->value.module.realm = realm; |
1919 | 393 | slot->value.module.id = moduleID; |
1920 | | /* EXPORTS */ |
1921 | 393 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
1922 | | /* STUFF */ |
1923 | 393 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
1924 | | /* META */ |
1925 | 393 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
1926 | | /* TRANSFERS */ |
1927 | 393 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
1928 | | /* INITIALIZE */ |
1929 | 393 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
1930 | | /* FUNCTION */ |
1931 | 393 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
1932 | | /* HOSTS */ |
1933 | 393 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
1934 | | /* LOADER */ |
1935 | 393 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
1936 | 393 | slot->flag = XS_INTERNAL_FLAG | moduleFlag; |
1937 | 393 | slot->kind = XS_MODULE_KIND; |
1938 | 393 | slot->value.module.realm = realm; |
1939 | 393 | slot->value.module.id = moduleID; |
1940 | 393 | module->kind = the->stack->kind; |
1941 | 393 | module->value = the->stack->value; |
1942 | 393 | mxPop(); |
1943 | | #if mxInstrument |
1944 | | the->loadedModulesCount++; |
1945 | | #endif |
1946 | 393 | } |
1947 | | |
1948 | | void fxOrderModule(txMachine* the, txSlot* queue, txSlot* order, txSlot* module) |
1949 | 308 | { |
1950 | 308 | txSlot** fromAddress = &(queue->next); |
1951 | 308 | txSlot** toAddress = &(order->next); |
1952 | 308 | txSlot* from; |
1953 | 308 | txSlot* to; |
1954 | 308 | while ((from = *fromAddress)) { |
1955 | 308 | if (from == module) { |
1956 | 308 | *fromAddress = module->next; |
1957 | 308 | module->next = C_NULL; |
1958 | 308 | break; |
1959 | 308 | } |
1960 | 0 | fromAddress = &(from->next); |
1961 | 0 | } |
1962 | 308 | if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) { |
1963 | 147 | txSlot* transfer = mxModuleTransfers(module)->value.reference->next; |
1964 | 517 | while (transfer) { |
1965 | 370 | from = mxTransferFrom(transfer); |
1966 | 370 | if (from->kind != XS_NULL_KIND) { |
1967 | 138 | to = queue->next; |
1968 | 157 | while (to) { |
1969 | 119 | if (to->value.reference == from->value.reference) |
1970 | 100 | break; |
1971 | 19 | to = to->next; |
1972 | 19 | } |
1973 | 138 | if (to) |
1974 | 100 | fxOrderModule(the, queue, order, to); |
1975 | 138 | } |
1976 | 370 | transfer = transfer->next; |
1977 | 370 | } |
1978 | 147 | } |
1979 | 489 | while ((to = *toAddress)) { |
1980 | 181 | if (to->value.reference == module->value.reference) |
1981 | 0 | return; |
1982 | 181 | toAddress = &(to->next); |
1983 | 181 | } |
1984 | 308 | *toAddress = module; |
1985 | 308 | } |
1986 | | |
1987 | | void fxOverrideModule(txMachine* the, txSlot* queue, txSlot* list, txSlot* result, txSlot* module, txSlot* record) |
1988 | 28 | { |
1989 | 28 | txSlot** address = &(queue->next); |
1990 | 28 | txSlot* slot; |
1991 | 60 | while ((slot = *address)) { |
1992 | 32 | if (slot->value.reference == module) { |
1993 | | // slot->value.reference = record; |
1994 | 28 | *address = slot->next; |
1995 | 28 | } |
1996 | 4 | else { |
1997 | 4 | if (mxModuleStatus(slot) == XS_MODULE_STATUS_LINKING) { |
1998 | 0 | txSlot* transfer = mxModuleTransfers(slot)->value.reference->next; |
1999 | 0 | while (transfer) { |
2000 | 0 | txSlot* from = mxTransferFrom(transfer); |
2001 | 0 | if ((from->kind == XS_REFERENCE_KIND) && (from->value.reference == module)) |
2002 | 0 | from->value.reference = record; |
2003 | 0 | transfer = transfer->next; |
2004 | 0 | } |
2005 | 0 | } |
2006 | 4 | } |
2007 | 32 | address = &(slot->next); |
2008 | 32 | } |
2009 | 28 | slot = list->value.reference->next; |
2010 | 68 | while (slot) { |
2011 | 40 | if (slot->value.reference == module) { |
2012 | 28 | slot->value.reference = record; |
2013 | 28 | } |
2014 | 40 | slot = slot->next; |
2015 | 40 | } |
2016 | 28 | if (result) { |
2017 | 21 | if (result->value.reference == module) { |
2018 | 21 | result->value.reference = record; |
2019 | 21 | } |
2020 | 21 | } |
2021 | 28 | } |
2022 | | |
2023 | | void fxPrepareModule(txMachine* the, txFlag flag) |
2024 | 180 | { |
2025 | 180 | txSlot* module = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.module; |
2026 | 180 | txInteger c = the->stack->value.integer, i; |
2027 | 180 | txSlot* argument = the->stack + c; |
2028 | 180 | txSlot* result = the->stack + c; |
2029 | 180 | txSlot* slot; |
2030 | 180 | txSlot* property; |
2031 | 180 | property = mxModuleInstanceInternal(module); |
2032 | 180 | fxCheckModuleFlag(the, property->value.module.id, flag, property->flag); |
2033 | 180 | property->flag |= flag; |
2034 | 180 | slot = argument--; |
2035 | 180 | property = mxModuleInstanceInitialize(module); |
2036 | 180 | property->kind = slot->kind; |
2037 | 180 | property->value = slot->value; |
2038 | 180 | slot = argument--; |
2039 | 180 | property = mxModuleInstanceExecute(module); |
2040 | 180 | property->kind = slot->kind; |
2041 | 180 | property->value = slot->value; |
2042 | 180 | mxFunctionInstanceCode(slot->value.reference)->ID = mxModuleInstanceInternal(module)->value.module.id; |
2043 | 180 | slot = &mxHosts; |
2044 | 180 | property = mxModuleInstanceHosts(module); |
2045 | 180 | property->kind = slot->kind; |
2046 | 180 | property->value = slot->value; |
2047 | 180 | mxPush(mxObjectPrototype); |
2048 | 180 | slot = fxLastProperty(the, fxNewObjectInstance(the)); |
2049 | 563 | for (i = 2; i < c; i++) |
2050 | 383 | slot = fxNextSlotProperty(the, slot, argument--, XS_NO_ID, XS_DONT_ENUM_FLAG); |
2051 | 180 | property = mxModuleInstanceTransfers(module); |
2052 | 180 | mxPullSlot(property); |
2053 | 180 | result->kind = XS_REFERENCE_KIND; |
2054 | 180 | result->value.reference = module; |
2055 | 180 | the->stack = result; |
2056 | 180 | } |
2057 | | |
2058 | | void fxPrepareTransfer(txMachine* the, txFlag flag) |
2059 | 576 | { |
2060 | 576 | txInteger c = the->stack->value.integer, i; |
2061 | 576 | txSlot* argument = the->stack + c; |
2062 | 576 | txSlot* result = the->stack + c; |
2063 | 576 | txSlot* property; |
2064 | 576 | txSlot* slot; |
2065 | 576 | mxPush(mxTransferPrototype); |
2066 | 576 | property = fxNewObjectInstance(the); |
2067 | 576 | property = fxNextSlotProperty(the, property, argument--, mxID(_local), XS_DONT_ENUM_FLAG); |
2068 | 576 | property = fxNextSlotProperty(the, property, argument--, mxID(_from), XS_DONT_ENUM_FLAG | flag); |
2069 | 576 | property = fxNextSlotProperty(the, property, argument--, mxID(_import), XS_DONT_ENUM_FLAG); |
2070 | 576 | if (c > 3) { |
2071 | 416 | mxPush(mxObjectPrototype); |
2072 | 416 | slot = fxLastProperty(the, fxNewObjectInstance(the)); |
2073 | 416 | if (argument->kind != XS_NULL_KIND) { |
2074 | 830 | for (i = 3; i < c; i++) |
2075 | 417 | slot = fxNextSlotProperty(the, slot, argument--, XS_NO_ID, XS_DONT_ENUM_FLAG); |
2076 | 413 | } |
2077 | 416 | property = fxNextSlotProperty(the, property, the->stack, mxID(_aliases), XS_DONT_ENUM_FLAG); |
2078 | 416 | mxPop(); |
2079 | 416 | } |
2080 | 160 | else { |
2081 | 160 | property = fxNextNullProperty(the, property, mxID(_aliases), XS_DONT_ENUM_FLAG); |
2082 | 160 | } |
2083 | 576 | property = fxNextNullProperty(the, property, mxID(_closure), XS_DONT_ENUM_FLAG); |
2084 | 576 | result->kind = the->stack->kind; |
2085 | 576 | result->value = the->stack->value; |
2086 | 576 | the->stack = result; |
2087 | | |
2088 | | // #ifdef mxDebug |
2089 | | // slot = the->frame->next; |
2090 | | // if (slot) { |
2091 | | // slot = slot - 1; |
2092 | | // if (slot->next) { |
2093 | | // property = fxNextSlotProperty(the, property, slot->next, XS_NO_ID, XS_DONT_ENUM_FLAG); |
2094 | | // property = fxNextIntegerProperty(the, property, slot->ID, XS_NO_ID, XS_DONT_ENUM_FLAG); |
2095 | | // } |
2096 | | // } |
2097 | | // #endif |
2098 | 576 | } |
2099 | | |
2100 | | txBoolean fxQueueModule(txMachine* the, txSlot* queue, txSlot* module) |
2101 | 433 | { |
2102 | 433 | txSlot** address = &(queue->next); |
2103 | 433 | txSlot* slot; |
2104 | 685 | while ((slot = *address)) { |
2105 | 291 | if (slot->value.reference == module->value.reference) |
2106 | 39 | return 0; |
2107 | 252 | address = &(slot->next); |
2108 | 252 | } |
2109 | 394 | slot = *address = fxNewSlot(the); |
2110 | 394 | slot->ID = mxModuleInternal(module)->value.module.id; //?? |
2111 | 394 | slot->kind = XS_REFERENCE_KIND; |
2112 | 394 | slot->value.reference = module->value.reference; |
2113 | 394 | return 1; |
2114 | 433 | } |
2115 | | |
2116 | | void fxResolveModule(txMachine* the, txSlot* module, txID moduleID, txScript* script, void* data, txDestructor destructor) |
2117 | 0 | { |
2118 | 0 | if (script->codeBuffer) { |
2119 | 0 | if (moduleID != XS_NO_ID) { |
2120 | 0 | txSlot* key = fxGetKey(the, moduleID); |
2121 | 0 | txSlot* meta = mxModuleMeta(module); |
2122 | 0 | txSlot* slot; |
2123 | 0 | if (mxIsNull(meta)) { |
2124 | 0 | txSlot* instance = fxNewInstance(the); |
2125 | 0 | meta->value.reference = instance; |
2126 | 0 | meta->kind = XS_REFERENCE_KIND; |
2127 | 0 | } |
2128 | 0 | slot = fxLastProperty(the, meta->value.reference); |
2129 | 0 | slot = slot->next = fxNewSlot(the); |
2130 | 0 | slot->value.string = key->value.key.string; |
2131 | 0 | if (key->kind == XS_KEY_KIND) |
2132 | 0 | slot->kind = XS_STRING_KIND; |
2133 | 0 | else |
2134 | 0 | slot->kind = XS_STRING_X_KIND; |
2135 | 0 | slot->ID = mxID(_uri); |
2136 | 0 | slot->flag |= XS_DONT_DELETE_FLAG | XS_DONT_SET_FLAG; |
2137 | 0 | } |
2138 | | // mxPushClosure(module); |
2139 | 0 | fxRunScript(the, script, module, C_NULL, C_NULL, C_NULL, module->value.reference); |
2140 | 0 | mxPop(); |
2141 | 0 | } |
2142 | 0 | } |
2143 | | |
2144 | | txID fxResolveSpecifier(txMachine* the, txSlot* realm, txID moduleID, txSlot* name) |
2145 | 6.71k | { |
2146 | 6.71k | if (moduleID == XS_NO_ID) { |
2147 | 6.60k | if (realm == mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm) { |
2148 | 6.33k | moduleID = fxFindModule(the, realm, XS_NO_ID, name); |
2149 | 6.33k | if (moduleID == XS_NO_ID) { |
2150 | 0 | fxToStringBuffer(the, name, the->nameBuffer, sizeof(the->nameBuffer)); |
2151 | 0 | mxReferenceError("module \"%s\" not found", the->nameBuffer); |
2152 | 0 | } |
2153 | 6.33k | } |
2154 | 266 | else { |
2155 | 266 | if (name->kind == XS_STRING_X_KIND) |
2156 | 0 | moduleID = fxNewNameX(the, name->value.string); |
2157 | 266 | else |
2158 | 266 | moduleID = fxNewName(the, name); |
2159 | 266 | } |
2160 | 6.60k | } |
2161 | 110 | else { |
2162 | 110 | txSlot* resolveHook = mxResolveHook(realm); |
2163 | 126 | while (mxIsUndefined(resolveHook)) { |
2164 | 31 | txSlot* parent = mxRealmParent(realm); |
2165 | 31 | if (mxIsReference(parent)) { |
2166 | 16 | realm = parent->value.reference; |
2167 | 16 | resolveHook = mxResolveHook(realm); |
2168 | 16 | } |
2169 | 15 | else |
2170 | 15 | break; |
2171 | 31 | } |
2172 | 110 | if (mxIsUndefined(resolveHook)) { |
2173 | 15 | mxCheck(the, realm == mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm); |
2174 | 15 | moduleID = fxFindModule(the, realm, moduleID, name); |
2175 | 15 | if (moduleID == XS_NO_ID) { |
2176 | 1 | fxToStringBuffer(the, name, the->nameBuffer, sizeof(the->nameBuffer)); |
2177 | 1 | mxReferenceError("module \"%s\" not found", the->nameBuffer); |
2178 | 1 | } |
2179 | 15 | } |
2180 | 95 | else { |
2181 | 95 | mxPushUndefined(); |
2182 | 95 | mxPushSlot(resolveHook); |
2183 | 95 | mxCall(); |
2184 | 95 | mxPushSlot(name); |
2185 | 95 | fxPushKeyString(the, moduleID, C_NULL); |
2186 | 95 | mxRunCount(2); |
2187 | 95 | moduleID = fxToID(the, the->stack); |
2188 | 95 | mxPop(); |
2189 | 95 | } |
2190 | 110 | } |
2191 | 6.70k | name->kind = XS_SYMBOL_KIND; |
2192 | 6.70k | name->value.symbol = moduleID; |
2193 | 6.70k | return moduleID; |
2194 | 6.71k | } |
2195 | | |
2196 | | void fxImport(txMachine* the) |
2197 | 0 | { |
2198 | 0 | txSlot* realm = mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm; |
2199 | 0 | fxToString(the, the->stack); |
2200 | 0 | mxPushUndefined(); |
2201 | 0 | fxRunImport(the, realm, C_NULL); |
2202 | 0 | } |
2203 | | |
2204 | | |
2205 | | void fxRunImport(txMachine* the, txSlot* realm, txSlot* referrer) |
2206 | 6.49k | { |
2207 | 6.49k | txSlot* stack = the->stack + 1; |
2208 | 6.49k | txSlot* promise; |
2209 | 6.49k | txSlot* fulfillFunction; |
2210 | 6.49k | txSlot* rejectFunction; |
2211 | 6.49k | txSlot* module; |
2212 | 6.49k | txID status; |
2213 | 6.49k | txSlot* slot; |
2214 | | |
2215 | 6.49k | fxBeginHost(the); |
2216 | 6.49k | mxPush(mxPromisePrototype); |
2217 | 6.49k | promise = fxNewPromiseInstance(the); |
2218 | 6.49k | mxPromiseStatus(promise)->value.integer = mxPendingStatus; |
2219 | 6.49k | fxPushPromiseFunctions(the, promise); |
2220 | 6.49k | fulfillFunction = the->stack + 1; |
2221 | 6.49k | rejectFunction = the->stack; |
2222 | 6.49k | { |
2223 | 6.49k | mxTry(the) { |
2224 | 6.49k | module = fxRunImportAux(the, realm, referrer, stack, stack - 1, 0); |
2225 | 6.49k | status = mxModuleStatus(module); |
2226 | 6.49k | if (status == XS_MODULE_STATUS_ERROR) { |
2227 | | /* THIS */ |
2228 | 6.27k | mxPushUndefined(); |
2229 | | /* FUNCTION */ |
2230 | 6.27k | mxPushSlot(rejectFunction); |
2231 | 6.27k | mxCall(); |
2232 | | /* ARGUMENTS */ |
2233 | 6.27k | mxPushSlot(mxModuleMeta(module)); |
2234 | 6.27k | mxRunCount(1); |
2235 | 6.27k | } |
2236 | 226 | else if (status == XS_MODULE_STATUS_EXECUTED) { |
2237 | | /* THIS */ |
2238 | 7 | mxPushUndefined(); |
2239 | | /* FUNCTION */ |
2240 | 7 | mxPushSlot(fulfillFunction); |
2241 | 7 | mxCall(); |
2242 | | /* ARGUMENTS */ |
2243 | 7 | mxPushSlot(module); |
2244 | 7 | mxRunCount(1); |
2245 | 7 | } |
2246 | 219 | else { |
2247 | 219 | txSlot* queue = mxModuleQueue.value.reference; |
2248 | 219 | slot = fxLastProperty(the, module->value.reference); |
2249 | 219 | slot = fxNextSlotProperty(the, slot, fulfillFunction, XS_NO_ID, XS_NO_FLAG); |
2250 | 219 | slot = fxNextSlotProperty(the, slot, rejectFunction, XS_NO_ID, XS_NO_FLAG); |
2251 | | // if ((status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADED)) { |
2252 | | // txSlot* queue = fxNewInstance(the); |
2253 | 219 | if (fxQueueModule(the, queue, module)) |
2254 | 217 | fxLoadModules(the, queue); |
2255 | | // } |
2256 | 219 | } |
2257 | 6.49k | } |
2258 | 6.49k | mxCatch(the) { |
2259 | 1 | fxRejectException(the, rejectFunction); |
2260 | 1 | } |
2261 | 6.49k | } |
2262 | 6.49k | fxEndHost(the); |
2263 | 6.49k | stack->value.reference = promise; |
2264 | 6.49k | stack->kind = XS_REFERENCE_KIND; |
2265 | 6.49k | the->stack = stack; |
2266 | 6.49k | } |
2267 | | |
2268 | | txSlot* fxRunImportAux(txMachine* the, txSlot* realm, txSlot* referrer, txSlot* specifier, txSlot* options, txBoolean now) |
2269 | 6.57k | { |
2270 | 6.57k | txSlot* module; |
2271 | 6.57k | txID moduleID; |
2272 | 6.57k | txFlag moduleFlag = fxCheckModuleOptions(the, options); |
2273 | 6.57k | #if mxModuleStuff |
2274 | 6.57k | if (mxIsReference(specifier)) { |
2275 | 4 | txSlot* internal = specifier->value.reference->next; |
2276 | 4 | if (internal && (internal->kind == XS_MODULE_STUFF_KIND)) { |
2277 | 0 | module = mxModuleStuffModule(specifier); |
2278 | 0 | if (mxIsNull(module)) { |
2279 | 0 | txSlot* source = mxModuleStuffSource(specifier); |
2280 | 0 | fxNewModule(the, realm, XS_NO_ID, XS_NO_FLAG, module); |
2281 | 0 | if (mxIsModuleSource(source->value.reference)) |
2282 | 0 | fxDuplicateModuleTransfers(the, source, module); |
2283 | 0 | else |
2284 | 0 | fxLoadVirtualModuleSource(the, source, module->value.reference); |
2285 | 0 | internal = mxModuleHook(module); |
2286 | 0 | internal->kind = specifier->kind; |
2287 | 0 | internal->value = specifier->value; |
2288 | 0 | mxModuleStatus(module) = XS_MODULE_STATUS_LOADED; |
2289 | 0 | } |
2290 | 0 | return module; |
2291 | 0 | } |
2292 | 4 | } |
2293 | 6.57k | #endif |
2294 | 6.57k | fxToString(the, specifier); |
2295 | 6.57k | if (referrer) { |
2296 | 6.32k | #if mxModuleStuff |
2297 | 6.32k | if (referrer->next->kind == XS_MODULE_KIND) { |
2298 | 0 | txSlot* reference = mxModuleInstanceHook(referrer); |
2299 | 0 | if (mxIsReference(reference)) { |
2300 | 0 | txSlot* handler = mxModuleStuffHandler(reference); |
2301 | 0 | txSlot* importHook = (now) ? mxModuleStuffImportNowHook(reference) : mxModuleStuffImportHook(reference); |
2302 | 0 | if (mxIsReference(handler) && mxIsReference(importHook)) { |
2303 | 0 | module = fxImportModuleStuff(the, realm, mxModuleQueue.value.reference, reference, specifier, now); |
2304 | 0 | return module; |
2305 | 0 | } |
2306 | 0 | } |
2307 | 0 | } |
2308 | 6.32k | #endif |
2309 | 6.32k | moduleID = fxResolveSpecifier(the, realm, mxModuleInstanceInternal(referrer)->value.module.id, specifier); |
2310 | 6.32k | } |
2311 | 244 | else |
2312 | 244 | moduleID = fxResolveSpecifier(the, realm, XS_NO_ID, specifier); |
2313 | 6.57k | module = fxGetModule(the, realm, moduleID, moduleFlag); |
2314 | 6.57k | if (!module) { |
2315 | 280 | module = mxBehaviorSetProperty(the, mxOwnModules(realm)->value.reference, moduleID, 0, XS_OWN); |
2316 | 280 | fxNewModule(the, realm, moduleID, moduleFlag, module); |
2317 | 280 | } |
2318 | 6.57k | return module; |
2319 | 6.57k | } |
2320 | | |
2321 | | void fxRunImportFulfilled(txMachine* the, txSlot* module, txSlot* with) |
2322 | 60 | { |
2323 | 60 | if (mxModuleInstanceMeta(module)->next) { |
2324 | 60 | txSlot* stack = the->stack; |
2325 | 60 | txSlot* slot = mxModuleInstanceFulfill(module); |
2326 | 99 | while (slot) { |
2327 | 39 | mxPushSlot(slot); |
2328 | 39 | slot = slot->next; |
2329 | 39 | slot = slot->next; |
2330 | 39 | } |
2331 | 60 | mxModuleInstanceMeta(module)->next = C_NULL; |
2332 | 60 | slot = stack; |
2333 | 99 | while (slot > the->stack) { |
2334 | 39 | slot--; |
2335 | | /* THIS */ |
2336 | 39 | mxPushUndefined(); |
2337 | | /* FUNCTION */ |
2338 | 39 | mxPushSlot(slot); |
2339 | 39 | mxCall(); |
2340 | | /* ARGUMENTS */ |
2341 | 39 | mxPushReference(with); |
2342 | 39 | mxRunCount(1); |
2343 | 39 | mxPop(); |
2344 | 39 | } |
2345 | 60 | the->stack = stack; |
2346 | 60 | } |
2347 | 60 | } |
2348 | | |
2349 | | void fxRunImportRejected(txMachine* the, txSlot* module, txSlot* with) |
2350 | 220 | { |
2351 | 220 | if (mxModuleInstanceMeta(module)->next) { |
2352 | 220 | txSlot* stack = the->stack; |
2353 | 220 | txSlot* slot = mxModuleInstanceFulfill(module); |
2354 | 220 | txSlot* exception; |
2355 | 374 | while (slot) { |
2356 | 154 | slot = slot->next; |
2357 | 154 | mxPushSlot(slot); |
2358 | 154 | slot = slot->next; |
2359 | 154 | } |
2360 | 220 | mxModuleInstanceMeta(module)->next = C_NULL; |
2361 | 220 | exception = mxModuleInstanceMeta(with); |
2362 | 220 | slot = stack; |
2363 | 374 | while (slot > the->stack) { |
2364 | 154 | slot--; |
2365 | | /* THIS */ |
2366 | 154 | mxPushUndefined(); |
2367 | | /* FUNCTION */ |
2368 | 154 | mxPushSlot(slot); |
2369 | 154 | mxCall(); |
2370 | | /* ARGUMENTS */ |
2371 | 154 | mxPushSlot(exception); |
2372 | 154 | mxRunCount(1); |
2373 | 154 | mxPop(); |
2374 | 154 | } |
2375 | 220 | the->stack = stack; |
2376 | 220 | } |
2377 | 220 | } |
2378 | | |
2379 | | /* META */ |
2380 | | |
2381 | | void fxRunImportMeta(txMachine* the, txSlot* module) |
2382 | 44 | { |
2383 | 44 | txSlot* meta = mxModuleInstanceMeta(module); |
2384 | 44 | if (mxIsNull(meta)) { |
2385 | 0 | fxNewInstance(the); |
2386 | 0 | mxPullSlot(meta); |
2387 | 0 | #if mxModuleStuff |
2388 | 0 | { |
2389 | 0 | txSlot* reference = mxModuleInstanceHook(module); |
2390 | 0 | if (mxIsReference(reference)) { |
2391 | 0 | txSlot* handler = mxModuleStuffHandler(reference); |
2392 | 0 | txSlot* importMetaHook = mxModuleStuffImportMetaHook(reference); |
2393 | 0 | if (mxIsReference(handler) && mxIsReference(importMetaHook)) { |
2394 | 0 | fxBeginHost(the); |
2395 | 0 | mxPushSlot(handler); |
2396 | 0 | mxPushSlot(importMetaHook); |
2397 | 0 | mxCall(); |
2398 | 0 | mxPushSlot(meta); |
2399 | 0 | mxRunCount(1); |
2400 | 0 | mxPop(); |
2401 | 0 | fxEndHost(the); |
2402 | 0 | } |
2403 | 0 | } |
2404 | 0 | } |
2405 | 0 | #endif |
2406 | 0 | meta->value.reference->flag |= XS_DONT_PATCH_FLAG; |
2407 | 0 | } |
2408 | 44 | mxPushSlot(meta); |
2409 | 44 | } |
2410 | | |
2411 | | /* NOW */ |
2412 | | |
2413 | | void fxAwaitImport(txMachine* the, txBoolean defaultFlag) |
2414 | 0 | { |
2415 | 0 | txSlot* stack = the->stack; |
2416 | 0 | txSlot* realm = mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm; |
2417 | 0 | txID defaultID; |
2418 | 0 | txSlot* export; |
2419 | 0 | mxTry(the) { |
2420 | 0 | fxToString(the, stack); |
2421 | 0 | if (defaultFlag & XS_IMPORT_PREFLIGHT) { |
2422 | 0 | txID moduleID = fxFindModule(the, realm, XS_NO_ID, stack); |
2423 | 0 | stack->kind = XS_BOOLEAN_KIND; |
2424 | 0 | stack->value.boolean = moduleID != XS_NO_ID; |
2425 | 0 | } |
2426 | 0 | else { |
2427 | 0 | mxPushUndefined(); |
2428 | 0 | if (defaultFlag & XS_IMPORT_ASYNC) { |
2429 | 0 | gxDefaults.runImport(the, realm, C_NULL); |
2430 | 0 | } |
2431 | 0 | else { |
2432 | 0 | fxRunImportNow(the, realm, C_NULL); |
2433 | 0 | if (defaultFlag & XS_IMPORT_DEFAULT) { |
2434 | 0 | defaultID = mxID(_default); |
2435 | 0 | export = mxModuleExports(stack)->value.reference->next; |
2436 | 0 | while (export) { |
2437 | 0 | mxCheck(the, export->kind == XS_EXPORT_KIND); |
2438 | 0 | if (export->ID == defaultID) { |
2439 | 0 | stack->kind = export->value.export.closure->kind; |
2440 | 0 | stack->value = export->value.export.closure->value; |
2441 | 0 | break; |
2442 | 0 | } |
2443 | 0 | export = export->next; |
2444 | 0 | } |
2445 | 0 | } |
2446 | 0 | } |
2447 | 0 | } |
2448 | 0 | } |
2449 | 0 | mxCatch(the) { |
2450 | 0 | fxJump(the); |
2451 | 0 | } |
2452 | 0 | the->stack = stack; |
2453 | 0 | } |
2454 | | |
2455 | | void fxImportNow(txMachine* the) |
2456 | 0 | { |
2457 | 0 | txSlot* realm = mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm; |
2458 | 0 | fxToString(the, the->stack); |
2459 | 0 | mxPushUndefined(); |
2460 | 0 | fxRunImportNow(the, realm, C_NULL); |
2461 | 0 | } |
2462 | | |
2463 | | void fxRunImportNow(txMachine* the, txSlot* realm, txSlot* referrer) |
2464 | 74 | { |
2465 | 74 | txSlot* stack = the->stack + 1; |
2466 | 74 | txSlot* module = fxRunImportAux(the, realm, referrer, stack, stack - 1, 1); |
2467 | 74 | txID status = mxModuleStatus(module); |
2468 | 74 | if ((status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADED)) { |
2469 | 63 | txSlot* result = stack; |
2470 | 63 | txSlot* queue = fxNewInstance(the); |
2471 | 63 | mxTry(the) { |
2472 | 63 | txBoolean done = 1; |
2473 | 63 | result->kind = module->kind; |
2474 | 63 | result->value = module->value; |
2475 | | |
2476 | 63 | fxQueueModule(the, queue, module); |
2477 | | // slot = mxBehaviorSetProperty(the, queue, moduleID, 0, XS_OWN);; |
2478 | | // slot->flag |= XS_BASE_FLAG; |
2479 | | // slot->kind = XS_REFERENCE_KIND; |
2480 | | // slot->value.reference = module->value.reference; |
2481 | | |
2482 | 63 | mxReportModuleQueue("LOAD"); |
2483 | 63 | module = queue->next; |
2484 | 240 | while (module) { |
2485 | 202 | if (mxModuleStatus(module) == XS_MODULE_STATUS_NEW) { |
2486 | 93 | txSlot* loader = mxModuleLoader(module); |
2487 | 93 | txID moduleID = loader->value.module.id; |
2488 | 93 | txSlot* realm = loader->value.module.realm; |
2489 | 93 | if (!fxMapModule(the, realm, moduleID, module, queue, result)) { |
2490 | 50 | txSlot* loadNowHook = mxLoadNowHook(realm); |
2491 | 50 | if (mxIsUndefined(loadNowHook)) { |
2492 | 25 | if (realm != mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm) |
2493 | 20 | mxTypeError("no loadNowHook"); |
2494 | 5 | fxLoadModule(the, module, moduleID); |
2495 | 5 | if (mxModuleExecute(module)->kind == XS_NULL_KIND) |
2496 | 5 | mxTypeError("no module"); |
2497 | 0 | mxModuleStatus(module) = XS_MODULE_STATUS_LOADED; |
2498 | 0 | } |
2499 | 25 | else { |
2500 | 25 | txSlot* descriptor; |
2501 | 25 | done = 0; |
2502 | 25 | mxModuleStatus(module) = XS_MODULE_STATUS_LOADING; |
2503 | 25 | mxPushUndefined(); |
2504 | 25 | mxPushSlot(loadNowHook); |
2505 | 25 | mxCall(); |
2506 | 25 | fxPushKeyString(the, moduleID, C_NULL); |
2507 | 25 | fxPushModuleOptions(the, loader->flag); |
2508 | 25 | mxRunCount(2); |
2509 | 25 | descriptor = the->stack; |
2510 | 25 | fxMapModuleDescriptor(the, realm, moduleID, module, queue, result, descriptor); |
2511 | 25 | mxPop(); // descriptor |
2512 | 25 | } |
2513 | 50 | } |
2514 | 68 | module = queue; |
2515 | 68 | done = 1; |
2516 | 68 | mxReportModuleQueue("LOAD"); |
2517 | 68 | } |
2518 | 109 | else if (mxModuleStatus(module) == XS_MODULE_STATUS_LOADING) { |
2519 | 1 | done = 0; |
2520 | 1 | } |
2521 | 108 | else if (mxModuleStatus(module) == XS_MODULE_STATUS_LOADED) { |
2522 | 41 | #if mxModuleStuff |
2523 | 41 | if (!fxLoadModuleStuffFrom(the, queue, module->value.reference, 1)) |
2524 | 41 | #endif |
2525 | 41 | fxLoadModulesFrom(the, queue, module->value.reference, 1); |
2526 | 41 | mxModuleStatus(module) = XS_MODULE_STATUS_LINKING; |
2527 | 41 | module = queue; |
2528 | 41 | done = 1; |
2529 | 41 | } |
2530 | 177 | module = module->next; |
2531 | 177 | } |
2532 | 38 | if (!done) |
2533 | 1 | mxTypeError("async queue"); |
2534 | 37 | fxLinkModules(the, queue); |
2535 | 37 | mxReportModuleQueue("INIT"); |
2536 | 37 | module = queue->next; |
2537 | 70 | while (module) { |
2538 | 33 | if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKED) { |
2539 | 33 | mxModuleStatus(module) = XS_MODULE_STATUS_EXECUTING; |
2540 | 33 | if (mxModuleExecute(module)->value.reference->value.instance.prototype == mxAsyncFunctionPrototype.value.reference) |
2541 | 0 | mxTypeError("async module"); |
2542 | 33 | mxPushSlot(mxModuleHosts(module)); |
2543 | 33 | mxPull(mxHosts); |
2544 | 33 | mxPushUndefined(); |
2545 | 33 | mxPushSlot(mxModuleExecute(module)); |
2546 | 33 | mxCall(); |
2547 | 33 | mxRunCount(0); |
2548 | 33 | mxPop(); |
2549 | 33 | fxCompleteModule(the, module->value.reference, C_NULL); |
2550 | 33 | mxModuleMeta(module)->next = C_NULL; |
2551 | 33 | mxPushUndefined(); |
2552 | 33 | mxPull(mxHosts); |
2553 | 33 | mxReportModuleQueue("INIT"); |
2554 | 33 | } |
2555 | 33 | module = module->next; |
2556 | 33 | } |
2557 | 37 | mxPop(); |
2558 | 37 | } |
2559 | 38 | mxCatch(the) { |
2560 | 38 | module = queue->next; |
2561 | 79 | while (module) { |
2562 | 41 | if (mxModuleStatus(module) < XS_MODULE_STATUS_EXECUTED) { |
2563 | 41 | fxCompleteModule(the, module->value.reference, &mxException); |
2564 | 41 | mxModuleMeta(module)->next = C_NULL; |
2565 | 41 | } |
2566 | 41 | module = module->next; |
2567 | 41 | } |
2568 | 38 | mxPushUndefined(); |
2569 | 38 | mxPull(mxHosts); |
2570 | 38 | fxJump(the); |
2571 | 38 | } |
2572 | 63 | } |
2573 | 11 | else if (status == XS_MODULE_STATUS_EXECUTED) { |
2574 | 8 | stack->kind = module->kind; |
2575 | 8 | stack->value = module->value; |
2576 | 8 | } |
2577 | 3 | else if (status == XS_MODULE_STATUS_ERROR) { |
2578 | 3 | mxPushSlot(mxModuleMeta(module)); |
2579 | 3 | mxPull(mxException); |
2580 | 3 | fxJump(the); |
2581 | 3 | } |
2582 | 0 | else { |
2583 | 0 | mxTypeError("async module"); |
2584 | 0 | } |
2585 | 7 | the->stack = stack; |
2586 | 7 | } |
2587 | | |
2588 | | /* BEHAVIOR */ |
2589 | | |
2590 | 1 | void fxModuleGetter(txMachine* the) { |
2591 | 1 | mxReferenceError("not initialized yet"); |
2592 | 1 | } |
2593 | | |
2594 | | txBoolean fxModuleDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot, txFlag mask) |
2595 | 0 | { |
2596 | 0 | txSlot* property = fxModuleFindProperty(the, instance, id, index); |
2597 | 0 | if (property) { |
2598 | 0 | if ((mask & XS_DONT_DELETE_FLAG) && !(slot->flag & XS_DONT_DELETE_FLAG)) |
2599 | 0 | return 0; |
2600 | 0 | if ((mask & XS_DONT_ENUM_FLAG) && ((property->flag & XS_DONT_ENUM_FLAG) != (slot->flag & XS_DONT_ENUM_FLAG))) |
2601 | 0 | return 0; |
2602 | 0 | if (mask & XS_ACCESSOR_FLAG) { |
2603 | 0 | if (property->kind != XS_ACCESSOR_KIND) |
2604 | 0 | return 0; |
2605 | 0 | if (mask & XS_GETTER_FLAG) { |
2606 | 0 | if (property->value.accessor.getter != slot->value.accessor.getter) |
2607 | 0 | return 0; |
2608 | 0 | } |
2609 | 0 | if (mask & XS_SETTER_FLAG) { |
2610 | 0 | if (property->value.accessor.setter != slot->value.accessor.setter) |
2611 | 0 | return 0; |
2612 | 0 | } |
2613 | 0 | return 1; |
2614 | 0 | } |
2615 | 0 | if ((mask & XS_DONT_SET_FLAG) && ((property->flag & XS_DONT_SET_FLAG) != (slot->flag & XS_DONT_SET_FLAG))) |
2616 | 0 | return 0; |
2617 | 0 | if (property->kind == XS_ACCESSOR_KIND) |
2618 | 0 | return 0; |
2619 | 0 | if ((slot->kind != XS_UNINITIALIZED_KIND) && !fxIsSameValue(the, property, slot, 0)) |
2620 | 0 | return 0; |
2621 | 0 | return 1; |
2622 | 0 | } |
2623 | 0 | return 0; |
2624 | 0 | } |
2625 | | |
2626 | | txBoolean fxModuleDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index) |
2627 | 0 | { |
2628 | 0 | if (id == XS_NO_ID) |
2629 | 0 | return 1; |
2630 | 0 | if (fxIsKeySymbol(the, id)) { |
2631 | 0 | return (id == mxID(_Symbol_toStringTag)) ? 0 : 1; |
2632 | 0 | } |
2633 | | // if (mxModuleInstanceStatus(instance) < XS_MODULE_STATUS_LINKED) { |
2634 | | // mxReferenceError("module not initialized yet"); |
2635 | | // } |
2636 | | // else |
2637 | 0 | { |
2638 | 0 | txSlot* exports = mxModuleInstanceExports(instance); |
2639 | 0 | if (mxIsReference(exports)) { |
2640 | 0 | txSlot* property = exports->value.reference->next; |
2641 | 0 | while (property) { |
2642 | 0 | if (property->ID == id) |
2643 | 0 | return 0; |
2644 | 0 | property = property->next; |
2645 | 0 | } |
2646 | 0 | } |
2647 | 0 | } |
2648 | 0 | return 1; |
2649 | 0 | } |
2650 | | |
2651 | | txSlot* fxModuleFindProperty(txMachine* the, txSlot* instance, txID id, txIndex index) |
2652 | 0 | { |
2653 | 0 | if (id == XS_NO_ID) |
2654 | 0 | return C_NULL; |
2655 | 0 | if (fxIsKeySymbol(the, id)) { |
2656 | 0 | if (id == mxID(_Symbol_toStringTag)) |
2657 | 0 | return mxModulePrototype.value.reference->next; |
2658 | 0 | } |
2659 | | // if (mxModuleInstanceStatus(instance) < XS_MODULE_STATUS_LINKED) { |
2660 | | // mxReferenceError("module not initialized yet"); |
2661 | | // } |
2662 | | // else |
2663 | 0 | { |
2664 | 0 | txSlot* exports = mxModuleInstanceExports(instance); |
2665 | 0 | if (mxIsReference(exports)) { |
2666 | 0 | txSlot* property = exports->value.reference->next; |
2667 | 0 | while (property) { |
2668 | 0 | if (property->ID == id) { |
2669 | 0 | property = property->value.export.closure; |
2670 | 0 | if (property && (property->kind == XS_UNINITIALIZED_KIND)) { |
2671 | 0 | fxIDToString(the, id, the->nameBuffer, sizeof(the->nameBuffer)); |
2672 | 0 | mxReferenceError("get %s: not initialized yet", the->nameBuffer); |
2673 | 0 | } |
2674 | 0 | return property; |
2675 | 0 | } |
2676 | 0 | property = property->next; |
2677 | 0 | } |
2678 | 0 | } |
2679 | 0 | } |
2680 | 0 | return C_NULL; |
2681 | 0 | } |
2682 | | |
2683 | | txBoolean fxModuleGetOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot) |
2684 | 0 | { |
2685 | 0 | txSlot* property = fxModuleFindProperty(the, instance, id, index); |
2686 | 0 | if (property) { |
2687 | 0 | slot->flag = (id == mxID(_Symbol_toStringTag)) ? property->flag : XS_DONT_DELETE_FLAG; |
2688 | 0 | slot->kind = property->kind; |
2689 | 0 | slot->value = property->value; |
2690 | 0 | return 1; |
2691 | 0 | } |
2692 | 0 | slot->flag = XS_NO_FLAG; |
2693 | 0 | slot->kind = XS_UNDEFINED_KIND; |
2694 | 0 | return 0; |
2695 | 0 | } |
2696 | | |
2697 | | txSlot* fxModuleGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag) |
2698 | 83 | { |
2699 | 83 | if (id == XS_NO_ID) |
2700 | 0 | return C_NULL; |
2701 | 83 | if (fxIsKeySymbol(the, id)) { |
2702 | 0 | if (id == mxID(_Symbol_toStringTag)) |
2703 | 0 | return mxModulePrototype.value.reference->next; |
2704 | 0 | } |
2705 | | // if (mxModuleInstanceStatus(instance) < XS_MODULE_STATUS_LINKED) { |
2706 | | // return &mxModuleAccessor; |
2707 | | // } |
2708 | | // else |
2709 | 83 | { |
2710 | 83 | txSlot* exports = mxModuleInstanceExports(instance); |
2711 | 83 | if (mxIsReference(exports)) { |
2712 | 83 | txSlot* property = exports->value.reference->next; |
2713 | 210 | while (property) { |
2714 | 153 | if (property->ID == id) { |
2715 | 26 | property = property->value.export.closure; |
2716 | 26 | if (property && (property->kind == XS_UNINITIALIZED_KIND)) { |
2717 | 1 | return &mxModuleAccessor; |
2718 | 1 | } |
2719 | 25 | return property; |
2720 | 26 | } |
2721 | 127 | property = property->next; |
2722 | 127 | } |
2723 | 83 | } |
2724 | 83 | } |
2725 | 57 | return C_NULL; |
2726 | 83 | } |
2727 | | |
2728 | | txBoolean fxModuleGetPropertyValue(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* receiver, txSlot* value) |
2729 | 0 | { |
2730 | 0 | txSlot* property = fxModuleFindProperty(the, instance, id, index); |
2731 | 0 | if (property) { |
2732 | 0 | value->kind = property->kind; |
2733 | 0 | value->value = property->value; |
2734 | 0 | return 1; |
2735 | 0 | } |
2736 | 0 | value->kind = XS_UNDEFINED_KIND; |
2737 | 0 | return 0; |
2738 | 0 | } |
2739 | | |
2740 | | txBoolean fxModuleGetPrototype(txMachine* the, txSlot* instance, txSlot* result) |
2741 | 0 | { |
2742 | 0 | result->kind = XS_NULL_KIND; |
2743 | 0 | return 0; |
2744 | 0 | } |
2745 | | |
2746 | | txBoolean fxModuleHasProperty(txMachine* the, txSlot* instance, txID id, txIndex index) |
2747 | 0 | { |
2748 | 0 | if (id == XS_NO_ID) |
2749 | 0 | return 0; |
2750 | 0 | if (fxIsKeySymbol(the, id)) { |
2751 | 0 | return (id == mxID(_Symbol_toStringTag)) ? 1 : 0; |
2752 | 0 | } |
2753 | | // if (mxModuleInstanceStatus(instance) < XS_MODULE_STATUS_LINKED) { |
2754 | | // mxReferenceError("module not initialized yet"); |
2755 | | // } |
2756 | | // else |
2757 | 0 | { |
2758 | 0 | txSlot* exports = mxModuleInstanceExports(instance); |
2759 | 0 | if (mxIsReference(exports)) { |
2760 | 0 | txSlot* property = exports->value.reference->next; |
2761 | 0 | while (property) { |
2762 | 0 | if (property->ID == id) { |
2763 | 0 | property = property->value.export.closure; |
2764 | 0 | return property ? 1 : 0; |
2765 | 0 | } |
2766 | 0 | property = property->next; |
2767 | 0 | } |
2768 | 0 | } |
2769 | 0 | } |
2770 | 0 | return 0; |
2771 | 0 | } |
2772 | | |
2773 | | txBoolean fxModuleIsExtensible(txMachine* the, txSlot* instance) |
2774 | 0 | { |
2775 | 0 | return 0; |
2776 | 0 | } |
2777 | | |
2778 | | void fxModuleOwnKeys(txMachine* the, txSlot* instance, txFlag flag, txSlot* keys) |
2779 | 0 | { |
2780 | 0 | if (flag & XS_EACH_NAME_FLAG) { |
2781 | | // if (mxModuleInstanceStatus(instance) < XS_MODULE_STATUS_LINKED) { |
2782 | | // mxReferenceError("module not initialized yet"); |
2783 | | // } |
2784 | | // else |
2785 | 0 | { |
2786 | 0 | txSlot* exports = mxModuleInstanceExports(instance); |
2787 | 0 | if (mxIsReference(exports)) { |
2788 | 0 | txSlot* property = exports->value.reference->next; |
2789 | 0 | txSlot* stack = the->stack; |
2790 | 0 | while (property) { |
2791 | 0 | if (property->value.export.closure) { |
2792 | 0 | txSlot* key = fxGetKey(the, property->ID); |
2793 | 0 | mxPushSlot(key); |
2794 | 0 | the->stack->ID = key->ID; |
2795 | 0 | } |
2796 | 0 | property = property->next; |
2797 | 0 | } |
2798 | 0 | c_qsort(the->stack, stack - the->stack, sizeof(txSlot), fxModuleOwnKeysCompare); |
2799 | 0 | while (the->stack < stack) { |
2800 | 0 | keys = fxQueueKey(the, the->stack->ID, 0, keys); |
2801 | 0 | mxPop(); |
2802 | 0 | } |
2803 | 0 | } |
2804 | 0 | } |
2805 | 0 | } |
2806 | 0 | if (flag & XS_EACH_SYMBOL_FLAG) { |
2807 | 0 | txSlot* property = mxModulePrototype.value.reference->next; |
2808 | 0 | keys = fxQueueKey(the, property->ID, 0, keys); |
2809 | 0 | } |
2810 | 0 | } |
2811 | | |
2812 | | int fxModuleOwnKeysCompare(const void* p, const void* q) |
2813 | 0 | { |
2814 | 0 | return c_strcmp(((txSlot*)p)->value.key.string, ((txSlot*)q)->value.key.string); |
2815 | 0 | } |
2816 | | |
2817 | | txBoolean fxModulePreventExtensions(txMachine* the, txSlot* instance) |
2818 | 0 | { |
2819 | 0 | return 1; |
2820 | 0 | } |
2821 | | |
2822 | | txSlot* fxModuleSetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag) |
2823 | 1 | { |
2824 | 1 | return C_NULL; |
2825 | 1 | } |
2826 | | |
2827 | | txBoolean fxModuleSetPropertyValue(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* value, txSlot* receiver) |
2828 | 0 | { |
2829 | 0 | return 0; |
2830 | 0 | } |
2831 | | |
2832 | | txBoolean fxModuleSetPrototype(txMachine* the, txSlot* instance, txSlot* prototype) |
2833 | 0 | { |
2834 | 0 | return (prototype->kind == XS_NULL_KIND) ? 1 : 0; |
2835 | 0 | } |
2836 | | |
2837 | | /* COMPARTMENT */ |
2838 | | |
2839 | | txSlot* fxCheckCompartmentInstance(txMachine* the, txSlot* slot) |
2840 | 319 | { |
2841 | 319 | if (slot->kind == XS_REFERENCE_KIND) { |
2842 | 319 | txSlot* instance = slot->value.reference; |
2843 | 319 | if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_PROGRAM_KIND)) { |
2844 | 319 | return instance; |
2845 | 319 | } |
2846 | 319 | } |
2847 | 319 | mxTypeError("this: not a Compartment instance"); |
2848 | 0 | return C_NULL; |
2849 | 319 | } |
2850 | | |
2851 | | void fxPrepareCompartmentFunction(txMachine* the, txSlot* program, txSlot* instance) |
2852 | 2.03k | { |
2853 | 2.03k | txSlot* property = mxFunctionInstanceHome(instance); |
2854 | 2.03k | property->value.home.module = program; |
2855 | 2.03k | if (mxCompartmentGlobal.kind != XS_UNDEFINED_KIND) { |
2856 | 0 | instance->flag |= XS_DONT_PATCH_FLAG; |
2857 | 0 | property = property->next; |
2858 | 0 | while (property) { |
2859 | 0 | if (!(property->flag & XS_INTERNAL_FLAG)) |
2860 | 0 | property->flag |= XS_DONT_DELETE_FLAG | XS_DONT_SET_FLAG; |
2861 | 0 | property = property->next; |
2862 | 0 | } |
2863 | 0 | } |
2864 | 2.03k | } |
2865 | | |
2866 | | void fx_Compartment(txMachine* the) |
2867 | 509 | { |
2868 | 509 | txSlot* module = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.module; |
2869 | 509 | txSlot* program = C_NULL; |
2870 | 509 | txSlot* parent; |
2871 | 509 | txSlot* realm; |
2872 | 509 | txSlot* global = C_NULL; |
2873 | 509 | txSlot* closures = C_NULL; |
2874 | 509 | txSlot* slot; |
2875 | 509 | txSlot* target; |
2876 | 509 | txSlot* own; |
2877 | 509 | txInteger id; |
2878 | | |
2879 | 509 | if (!module) module = mxProgram.value.reference; |
2880 | 509 | mxTry(the) { |
2881 | 509 | if (mxIsUndefined(mxTarget)) |
2882 | 1 | mxTypeError("call: Compartment"); |
2883 | | |
2884 | 508 | mxPushSlot(mxTarget); |
2885 | 508 | fxGetPrototypeFromConstructor(the, &mxCompartmentPrototype); |
2886 | 508 | program = fxNewProgramInstance(the); |
2887 | 508 | mxPullSlot(mxResult); |
2888 | | |
2889 | | // PARENT |
2890 | 508 | parent = mxModuleInstanceInternal(module)->value.module.realm; |
2891 | 508 | mxPushReference(parent); |
2892 | | |
2893 | | // GLOBALS |
2894 | 508 | if (the->sharedMachine == C_NULL) { |
2895 | 508 | txSlot* instance; |
2896 | 508 | txSlot* property; |
2897 | 508 | txSlot* callback; |
2898 | 508 | mxPush(mxObjectPrototype); |
2899 | | #ifdef mxLink |
2900 | | global = fxNewObjectInstance(the); |
2901 | | #else |
2902 | 508 | global = fxNewGlobalInstance(the); |
2903 | 508 | #endif |
2904 | 508 | slot = fxLastProperty(the, global); |
2905 | 508 | if (mxCompartmentGlobal.kind == XS_UNDEFINED_KIND) { |
2906 | 31.4k | for (id = XS_SYMBOL_ID_COUNT; id < _Infinity; id++) |
2907 | 30.9k | slot = fxNextSlotProperty(the, slot, &the->stackIntrinsics[-1 - id], mxID(id), XS_DONT_ENUM_FLAG); |
2908 | 2.03k | for (; id < _Compartment; id++) |
2909 | 1.52k | slot = fxNextSlotProperty(the, slot, &the->stackIntrinsics[-1 - id], mxID(id), XS_GET_ONLY); |
2910 | 508 | } |
2911 | 0 | else { |
2912 | 0 | txSlot* item = mxCompartmentGlobal.value.reference->next; |
2913 | 0 | for (id = XS_SYMBOL_ID_COUNT; id < _Infinity; id++) { |
2914 | 0 | mxPushSlot(item->value.array.address + id); |
2915 | 0 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(id), XS_DONT_ENUM_FLAG); |
2916 | 0 | mxPop(); |
2917 | 0 | } |
2918 | 0 | for (; id < _Compartment; id++) { |
2919 | 0 | mxPushSlot(item->value.array.address + id); |
2920 | 0 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(id), XS_GET_ONLY); |
2921 | 0 | mxPop(); |
2922 | 0 | } |
2923 | 0 | } |
2924 | | |
2925 | 508 | callback = mxFunctionInstanceCode(mxCompartmentConstructor.value.reference); |
2926 | 508 | instance = fxBuildHostFunction(the, callback->value.callback.address, 1, mxID(_Compartment)); |
2927 | 508 | instance->flag |= XS_CAN_CONSTRUCT_FLAG; |
2928 | 508 | property = fxLastProperty(the, instance); |
2929 | 508 | fxNextSlotProperty(the, property, &mxCompartmentPrototype, mxID(_prototype), XS_GET_ONLY); |
2930 | 508 | fxPrepareCompartmentFunction(the, program, instance); |
2931 | 508 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_Compartment), XS_DONT_ENUM_FLAG); |
2932 | 508 | mxPop(); |
2933 | | |
2934 | 508 | callback = mxFunctionInstanceCode(mxFunctionConstructor.value.reference); |
2935 | 508 | instance = fxBuildHostFunction(the, callback->value.callback.address, 1, mxID(_Function)); |
2936 | 508 | instance->flag |= XS_CAN_CONSTRUCT_FLAG; |
2937 | 508 | property = fxLastProperty(the, instance); |
2938 | 508 | fxNextSlotProperty(the, property, &mxFunctionPrototype, mxID(_prototype), XS_GET_ONLY); |
2939 | 508 | fxPrepareCompartmentFunction(the, program, instance); |
2940 | 508 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_Function), XS_DONT_ENUM_FLAG); |
2941 | 508 | mxPop(); |
2942 | | |
2943 | 508 | #if mxModuleStuff |
2944 | 508 | callback = mxFunctionInstanceCode(mxModuleStuffConstructor.value.reference); |
2945 | 508 | instance = fxBuildHostFunction(the, callback->value.callback.address, 1, mxID(_ModuleStuff)); |
2946 | 508 | instance->flag |= XS_CAN_CONSTRUCT_FLAG; |
2947 | 508 | property = fxLastProperty(the, instance); |
2948 | 508 | fxNextSlotProperty(the, property, &mxModuleStuffPrototype, mxID(_prototype), XS_GET_ONLY); |
2949 | 508 | fxPrepareCompartmentFunction(the, program, instance); |
2950 | 508 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_ModuleStuff), XS_DONT_ENUM_FLAG); |
2951 | 508 | mxPop(); |
2952 | 508 | #endif |
2953 | | |
2954 | 508 | callback = mxFunctionInstanceCode(mxEvalFunction.value.reference); |
2955 | 508 | instance = fxBuildHostFunction(the, callback->value.callback.address, 1, mxID(_eval)); |
2956 | 508 | fxPrepareCompartmentFunction(the, program, instance); |
2957 | 508 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_eval), XS_DONT_ENUM_FLAG); |
2958 | 508 | mxPop(); |
2959 | 508 | } |
2960 | 0 | else { |
2961 | 0 | mxPush(mxCompartmentGlobal); |
2962 | 0 | global = fxNewObjectInstance(the); |
2963 | 0 | slot = fxLastProperty(the, global); |
2964 | 0 | id = _Compartment; |
2965 | 0 | for (; id < XS_INTRINSICS_COUNT; id++) { |
2966 | 0 | txSlot* instance = fxDuplicateInstance(the, the->stackIntrinsics[-1 - id].value.reference); |
2967 | 0 | mxFunctionInstanceHome(instance)->value.home.module = program; |
2968 | 0 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(id), XS_DONT_ENUM_FLAG); |
2969 | 0 | mxPop(); |
2970 | 0 | } |
2971 | 0 | } |
2972 | 508 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_global), XS_DONT_ENUM_FLAG); |
2973 | 508 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_globalThis), XS_DONT_ENUM_FLAG); |
2974 | | |
2975 | 508 | if (mxArgc > 0) { |
2976 | 477 | if (!mxIsReference(mxArgv(0))) |
2977 | 32 | mxTypeError("options: not an object"); |
2978 | | |
2979 | 445 | mxPushSlot(mxArgv(0)); |
2980 | 445 | if (mxHasID(fxID(the, "globals"))) { |
2981 | 25 | mxPushSlot(mxArgv(0)); |
2982 | 25 | mxGetID(fxID(the, "globals")); |
2983 | 25 | slot = the->stack; |
2984 | 25 | if (!mxIsReference(slot)) |
2985 | 10 | mxTypeError("options.globals: not an object"); |
2986 | 15 | mxPushUndefined(); |
2987 | 15 | mxPush(mxAssignObjectFunction); |
2988 | 15 | mxCall(); |
2989 | 15 | mxPushReference(global); |
2990 | 15 | mxPushSlot(slot); |
2991 | 15 | mxRunCount(2); |
2992 | 15 | mxPop(); |
2993 | 15 | mxPop(); // globals |
2994 | 15 | } |
2995 | | |
2996 | 435 | target = fxNewInstance(the); |
2997 | 435 | own = fxNewInstance(the); |
2998 | 435 | mxPushSlot(mxArgv(0)); |
2999 | 435 | if (mxHasID(fxID(the, "modules"))) { |
3000 | 146 | txSlot* source; |
3001 | 146 | txSlot* at; |
3002 | 146 | txSlot* temporary; |
3003 | 146 | mxPushSlot(mxArgv(0)); |
3004 | 146 | mxGetID(fxID(the, "modules")); |
3005 | 146 | if (!mxIsReference(the->stack)) |
3006 | 13 | mxTypeError("options.modules: not an object"); |
3007 | 133 | source = the->stack->value.reference; |
3008 | 133 | at = fxNewInstance(the); |
3009 | 133 | mxBehaviorOwnKeys(the, source, XS_EACH_NAME_FLAG, at); |
3010 | 133 | mxTemporary(temporary); |
3011 | 390 | while ((at = at->next)) { |
3012 | 257 | if (mxBehaviorGetOwnProperty(the, source, at->value.at.id, at->value.at.index, temporary) && !(temporary->flag & XS_DONT_ENUM_FLAG)) { |
3013 | 246 | txSlot* descriptor; |
3014 | 246 | txSlot* property; |
3015 | 246 | mxPushReference(source); |
3016 | 246 | mxGetAll(at->value.at.id, at->value.at.index); |
3017 | 246 | descriptor = the->stack; |
3018 | 246 | property = mxBehaviorSetProperty(the, target, at->value.at.id, at->value.at.index, XS_OWN); |
3019 | 246 | property->kind = descriptor->kind; |
3020 | 246 | property->value = descriptor->value; |
3021 | 246 | mxPop(); // descriptor |
3022 | 246 | } |
3023 | 257 | } |
3024 | 133 | mxPop(); // temporary |
3025 | 133 | mxPop(); // at |
3026 | 133 | mxPop(); // modules |
3027 | 133 | } |
3028 | | |
3029 | 422 | mxPushUndefined(); |
3030 | 422 | closures = fxNewEnvironmentInstance(the, C_NULL); |
3031 | 422 | mxPushSlot(mxArgv(0)); |
3032 | 422 | if (mxHasID(fxID(the, "globalLexicals"))) { |
3033 | 44 | txSlot* target = fxLastProperty(the, closures); |
3034 | 44 | txSlot* source; |
3035 | 44 | txSlot* at; |
3036 | 44 | txSlot* property; |
3037 | 44 | mxPushSlot(mxArgv(0)); |
3038 | 44 | mxGetID(fxID(the, "globalLexicals")); |
3039 | 44 | if (!mxIsReference(the->stack)) |
3040 | 32 | mxTypeError("options.globalLexicals: not an object"); |
3041 | 12 | source = the->stack->value.reference; |
3042 | 12 | at = fxNewInstance(the); |
3043 | 12 | mxBehaviorOwnKeys(the, source, XS_EACH_NAME_FLAG, at); |
3044 | 12 | mxTemporary(property); |
3045 | 39 | while ((at = at->next)) { |
3046 | 27 | if ((at->value.at.id != XS_NO_ID) && mxBehaviorGetOwnProperty(the, source, at->value.at.id, at->value.at.index, property) && !(property->flag & XS_DONT_ENUM_FLAG)) { |
3047 | 20 | mxPushReference(source); |
3048 | 20 | mxGetAll(at->value.at.id, at->value.at.index); |
3049 | 20 | target = target->next = fxNewSlot(the); |
3050 | 20 | target->value.closure = fxNewSlot(the);; |
3051 | 20 | target->kind = XS_CLOSURE_KIND; |
3052 | 20 | target->ID = at->value.at.id; |
3053 | 20 | if (property->kind == XS_ACCESSOR_KIND) |
3054 | 5 | target->value.closure->flag = property->value.accessor.setter ? XS_NO_FLAG : XS_DONT_SET_FLAG; |
3055 | 15 | else |
3056 | 15 | target->value.closure->flag = property->flag & XS_DONT_SET_FLAG; |
3057 | 20 | target->value.closure->kind = the->stack->kind; |
3058 | 20 | target->value.closure->value = the->stack->value; |
3059 | 20 | mxPop(); |
3060 | 20 | } |
3061 | 27 | } |
3062 | 12 | mxPop(); // property |
3063 | 12 | mxPop(); // at |
3064 | 12 | mxPop(); // globalLexicals |
3065 | 12 | } |
3066 | | |
3067 | 390 | mxPushSlot(mxArgv(0)); |
3068 | 390 | if (mxHasID(fxID(the, "resolveHook"))) { |
3069 | 146 | mxPushSlot(mxArgv(0)); |
3070 | 146 | mxGetID(fxID(the, "resolveHook")); |
3071 | 146 | if (!fxIsCallable(the, the->stack)) |
3072 | 17 | mxTypeError("options.resolveHook: not a function"); |
3073 | 146 | } |
3074 | 244 | else |
3075 | 244 | mxPushUndefined(); |
3076 | | |
3077 | 373 | mxPushUndefined(); // moduleMapHook; |
3078 | | |
3079 | 373 | mxPushSlot(mxArgv(0)); |
3080 | 373 | if (mxHasID(fxID(the, "importHook"))) { |
3081 | 11 | mxPushSlot(mxArgv(0)); |
3082 | 11 | mxGetID(fxID(the, "importHook")); |
3083 | 11 | if (!fxIsCallable(the, the->stack)) |
3084 | 0 | mxTypeError("options.importHook: not a function"); |
3085 | 11 | } |
3086 | 362 | else { |
3087 | 362 | mxPushSlot(mxArgv(0)); |
3088 | 362 | if (mxHasID(fxID(the, "loadHook"))) { |
3089 | 40 | mxPushSlot(mxArgv(0)); |
3090 | 40 | mxGetID(fxID(the, "loadHook")); |
3091 | 40 | if (!fxIsCallable(the, the->stack)) |
3092 | 15 | mxTypeError("options.loadHook: not a function"); |
3093 | 40 | } |
3094 | 322 | else |
3095 | 322 | mxPushUndefined(); |
3096 | 362 | } |
3097 | | |
3098 | 358 | mxPushSlot(mxArgv(0)); |
3099 | 358 | if (mxHasID(fxID(the, "importNowHook"))) { |
3100 | 7 | mxPushSlot(mxArgv(0)); |
3101 | 7 | mxGetID(fxID(the, "importNowHook")); |
3102 | 7 | if (!fxIsCallable(the, the->stack)) |
3103 | 0 | mxTypeError("options.importNowHook: not a function"); |
3104 | 7 | } |
3105 | 351 | else { |
3106 | 351 | mxPushSlot(mxArgv(0)); |
3107 | 351 | if (mxHasID(fxID(the, "loadNowHook"))) { |
3108 | 28 | mxPushSlot(mxArgv(0)); |
3109 | 28 | mxGetID(fxID(the, "loadNowHook")); |
3110 | 28 | if (!fxIsCallable(the, the->stack)) |
3111 | 14 | mxTypeError("options.loadNowHook: not a function"); |
3112 | 28 | } |
3113 | 323 | else |
3114 | 323 | mxPushUndefined(); |
3115 | 351 | } |
3116 | | |
3117 | 344 | mxPushUndefined(); // importMetaHook; |
3118 | 344 | } |
3119 | 31 | else { |
3120 | 31 | target = fxNewInstance(the); |
3121 | 31 | own = fxNewInstance(the); |
3122 | | |
3123 | 31 | mxPushUndefined(); |
3124 | 31 | closures = fxNewEnvironmentInstance(the, C_NULL); |
3125 | | |
3126 | 31 | mxPushUndefined(); |
3127 | 31 | mxPushUndefined(); |
3128 | 31 | mxPushUndefined(); |
3129 | 31 | mxPushUndefined(); |
3130 | 31 | mxPushUndefined(); |
3131 | 31 | } |
3132 | | |
3133 | 375 | realm = fxNewRealmInstance(the); |
3134 | 375 | mxModuleInstanceInternal(program)->value.module.realm = realm; |
3135 | | |
3136 | 375 | slot = own->next; |
3137 | 375 | while (slot) { |
3138 | 0 | txSlot* internal = mxModuleInternal(slot); |
3139 | 0 | if (internal->value.module.realm == C_NULL) { |
3140 | 0 | if (!(internal->flag & XS_MARK_FLAG)) |
3141 | 0 | internal->value.module.realm = realm; |
3142 | 0 | } |
3143 | 0 | slot = slot->next; |
3144 | 0 | } |
3145 | | |
3146 | | |
3147 | 375 | mxPop(); |
3148 | 375 | } |
3149 | 375 | mxCatch(the) { |
3150 | 134 | fxJump(the); |
3151 | 134 | } |
3152 | 509 | } |
3153 | | |
3154 | | void fx_Compartment_prototype_get_globalThis(txMachine* the) |
3155 | 24 | { |
3156 | 24 | txSlot* program = fxCheckCompartmentInstance(the, mxThis); |
3157 | 24 | txSlot* realm = mxModuleInstanceInternal(program)->value.module.realm; |
3158 | 24 | txSlot* global = mxRealmGlobal(realm); |
3159 | 24 | mxResult->kind = global->kind; |
3160 | 24 | mxResult->value = global->value; |
3161 | 24 | } |
3162 | | |
3163 | | void fx_Compartment_prototype_evaluate(txMachine* the) |
3164 | 29 | { |
3165 | 29 | txSlot* program = fxCheckCompartmentInstance(the, mxThis); |
3166 | 29 | txSlot* realm = mxModuleInstanceInternal(program)->value.module.realm; |
3167 | 29 | if (mxArgc > 0) { |
3168 | 29 | txStringStream stream; |
3169 | 29 | stream.slot = mxArgv(0); |
3170 | 29 | stream.offset = 0; |
3171 | 29 | stream.size = mxStringLength(fxToString(the, mxArgv(0))); |
3172 | 29 | fxRunScript(the, fxParseScript(the, &stream, fxStringGetter, mxStrictFlag | mxProgramFlag | mxDebugFlag), mxRealmGlobal(realm), C_NULL, mxRealmClosures(realm)->value.reference, C_NULL, program); |
3173 | 29 | mxPullSlot(mxResult); |
3174 | 29 | } |
3175 | 29 | } |
3176 | | |
3177 | | void fx_Compartment_prototype_import(txMachine* the) |
3178 | 169 | { |
3179 | 169 | txSlot* program = fxCheckCompartmentInstance(the, mxThis); |
3180 | 169 | txSlot* realm = mxModuleInstanceInternal(program)->value.module.realm; |
3181 | 169 | if (mxArgc > 0) |
3182 | 168 | mxPushSlot(mxArgv(0)); |
3183 | 1 | else |
3184 | 1 | mxPushUndefined(); |
3185 | 169 | if (mxArgc > 1) |
3186 | 0 | mxPushSlot(mxArgv(1)); |
3187 | 169 | else |
3188 | 169 | mxPushUndefined(); |
3189 | 169 | gxDefaults.runImport(the, realm, C_NULL); |
3190 | 169 | mxPullSlot(mxResult); |
3191 | 169 | } |
3192 | | |
3193 | | void fx_Compartment_prototype_importNow(txMachine* the) |
3194 | 74 | { |
3195 | 74 | txSlot* program = fxCheckCompartmentInstance(the, mxThis); |
3196 | 74 | txSlot* realm = mxModuleInstanceInternal(program)->value.module.realm; |
3197 | 74 | if (mxArgc > 0) |
3198 | 74 | mxPushSlot(mxArgv(0)); |
3199 | 0 | else |
3200 | 0 | mxPushUndefined(); |
3201 | 74 | if (mxArgc > 1) |
3202 | 0 | mxPushSlot(mxArgv(1)); |
3203 | 74 | else |
3204 | 74 | mxPushUndefined(); |
3205 | 74 | fxRunImportNow(the, realm, C_NULL); |
3206 | 74 | mxPullSlot(mxResult); |
3207 | 74 | } |
3208 | | |
3209 | | txSlot* fxCheckModuleSourceInstance(txMachine* the, txSlot* slot) |
3210 | 17 | { |
3211 | 17 | if (slot->kind == XS_REFERENCE_KIND) { |
3212 | 17 | txSlot* instance = slot->value.reference; |
3213 | 17 | if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_MODULE_SOURCE_KIND)) { |
3214 | 16 | return instance; |
3215 | 16 | } |
3216 | 17 | } |
3217 | 17 | mxTypeError("this: not a ModuleSource instance"); |
3218 | 0 | return C_NULL; |
3219 | 17 | } |
3220 | | |
3221 | | txSlot* fxNewModuleSourceInstance(txMachine* the) |
3222 | 865 | { |
3223 | 865 | txSlot* instance; |
3224 | 865 | txSlot* slot; |
3225 | 865 | instance = fxNewSlot(the); |
3226 | 865 | instance->kind = XS_INSTANCE_KIND; |
3227 | 865 | instance->value.instance.garbage = C_NULL; |
3228 | 865 | instance->value.instance.prototype = the->stack->value.reference; |
3229 | 865 | the->stack->kind = XS_REFERENCE_KIND; |
3230 | 865 | the->stack->value.reference = instance; |
3231 | | /* HOST */ |
3232 | 865 | slot = instance->next = fxNewSlot(the); |
3233 | 865 | slot->flag = XS_INTERNAL_FLAG; |
3234 | 865 | slot->kind = XS_MODULE_SOURCE_KIND; |
3235 | 865 | slot->value.module.realm = C_NULL; |
3236 | 865 | slot->value.module.id = XS_NO_ID; |
3237 | | /* EXPORTS */ |
3238 | 865 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
3239 | | /* STUFF */ |
3240 | 865 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
3241 | | /* META */ |
3242 | 865 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
3243 | | /* TRANSFERS */ |
3244 | 865 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
3245 | | /* INITIALIZE */ |
3246 | 865 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
3247 | | /* FUNCTION */ |
3248 | 865 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
3249 | | /* HOSTS */ |
3250 | 865 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
3251 | | /* LOADER */ |
3252 | 865 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
3253 | 865 | return instance; |
3254 | 865 | } |
3255 | | |
3256 | | void fxExecuteVirtualModuleSourceImport(txMachine* the) |
3257 | 0 | { |
3258 | 0 | txSlot* instance = mxFunction->value.reference; |
3259 | 0 | txSlot* home = mxFunctionInstanceHome(instance); |
3260 | 0 | txSlot* module = home->value.home.module; |
3261 | 0 | txSlot* internal = mxModuleInstanceInternal(module); |
3262 | 0 | mxPushSlot(mxArgv(0)); |
3263 | 0 | gxDefaults.runImport(the, internal->value.module.realm, module); |
3264 | 0 | mxPullSlot(mxResult); |
3265 | 0 | } |
3266 | | |
3267 | | void fx_ModuleSource(txMachine* the) |
3268 | 865 | { |
3269 | 865 | txSlot* instance; |
3270 | 865 | txUnsigned flags = mxDebugFlag; |
3271 | 865 | txSlot* slot; |
3272 | 865 | txStringStream stream; |
3273 | 865 | txScript* script; |
3274 | 865 | if (mxIsUndefined(mxTarget)) |
3275 | 0 | mxTypeError("call: ModuleSource"); |
3276 | 865 | mxPushSlot(mxTarget); |
3277 | 865 | fxGetPrototypeFromConstructor(the, &mxModuleSourcePrototype); |
3278 | 865 | instance = fxNewModuleSourceInstance(the); |
3279 | 865 | mxPullSlot(mxResult); |
3280 | 865 | if (mxArgc > 0) |
3281 | 865 | mxPushSlot(mxArgv(0)); |
3282 | 0 | else |
3283 | 0 | mxPushUndefined(); |
3284 | 865 | if (mxArgc > 1) { |
3285 | 0 | if (fxCheckModuleOptions(the, mxArgv(1))) { |
3286 | 0 | instance->next->flag |= XS_JSON_MODULE_FLAG; |
3287 | 0 | flags |= mxJSONModuleFlag; |
3288 | 0 | } |
3289 | 0 | } |
3290 | 865 | slot = the->stack; |
3291 | 865 | stream.slot = slot; |
3292 | 865 | stream.offset = 0; |
3293 | 865 | stream.size = mxStringLength(fxToString(the, slot)); |
3294 | 865 | script = fxParseScript(the, &stream, fxStringGetter, flags); |
3295 | | // mxPushClosure(mxResult); |
3296 | 865 | fxRunScript(the, script, mxResult, C_NULL, C_NULL, C_NULL, instance); |
3297 | 865 | mxPop(); |
3298 | 865 | if (mxModuleInstanceExecute(instance)->kind == XS_NULL_KIND) |
3299 | 0 | mxTypeError("no module"); |
3300 | 865 | mxPop(); |
3301 | 865 | mxPop(); |
3302 | 865 | } |
3303 | | |
3304 | | void fx_ModuleSource_prototype_get_bindings(txMachine* the) |
3305 | 8 | { |
3306 | 8 | txSlot* record = fxCheckModuleSourceInstance(the, mxThis); |
3307 | 8 | txSlot* resultInstance; |
3308 | 8 | txSlot* resultArray; |
3309 | 8 | txSlot* resultItem; |
3310 | 8 | txSlot* transfer; |
3311 | | |
3312 | 8 | mxPush(mxArrayPrototype); |
3313 | 8 | resultInstance = fxNewArrayInstance(the); |
3314 | 8 | mxPullSlot(mxResult); |
3315 | 8 | resultArray = resultInstance->next; |
3316 | 8 | resultItem = resultArray; |
3317 | | |
3318 | 8 | transfer = mxModuleInstanceTransfers(record)->value.reference->next; |
3319 | 51 | while (transfer) { |
3320 | 43 | txSlot* local = mxTransferLocal(transfer); |
3321 | 43 | txSlot* from = mxTransferFrom(transfer); |
3322 | 43 | txSlot* import = mxTransferImport(transfer); |
3323 | 43 | txSlot* aliases = mxTransferAliases(transfer); |
3324 | | |
3325 | 43 | if (local->kind != XS_NULL_KIND) { |
3326 | 28 | if (from->kind != XS_NULL_KIND) { |
3327 | 15 | txSlot* slot = fxNewObject(the); |
3328 | 15 | if (import->kind == XS_NULL_KIND) { |
3329 | 4 | mxPushString(from->value.string); |
3330 | 4 | slot = fxNextSlotProperty(the, slot, the->stack, fxID(the, "importAllFrom"), XS_NO_FLAG); |
3331 | 4 | mxPop(); |
3332 | 4 | fxPushKeyString(the, local->value.symbol, C_NULL); |
3333 | 4 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_as), XS_NO_FLAG); |
3334 | 4 | mxPop(); |
3335 | 4 | } |
3336 | 11 | else { |
3337 | 11 | fxPushKeyString(the, import->value.symbol, C_NULL); |
3338 | 11 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_import), XS_NO_FLAG); |
3339 | 11 | mxPop(); |
3340 | 11 | if (local->value.symbol != import->value.symbol) { |
3341 | 7 | fxPushKeyString(the, local->value.symbol, C_NULL); |
3342 | 7 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_as), XS_NO_FLAG); |
3343 | 7 | mxPop(); |
3344 | 7 | } |
3345 | 11 | mxPushString(from->value.string); |
3346 | 11 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_from), XS_NO_FLAG); |
3347 | 11 | mxPop(); |
3348 | 11 | } |
3349 | 15 | resultItem = resultItem->next = fxNewSlot(the); |
3350 | 15 | mxPullSlot(resultItem); |
3351 | 15 | resultArray->value.array.length++; |
3352 | 15 | } |
3353 | 28 | if (aliases->kind == XS_REFERENCE_KIND) { |
3354 | 11 | txSlot* alias = aliases->value.reference->next; |
3355 | 24 | while (alias) { |
3356 | 13 | txSlot* slot = fxNewObject(the); |
3357 | 13 | fxPushKeyString(the, local->value.symbol, C_NULL); |
3358 | 13 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_export), XS_NO_FLAG); |
3359 | 13 | mxPop(); |
3360 | 13 | if (local->value.symbol != alias->value.symbol) { |
3361 | 3 | fxPushKeyString(the, alias->value.symbol, C_NULL); |
3362 | 3 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_as), XS_NO_FLAG); |
3363 | 3 | mxPop(); |
3364 | 3 | } |
3365 | 13 | resultItem = resultItem->next = fxNewSlot(the); |
3366 | 13 | mxPullSlot(resultItem); |
3367 | 13 | resultArray->value.array.length++; |
3368 | 13 | alias = alias->next; |
3369 | 13 | } |
3370 | 11 | } |
3371 | 28 | } |
3372 | 15 | else if (aliases->kind == XS_REFERENCE_KIND) { |
3373 | 12 | txSlot* alias = aliases->value.reference->next; |
3374 | 12 | if (alias) { |
3375 | 18 | while (alias) { |
3376 | 9 | txSlot* slot = fxNewObject(the); |
3377 | 9 | if (from->kind != XS_NULL_KIND) { |
3378 | 9 | if (import->kind == XS_NULL_KIND) { |
3379 | 3 | mxPushString(from->value.string); |
3380 | 3 | slot = fxNextSlotProperty(the, slot, the->stack, fxID(the, "exportAllFrom"), XS_NO_FLAG); |
3381 | 3 | mxPop(); |
3382 | 3 | fxPushKeyString(the, alias->value.symbol, C_NULL); |
3383 | 3 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_as), XS_NO_FLAG); |
3384 | 3 | mxPop(); |
3385 | 3 | } |
3386 | 6 | else { |
3387 | 6 | fxPushKeyString(the, import->value.symbol, C_NULL); |
3388 | 6 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_export), XS_NO_FLAG); |
3389 | 6 | mxPop(); |
3390 | 6 | if (alias->value.symbol != import->value.symbol) { |
3391 | 2 | fxPushKeyString(the, alias->value.symbol, C_NULL); |
3392 | 2 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_as), XS_NO_FLAG); |
3393 | 2 | mxPop(); |
3394 | 2 | } |
3395 | 6 | mxPushString(from->value.string); |
3396 | 6 | slot = fxNextSlotProperty(the, slot, the->stack, mxID(_from), XS_NO_FLAG); |
3397 | 6 | mxPop(); |
3398 | 6 | } |
3399 | 9 | resultItem = resultItem->next = fxNewSlot(the); |
3400 | 9 | mxPullSlot(resultItem); |
3401 | 9 | resultArray->value.array.length++; |
3402 | 9 | } |
3403 | 9 | alias = alias->next; |
3404 | 9 | } |
3405 | 9 | } |
3406 | 3 | else { |
3407 | 3 | txSlot* slot = fxNewObject(the); |
3408 | 3 | mxPushString(from->value.string); |
3409 | 3 | slot = fxNextSlotProperty(the, slot, the->stack, fxID(the, "exportAllFrom"), XS_NO_FLAG); |
3410 | 3 | mxPop(); |
3411 | 3 | resultItem = resultItem->next = fxNewSlot(the); |
3412 | 3 | mxPullSlot(resultItem); |
3413 | 3 | resultArray->value.array.length++; |
3414 | 3 | } |
3415 | 12 | } |
3416 | 3 | else if ((from->kind != XS_NULL_KIND) && (import->kind == XS_NULL_KIND)) { |
3417 | 3 | txSlot* slot = fxNewObject(the); |
3418 | 3 | mxPushString(from->value.string); |
3419 | 3 | slot = fxNextSlotProperty(the, slot, the->stack, fxID(the, "importFrom"), XS_NO_FLAG); |
3420 | 3 | mxPop(); |
3421 | 3 | resultItem = resultItem->next = fxNewSlot(the); |
3422 | 3 | mxPullSlot(resultItem); |
3423 | 3 | resultArray->value.array.length++; |
3424 | 3 | } |
3425 | 43 | transfer = transfer->next; |
3426 | 43 | } |
3427 | | |
3428 | 8 | fxCacheArray(the, resultInstance); |
3429 | 8 | } |
3430 | | |
3431 | | void fx_ModuleSource_prototype_get_needsImport(txMachine* the) |
3432 | 6 | { |
3433 | 6 | txSlot* record = fxCheckModuleSourceInstance(the, mxThis); |
3434 | 6 | txFlag flag = mxModuleInstanceInternal(record)->flag; |
3435 | 6 | mxResult->value.boolean = (flag & XS_IMPORT_FLAG) ? 1 : 0; |
3436 | 6 | mxResult->kind = XS_BOOLEAN_KIND; |
3437 | 6 | } |
3438 | | |
3439 | | void fx_ModuleSource_prototype_get_needsImportMeta(txMachine* the) |
3440 | 3 | { |
3441 | 3 | txSlot* record = fxCheckModuleSourceInstance(the, mxThis); |
3442 | 3 | txFlag flag = mxModuleInstanceInternal(record)->flag; |
3443 | 3 | mxResult->value.boolean = (flag & XS_IMPORT_META_FLAG) ? 1 : 0; |
3444 | 3 | mxResult->kind = XS_BOOLEAN_KIND; |
3445 | 3 | } |
3446 | | |
3447 | | void fx_ModuleSource_prototype_get_options(txMachine* the) |
3448 | 0 | { |
3449 | 0 | txSlot* record = fxCheckModuleSourceInstance(the, mxThis); |
3450 | 0 | txFlag flag = mxModuleInstanceInternal(record)->flag; |
3451 | 0 | fxPushModuleOptions(the, flag); |
3452 | 0 | mxPullSlot(mxResult); |
3453 | 0 | } |
3454 | | |
3455 | | #if mxModuleStuff |
3456 | | |
3457 | | txSlot* fxCheckModuleStuffInstance(txMachine* the, txSlot* slot) |
3458 | 0 | { |
3459 | 0 | if (slot->kind == XS_REFERENCE_KIND) { |
3460 | 0 | txSlot* instance = slot->value.reference; |
3461 | 0 | if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_MODULE_STUFF_KIND)) { |
3462 | 0 | return instance; |
3463 | 0 | } |
3464 | 0 | } |
3465 | 0 | mxTypeError("this: not a ModuleStuff instance"); |
3466 | 0 | return C_NULL; |
3467 | 0 | } |
3468 | | |
3469 | | txSlot* fxImportModuleStuff(txMachine* the, txSlot* realm, txSlot* queue, txSlot* reference, txSlot* name, txBoolean now) |
3470 | 0 | { |
3471 | 0 | txID moduleID = (name->kind == XS_STRING_X_KIND) ? fxNewNameX(the, name->value.string) : fxNewName(the, name); |
3472 | 0 | txSlot* list = mxModuleStuffModules(reference)->value.reference; |
3473 | 0 | txSlot* module = mxBehaviorGetProperty(the, list, moduleID, 0, XS_ANY); |
3474 | 0 | if (!module) { |
3475 | 0 | txSlot* handler = mxModuleStuffHandler(reference); |
3476 | 0 | txSlot* importHook = (now) ? mxModuleStuffImportNowHook(reference) : mxModuleStuffImportHook(reference); |
3477 | 0 | txSlot* loader; |
3478 | | |
3479 | 0 | module = mxBehaviorSetProperty(the, list, moduleID, 0, XS_OWN); |
3480 | 0 | fxNewModule(the, realm, XS_NO_ID, XS_NO_FLAG, module); |
3481 | 0 | mxModuleStatus(module) = XS_MODULE_STATUS_LOADING; |
3482 | 0 | fxQueueModule(the, queue, module); |
3483 | | |
3484 | 0 | loader = mxModuleLoader(module); |
3485 | 0 | loader->kind = reference->kind; |
3486 | 0 | loader->value = reference->value; |
3487 | | |
3488 | 0 | mxPushSlot(handler); |
3489 | 0 | mxPushSlot(importHook); |
3490 | 0 | mxCall(); |
3491 | 0 | mxPushSlot(name); |
3492 | 0 | fxPushModuleOptions(the, name->flag); |
3493 | 0 | mxRunCount(2); |
3494 | | |
3495 | 0 | if (now) { |
3496 | 0 | fxLoadModuleStuff(the, queue, module, the->stack); |
3497 | 0 | } |
3498 | 0 | else { |
3499 | 0 | fxLoadModulesPromise(the, queue, module, the->stack, fxLoadModuleStuffFulfilled, fxLoadModuleStuffRejected); |
3500 | 0 | } |
3501 | 0 | mxPop(); |
3502 | 0 | } |
3503 | 0 | return module; |
3504 | 0 | } |
3505 | | |
3506 | | void fxLoadModuleStuff(txMachine* the, txSlot* queue, txSlot* module, txSlot* stuff) |
3507 | 0 | { |
3508 | 0 | txSlot* instance = fxCheckModuleStuffInstance(the, stuff); |
3509 | 0 | txSlot* internal = mxModuleStuffInstanceModule(instance); |
3510 | 0 | if (mxIsReference(internal)) { |
3511 | 0 | txSlot* loader = mxModuleLoader(module); |
3512 | 0 | fxOverrideModule(the, queue, mxModuleStuffModules(loader), C_NULL, module->value.reference, internal->value.reference); |
3513 | 0 | loader->kind = XS_UNDEFINED_KIND; |
3514 | 0 | } |
3515 | 0 | else { |
3516 | 0 | txSlot* source = mxModuleStuffInstanceSource(instance); |
3517 | 0 | if (mxIsModuleSource(source->value.reference)) |
3518 | 0 | fxDuplicateModuleTransfers(the, source, module); |
3519 | 0 | else |
3520 | 0 | fxLoadVirtualModuleSource(the, source, module->value.reference); |
3521 | 0 | internal->value.reference = module->value.reference; |
3522 | 0 | internal->kind = XS_REFERENCE_KIND; |
3523 | 0 | internal = mxModuleHook(module); |
3524 | 0 | internal->value.reference = instance; |
3525 | 0 | internal->kind = XS_REFERENCE_KIND; |
3526 | 0 | mxModuleStatus(module) = XS_MODULE_STATUS_LOADED; |
3527 | 0 | } |
3528 | 0 | } |
3529 | | |
3530 | | txBoolean fxLoadModuleStuffFrom(txMachine* the, txSlot* queue, txSlot* module, txBoolean now) |
3531 | 156 | { |
3532 | 156 | txSlot* realm = mxModuleInstanceInternal(module)->value.module.realm; |
3533 | 156 | txSlot* reference = mxModuleInstanceHook(module); |
3534 | 156 | if (mxIsReference(reference)) { |
3535 | 0 | txSlot* handler = mxModuleStuffHandler(reference); |
3536 | 0 | txSlot* importHook = (now) ? mxModuleStuffImportNowHook(reference) : mxModuleStuffImportHook(reference); |
3537 | 0 | if (mxIsReference(handler) && mxIsReference(importHook)) { |
3538 | 0 | txSlot* transfer = mxModuleInstanceTransfers(module)->value.reference->next; |
3539 | 0 | while (transfer) { |
3540 | 0 | txSlot* from = mxTransferFrom(transfer); |
3541 | 0 | if (from->kind != XS_NULL_KIND) { |
3542 | 0 | txSlot* importModule = fxImportModuleStuff(the, realm, queue, reference, from, now); |
3543 | 0 | txID status = mxModuleStatus(importModule); |
3544 | 0 | from->value.reference = importModule->value.reference; |
3545 | 0 | from->kind = XS_REFERENCE_KIND; |
3546 | 0 | if ((status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADED)) { |
3547 | 0 | fxQueueModule(the, queue, importModule); |
3548 | 0 | } |
3549 | 0 | } |
3550 | 0 | transfer = transfer->next; |
3551 | 0 | } |
3552 | 0 | return 1; |
3553 | 0 | } |
3554 | 0 | } |
3555 | 156 | return 0; |
3556 | 156 | } |
3557 | | |
3558 | | void fxLoadModuleStuffFulfilled(txMachine* the) |
3559 | 0 | { |
3560 | 0 | txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference); |
3561 | 0 | txSlot* queue = home->value.home.object; |
3562 | 0 | txSlot* module = home->value.home.module; |
3563 | 0 | mxTry(the) { |
3564 | 0 | mxPushReference(module); |
3565 | 0 | fxLoadModuleStuff(the, queue, the->stack, mxArgv(0)); |
3566 | 0 | mxPop(); |
3567 | 0 | } |
3568 | 0 | mxCatch(the) { |
3569 | 0 | mxPush(mxException); |
3570 | 0 | mxException = mxUndefined; |
3571 | 0 | fxCompleteModule(the, module, the->stack); |
3572 | 0 | fxRunImportRejected(the, module, module); |
3573 | 0 | mxPop(); |
3574 | 0 | } |
3575 | 0 | fxLoadModules(the, queue); |
3576 | 0 | } |
3577 | | |
3578 | | void fxLoadModuleStuffRejected(txMachine* the) |
3579 | 0 | { |
3580 | 0 | txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference); |
3581 | 0 | txSlot* queue = home->value.home.object; |
3582 | 0 | txSlot* module = home->value.home.module; |
3583 | 0 | fxCompleteModule(the, module, mxArgv(0)); |
3584 | 0 | fxRunImportRejected(the, module, module); |
3585 | 0 | fxLoadModules(the, queue); |
3586 | 0 | } |
3587 | | |
3588 | | txSlot* fxNewModuleStuffInstance(txMachine* the) |
3589 | 0 | { |
3590 | 0 | txSlot* instance; |
3591 | 0 | txSlot* slot; |
3592 | 0 | txSlot* modules; |
3593 | 0 | instance = fxNewSlot(the); |
3594 | 0 | instance->kind = XS_INSTANCE_KIND; |
3595 | 0 | instance->value.instance.garbage = C_NULL; |
3596 | 0 | instance->value.instance.prototype = the->stack->value.reference; |
3597 | 0 | the->stack->kind = XS_REFERENCE_KIND; |
3598 | 0 | the->stack->value.reference = instance; |
3599 | | /* HOST */ |
3600 | 0 | slot = instance->next = fxNewSlot(the); |
3601 | 0 | slot->flag = XS_INTERNAL_FLAG; |
3602 | 0 | slot->kind = XS_MODULE_STUFF_KIND; |
3603 | | /* MODULE */ |
3604 | 0 | slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG); |
3605 | | /* MODULES */ |
3606 | 0 | modules = fxNewInstance(the); |
3607 | 0 | slot = fxNextReferenceProperty(the, slot, modules, XS_NO_ID, XS_INTERNAL_FLAG); |
3608 | 0 | mxPop(); |
3609 | 0 | return instance; |
3610 | 0 | } |
3611 | | |
3612 | | void fx_ModuleStuff(txMachine* the) |
3613 | 0 | { |
3614 | 0 | txSlot* instance; |
3615 | 0 | txSlot* handler; |
3616 | 0 | txSlot* importHook; |
3617 | 0 | txSlot* importMetaHook; |
3618 | 0 | txSlot* importNowHook; |
3619 | 0 | txSlot* slot; |
3620 | 0 | if (mxIsUndefined(mxTarget)) |
3621 | 0 | mxTypeError("call: ModuleStuff"); |
3622 | 0 | if ((mxArgc < 1) || (!mxIsReference(mxArgv(0)))) |
3623 | 0 | mxTypeError("source: not an object"); |
3624 | 0 | if ((mxArgc < 2) || mxIsUndefined(mxArgv(1))) { |
3625 | 0 | mxPushUndefined(); |
3626 | 0 | mxPushUndefined(); |
3627 | 0 | mxPushUndefined(); |
3628 | 0 | mxPushUndefined(); |
3629 | 0 | } |
3630 | 0 | else if (mxIsReference(mxArgv(1))) { |
3631 | 0 | mxPushSlot(mxArgv(1)); |
3632 | 0 | mxPushSlot(mxArgv(1)); |
3633 | 0 | mxGetID(fxID(the, "importHook")); |
3634 | 0 | if (!mxIsUndefined(the->stack) && !fxIsCallable(the, the->stack)) |
3635 | 0 | mxTypeError("handler.importHook: not a function"); |
3636 | 0 | mxPushSlot(mxArgv(1)); |
3637 | 0 | mxGetID(fxID(the, "importMetaHook")); |
3638 | 0 | if (!mxIsUndefined(the->stack) && !fxIsCallable(the, the->stack)) |
3639 | 0 | mxTypeError("handler.importMetaHook: not a function"); |
3640 | 0 | mxPushSlot(mxArgv(1)); |
3641 | 0 | mxGetID(fxID(the, "importNowHook")); |
3642 | 0 | if (!mxIsUndefined(the->stack) && !fxIsCallable(the, the->stack)) |
3643 | 0 | mxTypeError("handler.importNowHook: not a function"); |
3644 | 0 | } |
3645 | 0 | else { |
3646 | 0 | mxTypeError("handler: not an object"); |
3647 | 0 | } |
3648 | 0 | handler = the->stack + 3; |
3649 | 0 | importHook = the->stack + 2; |
3650 | 0 | importMetaHook = the->stack + 1; |
3651 | 0 | importNowHook = the->stack; |
3652 | | |
3653 | 0 | mxPushSlot(mxTarget); |
3654 | 0 | fxGetPrototypeFromConstructor(the, &mxModuleStuffPrototype); |
3655 | 0 | instance = fxNewModuleStuffInstance(the); |
3656 | 0 | mxPullSlot(mxResult); |
3657 | | |
3658 | 0 | slot = fxLastProperty(the, instance); |
3659 | 0 | slot = fxNextSlotProperty(the, slot, mxArgv(0), XS_NO_ID, XS_INTERNAL_FLAG); |
3660 | 0 | slot = fxNextSlotProperty(the, slot, handler, XS_NO_ID, XS_INTERNAL_FLAG); |
3661 | 0 | slot = fxNextSlotProperty(the, slot, importHook, XS_NO_ID, XS_INTERNAL_FLAG); |
3662 | 0 | slot = fxNextSlotProperty(the, slot, importMetaHook, XS_NO_ID, XS_INTERNAL_FLAG); |
3663 | 0 | slot = fxNextSlotProperty(the, slot, importNowHook, XS_NO_ID, XS_INTERNAL_FLAG); |
3664 | | |
3665 | 0 | mxPop(); |
3666 | 0 | mxPop(); |
3667 | 0 | mxPop(); |
3668 | 0 | mxPop(); |
3669 | 0 | } |
3670 | | |
3671 | | #endif |