Coverage Report

Created: 2026-03-30 06:33

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
13
  (((THE_SLOT)->next) && ((THE_SLOT)->next->flag & XS_INTERNAL_FLAG) && ((THE_SLOT)->next->kind == XS_MODULE_KIND))
143
#define mxIsModuleSource(THE_SLOT) \
144
200
  (((THE_SLOT)->next) && ((THE_SLOT)->next->flag & XS_INTERNAL_FLAG) && ((THE_SLOT)->next->kind == XS_MODULE_SOURCE_KIND))
145
146
30.1k
#define mxModuleInstanceStatus(MODULE)    ((MODULE)->next->next->ID)
147
29.7k
#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
23.3k
{
240
23.3k
#ifndef mxLink
241
23.3k
  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
23.3k
  else {
248
23.3k
    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
23.3k
  }
253
23.3k
#endif
254
23.3k
}
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
23.8k
{
273
23.8k
  txFlag moduleFlag = XS_NO_FLAG;
274
23.8k
#if mxECMAScript2025  
275
23.8k
  if (!mxIsUndefined(options)) {
276
390
    txSlot* with;
277
390
    if (!mxIsReference(options))
278
388
      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
23.4k
#endif
317
23.4k
  return moduleFlag;
318
23.8k
}
319
320
void fxCompleteModule(txMachine* the, txSlot* module, txSlot* exception)
321
390
{
322
390
  if (exception) {
323
270
    txSlot* exports = mxModuleInstanceExports(module);
324
270
    txSlot* meta = mxModuleInstanceMeta(module);
325
270
    if (exports->kind == XS_REFERENCE_KIND) {
326
65
      exports->value.reference->next = C_NULL;
327
65
    }
328
205
    else {
329
205
      fxNewInstance(the);
330
205
      mxPullSlot(exports);
331
205
    }
332
270
    meta->value = exception->value;
333
270
    meta->kind = exception->kind;
334
270
    mxModuleInstanceStatus(module) = XS_MODULE_STATUS_ERROR;
335
270
  }
336
120
  else {
337
120
    mxModuleInstanceStatus(module) = XS_MODULE_STATUS_EXECUTED;
338
120
  }
339
390
}
340
341
void fxDuplicateModuleTransfers(txMachine* the, txSlot* srcModule, txSlot* dstModule)
342
135
{
343
135
  txSlot* srcSlot;
344
135
  txSlot* dstSlot;
345
135
  txSlot* transfer;
346
135
  txSlot* aliases;
347
135
  txSlot* function;
348
135
  srcSlot = mxModuleInternal(srcModule);
349
135
  dstSlot = mxModuleInternal(dstModule);
350
135
  dstSlot->flag |= (srcSlot->flag & (XS_IMPORT_FLAG | XS_IMPORT_META_FLAG));
351
135
  srcSlot = mxModuleTransfers(srcModule);
352
135
  dstSlot = mxModuleTransfers(dstModule);
353
135
  fxDuplicateInstance(the, srcSlot->value.reference);
354
135
  mxPullSlot(dstSlot);
355
135
  transfer = dstSlot->value.reference->next;
356
376
  while (transfer) {
357
241
    fxDuplicateInstance(the, transfer->value.reference);
358
241
    mxPullSlot(transfer);
359
241
    aliases = mxTransferAliases(transfer);
360
241
    if (aliases->kind == XS_REFERENCE_KIND) {
361
194
      fxDuplicateInstance(the, aliases->value.reference);
362
194
      mxPullSlot(aliases);
363
194
    }    
364
241
    transfer = transfer->next;
365
241
  }
366
135
  srcSlot = mxModuleInitialize(srcModule);
367
135
  dstSlot = mxModuleInitialize(dstModule);
368
135
  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
135
  else {
374
135
    dstSlot->kind = srcSlot->kind;
375
135
    dstSlot->value = srcSlot->value;
376
135
  }
377
135
  srcSlot = mxModuleExecute(srcModule);
378
135
  dstSlot = mxModuleExecute(dstModule);
379
135
  function = fxDuplicateInstance(the, srcSlot->value.reference);
380
135
  mxPullSlot(dstSlot);
381
135
  mxFunctionInstanceHome(function)->value.home.module =   dstModule->value.reference;
382
135
}
383
384
void fxExecuteModules(txMachine* the, txSlot* queue)
385
213
{
386
213
  txBoolean done = 1;
387
213
  txSlot* module = queue->next;
388
213
  mxReportModuleQueue("INIT");
389
530
  while (module) {
390
317
    txID status = mxModuleStatus(module);
391
317
    if (status == XS_MODULE_STATUS_LINKED) {
392
108
      txSlot* exception;
393
108
      txID fromStatus = fxExecuteModulesFrom(the, queue, module, &exception);
394
108
      if (fromStatus == XS_MODULE_STATUS_ERROR) {
395
10
        fxCompleteModule(the, module->value.reference, exception);
396
10
        fxRunImportRejected(the, module->value.reference, module->value.reference);
397
10
      }
398
98
      else if (fromStatus == XS_MODULE_STATUS_LINKED) {
399
98
        mxModuleStatus(module) = XS_MODULE_STATUS_EXECUTING;
400
98
        mxPushSlot(mxModuleHosts(module));
401
98
        mxPull(mxHosts);
402
98
        {
403
98
          mxTry(the) {
404
98
            txSlot* result;
405
98
            mxPushUndefined();
406
98
            mxPushSlot(mxModuleExecute(module));
407
98
            mxCall();
408
98
            mxRunCount(0);
409
98
            result = the->stack;
410
98
            if (mxIsReference(result) && mxIsPromise(result->value.reference)) {
411
13
              txSlot* function;
412
13
              txSlot* home;
413
13
              txSlot* resolveExecuteFunction;
414
13
              txSlot* rejectExecuteFunction;
415
              
416
13
              function = fxNewHostFunction(the, fxExecuteModulesFulfilled, 1, XS_NO_ID, mxExecuteModulesFulfilledProfileID);
417
13
              home = mxFunctionInstanceHome(function);
418
13
              home->value.home.object = queue;
419
13
              home->value.home.module = module->value.reference;
420
13
              resolveExecuteFunction = the->stack;
421
  
422
13
              function = fxNewHostFunction(the, fxExecuteModulesRejected, 1, XS_NO_ID, mxExecuteModulesRejectedProfileID);
423
13
              home = mxFunctionInstanceHome(function);
424
13
              home->value.home.object = queue;
425
13
              home->value.home.module = module->value.reference;
426
13
              rejectExecuteFunction = the->stack;
427
        
428
13
              fxPromiseThen(the, result->value.reference, resolveExecuteFunction, rejectExecuteFunction, C_NULL, C_NULL);
429
            
430
13
              mxPop();
431
13
              mxPop();
432
13
              mxPop();
433
13
              done = 0;
434
13
            }
435
85
            else {
436
85
              mxPop();
437
85
              fxCompleteModule(the, module->value.reference, C_NULL);
438
85
              fxRunImportFulfilled(the, module->value.reference, module->value.reference);
439
85
            }
440
98
          }
441
98
          mxCatch(the) {
442
15
            mxPush(mxException);
443
15
            mxException = mxUndefined;
444
15
            fxCompleteModule(the, module->value.reference, the->stack);
445
15
            fxRunImportRejected(the, module->value.reference, module->value.reference);
446
15
            mxPop();
447
15
          }
448
98
        }
449
98
        mxPushUndefined();
450
98
        mxPull(mxHosts);
451
98
      }
452
0
      else
453
0
        done = 0;
454
108
    }
455
209
    else if (status < XS_MODULE_STATUS_EXECUTED)
456
1
      done = 0;
457
317
    module = module->next;
458
317
  }
459
213
  if (done) {
460
199
    queue->next = C_NULL;
461
199
    mxReportModuleQueue("DONE");
462
199
  }
463
213
}
464
465
txID fxExecuteModulesFrom(txMachine* the, txSlot* queue, txSlot* module, txSlot** exception)
466
108
{
467
108
  txSlot* fromModules = mxModuleTransfers(module)->value.reference;
468
108
  txSlot* fromModule;
469
108
  if (mxModuleTransfers(module)->kind == XS_NULL_KIND)
470
70
    return XS_MODULE_STATUS_LINKED;
471
38
  fromModule = fromModules->next;
472
66
  while (fromModule) {
473
38
    if (mxModuleStatus(fromModule) == XS_MODULE_STATUS_ERROR) {
474
10
      *exception = mxModuleMeta(fromModule);
475
10
      return XS_MODULE_STATUS_ERROR;
476
10
    }
477
28
    fromModule = fromModule->next;
478
28
  }
479
28
  fromModule = fromModules->next;
480
56
  while (fromModule) {
481
28
    if (mxModuleStatus(fromModule) == XS_MODULE_STATUS_EXECUTING) {
482
0
      return XS_MODULE_STATUS_EXECUTING;
483
0
    }
484
28
    fromModule = fromModule->next;
485
28
  }
486
28
  fromModule = fromModules->next;
487
56
  while (fromModule) {
488
28
    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
28
    fromModule = fromModule->next;
499
28
  }
500
28
  return XS_MODULE_STATUS_LINKED;
501
28
}
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
3
{
515
3
  txSlot* home = mxFunctionInstanceHome(mxFunction->value.reference);
516
3
  txSlot* queue = home->value.home.object;
517
3
  txSlot* module = home->value.home.module;
518
3
  fxCompleteModule(the, module,  mxArgv(0));
519
3
  fxRunImportRejected(the, module, module);
520
3
  fxExecuteModules(the, queue);
521
3
}
522
523
void fxExecuteVirtualModuleSource(txMachine* the)
524
37
{
525
37
  txSlot* instance = mxFunction->value.reference;
526
37
  txSlot* function = fxLastProperty(the, instance);
527
37
  txSlot* home = mxFunctionInstanceHome(instance);
528
37
  txSlot* module = home->value.home.module;
529
37
  txSlot* internal = mxModuleInstanceInternal(module);
530
37
  txSlot* meta = mxModuleInstanceMeta(module);
531
37
  txSlot* closures = mxFunctionInstanceCode(instance)->value.callback.closures;
532
37
  txSlot* property;
533
37
  if (mxIsUndefined(function))
534
5
    return;
535
32
  closures->flag |= XS_DONT_PATCH_FLAG;
536
32
  closures->value.instance.prototype = C_NULL;
537
32
  property = closures->next->next;
538
95
  while (property) {
539
63
    property->flag |= XS_DONT_DELETE_FLAG;
540
63
    property = property->next;
541
63
  }
542
  /* THIS */
543
32
  mxPushReference(home->value.home.object);
544
  /* FUNCTION */
545
32
  mxPushSlot(function);
546
32
  mxCall();
547
  /* ARGUMENTS */
548
32
  mxPushReference(closures);
549
32
  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
31
  else
554
31
    mxPushUndefined();
555
32
  if (internal->flag & XS_IMPORT_META_FLAG)
556
1
    mxPushSlot(meta);
557
31
  else
558
31
    mxPushUndefined();
559
32
  mxRunCount(3);
560
32
  mxPullSlot(mxResult);
561
32
}
562
563
txSlot* fxGetModule(txMachine* the, txSlot* realm, txID moduleID, txFlag moduleFlag)
564
23.5k
{
565
23.5k
  txSlot* result = mxBehaviorGetProperty(the, mxOwnModules(realm)->value.reference, moduleID, 0, XS_ANY);
566
23.5k
  if (result)
567
23.1k
    fxCheckModuleFlag(the, moduleID, mxModuleInternal(result)->flag, moduleFlag);
568
23.5k
  return result;
569
23.5k
}
570
571
void fxLinkCircularities(txMachine* the, txSlot* module, txSlot* circularities, txSlot* exports)
572
172
{
573
172
  txSlot* circularitiesInstance;
574
172
  txSlot* circularity;
575
172
  txSlot* transfers;
576
172
  txSlot* exportsInstance;
577
172
  txSlot* export;
578
172
  txSlot* transfer;
579
172
  txSlot* aliases;
580
172
  txSlot* alias;
581
172
  txSlot* circularitiesCopy;
582
172
  txSlot* circularityCopy;
583
172
  txSlot* from;
584
172
  txSlot* stars;
585
172
  txSlot* star;
586
172
  circularitiesInstance = circularities->value.reference;
587
172
  circularity = circularitiesInstance->next;
588
172
  while (circularity) {
589
0
    if (circularity->value.reference == module->value.reference)
590
0
      return;
591
0
    circularity = circularity->next;
592
0
  }
593
172
  circularity = fxDuplicateSlot(the, module);
594
172
  circularity->next = circularitiesInstance->next;
595
172
  circularitiesInstance->next = circularity;
596
172
  exportsInstance = exports->value.reference;
597
172
  export = exportsInstance;
598
172
  transfers = mxModuleExports(module);
599
172
  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
172
  transfers = mxModuleTransfers(module);
611
172
  if (transfers->kind == XS_REFERENCE_KIND) {
612
172
    txBoolean starFlag = 0;
613
172
    transfer = transfers->value.reference->next;
614
567
    while (transfer) {
615
395
      aliases = mxTransferAliases(transfer);
616
395
      if (aliases->kind == XS_REFERENCE_KIND) {
617
295
        alias = aliases->value.reference->next;
618
295
        if (alias) {
619
595
          while (alias) {
620
300
            export = export->next = fxNewSlot(the);
621
300
            export->ID = alias->value.symbol;
622
300
            export->kind = transfer->kind;
623
300
            export->value = transfer->value;
624
300
            alias = alias->next;
625
300
          }
626
295
        }
627
0
        else {
628
0
          mxCheck(the, mxTransferLocal(transfer)->kind == XS_NULL_KIND);
629
0
          starFlag = 1;
630
0
        }
631
295
      }
632
395
      transfer = transfer->next;
633
395
    }
634
172
    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
172
  }
719
172
}
720
721
void fxLinkExports(txMachine* the, txSlot* module)
722
172
{
723
172
  txSlot* exports;
724
172
  txSlot* transfer;
725
172
  txSlot* from;
726
172
  txSlot* import;
727
172
  txSlot* closure;
728
729
172
  exports = mxModuleExports(module)->value.reference;
730
172
  exports->flag |= XS_DONT_PATCH_FLAG;
731
172
  transfer = exports->next;
732
461
  while (transfer) {
733
289
    if (transfer->kind != XS_EXPORT_KIND) {
734
289
      from = mxTransferFrom(transfer);
735
289
      if (from->kind != XS_NULL_KIND) {
736
36
        import = mxTransferImport(transfer);
737
36
        if (import->kind != XS_NULL_KIND)
738
25
          fxLinkTransfer(the, from, import->value.symbol, transfer);
739
11
        else
740
11
          fxLinkNamespace(the, from, transfer);
741
36
      }
742
289
      closure = mxTransferClosure(transfer);
743
289
      transfer->kind = closure->kind;
744
289
      transfer->value = closure->value;
745
289
    }
746
289
    transfer->flag |= XS_DONT_DELETE_FLAG | XS_DONT_SET_FLAG;
747
289
    transfer = transfer->next;
748
289
  }
749
172
}
750
751
void fxLinkLocals(txMachine* the, txSlot* module)
752
159
{
753
159
  txSlot* transfer;
754
159
  txSlot* local;
755
159
  txSlot* from;
756
159
  txSlot* import;
757
159
  txSlot* closure;
758
759
159
  transfer = mxModuleTransfers(module)->value.reference->next;
760
457
  while (transfer) {
761
298
    local = mxTransferLocal(transfer);
762
298
    if (local->kind != XS_NULL_KIND) {
763
266
      from = mxTransferFrom(transfer);
764
266
      if (from->kind != XS_NULL_KIND) {
765
65
        import = mxTransferImport(transfer);
766
65
        if (import->kind != XS_NULL_KIND)
767
56
          fxLinkTransfer(the, from, import->value.symbol, transfer);
768
9
        else
769
9
          fxLinkNamespace(the, from, transfer);
770
65
        closure = mxTransferClosure(transfer);
771
65
        closure->flag |= XS_DONT_SET_FLAG;
772
65
      }
773
266
    }
774
298
    transfer = transfer->next;
775
298
  }
776
159
}
777
778
void fxLinkModules(txMachine* the, txSlot* queue)
779
244
{
780
244
  txSlot* module;
781
244
  txSlot* order;
782
244
  txSlot* transfer;
783
244
  txSlot* local;
784
244
  txSlot* from;
785
244
  txSlot* import;
786
244
  txSlot* aliases;
787
244
  txSlot* closure;
788
244
  txSlot* property;
789
244
  txSlot* circularities;
790
244
  txSlot* exports;
791
244
  txSlot* realm;
792
244
  txSlot* closures;
793
244
  txSlot* export;
794
  
795
244
  order = fxNewInstance(the);
796
493
  while ((module = queue->next))
797
249
    fxOrderModule(the, queue, order, module);
798
244
  queue->next = order->next;
799
244
  order->next = C_NULL;
800
244
  mxPop();
801
802
244
  mxReportModuleQueue("LINK");
803
244
  module = queue->next;
804
589
  while (module) {
805
345
    if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) {
806
172
      transfer = mxModuleTransfers(module)->value.reference->next;
807
567
      while (transfer) {
808
395
        local = mxTransferLocal(transfer);
809
395
        from = mxTransferFrom(transfer);
810
395
        import = mxTransferImport(transfer);
811
395
        aliases = mxTransferAliases(transfer);
812
395
        if (local->kind != XS_NULL_KIND) {
813
336
          if ((from->kind == XS_NULL_KIND) || (import->kind == XS_NULL_KIND)) {
814
269
            closure = mxTransferClosure(transfer);
815
269
            closure->value.export.closure = fxNewSlot(the);
816
269
            closure->value.export.closure->kind = XS_UNINITIALIZED_KIND;
817
269
            closure->value.export.module = module->value.reference;
818
269
            closure->kind = XS_EXPORT_KIND;
819
269
          }
820
336
        }
821
59
        else {
822
59
          if ((from->kind != XS_NULL_KIND) && (import->kind == XS_NULL_KIND) && (aliases->kind != XS_NULL_KIND)) {
823
15
            closure = mxTransferClosure(transfer);
824
15
            closure->value.export.closure = fxNewSlot(the);
825
15
            closure->value.export.closure->kind = XS_UNINITIALIZED_KIND;
826
15
            closure->value.export.module = module->value.reference;
827
15
            closure->kind = XS_EXPORT_KIND;
828
15
          }
829
59
        }
830
395
        transfer = transfer->next;
831
395
      }
832
172
    }
833
345
    module = module->next;
834
345
  }
835
836
244
  module = queue->next;
837
589
  while (module) {
838
345
    if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) {
839
172
      fxNewInstance(the);
840
172
      circularities = the->stack;
841
172
      fxNewInstance(the);
842
172
      exports = the->stack;
843
172
      fxLinkCircularities(the, module, circularities, exports);
844
172
      mxModuleExports(module)->kind = XS_REFERENCE_KIND;
845
172
      mxModuleExports(module)->value.reference = exports->value.reference;
846
172
      mxPop();
847
172
      mxPop();
848
172
    }
849
345
    module = module->next;
850
345
  }
851
852
244
  module = queue->next;
853
589
  while (module) {
854
345
    if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING)
855
172
      fxLinkExports(the, module);
856
345
    module = module->next;
857
345
  }
858
244
  module = queue->next;
859
552
  while (module) {
860
308
    if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING)
861
159
      fxLinkLocals(the, module);
862
308
    module = module->next;
863
308
  }
864
865
244
  module = queue->next;
866
529
  while (module) {
867
285
    if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) {
868
145
      txInteger count = 0;
869
145
      mxPushUndefined();
870
145
      realm = mxModuleInternal(module)->value.module.realm;
871
145
      closures = fxNewEnvironmentInstance(the, mxRealmClosures(realm));
872
145
      closure = closures->next;
873
145
      transfer = mxModuleTransfers(module)->value.reference->next;
874
420
      while (transfer) {
875
275
        local = mxTransferLocal(transfer);
876
275
        if (local->kind != XS_NULL_KIND) {
877
243
          export = mxTransferClosure(transfer);
878
243
          mxCheck(the, export->kind == XS_EXPORT_KIND);
879
243
          closure = closure->next = fxNewSlot(the);
880
243
          closure->ID = local->value.symbol;
881
243
          closure->flag = export->flag;
882
243
          closure->kind = XS_CLOSURE_KIND;
883
243
          closure->value.closure = export->value.export.closure;
884
243
        }
885
275
        from = mxTransferFrom(transfer);
886
275
        if (from->kind != XS_NULL_KIND)
887
87
          count++;
888
275
        transfer = transfer->next;
889
275
      }
890
145
      property = mxModuleInitialize(module);
891
145
      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
145
      property = mxModuleExecute(module);
899
145
      if (property->kind == XS_REFERENCE_KIND) {
900
145
        property = property->value.reference->next;
901
145
        if ((property->kind == XS_CODE_KIND) || (property->kind == XS_CODE_X_KIND))
902
102
          property->value.code.closures = closures;
903
43
        else if (property->kind == XS_CALLBACK_KIND)
904
43
          property->value.callback.closures = closures;
905
145
      }
906
145
      mxPop();
907
145
      if (count > 0) {
908
48
        txSlot* instance = fxNewInstance(the);
909
48
        transfer = mxModuleTransfers(module)->value.reference->next;
910
206
        while (transfer) {
911
158
          from = mxTransferFrom(transfer);
912
158
          if (from->kind != XS_NULL_KIND) {
913
87
            txSlot** address = &(instance->next);
914
87
            txSlot* slot;
915
99
            while ((slot = *address)) {
916
44
              if (slot->value.reference == from->value.reference)
917
32
                break;
918
12
              address = &slot->next;
919
12
            }
920
87
            if (!slot)
921
55
              slot = *address = fxDuplicateSlot(the, from);
922
87
          }
923
158
          transfer = transfer->next;
924
158
        }
925
48
        mxModuleTransfers(module)->value.reference = instance;
926
48
        mxPop();
927
48
      }
928
97
      else
929
97
        mxModuleTransfers(module)->kind = XS_NULL_KIND;
930
145
    }
931
285
    module = module->next;
932
285
  }
933
934
244
  module = queue->next;
935
529
  while (module) {
936
285
    if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) {
937
145
      mxModuleStatus(module) = XS_MODULE_STATUS_LINKED;
938
145
      property = mxModuleInitialize(module);
939
145
      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
145
    }
951
285
    module = module->next;
952
285
  }
953
244
}
954
955
void fxLinkNamespace(txMachine* the, txSlot* module, txSlot* transfer)
956
20
{
957
20
  txSlot* export = mxTransferClosure(transfer);
958
20
  mxCheck(the, export->kind == XS_EXPORT_KIND);
959
20
  export->value.export.closure = fxDuplicateSlot(the, module);
960
20
  export->value.export.closure->ID = XS_NO_ID;
961
20
}
962
963
void fxLinkTransfer(txMachine* the, txSlot* module, txID importID, txSlot* transfer)
964
81
{
965
81
  txSlot* export;
966
81
  txSlot* exportClosure;
967
81
  txSlot* transferClosure;
968
81
  txSlot* from;
969
81
  txSlot* import;
970
  
971
81
  export = mxBehaviorGetProperty(the, mxModuleExports(module)->value.reference, importID, 0, XS_OWN);
972
81
  if (export) {
973
62
    if (export->kind == XS_EXPORT_KIND) {
974
62
      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
62
      transferClosure = mxTransferClosure(transfer);
988
62
      transferClosure->value = export->value;
989
62
      transferClosure->kind = export->kind;
990
62
    }
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
62
  }
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
81
}
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
268
{
1070
268
  txSlot* module = queue->next;
1071
268
  txBoolean done = 1;
1072
268
  if (queue->flag & XS_LEVEL_FLAG)
1073
0
    return;
1074
268
  queue->flag |= XS_LEVEL_FLAG;
1075
268
  mxReportModuleQueue("LOAD");
1076
960
  while (module) {
1077
825
    if (mxModuleStatus(module) == XS_MODULE_STATUS_NEW) {
1078
366
      txSlot* loader = mxModuleLoader(module);
1079
366
      txID moduleID = loader->value.module.id;
1080
366
      txSlot* realm = loader->value.module.realm;
1081
366
      mxTry(the) {
1082
366
        if (fxMapModule(the, realm, moduleID, module, queue, C_NULL)) {
1083
176
          module = queue;
1084
176
          done = 0;
1085
176
        }
1086
190
        else {
1087
190
          txSlot* loadHook = mxLoadHook(realm);
1088
190
          mxModuleStatus(module) = XS_MODULE_STATUS_LOADING;
1089
190
          if (mxIsUndefined(loadHook)) {
1090
133
            if (realm != mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm)
1091
62
              mxTypeError("no loadHook");
1092
71
            fxLoadModule(the, module, moduleID);
1093
71
            if (mxModuleExecute(module)->kind == XS_NULL_KIND)
1094
71
              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
57
          else {
1101
57
            done = 0;
1102
57
            mxModuleStatus(module) = XS_MODULE_STATUS_LOADING;
1103
            
1104
57
            mxPushUndefined();
1105
57
            mxPushSlot(loadHook);
1106
57
            mxCall();
1107
57
            fxPushKeyString(the, moduleID, C_NULL);
1108
57
            fxPushModuleOptions(the, loader->flag);
1109
57
            mxRunCount(2);
1110
            
1111
57
            fxLoadModulesPromise(the, queue, module, the->stack, fxLoadModulesFulfilled, fxLoadModulesRejected);
1112
1113
57
            mxPop();
1114
57
          }
1115
190
        }
1116
366
      }
1117
233
      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
366
    }
1124
459
    else if (mxModuleStatus(module) == XS_MODULE_STATUS_LOADING) {
1125
13
      done = 0;
1126
13
    }
1127
446
    else if (mxModuleStatus(module) == XS_MODULE_STATUS_LOADED) {
1128
145
      mxTry(the) {
1129
145
      #if mxModuleStuff
1130
145
        if (!fxLoadModuleStuffFrom(the, queue, module->value.reference, 0))
1131
145
      #endif
1132
145
          fxLoadModulesFrom(the, queue, module->value.reference, 0);
1133
145
        mxModuleStatus(module) = XS_MODULE_STATUS_LINKING;
1134
145
        module = queue;
1135
145
        done = 1;
1136
145
      }
1137
145
      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
145
    }
1144
692
    module = module->next;
1145
692
  }
1146
135
  queue->flag &= ~XS_LEVEL_FLAG;
1147
208
  if (done) {
1148
208
    mxTry(the) {
1149
208
      fxLinkModules(the, queue);
1150
208
    }
1151
208
    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
208
    fxExecuteModules(the, queue);
1165
208
  }
1166
135
}
1167
1168
void fxLoadModulesFrom(txMachine* the, txSlot* queue, txSlot* module, txBoolean now)
1169
185
{
1170
185
  txSlot* internal = mxModuleInstanceInternal(module);
1171
185
  txID moduleID = internal->value.module.id;
1172
185
  txSlot* realm = internal->value.module.realm;
1173
185
  txSlot* transfer = mxModuleInstanceTransfers(module)->value.reference->next;
1174
185
  txSlot* already = the->stack;
1175
601
  while (transfer) {
1176
416
    txSlot* from = mxTransferFrom(transfer);
1177
416
    if (from->kind != XS_NULL_KIND) {
1178
161
      txID importModuleID = XS_NO_ID;
1179
161
      txSlot* importModule;
1180
161
      txID status;
1181
161
      txSlot* former = the->stack;
1182
219
      while (former < already) {
1183
107
        if (!c_strcmp(former->value.string, from->value.string)) {
1184
49
          importModuleID = former->ID;
1185
49
          break;
1186
49
        }
1187
58
        former++;
1188
58
      }
1189
161
      if (importModuleID == XS_NO_ID) {
1190
112
        mxPushSlot(from);
1191
112
        importModuleID = fxResolveSpecifier(the, realm, moduleID, from);
1192
112
        the->stack->ID = importModuleID;
1193
112
      }
1194
161
      importModule = fxGetModule(the, realm, importModuleID, from->flag & XS_JSON_MODULE_FLAG);
1195
161
      if (!importModule) {
1196
101
        importModule = mxBehaviorSetProperty(the, mxOwnModules(realm)->value.reference, importModuleID, 0, XS_OWN);
1197
101
        fxNewModule(the, realm, importModuleID, from->flag & XS_JSON_MODULE_FLAG, importModule);
1198
101
      }
1199
161
      from->kind = XS_REFERENCE_KIND;
1200
161
      from->value.reference = importModule->value.reference;
1201
161
      status = mxModuleStatus(importModule);
1202
161
      if ((status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADED)) {
1203
151
        fxQueueModule(the, queue, importModule);
1204
151
      }
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
161
    }
1226
416
    transfer = transfer->next;
1227
416
  }
1228
185
  the->stack = already;
1229
185
}
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
13
{
1266
13
  txSlot* exports = fxNewInstance(the);
1267
13
  txSlot* export = exports;
1268
13
  txSlot* at;
1269
13
  txSlot* property;
1270
13
  at = fxNewInstance(the);
1271
13
  mxBehaviorOwnKeys(the, object, XS_EACH_NAME_FLAG, at);
1272
13
  mxTemporary(property);
1273
52
  while ((at = at->next)) {
1274
39
    if (at->value.at.id != XS_NO_ID) {
1275
35
      if (mxBehaviorGetOwnProperty(the, object, at->value.at.id, at->value.at.index, property) && !(property->flag & XS_DONT_ENUM_FLAG)) {
1276
21
        mxPushReference(object);
1277
21
        mxGetAll(at->value.at.id, at->value.at.index);
1278
21
        export = export->next = fxNewSlot(the);
1279
21
        export->ID = at->value.at.id;
1280
21
        export->value.export.closure = fxNewSlot(the);
1281
21
        export->value.export.closure->kind = the->stack->kind;
1282
21
        export->value.export.closure->value = the->stack->value;
1283
21
        export->value.export.module = module;
1284
21
        export->kind = XS_EXPORT_KIND;
1285
21
        mxPop();
1286
21
      }
1287
35
    }
1288
39
  }
1289
13
  mxPop();
1290
13
  mxPop();
1291
13
  mxPullSlot(mxModuleInstanceExports(module));
1292
13
}
1293
1294
void fxLoadVirtualModuleSource(txMachine* the, txSlot* record, txSlot* instance)
1295
65
{
1296
65
  txSlot* slot;
1297
65
  txSlot* function;
1298
65
  txSlot* property;
1299
65
  txSlot* transfers;
1300
65
  txSlot* transfer;
1301
  
1302
65
  mxPushSlot(record);
1303
65
  mxGetID(fxID(the, "execute"));
1304
65
  slot = the->stack;
1305
65
  if (!mxIsUndefined(slot)) {
1306
59
    if (!fxIsCallable(the, slot))
1307
0
      mxTypeError("execute: not a function");
1308
59
  }
1309
65
  function = fxNewHostFunction(the, fxExecuteVirtualModuleSource, 0, XS_NO_ID, mxExecuteVirtualModuleSourceProfileID);
1310
65
  property = mxFunctionInstanceHome(function);
1311
65
  property->value.home.object = fxToInstance(the, record);
1312
65
  property->value.home.module = instance;
1313
65
  property = fxLastProperty(the, function);
1314
65
  property = fxNextSlotProperty(the, property, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1315
65
  mxPullSlot(mxModuleInstanceExecute(instance));
1316
65
  mxPop(); // initialize
1317
      
1318
65
  mxPush(mxObjectPrototype);
1319
65
  transfers = fxNewObjectInstance(the);
1320
65
  transfer = fxLastProperty(the, transfers);
1321
  
1322
65
  mxPushSlot(record);
1323
65
  mxGetID(mxID(_bindings));
1324
65
  if (!mxIsUndefined(the->stack)) {
1325
47
    txSlot* array;
1326
47
    txInteger length, index;
1327
    
1328
47
    array = the->stack;
1329
47
    mxPushSlot(array);
1330
47
    mxGetID(mxID(_length));
1331
47
    length = fxToInteger(the, the->stack);
1332
47
    mxPop();
1333
    
1334
286
    for (index = 0; index < length; index++) {
1335
249
      txSlot* item;
1336
249
      txSlot* temporary;
1337
249
      txInteger from = 0;
1338
249
      txInteger export = 0;
1339
249
      txInteger import = 0;
1340
249
      txID nameID = 0, asID;
1341
249
      txSlot* specifier = C_NULL;
1342
249
      txSlot* former;
1343
1344
249
      mxPushSlot(array);
1345
249
      mxGetIndex(index);
1346
249
      item = the->stack;
1347
    
1348
249
      mxTemporary(temporary);
1349
    
1350
249
      mxPushSlot(item);
1351
249
      mxGetID(mxID(_from));
1352
249
      if (!mxIsUndefined(the->stack)) {
1353
81
        from++;
1354
81
        fxToString(the, the->stack);
1355
81
        mxPullSlot(temporary);
1356
81
        specifier = temporary;
1357
81
      }
1358
168
      else
1359
168
        mxPop();
1360
        
1361
249
      mxPushSlot(item);
1362
249
      mxGetID(fxID(the, "exportAllFrom"));
1363
249
      if (!mxIsUndefined(the->stack)) {
1364
35
        from++;
1365
35
        export++;
1366
35
        fxToString(the, the->stack);
1367
35
        mxPullSlot(temporary);
1368
35
        specifier = temporary;
1369
35
        nameID = XS_NO_ID;
1370
35
      }
1371
214
      else
1372
214
        mxPop();
1373
    
1374
249
      mxPushSlot(item);
1375
249
      mxGetID(fxID(the, "importAllFrom"));
1376
249
      if (!mxIsUndefined(the->stack)) {
1377
22
        from++;
1378
22
        import++;
1379
22
        fxToString(the, the->stack);
1380
22
        mxPullSlot(temporary);
1381
22
        specifier = temporary;
1382
22
        nameID = XS_NO_ID;
1383
22
      }
1384
227
      else
1385
227
        mxPop();
1386
    
1387
249
      mxPushSlot(item);
1388
249
      mxGetID(mxID(_export));
1389
249
      if (!mxIsUndefined(the->stack)) {
1390
142
        export++;
1391
142
        nameID = fxToID(the, the->stack);
1392
142
      }
1393
249
      mxPop();
1394
      
1395
249
      mxPushSlot(item);
1396
249
      mxGetID(mxID(_import));
1397
249
      if (!mxIsUndefined(the->stack)) {
1398
47
        import++;
1399
47
        nameID = fxToID(the, the->stack);
1400
47
      }
1401
249
      mxPop();
1402
    
1403
249
      mxPushSlot(item);
1404
249
      mxGetID(mxID(_as));
1405
249
      if (!mxIsUndefined(the->stack)) {
1406
111
        asID = fxToID(the, the->stack);
1407
111
      }
1408
138
      else
1409
138
        asID = nameID;
1410
249
      mxPop();
1411
        
1412
249
      if (from > 1)
1413
0
        mxSyntaxError("too many from");
1414
249
      else if (export > 1)
1415
0
        mxSyntaxError("too many export");
1416
249
      else if (import > 1)
1417
0
        mxSyntaxError("too many import");
1418
249
      else if (export && import)
1419
1
        mxSyntaxError("export and import");
1420
248
      else if (!export && !import)
1421
4
        mxSyntaxError("neither export nor import");
1422
      
1423
244
      if (export) {
1424
176
        if (asID != XS_NO_ID) {
1425
156
          former = transfers->next;
1426
470
          while (former) {
1427
315
            txSlot* aliases = mxTransferAliases(former);
1428
315
            if (!mxIsNull(aliases)) {
1429
240
              txSlot* alias = aliases->value.reference->next;
1430
491
              while (alias) {
1431
252
                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
251
                alias = alias->next;
1436
251
              }
1437
240
            }
1438
314
            former = former->next;
1439
314
          }
1440
155
          if (specifier) {
1441
49
            former = transfers->next;
1442
226
            while (former) {
1443
178
              txSlot* aliases = mxTransferAliases(former);
1444
178
              if (!mxIsNull(aliases)) {
1445
132
                txSlot* local = mxTransferLocal(former);
1446
132
                if (mxIsNull(local)) {
1447
26
                  txSlot* from = mxTransferFrom(former);
1448
26
                  if (!mxIsNull(from) && !c_strcmp(from->value.string, specifier->value.string)) {
1449
16
                    txSlot* import = mxTransferImport(former);
1450
16
                    if (mxIsNull(import)) {
1451
0
                      if (nameID == XS_NO_ID) 
1452
0
                        break;
1453
0
                    }
1454
16
                    else {
1455
16
                      if (nameID == import->value.symbol)
1456
1
                        break;
1457
16
                    }
1458
16
                  }
1459
26
                }
1460
132
              }
1461
177
              former = former->next;
1462
177
            }
1463
49
          }
1464
106
          else {
1465
106
            former = transfers->next;
1466
229
            while (former) {
1467
133
              txSlot* local = mxTransferLocal(former);
1468
133
              if ((local->kind == XS_SYMBOL_KIND) && (local->value.symbol == nameID))
1469
10
                break;
1470
123
              former = former->next;
1471
123
            }
1472
106
          }
1473
155
          if (former) {
1474
11
            txSlot* aliases = mxTransferAliases(former);
1475
11
            txSlot* alias;
1476
11
            if (mxIsNull(aliases)) {
1477
1
              mxPush(mxObjectPrototype);
1478
1
              alias = fxLastProperty(the, fxNewObjectInstance(the));
1479
1
              mxPullSlot(mxTransferAliases(former));
1480
1
            }
1481
10
            else {
1482
10
              alias = fxLastProperty(the, aliases->value.reference);
1483
10
            }
1484
11
            fxNextSymbolProperty(the, alias, asID, XS_NO_ID, XS_DONT_ENUM_FLAG);
1485
11
          }
1486
144
          else if (specifier) {
1487
48
            mxPushNull();
1488
48
            mxPushSlot(specifier);
1489
48
            if ((nameID != XS_NO_ID) || (asID != XS_NO_ID)) {
1490
48
              if (nameID != XS_NO_ID) 
1491
33
                mxPushSymbol(nameID);
1492
15
              else
1493
15
                mxPushNull();
1494
48
              if (asID != XS_NO_ID) 
1495
48
                mxPushSymbol(asID);
1496
0
              else      
1497
0
                mxPushSymbol(nameID);
1498
48
              mxPushInteger(4);
1499
48
            }
1500
0
            else { 
1501
0
              mxPushNull();
1502
0
              mxPushInteger(3);
1503
0
            }
1504
48
            fxPrepareTransfer(the, XS_NO_FLAG);
1505
48
            transfer = fxNextSlotProperty(the, transfer, the->stack, XS_NO_ID, XS_DONT_ENUM_FLAG);
1506
48
            mxPop(); // transfer
1507
48
          }
1508
96
          else {
1509
96
            mxPushSymbol(nameID);
1510
96
            mxPushNull();
1511
96
            mxPushNull();
1512
96
            mxPushSymbol(asID);
1513
96
            mxPushInteger(4);
1514
96
            fxPrepareTransfer(the, XS_NO_FLAG);
1515
96
            transfer = fxNextSlotProperty(the, transfer, the->stack, XS_NO_ID, XS_DONT_ENUM_FLAG);
1516
96
            mxPop(); // transfer
1517
96
          }
1518
155
        }
1519
20
        else if (specifier) {
1520
20
          former = transfers->next;
1521
116
          while (former) {
1522
97
            txSlot* from = mxTransferFrom(former);
1523
97
            if (!mxIsNull(from) && !c_strcmp(from->value.string, specifier->value.string)) {
1524
19
              txSlot* local = mxTransferLocal(former);
1525
19
              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
19
            }
1535
96
            former = former->next;
1536
96
          }
1537
19
          mxPushNull();
1538
19
          mxPushSlot(specifier);
1539
19
          mxPushNull();
1540
19
          mxPushInteger(3);
1541
19
          fxPrepareTransfer(the, XS_NO_FLAG);
1542
19
          transfer = fxNextSlotProperty(the, transfer, the->stack, XS_NO_ID, XS_DONT_ENUM_FLAG);
1543
19
          mxPop(); // transfer
1544
19
        }
1545
0
        else
1546
0
          mxSyntaxError("invalid export *");
1547
176
      }
1548
68
      else {
1549
68
        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
67
        else if (asID == XS_NO_ID)
1558
1
          mxSyntaxError("invalid import * from %s", specifier->value.string);
1559
      
1560
66
        former = transfers->next;
1561
271
        while (former) {
1562
208
          txSlot* local = mxTransferLocal(former);
1563
208
          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
205
          former = former->next;
1572
205
        }
1573
65
        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
63
        else {
1584
63
          mxPushSymbol(asID);
1585
63
          mxPushSlot(specifier);
1586
63
          if (nameID != XS_NO_ID)
1587
42
            mxPushSymbol(nameID);
1588
21
          else      
1589
21
            mxPushNull();
1590
63
          mxPushInteger(3);
1591
63
          fxPrepareTransfer(the, XS_NO_FLAG);
1592
63
          transfer = fxNextSlotProperty(the, transfer, the->stack, XS_NO_ID, XS_DONT_ENUM_FLAG);
1593
63
          mxPop(); // transfer
1594
63
        }
1595
65
      }  
1596
1597
239
      mxPop(); // temporary
1598
239
      mxPop(); // item
1599
239
    }
1600
47
  }
1601
55
  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
55
  mxPullSlot(mxModuleInstanceTransfers(instance));
1639
1640
55
  mxPushSlot(record);
1641
55
  mxGetID(mxID(_needsImport));
1642
55
  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
55
  mxPop(); // needsImport
1649
  
1650
55
  mxPushSlot(record);
1651
55
  mxGetID(mxID(_needsImportMeta));
1652
55
  if (!mxIsUndefined(the->stack)) {
1653
1
    if (fxToBoolean(the, the->stack)) {
1654
1
      txSlot* internal = mxModuleInstanceInternal(instance);
1655
1
      internal->flag |= XS_IMPORT_META_FLAG;
1656
1
    }
1657
1
  }
1658
55
  mxPop(); // _needsImportMeta
1659
55
}
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
719
  while (descriptor) {
1666
524
    if (descriptor->ID == moduleID) {
1667
257
      fxMapModuleDescriptor(the, realm, moduleID, module, queue, result,descriptor);
1668
257
      return 1;
1669
257
    }
1670
267
    descriptor = descriptor->next;
1671
267
  }
1672
195
  return 0;
1673
452
}
1674
1675
void fxMapModuleDescriptor(txMachine* the, txSlot* realm, txID moduleID, txSlot* module, txSlot* queue, txSlot* result, txSlot* descriptor)
1676
283
{
1677
283
  txSlot* property;
1678
283
  if (!mxIsReference(descriptor))
1679
15
    mxTypeError("descriptor: not an object");
1680
1681
268
  mxPushSlot(descriptor);
1682
268
  mxGetID(fxID(the, "namespace"));
1683
268
  property = the->stack;
1684
268
  if (!mxIsUndefined(property)) {
1685
49
    if ((property->kind == XS_STRING_KIND) || (property->kind == XS_STRING_X_KIND)) {
1686
35
      txSlot* aliasRealm;
1687
35
      txSlot* aliasOwn;
1688
35
      txID aliasModuleID;
1689
35
      txSlot* aliasModule;
1690
35
      mxPushSlot(descriptor);
1691
35
      mxGetID(fxID(the, "compartment"));
1692
35
      if (!mxIsUndefined(the->stack)) {
1693
30
        txSlot* program = fxCheckCompartmentInstance(the, the->stack);
1694
30
        aliasRealm = mxModuleInstanceInternal(program)->value.module.realm;
1695
30
      }
1696
5
      else {
1697
5
        aliasRealm = mxRealmParent(realm)->value.reference;
1698
5
      }
1699
35
      aliasOwn = mxOwnModules(aliasRealm)->value.reference;
1700
35
      mxPop();
1701
35
      aliasModuleID = fxResolveSpecifier(the, aliasRealm, XS_NO_ID, property);
1702
  //       if ((aliasRealm == realm) && (aliasModuleID == moduleID))
1703
  //         mxTypeError("descriptor.specifier is circular");
1704
      
1705
35
      aliasModule = mxBehaviorGetProperty(the, aliasOwn, aliasModuleID, 0, XS_ANY);
1706
35
      if (aliasModule) {
1707
20
        property = aliasModule;
1708
20
      }
1709
15
      else {
1710
15
        property = mxBehaviorSetProperty(the, aliasOwn, aliasModuleID, 0, XS_OWN);
1711
15
        fxNewModule(the, aliasRealm, aliasModuleID, XS_NO_FLAG, property);
1712
15
      }
1713
35
      goto namespace;
1714
35
    }
1715
14
    else {
1716
14
      txSlot* instance = module->value.reference;
1717
14
      if (!mxIsReference(property))
1718
1
        mxTypeError("descriptor.namespace: not an object");
1719
13
      if (mxIsModule(property->value.reference))
1720
0
        goto namespace;
1721
13
      fxLoadVirtualModuleNamespace(the, property->value.reference, instance);
1722
13
      txID status = mxModuleInstanceStatus(instance);
1723
13
      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
13
      goto done;
1734
13
    }
1735
    
1736
34
namespace:
1737
34
    if (module->kind == XS_UNDEFINED_KIND) {
1738
0
      module->kind = property->kind;
1739
0
      module->value = property->value;
1740
0
    }
1741
34
    else {
1742
34
      txID status = mxModuleStatus(module);
1743
34
      mxCheck(the, (status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADING));
1744
34
      mxPushSlot(module);
1745
34
      realm = mxModuleInternal(module)->value.module.realm;
1746
34
      fxOverrideModule(the, queue, mxOwnModules(realm), result, module->value.reference, property->value.reference);
1747
34
      status = mxModuleStatus(property);
1748
34
      if (result) {
1749
20
        if (status == XS_MODULE_STATUS_ERROR) {
1750
3
          mxPushSlot(mxModuleMeta(property));
1751
3
          mxPull(mxException);
1752
3
          fxJump(the);
1753
3
        }
1754
17
        else if (status == XS_MODULE_STATUS_EXECUTED) {
1755
8
        }
1756
9
        else {
1757
9
          fxQueueModule(the, queue, property);
1758
9
        }
1759
20
      }
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
31
      mxPop();
1780
31
    }
1781
31
    goto done;
1782
34
  }
1783
219
  mxPop(); // property;
1784
1785
219
  if (module->kind == XS_UNDEFINED_KIND)
1786
0
    fxNewModule(the, realm, moduleID, XS_NO_FLAG, module);
1787
219
  else {
1788
219
    txID status = mxModuleStatus(module);
1789
219
    mxCheck(the, (status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADING));
1790
219
  }
1791
  
1792
219
  mxPushSlot(descriptor);
1793
219
  mxGetID(fxID(the, "archive"));
1794
219
  property = the->stack;
1795
219
  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
219
  mxPop(); // property;
1831
  
1832
219
  mxPushSlot(descriptor);
1833
219
  mxGetID(fxID(the, "source"));
1834
219
  property = the->stack;
1835
219
  if (!mxIsUndefined(property)) {
1836
214
    if ((property->kind == XS_STRING_KIND) || (property->kind == XS_STRING_X_KIND)) {
1837
11
      txSlot* loader = mxModuleLoader(module);
1838
11
      loader->value.module.realm = mxRealmParent(realm)->value.reference;
1839
11
      if (property->kind == XS_STRING_X_KIND)
1840
0
        loader->value.module.id = fxNewNameX(the, property->value.string);
1841
11
      else
1842
11
        loader->value.module.id = fxNewName(the, property);
1843
11
      mxModuleStatus(module) = XS_MODULE_STATUS_NEW;
1844
11
      goto done;
1845
11
    }
1846
203
    if (!mxIsReference(property))
1847
3
      mxTypeError("descriptor.source: not an object");
1848
200
    if (mxIsModuleSource(property->value.reference))
1849
135
      fxDuplicateModuleTransfers(the, property, module);
1850
65
    else
1851
//      mxTypeError("descriptor.source is object");
1852
65
      fxLoadVirtualModuleSource(the, property, module->value.reference);
1853
200
    goto importMeta;
1854
203
  }
1855
5
  mxPop(); // property
1856
  
1857
5
  mxTypeError("invalid descriptor");
1858
  
1859
190
importMeta:
1860
190
  mxPop(); // property
1861
190
  mxModuleStatus(module) = XS_MODULE_STATUS_LOADED;
1862
  
1863
190
  mxPushSlot(descriptor);
1864
190
  mxGetID(fxID(the, "importMeta"));
1865
190
  property = the->stack;
1866
190
  if (!mxIsUndefined(property)) {
1867
86
    if (!mxIsReference(property))
1868
5
      mxTypeError("descriptor.importMeta: not an object");
1869
81
    txSlot* meta = mxModuleMeta(module);
1870
81
    if (mxIsNull(meta)) {
1871
81
      txSlot* instance = fxNewInstance(the);
1872
81
      meta->value.reference = instance;
1873
81
      meta->kind = XS_REFERENCE_KIND;
1874
81
    }
1875
81
    meta->value.reference->flag &= ~XS_DONT_PATCH_FLAG;
1876
81
    mxPushUndefined();
1877
81
    mxPush(mxAssignObjectFunction);
1878
81
    mxCall();
1879
81
    mxPushSlot(meta);
1880
81
    mxPushSlot(property);
1881
81
    mxRunCount(2);
1882
81
    mxPop();
1883
81
    meta->value.reference->flag |= XS_DONT_PATCH_FLAG;
1884
81
  }
1885
185
  mxPop(); // property
1886
  
1887
185
  mxPushSlot(descriptor);
1888
185
  mxGetID(fxID(the, "specifier"));
1889
185
  property = the->stack;
1890
185
  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
185
  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
441
{
1908
441
  txSlot* slot;
1909
  
1910
441
  mxPush(mxModulePrototype);
1911
441
  slot = fxNewObjectInstance(the);
1912
441
  slot->flag |= XS_EXOTIC_FLAG | XS_DONT_PATCH_FLAG;
1913
  /* HOST */
1914
441
  slot = slot->next = fxNewSlot(the);
1915
441
  slot->ID = XS_MODULE_BEHAVIOR;
1916
441
  slot->flag = XS_INTERNAL_FLAG | moduleFlag;
1917
441
  slot->kind = XS_MODULE_KIND;
1918
441
  slot->value.module.realm = realm;
1919
441
  slot->value.module.id = moduleID;
1920
  /* EXPORTS */
1921
441
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1922
  /* STUFF */
1923
441
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1924
  /* META */
1925
441
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1926
  /* TRANSFERS */
1927
441
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1928
  /* INITIALIZE */
1929
441
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1930
  /* FUNCTION */
1931
441
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1932
  /* HOSTS */
1933
441
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1934
  /* LOADER */
1935
441
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
1936
441
  slot->flag = XS_INTERNAL_FLAG | moduleFlag;
1937
441
  slot->kind = XS_MODULE_KIND;
1938
441
  slot->value.module.realm = realm;
1939
441
  slot->value.module.id = moduleID; 
1940
441
  module->kind = the->stack->kind;
1941
441
  module->value = the->stack->value;
1942
441
  mxPop();
1943
#if mxInstrument
1944
  the->loadedModulesCount++;
1945
#endif
1946
441
}
1947
1948
void fxOrderModule(txMachine* the, txSlot* queue, txSlot* order, txSlot* module)
1949
345
{
1950
345
  txSlot** fromAddress = &(queue->next);
1951
345
  txSlot** toAddress = &(order->next);
1952
345
  txSlot* from;
1953
345
  txSlot* to;
1954
345
  while ((from = *fromAddress)) {
1955
345
    if (from == module) {
1956
345
      *fromAddress = module->next;
1957
345
      module->next = C_NULL;
1958
345
      break;
1959
345
    }
1960
0
    fromAddress = &(from->next);
1961
0
  }
1962
345
  if (mxModuleStatus(module) == XS_MODULE_STATUS_LINKING) {
1963
172
    txSlot* transfer = mxModuleTransfers(module)->value.reference->next;
1964
567
    while (transfer) {
1965
395
      from = mxTransferFrom(transfer);
1966
395
      if (from->kind != XS_NULL_KIND) {
1967
145
        to = queue->next;
1968
158
        while (to) {
1969
109
          if (to->value.reference == from->value.reference)
1970
96
            break;
1971
13
          to = to->next;
1972
13
        }
1973
145
        if (to)
1974
96
          fxOrderModule(the, queue, order, to);
1975
145
      }
1976
395
      transfer = transfer->next;
1977
395
    }
1978
172
  }
1979
512
  while ((to = *toAddress)) {
1980
167
    if (to->value.reference == module->value.reference)
1981
0
      return;
1982
167
    toAddress = &(to->next);
1983
167
  }
1984
345
  *toAddress = module;
1985
345
}
1986
1987
void fxOverrideModule(txMachine* the, txSlot* queue, txSlot* list, txSlot* result, txSlot* module, txSlot* record)
1988
34
{
1989
34
  txSlot** address = &(queue->next);
1990
34
  txSlot* slot;
1991
78
  while ((slot = *address)) {
1992
44
    if (slot->value.reference == module) {
1993
//       slot->value.reference = record;
1994
34
      *address = slot->next;
1995
34
    }
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
44
    address = &(slot->next);
2008
44
  }
2009
34
  slot = list->value.reference->next;
2010
82
  while (slot) {
2011
48
    if (slot->value.reference == module) {
2012
34
      slot->value.reference = record;
2013
34
    }
2014
48
    slot = slot->next;
2015
48
  }
2016
34
  if (result) {
2017
20
    if (result->value.reference == module) {
2018
20
      result->value.reference = record;
2019
20
    }
2020
20
  }
2021
34
}
2022
2023
void fxPrepareModule(txMachine* the, txFlag flag)
2024
226
{
2025
226
  txSlot* module = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.module;
2026
226
  txInteger c = the->stack->value.integer, i;
2027
226
  txSlot* argument = the->stack + c;
2028
226
  txSlot* result = the->stack + c;
2029
226
  txSlot* slot;
2030
226
  txSlot* property;
2031
226
  property = mxModuleInstanceInternal(module); 
2032
226
  fxCheckModuleFlag(the, property->value.module.id, flag, property->flag);
2033
226
  property->flag |= flag;
2034
226
  slot = argument--;
2035
226
  property = mxModuleInstanceInitialize(module); 
2036
226
  property->kind = slot->kind;
2037
226
  property->value = slot->value;
2038
226
  slot = argument--;
2039
226
  property = mxModuleInstanceExecute(module); 
2040
226
  property->kind = slot->kind;
2041
226
  property->value = slot->value;
2042
226
  mxFunctionInstanceCode(slot->value.reference)->ID = mxModuleInstanceInternal(module)->value.module.id;
2043
226
  slot = &mxHosts; 
2044
226
  property = mxModuleInstanceHosts(module); 
2045
226
  property->kind = slot->kind;
2046
226
  property->value = slot->value;
2047
226
  mxPush(mxObjectPrototype);
2048
226
  slot = fxLastProperty(the, fxNewObjectInstance(the));
2049
718
  for (i = 2; i < c; i++)
2050
492
    slot = fxNextSlotProperty(the, slot, argument--, XS_NO_ID, XS_DONT_ENUM_FLAG);
2051
226
  property = mxModuleInstanceTransfers(module); 
2052
226
  mxPullSlot(property);
2053
226
  result->kind = XS_REFERENCE_KIND;
2054
226
  result->value.reference = module;
2055
226
  the->stack = result;
2056
226
}
2057
2058
void fxPrepareTransfer(txMachine* the, txFlag flag)
2059
718
{
2060
718
  txInteger c = the->stack->value.integer, i;
2061
718
  txSlot* argument = the->stack + c;
2062
718
  txSlot* result = the->stack + c;
2063
718
  txSlot* property;
2064
718
  txSlot* slot;
2065
718
  mxPush(mxTransferPrototype);
2066
718
  property = fxNewObjectInstance(the);
2067
718
  property = fxNextSlotProperty(the, property, argument--, mxID(_local), XS_DONT_ENUM_FLAG);
2068
718
  property = fxNextSlotProperty(the, property, argument--, mxID(_from), XS_DONT_ENUM_FLAG | flag);
2069
718
  property = fxNextSlotProperty(the, property, argument--, mxID(_import), XS_DONT_ENUM_FLAG);
2070
718
  if (c > 3) {
2071
510
    mxPush(mxObjectPrototype);
2072
510
    slot = fxLastProperty(the, fxNewObjectInstance(the));
2073
510
    if (argument->kind != XS_NULL_KIND) {
2074
1.01k
      for (i = 3; i < c; i++)
2075
510
        slot = fxNextSlotProperty(the, slot, argument--, XS_NO_ID, XS_DONT_ENUM_FLAG);
2076
506
    }
2077
510
    property = fxNextSlotProperty(the, property, the->stack, mxID(_aliases), XS_DONT_ENUM_FLAG);
2078
510
    mxPop();
2079
510
  }
2080
208
  else {
2081
208
    property = fxNextNullProperty(the, property, mxID(_aliases), XS_DONT_ENUM_FLAG);
2082
208
  }
2083
718
  property = fxNextNullProperty(the, property, mxID(_closure), XS_DONT_ENUM_FLAG);
2084
718
  result->kind = the->stack->kind;
2085
718
  result->value = the->stack->value;
2086
718
  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
718
}
2099
2100
txBoolean fxQueueModule(txMachine* the, txSlot* queue, txSlot* module)
2101
494
{
2102
494
  txSlot** address = &(queue->next);
2103
494
  txSlot* slot;
2104
759
  while ((slot = *address)) {
2105
318
    if (slot->value.reference == module->value.reference)
2106
53
      return 0;
2107
265
    address = &(slot->next);
2108
265
  }
2109
441
  slot = *address = fxNewSlot(the);
2110
441
  slot->ID = mxModuleInternal(module)->value.module.id; //??
2111
441
  slot->kind = XS_REFERENCE_KIND;
2112
441
  slot->value.reference = module->value.reference;
2113
441
  return 1;
2114
494
}
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
23.5k
{
2146
23.5k
  if (moduleID == XS_NO_ID) {
2147
23.4k
    if (realm == mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm) {
2148
23.1k
      moduleID = fxFindModule(the, realm, XS_NO_ID, name);
2149
23.1k
      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
23.1k
    }
2154
320
    else {
2155
320
      if (name->kind == XS_STRING_X_KIND)
2156
0
        moduleID = fxNewNameX(the, name->value.string);
2157
320
      else
2158
320
        moduleID = fxNewName(the, name);
2159
320
    }
2160
23.4k
  }
2161
112
  else {
2162
112
    txSlot* resolveHook = mxResolveHook(realm);
2163
139
    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
112
    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
85
    else {
2181
85
      mxPushUndefined();
2182
85
      mxPushSlot(resolveHook);
2183
85
      mxCall();
2184
85
      mxPushSlot(name);
2185
85
      fxPushKeyString(the, moduleID, C_NULL);
2186
85
      mxRunCount(2);
2187
85
      moduleID = fxToID(the, the->stack);
2188
85
      mxPop();
2189
85
    }
2190
112
  }
2191
23.5k
  name->kind = XS_SYMBOL_KIND;
2192
23.5k
  name->value.symbol = moduleID;
2193
23.5k
  return moduleID;
2194
23.5k
}
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
23.3k
{
2207
23.3k
  txSlot* stack = the->stack + 1;
2208
23.3k
  txSlot* promise;
2209
23.3k
  txSlot* fulfillFunction;
2210
23.3k
  txSlot* rejectFunction;
2211
23.3k
  txSlot* module;
2212
23.3k
  txID status;
2213
23.3k
  txSlot* slot;
2214
  
2215
23.3k
  fxBeginHost(the);
2216
23.3k
  mxPush(mxPromisePrototype);
2217
23.3k
  promise = fxNewPromiseInstance(the);
2218
23.3k
  mxPromiseStatus(promise)->value.integer = mxPendingStatus;
2219
23.3k
  fxPushPromiseFunctions(the, promise);
2220
23.3k
  fulfillFunction = the->stack + 1;
2221
23.3k
  rejectFunction = the->stack;
2222
23.3k
  {
2223
23.3k
    mxTry(the) {
2224
23.3k
      module = fxRunImportAux(the, realm, referrer, stack, stack - 1, 0);
2225
23.3k
      status = mxModuleStatus(module);
2226
23.3k
      if (status == XS_MODULE_STATUS_ERROR) {
2227
        /* THIS */
2228
23.0k
        mxPushUndefined();
2229
        /* FUNCTION */
2230
23.0k
        mxPushSlot(rejectFunction);
2231
23.0k
        mxCall();
2232
        /* ARGUMENTS */
2233
23.0k
        mxPushSlot(mxModuleMeta(module));
2234
23.0k
        mxRunCount(1);
2235
23.0k
      }
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
266
            fxLoadModules(the, queue);
2255
//        }
2256
271
      }
2257
23.3k
    }
2258
23.3k
    mxCatch(the) {
2259
2
      fxRejectException(the, rejectFunction);
2260
2
    }
2261
23.3k
  }
2262
23.3k
  fxEndHost(the);
2263
23.3k
  stack->value.reference = promise;
2264
23.3k
  stack->kind = XS_REFERENCE_KIND;
2265
23.3k
  the->stack = stack;
2266
23.3k
}
2267
2268
txSlot* fxRunImportAux(txMachine* the, txSlot* realm, txSlot* referrer, txSlot* specifier, txSlot* options, txBoolean now)
2269
23.4k
{
2270
23.4k
  txSlot* module;
2271
23.4k
  txID moduleID;
2272
23.4k
  txFlag moduleFlag = fxCheckModuleOptions(the, options);
2273
23.4k
#if mxModuleStuff
2274
23.4k
  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
23.4k
#endif
2294
23.4k
  fxToString(the, specifier);
2295
23.4k
  if (referrer) {
2296
23.1k
#if mxModuleStuff
2297
23.1k
    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
23.1k
#endif
2309
23.1k
    moduleID = fxResolveSpecifier(the, realm, mxModuleInstanceInternal(referrer)->value.module.id, specifier);
2310
23.1k
  }
2311
293
  else
2312
293
    moduleID = fxResolveSpecifier(the, realm, XS_NO_ID, specifier);
2313
23.4k
  module = fxGetModule(the, realm, moduleID, moduleFlag);
2314
23.4k
  if (!module) {
2315
326
    module = mxBehaviorSetProperty(the, mxOwnModules(realm)->value.reference, moduleID, 0, XS_OWN);
2316
326
    fxNewModule(the, realm, moduleID, moduleFlag, module);
2317
326
  }
2318
23.4k
  return module;
2319
23.4k
}
2320
2321
void fxRunImportFulfilled(txMachine* the, txSlot* module, txSlot* with)
2322
88
{
2323
88
  if (mxModuleInstanceMeta(module)->next) {
2324
88
    txSlot* stack = the->stack;
2325
88
    txSlot* slot = mxModuleInstanceFulfill(module);
2326
148
    while (slot) {
2327
60
      mxPushSlot(slot);
2328
60
      slot = slot->next;
2329
60
      slot = slot->next;
2330
60
    }
2331
88
    mxModuleInstanceMeta(module)->next = C_NULL;
2332
88
    slot = stack;
2333
148
    while (slot > the->stack) {
2334
60
      slot--;
2335
      /* THIS */
2336
60
      mxPushUndefined();
2337
      /* FUNCTION */
2338
60
      mxPushSlot(slot);
2339
60
      mxCall();
2340
      /* ARGUMENTS */
2341
60
      mxPushReference(with);
2342
60
      mxRunCount(1);
2343
60
      mxPop();
2344
60
    }
2345
88
    the->stack = stack;
2346
88
  }
2347
88
}
2348
2349
void fxRunImportRejected(txMachine* the, txSlot* module, txSlot* with)
2350
241
{
2351
241
  if (mxModuleInstanceMeta(module)->next) {
2352
241
    txSlot* stack = the->stack;
2353
241
    txSlot* slot = mxModuleInstanceFulfill(module);
2354
241
    txSlot* exception;
2355
421
    while (slot) {
2356
180
      slot = slot->next;
2357
180
      mxPushSlot(slot);
2358
180
      slot = slot->next;
2359
180
    }
2360
241
    mxModuleInstanceMeta(module)->next = C_NULL;
2361
241
    exception = mxModuleInstanceMeta(with);
2362
241
    slot = stack;
2363
421
    while (slot > the->stack) {
2364
180
      slot--;
2365
      /* THIS */
2366
180
      mxPushUndefined();
2367
      /* FUNCTION */
2368
180
      mxPushSlot(slot);
2369
180
      mxCall();
2370
      /* ARGUMENTS */
2371
180
      mxPushSlot(exception);
2372
180
      mxRunCount(1);
2373
180
      mxPop();
2374
180
    }
2375
241
    the->stack = stack;
2376
241
  }
2377
241
}
2378
2379
/* META */
2380
2381
void fxRunImportMeta(txMachine* the, txSlot* module)
2382
50
{
2383
50
  txSlot* meta = mxModuleInstanceMeta(module);
2384
50
  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
50
  mxPushSlot(meta);
2409
50
}
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
69
{
2465
69
  txSlot* stack = the->stack + 1;
2466
69
  txSlot* module = fxRunImportAux(the, realm, referrer, stack, stack - 1, 1);
2467
69
  txID status = mxModuleStatus(module);
2468
69
  if ((status == XS_MODULE_STATUS_NEW) || (status == XS_MODULE_STATUS_LOADED)) {
2469
60
    txSlot* result = stack;
2470
60
    txSlot* queue = fxNewInstance(the);
2471
60
    mxTry(the) {
2472
60
      txBoolean done = 1;
2473
60
      result->kind = module->kind;
2474
60
      result->value = module->value;
2475
2476
60
      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
60
      mxReportModuleQueue("LOAD");
2483
60
      module = queue->next;
2484
228
      while (module) {
2485
186
        if (mxModuleStatus(module) == XS_MODULE_STATUS_NEW) {
2486
86
          txSlot* loader = mxModuleLoader(module);
2487
86
          txID moduleID = loader->value.module.id;
2488
86
          txSlot* realm = loader->value.module.realm;
2489
86
          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
68
          module = queue;
2515
68
          done = 1;
2516
68
          mxReportModuleQueue("LOAD");
2517
68
        }
2518
100
        else if (mxModuleStatus(module) == XS_MODULE_STATUS_LOADING) {
2519
0
          done = 0;
2520
0
        }
2521
100
        else if (mxModuleStatus(module) == XS_MODULE_STATUS_LOADED) {
2522
40
        #if mxModuleStuff
2523
40
          if (!fxLoadModuleStuffFrom(the, queue, module->value.reference, 1))
2524
40
        #endif
2525
40
            fxLoadModulesFrom(the, queue, module->value.reference, 1);
2526
40
          mxModuleStatus(module) = XS_MODULE_STATUS_LINKING;
2527
40
          module = queue;
2528
40
          done = 1;
2529
40
        }
2530
168
        module = module->next;
2531
168
      }
2532
42
      if (!done)
2533
0
        mxTypeError("async queue");
2534
42
      fxLinkModules(the, queue);
2535
42
      mxReportModuleQueue("INIT");
2536
42
      module = queue->next;
2537
76
      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
42
      mxPop();
2558
42
    }
2559
42
    mxCatch(the) {
2560
32
      module = queue->next;
2561
66
      while (module) {
2562
34
        if (mxModuleStatus(module) < XS_MODULE_STATUS_EXECUTED) {
2563
34
          fxCompleteModule(the, module->value.reference, &mxException);
2564
34
          mxModuleMeta(module)->next = C_NULL;
2565
34
        }
2566
34
        module = module->next;
2567
34
      }
2568
32
      mxPushUndefined();
2569
32
      mxPull(mxHosts);
2570
32
      fxJump(the);
2571
32
    }
2572
60
  }
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
16
  the->stack = stack;
2586
16
}
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
112
{
2699
112
  if (id == XS_NO_ID)
2700
0
    return C_NULL;
2701
112
  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
112
  {
2710
112
    txSlot* exports = mxModuleInstanceExports(instance);
2711
112
    if (mxIsReference(exports)) {
2712
112
      txSlot* property = exports->value.reference->next;
2713
305
      while (property) {
2714
218
        if (property->ID == id) {
2715
25
          property = property->value.export.closure;
2716
25
          if (property && (property->kind == XS_UNINITIALIZED_KIND)) {
2717
1
            return &mxModuleAccessor;
2718
1
          }
2719
24
          return property;
2720
25
        }
2721
193
        property = property->next;
2722
193
      }
2723
112
    }
2724
112
  }
2725
87
  return C_NULL;
2726
112
}
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
379
{
2841
379
  if (slot->kind == XS_REFERENCE_KIND) {
2842
378
    txSlot* instance = slot->value.reference;
2843
378
    if (((slot = instance->next)) && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_PROGRAM_KIND)) {
2844
378
      return instance;
2845
378
    }
2846
378
  }
2847
379
  mxTypeError("this: not a Compartment instance");
2848
0
  return C_NULL;
2849
379
}
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
441
{
2868
441
  txSlot* module = mxFunctionInstanceHome(mxFunction->value.reference)->value.home.module;
2869
441
  txSlot* program = C_NULL;
2870
441
  txSlot* parent;
2871
441
  txSlot* realm;
2872
441
  txSlot* global = C_NULL;
2873
441
  txSlot* closures = C_NULL;
2874
441
  txSlot* slot;
2875
441
  txSlot* target;
2876
441
  txSlot* own;
2877
441
  txInteger id;
2878
  
2879
441
  if (!module) module = mxProgram.value.reference;
2880
441
  mxTry(the) {
2881
441
    if (mxIsUndefined(mxTarget))
2882
1
      mxTypeError("call: Compartment");
2883
      
2884
440
    mxPushSlot(mxTarget);
2885
440
    fxGetPrototypeFromConstructor(the, &mxCompartmentPrototype);
2886
440
    program = fxNewProgramInstance(the);
2887
440
    mxPullSlot(mxResult);
2888
    
2889
    // PARENT
2890
440
    parent = mxModuleInstanceInternal(module)->value.module.realm;
2891
440
    mxPushReference(parent);
2892
    
2893
    // GLOBALS
2894
440
    if (the->sharedMachine == C_NULL) {
2895
440
      txSlot* instance;
2896
440
      txSlot* property;
2897
440
      txSlot* callback;
2898
440
      mxPush(mxObjectPrototype);
2899
  #ifdef mxLink
2900
      global = fxNewObjectInstance(the);
2901
  #else
2902
440
      global = fxNewGlobalInstance(the);
2903
440
  #endif
2904
440
      slot = fxLastProperty(the, global);
2905
440
      if (mxCompartmentGlobal.kind == XS_UNDEFINED_KIND) {
2906
27.2k
        for (id = XS_SYMBOL_ID_COUNT; id < _Infinity; id++)
2907
26.8k
          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
440
      }
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
440
      callback = mxFunctionInstanceCode(mxCompartmentConstructor.value.reference);
2926
440
      instance = fxBuildHostFunction(the, callback->value.callback.address, 1, mxID(_Compartment));
2927
440
      instance->flag |= XS_CAN_CONSTRUCT_FLAG;
2928
440
      property = fxLastProperty(the, instance);
2929
440
      fxNextSlotProperty(the, property, &mxCompartmentPrototype, mxID(_prototype), XS_GET_ONLY);
2930
440
      fxPrepareCompartmentFunction(the, program, instance);
2931
440
      slot = fxNextSlotProperty(the, slot, the->stack, mxID(_Compartment), XS_DONT_ENUM_FLAG);
2932
440
      mxPop();
2933
      
2934
440
      callback = mxFunctionInstanceCode(mxFunctionConstructor.value.reference);
2935
440
      instance = fxBuildHostFunction(the, callback->value.callback.address, 1, mxID(_Function));
2936
440
      instance->flag |= XS_CAN_CONSTRUCT_FLAG;
2937
440
      property = fxLastProperty(the, instance);
2938
440
      fxNextSlotProperty(the, property, &mxFunctionPrototype, mxID(_prototype), XS_GET_ONLY);
2939
440
      fxPrepareCompartmentFunction(the, program, instance);
2940
440
      slot = fxNextSlotProperty(the, slot, the->stack, mxID(_Function), XS_DONT_ENUM_FLAG);
2941
440
      mxPop();
2942
      
2943
440
    #if mxModuleStuff   
2944
440
      callback = mxFunctionInstanceCode(mxModuleStuffConstructor.value.reference);
2945
440
      instance = fxBuildHostFunction(the, callback->value.callback.address, 1, mxID(_ModuleStuff));
2946
440
      instance->flag |= XS_CAN_CONSTRUCT_FLAG;
2947
440
      property = fxLastProperty(the, instance);
2948
440
      fxNextSlotProperty(the, property, &mxModuleStuffPrototype, mxID(_prototype), XS_GET_ONLY);
2949
440
      fxPrepareCompartmentFunction(the, program, instance);
2950
440
      slot = fxNextSlotProperty(the, slot, the->stack, mxID(_ModuleStuff), XS_DONT_ENUM_FLAG);
2951
440
      mxPop();
2952
440
    #endif
2953
      
2954
440
      callback = mxFunctionInstanceCode(mxEvalFunction.value.reference);
2955
440
      instance = fxBuildHostFunction(the, callback->value.callback.address, 1, mxID(_eval));
2956
440
      fxPrepareCompartmentFunction(the, program, instance);
2957
440
      slot = fxNextSlotProperty(the, slot, the->stack, mxID(_eval), XS_DONT_ENUM_FLAG);
2958
440
      mxPop();
2959
440
    }
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
440
    slot = fxNextSlotProperty(the, slot, the->stack, mxID(_global), XS_DONT_ENUM_FLAG);
2973
440
    slot = fxNextSlotProperty(the, slot, the->stack, mxID(_globalThis), XS_DONT_ENUM_FLAG);
2974
    
2975
440
    if (mxArgc > 0) {
2976
416
      if (!mxIsReference(mxArgv(0)))
2977
27
        mxTypeError("options: not an object");
2978
    
2979
389
      mxPushSlot(mxArgv(0));
2980
389
      if (mxHasID(fxID(the, "globals"))) {
2981
25
        mxPushSlot(mxArgv(0));
2982
25
        mxGetID(fxID(the, "globals"));
2983
25
        slot = the->stack;
2984
25
        if (!mxIsReference(slot))
2985
10
          mxTypeError("options.globals: not an object");
2986
15
        mxPushUndefined();
2987
15
        mxPush(mxAssignObjectFunction);
2988
15
        mxCall();
2989
15
        mxPushReference(global);
2990
15
        mxPushSlot(slot);
2991
15
        mxRunCount(2);
2992
15
        mxPop();
2993
15
        mxPop(); // globals
2994
15
      }
2995
      
2996
379
      target = fxNewInstance(the);
2997
379
      own = fxNewInstance(the);
2998
379
      mxPushSlot(mxArgv(0));
2999
379
      if (mxHasID(fxID(the, "modules"))) {
3000
202
        txSlot* source;
3001
202
        txSlot* at;
3002
202
        txSlot* temporary;
3003
202
        mxPushSlot(mxArgv(0));
3004
202
        mxGetID(fxID(the, "modules"));
3005
202
        if (!mxIsReference(the->stack))
3006
18
          mxTypeError("options.modules: not an object");
3007
184
        source = the->stack->value.reference;
3008
184
        at = fxNewInstance(the);
3009
184
        mxBehaviorOwnKeys(the, source, XS_EACH_NAME_FLAG, at);
3010
184
        mxTemporary(temporary);
3011
542
        while ((at = at->next)) {
3012
358
          if (mxBehaviorGetOwnProperty(the, source, at->value.at.id, at->value.at.index, temporary) && !(temporary->flag & XS_DONT_ENUM_FLAG)) {
3013
341
            txSlot* descriptor;
3014
341
            txSlot* property;
3015
341
            mxPushReference(source);
3016
341
            mxGetAll(at->value.at.id, at->value.at.index);
3017
341
            descriptor = the->stack;
3018
341
            property = mxBehaviorSetProperty(the, target, at->value.at.id, at->value.at.index, XS_OWN);
3019
341
            property->kind = descriptor->kind;
3020
341
            property->value = descriptor->value;
3021
341
            mxPop(); // descriptor
3022
341
          }
3023
358
        }
3024
184
        mxPop(); // temporary
3025
184
        mxPop(); // at
3026
184
        mxPop(); // modules
3027
184
      }
3028
      
3029
361
      mxPushUndefined();
3030
361
      closures = fxNewEnvironmentInstance(the, C_NULL);
3031
361
      mxPushSlot(mxArgv(0));
3032
361
      if (mxHasID(fxID(the, "globalLexicals"))) {
3033
39
        txSlot* target = fxLastProperty(the, closures);
3034
39
        txSlot* source;
3035
39
        txSlot* at;
3036
39
        txSlot* property;
3037
39
        mxPushSlot(mxArgv(0));
3038
39
        mxGetID(fxID(the, "globalLexicals"));
3039
39
        if (!mxIsReference(the->stack))
3040
23
          mxTypeError("options.globalLexicals: not an object");
3041
16
        source = the->stack->value.reference;
3042
16
        at = fxNewInstance(the);
3043
16
        mxBehaviorOwnKeys(the, source, XS_EACH_NAME_FLAG, at);
3044
16
        mxTemporary(property);
3045
66
        while ((at = at->next)) {
3046
50
          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
35
            mxPushReference(source);
3048
35
            mxGetAll(at->value.at.id, at->value.at.index);
3049
35
            target = target->next = fxNewSlot(the);
3050
35
            target->value.closure = fxNewSlot(the);;
3051
35
            target->kind = XS_CLOSURE_KIND;
3052
35
            target->ID = at->value.at.id;
3053
35
            if (property->kind == XS_ACCESSOR_KIND)
3054
10
              target->value.closure->flag = property->value.accessor.setter ? XS_NO_FLAG : XS_DONT_SET_FLAG;
3055
25
            else
3056
25
              target->value.closure->flag = property->flag & XS_DONT_SET_FLAG;
3057
35
            target->value.closure->kind = the->stack->kind;
3058
35
            target->value.closure->value = the->stack->value;
3059
35
            mxPop();
3060
35
          }
3061
50
        }
3062
16
        mxPop(); // property
3063
16
        mxPop(); // at
3064
16
        mxPop(); // globalLexicals
3065
16
      }
3066
  
3067
338
      mxPushSlot(mxArgv(0));
3068
338
      if (mxHasID(fxID(the, "resolveHook"))) {
3069
165
        mxPushSlot(mxArgv(0));
3070
165
        mxGetID(fxID(the, "resolveHook"));
3071
165
        if (!fxIsCallable(the, the->stack))
3072
12
          mxTypeError("options.resolveHook: not a function");
3073
165
      }
3074
173
      else
3075
173
        mxPushUndefined();
3076
      
3077
326
      mxPushUndefined(); // moduleMapHook;
3078
      
3079
326
      mxPushSlot(mxArgv(0));
3080
326
      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
323
      else {
3087
323
        mxPushSlot(mxArgv(0));
3088
323
        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
291
        else
3095
291
          mxPushUndefined();
3096
323
      }
3097
        
3098
314
      mxPushSlot(mxArgv(0));
3099
314
      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
305
      else {
3106
305
        mxPushSlot(mxArgv(0));
3107
305
        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
279
        else
3114
279
          mxPushUndefined();
3115
305
      }
3116
      
3117
300
      mxPushUndefined(); // importMetaHook;
3118
300
    }
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
324
    realm = fxNewRealmInstance(the);
3134
324
    mxModuleInstanceInternal(program)->value.module.realm = realm;
3135
    
3136
324
    slot = own->next;
3137
324
    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
324
    mxPop();
3148
324
  }
