Coverage Report

Created: 2025-10-28 07:25

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