Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(compartment-mapper): remove the file: protocol from __filename an… #1155

Merged
merged 4 commits into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/compartment-mapper/NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ User-visible changes to the compartment mapper:
We still allow for the possibility that these duplicates exist and in fact
may contain different sources, since they may be retained as dependencies
beyond the purview of npm.
- A package.json file with the "type" field nested within a package's folder structure a is now taken into account when determining if a .js file is an ES module.
- A package.json file with the "type" field nested within a package's folder
structure a is now taken into account when determining if a .js file is an
ES module.
- Adds means to make `__dirname` and `__filename` work in CommonJS modules when
loaded via importLocation or loadLocation. Pass `readPowers` with
`fileURLToPath` method present.

# 0.7.2 (2022-04-11)

Expand Down
9 changes: 7 additions & 2 deletions packages/compartment-mapper/src/import-hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
/** @typedef {import('ses').ImportHook} ImportHook */
/** @typedef {import('ses').StaticModuleType} StaticModuleType */
/** @typedef {import('./types.js').ReadFn} ReadFn */
/** @typedef {import('./types.js').ReadPowers} ReadPowers */
/** @typedef {import('./types.js').HashFn} HashFn */
/** @typedef {import('./types.js').Sources} Sources */
/** @typedef {import('./types.js').CompartmentSources} CompartmentSources */
/** @typedef {import('./types.js').CompartmentDescriptor} CompartmentDescriptor */
/** @typedef {import('./types.js').ImportHookMaker} ImportHookMaker */

import { parseExtension } from './extension.js';
import { unpackReadPowers } from './powers.js';

// q, as in quote, for quoting strings in error messages.
const q = JSON.stringify;
Expand Down Expand Up @@ -44,7 +46,7 @@ function getImportsFromRecord(record) {
}

/**
* @param {ReadFn} read
* @param {ReadFn|ReadPowers} readPowers
* @param {string} baseLocation
* @param {Sources} sources
* @param {Record<string, CompartmentDescriptor>} compartments
Expand All @@ -53,7 +55,7 @@ function getImportsFromRecord(record) {
* @returns {ImportHookMaker}
*/
export const makeImportHookMaker = (
read,
readPowers,
baseLocation,
sources = Object.create(null),
compartments = Object.create(null),
Expand Down Expand Up @@ -152,6 +154,8 @@ export const makeImportHookMaker = (
}
}

const { read } = unpackReadPowers(readPowers);

