async requestModule()

in packages/ice/src/service/Runner.ts [145:241]


  async requestModule(id: string, _callstack: string[] = [], namespace = '') {
    const mod = this.moduleCache.get(id);
    const callstack = [..._callstack, id];
    let { code: transformed, externalize } = await this.options.load({
      path: id,
      namespace,
    });
    const request = async (dep: string) => {
      const { id: requestId, namespace } = await this.resolveUrl(dep, id);
      return this.dependencyRequest(requestId, callstack, namespace);
    };

    if (externalize) {
      const exports = await this.interopedImport(externalize);
      mod.exports = exports;
      return exports;
    }

    const { href } = pathToFileURL(id);
    const meta = {
      url: href,
      ...this.importMeta,
    };
    const exports = Object.create(null);

    // this proxy is triggered only on exports.{name} and module.exports access
    const cjsExports = new Proxy(exports, {
      set: (_, p, value) => {
        // treat "module.exports =" the same as "exports.default =" to not have nested "default.default",
        // so "exports.default" becomes the actual module
        if (p === 'default' && this.shouldInterop(id, { default: value })) {
          exportAll(cjsExports, value);
          exports.default = value;
          return true;
        }

        if (!Reflect.has(exports, 'default')) exports.default = {};

        // returns undefined, when accessing named exports, if default is not an object
        // but is still present inside hasOwnKeys, this is Node behaviour for CJS
        if (isPrimitive(exports.default)) {
          defineExport(exports, p, () => undefined);
          return true;
        }

        exports.default[p] = value;
        if (p !== 'default') defineExport(exports, p, () => value);

        return true;
      },
    });

    Object.assign(mod, { code: transformed, exports });
    const __filename = fileURLToPath(href);
    const moduleProxy = {
      set exports(value) {
        exportAll(cjsExports, value);
        exports.default = value;
      },
      get exports() {
        return cjsExports;
      },
    };

    const context = {
      // esm transformed by ice, https://github.com/ice-lab/swc-plugins/pull/9
      __ice_import__: request,
      __ice_dynamic_import__: request,
      __ice_exports__: exports,
      __ice_exports_all__: (obj: any) => exportAll(exports, obj),
      __ice_import_meta__: meta,

      // cjs compact
      require: createRequire(href),
      exports: cjsExports,
      module: moduleProxy,
      __filename,
      __dirname: path.dirname(__filename),

      // valid define global expressions
      ...this.contextDefineVars,
    };

    if (transformed[0] === '#') transformed = transformed.replace(/^#!.*/, s => ' '.repeat(s.length));
    // add 'use strict' since ESM enables it by default
    const codeDefinition = `'use strict';async (${Object.keys(context).join(',')})=>{{\n`;
    const code = `${codeDefinition}${transformed}\n}}`;
    const fn = vm.runInThisContext(code, {
      filename: __filename,
      lineOffset: -1,
      columnOffset: 0,
    });

    await fn(...Object.values(context));

    return exports;
  }