Coverage Report

Created: 2026-03-16 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsModule.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2016-2025  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
14
  (((THE_SLOT)->next) && ((THE_SLOT)->next->flag & XS_INTERNAL_FLAG) && ((THE_SLOT)->next->kind == XS_MODULE_KIND))
143
#define mxIsModuleSource(THE_SLOT) \
144
202
  (((THE_SLOT)->next) && ((THE_SLOT)->next->flag & XS_INTERNAL_FLAG) && ((THE_SLOT)->next->kind == XS_MODULE_SOURCE_KIND))
145
146
25.8k
#define mxModuleInstanceStatus(MODULE)    ((MODULE)->next->next->ID)
147
25.4k
#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
20.4k
{
178
20.4k
  txSlot* slot;
179
  
180
20.4k
  fxNewHostFunction(the, mxCallback(fxModuleGetter), 0, XS_NO_ID, XS_NO_ID);
181
20.4k
  mxPushUndefined();
182
20.4k
  the->stack->flag = XS_DONT_DELETE_FLAG;
183
20.4k
  the->stack->kind = XS_ACCESSOR_KIND;
184
20.4k
  the->stack->value.accessor.getter = (the->stack + 1)->value.reference;
185
20.4k
  the->stack->value.accessor.setter = C_NULL;
186
20.4k
  mxPull(mxModuleAccessor);
187
20.4k
  the->stack += 1;
188
  
189
20.4k
  mxPush(mxObjectPrototype);
190
20.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
191
20.4k
  slot = fxNextStringXProperty(the, slot, "Module", mxID(_Symbol_toStringTag), XS_GET_ONLY);
192
20.4k
  mxModulePrototype = *the->stack;
193
20.4k
  mxPop();
194
  
195
20.4k
  mxPush(mxObjectPrototype);
196
20.4k
  fxNewObjectInstance(the);
197
20.4k
  mxTransferPrototype = *the->stack;
198
20.4k
  mxPop();
199
200
20.4k
  mxPush(mxObjectPrototype);
201
20.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
202
20.4k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_Compartment_prototype_get_globalThis), C_NULL, mxID(_globalThis), XS_DONT_ENUM_FLAG);
203
20.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Compartment_prototype_evaluate), 1, mxID(_evaluate), XS_DONT_ENUM_FLAG);
204
20.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Compartment_prototype_import), 1, mxID(_import), XS_DONT_ENUM_FLAG);
205
20.4k
  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
20.4k
  slot = fxNextStringXProperty(the, slot, "Compartment", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
208
20.4k
  mxCompartmentPrototype = *the->stack;
209
20.4k
  slot = fxBuildHostConstructor(the, mxCallback(fx_Compartment), 1, mxID(_Compartment));
210
20.4k
  mxCompartmentConstructor = *the->stack;
211
20.4k
  mxPop();
212
  
213
20.4k
  mxPush(mxObjectPrototype);
214
20.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
215
20.4k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_ModuleSource_prototype_get_bindings), C_NULL, mxID(_bindings), XS_DONT_ENUM_FLAG);
216
20.4k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_ModuleSource_prototype_get_needsImport), C_NULL, mxID(_needsImport), XS_DONT_ENUM_FLAG);
217
20.4k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_ModuleSource_prototype_get_needsImportMeta), C_NULL, mxID(_needsImportMeta), XS_DONT_ENUM_FLAG);
218
20.4k
#if mxECMAScript2025  
219
20.4k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_ModuleSource_prototype_get_options), C_NULL, mxID(_options), XS_DONT_ENUM_FLAG);
220
20.4k
#endif
221
20.4k
  slot = fxNextStringXProperty(the, slot, "ModuleSource", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
222
20.4k
  mxModuleSourcePrototype = *the->stack;
223
20.4k
  slot = fxBuildHostConstructor(the, mxCallback(fx_ModuleSource), 1, mxID(_ModuleSource));
224
20.4k
  mxModuleSourceConstructor = *the->stack;
225
20.4k
  mxPop();
226
  
227
20.4k
#if mxModuleStuff 
228
20.4k
  mxPush(mxObjectPrototype);
229
20.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
230
20.4k
  slot = fxNextStringXProperty(the, slot, "ModuleStuff", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
231
20.4k
  mxModuleStuffPrototype = *the->stack;
232
20.4k
  slot = fxBuildHostConstructor(the, mxCallback(fx_ModuleStuff), 1, mxID(_ModuleStuff));
233
20.4k
  mxModuleStuffConstructor = *the->stack;
234
20.4k
  mxPop();
235
20.4k
#endif
236
20.4k
}
237
238
void fxCheckModuleFlag(txMachine* the, txID moduleID, txFlag moduleFlag, txFlag requestFlag)
239
19.0k
{
240
19.0k
#ifndef mxLink
241
19.0k
  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
19.0k
  else {
248
19.0k
    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
19.0k
  }
253
19.0k
#endif
254
19.0k
}
255
256
void fxPushModuleOptions(txMachine* the, txFlag moduleFlag)
257
44
{
258
44
#if mxECMAScript2025  
259
44
  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
44
  else
267
44
#endif
268
44
    mxPushUndefined();
269
44
}
270
271
txFlag fxCheckModuleOptions(txMachine* the, txSlot* options)
272
19.4k
{
273
19.4k
  txFlag moduleFlag = XS_NO_FLAG;
274
19.4k
#if mxECMAScript2025  
275
19.4k
  if (!mxIsUndefined(options)) {
276
389
    txSlot* with;
277
389
    if (!mxIsReference(options))
278
387
      mxTypeError("options: not an object");
279
2
    mxPushSlot(options);
280
2
    mxGetID(mxID(_with));
281
2
    with = the->stack;
282
2
    if (!mxIsUndefined(with)) {
283
1
      txSlot* key;
284
1
      txSlot* property;
285
1
      txSlot* value;
286
1
      txInteger count = 0;
287
1
      if (!mxIsReference(with))
288
0
        mxTypeError("options.with: not an object");
289
1
      key = fxNewInstance(the);
290
1
      mxBehaviorOwnKeys(the, with->value.reference, XS_EACH_NAME_FLAG, key);
291
1
      mxTemporary(property);
292
3
      while ((key = key->next)) {
293
2
        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
2
      }
309
1
      mxPop();
310
1
      mxPop();
311
1
      if (count > 0)
312
0
        mxTypeError("options.with: invalid attributes");
313
1
    }
314
2
    mxPop();
315
2
  }
316
19.0k
#endif
317
19.0k
  return moduleFlag;
318
19.4k
}
319
320
void fxCompleteModule(txMachine* the, txSlot* module, txSlot* exception)
321
396
{
322
396
  if (exception) {
323
273
    txSlot* exports = mxModuleInstanceExports(module);
324
273
    txSlot* meta = mxModuleInstanceMeta(module);
325
273
    if (exports->kind == XS_REFERENCE_KIND) {
326
68
      exports->value.reference->next = C_NULL;
327
68
    }
328
205
    else {
329
205
      fxNewInstance(the);
330
205
      mxPullSlot(exports);
331
205
    }
332
273
    meta->value = exception->value;
333
273
    meta->kind = exception->kind;
334
273
    mxModuleInstanceStatus(module) = XS_MODULE_STATUS_ERROR;
335
273
  }
336
123
  else {
337
123
    mxModuleInstanceStatus(module) = XS_MODULE_STATUS_EXECUTED;
338
123
  }
339
396
}
340
341
void fxDuplicateModuleTransfers(txMachine* the, txSlot* srcModule, txSlot* dstModule)
342
132
{
343
132
  txSlot* srcSlot;
344
132
  txSlot* dstSlot;
345
132
  txSlot* transfer;
346
132
  txSlot* aliases;
347
132
  txSlot* function;
348
132
  srcSlot = mxModuleInternal(srcModule);
349
132
  dstSlot = mxModuleInternal(dstModule);
350
132
  dstSlot->flag |= (srcSlot->flag & (XS_IMPORT_FLAG | XS_IMPORT_META_FLAG));
351
132
  srcSlot = mxModuleTransfers(srcModule);
352
132
  dstSlot = mxModuleTransfers(dstModule);
353
132
  fxDuplicateInstance(the, srcSlot->value.reference);
354
132
  mxPullSlot(dstSlot);
355
132
  transfer = dstSlot->value.reference->next;
356
378
  while (transfer) {
357
246
    fxDuplicateInstance(the, transfer->value.reference);
358
246
    mxPullSlot(transfer);
359
246
    aliases = mxTransferAliases(transfer);
360
246
    if (aliases->kind == XS_REFERENCE_KIND) {
361
201
      fxDuplicateInstance(the, aliases->value.reference);
362
201
      mxPullSlot(aliases);
363
201
    }    
364
246
    transfer = transfer->next;
365
246
  }
366
132
  srcSlot = mxModuleInitialize(srcModule);
367
132
  dstSlot = mxModuleInitialize(dstModule);
368
132
  if (srcSlot->kind == XS_REFERENCE_KIND) {
369
0
    function = fxDuplicateInstance(the, srcSlot->value.reference);
370
0
    mxPullSlot(dstSlot);
371
0
    mxFunctionInstanceHome(function)->value.home.module =   dstModule->value.reference;
372
0
  }
373
132
  else {
374
132
    dstSlot->kind = srcSlot->kind;
375
132
    dstSlot->value = srcSlot->value;
376
132
  }
377
132
  srcSlot = mxModuleExecute(srcModule);
378
132
  dstSlot = mxModuleExecute(dstModule);
379
132
  function = fxDuplicateInstance(the, srcSlot->value.reference);
380
132
  mxPullSlot(dstSlot);
381
132
  mxFunctionInstanceHome(function)->value.home.module =   dstModule->value.reference;
382
132
}
383
384
void fxExecuteModules(txMachine* the, txSlot* queue)
385
217
{
386
217
  txBoolean done = 1;
387
217
  txSlot* module = queue->next;
388
217
  mxReportModuleQueue("INIT");
389
543
  while (module) {
390
326
    txID status = mxModuleStatus(module);
391
326
    if (status == XS_MODULE_STATUS_LINKED) {
392
113
      txSlot* exception;
393
113
      txID fromStatus = fxExecuteModulesFrom(the, queue, module, &exception);
394
113
      if (fromStatus == XS_MODULE_STATUS_ERROR) {
395
11
        fxCompleteModule(the, module->value.reference, exception);
396
11
        fxRunImportRejected(the, module->value.reference, module->value.reference);
397
11
      }
398
102
      else if (fromStatus == XS_MODULE_STATUS_LINKED) {
399
102
        mxModuleStatus(module) = XS_MODULE_STATUS_EXECUTING;
400
102
        mxPushSlot(mxModuleHosts(module));
401
102
        mxPull(mxHosts);
402
102
        {
403
102
          mxTry(the) {
404
102
            txSlot* result;
405
102
            mxPushUndefined();
406
102
            mxPushSlot(mxModuleExecute(module));
407
102
            mxCall();
408
102
            mxRunCount(0);
409
102
            result = the->stack;
410
102
            if (mxIsReference(result) && mxIsPromise(result->value.reference)) {
411
14
              txSlot* function;
412
14
              txSlot* home;
413
14
              txSlot* resolveExecuteFunction;
414
14
              txSlot* rejectExecuteFunction;
415
              
416
14
              function = fxNewHostFunction(the, fxExecuteModulesFulfilled, 1, XS_NO_ID, mxExecuteModulesFulfilledProfileID);
417
14
              home = mxFunctionInstanceHome(function);
418
14
              home->value.home.object = queue;
419
14
              home->value.home.module = module->value.reference;
420
14
              resolveExecuteFunction = the->stack;
421
  
422
14
              function = fxNewHostFunction(the, fxExecuteModulesRejected, 1, XS_NO_ID, mxExecuteModulesRejectedProfileID);
423
14
              home = mxFunctionInstanceHome(function);
424
14
              home->value.home.object = queue;
425
14
              home->value.home.module = module->value.reference;
426
14
              rejectExecuteFunction = the->stack;
427
        
428
14
              fxPromiseThen(the, result->value.reference, resolveExecuteFunction, rejectExecuteFunction, C_NULL, C_NULL);
429
            
430
14
              mxPop();
431
14
              mxPop();
432
14
              mxPop();
433
14
              done = 0;
434
14
            }
435
88
            else {
436
88
              mxPop();
437
88
              fxCompleteModule(the, module->value.reference, C_NULL);
438
88
              fxRunImportFulfilled(the, module->value.reference, module->value.reference);
439
88
            }
440
102
          }
441
102
          mxCatch(the) {
442
14
            mxPush(mxException);
443
14
            mxException = mxUndefined;
444
14
            fxCompleteModule(the, module->value.reference, the->stack);
445
14
            fxRunImportRejected(the, module->value.reference, module->value.reference);
446
14
            mxPop();
447
14
          }
448
102
        }
449
102
        mxPushUndefined();
450
102
        mxPull(mxHosts);
451
102
      }
452
0
      else
453
0
        done = 0;
454
113
    }
455
213
    else if (status < XS_MODULE_STATUS_EXECUTED)
456
1
      done = 0;
457
326
    module = module->next;
458
326
  }
459
217
  if (done) {
460
202
    queue->next = C_NULL;
461
202
    mxReportModuleQueue("DONE");
462
202
  }
463
217
}
464
465
txID fxExecuteModulesFrom(txMachine* the, txSlot* queue, txSlot* module, txSlot** exception)
466
113
{
467
113
  txSlot* fromModules = mxModuleTransfers(module)->value.reference;
468
113
  txSlot* fromModule;
469
113
  if (mxModuleTransfers(module)->kind == XS_NULL_KIND)
470
73
    return XS_MODULE_STATUS_LINKED;
471
40
  fromModule = fromModules->next;
472
71
  while (fromModule) {
473
42
    if (mxModuleStatus(fromModule) == XS_MODULE_STATUS_ERROR) {
474
11
      *exception = mxModuleMeta(fromModule);
475
11
      return XS_MODULE_STATUS_ERROR;
476
11
    }
477
31
    fromModule = fromModule->next;
478
31
  }
479
29
  fromModule = fromModules->next;
480
58
  while (fromModule) {
481
29
    if (mxModuleStatus(fromModule) == XS_MODULE_STATUS_EXECUTING) {
482
0
      return XS_MODULE_STATUS_EXECUTING;
483
0
    }
484
29
    fromModule = fromModule->next;
485
29
  }
486
29
  fromModule = fromModules->next;
487
58
  while (fromModule) {
488
29
    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
29
    fromModule = fromModule->next;
499
29
  }
500
29
  return XS_MODULE_STATUS_LINKED;
501
29
}
502
503
void fxExecuteModulesFulfilled(txMachine* the)
504
2
{
505
2
  txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference);
506
2
  txSlot* queue = home->value.home.object;
507
2
  txSlot* module = home->value.home.module;
508
2
  fxCompleteModule(the, module, C_NULL);
509
2
  fxRunImportFulfilled(the, module, module);
510
2
  fxExecuteModules(the, queue);
511
2
}
512
513
void fxExecuteModulesRejected(txMachine* the)
514
4
{
515
4
  txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference);