for (const candidateSpecifier of candidates) {
// Using a specifier as a location.
// This is not always valid.
Expand All @@ -172,6 +176,7 @@ export const makeImportHookMaker = (
candidateSpecifier,
moduleLocation,
packageLocation,
readPowers,
);
const {
parser,
Expand Down
12 changes: 8 additions & 4 deletions packages/compartment-mapper/src/import.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const loadLocation = async (readPowers, moduleLocation, options) => {
__shimTransforms__,
Compartment,
} = options;
const makeImportHook = makeImportHookMaker(read, packageLocation);
const makeImportHook = makeImportHookMaker(readPowers, packageLocation);
const { compartment } = link(compartmentMap, {
makeImportHook,
parserForLanguage,
Expand All @@ -92,13 +92,17 @@ export const loadLocation = async (readPowers, moduleLocation, options) => {
};

/**
* @param {ReadFn} read
* @param {ReadFn | ReadPowers} readPowers
* @param {string} moduleLocation
* @param {ExecuteOptions & ArchiveOptions} [options]
* @returns {Promise<Object>} the object of the imported modules exported
* names.
*/
export const importLocation = async (read, moduleLocation, options = {}) => {
const application = await loadLocation(read, moduleLocation, options);
export const importLocation = async (
readPowers,
moduleLocation,
options = {},
) => {
const application = await loadLocation(readPowers, moduleLocation, options);
return application.import(options);
};
4 changes: 2 additions & 2 deletions packages/compartment-mapper/src/link.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const makeExtensionParser = (
parserForLanguage,
transforms,
) => {
return async (bytes, specifier, location, packageLocation) => {
return async (bytes, specifier, location, packageLocation, readPowers) => {
let language;
if (has(languageForModuleSpecifier, specifier)) {
language = languageForModuleSpecifier[specifier];
Expand Down Expand Up @@ -106,7 +106,7 @@ const makeExtensionParser = (
);
}
const { parse } = parserForLanguage[language];
return parse(bytes, specifier, location, packageLocation);
return parse(bytes, specifier, location, packageLocation, readPowers);
};
};

Expand Down
2 changes: 1 addition & 1 deletion packages/compartment-mapper/src/node-powers.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const makeReadPowersSloppy = ({ fs, url = undefined, crypto = undefined }) => {
}
: undefined;

return { read, canonical, computeSha512 };
return { read, fileURLToPath, pathToFileURL, canonical, computeSha512 };
};

/**
Expand Down
50 changes: 50 additions & 0 deletions packages/compartment-mapper/src/parse-cjs-shared-export-wrapper.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
// @ts-check

/** @typedef {import('./types.js').ReadFn} ReadFn */
/** @typedef {import('./types.js').ReadPowers} ReadPowers */

const { apply } = Reflect;
const { freeze, keys, create, hasOwnProperty, defineProperty } = Object;

Expand All @@ -9,6 +13,52 @@ const { freeze, keys, create, hasOwnProperty, defineProperty } = Object;
*/
const has = (object, key) => apply(hasOwnProperty, object, [key]);

const noTrailingSlash = path => {
const l = path.length - 1;
return path[l] === '\\' || path[l] === '/' ? path.slice(0, -1) : path;
};

/**
* Generates values for __filename and __dirname from location
* @param {ReadPowers | ReadFn | undefined} readPowers
* @param {string} location
* @returns {{
* filename:string|null,
* dirname: string|null
* }}
*/
export const getModulePaths = (readPowers, location) => {
if (
readPowers &&
typeof readPowers !== 'function' &&
readPowers.fileURLToPath
) {
let filename = location;
let dirname;
try {
dirname = new URL('./', filename).href;
} catch (_) {
return {
filename: null,
dirname: null,
};
}

filename = readPowers.fileURLToPath(filename).toString();
dirname = noTrailingSlash(readPowers.fileURLToPath(dirname).toString());

return {
filename,
dirname,
};
} else {
return {
filename: null,
dirname: null,
};
}
};

/**
* ModuleEnvironmentRecord wrapper
* Creates shared export processing primitives to be used both Location and Archive usecases of cjs
Expand Down
13 changes: 5 additions & 8 deletions packages/compartment-mapper/src/parse-cjs.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @ts-check

import { analyzeCommonJS } from '@endo/cjs-module-analyzer';
import { wrap } from './parse-cjs-shared-export-wrapper.js';
import { wrap, getModulePaths } from './parse-cjs-shared-export-wrapper.js';

const textDecoder = new TextDecoder();

Expand All @@ -13,6 +13,7 @@ export const parseCjs = async (
_specifier,
location,
_packageLocation,
readPowers,
) => {
const source = textDecoder.decode(bytes);

Expand All @@ -25,6 +26,8 @@ export const parseCjs = async (
exports.push('default');
}

const { filename, dirname } = await getModulePaths(readPowers, location);

/**
* @param {Object} moduleEnvironmentRecord
* @param {Compartment} compartment
Expand All @@ -41,13 +44,7 @@ export const parseCjs = async (
resolvedImports,
);

functor(
require,
moduleExports,
module,
location, // __filename
new URL('./', location).toString(), // __dirname
);
functor(require, moduleExports, module, filename, dirname);

afterExecute();
};
Expand Down
21 changes: 5 additions & 16 deletions packages/compartment-mapper/src/parse-pre-cjs.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
// @ts-check

import { parseLocatedJson } from './json.js';
import { wrap } from './parse-cjs-shared-export-wrapper.js';
import { wrap, getModulePaths } from './parse-cjs-shared-export-wrapper.js';

const textDecoder = new TextDecoder();

const locationParent = location => {
const index = location.lastIndexOf('/');
if (index >= 0) {
return location.slice(0, index);
}
return location;
};

/** @type {import('./types.js').ParseFn} */
export const parsePreCjs = async (
bytes,
_specifier,
location,
_packageLocation,
readPowers,
) => {
const text = textDecoder.decode(bytes);
const { source, imports, exports, reexports } = parseLocatedJson(
text,
location,
);

const { filename, dirname } = await getModulePaths(readPowers, location);

/**
* @param {Object} moduleEnvironmentRecord
* @param {Compartment} compartment
Expand All @@ -40,13 +35,7 @@ export const parsePreCjs = async (
resolvedImports,
);

functor(
require,
moduleExports,
module,
location, // __filename
locationParent(location), // __dirname
);
functor(require, moduleExports, module, filename, dirname);

afterExecute();
};
Expand Down
3 changes: 3 additions & 0 deletions packages/compartment-mapper/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ export {};
* @property {ReadFn} read
* @property {CanonicalFn} canonical
* @property {HashFn} [computeSha512]
* @property {Function} [fileURLToPath]
* @property {Function} [pathToFileURL]
*/

/**
Expand Down Expand Up @@ -195,6 +197,7 @@ export {};
* @param {string} specifier
* @param {string} location
* @param {string} packageLocation
* @param {ReadFn | ReadPowers} [readPowers]
kriskowal marked this conversation as resolved.
Show resolved Hide resolved
* @returns {Promise<{
* bytes: Uint8Array,
* parser: Language,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading