Coverage Report

Created: 2026-09-03 07:12

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