516
4
  txSlot* queue = home->value.home.object;
517
4
  txSlot* module = home->value.home.module;
518
4
  fxCompleteModule(the, module,  mxArgv(0));
519
4
  fxRunImportRejected(the, module, module);
520
4
  fxExecuteModules(the, queue);
521
4
}
522
523
void fxExecuteVirtualModuleSource(txMachine* the)
524
40
{
525
40
  txSlot* instance = mxFunction->value.reference;
526
40
  txSlot* function = fxLastProperty(the, instance);
527
40
  txSlot* home = mxFunctionInstanceHome(instance);
528
40
  txSlot* module = home->value.home.module;
529
40
  txSlot* internal = mxModuleInstanceInternal(module);
530
40
  txSlot* meta = mxModuleInstanceMeta(module);
531
40
  txSlot* closures = mxFunctionInstanceCode(instance)->value.callback.closures;
532
40
  txSlot* property;
533
40
  if (mxIsUndefined(function))
534
6
    return;
535
34
  closures->flag |= XS_DONT_PATCH_FLAG;
536
34
  closures->value.instance.prototype = C_NULL;
537
34
  property = closures->next->next;
538
99
  while (property) {
539
65
    property->flag |= XS_DONT_DELETE_FLAG;
540
65
    property = property->next;
541
65
  }
542
  /* THIS */
543
34
  mxPushReference(home->value.home.object);
544
  /* FUNCTION */
545
34
  mxPushSlot(function);
546
34
  mxCall();
547
  /* ARGUMENTS */
548
34
  mxPushReference(closures);
549
34
  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
33
  else
554
33
    mxPushUndefined();
555
34
  if (internal->flag & XS_IMPORT_META_FLAG)
556
1
    mxPushSlot(meta);
557
33
  else
558
33
    mxPushUndefined();
559
34
  mxRunCount(3);
560
34
  mxPullSlot(mxResult);
561
34
}
562
563
txSlot* fxGetModule(txMachine* the, txSlot* realm, txID moduleID, txFlag moduleFlag)
564
19.2k
{
565
19.2k
  txSlot* result = mxBehaviorGetProperty(the, mxOwnModules(realm)->value.reference, moduleID, 0, XS_ANY);
566
19.2k
  if (result)
567
18.7k
    fxCheckModuleFlag(the, moduleID, mxModuleInternal(result)->flag, moduleFlag);
568
19.2k
  return result;
569
19.2k
}
570
571
void fxLinkCircularities(txMachine* the, txSlot* module, txSlot* circularities, txSlot* exports)
572
178
{
573
178
  txSlot* circularitiesInstance;
574
178
  txSlot* circularity;
575
178
  txSlot* transfers;
576
178
  txSlot* exportsInstance;
577
178
  txSlot* export;
578
178
  txSlot* transfer;
579
178
  txSlot* aliases;
580
178
  txSlot* alias;
581
178
  txSlot* circularitiesCopy;
582
178
  txSlot* circularityCopy;
583
178
  txSlot* from;
584
178
  txSlot* stars;
585
178
  txSlot* star;
586
178
  circularitiesInstance = circularities->value.reference;
587
178
  circularity = circularitiesInstance->next;
588
178
  while (circularity) {
589
0
    if (circularity->value.reference == module->value.reference)
590
0
      return;
591
0
    circularity = circularity->next;
592
0
  }
593
178
  circularity = fxDuplicateSlot(the, module);
594
178
  circularity->next = circularitiesInstance->next;
595
178
  circularitiesInstance->next = circularity;
596
178
  exportsInstance = exports->value.reference;
597
178
  export = exportsInstance;
598
178
  transfers = mxModuleExports(module);
599
178
  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
178
  transfers = mxModuleTransfers(module);
611
178
  if (transfers->kind == XS_REFERENCE_KIND) {
612
178
    txBoolean starFlag = 0;
613
178
    transfer = transfers->value.reference->next;
614
604
    while (transfer) {
615
426
      aliases = mxTransferAliases(transfer);
616
426
      if (aliases->kind == XS_REFERENCE_KIND) {
617
320
        alias = aliases->value.reference->next;
618
320
        if (alias) {
619
647
          while (alias) {
620
327
            export = export->next = fxNewSlot(the);
621
327
            export->ID = alias->value.symbol;
622
327
            export->kind = transfer->kind;
623
327
            export->value = transfer->value;
624
327
            alias = alias->next;
625
327
          }
626
320
        }
627
0
        else {
628
0
          mxCheck(the, mxTransferLocal(transfer)->kind == XS_NULL_KIND);
629
0
          starFlag = 1;
630
0
        }
631
320
      }
632
426
      transfer = transfer->next;
633
426
    }
634
178
    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
178
  }
719
178
}
720
721
void fxLinkExports(txMachine* the, txSlot* module)
722
178
{
723
178
  txSlot* exports;
724
178
  txSlot* transfer;
725
178
  txSlot* from;
726
178
  txSlot* import;
727
178
  txSlot* closure;
728
729
178
  exports = mxModuleExports(module)->value.reference;
730
178
  exports->flag |= XS_DONT_PATCH_FLAG;
731
178
  transfer = exports->next;
732
492
  while (transfer) {
733
314
    if (transfer->kind != XS_EXPORT_KIND) {
734
314
      from = mxTransferFrom(transfer);
735
314
      if (from->kind != XS_NULL_KIND) {
736
44
        import = mxTransferImport(transfer);
737
44
        if (import->kind != XS_NULL_KIND)
738
31
          fxLinkTransfer(the, from, import->value.symbol, transfer);
739
13
        else
740
13
          fxLinkNamespace(the, from, transfer);
741
44
      }
742
314
      closure = mxTransferClosure(transfer);
743
314
      transfer->kind = closure->kind;
744
314
      transfer->value = closure->value;
745
314
    }
746
314
    transfer->flag |= XS_DONT_DELETE_FLAG | XS_DONT_SET_FLAG;
747
314
    transfer = transfer->next;
748
314
  }
749
178
}
750
751
void fxLinkLocals(txMachine* the, txSlot* module)
752
163
{
753
163
  txSlot* transfer;
754
163
  txSlot* local;
755
163
  txSlot* from;
756
163
  txSlot* import;
757
163
  txSlot* closure;
758
759
163
  transfer = mxModuleTransfers(module)->value.reference->next;
760
483
  while (transfer) {
761
320
    local = mxTransferLocal(transfer);
762
320
    if (local->kind != XS_NULL_KIND) {
763
281
      from = mxTransferFrom(transfer);
764
281
      if (from->kind != XS_NULL_KIND) {
765
71
        import = mxTransferImport(transfer);
766
71
        if (import->kind != XS_NULL_KIND)
767
60
          fxLinkTransfer(the, from, import->value.symbol, transfer);
768
11
        else
769
11
          fxLinkNamespace(the, from, transfer);
770
71
        closure = mxTransferClosure(transfer);
771
71
        closure->flag |= XS_DONT_SET_FLAG;
772
71
      }
773
281
    }
774
320
    transfer = transfer->next;
775
320
  }
776
163
}
777
778
void fxLinkModules(txMachine* the, txSlot* queue)
779
245
{
780
245
  txSlot* module;
781
245
  txSlot* order;
782
245
  txSlot* transfer;
783
245
  txSlot* local;
784
245
  txSlot* from;
785
245
  txSlot* import;
786
245
  txSlot* aliases;
787
245
  txSlot* closure;
788
245
  txSlot* property;
789
245
  txSlot* circularities;
790
245
  txSlot* exports;
791
245
  txSlot* realm;
792
245
  txSlot* closures;
793
245
  txSlot* export;
794
  
795
245
  order = fxNewInstance(the);
796
497
  while ((module = queue->next))
797
252
    fxOrderModule(the, queue, order, module);
798
245
  queue->next = order->next;
799
245
  order->next = C_NULL;
800
245
  mxPop();
801
802
245
  mxReportModuleQueue("LINK");
803
245
  module = queue->next;
804
598
  while (module) {
805
353
    if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) {
806
178
      transfer = mxModuleTransfers(module)->value.reference->next;
807
604
      while (transfer) {
808
426
        local = mxTransferLocal(transfer);
809
426
        from = mxTransferFrom(transfer);
810
426
        import = mxTransferImport(transfer);
811
426
        aliases = mxTransferAliases(transfer);
812
426
        if (local->kind != XS_NULL_KIND) {
813
358
          if ((from->kind == XS_NULL_KIND) || (import->kind == XS_NULL_KIND)) {
814
286
            closure = mxTransferClosure(transfer);
815
286
            closure->value.export.closure = fxNewSlot(the);
816
286
            closure->value.export.closure->kind = XS_UNINITIALIZED_KIND;
817
286
            closure->value.export.module = module->value.reference;
818
286
            closure->kind = XS_EXPORT_KIND;
819
286
          }
820
358
        }
821
68
        else {
822
68
          if ((from->kind != XS_NULL_KIND) && (import->kind == XS_NULL_KIND) && (aliases->kind != XS_NULL_KIND)) {
823
18
            closure = mxTransferClosure(transfer);
824
18
            closure->value.export.closure = fxNewSlot(the);
825
18
            closure->value.export.closure->kind = XS_UNINITIALIZED_KIND;
826
18
            closure->value.export.module = module->value.reference;
827
18
            closure->kind = XS_EXPORT_KIND;
828
18
          }
829
68
        }
830
426
        transfer = transfer->next;
831
426
      }
832
178
    }
833
353
    module = module->next;
834
353
  }
835
836
245
  module = queue->next;
837
598
  while (module) {
838
353
    if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) {
839
178
      fxNewInstance(the);
840
178
      circularities = the->stack;
841
178
      fxNewInstance(the);
842
178
      exports = the->stack;
843
178
      fxLinkCircularities(the, module, circularities, exports);
844
178
      mxModuleExports(module)->kind = XS_REFERENCE_KIND;
845
178
      mxModuleExports(module)->value.reference = exports->value.reference;
846
178
      mxPop();
847
178
      mxPop();
848
178
    }
849
353
    module = module->next;
850
353
  }
851
852
245
  module = queue->next;
853
598
  while (module) {
854
353
    if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING)
855
178
      fxLinkExports(the, module);
856
353
    module = module->next;
857
353
  }
858
245
  module = queue->next;
859
558
  while (module) {
860
313
    if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING)
861
163
      fxLinkLocals(the, module);
862
313
    module = module->next;
863
313
  }
864
865
245
  module = queue->next;
866
538
  while (module) {
867
293
    if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) {
868
151
      txInteger count = 0;
869
151
      mxPushUndefined();
870
151
      realm = mxModuleInternal(module)->value.module.realm;
871
151
      closures = fxNewEnvironmentInstance(the, mxRealmClosures(realm));
872
151
      closure = closures->next;
873
151
      transfer = mxModuleTransfers(module)->value.reference->next;
874
456
      while (transfer) {
875
305
        local = mxTransferLocal(transfer);
876
305
        if (local->kind != XS_NULL_KIND) {
877
266
          export = mxTransferClosure(transfer);
878
266
          mxCheck(the, export->kind == XS_EXPORT_KIND);
879
266
          closure = closure->next = fxNewSlot(the);
880
266
          closure->ID = local->value.symbol;
881
266
          closure->flag = export->flag;
882
266
          closure->kind = XS_CLOSURE_KIND;
883
266
          closure->value.closure = export->value.export.closure;
884
266
        }
885
305
        from = mxTransferFrom(transfer);
886
305
        if (from->kind != XS_NULL_KIND)
887
101
          count++;
888
305
        transfer = transfer->next;
889
305
      }
890
151
      property = mxModuleInitialize(module);
891
151
      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
151
      property = mxModuleExecute(module);
899
151
      if (property->kind == XS_REFERENCE_KIND) {
900
151
        property = property->value.reference->next;
901
151
        if ((property->kind == XS_CODE_KIND) || (property->kind == XS_CODE_X_KIND))
902
103
          property->value.code.closures = closures;
903
48
        else if (property->kind == XS_CALLBACK_KIND)
904
48
          property->value.callback.closures = closures;
905
151
      }
906
151
      mxPop();
907
151
      if (count > 0) {
908
51
        txSlot* instance = fxNewInstance(the);
909
51
        transfer = mxModuleTransfers(module)->value.reference->next;
910
228
        while (transfer) {
911
177
          from = mxTransferFrom(transfer);
912
177
          if (from->kind != XS_NULL_KIND) {
913
101
            txSlot** address = &(instance->next);
914
101
            txSlot* slot;
915
115
            while ((slot = *address)) {
916
55
              if (slot->value.reference == from->value.reference)
917
41
                break;
918
14
              address = &slot->next;
919
14
            }
920
101
            if (!slot)
921
60
              slot = *address = fxDuplicateSlot(the, from);
922
101
          }
923
177
          transfer = transfer->next;
924
177
        }
925
51
        mxModuleTransfers(module)->value.reference = instance;
926
51
        mxPop();
927
51
      }
928
100
      else
929
100
        mxModuleTransfers(module)->kind = XS_NULL_KIND;
930
151
    }
931
293
    module = module->next;
932
293
  }
933
934
245
  module = queue->next;
