diff --git a/docs/05-plugins.md b/docs/05-plugins.md
index 17b3e1ba200..7d3ee34d7a5 100644
--- a/docs/05-plugins.md
+++ b/docs/05-plugins.md
@@ -195,27 +195,30 @@ If you return an object, then it is possible to resolve an import to a different
```js
resolveId(id) {
- if (id === 'my-dependency') {
- return {id: 'my-dependency-develop', external: true};
- }
- return null;
+ if (id === 'my-dependency') {
+ return {id: 'my-dependency-develop', external: true};
+ }
+ return null;
}
```
-#### `resolveImportMetaUrl`
-Type: `({chunkId: string, moduleId: string, format: string}) => string | null`
+#### `resolveImportMeta`
+Type: `(property: string | null, {chunkId: string, moduleId: string, format: string}) => string | null`
Kind: `sync, first`
-Allows to customize how Rollup handles `import.meta.url`. In ES modules, `import.meta.url` returns the URL of the current module, e.g. `http://server.net/bundle.js` for browsers or `file:///path/to/bundle.js` in Node.
+Allows to customize how Rollup handles `import.meta` and `import.meta.someProperty`, in particular `import.meta.url`. In ES modules, `import.meta` is an object and `import.meta.url` contains the URL of the current module, e.g. `http://server.net/bundle.js` for browsers or `file:///path/to/bundle.js` in Node.
-By default for formats other than ES modules, Rollup replaces `import.meta.url` with code that attempts to match this behaviour by returning the dynamic URL of the current chunk. Note that all formats except CommonJS and UMD assume that they run in a browser environment where `URL` and `document` are available.
+By default for formats other than ES modules, Rollup replaces `import.meta.url` with code that attempts to match this behaviour by returning the dynamic URL of the current chunk. Note that all formats except CommonJS and UMD assume that they run in a browser environment where `URL` and `document` are available. For other properties, `import.meta.someProperty` is replaced with `undefined` while `import.meta` is replaced with an object containing a `url` property.
- This behaviour can be changed by returning a replacement for `import.meta.url`. For example, the following code will resolve `import.meta.url` using the relative path of the original module to the current working directory and again resolve this path against the base URL of the current document at runtime:
+ This behaviour can be changed—also for ES modules—via this hook. For each occurrence of `import.meta<.someProperty>`, this hook is called with the name of the property or `null` if `import.meta` is accessed directly. For example, the following code will resolve `import.meta.url` using the relative path of the original module to the current working directory and again resolve this path against the base URL of the current document at runtime:
```javascript
// rollup.config.js
-resolveImportMetaUrl({moduleId}) {
- return `new URL('${path.relative(process.cwd(), moduleId)}', document.baseURI).href`;
+resolveImportMeta(property, {moduleId}) {
+ if (property === 'url') {
+ return `new URL('${path.relative(process.cwd(), moduleId)}', document.baseURI).href`;
+ }
+ return null;
}
```
diff --git a/src/ast/nodes/MetaProperty.ts b/src/ast/nodes/MetaProperty.ts
index de0e82d8f9c..e532a8a0adb 100644
--- a/src/ast/nodes/MetaProperty.ts
+++ b/src/ast/nodes/MetaProperty.ts
@@ -1,9 +1,7 @@
import MagicString from 'magic-string';
import { dirname, normalize, relative } from '../../utils/path';
import { PluginDriver } from '../../utils/pluginDriver';
-import { RenderOptions } from '../../utils/renderHelpers';
import Identifier from './Identifier';
-import Literal from './Literal';
import MemberExpression from './MemberExpression';
import * as NodeType from './NodeType';
import { NodeBase } from './shared/Node';
@@ -35,60 +33,56 @@ const relUrlMechanisms: Record string> = {
export default class MetaProperty extends NodeBase {
meta: Identifier;
property: Identifier;
- rendered: boolean;
type: NodeType.tMetaProperty;
initialise() {
if (this.meta.name === 'import') {
- this.rendered = false;
this.context.addImportMeta(this);
}
this.included = false;
}
- render(code: MagicString, options: RenderOptions) {
- if (this.meta.name === 'import') this.rendered = true;
- super.render(code, options);
- }
-
renderFinalMechanism(
code: MagicString,
chunkId: string,
format: string,
pluginDriver: PluginDriver
): boolean {
- if (!this.included || !(this.parent instanceof MemberExpression)) return false;
-
+ if (!this.included) return false;
const parent = this.parent;
-
- let importMetaProperty: string;
- if (parent.property instanceof Identifier) importMetaProperty = parent.property.name;
- else if (parent.property instanceof Literal && typeof parent.property.value === 'string')
- importMetaProperty = parent.property.value;
- else return false;
+ const importMetaProperty =
+ parent instanceof MemberExpression && typeof parent.propertyKey === 'string'
+ ? parent.propertyKey
+ : null;
// support import.meta.ROLLUP_ASSET_URL_[ID]
- if (importMetaProperty.startsWith('ROLLUP_ASSET_URL_')) {
+ if (importMetaProperty && importMetaProperty.startsWith('ROLLUP_ASSET_URL_')) {
const assetFileName = this.context.getAssetFileName(importMetaProperty.substr(17));
const relPath = normalize(relative(dirname(chunkId), assetFileName));
- code.overwrite(parent.start, parent.end, relUrlMechanisms[format](relPath));
+ code.overwrite(
+ (parent as MemberExpression).start,
+ (parent as MemberExpression).end,
+ relUrlMechanisms[format](relPath)
+ );
return true;
}
- if (importMetaProperty === 'url') {
- const replacement = pluginDriver.hookFirstSync('resolveImportMetaUrl', [
- {
- chunkId,
- format,
- moduleId: this.context.module.id
- }
- ]);
- if (typeof replacement === 'string') {
+ const replacement = pluginDriver.hookFirstSync('resolveImportMeta', [
+ importMetaProperty,
+ {
+ chunkId,
+ format,
+ moduleId: this.context.module.id
+ }
+ ]);
+ if (typeof replacement === 'string') {
+ if (parent instanceof MemberExpression) {
code.overwrite(parent.start, parent.end, replacement);
+ } else {
+ code.overwrite(this.start, this.end, replacement);
}
return true;
}
-
return false;
}
}
diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts
index 9922f736a71..316666f3c1f 100644
--- a/src/rollup/types.d.ts
+++ b/src/rollup/types.d.ts
@@ -191,8 +191,9 @@ export type ResolveDynamicImportHook = (
parentId: string
) => Promise | string | void;
-export type ResolveImportMetaUrlHook = (
+export type ResolveImportMetaHook = (
this: PluginContext,
+ prop: string | null,
options: { chunkId: string; format: string; moduleId: string }
) => string | void;
@@ -249,7 +250,7 @@ export interface Plugin {
renderStart?: (this: PluginContext) => Promise | void;
resolveDynamicImport?: ResolveDynamicImportHook;
resolveId?: ResolveIdHook;
- resolveImportMetaUrl?: ResolveImportMetaUrlHook;
+ resolveImportMeta?: ResolveImportMetaHook;
transform?: TransformHook;
/** @deprecated */
transformBundle?: TransformChunkHook;
diff --git a/src/utils/defaultPlugin.ts b/src/utils/defaultPlugin.ts
index a37a30c8c73..4cc1c4bda4f 100644
--- a/src/utils/defaultPlugin.ts
+++ b/src/utils/defaultPlugin.ts
@@ -14,8 +14,11 @@ export function getRollupDefaultPlugin(options: InputOptions): Plugin {
if (typeof specifier === 'string' && !this.isExternal(specifier, parentId, false))
return >this.resolveId(specifier, parentId);
},
- resolveImportMetaUrl({ chunkId, format }) {
- return importMetaUrlMechanisms[format] && importMetaUrlMechanisms[format](chunkId);
+ resolveImportMeta(prop, { chunkId, format }) {
+ const mechanism = importMetaUrlMechanisms[format] && importMetaUrlMechanisms[format](chunkId);
+ if (mechanism) {
+ return prop === null ? `({ url: ${mechanism} })` : prop === 'url' ? mechanism : 'undefined';
+ }
}
};
}
diff --git a/test/form/samples/configure-import-meta-url/_config.js b/test/form/samples/configure-import-meta-url/_config.js
index 2e6888486a8..d0db2f15cc8 100644
--- a/test/form/samples/configure-import-meta-url/_config.js
+++ b/test/form/samples/configure-import-meta-url/_config.js
@@ -3,9 +3,9 @@ module.exports = {
options: {
plugins: [
{
- resolveImportMetaUrl({ chunkId, moduleId }) {
+ resolveImportMeta(prop, { chunkId, moduleId }) {
if (!moduleId.endsWith('resolved.js')) {
- return `'${chunkId}/${moduleId
+ return `'${prop}=${chunkId}:${moduleId
.replace(/\\/g, '/')
.split('/')
.slice(-2)
@@ -15,7 +15,7 @@ module.exports = {
}
},
{
- resolveImportMetaUrl({ moduleId }) {
+ resolveImportMeta(prop, { moduleId }) {
if (!moduleId.endsWith('unresolved.js')) {
return `'resolved'`;
}
diff --git a/test/form/samples/configure-import-meta-url/_expected/amd.js b/test/form/samples/configure-import-meta-url/_expected/amd.js
index aa3bae2b300..38d40a1bcb1 100644
--- a/test/form/samples/configure-import-meta-url/_expected/amd.js
+++ b/test/form/samples/configure-import-meta-url/_expected/amd.js
@@ -1,9 +1,15 @@
define(['module'], function (module) { 'use strict';
console.log('resolved');
+ console.log('resolved');
+ console.log('resolved');
console.log(new URL(module.uri, document.baseURI).href);
+ console.log(undefined);
+ console.log(({ url: new URL(module.uri, document.baseURI).href }));
- console.log('amd.js/configure-import-meta-url/main.js');
+ console.log('url=amd.js:configure-import-meta-url/main.js');
+ console.log('privateProp=amd.js:configure-import-meta-url/main.js');
+ console.log('null=amd.js:configure-import-meta-url/main.js');
});
diff --git a/test/form/samples/configure-import-meta-url/_expected/cjs.js b/test/form/samples/configure-import-meta-url/_expected/cjs.js
index 40cf325fe1f..f6ab33ad5e5 100644
--- a/test/form/samples/configure-import-meta-url/_expected/cjs.js
+++ b/test/form/samples/configure-import-meta-url/_expected/cjs.js
@@ -1,7 +1,13 @@
'use strict';
+console.log('resolved');
+console.log('resolved');
console.log('resolved');
console.log((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('cjs.js', document.baseURI).href)));
+console.log(undefined);
+console.log(({ url: (typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('cjs.js', document.baseURI).href)) }));
-console.log('cjs.js/configure-import-meta-url/main.js');
+console.log('url=cjs.js:configure-import-meta-url/main.js');
+console.log('privateProp=cjs.js:configure-import-meta-url/main.js');
+console.log('null=cjs.js:configure-import-meta-url/main.js');
diff --git a/test/form/samples/configure-import-meta-url/_expected/es.js b/test/form/samples/configure-import-meta-url/_expected/es.js
index 9c60ac1b8c3..65363fbdc91 100644
--- a/test/form/samples/configure-import-meta-url/_expected/es.js
+++ b/test/form/samples/configure-import-meta-url/_expected/es.js
@@ -1,5 +1,11 @@
console.log('resolved');
+console.log('resolved');
+console.log('resolved');
console.log(import.meta.url);
+console.log(import.meta.privateProp);
+console.log(import.meta);
-console.log('es.js/configure-import-meta-url/main.js');
+console.log('url=es.js:configure-import-meta-url/main.js');
+console.log('privateProp=es.js:configure-import-meta-url/main.js');
+console.log('null=es.js:configure-import-meta-url/main.js');
diff --git a/test/form/samples/configure-import-meta-url/_expected/iife.js b/test/form/samples/configure-import-meta-url/_expected/iife.js
index 885ab9f917e..2914b6951c8 100644
--- a/test/form/samples/configure-import-meta-url/_expected/iife.js
+++ b/test/form/samples/configure-import-meta-url/_expected/iife.js
@@ -1,10 +1,16 @@
(function () {
'use strict';
+ console.log('resolved');
+ console.log('resolved');
console.log('resolved');
console.log((document.currentScript && document.currentScript.src || new URL('iife.js', document.baseURI).href));
+ console.log(undefined);
+ console.log(({ url: (document.currentScript && document.currentScript.src || new URL('iife.js', document.baseURI).href) }));
- console.log('iife.js/configure-import-meta-url/main.js');
+ console.log('url=iife.js:configure-import-meta-url/main.js');
+ console.log('privateProp=iife.js:configure-import-meta-url/main.js');
+ console.log('null=iife.js:configure-import-meta-url/main.js');
}());
diff --git a/test/form/samples/configure-import-meta-url/_expected/system.js b/test/form/samples/configure-import-meta-url/_expected/system.js
index f6fea59b8e9..0023ad18505 100644
--- a/test/form/samples/configure-import-meta-url/_expected/system.js
+++ b/test/form/samples/configure-import-meta-url/_expected/system.js
@@ -4,10 +4,16 @@ System.register([], function (exports, module) {
execute: function () {
console.log('resolved');
+ console.log('resolved');
+ console.log('resolved');
console.log(module.meta.url);
+ console.log(undefined);
+ console.log(({ url: module.meta.url }));
- console.log('system.js/configure-import-meta-url/main.js');
+ console.log('url=system.js:configure-import-meta-url/main.js');
+ console.log('privateProp=system.js:configure-import-meta-url/main.js');
+ console.log('null=system.js:configure-import-meta-url/main.js');
}
};
diff --git a/test/form/samples/configure-import-meta-url/_expected/umd.js b/test/form/samples/configure-import-meta-url/_expected/umd.js
index 4fac39ab8db..187f2c2e07e 100644
--- a/test/form/samples/configure-import-meta-url/_expected/umd.js
+++ b/test/form/samples/configure-import-meta-url/_expected/umd.js
@@ -4,9 +4,15 @@
}(function () { 'use strict';
console.log('resolved');
+ console.log('resolved');
+ console.log('resolved');
console.log((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('umd.js', document.baseURI).href)));
+ console.log(undefined);
+ console.log(({ url: (typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('umd.js', document.baseURI).href)) }));
- console.log('umd.js/configure-import-meta-url/main.js');
+ console.log('url=umd.js:configure-import-meta-url/main.js');
+ console.log('privateProp=umd.js:configure-import-meta-url/main.js');
+ console.log('null=umd.js:configure-import-meta-url/main.js');
}));
diff --git a/test/form/samples/configure-import-meta-url/main.js b/test/form/samples/configure-import-meta-url/main.js
index 31d82d63ea7..a4a0af99305 100644
--- a/test/form/samples/configure-import-meta-url/main.js
+++ b/test/form/samples/configure-import-meta-url/main.js
@@ -2,3 +2,5 @@ import './resolved';
import './unresolved';
console.log(import.meta.url);
+console.log(import.meta.privateProp);
+console.log(import.meta);
diff --git a/test/form/samples/configure-import-meta-url/resolved.js b/test/form/samples/configure-import-meta-url/resolved.js
index d9536a69b3f..0a555e5ad35 100644
--- a/test/form/samples/configure-import-meta-url/resolved.js
+++ b/test/form/samples/configure-import-meta-url/resolved.js
@@ -1 +1,3 @@
console.log(import.meta.url);
+console.log(import.meta.privateProp);
+console.log(import.meta);
diff --git a/test/form/samples/configure-import-meta-url/unresolved.js b/test/form/samples/configure-import-meta-url/unresolved.js
index d9536a69b3f..0a555e5ad35 100644
--- a/test/form/samples/configure-import-meta-url/unresolved.js
+++ b/test/form/samples/configure-import-meta-url/unresolved.js
@@ -1 +1,3 @@
console.log(import.meta.url);
+console.log(import.meta.privateProp);
+console.log(import.meta);