3149
324
  mxCatch(the) {
3150
118
    fxJump(the);
3151
118
  }
3152
441
}
3153
3154
void fx_Compartment_prototype_get_globalThis(txMachine* the)
3155
25
{
3156
25
  txSlot* program = fxCheckCompartmentInstance(the, mxThis);
3157
25
  txSlot* realm = mxModuleInstanceInternal(program)->value.module.realm;
3158
25
  txSlot* global = mxRealmGlobal(realm);
3159
25
  mxResult->kind = global->kind;
3160
25
  mxResult->value = global->value;
3161
25
}
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
222
{
3179
222
  txSlot* program = fxCheckCompartmentInstance(the, mxThis);
3180
222
  txSlot* realm = mxModuleInstanceInternal(program)->value.module.realm;
3181
222
  if (mxArgc > 0)
3182
221
    mxPushSlot(mxArgv(0));
3183
1
  else
3184
1
    mxPushUndefined();
3185
222
  if (mxArgc > 1)
3186
0
    mxPushSlot(mxArgv(1));
3187
222
  else
3188
222
    mxPushUndefined();
3189
222
  gxDefaults.runImport(the, realm, C_NULL);
3190
222
  mxPullSlot(mxResult);
3191
222
}
3192
3193
void fx_Compartment_prototype_importNow(txMachine* the)
3194
69
{
3195
69
  txSlot* program = fxCheckCompartmentInstance(the, mxThis);
3196
69
  txSlot* realm = mxModuleInstanceInternal(program)->value.module.realm;
3197
69
  if (mxArgc > 0)
3198
69
    mxPushSlot(mxArgv(0));
3199
0
  else
3200
0
    mxPushUndefined();
3201
69
  if (mxArgc > 1)
3202
0
    mxPushSlot(mxArgv(1));
3203
69
  else
3204
69
    mxPushUndefined();
3205
69
  fxRunImportNow(the, realm, C_NULL);
3206
69
  mxPullSlot(mxResult);
3207
69
}
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
4.33k
{
3223
4.33k
  txSlot* instance;
3224
4.33k
  txSlot* slot;
3225
4.33k
  instance = fxNewSlot(the);
3226
4.33k
  instance->kind = XS_INSTANCE_KIND;
3227
4.33k
  instance->value.instance.garbage = C_NULL;
3228
4.33k
  instance->value.instance.prototype = the->stack->value.reference;
3229
4.33k
  the->stack->kind = XS_REFERENCE_KIND;
3230
4.33k
  the->stack->value.reference = instance;
3231
  /* HOST */
3232
4.33k
  slot = instance->next = fxNewSlot(the);
3233
4.33k
  slot->flag = XS_INTERNAL_FLAG;
3234
4.33k
  slot->kind = XS_MODULE_SOURCE_KIND;
3235
4.33k
  slot->value.module.realm = C_NULL;
3236
4.33k
  slot->value.module.id = XS_NO_ID;
3237
  /* EXPORTS */
3238
4.33k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3239
  /* STUFF */
3240
4.33k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3241
  /* META */
3242
4.33k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3243
  /* TRANSFERS */
3244
4.33k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3245
  /* INITIALIZE */
3246
4.33k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3247
  /* FUNCTION */
3248
4.33k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3249
  /* HOSTS */
3250
4.33k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3251
  /* LOADER */
3252
4.33k
  slot = fxNextNullProperty(the, slot, XS_NO_ID, XS_INTERNAL_FLAG);
3253
4.33k
  return instance;
3254
4.33k
}
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
4.33k
{
3269
4.33k
  txSlot* instance;
3270
4.33k
  txUnsigned flags = mxDebugFlag;
3271
4.33k
  txSlot* slot;
3272
4.33k
  txStringStream stream;
3273
4.33k
  txScript* script;
3274
4.33k
  if (mxIsUndefined(mxTarget))
3275
1
    mxTypeError("call: ModuleSource");
3276
4.33k
  mxPushSlot(mxTarget);
3277
4.33k
  fxGetPrototypeFromConstructor(the, &mxModuleSourcePrototype);
3278
4.33k
  instance = fxNewModuleSourceInstance(the);
3279
4.33k
  mxPullSlot(mxResult);
3280
4.33k
  if (mxArgc > 0)
3281
4.33k
    mxPushSlot(mxArgv(0));
3282
1
  else    
3283
1
    mxPushUndefined();
3284
4.33k
  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
4.33k
  slot = the->stack;
3291
4.33k
  stream.slot = slot;
3292
4.33k
  stream.offset = 0;
3293
4.33k
  stream.size = mxStringLength(fxToString(the, slot));
3294
4.33k
  script = fxParseScript(the, &stream, fxStringGetter, flags);
3295
//    mxPushClosure(mxResult);
3296
4.33k
  fxRunScript(the, script, mxResult, C_NULL, C_NULL, C_NULL, instance);
3297
4.33k
  mxPop();
3298
4.33k
  if (mxModuleInstanceExecute(instance)->kind == XS_NULL_KIND)
3299
0
    mxTypeError("no module");
3300
4.33k
  mxPop();
3301
4.33k
  mxPop();
3302
4.33k
}
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
185
{
3532
185
  txSlot* realm = mxModuleInstanceInternal(module)->value.module.realm;
3533
185
  txSlot* reference = mxModuleInstanceHook(module);
3534
185
  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
185
  return 0;
3556
185
}
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