935
538
  while (module) {
936
293
    if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) {
937
151
      mxModuleStatus(module) = XS_MODULE_STATUS_LINKED;
938
151
      property = mxModuleInitialize(module);
939
151
      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
151
    }
951
293
    module = module->next;
952
293
  }
953
245
}
954
955
void fxLinkNamespace(txMachine* the, txSlot* module, txSlot* transfer)
956
24
{
957
24
  txSlot* export = mxTransferClosure(transfer);
958
24
  mxCheck(the, export->kind == XS_EXPORT_KIND);
959
24
  export->value.export.closure = fxDuplicateSlot(the, module);
960
24
  export->value.export.closure->ID = XS_NO_ID;
961
24
}
962
963
void fxLinkTransfer(txMachine* the, txSlot* module, txID importID, txSlot* transfer)
964
91
{
965
91
  txSlot* export;
966
91
  txSlot* exportClosure;
967
91
  txSlot* transferClosure;
968
91
  txSlot* from;
969
91
  txSlot* import;
970
  
971
91
  export = mxBehaviorGetProperty(the, mxModuleExports(module)->value.reference, importID, 0, XS_OWN);
972
91
  if (export) {
973
72
    if (export->kind == XS_EXPORT_KIND) {
974
72
      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
72
      transferClosure = mxTransferClosure(transfer);
988
72
      transferClosure->value = export->value;
989
72
      transferClosure->kind = export->kind;
990
72
    }
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
72
  }
1020
19
  else {
1021
19
    txString path = C_NULL;
1022
19
    txInteger line = 0;
1023
19
  #ifdef mxDebug
1024
19
    txSlot* slot = mxTransferClosure(transfer)->next;
1025
19
    if (slot) {
1026
0
      path = slot->value.string;
1027
0
      line = slot->next->value.integer;
1028
0
    }
1029
19
  #endif  
1030
19
    fxIDToString(the, importID, the->nameBuffer, sizeof(the->nameBuffer));
1031
19
    fxThrowMessage(the, path, line, XS_SYNTAX_ERROR, "import %s not found", the->nameBuffer);
1032
19
  }
1033
91
}
1034
1035
void fxLoadModulesPromise(txMachine* the, txSlot* queue, txSlot* module, txSlot* promise, txCallback fulfilled, txCallback rejected)
1036
19
{
1037
19
  txSlot* function;
1038
19
  txSlot* home;
1039
19
  txSlot* resolveLoadFunction;
1040
19
  txSlot* rejectLoadFunction;
1041
1042
19
  mxPushUndefined();
1043
19
  mxPush(mxPromiseConstructor);
1044
19
  mxPushSlot(promise);
1045
19
  fx_Promise_resolveAux(the);
1046
19
  mxPop();
1047
19
  mxPop();
1048
19
  promise = the->stack;
1049
1050
19
  function = fxNewHostFunction(the, fulfilled, 1, XS_NO_ID, mxLoadModulesFulfilledProfileID);
1051
19
  home = mxFunctionInstanceHome(function);
1052
19
  home->value.home.object = queue;
1053
19
  home->value.home.module = module->value.reference;
1054
19
  resolveLoadFunction = the->stack;
1055
1056
19
  function = fxNewHostFunction(the, rejected, 1, XS_NO_ID, mxLoadModulesRejectedProfileID);
1057
19
  home = mxFunctionInstanceHome(function);
1058
19
  home->value.home.object = queue;
1059
19
  home->value.home.module = module->value.reference;
1060
19
  rejectLoadFunction = the->stack;
1061
1062
19
  fxPromiseThen(the, promise->value.reference, resolveLoadFunction, rejectLoadFunction, C_NULL, C_NULL);
1063
  
1064
19
  mxPop();
1065
19
  mxPop();
1066
19
}
1067
1068
void fxLoadModules(txMachine* the, txSlot* queue)
1069
269
{
1070
269
  txSlot* module = queue->next;
1071
269
  txBoolean done = 1;
1072
269
  if (queue->flag & XS_LEVEL_FLAG)
1073
0
    return;
1074
269
  queue->flag |= XS_LEVEL_FLAG;
1075
269
  mxReportModuleQueue("LOAD");
1076
963
  while (module) {
1077
832
    if (mxModuleStatus(module) == XS_MODULE_STATUS_NEW) {
1078
368
      txSlot* loader = mxModuleLoader(module);
1079
368
      txID moduleID = loader->value.module.id;
1080
368
      txSlot* realm = loader->value.module.realm;
1081
368
      mxTry(the) {
1082
368
        if (fxMapModule(the, realm, moduleID, module, queue, C_NULL)) {
1083
178
          module = queue;
1084
178
          done = 0;
1085
178
        }
1086
190
        else {
1087
190
          txSlot* loadHook = mxLoadHook(realm);
1088
190
          mxModuleStatus(module) = XS_MODULE_STATUS_LOADING;
1089
190
          if (mxIsUndefined(loadHook)) {
1090
138
            if (realm != mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm)
1091
65
              mxTypeError("no loadHook");
1092
73
            fxLoadModule(the, module, moduleID);
1093
73
            if (mxModuleExecute(module)->kind == XS_NULL_KIND)
1094
73
              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
52
          else {
1101
52
            done = 0;
1102
52
            mxModuleStatus(module) = XS_MODULE_STATUS_LOADING;
1103
            
1104
52
            mxPushUndefined();
1105
52
            mxPushSlot(loadHook);
1106
52
            mxCall();
1107
52
            fxPushKeyString(the, moduleID, C_NULL);
1108
52
            fxPushModuleOptions(the, loader->flag);
1109
52
            mxRunCount(2);
1110
            
1111
52
            fxLoadModulesPromise(the, queue, module, the->stack, fxLoadModulesFulfilled, fxLoadModulesRejected);
1112
1113
52
            mxPop();
1114
52
          }
1115
190
        }
1116
368
      }
1117
230
      mxCatch(the) {
1118
171
        mxPush(mxException);
1119
171
        mxException = mxUndefined;
1120
171
        fxCompleteModule(the, module->value.reference, the->stack);
1121
171
        fxRunImportRejected(the, module->value.reference, module->value.reference);
1122
171
      }
1123
368
    }
1124
464
    else if (mxModuleStatus(module) == XS_MODULE_STATUS_LOADING) {
1125
13
      done = 0;
1126
13
    }
1127
451
    else if (mxModuleStatus(module) == XS_MODULE_STATUS_LOADED) {
1128
149
      mxTry(the) {
1129
149
      #if mxModuleStuff
1130
149
        if (!fxLoadModuleStuffFrom(the, queue, module->value.reference, 0))
1131
149
      #endif
1132
149
          fxLoadModulesFrom(the, queue, module->value.reference, 0);
1133
149
        mxModuleStatus(module) = XS_MODULE_STATUS_LINKING;
1134
149
        module = queue;
1135
149
        done = 1;
1136
149
      }
1137
149
      mxCatch(the) {
1138
10
        mxPush(mxException);
1139
10
        mxException = mxUndefined;
1140
10
        fxCompleteModule(the, module->value.reference, the->stack);
1141
10
        fxRunImportRejected(the, module->value.reference, module->value.reference);
1142
10
      }
1143
149
    }
1144
694
    module = module->next;
1145
694
  }
1146
131
  queue->flag &= ~XS_LEVEL_FLAG;
1147
211
  if (done) {
1148
211
    mxTry(the) {
1149
211
      fxLinkModules(the, queue);
1150
211
    }
1151
211
    mxCatch(the) {
1152
18
      mxPush(mxException);
1153
18
      mxException = mxUndefined;
1154
18
      module = queue->next;
1155
77
      while (module) {
1156
59
        if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) {
1157
26
          fxCompleteModule(the, module->value.reference, the->stack);
1158
26
          fxRunImportRejected(the, module->value.reference, module->value.reference);
1159
26
        }
1160
59
        module = module->next;
1161
59
      }
1162
18
      mxPop();
1163
18
    }
1164
211
    fxExecuteModules(the, queue);
1165
211
  }
1166
131
}
1167
1168
void fxLoadModulesFrom(txMachine* the, txSlot* queue, txSlot* module, txBoolean now)
1169
190
{
1170
190
  txSlot* internal = mxModuleInstanceInternal(module);
1171
190
  txID moduleID = internal->value.module.id;
1172
190
  txSlot* realm = internal->value.module.realm;
1173
190
  txSlot* transfer = mxModuleInstanceTransfers(module)->value.reference->next;
1174
190
  txSlot* already = the->stack;
1175
635
  while (transfer) {
1176
445
    txSlot* from = mxTransferFrom(transfer);
1177
445
    if (from->kind != XS_NULL_KIND) {
1178
176
      txID importModuleID = XS_NO_ID;
1179
176
      txSlot* importModule;
1180
176
      txID status;
1181
176
      txSlot* former = the->stack;
1182
241
      while (former < already) {
1183
125
        if (!c_strcmp(former->value.string, from->value.string)) {
1184
60
          importModuleID = former->ID;
1185
60
          break;
1186
60
        }
1187
65
        former++;
1188
65
      }
1189
176
      if (importModuleID == XS_NO_ID) {
1190
116
        mxPushSlot(from);
1191
116
        importModuleID = fxResolveSpecifier(the, realm, moduleID, from);
1192
116
        the->stack->ID = importModuleID;
1193
116
      }
1194
176
      importModule = fxGetModule(the, realm, importModuleID, from->flag & XS_JSON_MODULE_FLAG);
1195
176
      if (!importModule) {
1196
105
        importModule = mxBehaviorSetProperty(the, mxOwnModules(realm)->value.reference, importModuleID, 0, XS_OWN);
1197
105
        fxNewModule(the, realm, importModuleID, from->flag & XS_JSON_MODULE_FLAG, importModule);
1198
105
      }
1199
176
      from->kind = XS_REFERENCE_KIND;
1200
176
      from->value.reference = importModule->value.reference;
1201
176
      status = mxModuleStatus(importModule);
1202
176
      if ((status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADED)) {
1203
166
        fxQueueModule(the, queue, importModule);
1204
166
      }
1205
10
      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
176
    }
1226
445
    transfer = transfer->next;
1227
445
  }
1228
190
  the->stack = already;
1229
190
}
1230
1231
void fxLoadModulesFulfilled(txMachine* the)
1232
2
{
1233
2
  txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference);
1234
2
  txSlot* queue = home->value.home.object;
1235
2
  txSlot* module = home->value.home.module;
1236
2
  txSlot* internal = mxModuleInstanceInternal(module);
1237
2
  txSlot* realm = internal->value.module.realm;
1238
2
  txID moduleID = internal->value.module.id;
1239
2
  mxTry(the) {
1240
2
    mxPushReference(module);
1241
2
    fxMapModuleDescriptor(the, realm, moduleID, the->stack, queue, C_NULL, mxArgv(0));
1242
2
    mxPop(); // module
1243
2
  }
1244
2
  mxCatch(the) {
1245
1
    mxPush(mxException);
1246
1
    mxException = mxUndefined;
1247
1
    fxCompleteModule(the, module, the->stack);
1248
1
    fxRunImportRejected(the, module, module);
1249
1
    mxPop();
1250
1
  }
1251
2
  fxLoadModules(the, queue);
1252
2
}
1253
1254
void fxLoadModulesRejected(txMachine* the)
1255
0
{
1256
0
  txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference);
1257
0
  txSlot* queue = home->value.home.object;
1258
0
  txSlot* module = home->value.home.module;
1259
0
  fxCompleteModule(the, module, mxArgv(0));
1260
0
  fxRunImportRejected(the, module, module);
1261
0
  fxLoadModules(the, queue);
1262
0
}
1263
1264
void fxLoadVirtualModuleNamespace(txMachine* the, txSlot* object, txSlot* module)
1265
14
{
1266
14
  txSlot* exports = fxNewInstance(the);
1267
14
  txSlot* export = exports;
1268
14
  txSlot* at;
1269
14
  txSlot* property;
1270
14
  at = fxNewInstance(the);
1271
14
  mxBehaviorOwnKeys(the, object, XS_EACH_NAME_FLAG, at);
1272
14
  mxTemporary(property);
1273
56
  while ((at = at->next)) {
1274
42
    if (at->value.at.id != XS_NO_ID) {
1275
37
      if (mxBehaviorGetOwnProperty(the, object, at->value.at.id, at->value.at.index, property) && !(property->flag & XS_DONT_ENUM_FLAG)) {
1276
23
        mxPushReference(object);
1277
23
        mxGetAll(at->value.at.id, at->value.at.index);
1278
23
        export = export->next = fxNewSlot(the);
1279
23
        export->ID = at->value.at.id;
1280
23
        export->value.export.closure = fxNewSlot(the);
1281
23
        export->value.export.closure->kind = the->stack->kind;
1282
23
        export->value.export.closure->value = the->stack->value;
1283
23
        export->value.export.module = module;
1284
23
        export->kind = XS_EXPORT_KIND;
1285
23
        mxPop();
1286
23
      }
1287
37
    }
1288
42
  }
1289
14
  mxPop();
1290
14
  mxPop();
1291
14
  mxPullSlot(mxModuleInstanceExports(module));
1292
14
}
1293
1294
void fxLoadVirtualModuleSource(txMachine* the, txSlot* record, txSlot* instance)
1295
70
{
1296
70
  txSlot* slot;
1297
70
  txSlot* function;
1298
70
  txSlot* property;
1299
70
  txSlot* transfers;
1300
70
  txSlot* transfer;
1301
  
1302
70
  mxPushSlot(record);
1303
70
  mxGetID(fxID(the, "execute"));
1304
70
  slot = the->stack;
1305
70
  if (!mxIsUndefined(slot)) {
1306
63
    if (!fxIsCallable(the, slot))
1307
0
      mxTypeError("execute: not a function");
1308
63
  }
1309
70
  function = fxNewHostFunction(the, fxExecuteVirtualModuleSource, 0, XS_NO_ID, mxExecuteVirtualModuleSourceProfileID);
1310
70
  property = mxFunctionInstanceHome(function);
1311
70
  property->value.home.object = fxToInstance(the, record);
1312
70
  property->value.home.module = instance;
1313
70
  property = fxLastProperty(the, function);
1314
70
  property = fxNextSlotProperty(the, property, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1315
70
  mxPullSlot(mxModuleInstanceExecute(instance));
1316
70
  mxPop(); // initialize
1317
      
1318
70
  mxPush(mxObjectPrototype);
1319
70
  transfers = fxNewObjectInstance(the);
1320
70
  transfer = fxLastProperty(the, transfers);
1321
  
1322
70
  mxPushSlot(record);
1323
70
  mxGetID(mxID(_bindings));
1324
70
  if (!mxIsUndefined(the->stack)) {
1325
50
    txSlot* array;
1326
50
    txInteger length, index;
1327
    
1328
50
    array = the->stack;
1329
50
    mxPushSlot(array);
1330
50
    mxGetID(mxID(_length));
1331
50
    length = fxToInteger(the, the->stack);
1332
50
    mxPop();
1333
    
1334
311
    for (index = 0; index < length; index++) {
1335
271
      txSlot* item;
1336
271
      txSlot* temporary;
1337
271
      txInteger from = 0;
1338
271
      txInteger export = 0;
1339
271
      txInteger import = 0;
1340
271
      txID nameID = 0, asID;
1341
271
      txSlot* specifier = C_NULL;
1342
271
      txSlot* former;
1343
1344
271
      mxPushSlot(array);
1345
271
      mxGetIndex(index);
1346
271
      item = the->stack;
1347
    
1348
271
      mxTemporary(temporary);
1349
    
1350
271
      mxPushSlot(item);
1351
271
      mxGetID(mxID(_from));
1352
271
      if (!mxIsUndefined(the->stack)) {
1353
93
        from++;
1354
93
        fxToString(the, the->stack);
1355
93
        mxPullSlot(temporary);
1356
93
        specifier = temporary;
1357
93
      }
1358
178
      else
1359
178
        mxPop();
1360
        
1361
271
      mxPushSlot(item);
1362
271
      mxGetID(fxID(the, "exportAllFrom"));
1363
271
      if (!mxIsUndefined(the->stack)) {
1364
37
        from++;
1365
37
        export++;
1366
37
        fxToString(the, the->stack);
1367
37
        mxPullSlot(temporary);
1368
37
        specifier = temporary;
1369
37
        nameID = XS_NO_ID;
1370
37
      }
1371
234
      else
1372
234
        mxPop();
1373
    
1374
271
      mxPushSlot(item);
1375
271
      mxGetID(fxID(the, "importAllFrom"));
1376
271
      if (!mxIsUndefined(the->stack)) {
1377
24
        from++;
1378
24
        import++;
1379
24
        fxToString(the, the->stack);
1380
24
        mxPullSlot(temporary);
1381
24
        specifier = temporary;
1382
24
        nameID = XS_NO_ID;
1383
24
      }
1384
247
      else
1385
247
        mxPop();
1386
    
1387
271
      mxPushSlot(item);
1388
271
      mxGetID(mxID(_export));
1389
271
      if (!mxIsUndefined(the->stack)) {
1390
155
        export++;
1391
155
        nameID = fxToID(the, the->stack);
1392
155
      }
1393
271
      mxPop();
1394
      
1395
271
      mxPushSlot(item);
1396
271
      mxGetID(mxID(_import));
1397
271
      if (!mxIsUndefined(the->stack)) {
1398
52
        import++;
1399
52
        nameID = fxToID(the, the->stack);
1400
52
      }
1401
271
      mxPop();
1402
    
1403
271
      mxPushSlot(item);
1404
271
      mxGetID(mxID(_as));
1405
271
      if (!mxIsUndefined(the->stack)) {
1406
123
        asID = fxToID(the, the->stack);
1407
123
      }
1408
148
      else
1409
148
        asID = nameID;
1410
271
      mxPop();
1411
        
1412
271
      if (from > 1)
1413
0
        mxSyntaxError("too many from");
1414
271
      else if (export > 1)
1415
0
        mxSyntaxError("too many export");
1416
271
      else if (import > 1)
1417
0
        mxSyntaxError("too many import");
1418
271
      else if (export && import)
1419
1
        mxSyntaxError("export and import");
1420
270
      else if (!export && !import)
1421
4
        mxSyntaxError("neither export nor import");
1422
      
1423
266
      if (export) {
1424
191
        if (asID != XS_NO_ID) {
1425
172
          former = transfers->next;
1426
536
          while (former) {
1427
365
            txSlot* aliases = mxTransferAliases(former);
1428
365
            if (!mxIsNull(aliases)) {
1429
272
              txSlot* alias = aliases->value.reference->next;
1430
563
              while (alias) {
1431
292
                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
291
                alias = alias->next;
1436
291
              }
1437
272
            }
1438
364
            former = former->next;
1439
364
          }
1440
171
          if (specifier) {
1441
59
            former = transfers->next;
1442
283
            while (former) {
1443
225
              txSlot* aliases = mxTransferAliases(former);
1444
225
              if (!mxIsNull(aliases)) {
1445
160
                txSlot* local = mxTransferLocal(former);
1446
160
                if (mxIsNull(local)) {
1447
35
                  txSlot* from = mxTransferFrom(former);
1448
35
                  if (!mxIsNull(from) && !c_strcmp(from->value.string, specifier->value.string)) {
1449
21
                    txSlot* import = mxTransferImport(former);
1450
21
                    if (mxIsNull(import)) {
1451
0
                      if (nameID == XS_NO_ID) 
1452
0
                        break;
1453
0
                    }
1454
21
                    else {
1455
21
                      if (nameID == import->value.symbol)
1456
1
                        break;
1457
21
                    }
1458
21
                  }
1459
35
                }
1460
160
              }
1461
224
              former = former->next;
1462
224
            }
1463
59
          }
1464
112
          else {
1465
112
            former = transfers->next;
1466
236
            while (former) {
1467
136
              txSlot* local = mxTransferLocal(former);
1468
136
              if ((local->kind == XS_SYMBOL_KIND) && (local->value.symbol == nameID))
1469
12
                break;
1470
124
              former = former->next;
1471
124
            }
1472
112
          }
1473
171
          if (former) {
1474
13
            txSlot* aliases = mxTransferAliases(former);
1475
13
            txSlot* alias;
1476
13
            if (mxIsNull(aliases)) {
1477
1
              mxPush(mxObjectPrototype);
1478
1
              alias = fxLastProperty(the, fxNewObjectInstance(the));
1479
1
              mxPullSlot(mxTransferAliases(former));
1480
1
            }
1481
12
            else {
1482
12
              alias = fxLastProperty(the, aliases->value.reference);
1483
12
            }
1484
13
            fxNextSymbolProperty(the, alias, asID, XS_NO_ID, XS_DONT_ENUM_FLAG);
1485
13
          }
1486
158
          else if (specifier) {
1487
58
            mxPushNull();
1488
58
            mxPushSlot(specifier);
1489
58
            if ((nameID != XS_NO_ID) || (asID != XS_NO_ID)) {
1490
58
              if (nameID != XS_NO_ID) 
1491
40
                mxPushSymbol(nameID);
1492
18
              else
1493
18
                mxPushNull();
1494
58
              if (asID != XS_NO_ID) 
1495
58
                mxPushSymbol(asID);
1496
0
              else      
1497
0
                mxPushSymbol(nameID);
1498
58
              mxPushInteger(4);
1499
58
            }
1500
0
            else { 
1501
0
              mxPushNull();
1502
0
              mxPushInteger(3);
1503
0
            }
1504
58
            fxPrepareTransfer(the, XS_NO_FLAG);
1505
58
            transfer = fxNextSlotProperty(the, transfer, the->stack, XS_NO_ID, XS_DONT_ENUM_FLAG);
1506
58
            mxPop(); // transfer
1507
58
          }
1508
100
          else {
1509
100
            mxPushSymbol(nameID);
1510
100
            mxPushNull();
1511
100
            mxPushNull();
1512
100
            mxPushSymbol(asID);
1513
100
            mxPushInteger(4);
1514
100
            fxPrepareTransfer(the, XS_NO_FLAG);
1515
100
            transfer = fxNextSlotProperty(the, transfer, the->stack, XS_NO_ID, XS_DONT_ENUM_FLAG);
1516
100
            mxPop(); // transfer
1517
100
          }
1518
171
        }
1519
19
        else if (specifier) {
1520
19
          former = transfers->next;
1521
109
          while (former) {
1522
91
            txSlot* from = mxTransferFrom(former);
1523
91
            if (!mxIsNull(from) && !c_strcmp(from->value.string, specifier->value.string)) {
1524
17
              txSlot* local = mxTransferLocal(former);
1525
17
              if (mxIsNull(local)) {
1526
7
                txSlot* import = mxTransferImport(former);
1527
7
                if (mxIsNull(import)) {
1528
3
                  txSlot* aliases = mxTransferAliases(former);
1529
3
                  if (mxIsNull(aliases)) {
1530
1
                    mxSyntaxError("duplicate export *");
1531
1
                  }
1532
3
                }
1533
7
              }
1534
17
            }
1535
90
            former = former->next;
1536
90
          }
1537
18
          mxPushNull();
1538
18
          mxPushSlot(specifier);
1539
18
          mxPushNull();
1540
18
          mxPushInteger(3);
1541
18
          fxPrepareTransfer(the, XS_NO_FLAG);
1542
18
          transfer = fxNextSlotProperty(the, transfer, the->stack, XS_NO_ID, XS_DONT_ENUM_FLAG);
1543
18
          mxPop(); // transfer
1544
18
        }
1545
0
        else
1546
0
          mxSyntaxError("invalid export *");
1547
191
      }
1548
75
      else {
1549
75
        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
74
        else if (asID == XS_NO_ID)
1558
1
          mxSyntaxError("invalid import * from %s", specifier->value.string);
1559
      
1560
73
        former = transfers->next;
1561
304
        while (former) {
1562
234
          txSlot* local = mxTransferLocal(former);
1563
234
          if ((local->kind == XS_SYMBOL_KIND) && (local->value.symbol == asID)) {
1564
3
            txSlot* from = mxTransferFrom(former);
1565
3
            if (!mxIsNull(from)) {
1566
1
              fxIDToString(the, asID, the->nameBuffer, sizeof(the->nameBuffer));
1567
1
              mxSyntaxError("duplicate import %s", the->nameBuffer);
1568
1
            }
1569
2
            break;
1570
3
          }
1571
231
          former = former->next;
1572
231
        }
1573
72
        if (former) {
1574
2
          txSlot* from = mxTransferFrom(former);
1575
2
          mxPushSlot(specifier);
1576
2
          mxPullSlot(from); 
1577
2
          if (nameID != XS_NO_ID) {
1578
2
            txSlot* import = mxTransferImport(former);
1579
2
            import->kind = XS_SYMBOL_KIND;
1580
2
            import->value.symbol = nameID;
1581
2
          }
1582
2
        }
1583
70
        else {
1584
70
          mxPushSymbol(asID);
1585
70
          mxPushSlot(specifier);
1586
70
          if (nameID != XS_NO_ID)
1587
47
            mxPushSymbol(nameID);
1588
23
          else      
1589
23
            mxPushNull();
1590
70
          mxPushInteger(3);
1591
70
          fxPrepareTransfer(the, XS_NO_FLAG);
1592
70
          transfer = fxNextSlotProperty(the, transfer, the->stack, XS_NO_ID, XS_DONT_ENUM_FLAG);
1593
70
          mxPop(); // transfer
1594
70
        }
1595
72
      }  
1596
1597
261
      mxPop(); // temporary
1598
261
      mxPop(); // item
1599
261
    }
1600
50
  }
1601
60
  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
60
  mxPullSlot(mxModuleInstanceTransfers(instance));
1639
1640
60
  mxPushSlot(record);
1641
60
  mxGetID(mxID(_needsImport));
1642
60
  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
60
  mxPop(); // needsImport
1649
  
1650
60
  mxPushSlot(record);
1651
60
  mxGetID(mxID(_needsImportMeta));
1652
60
  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
60
  mxPop(); // _needsImportMeta
1659
60
}
1660
1661
txBoolean fxMapModule(txMachine* the, txSlot* realm, txID moduleID, txSlot* module, txSlot* queue, txSlot* result)
1662
452
{
1663
452
  txSlot* moduleMap = mxModuleMap(realm);
1664
452
  txSlot* descriptor = moduleMap->value.reference->next;
1665
721
  while (descriptor) {
1666
521
    if (descriptor->ID == moduleID) {
1667
252
      fxMapModuleDescriptor(the, realm, moduleID, module, queue, result,descriptor);
1668
252
      return 1;
1669
252
    }
1670
269
    descriptor = descriptor->next;
1671
269
  }
1672
200
  return 0;
1673
452
}
1674
1675
void fxMapModuleDescriptor(txMachine* the, txSlot* realm, txID moduleID, txSlot* module, txSlot* queue, txSlot* result, txSlot* descriptor)
1676
278
{
1677
278
  txSlot* property;
1678
278
  if (!mxIsReference(descriptor))
1679
15
    mxTypeError("descriptor: not an object");
1680
1681
263
  mxPushSlot(descriptor);
1682
263
  mxGetID(fxID(the, "namespace"));
1683
263
  property = the->stack;
1684
263
  if (!mxIsUndefined(property)) {
1685
47
    if ((property->kind == XS_STRING_KIND) || (property->kind == XS_STRING_X_KIND)) {
1686
32
      txSlot* aliasRealm;
1687
32
      txSlot* aliasOwn;
1688
32
      txID aliasModuleID;
1689
32
      txSlot* aliasModule;
1690
32
      mxPushSlot(descriptor);
1691
32
      mxGetID(fxID(the, "compartment"));
1692
32
      if (!mxIsUndefined(the->stack)) {
1693
27
        txSlot* program = fxCheckCompartmentInstance(the, the->stack);
1694
27
        aliasRealm = mxModuleInstanceInternal(program)->value.module.realm;
1695
27
      }
1696
5
      else {
1697
5
        aliasRealm = mxRealmParent(realm)->value.reference;
1698
5
      }
1699
32
      aliasOwn = mxOwnModules(aliasRealm)->value.reference;
1700
32
      mxPop();
1701
32
      aliasModuleID = fxResolveSpecifier(the, aliasRealm, XS_NO_ID, property);
1702
  //       if ((aliasRealm == realm) && (aliasModuleID == moduleID))
1703
  //         mxTypeError("descriptor.specifier is circular");
1704
      
1705
32
      aliasModule = mxBehaviorGetProperty(the, aliasOwn, aliasModuleID, 0, XS_ANY);
1706
32
      if (aliasModule) {
1707
18
        property = aliasModule;
1708
18
      }
1709
14
      else {
1710
14
        property = mxBehaviorSetProperty(the, aliasOwn, aliasModuleID, 0, XS_OWN);
1711
14
        fxNewModule(the, aliasRealm, aliasModuleID, XS_NO_FLAG, property);
1712
14
      }
1713
32
      goto namespace;
1714
32
    }
1715
15
    else {
1716
15
      txSlot* instance = module->value.reference;
1717
15
      if (!mxIsReference(property))
1718
1
        mxTypeError("descriptor.namespace: not an object");
1719
14
      if (mxIsModule(property->value.reference))
1720
0
        goto namespace;
1721
14
      fxLoadVirtualModuleNamespace(the, property->value.reference, instance);
1722
14
      txID status = mxModuleInstanceStatus(instance);
1723
14
      if ((status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADING)) {
1724
12
        mxModuleInstanceStatus(instance) = XS_MODULE_STATUS_EXECUTED;
1725
12
        if (result) {
1726
      
1727
0
        }
1728
12
        else {
1729
12
          fxCompleteModule(the, instance, C_NULL);
1730
12
          fxRunImportFulfilled(the, instance, instance);
1731
12
        }
1732
12
      }
1733
14
      goto done;
1734
14
    }
1735
    
1736
31
namespace:
1737
31
    if (module->kind == XS_UNDEFINED_KIND) {
1738
0
      module->kind = property->kind;
1739
0
      module->value = property->value;
1740
0
    }
1741
31
    else {
1742
31
      txID status = mxModuleStatus(module);
1743
31
      mxCheck(the, (status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADING));
1744
31
      mxPushSlot(module);
1745
31
      realm = mxModuleInternal(module)->value.module.realm;
1746
31
      fxOverrideModule(the, queue, mxOwnModules(realm), result, module->value.reference, property->value.reference);
1747
31
      status = mxModuleStatus(property);
1748
31
      if (result) {
1749
17
        if (status == XS_MODULE_STATUS_ERROR) {
1750
3
          mxPushSlot(mxModuleMeta(property));
1751
3
          mxPull(mxException);
1752
3
          fxJump(the);
1753
3
        }
1754
14
        else if (status == XS_MODULE_STATUS_EXECUTED) {
1755
6
        }
1756
8
        else {
1757
8
          fxQueueModule(the, queue, property);
1758
8
        }
1759
17
      }
1760
14
      else {
1761
14
        if (status == XS_MODULE_STATUS_ERROR) {
1762
5
          fxCompleteModule(the, module->value.reference, C_NULL);
1763
5
          fxRunImportRejected(the, module->value.reference, property->value.reference);
1764
5
        }
1765
9
        else if (status == XS_MODULE_STATUS_EXECUTED) {
1766
4
          fxCompleteModule(the, module->value.reference, C_NULL);
1767
4
          fxRunImportFulfilled(the, module->value.reference, property->value.reference);
1768
4
        }
1769
5
        else {
1770
5
          txSlot* srcSlot = mxModuleFulfill(module);
1771
5
          txSlot* dstSlot = fxLastProperty(the, property->value.reference);
1772
15
          while (srcSlot) {
1773
10
            dstSlot = fxNextSlotProperty(the, dstSlot, srcSlot, XS_NO_ID, XS_NO_FLAG);
1774
10
            srcSlot = srcSlot->next;
1775
10
          }
1776
5
          fxQueueModule(the, queue, property);
1777
5
        }
1778
14
      }
1779
28
      mxPop();
1780
28
    }
1781
28
    goto done;
1782
31
  }
1783
216
  mxPop(); // property;
1784
1785
216
  if (module->kind == XS_UNDEFINED_KIND)
1786
0
    fxNewModule(the, realm, moduleID, XS_NO_FLAG, module);
1787
216
  else {
1788
216
    txID status = mxModuleStatus(module);
1789
216
    mxCheck(the, (status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADING));
1790
216
  }
1791
  
1792
216
  mxPushSlot(descriptor);
1793
216
  mxGetID(fxID(the, "archive"));
1794
216
  property = the->stack;
1795
216
  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
216
  mxPop(); // property;
1831
  
1832
216
  mxPushSlot(descriptor);
1833
216
  mxGetID(fxID(the, "source"));
1834
216
  property = the->stack;
1835
216
  if (!mxIsUndefined(property)) {
1836
214
    if ((property->kind == XS_STRING_KIND) || (property->kind == XS_STRING_X_KIND)) {
1837
9
      txSlot* loader = mxModuleLoader(module);
1838
9
      loader->value.module.realm = mxRealmParent(realm)->value.reference;
1839
9
      if (property->kind == XS_STRING_X_KIND)
1840
0
        loader->value.module.id = fxNewNameX(the, property->value.string);
1841
9
      else
1842
9
        loader->value.module.id = fxNewName(the, property);
1843
9
      mxModuleStatus(module) = XS_MODULE_STATUS_NEW;
1844
9
      goto done;
1845
9
    }
1846
205
    if (!mxIsReference(property))
1847
3
      mxTypeError("descriptor.source: not an object");
1848
202
    if (mxIsModuleSource(property->value.reference))
1849
132
      fxDuplicateModuleTransfers(the, property, module);
1850
70
    else
1851
//      mxTypeError("descriptor.source is object");
1852
70
      fxLoadVirtualModuleSource(the, property, module->value.reference);
1853
202
    goto importMeta;
1854
205
  }
1855
2
  mxPop(); // property
1856
  
1857
2
  mxTypeError("invalid descriptor");
1858
  
1859
192
importMeta:
1860
192
  mxPop(); // property
1861
192
  mxModuleStatus(module) = XS_MODULE_STATUS_LOADED;
1862
  
1863
192
  mxPushSlot(descriptor);
1864
192
  mxGetID(fxID(the, "importMeta"));
1865
192
  property = the->stack;
1866
192
  if (!mxIsUndefined(property)) {
1867
80
    if (!mxIsReference(property))
1868
2
      mxTypeError("descriptor.importMeta: not an object");
1869
78
    txSlot* meta = mxModuleMeta(module);
1870
78
    if (mxIsNull(meta)) {
1871
78
      txSlot* instance = fxNewInstance(the);
1872
78
      meta->value.reference = instance;
1873
78
      meta->kind = XS_REFERENCE_KIND;
1874
78
    }
1875
78
    meta->value.reference->flag &= ~XS_DONT_PATCH_FLAG;
1876
78
    mxPushUndefined();
1877
78
    mxPush(mxAssignObjectFunction);
1878
78
    mxCall();
1879
78
    mxPushSlot(meta);
1880
78
    mxPushSlot(property);
1881
78
    mxRunCount(2);
1882
78
    mxPop();
1883
78
    meta->value.reference->flag |= XS_DONT_PATCH_FLAG;
1884
78
  }
1885
190
  mxPop(); // property
1886
  
1887
190
  mxPushSlot(descriptor);
1888
190
  mxGetID(fxID(the, "specifier"));
1889
190
  property = the->stack;
1890
190
  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
190
  goto done;
1900
  
1901
239
done:
1902
239
  mxPop(); // property
1903
239
}
1904
1905
1906
void fxNewModule(txMachine* the, txSlot* realm, txID moduleID, txFlag moduleFlag, txSlot* module)
1907
443
{
1908
443
  txSlot* slot;
1909
  
1910
443
  mxPush(mxModulePrototype);
1911
443
  slot = fxNewObjectInstance(the);
1912
443
  slot->flag |= XS_EXOTIC_FLAG | XS_DONT_PATCH_FLAG;
1913
  /* HOST */
1914
443
  slot = slot->next = fxNewSlot(the);
1915
443
  slot->ID = XS_MODULE_BEHAVIOR;
1916
443
  slot->flag = XS_INTERNAL_FLAG | moduleFlag;
1917
443
  slot->kind = XS_MODULE_KIND;
1918
443
  slot->value.module.realm = realm;
1919
443
  slot->value.module.id = moduleID;
1920
  /* EXPORTS */
1921
443
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1922
  /* STUFF */
1923
443
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1924
  /* META */
1925
443
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1926
  /* TRANSFERS */
1927
443
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1928
  /* INITIALIZE */
1929
443
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1930
  /* FUNCTION */
1931
443
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1932
  /* HOSTS */
1933
443
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1934
  /* LOADER */
1935
443
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1936
443
  slot->flag = XS_INTERNAL_FLAG | moduleFlag;
1937
443
  slot->kind = XS_MODULE_KIND;
1938
443
  slot->value.module.realm = realm;
1939
443
  slot->value.module.id = moduleID; 
1940
443
  module->kind = the->stack->kind;
1941
443
  module->value = the->stack->value;
1942
443
  mxPop();
1943
#if mxInstrument
1944
  the->loadedModulesCount++;
1945
#endif
1946
443
}
1947
1948
void fxOrderModule(txMachine* the, txSlot* queue, txSlot* order, txSlot* module)
1949
353
{
1950
353
  txSlot** fromAddress = &(queue->next);
1951
353
  txSlot** toAddress = &(order->next);
1952
353
  txSlot* from;
1953
353
  txSlot* to;
1954
353
  while ((from = *fromAddress)) {
1955
353
    if (from == module) {
1956
353
      *fromAddress = module->next;
1957
353
      module->next = C_NULL;
1958
353
      break;
1959
353
    }
1960
0
    fromAddress = &(from->next);
1961
0
  }
1962
353
  if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) {
1963
178
    txSlot* transfer = mxModuleTransfers(module)->value.reference->next;
1964
604
    while (transfer) {
1965
426
      from = mxTransferFrom(transfer);
1966
426
      if (from->kind != XS_NULL_KIND) {
1967
161
        to = queue->next;
1968
181
        while (to) {
1969
121
          if (to->value.reference == from->value.reference)
1970
101
            break;
1971
20
          to = to->next;
1972
20
        }
1973
161
        if (to)
1974
101
          fxOrderModule(the, queue, order, to);
1975
161
      }
1976
426
      transfer = transfer->next;
1977
426
    }
1978
178
  }
1979
527
  while ((to = *toAddress)) {
1980
174
    if (to->value.reference == module->value.reference)
1981
0
      return;
1982
174
    toAddress = &(to->next);
1983
174
  }
1984
353
  *toAddress = module;
1985
353
}
1986
1987
void fxOverrideModule(txMachine* the, txSlot* queue, txSlot* list, txSlot* result, txSlot* module, txSlot* record)
1988
31
{
1989
31
  txSlot** address = &(queue->next);
1990
31
  txSlot* slot;
1991
72
  while ((slot = *address)) {
1992
41
    if (slot->value.reference == module) {
1993
//       slot->value.reference = record;
1994
31
      *address = slot->next;
1995
31
    }
1996
10
    else {
1997
10
      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
10
    }
2007
41
    address = &(slot->next);
2008
41
  }
2009
31
  slot = list->value.reference->next;
2010
75
  while (slot) {
2011
44
    if (slot->value.reference == module) {
2012
31
      slot->value.reference = record;
2013
31
    }
2014
44
    slot = slot->next;
2015
44
  }
2016
31
  if (result) {
2017
17
    if (result->value.reference == module) {
2018
17
      result->value.reference = record;
2019
17
    }
2020
17
  }
2021
31
}
2022
2023
void fxPrepareModule(txMachine* the, txFlag flag)
2024
221
{
2025
221
  txSlot* module = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.module;
2026
221
  txInteger c = the->stack->value.integer, i;
2027
221
  txSlot* argument = the->stack + c;
2028
221
  txSlot* result = the->stack + c;
2029
221
  txSlot* slot;
2030
221
  txSlot* property;
2031
221
  property = mxModuleInstanceInternal(module); 
2032
221
  fxCheckModuleFlag(the, property->value.module.id, flag, property->flag);
2033
221
  property->flag |= flag;
2034
221
  slot = argument--;
2035
221
  property = mxModuleInstanceInitialize(module); 
2036
221
  property->kind = slot->kind;
2037
221
  property->value = slot->value;
2038
221
  slot = argument--;
2039
221
  property = mxModuleInstanceExecute(module); 
2040
221
  property->kind = slot->kind;
2041
221
  property->value = slot->value;
2042
221
  mxFunctionInstanceCode(slot->value.reference)->ID = mxModuleInstanceInternal(module)->value.module.id;
2043
221
  slot = &mxHosts; 
2044
221
  property = mxModuleInstanceHosts(module); 
2045
221
  property->kind = slot->kind;
2046
221
  property->value = slot->value;
2047
221
  mxPush(mxObjectPrototype);
2048
221
  slot = fxLastProperty(the, fxNewObjectInstance(the));
2049
720
  for (i = 2; i < c; i++)
2050
499
    slot = fxNextSlotProperty(the, slot, argument--, XS_NO_ID, XS_DONT_ENUM_FLAG);
2051
221
  property = mxModuleInstanceTransfers(module); 
2052
221
  mxPullSlot(property);
2053
221
  result->kind = XS_REFERENCE_KIND;
2054
221
  result->value.reference = module;
2055
221
  the->stack = result;
2056
221
}
2057
2058
void fxPrepareTransfer(txMachine* the, txFlag flag)
2059
745
{
2060
745
  txInteger c = the->stack->value.integer, i;
2061
745
  txSlot* argument = the->stack + c;
2062
745
  txSlot* result = the->stack + c;
2063
745
  txSlot* property;
2064
745
  txSlot* slot;
2065
745
  mxPush(mxTransferPrototype);
2066
745
  property = fxNewObjectInstance(the);
2067
745
  property = fxNextSlotProperty(the, property, argument--, mxID(_local), XS_DONT_ENUM_FLAG);
2068
745
  property = fxNextSlotProperty(the, property, argument--, mxID(_from), XS_DONT_ENUM_FLAG | flag);
2069
745
  property = fxNextSlotProperty(the, property, argument--, mxID(_import), XS_DONT_ENUM_FLAG);
2070
745
  if (c > 3) {
2071
528
    mxPush(mxObjectPrototype);
2072
528
    slot = fxLastProperty(the, fxNewObjectInstance(the));
2073
528
    if (argument->kind != XS_NULL_KIND) {
2074
1.05k
      for (i = 3; i < c; i++)
2075
528
        slot = fxNextSlotProperty(the, slot, argument--, XS_NO_ID, XS_DONT_ENUM_FLAG);
2076
524
    }
2077
528
    property = fxNextSlotProperty(the, property, the->stack, mxID(_aliases), XS_DONT_ENUM_FLAG);
2078
528
    mxPop();
2079
528
  }
2080
217
  else {
2081
217
    property = fxNextNullProperty(the, property, mxID(_aliases), XS_DONT_ENUM_FLAG);
2082
217
  }
2083
745
  property = fxNextNullProperty(the, property, mxID(_closure), XS_DONT_ENUM_FLAG);
2084
745
  result->kind = the->stack->kind;
2085
745
  result->value = the->stack->value;
2086
745
  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
745
}
2099
2100
txBoolean fxQueueModule(txMachine* the, txSlot* queue, txSlot* module)
2101
507
{
2102
507
  txSlot** address = &(queue->next);
2103
507
  txSlot* slot;
2104
785
  while ((slot = *address)) {
2105
342
    if (slot->value.reference == module->value.reference)
2106
64
      return 0;
2107
278
    address = &(slot->next);
2108
278
  }
2109
443
  slot = *address = fxNewSlot(the);
2110
443
  slot->ID = mxModuleInternal(module)->value.module.id; //??
2111
443
  slot->kind = XS_REFERENCE_KIND;
2112
443
  slot->value.reference = module->value.reference;
2113
443
  return 1;
2114
507
}
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
19.1k
{
2146
19.1k
  if (moduleID == XS_NO_ID) {
2147
19.0k
    if (realm == mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm) {
2148
18.7k
      moduleID = fxFindModule(the, realm, XS_NO_ID, name);
2149
18.7k
      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
18.7k
    }
2154
310
    else {
2155
310
      if (name->kind == XS_STRING_X_KIND)
2156
0
        moduleID = fxNewNameX(the, name->value.string);
2157
310
      else
2158
310
        moduleID = fxNewName(the, name);
2159
310
    }
2160
19.0k
  }
2161
116
  else {
2162
116
    txSlot* resolveHook = mxResolveHook(realm);
2163
143
    while (mxIsUndefined(resolveHook)) {
2164
54
      txSlot* parent = mxRealmParent(realm);
2165
54
      if (mxIsReference(parent)) {
2166
27
        realm = parent->value.reference;
2167
27
        resolveHook = mxResolveHook(realm);
2168
27
      }
2169
27
      else
2170
27
        break;
2171
54
    }
2172
116
    if (mxIsUndefined(resolveHook)) {
2173
27
      mxCheck(the, realm == mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm);
2174
27
      moduleID = fxFindModule(the, realm, moduleID, name);
2175
27
      if (moduleID == XS_NO_ID) {
2176
2
        fxToStringBuffer(the, name, the->nameBuffer, sizeof(the->nameBuffer));
2177
2
        mxReferenceError("module \"%s\" not found", the->nameBuffer);
2178
2
      }
2179
27
    }
2180
89
    else {
2181
89
      mxPushUndefined();
2182
89
      mxPushSlot(resolveHook);
2183
89
      mxCall();
2184
89
      mxPushSlot(name);
2185
89
      fxPushKeyString(the, moduleID, C_NULL);
2186
89
      mxRunCount(2);
2187
89
      moduleID = fxToID(the, the->stack);
2188
89
      mxPop();
2189
89
    }
2190
116
  }
2191
19.1k
  name->kind = XS_SYMBOL_KIND;
2192
19.1k
  name->value.symbol = moduleID;
2193
19.1k
  return moduleID;
2194
19.1k
}
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
18.9k
{
2207
18.9k
  txSlot* stack = the->stack + 1;
2208
18.9k
  txSlot* promise;
2209
18.9k
  txSlot* fulfillFunction;
2210
18.9k
  txSlot* rejectFunction;
2211
18.9k
  txSlot* module;
2212
18.9k
  txID status;
2213
18.9k
  txSlot* slot;
2214
  
2215
18.9k
  fxBeginHost(the);
2216
18.9k
  mxPush(mxPromisePrototype);
2217
18.9k
  promise = fxNewPromiseInstance(the);
2218
18.9k
  mxPromiseStatus(promise)->value.integer = mxPendingStatus;
2219
18.9k
  fxPushPromiseFunctions(the, promise);
2220
18.9k
  fulfillFunction = the->stack + 1;
2221
18.9k
  rejectFunction = the->stack;
2222
18.9k
  {
2223
18.9k
    mxTry(the) {
2224
18.9k
      module = fxRunImportAux(the, realm, referrer, stack, stack - 1, 0);
2225
18.9k
      status = mxModuleStatus(module);
2226
18.9k
      if (status == XS_MODULE_STATUS_ERROR) {
2227
        /* THIS */
2228
18.7k
        mxPushUndefined();
2229
        /* FUNCTION */
2230
18.7k
        mxPushSlot(rejectFunction);
2231
18.7k
        mxCall();
2232
        /* ARGUMENTS */
2233
18.7k
        mxPushSlot(mxModuleMeta(module));
2234
18.7k
        mxRunCount(1);
2235
18.7k
      }
2236
280
      else if (status == XS_MODULE_STATUS_EXECUTED) {
2237
        /* THIS */
2238
9
        mxPushUndefined();
2239
        /* FUNCTION */
2240
9
        mxPushSlot(fulfillFunction);
2241
9
        mxCall();
2242
        /* ARGUMENTS */
2243
9
        mxPushSlot(module);
2244
9
        mxRunCount(1);
2245
9
      }
2246
271
      else {
2247
271
        txSlot* queue = mxModuleQueue.value.reference;
2248
271
        slot = fxLastProperty(the, module->value.reference);
2249
271
        slot = fxNextSlotProperty(the, slot, fulfillFunction, XS_NO_ID, XS_NO_FLAG);
2250
271
        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
271
          if (fxQueueModule(the, queue, module))
2254
267
            fxLoadModules(the, queue);
2255
//        }
2256
271
      }
2257
18.9k
    }
2258
18.9k
    mxCatch(the) {
2259
1
      fxRejectException(the, rejectFunction);
2260
1
    }
2261
18.9k
  }
2262
18.9k
  fxEndHost(the);
2263
18.9k
  stack->value.reference = promise;
2264
18.9k
  stack->kind = XS_REFERENCE_KIND;
2265
18.9k
  the->stack = stack;
2266
18.9k
}
2267
2268
txSlot* fxRunImportAux(txMachine* the, txSlot* realm, txSlot* referrer, txSlot* specifier, txSlot* options, txBoolean now)
2269
19.0k
{
2270
19.0k
  txSlot* module;
2271
19.0k
  txID moduleID;
2272
19.0k
  txFlag moduleFlag = fxCheckModuleOptions(the, options);
2273
19.0k
#if mxModuleStuff
2274
19.0k
  if (mxIsReference(specifier)) {
2275
4.44k
    txSlot* internal = specifier->value.reference->next;
2276
4.44k
    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.44k
  }
2293
19.0k
#endif
2294
19.0k
  fxToString(the, specifier);
2295
19.0k
  if (referrer) {
2296
18.7k
#if mxModuleStuff
2297
18.7k
    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
18.7k
#endif
2309
18.7k
    moduleID = fxResolveSpecifier(the, realm, mxModuleInstanceInternal(referrer)->value.module.id, specifier);
2310
18.7k
  }
2311
285
  else
2312
285
    moduleID = fxResolveSpecifier(the, realm, XS_NO_ID, specifier);
2313
19.0k
  module = fxGetModule(the, realm, moduleID, moduleFlag);
2314
19.0k
  if (!module) {
2315
325
    module = mxBehaviorSetProperty(the, mxOwnModules(realm)->value.reference, moduleID, 0, XS_OWN);
2316
325
    fxNewModule(the, realm, moduleID, moduleFlag, module);
2317
325
  }
2318
19.0k
  return module;
2319
19.0k
}
2320
2321
void fxRunImportFulfilled(txMachine* the, txSlot* module, txSlot* with)
2322
92
{
2323
92
  if (mxModuleInstanceMeta(module)->next) {
2324
92
    txSlot* stack = the->stack;
2325
92
    txSlot* slot = mxModuleInstanceFulfill(module);
2326
153
    while (slot) {
2327
61
      mxPushSlot(slot);
2328
61
      slot = slot->next;
2329
61
      slot = slot->next;
2330
61
    }
2331
92
    mxModuleInstanceMeta(module)->next = C_NULL;
2332
92
    slot = stack;
2333
153
    while (slot > the->stack) {
2334
61
      slot--;
2335
      /* THIS */
2336
61
      mxPushUndefined();
2337
      /* FUNCTION */
2338
61
      mxPushSlot(slot);
2339
61
      mxCall();
2340
      /* ARGUMENTS */
2341
61
      mxPushReference(with);
2342
61
      mxRunCount(1);
2343
61
      mxPop();
2344
61
    }
2345
92
    the->stack = stack;
2346
92
  }
2347
92
}
2348
2349
void fxRunImportRejected(txMachine* the, txSlot* module, txSlot* with)
2350
242
{
2351
242
  if (mxModuleInstanceMeta(module)->next) {
2352
242
    txSlot* stack = the->stack;
2353
242
    txSlot* slot = mxModuleInstanceFulfill(module);
2354
242
    txSlot* exception;
2355
423
    while (slot) {
2356
181
      slot = slot->next;
2357
181
      mxPushSlot(slot);
2358
181
      slot = slot->next;
2359
181
    }
2360
242
    mxModuleInstanceMeta(module)->next = C_NULL;
2361
242
    exception = mxModuleInstanceMeta(with);
2362
242
    slot = stack;
2363
423
    while (slot > the->stack) {
2364
181
      slot--;
2365
      /* THIS */
2366
181
      mxPushUndefined();
2367
      /* FUNCTION */
2368
181
      mxPushSlot(slot);
2369
181
      mxCall();
2370
      /* ARGUMENTS */
2371
181
      mxPushSlot(exception);
2372
181
      mxRunCount(1);
2373
181
      mxPop();
2374
181
    }
2375
242
    the->stack = stack;
2376
242
  }
2377
242
}
2378
2379
/* META */
2380
2381
void fxRunImportMeta(txMachine* the, txSlot* module)
2382
49
{
2383
49
  txSlot* meta = mxModuleInstanceMeta(module);
2384
49
  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
49
  mxPushSlot(meta);
2409
49
}
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
67
{
2465
67
  txSlot* stack = the->stack + 1;
2466
67
  txSlot* module = fxRunImportAux(the, realm, referrer, stack, stack - 1, 1);
2467
67
  txID status = mxModuleStatus(module);
2468
67
  if ((status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADED)) {
2469
58
    txSlot* result = stack;
2470
58
    txSlot* queue = fxNewInstance(the);
2471
58
    mxTry(the) {
2472
58
      txBoolean done = 1;
2473
58
      result->kind = module->kind;
2474
58
      result->value = module->value;
2475
2476
58
      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
58
      mxReportModuleQueue("LOAD");
2483
58
      module = queue->next;
2484
228
      while (module) {
2485
188
        if (mxModuleStatus(module) == XS_MODULE_STATUS_NEW) {
2486
84
          txSlot* loader = mxModuleLoader(module);
2487
84
          txID moduleID = loader->value.module.id;
2488
84
          txSlot* realm = loader->value.module.realm;
2489
84
          if (!fxMapModule(the, realm, moduleID, module, queue, result)) {
2490
43
            txSlot* loadNowHook = mxLoadNowHook(realm);
2491
43
            if (mxIsUndefined(loadNowHook)) {
2492
18
              if (realm != mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm)
2493
15
                mxTypeError("no loadNowHook");
2494
3
              fxLoadModule(the, module, moduleID);
2495
3
              if (mxModuleExecute(module)->kind == XS_NULL_KIND)
2496
3
                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
43
          }
2514
66
          module = queue;
2515
66
          done = 1;
2516
66
          mxReportModuleQueue("LOAD");
2517
66
        }
2518
104
        else if (mxModuleStatus(module) == XS_MODULE_STATUS_LOADING) {
2519
0
          done = 0;
2520
0
        }
2521
104
        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
170
        module = module->next;
2531
170
      }
2532
40
      if (!done)
2533
0
        mxTypeError("async queue");
2534
40
      fxLinkModules(the, queue);
2535
40
      mxReportModuleQueue("INIT");
2536
40
      module = queue->next;
2537
74
      while (module) {
2538
34
        if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKED) {
2539
34
          mxModuleStatus(module) = XS_MODULE_STATUS_EXECUTING;
2540
34
          if (mxModuleExecute(module)->value.reference->value.instance.prototype == mxAsyncFunctionPrototype.value.reference)
2541
0
            mxTypeError("async module");
2542
34
          mxPushSlot(mxModuleHosts(module));
2543
34
          mxPull(mxHosts);
2544
34
          mxPushUndefined();
2545
34
          mxPushSlot(mxModuleExecute(module));
2546
34
          mxCall();
2547
34
          mxRunCount(0);
2548
34
          mxPop();
2549
34
          fxCompleteModule(the, module->value.reference, C_NULL);
2550
34
          mxModuleMeta(module)->next = C_NULL;
2551
34
          mxPushUndefined();
2552
34
          mxPull(mxHosts);
2553
34
          mxReportModuleQueue("INIT");
2554
34
        }
2555
34
        module = module->next;
2556
34
      }
2557
40
      mxPop();
2558
40
    }
2559
40
    mxCatch(the) {
2560
33
      module = queue->next;
2561
69
      while (module) {
2562
36
        if (mxModuleStatus(module) < XS_MODULE_STATUS_EXECUTED) {
2563
36
          fxCompleteModule(the, module->value.reference, &mxException);
2564
36
          mxModuleMeta(module)->next = C_NULL;
2565
36
        }
2566
36
        module = module->next;
2567
36
      }
2568
33
      mxPushUndefined();
2569
33
      mxPull(mxHosts);
2570
33
      fxJump(the);
2571
33
    }
2572
58
  }
2573
9
  else if (status == XS_MODULE_STATUS_EXECUTED) {
2574
6
    stack->kind = module->kind;
2575
6
    stack->value = module->value;
2576
6
  }
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
13
  the->stack = stack;
2586
13
}
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
111
{
2699
111
  if (id == XS_NO_ID)
2700
0
    return C_NULL;
2701
111
  if (fxIsKeySymbol(the, id)) {
2702
1
    if (id == mxID(_Symbol_toStringTag))
2703
0
      return mxModulePrototype.value.reference->next;
2704
1
  }
2705
//  if (mxModuleInstanceStatus(instance) < XS_MODULE_STATUS_LINKED) {
2706
//    return &mxModuleAccessor;
2707
//  }
2708
//  else
2709
111
  {
2710
111
    txSlot* exports = mxModuleInstanceExports(instance);
2711
111
    if (mxIsReference(exports)) {
2712
111
      txSlot* property = exports->value.reference->next;
2713
304
      while (property) {
2714
216
        if (property->ID == id) {
2715
23
          property = property->value.export.closure;
2716
23
          if (property && (property->kind == XS_UNINITIALIZED_KIND)) {
2717
1
            return &mxModuleAccessor;
2718
1
          }
2719
22
          return property;
2720
23
        }
2721
193
        property = property->next;
2722
193
      }
2723
111
    }
2724
111
  }
2725
88
  return C_NULL;
2726
111
}
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
0
{
2824
0
  return C_NULL;
2825
0
}
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
368
{
2841
368
  if (slot->kind == XS_REFERENCE_KIND) {
2842
367
    txSlot* instance = slot->value.reference;
2843
367
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_PROGRAM_KIND)) {
2844
367
      return instance;
2845
367
    }
