Coverage Report

Created: 2026-07-16 06:39

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