diff --git a/build-plugins/get-banner.ts b/build-plugins/get-banner.ts index dfabe13bf65..c62d9a53dad 100644 --- a/build-plugins/get-banner.ts +++ b/build-plugins/get-banner.ts @@ -23,9 +23,14 @@ function generateBanner(commitHash: string, version: string): string { let getBannerPromise: Promise | null = null; -export default async function getBanner(): Promise { +export default function getBanner(): Promise { return (getBannerPromise ||= Promise.all([ - execPromise('git rev-parse HEAD'), + execPromise('git rev-parse HEAD') + .then(({ stdout }) => stdout.trim()) + .catch(error => { + console.error('Could not determine commit hash:', error); + return 'unknown'; + }), fs.readFile(new URL('../package.json', import.meta.url), 'utf8') - ]).then(([{ stdout }, package_]) => generateBanner(stdout.trim(), JSON.parse(package_).version))); + ]).then(([commit, package_]) => generateBanner(commit, JSON.parse(package_).version))); } diff --git a/src/Chunk.ts b/src/Chunk.ts index bcf96ebb293..88574c17152 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -54,7 +54,7 @@ import { } from './utils/interopHelpers'; import type { OutputBundleWithPlaceholders } from './utils/outputBundle'; import { FILE_PLACEHOLDER } from './utils/outputBundle'; -import { basename, extname, isAbsolute, resolve } from './utils/path'; +import { basename, extname, isAbsolute, normalize, resolve } from './utils/path'; import { getAliasName, getImportPath } from './utils/relativeId'; import type { RenderOptions } from './utils/renderHelpers'; import { makeUnique, renderNamePattern } from './utils/renderNamePattern'; @@ -974,7 +974,7 @@ export default class Chunk { const predefinedChunkName = getPredefinedChunkNameFromModule(module); if (predefinedChunkName) return predefinedChunkName; const { preserveModulesRoot, sanitizeFileName } = this.outputOptions; - const sanitizedId = sanitizeFileName(module.id.split(QUERY_HASH_REGEX, 1)[0]); + const sanitizedId = sanitizeFileName(normalize(module.id.split(QUERY_HASH_REGEX, 1)[0])); const extensionName = extname(sanitizedId); const idWithoutExtension = NON_ASSET_EXTENSIONS.has(extensionName) ? sanitizedId.slice(0, -extensionName.length) diff --git a/src/ast/nodes/MetaProperty.ts b/src/ast/nodes/MetaProperty.ts index e71d1d8cd59..611f68afc02 100644 --- a/src/ast/nodes/MetaProperty.ts +++ b/src/ast/nodes/MetaProperty.ts @@ -1,6 +1,7 @@ import type MagicString from 'magic-string'; import type { InternalModuleFormat } from '../../rollup/types'; import type { PluginDriver } from '../../utils/PluginDriver'; +import { escapeId } from '../../utils/escapeId'; import type { GenerateCodeSnippets } from '../../utils/generateCodeSnippets'; import { dirname, normalize, relative } from '../../utils/path'; import type { RenderOptions } from '../../utils/renderHelpers'; @@ -145,7 +146,7 @@ const getResolveUrl = (path: string, URL = 'URL') => `new ${URL}(${path}).href`; const getRelativeUrlFromDocument = (relativePath: string, umd = false) => getResolveUrl( - `'${relativePath}', ${ + `'${escapeId(relativePath)}', ${ umd ? `typeof document === 'undefined' ? location.href : ` : '' }document.currentScript && document.currentScript.src || document.baseURI` ); @@ -164,7 +165,9 @@ const getGenericImportMetaMechanism = const getUrlFromDocument = (chunkId: string, umd = false) => `${ umd ? `typeof document === 'undefined' ? location.href : ` : '' - }(document.currentScript && document.currentScript.src || new URL('${chunkId}', document.baseURI).href)`; + }(document.currentScript && document.currentScript.src || new URL('${escapeId( + chunkId + )}', document.baseURI).href)`; const relativeUrlMechanisms: Record string> = { amd: relativePath => { diff --git a/test/chunking-form/samples/import-meta-numeric-paths/0/1/nested.js b/test/chunking-form/samples/import-meta-numeric-paths/0/1/nested.js new file mode 100644 index 00000000000..bdeb009362b --- /dev/null +++ b/test/chunking-form/samples/import-meta-numeric-paths/0/1/nested.js @@ -0,0 +1 @@ +export const url = import.meta.url; diff --git a/test/chunking-form/samples/import-meta-numeric-paths/_config.js b/test/chunking-form/samples/import-meta-numeric-paths/_config.js new file mode 100644 index 00000000000..045146cd4bb --- /dev/null +++ b/test/chunking-form/samples/import-meta-numeric-paths/_config.js @@ -0,0 +1,16 @@ +const assert = require('node:assert'); + +module.exports = { + description: 'supports nested numeric paths without issues on Windows', + options: { + output: { preserveModules: true }, + plugins: [ + { + name: 'test', + generateBundle(options, bundle) { + assert.deepStrictEqual(Object.keys(bundle), ['main.js', '0/1/nested.js']); + } + } + ] + } +}; diff --git a/test/chunking-form/samples/import-meta-numeric-paths/_expected/amd/0/1/nested.js b/test/chunking-form/samples/import-meta-numeric-paths/_expected/amd/0/1/nested.js new file mode 100644 index 00000000000..69562cb0eb6 --- /dev/null +++ b/test/chunking-form/samples/import-meta-numeric-paths/_expected/amd/0/1/nested.js @@ -0,0 +1,7 @@ +define(['module', 'exports'], (function (module, exports) { 'use strict'; + + const url = new URL(module.uri, document.baseURI).href; + + exports.url = url; + +})); diff --git a/test/chunking-form/samples/import-meta-numeric-paths/_expected/amd/main.js b/test/chunking-form/samples/import-meta-numeric-paths/_expected/amd/main.js new file mode 100644 index 00000000000..386d534b366 --- /dev/null +++ b/test/chunking-form/samples/import-meta-numeric-paths/_expected/amd/main.js @@ -0,0 +1,7 @@ +define(['exports', './0/1/nested'], (function (exports, nested) { 'use strict'; + + + + exports.url = nested.url; + +})); diff --git a/test/chunking-form/samples/import-meta-numeric-paths/_expected/cjs/0/1/nested.js b/test/chunking-form/samples/import-meta-numeric-paths/_expected/cjs/0/1/nested.js new file mode 100644 index 00000000000..bd090200b2a --- /dev/null +++ b/test/chunking-form/samples/import-meta-numeric-paths/_expected/cjs/0/1/nested.js @@ -0,0 +1,5 @@ +'use strict'; + +const url = (typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('0/1/nested.js', document.baseURI).href)); + +exports.url = url; diff --git a/test/chunking-form/samples/import-meta-numeric-paths/_expected/cjs/main.js b/test/chunking-form/samples/import-meta-numeric-paths/_expected/cjs/main.js new file mode 100644 index 00000000000..7b739791d3d --- /dev/null +++ b/test/chunking-form/samples/import-meta-numeric-paths/_expected/cjs/main.js @@ -0,0 +1,7 @@ +'use strict'; + +var nested = require('./0/1/nested.js'); + + + +exports.url = nested.url; diff --git a/test/chunking-form/samples/import-meta-numeric-paths/_expected/es/0/1/nested.js b/test/chunking-form/samples/import-meta-numeric-paths/_expected/es/0/1/nested.js new file mode 100644 index 00000000000..ee0310bf234 --- /dev/null +++ b/test/chunking-form/samples/import-meta-numeric-paths/_expected/es/0/1/nested.js @@ -0,0 +1,3 @@ +const url = import.meta.url; + +export { url }; diff --git a/test/chunking-form/samples/import-meta-numeric-paths/_expected/es/main.js b/test/chunking-form/samples/import-meta-numeric-paths/_expected/es/main.js new file mode 100644 index 00000000000..0b111561502 --- /dev/null +++ b/test/chunking-form/samples/import-meta-numeric-paths/_expected/es/main.js @@ -0,0 +1 @@ +export { url } from './0/1/nested.js'; diff --git a/test/chunking-form/samples/import-meta-numeric-paths/_expected/system/0/1/nested.js b/test/chunking-form/samples/import-meta-numeric-paths/_expected/system/0/1/nested.js new file mode 100644 index 00000000000..17dd3b000c0 --- /dev/null +++ b/test/chunking-form/samples/import-meta-numeric-paths/_expected/system/0/1/nested.js @@ -0,0 +1,10 @@ +System.register([], (function (exports, module) { + 'use strict'; + return { + execute: (function () { + + const url = exports('url', module.meta.url); + + }) + }; +})); diff --git a/test/chunking-form/samples/import-meta-numeric-paths/_expected/system/main.js b/test/chunking-form/samples/import-meta-numeric-paths/_expected/system/main.js new file mode 100644 index 00000000000..0be3e5010b5 --- /dev/null +++ b/test/chunking-form/samples/import-meta-numeric-paths/_expected/system/main.js @@ -0,0 +1,13 @@ +System.register(['./0/1/nested.js'], (function (exports) { + 'use strict'; + return { + setters: [function (module) { + exports('url', module.url); + }], + execute: (function () { + + + + }) + }; +})); diff --git a/test/chunking-form/samples/import-meta-numeric-paths/main.js b/test/chunking-form/samples/import-meta-numeric-paths/main.js new file mode 100644 index 00000000000..0b111561502 --- /dev/null +++ b/test/chunking-form/samples/import-meta-numeric-paths/main.js @@ -0,0 +1 @@ +export { url } from './0/1/nested.js'; diff --git a/test/cli/samples/watch/clearScreen/wrapper.js b/test/cli/samples/watch/clearScreen/wrapper.js index 8f733cc8815..57f1e1c7333 100755 --- a/test/cli/samples/watch/clearScreen/wrapper.js +++ b/test/cli/samples/watch/clearScreen/wrapper.js @@ -2,4 +2,5 @@ process.stdout.isTTY = true; process.stderr.isTTY = true; +process.stderr.hasColors = () => true; require('../../../../../dist/bin/rollup'); diff --git a/test/cli/samples/watch/no-clearScreen-command/wrapper.js b/test/cli/samples/watch/no-clearScreen-command/wrapper.js index 8f733cc8815..57f1e1c7333 100755 --- a/test/cli/samples/watch/no-clearScreen-command/wrapper.js +++ b/test/cli/samples/watch/no-clearScreen-command/wrapper.js @@ -2,4 +2,5 @@ process.stdout.isTTY = true; process.stderr.isTTY = true; +process.stderr.hasColors = () => true; require('../../../../../dist/bin/rollup'); diff --git a/test/cli/samples/watch/no-clearScreen/wrapper.js b/test/cli/samples/watch/no-clearScreen/wrapper.js index 8f733cc8815..57f1e1c7333 100755 --- a/test/cli/samples/watch/no-clearScreen/wrapper.js +++ b/test/cli/samples/watch/no-clearScreen/wrapper.js @@ -2,4 +2,5 @@ process.stdout.isTTY = true; process.stderr.isTTY = true; +process.stderr.hasColors = () => true; require('../../../../../dist/bin/rollup'); diff --git a/test/cli/samples/watch/no-watch-by-default/wrapper.js b/test/cli/samples/watch/no-watch-by-default/wrapper.js index 8f733cc8815..57f1e1c7333 100755 --- a/test/cli/samples/watch/no-watch-by-default/wrapper.js +++ b/test/cli/samples/watch/no-watch-by-default/wrapper.js @@ -2,4 +2,5 @@ process.stdout.isTTY = true; process.stderr.isTTY = true; +process.stderr.hasColors = () => true; require('../../../../../dist/bin/rollup'); diff --git a/test/cli/samples/watch/watch-event-hooks-error/wrapper.js b/test/cli/samples/watch/watch-event-hooks-error/wrapper.js index 8f733cc8815..57f1e1c7333 100644 --- a/test/cli/samples/watch/watch-event-hooks-error/wrapper.js +++ b/test/cli/samples/watch/watch-event-hooks-error/wrapper.js @@ -2,4 +2,5 @@ process.stdout.isTTY = true; process.stderr.isTTY = true; +process.stderr.hasColors = () => true; require('../../../../../dist/bin/rollup'); diff --git a/test/cli/samples/watch/watch-event-hooks/wrapper.js b/test/cli/samples/watch/watch-event-hooks/wrapper.js index 8f733cc8815..57f1e1c7333 100644 --- a/test/cli/samples/watch/watch-event-hooks/wrapper.js +++ b/test/cli/samples/watch/watch-event-hooks/wrapper.js @@ -2,4 +2,5 @@ process.stdout.isTTY = true; process.stderr.isTTY = true; +process.stderr.hasColors = () => true; require('../../../../../dist/bin/rollup');