Coverage Report

Created: 2025-08-03 06:59

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