Coverage Report

Created: 2026-06-10 07:01

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