Skip to content

Instantly share code, notes, and snippets.

@DerekNonGeneric
Last active July 21, 2020 22:37

Revisions

  1. DerekNonGeneric revised this gist Jul 21, 2020. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions reservedResolve_userland.mjs
    Original file line number Diff line number Diff line change
    @@ -62,11 +62,11 @@ export class InvalidModuleSpecifierError extends TypeError {
    * Resolve hook that allows customizing the default module resolution.
    * @param {string} specifier
    * @param {{
    * conditions: Array<string>,
    * parentURL: !(string | undefined),
    * conditions: !(Array<string>),
    * }} context
    * @param {!Function} defaultResolve
    * @returns {!(Promise<{ url: string }>)}
    * @returns {Promise<{ url: string }>}
    */
    export function resolve(specifier, context, defaultResolve) {
    const { parentURL = baseURL.href } = context;
  2. DerekNonGeneric renamed this gist Jun 12, 2020. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  3. DerekNonGeneric revised this gist Jun 12, 2020. 1 changed file with 9 additions and 8 deletions.
    17 changes: 9 additions & 8 deletions reservedResolve.mjs
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    /**
    * @file Userland JS implementation of Node.js's specifier restriction.
    * @flags --experimental-loader
    * @flag --experimental-loader
    * @license 0BSD
    * @author Derek Lewis <DerekNonGeneric@inf.is>
    * @module {Es6Module} reservedResolve_userland
    @@ -19,8 +19,8 @@ baseURL.pathname = process.cwd() + '/';
    /**
    * If specifier starts with the character U+002F SOLIDUS (`/`) or the
    * two-character sequence U+002F SOLIDUS U+002F SOLIDUS (`//`), return true.
    * @param {!string} specifier
    * @return {!boolean}
    * @param {string} specifier
    * @returns {boolean}
    * @see https://github.com/nodejs/node/blame/master/doc/api/esm.md#L825-L826
    */
    export function isReservedSpecifier(specifier) {
    @@ -41,14 +41,14 @@ export function isReservedSpecifier(specifier) {
    */
    export class InvalidModuleSpecifierError extends TypeError {
    /**
    * @param {!string} specifier The invalid module specifier.
    * @param {!string} baseFilePath The parent module's file path basename.
    * @param {string} specifier The invalid module specifier.
    * @param {string} baseFilePath The parent module's file path basename.
    */
    constructor(specifier, baseFilePath) {
    super(
    `Failed to resolve module specifier ${inspect(specifier)} imported ` +
    `from ${inspect(baseFilePath)}. Specifiers may not begin with '/' ` +
    `or '//'. These are reserved for potential future use.`
    "or '//'. These are reserved for potential future use."
    );
    this.code = 'ERR_INVALID_MODULE_SPECIFIER';
    }
    @@ -60,12 +60,13 @@ export class InvalidModuleSpecifierError extends TypeError {

    /**
    * Resolve hook that allows customizing the default module resolution.
    * @param {string} specifier
    * @param {{
    * parentURL: !(string | undefined),
    * conditions: !(Array<string>),
    * }} context
    * @param {!Function} defaultResolve
    * @returns {!(Promise<{ url: !string }>)}
    * @returns {!(Promise<{ url: string }>)}
    */
    export function resolve(specifier, context, defaultResolve) {
    const { parentURL = baseURL.href } = context;
    @@ -74,4 +75,4 @@ export function resolve(specifier, context, defaultResolve) {
    } else {
    return defaultResolve(specifier, { parentURL }, defaultResolve);
    }
    }
    }
  4. DerekNonGeneric revised this gist Jun 12, 2020. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions reservedResolve.mjs
    Original file line number Diff line number Diff line change
    @@ -41,8 +41,8 @@ export function isReservedSpecifier(specifier) {
    */
    export class InvalidModuleSpecifierError extends TypeError {
    /**
    * @param {!(string)} specifier The invalid module specifier.
    * @param {!(string)} baseFilePath The parent module's file path basename.
    * @param {!string} specifier The invalid module specifier.
    * @param {!string} baseFilePath The parent module's file path basename.
    */
    constructor(specifier, baseFilePath) {
    super(
  5. DerekNonGeneric revised this gist Jun 12, 2020. 1 changed file with 15 additions and 43 deletions.
    58 changes: 15 additions & 43 deletions reservedResolve.mjs
    Original file line number Diff line number Diff line change
    @@ -1,50 +1,30 @@
    /**
    * @file Userland JS implementation of Node's specifier restriction.
    * @flags: --experimental-loader
    * @file Userland JS implementation of Node.js's specifier restriction.
    * @flags --experimental-loader
    * @license 0BSD
    * @author Derek Lewis <DerekNonGeneric@inf.is>
    * @module {Es6Module} reservedResolve_userland
    * @see https://github.com/nodejs/modules/issues/505
    */

    import { format } from 'util';
    import { inspect } from 'util';

    const baseURL = new URL('file://');
    baseURL.pathname = process.cwd() + '/';

    /** @enum {string} */
    const unicodeEscapes = {
    leftDoubleQuotes: '\u201c', // “
    rightDoubleQuotes: '\u201d', // ”
    };

    // -----------------------------------------------------------------------------
    // Helpers
    // -----------------------------------------------------------------------------

    /**
    * Returns the supplied string as a curly quoted string.
    * TODO: Only curly quote if the terminal supports Unicode.
    * @param {string} arbitraryString
    * @return {string}
    */
    export function curlyQuote(arbitraryString) {
    return format(
    '%s%s%s',
    unicodeEscapes.leftDoubleQuotes,
    arbitraryString,
    unicodeEscapes.rightDoubleQuotes
    );
    }

    /**
    * If specifier starts with the character U+002F SOLIDUS (`/`) or the
    * two-character sequence U+002F SOLIDUS U+002F SOLIDUS (`//`), return true.
    * @param {string} specifier
    * @return {boolean}
    * @param {!string} specifier
    * @return {!boolean}
    * @see https://github.com/nodejs/node/blame/master/doc/api/esm.md#L825-L826
    */
    export function isReservedSpecifier(specifier) {
    if (specifier.charCodeAt(0) === 0x2f /** forward slash (/) */) {
    if (specifier.charCodeAt(0) === 0x2f /* U+002F SOLIDUS (`/`) */) {
    return true;
    } else {
    return false;
    @@ -66,11 +46,9 @@ export class InvalidModuleSpecifierError extends TypeError {
    */
    constructor(specifier, baseFilePath) {
    super(
    `Failed to resolve module specifier ${curlyQuote(specifier)} imported ` +
    `from ${curlyQuote(baseFilePath)}. Specifiers may not begin with ` +
    `${curlyQuote('/')} or ${curlyQuote('//')}. These are reserved for ` +
    'potential future use. The root of the current volume may be ' +
    `referenced via ${curlyQuote('file:///')}.`
    `Failed to resolve module specifier ${inspect(specifier)} imported ` +
    `from ${inspect(baseFilePath)}. Specifiers may not begin with '/' ` +
    `or '//'. These are reserved for potential future use.`
    );
    this.code = 'ERR_INVALID_MODULE_SPECIFIER';
    }
    @@ -81,19 +59,13 @@ export class InvalidModuleSpecifierError extends TypeError {
    // -----------------------------------------------------------------------------

    /**
    * Resolve hook that allows customizing the default module resolution. Loads
    * JavaScript restricted to browser resolution rules with only JS file
    * extensions and Node.js builtin modules support. opt_parentModuleUrl is
    * provided as undefined when performing main Node.js loading of itself.
    * @param {string} specifier
    * Resolve hook that allows customizing the default module resolution.
    * @param {{
    * parentURL:!(string|undefined),
    * conditions:Array<string>,
    * parentURL: !(string | undefined),
    * conditions: !(Array<string>),
    * }} context
    * @param {Function} defaultResolve
    * @return {{
    * url:string,
    * }}
    * @param {!Function} defaultResolve
    * @returns {!(Promise<{ url: !string }>)}
    */
    export function resolve(specifier, context, defaultResolve) {
    const { parentURL = baseURL.href } = context;
  6. DerekNonGeneric revised this gist May 20, 2020. 1 changed file with 3 additions and 5 deletions.
    8 changes: 3 additions & 5 deletions reservedResolve.mjs
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,8 @@
    /**
    * @file Userland JS implementation of Node's reserved specifier resolve hook.
    *
    * Flags: --experimental-loader
    *
    * @author Derek Lewis <DerekNonGeneric@inf.is>
    * @file Userland JS implementation of Node's specifier restriction.
    * @flags: --experimental-loader
    * @license 0BSD
    * @author Derek Lewis <DerekNonGeneric@inf.is>
    * @module {Es6Module} reservedResolve_userland
    * @see https://github.com/nodejs/modules/issues/505
    */
  7. DerekNonGeneric revised this gist May 20, 2020. 1 changed file with 12 additions and 8 deletions.
    20 changes: 12 additions & 8 deletions reservedResolve.mjs
    Original file line number Diff line number Diff line change
    @@ -20,9 +20,9 @@ const unicodeEscapes = {
    rightDoubleQuotes: '\u201d', // ”
    };

    //------------------------------------------------------------------------------
    // -----------------------------------------------------------------------------
    // Helpers
    //------------------------------------------------------------------------------
    // -----------------------------------------------------------------------------

    /**
    * Returns the supplied string as a curly quoted string.
    @@ -40,6 +40,8 @@ export function curlyQuote(arbitraryString) {
    }

    /**
    * If specifier starts with the character U+002F SOLIDUS (`/`) or the
    * two-character sequence U+002F SOLIDUS U+002F SOLIDUS (`//`), return true.
    * @param {string} specifier
    * @return {boolean}
    */
    @@ -51,9 +53,9 @@ export function isReservedSpecifier(specifier) {
    }
    }

    //------------------------------------------------------------------------------
    // -----------------------------------------------------------------------------
    // Errors
    //------------------------------------------------------------------------------
    // -----------------------------------------------------------------------------

    /**
    **ERR_INVALID_MODULE_SPECIFIER
    @@ -76,13 +78,15 @@ export class InvalidModuleSpecifierError extends TypeError {
    }
    }

    //------------------------------------------------------------------------------
    // -----------------------------------------------------------------------------
    // Hooks
    //------------------------------------------------------------------------------
    // -----------------------------------------------------------------------------

    /**
    * If specifier starts with the character U+002F SOLIDUS (`/`) or the
    * two-character sequence U+002F SOLIDUS U+002F SOLIDUS (`//`), throw error.
    * Resolve hook that allows customizing the default module resolution. Loads
    * JavaScript restricted to browser resolution rules with only JS file
    * extensions and Node.js builtin modules support. opt_parentModuleUrl is
    * provided as undefined when performing main Node.js loading of itself.
    * @param {string} specifier
    * @param {{
    * parentURL:!(string|undefined),
  8. DerekNonGeneric revised this gist May 13, 2020. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions reservedResolve.mjs
    Original file line number Diff line number Diff line change
    @@ -26,6 +26,7 @@ const unicodeEscapes = {

    /**
    * Returns the supplied string as a curly quoted string.
    * TODO: Only curly quote if the terminal supports Unicode.
    * @param {string} arbitraryString
    * @return {string}
    */
  9. DerekNonGeneric revised this gist May 13, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion reservedResolve.mjs
    Original file line number Diff line number Diff line change
    @@ -61,7 +61,7 @@ export function isReservedSpecifier(specifier) {
    export class InvalidModuleSpecifierError extends TypeError {
    /**
    * @param {!(string)} specifier The invalid module specifier.
    * @param {!(string)} baseFilePath The parent pjson file path basename.
    * @param {!(string)} baseFilePath The parent module's file path basename.
    */
    constructor(specifier, baseFilePath) {
    super(
  10. DerekNonGeneric created this gist May 13, 2020.
    102 changes: 102 additions & 0 deletions reservedResolve.mjs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,102 @@
    /**
    * @file Userland JS implementation of Node's reserved specifier resolve hook.
    *
    * Flags: --experimental-loader
    *
    * @author Derek Lewis <DerekNonGeneric@inf.is>
    * @license 0BSD
    * @module {Es6Module} reservedResolve_userland
    * @see https://github.com/nodejs/modules/issues/505
    */

    import { format } from 'util';

    const baseURL = new URL('file://');
    baseURL.pathname = process.cwd() + '/';

    /** @enum {string} */
    const unicodeEscapes = {
    leftDoubleQuotes: '\u201c', // “
    rightDoubleQuotes: '\u201d', // ”
    };

    //------------------------------------------------------------------------------
    // Helpers
    //------------------------------------------------------------------------------

    /**
    * Returns the supplied string as a curly quoted string.
    * @param {string} arbitraryString
    * @return {string}
    */
    export function curlyQuote(arbitraryString) {
    return format(
    '%s%s%s',
    unicodeEscapes.leftDoubleQuotes,
    arbitraryString,
    unicodeEscapes.rightDoubleQuotes
    );
    }

    /**
    * @param {string} specifier
    * @return {boolean}
    */
    export function isReservedSpecifier(specifier) {
    if (specifier.charCodeAt(0) === 0x2f /** forward slash (/) */) {
    return true;
    } else {
    return false;
    }
    }

    //------------------------------------------------------------------------------
    // Errors
    //------------------------------------------------------------------------------

    /**
    **ERR_INVALID_MODULE_SPECIFIER
    * @description An invalid module specifier.
    */
    export class InvalidModuleSpecifierError extends TypeError {
    /**
    * @param {!(string)} specifier The invalid module specifier.
    * @param {!(string)} baseFilePath The parent pjson file path basename.
    */
    constructor(specifier, baseFilePath) {
    super(
    `Failed to resolve module specifier ${curlyQuote(specifier)} imported ` +
    `from ${curlyQuote(baseFilePath)}. Specifiers may not begin with ` +
    `${curlyQuote('/')} or ${curlyQuote('//')}. These are reserved for ` +
    'potential future use. The root of the current volume may be ' +
    `referenced via ${curlyQuote('file:///')}.`
    );
    this.code = 'ERR_INVALID_MODULE_SPECIFIER';
    }
    }

    //------------------------------------------------------------------------------
    // Hooks
    //------------------------------------------------------------------------------

    /**
    * If specifier starts with the character U+002F SOLIDUS (`/`) or the
    * two-character sequence U+002F SOLIDUS U+002F SOLIDUS (`//`), throw error.
    * @param {string} specifier
    * @param {{
    * parentURL:!(string|undefined),
    * conditions:Array<string>,
    * }} context
    * @param {Function} defaultResolve
    * @return {{
    * url:string,
    * }}
    */
    export function resolve(specifier, context, defaultResolve) {
    const { parentURL = baseURL.href } = context;
    if (isReservedSpecifier(specifier)) {
    throw new InvalidModuleSpecifierError(specifier, parentURL);
    } else {
    return defaultResolve(specifier, { parentURL }, defaultResolve);
    }
    }