2846
367
  }
2847
368
  mxTypeError("this: not a Compartment instance");
2848
0
  return C_NULL;
2849
368
}
2850
2851
void fxPrepareCompartmentFunction(txMachine* the, txSlot* program, txSlot* instance)
2852
1.76k
{
2853
1.76k
  txSlot* property = mxFunctionInstanceHome(instance);
2854
1.76k
  property->value.home.module = program;
2855
1.76k
  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
1.76k
}
2865
2866
void fx_Compartment(txMachine* the)
2867
442
{
2868
442
  txSlot* module = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.module;
2869
442
  txSlot* program = C_NULL;
2870
442
  txSlot* parent;
2871
442
  txSlot* realm;
2872
442
  txSlot* global = C_NULL;
2873
442
  txSlot* closures = C_NULL;
2874
442
  txSlot* slot;
2875
442
  txSlot* target;
2876
442
  txSlot* own;
2877
442
  txInteger id;
2878
  
2879
442
  if (!module) module = mxProgram.value.reference;
2880
442
  mxTry(the) {
2881
442
    if (mxIsUndefined(mxTarget))
2882
1
      mxTypeError("call: Compartment");
2883
      
2884
441
    mxPushSlot(mxTarget);
2885
441
    fxGetPrototypeFromConstructor(the, &mxCompartmentPrototype);
2886
441
    program = fxNewProgramInstance(the);
2887
441
    mxPullSlot(mxResult);
2888
    
2889
    // PARENT
2890
441
    parent = mxModuleInstanceInternal(module)->value.module.realm;
2891
441
    mxPushReference(parent);
2892
    
2893
    // GLOBALS
2894
441
    if (the->sharedMachine == C_NULL) {
2895
441
      txSlot* instance;
2896
441
      txSlot* property;
2897
441
      txSlot* callback;
2898
441
      mxPush(mxObjectPrototype);
2899
  #ifdef mxLink
2900
      global = fxNewObjectInstance(the);
2901
  #else
2902
441
      global = fxNewGlobalInstance(the);
2903
441
  #endif
2904
441
      slot = fxLastProperty(the, global);
2905
441
      if (mxCompartmentGlobal.kind == XS_UNDEFINED_KIND) {
2906
27.3k
        for (id = XS_SYMBOL_ID_COUNT; id < _Infinity; id++)
2907
26.9k
          slot = fxNextSlotProperty(the, slot, &the->stackIntrinsics[-1 - id], mxID(id), XS_DONT_ENUM_FLAG);
2908
1.76k
        for (; id < _Compartment; id++)
2909
1.32k
          slot = fxNextSlotProperty(the, slot, &the->stackIntrinsics[-1 - id], mxID(id), XS_GET_ONLY);
2910
441
      }
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
441
      callback = mxFunctionInstanceCode(mxCompartmentConstructor.value.reference);
2926
441
      instance = fxBuildHostFunction(the, callback->value.callback.address, 1, mxID(_Compartment));
2927
441
      instance->flag |= XS_CAN_CONSTRUCT_FLAG;
2928
441
      property = fxLastProperty(the, instance);
2929
441
      fxNextSlotProperty(the, property, &mxCompartmentPrototype, mxID(_prototype), XS_GET_ONLY);
2930
441
      fxPrepareCompartmentFunction(the, program, instance);
2931
441
      slot = fxNextSlotProperty(the, slot, the->stack, mxID(_Compartment), XS_DONT_ENUM_FLAG);
2932
441
      mxPop();
2933
      
2934
441
      callback = mxFunctionInstanceCode(mxFunctionConstructor.value.reference);
2935
441
      instance = fxBuildHostFunction(the, callback->value.callback.address, 1, mxID(_Function));
2936
441
      instance->flag |= XS_CAN_CONSTRUCT_FLAG;
2937
441
      property = fxLastProperty(the, instance);
2938
441
      fxNextSlotProperty(the, property, &mxFunctionPrototype, mxID(_prototype), XS_GET_ONLY);
2939
441
      fxPrepareCompartmentFunction(the, program, instance);
2940
441
      slot = fxNextSlotProperty(the, slot, the->stack, mxID(_Function), XS_DONT_ENUM_FLAG);
2941
441
      mxPop();
2942
      
2943
441
    #if mxModuleStuff   
2944
441
      callback = mxFunctionInstanceCode(mxModuleStuffConstructor.value.reference);
2945
441
      instance = fxBuildHostFunction(the, callback->value.callback.address, 1, mxID(_ModuleStuff));
2946
441
      instance->flag |= XS_CAN_CONSTRUCT_FLAG;
2947
441
      property = fxLastProperty(the, instance);
2948
441
      fxNextSlotProperty(the, property, &mxModuleStuffPrototype, mxID(_prototype), XS_GET_ONLY);
2949
441
      fxPrepareCompartmentFunction(the, program, instance);
2950
441
      slot = fxNextSlotProperty(the, slot, the->stack, mxID(_ModuleStuff), XS_DONT_ENUM_FLAG);
2951
441
      mxPop();
2952
441
    #endif
2953
      
2954
441
      callback = mxFunctionInstanceCode(mxEvalFunction.value.reference);
2955
441
      instance = fxBuildHostFunction(the, callback->value.callback.address, 1, mxID(_eval));
2956
441
      fxPrepareCompartmentFunction(the, program, instance);
2957
441
      slot = fxNextSlotProperty(the, slot, the->stack, mxID(_eval), XS_DONT_ENUM_FLAG);
2958
441
      mxPop();
2959
441
    }
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
441
    slot = fxNextSlotProperty(the, slot, the->stack, mxID(_global), XS_DONT_ENUM_FLAG);
2973
441
    slot = fxNextSlotProperty(the, slot, the->stack, mxID(_globalThis), XS_DONT_ENUM_FLAG);
2974
    
2975
441
    if (mxArgc > 0) {
2976
417
      if (!mxIsReference(mxArgv(0)))
2977
27
        mxTypeError("options: not an object");
2978
    
2979
390
      mxPushSlot(mxArgv(0));
2980
390
      if (mxHasID(fxID(the, "globals"))) {
2981
26
        mxPushSlot(mxArgv(0));
2982
26
        mxGetID(fxID(the, "globals"));
2983
26
        slot = the->stack;
2984
26
        if (!mxIsReference(slot))
2985
10
          mxTypeError("options.globals: not an object");
2986
16
        mxPushUndefined();
2987
16
        mxPush(mxAssignObjectFunction);
2988
16
        mxCall();
2989
16
        mxPushReference(global);
2990
16
        mxPushSlot(slot);
2991
16
        mxRunCount(2);
2992
16
        mxPop();
2993
16
        mxPop(); // globals
2994
16
      }
2995
      
2996
380
      target = fxNewInstance(the);
2997
380
      own = fxNewInstance(the);
2998
380
      mxPushSlot(mxArgv(0));
2999
380
      if (mxHasID(fxID(the, "modules"))) {
3000
199
        txSlot* source;
3001
199
        txSlot* at;
3002
199
        txSlot* temporary;
3003
199
        mxPushSlot(mxArgv(0));
3004
199
        mxGetID(fxID(the, "modules"));
3005
199
        if (!mxIsReference(the->stack))
3006
18
          mxTypeError("options.modules: not an object");
3007
181
        source = the->stack->value.reference;
3008
181
        at = fxNewInstance(the);
3009
181
        mxBehaviorOwnKeys(the, source, XS_EACH_NAME_FLAG, at);
3010
181
        mxTemporary(temporary);
3011
532
        while ((at = at->next)) {
3012
351
          if (mxBehaviorGetOwnProperty(the, source, at->value.at.id, at->value.at.index, temporary) && !(temporary->flag & XS_DONT_ENUM_FLAG)) {
3013
334
            txSlot* descriptor;
3014
334
            txSlot* property;
3015
334
            mxPushReference(source);
3016
334
            mxGetAll(at->value.at.id, at->value.at.index);
3017
334
            descriptor = the->stack;
3018
334
            property = mxBehaviorSetProperty(the, target, at->value.at.id, at->value.at.index, XS_OWN);
3019
334
            property->kind = descriptor->kind;
3020
334
            property->value = descriptor->value;
3021
334
            mxPop(); // descriptor
3022
334
          }
3023
351
        }
3024
181
        mxPop(); // temporary
3025
181
        mxPop(); // at
3026
181
        mxPop(); // modules
3027
181
      }
3028
      
3029
362
      mxPushUndefined();
3030
362
      closures = fxNewEnvironmentInstance(the, C_NULL);
3031
362
      mxPushSlot(mxArgv(0));
3032
362
      if (mxHasID(fxID(the, "globalLexicals"))) {
3033
42
        txSlot* target = fxLastProperty(the, closures);
3034
42
        txSlot* source;
3035
42
        txSlot* at;
3036
42
        txSlot* property;
3037
42
        mxPushSlot(mxArgv(0));
3038
42
        mxGetID(fxID(the, "globalLexicals"));
3039
42
        if (!mxIsReference(the->stack))
3040
25
          mxTypeError("options.globalLexicals: not an object");
3041
17
        source = the->stack->value.reference;
3042
17
        at = fxNewInstance(the);
3043
17
        mxBehaviorOwnKeys(the, source, XS_EACH_NAME_FLAG, at);
3044
17
        mxTemporary(property);
3045
68
        while ((at = at->next)) {
3046
51
          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
36
            mxPushReference(source);
3048
36
            mxGetAll(at->value.at.id, at->value.at.index);
3049
36
            target = target->next = fxNewSlot(the);
3050
36
            target->value.closure = fxNewSlot(the);;
3051
36
            target->kind = XS_CLOSURE_KIND;
3052
36
            target->ID = at->value.at.id;
3053
36
            if (property->kind == XS_ACCESSOR_KIND)
3054
9
              target->value.closure->flag = property->value.accessor.setter ? XS_NO_FLAG : XS_DONT_SET_FLAG;
3055
27
            else
3056
27
              target->value.closure->flag = property->flag & XS_DONT_SET_FLAG;
3057
36
            target->value.closure->kind = the->stack->kind;
3058
36
            target->value.closure->value = the->stack->value;
3059
36
            mxPop();
3060
36
          }
3061
51
        }
3062
17
        mxPop(); // property
3063
17
        mxPop(); // at
3064
17
        mxPop(); // globalLexicals
3065
17
      }
3066
  
3067
337
      mxPushSlot(mxArgv(0));
3068
337
      if (mxHasID(fxID(the, "resolveHook"))) {
3069
160
        mxPushSlot(mxArgv(0));
3070
160
        mxGetID(fxID(the, "resolveHook"));
3071
160
        if (!fxIsCallable(the, the->stack))
3072
12
          mxTypeError("options.resolveHook: not a function");
3073
160
      }
3074
177
      else
3075
177
        mxPushUndefined();
3076
      
3077
325
      mxPushUndefined(); // moduleMapHook;
3078
      
3079
325
      mxPushSlot(mxArgv(0));
3080
325
      if (mxHasID(fxID(the, "importHook"))) {
3081
3
        mxPushSlot(mxArgv(0));
3082
3
        mxGetID(fxID(the, "importHook"));
3083
3
        if (!fxIsCallable(the, the->stack))
3084
0
          mxTypeError("options.importHook: not a function");
3085
3
      }
3086
322
      else {
3087
322
        mxPushSlot(mxArgv(0));
3088
322
        if (mxHasID(fxID(the, "loadHook"))) {
3089
32
          mxPushSlot(mxArgv(0));
3090
32
          mxGetID(fxID(the, "loadHook"));
3091
32
          if (!fxIsCallable(the, the->stack))
3092
12
            mxTypeError("options.loadHook: not a function");
3093
32
        }
3094
290
        else
3095
290
          mxPushUndefined();
3096
322
      }
3097
        
3098
313
      mxPushSlot(mxArgv(0));
3099
313
      if (mxHasID(fxID(the, "importNowHook"))) {
3100
9
        mxPushSlot(mxArgv(0));
3101
9
        mxGetID(fxID(the, "importNowHook"));
3102
9
        if (!fxIsCallable(the, the->stack))
3103
0
          mxTypeError("options.importNowHook: not a function");
3104
9
      }
3105
304
      else {
3106
304
        mxPushSlot(mxArgv(0));
3107
304
        if (mxHasID(fxID(the, "loadNowHook"))) {
3108
26
          mxPushSlot(mxArgv(0));
3109
26
          mxGetID(fxID(the, "loadNowHook"));
3110
26
          if (!fxIsCallable(the, the->stack))
3111
14
            mxTypeError("options.loadNowHook: not a function");
3112
26
        }
3113
278
        else
3114
278
          mxPushUndefined();
3115
304
      }
3116
      
3117
299
      mxPushUndefined(); // importMetaHook;
3118
299
    }
3119
24
    else {
3120
24
      target = fxNewInstance(the);
3121
24
      own = fxNewInstance(the);
3122
  
3123
24
      mxPushUndefined();
3124
24
      closures = fxNewEnvironmentInstance(the, C_NULL);
3125
3126
24
      mxPushUndefined();
3127
24
      mxPushUndefined();
3128
24
      mxPushUndefined();
3129
24
      mxPushUndefined();
3130
24
      mxPushUndefined();
3131
24
    }
3132
    
3133
323
    realm = fxNewRealmInstance(the);
3134
323
    mxModuleInstanceInternal(program)->value.module.realm = realm;
3135
    
3136
323
    slot = own->next;
3137
323
    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
323
    mxPop();
3148
323
  }
3149
323
  mxCatch(the) {
3150
121
    fxJump(the);
3151
121
  }
3152
442
}
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
33
{
3165
33
  txSlot* program = fxCheckCompartmentInstance(the, mxThis);
3166
33
  txSlot* realm = mxModuleInstanceInternal(program)->value.module.realm;
3167
33
  if (mxArgc > 0) {
3168
33
    txStringStream stream;
3169
33
    stream.slot = mxArgv(0);
3170
33
    stream.offset = 0;
3171
33
    stream.size = mxStringLength(fxToString(the, mxArgv(0)));
3172
33
    fxRunScript(the, fxParseScript(the, &stream, fxStringGetter, mxStrictFlag | mxProgramFlag | mxDebugFlag), mxRealmGlobal(realm), C_NULL, mxRealmClosures(realm)->value.reference, C_NULL, program);
3173
33
    mxPullSlot(mxResult);
3174
33
  }
3175
33
}
3176
3177
void fx_Compartment_prototype_import(txMachine* the)
3178
217
{
3179
217
  txSlot* program = fxCheckCompartmentInstance(the, mxThis);
3180
217
  txSlot* realm = mxModuleInstanceInternal(program)->value.module.realm;
3181
217
  if (mxArgc > 0)
3182
216
    mxPushSlot(mxArgv(0));
3183
1
  else
3184
1
    mxPushUndefined();
3185
217
  if (mxArgc > 1)
3186
0
    mxPushSlot(mxArgv(1));
3187
217
  else
3188
217
    mxPushUndefined();
3189
217
  gxDefaults.runImport(the, realm, C_NULL);
3190
217
  mxPullSlot(mxResult);
3191
217
}
3192
3193
void fx_Compartment_prototype_importNow(txMachine* the)
3194
67
{
3195
67
  txSlot* program = fxCheckCompartmentInstance(the, mxThis);
3196
67
  txSlot* realm = mxModuleInstanceInternal(program)->value.module.realm;
3197
67
  if (mxArgc > 0)
3198
67
    mxPushSlot(mxArgv(0));
3199
0
  else
3200
0
    mxPushUndefined();
3201
67
  if (mxArgc > 1)
3202
0
    mxPushSlot(mxArgv(1));
3203
67
  else
3204
67
    mxPushUndefined();
3205
67
  fxRunImportNow(the, realm, C_NULL);
3206
67
  mxPullSlot(mxResult);
3207
67
}
3208
3209
txSlot* fxCheckModuleSourceInstance(txMachine* the, txSlot* slot)
3210
18
{
3211
18
  if (slot->kind == XS_REFERENCE_KIND) {
3212
18
    txSlot* instance = slot->value.reference;
3213
18
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_MODULE_SOURCE_KIND)) {
3214
18
      return instance;
3215
18
    }
3216
18
  }
3217
18
  mxTypeError("this: not a ModuleSource instance");
3218
0
  return C_NULL;
3219
18
}
3220
3221
txSlot* fxNewModuleSourceInstance(txMachine* the)
3222
3.88k
{
3223
3.88k
  txSlot* instance;
3224
3.88k
  txSlot* slot;
3225
3.88k
  instance = fxNewSlot(the);
3226
3.88k
  instance->kind = XS_INSTANCE_KIND;
3227
3.88k
  instance->value.instance.garbage = C_NULL;
3228
3.88k
  instance->value.instance.prototype = the->stack->value.reference;
3229
3.88k
  the->stack->kind = XS_REFERENCE_KIND;
3230
3.88k
  the->stack->value.reference = instance;
3231
  /* HOST */
3232
3.88k
  slot = instance->next = fxNewSlot(the);
3233
3.88k
  slot->flag = XS_INTERNAL_FLAG;
3234
3.88k
  slot->kind = XS_MODULE_SOURCE_KIND;
3235
3.88k
  slot->value.module.realm = C_NULL;
3236
3.88k
  slot->value.module.id = XS_NO_ID;
3237
  /* EXPORTS */
3238
3.88k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3239
  /* STUFF */
3240
3.88k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3241
  /* META */
3242
3.88k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3243
  /* TRANSFERS */
3244
3.88k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3245
  /* INITIALIZE */
3246
3.88k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3247
  /* FUNCTION */
3248
3.88k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3249
  /* HOSTS */
3250
3.88k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3251
  /* LOADER */
3252
3.88k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3253
3.88k
  return instance;
3254
3.88k
}
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
3.88k
{
3269
3.88k
  txSlot* instance;
3270
3.88k
  txUnsigned flags = mxDebugFlag;
3271
3.88k
  txSlot* slot;
3272
3.88k
  txStringStream stream;
3273
3.88k
  txScript* script;
3274
3.88k
  if (mxIsUndefined(mxTarget))
3275
1
    mxTypeError("call: ModuleSource");
3276
3.88k
  mxPushSlot(mxTarget);
3277
3.88k
  fxGetPrototypeFromConstructor(the, &mxModuleSourcePrototype);
3278
3.88k
  instance = fxNewModuleSourceInstance(the);
3279
3.88k
  mxPullSlot(mxResult);
3280
3.88k
  if (mxArgc > 0)
3281
3.88k
    mxPushSlot(mxArgv(0));
3282
1
  else    
3283
1
    mxPushUndefined();
3284
3.88k
  if (mxArgc > 1) {
3285
386
    if (fxCheckModuleOptions(the, mxArgv(1))) {
3286
0
      instance->next->flag |= XS_JSON_MODULE_FLAG;
3287
0
      flags |= mxJSONModuleFlag;
3288
0
    }
3289
386
  }
3290
3.88k
  slot = the->stack;
3291
3.88k
  stream.slot = slot;
3292
3.88k
  stream.offset = 0;
3293
3.88k
  stream.size = mxStringLength(fxToString(the, slot));
3294
3.88k
  script = fxParseScript(the, &stream, fxStringGetter, flags);
3295
//    mxPushClosure(mxResult);
3296
3.88k
  fxRunScript(the, script, mxResult, C_NULL, C_NULL, C_NULL, instance);
3297
3.88k
  mxPop();
3298
3.88k
  if (mxModuleInstanceExecute(instance)->kind == XS_NULL_KIND)
3299
0
    mxTypeError("no module");
3300
3.88k
  mxPop();
3301
3.88k
  mxPop();
3302
3.88k
}
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
60
  while (transfer) {
3320
52
    txSlot* local = mxTransferLocal(transfer);
3321
52
    txSlot* from = mxTransferFrom(transfer);
3322
52
    txSlot* import = mxTransferImport(transfer);
3323
52
    txSlot* aliases = mxTransferAliases(transfer);
3324
    
3325
52
    if (local->kind != XS_NULL_KIND) {
3326
33
      if (from->kind != XS_NULL_KIND) {
3327
17
        txSlot* slot = fxNewObject(the);
3328
17
        if (import->kind == XS_NULL_KIND) {
3329
5
          mxPushString(from->value.string);
3330
5
          slot = fxNextSlotProperty(the, slot, the->stack, fxID(the, "importAllFrom"), XS_NO_FLAG);
3331
5
          mxPop();
3332
5
          fxPushKeyString(the, local->value.symbol, C_NULL);
3333
5
          slot = fxNextSlotProperty(the, slot, the->stack, mxID(_as), XS_NO_FLAG);
3334
5
          mxPop();
3335
5
        }
3336
12
        else {
3337
12
          fxPushKeyString(the, import->value.symbol, C_NULL);
3338
12
          slot = fxNextSlotProperty(the, slot, the->stack, mxID(_import), XS_NO_FLAG);
3339
12
          mxPop();
3340
12
          if (local->value.symbol != import->value.symbol) {
3341
5
            fxPushKeyString(the, local->value.symbol, C_NULL);
3342
5
            slot = fxNextSlotProperty(the, slot, the->stack, mxID(_as), XS_NO_FLAG);
3343
5
            mxPop();
3344
5
          }
3345
12
          mxPushString(from->value.string);
3346
12
          slot = fxNextSlotProperty(the, slot, the->stack, mxID(_from), XS_NO_FLAG);
3347
12
          mxPop();
3348
12
        }
3349
17
        resultItem = resultItem->next = fxNewSlot(the);
3350
17
        mxPullSlot(resultItem);
3351
17
        resultArray->value.array.length++;
3352
17
      }
3353
33
      if (aliases->kind == XS_REFERENCE_KIND) {
3354
15
        txSlot* alias = aliases->value.reference->next;
3355
34
        while (alias) {
3356
19
          txSlot* slot = fxNewObject(the);
3357
19
          fxPushKeyString(the, local->value.symbol, C_NULL);
3358
19
          slot = fxNextSlotProperty(the, slot, the->stack, mxID(_export), XS_NO_FLAG);
3359
19
          mxPop();
3360
19
          if (local->value.symbol != alias->value.symbol) {
3361
5
            fxPushKeyString(the, alias->value.symbol, C_NULL);
3362
5
            slot = fxNextSlotProperty(the, slot, the->stack, mxID(_as), XS_NO_FLAG);
3363
5
            mxPop();
3364
5
          }
3365
19
          resultItem = resultItem->next = fxNewSlot(the);
3366
19
          mxPullSlot(resultItem);
3367
19
          resultArray->value.array.length++;
3368
19
          alias = alias->next;
3369
19
        }
3370
15
      }
3371
33
    }
3372
19
    else if (aliases->kind == XS_REFERENCE_KIND) {
3373
15
      txSlot* alias = aliases->value.reference->next;
3374
15
      if (alias) {
3375
22
        while (alias) {
3376
11
          txSlot* slot = fxNewObject(the);
3377
11
          if (from->kind != XS_NULL_KIND) {
3378
11
            if (import->kind == XS_NULL_KIND) {
3379
4
              mxPushString(from->value.string);
3380
4
              slot = fxNextSlotProperty(the, slot, the->stack, fxID(the, "exportAllFrom"), XS_NO_FLAG);
3381
4
              mxPop();
3382
4
              fxPushKeyString(the, alias->value.symbol, C_NULL);
3383
4
              slot = fxNextSlotProperty(the, slot, the->stack, mxID(_as), XS_NO_FLAG);
3384
4
              mxPop();
3385
4
            }
3386
7
            else {
3387
7
              fxPushKeyString(the, import->value.symbol, C_NULL);
3388
7
              slot = fxNextSlotProperty(the, slot, the->stack, mxID(_export), XS_NO_FLAG);
3389
7
              mxPop();
3390
7
              if (alias->value.symbol != import->value.symbol) {
3391
4
                fxPushKeyString(the, alias->value.symbol, C_NULL);
3392
4
                slot = fxNextSlotProperty(the, slot, the->stack, mxID(_as), XS_NO_FLAG);
3393
4
                mxPop();
3394
4
              }
3395
7
              mxPushString(from->value.string);
3396
7
              slot = fxNextSlotProperty(the, slot, the->stack, mxID(_from), XS_NO_FLAG);
3397
7
              mxPop();
3398
7
            }
3399
11
            resultItem = resultItem->next = fxNewSlot(the);
3400
11
            mxPullSlot(resultItem);
3401
11
            resultArray->value.array.length++;
3402
11
          }
3403
11
          alias = alias->next;
3404
11
        }
3405
11
      }
3406
4
      else {
3407
4
        txSlot* slot = fxNewObject(the);
3408
4
        mxPushString(from->value.string);
3409
4
        slot = fxNextSlotProperty(the, slot, the->stack, fxID(the, "exportAllFrom"), XS_NO_FLAG);
3410
4
        mxPop();
3411
4
        resultItem = resultItem->next = fxNewSlot(the);
3412
4
        mxPullSlot(resultItem);
3413
4
        resultArray->value.array.length++;
3414
4
      }
3415
15
    }
3416
4
    else if ((from->kind != XS_NULL_KIND) && (import->kind == XS_NULL_KIND)) {
3417
4
      txSlot* slot = fxNewObject(the);
3418
4
      mxPushString(from->value.string);
3419
4
      slot = fxNextSlotProperty(the, slot, the->stack, fxID(the, "importFrom"), XS_NO_FLAG);
3420
4
      mxPop();
3421
4
      resultItem = resultItem->next = fxNewSlot(the);
3422
4
      mxPullSlot(resultItem);
3423
4
      resultArray->value.array.length++;
3424
4
    }
3425
52
    transfer = transfer->next;
3426
52
  }
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
4
{
3441
4
  txSlot* record = fxCheckModuleSourceInstance(the, mxThis);
3442
4
  txFlag flag = mxModuleInstanceInternal(record)->flag;
3443
4
  mxResult->value.boolean = (flag & XS_IMPORT_META_FLAG) ? 1 : 0;
3444
4
  mxResult->kind = XS_BOOLEAN_KIND;
3445
4
}
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
190
{
3532
190
  txSlot* realm = mxModuleInstanceInternal(module)->value.module.realm;
3533
190
  txSlot* reference = mxModuleInstanceHook(module);
3534
190
  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
190
  return 0;
3556
190
}
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