Skip to content

Commit

Permalink
module: make CJS load from ESM loader
Browse files Browse the repository at this point in the history
  • Loading branch information
aduh95 committed May 20, 2023
1 parent 85ac915 commit 8eee769
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 70 deletions.
70 changes: 65 additions & 5 deletions lib/internal/modules/esm/load.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,33 @@ async function getSource(url, context) {
return { __proto__: null, responseURL, source };
}

function getSourceSync(url, context) {
const parsed = new URL(url);
const responseURL = url;
let source;
if (parsed.protocol === 'file:') {
const { readFileSync } = require('fs');
source = readFileSync(parsed);
} else if (parsed.protocol === 'data:') {
const match = RegExpPrototypeExec(DATA_URL_PATTERN, parsed.pathname);
if (!match) {
throw new ERR_INVALID_URL(url);
}
const { 1: base64, 2: body } = match;
source = BufferFrom(decodeURIComponent(body), base64 ? 'base64' : 'utf8');
} else {
const supportedSchemes = ['file', 'data'];
if (experimentalNetworkImports) {
ArrayPrototypePush(supportedSchemes, 'http', 'https');
}
throw new ERR_UNSUPPORTED_ESM_URL_SCHEME(parsed, supportedSchemes);
}
if (policy?.manifest) {
policy.manifest.assertIntegrity(parsed, source);
}
return { __proto__: null, responseURL, source };
}


/**
* Node.js default load hook.
Expand All @@ -82,15 +109,12 @@ async function defaultLoad(url, context = kEmptyObject) {
throwIfUnsupportedURLScheme(new URL(url), experimentalNetworkImports);

if (format == null) {
format = await defaultGetFormat(url, context);
format = defaultGetFormat(url, context);
}

validateAssertions(url, format, importAssertions);

if (
format === 'builtin' ||
format === 'commonjs'
) {
if (format === 'builtin') {
source = null;
} else if (source == null) {
({ responseURL, source } = await getSource(url, context));
Expand All @@ -104,6 +128,41 @@ async function defaultLoad(url, context = kEmptyObject) {
};
}

/**
* Node.js default load hook.
* @param {string} url
* @param {object} context
* @returns {object}
*/
function defaultLoadSync(url, context = kEmptyObject) {
let responseURL = url;
const { importAssertions } = context;
let {
format,
source,
} = context;

if (format == null) {
format = defaultGetFormat(url, context);
}

validateAssertions(url, format, importAssertions);

if (format === 'builtin') {
source = null;
} else if (source == null) {
({ responseURL, source } = getSourceSync(url, context));
}

return {
__proto__: null,
format,
responseURL,
source,
};
}


/**
* throws an error if the protocol is not one of the protocols
* that can be loaded in the default loader
Expand Down Expand Up @@ -155,5 +214,6 @@ function throwUnknownModuleFormat(url, format) {

module.exports = {
defaultLoad,
defaultLoadSync,
throwUnknownModuleFormat,
};
46 changes: 39 additions & 7 deletions lib/internal/modules/esm/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const { emitExperimentalWarning } = require('internal/util');
const {
getDefaultConditions,
} = require('internal/modules/esm/utils');
let defaultResolve, defaultLoad, importMetaInitializer;
let defaultResolve, defaultLoad, defaultLoadSync, importMetaInitializer;

function newModuleMap() {
const ModuleMap = require('internal/modules/esm/module_map');
Expand Down Expand Up @@ -152,12 +152,12 @@ class DefaultModuleLoader {
* module import.
* @returns {ModuleJob} The (possibly pending) module job
*/
getModuleJob(specifier, parentURL, importAssertions) {
getModuleJob(specifier, parentURL, importAssertions, sync = false) {
const resolveResult = this.resolve(specifier, parentURL, importAssertions);
return this.getJobFromResolveResult(resolveResult, parentURL, importAssertions);
return this.getJobFromResolveResult(resolveResult, parentURL, importAssertions, sync);
}

getJobFromResolveResult(resolveResult, parentURL, importAssertions) {
getJobFromResolveResult(resolveResult, parentURL, importAssertions, sync) {
const { url, format } = resolveResult;
const resolvedImportAssertions = resolveResult.importAssertions ?? importAssertions;

Expand All @@ -169,7 +169,7 @@ class DefaultModuleLoader {
}

if (job === undefined) {
job = this.#createModuleJob(url, resolvedImportAssertions, parentURL, format);
job = this.#createModuleJob(url, resolvedImportAssertions, parentURL, format, sync);
}

return job;
Expand All @@ -186,8 +186,25 @@ class DefaultModuleLoader {
* `resolve` hook
* @returns {Promise<ModuleJob>} The (possibly pending) module job
*/
#createModuleJob(url, importAssertions, parentURL, format) {
const moduleProvider = async (url, isMain) => {
#createModuleJob(url, importAssertions, parentURL, format, sync) {
const moduleProvider = sync ? (url, isMain) => {
const {
format: finalFormat,
responseURL,
source,
} = this.loadSync(url, {
format,
importAssertions,
});

const translator = getTranslators().get(finalFormat);

if (!translator) {
throw new ERR_UNKNOWN_MODULE_FORMAT(finalFormat, responseURL);
}

return FunctionPrototypeCall(translator, this, responseURL, source, isMain);
} : async (url, isMain) => {
const {
format: finalFormat,
responseURL,
Expand Down Expand Up @@ -319,6 +336,15 @@ class DefaultModuleLoader {
return result;
}

loadSync(url, context) {
defaultLoadSync ??= require('internal/modules/esm/load').defaultLoadSync;

const result = defaultLoadSync(url, context);
result.format = `require-${result?.format}`;
this.validateLoadResult(url, result?.format);
return result;
}

validateLoadResult(url, format) {
if (format == null) {
require('internal/modules/esm/load').throwUnknownModuleFormat(url, format);
Expand Down Expand Up @@ -393,6 +419,12 @@ class CustomizedModuleLoader extends DefaultModuleLoader {
const result = await hooksProxy.makeAsyncRequest('load', url, context);
this.validateLoadResult(url, result?.format);

return result;
}
loadSync(url, context) {
const result = hooksProxy.makeSyncRequest('load', url, context);
this.validateLoadResult(url, result?.format);

return result;
}
}
Expand Down
13 changes: 13 additions & 0 deletions lib/internal/modules/esm/module_job.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class ModuleJob {
this.isMain = isMain;
this.inspectBrk = inspectBrk;

this.url = url;

this.module = undefined;
// Expose the promise to the ModuleWrap directly for linking below.
// `this.module` is also filled in below.
Expand Down Expand Up @@ -184,6 +186,17 @@ class ModuleJob {
}
}

runSync() {
assert(this.modulePromise instanceof ModuleWrap);

// TODO: better handle errors
this.modulePromise.instantiate();
const timeout = -1;
const breakOnSigint = false;
this.modulePromise.evaluate(timeout, breakOnSigint);
return { __proto__: null, module: this.modulePromise };
}

async run() {
await this.instantiate();
const timeout = -1;
Expand Down
Loading

0 comments on commit 8eee769

Please sign in to comment.