From ddc83b0d70210e72164f49b6c8eb7826d38e120b Mon Sep 17 00:00:00 2001 From: Ivan Kopeykin Date: Wed, 5 Aug 2020 00:42:29 +0300 Subject: [PATCH] feat: url assets --- declarations/WebpackOptions.d.ts | 4 + lib/BaseURIPlugin.js | 53 +++++++++++++ lib/BaseURIRuntimeModule.js | 44 +++++++++++ lib/NormalModuleFactory.js | 1 + lib/RuntimeGlobals.js | 5 ++ lib/WebpackOptionsApply.js | 4 + lib/config/defaults.js | 7 ++ lib/dependencies/URLDependency.js | 75 ++++++++++++++++++ lib/dependencies/URLPlugin.js | 78 +++++++++++++++++++ schemas/WebpackOptions.json | 4 + .../asset-url/target-node1/index.css | 1 + .../asset-url/target-node1/index.js | 7 ++ .../asset-url/target-node1/webpack.config.js | 21 +++++ .../asset-url/target-node2/index.css | 1 + .../asset-url/target-node2/index.js | 7 ++ .../asset-url/target-node2/webpack.config.js | 20 +++++ .../asset-url/target-node3/index.css | 1 + .../asset-url/target-node3/index.js | 5 ++ .../asset-url/target-node3/webpack.config.js | 21 +++++ .../asset-url/target-web1/index.css | 1 + .../asset-url/target-web1/index.js | 5 ++ .../asset-url/target-web1/test.config.js | 9 +++ .../asset-url/target-web1/webpack.config.js | 20 +++++ .../asset-url/target-web2/index.css | 1 + .../asset-url/target-web2/index.js | 5 ++ .../asset-url/target-web2/test.config.js | 9 +++ .../asset-url/target-web2/webpack.config.js | 21 +++++ .../asset-url/target-webworker1/index.css | 1 + .../asset-url/target-webworker1/index.js | 5 ++ .../target-webworker1/test.config.js | 9 +++ .../target-webworker1/webpack.config.js | 20 +++++ .../asset-url/target-webworker2/index.css | 1 + .../asset-url/target-webworker2/index.js | 5 ++ .../target-webworker2/test.config.js | 9 +++ .../target-webworker2/webpack.config.js | 21 +++++ test/helpers/FakeDocument.js | 1 + types.d.ts | 6 ++ 37 files changed, 508 insertions(+) create mode 100644 lib/BaseURIPlugin.js create mode 100644 lib/BaseURIRuntimeModule.js create mode 100644 lib/dependencies/URLDependency.js create mode 100644 lib/dependencies/URLPlugin.js create mode 100644 test/configCases/asset-url/target-node1/index.css create mode 100644 test/configCases/asset-url/target-node1/index.js create mode 100644 test/configCases/asset-url/target-node1/webpack.config.js create mode 100644 test/configCases/asset-url/target-node2/index.css create mode 100644 test/configCases/asset-url/target-node2/index.js create mode 100644 test/configCases/asset-url/target-node2/webpack.config.js create mode 100644 test/configCases/asset-url/target-node3/index.css create mode 100644 test/configCases/asset-url/target-node3/index.js create mode 100644 test/configCases/asset-url/target-node3/webpack.config.js create mode 100644 test/configCases/asset-url/target-web1/index.css create mode 100644 test/configCases/asset-url/target-web1/index.js create mode 100644 test/configCases/asset-url/target-web1/test.config.js create mode 100644 test/configCases/asset-url/target-web1/webpack.config.js create mode 100644 test/configCases/asset-url/target-web2/index.css create mode 100644 test/configCases/asset-url/target-web2/index.js create mode 100644 test/configCases/asset-url/target-web2/test.config.js create mode 100644 test/configCases/asset-url/target-web2/webpack.config.js create mode 100644 test/configCases/asset-url/target-webworker1/index.css create mode 100644 test/configCases/asset-url/target-webworker1/index.js create mode 100644 test/configCases/asset-url/target-webworker1/test.config.js create mode 100644 test/configCases/asset-url/target-webworker1/webpack.config.js create mode 100644 test/configCases/asset-url/target-webworker2/index.css create mode 100644 test/configCases/asset-url/target-webworker2/index.js create mode 100644 test/configCases/asset-url/target-webworker2/test.config.js create mode 100644 test/configCases/asset-url/target-webworker2/webpack.config.js diff --git a/declarations/WebpackOptions.d.ts b/declarations/WebpackOptions.d.ts index aac001ebd..adbe17c21 100644 --- a/declarations/WebpackOptions.d.ts +++ b/declarations/WebpackOptions.d.ts @@ -1011,6 +1011,10 @@ export interface RuleSetRule { * Match the child compiler name. */ compiler?: RuleSetConditionOrConditions; + /** + * Match dependency type. + */ + dependency?: string; /** * Match values of properties in the description file (usually package.json). */ diff --git a/lib/BaseURIPlugin.js b/lib/BaseURIPlugin.js new file mode 100644 index 000000000..087da5e55 --- /dev/null +++ b/lib/BaseURIPlugin.js @@ -0,0 +1,53 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Ivan Kopeykin @vankop +*/ + +"use strict"; + +const BaseURIRuntimeModule = require("./BaseURIRuntimeModule"); +const RuntimeGlobals = require("./RuntimeGlobals"); + +/** @typedef {import("../declarations/WebpackOptions").Target} Target */ +/** @typedef {import("./Compiler")} Compiler */ + +class BaseURIPlugin { + /** + * @param {Target} target target + */ + constructor(target) { + switch (target) { + case "webworker": + this.environment = /** @type {"webworker"} */ ("webworker"); + break; + case "node": + case "async-node": + case "node-webkit": + case "electron-main": + case "electron-preload": + this.environment = /** @type {"node"} */ ("node"); + break; + default: + this.environment = /** @type {"web"} */ ("web"); + break; + } + } + + /** + * @param {Compiler} compiler compiler + */ + apply(compiler) { + compiler.hooks.compilation.tap("BaseURIPlugin", compilation => { + compilation.hooks.runtimeRequirementInTree + .for(RuntimeGlobals.baseURI) + .tap("BaseURIPlugin", (chunk, set) => { + compilation.addRuntimeModule( + chunk, + new BaseURIRuntimeModule(this.environment) + ); + }); + }); + } +} + +module.exports = BaseURIPlugin; diff --git a/lib/BaseURIRuntimeModule.js b/lib/BaseURIRuntimeModule.js new file mode 100644 index 000000000..3e0b1369b --- /dev/null +++ b/lib/BaseURIRuntimeModule.js @@ -0,0 +1,44 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Ivan Kopeykin @vankop +*/ + +"use strict"; + +const RuntimeGlobals = require("./RuntimeGlobals"); +const RuntimeModule = require("./RuntimeModule"); +const Template = require("./Template"); + +class BaseURIRuntimeModule extends RuntimeModule { + /** + * @param {"node"|"web"|"webworker"} environment environment + */ + constructor(environment) { + super("baseURI"); + this.env = environment; + } + + /** + * @returns {string} runtime code + */ + generate() { + switch (this.env) { + case "web": + return Template.asString([ + `${RuntimeGlobals.baseURI} = document.baseURI;` + ]); + case "webworker": + return Template.asString([ + `${RuntimeGlobals.baseURI} = self.location;` + ]); + case "node": + return Template.asString([ + `${RuntimeGlobals.baseURI} = require('url').pathToFileURL(__filename);` + ]); + default: + return ""; + } + } +} + +module.exports = BaseURIRuntimeModule; diff --git a/lib/NormalModuleFactory.js b/lib/NormalModuleFactory.js index 138524f59..58d85f433 100644 --- a/lib/NormalModuleFactory.js +++ b/lib/NormalModuleFactory.js @@ -132,6 +132,7 @@ const dependencyCache = new WeakMap(); const ruleSetCompiler = new RuleSetCompiler([ new BasicMatcherRulePlugin("test", "resource"), new BasicMatcherRulePlugin("mimetype"), + new BasicMatcherRulePlugin("dependency"), new BasicMatcherRulePlugin("include", "resource"), new BasicMatcherRulePlugin("exclude", "resource", true), new BasicMatcherRulePlugin("resource"), diff --git a/lib/RuntimeGlobals.js b/lib/RuntimeGlobals.js index 919227046..544f53d46 100644 --- a/lib/RuntimeGlobals.js +++ b/lib/RuntimeGlobals.js @@ -278,3 +278,8 @@ exports.hasOwnProperty = "__webpack_require__.o"; * the System.register context object */ exports.systemContext = "__webpack_require__.y"; + +/** + * the baseURI of current document + */ +exports.baseURI = "__webpack_require__.b"; diff --git a/lib/WebpackOptionsApply.js b/lib/WebpackOptionsApply.js index 87bcaa12c..7f8511a33 100644 --- a/lib/WebpackOptionsApply.js +++ b/lib/WebpackOptionsApply.js @@ -26,6 +26,8 @@ const TemplatedPathPlugin = require("./TemplatedPathPlugin"); const UseStrictPlugin = require("./UseStrictPlugin"); const WarnCaseSensitiveModulesPlugin = require("./WarnCaseSensitiveModulesPlugin"); +const BaseURIPlugin = require("./BaseURIPlugin"); +const URLPlugin = require("./dependencies/URLPlugin"); const DataUriPlugin = require("./schemes/DataUriPlugin"); const FileUriPlugin = require("./schemes/FileUriPlugin"); @@ -313,6 +315,8 @@ class WebpackOptionsApply extends OptionsApply { : true }).apply(compiler); + new BaseURIPlugin(options.target).apply(compiler); + new URLPlugin().apply(compiler); new DataUriPlugin().apply(compiler); new FileUriPlugin().apply(compiler); diff --git a/lib/config/defaults.js b/lib/config/defaults.js index 0ace07b7f..09ec02af6 100644 --- a/lib/config/defaults.js +++ b/lib/config/defaults.js @@ -356,6 +356,13 @@ const applyModuleDefaults = ( mimetype: "application/node", type: "javascript/auto" }, + { + test: /\.js$/, + dependency: "url", + resolve: { + conditionNames: ["esm", "..."] + } + }, { test: /\.json$/i, type: "json" diff --git a/lib/dependencies/URLDependency.js b/lib/dependencies/URLDependency.js new file mode 100644 index 000000000..12e2f8795 --- /dev/null +++ b/lib/dependencies/URLDependency.js @@ -0,0 +1,75 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Ivan Kopeykin @vankop +*/ + +"use strict"; + +const RuntimeGlobals = require("../RuntimeGlobals"); +const ModuleDependency = require("./ModuleDependency"); + +/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */ +/** @typedef {import("../ChunkGraph")} ChunkGraph */ +/** @typedef {import("../Dependency")} Dependency */ +/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */ +/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */ +/** @typedef {import("../ModuleGraph")} ModuleGraph */ +/** @typedef {import("../util/Hash")} Hash */ + +class URLDependency extends ModuleDependency { + /** + * @param {string} request request + * @param {[number, number]} range range + */ + constructor(request, range) { + super(request); + this.range = range; + } + + get type() { + return "new URL()"; + } + + get category() { + return "url"; + } +} + +URLDependency.Template = class URLDependencyTemplate extends ModuleDependency.Template { + /** + * @param {Dependency} dependency the dependency for which the template should be applied + * @param {ReplaceSource} source the current replace source which can be modified + * @param {DependencyTemplateContext} templateContext the context object + * @returns {void} + */ + apply(dependency, source, templateContext) { + const { + chunkGraph, + moduleGraph, + runtimeRequirements, + runtimeTemplate, + runtime + } = templateContext; + const dep = /** @type {URLDependency} */ (dependency); + + const connection = moduleGraph.getConnection(dep); + if (connection && !connection.isActive(runtime)) return; + + runtimeRequirements.add(RuntimeGlobals.baseURI); + runtimeRequirements.add(RuntimeGlobals.require); + + source.replace( + dep.range[0], + dep.range[1] - 1, + `new URL(/* asset import */ ${runtimeTemplate.moduleRaw({ + chunkGraph, + module: moduleGraph.getModule(dep), + request: dep.request, + runtimeRequirements, + weak: false + })}, ${RuntimeGlobals.baseURI})` + ); + } +}; + +module.exports = URLDependency; diff --git a/lib/dependencies/URLPlugin.js b/lib/dependencies/URLPlugin.js new file mode 100644 index 000000000..e30671948 --- /dev/null +++ b/lib/dependencies/URLPlugin.js @@ -0,0 +1,78 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Ivan Kopeykin @vankop +*/ + +"use strict"; + +const URLDependency = require("./URLDependency"); + +/** @typedef {import("estree").NewExpression} NewExpressionNode */ +/** @typedef {import("../Compiler")} Compiler */ +/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */ + +class URLPlugin { + /** + * @param {Compiler} compiler compiler + */ + apply(compiler) { + compiler.hooks.compilation.tap( + "URLPlugin", + (compilation, { normalModuleFactory }) => { + compilation.dependencyFactories.set(URLDependency, normalModuleFactory); + compilation.dependencyTemplates.set( + URLDependency, + new URLDependency.Template() + ); + + /** + * @param {JavascriptParser} parser parser + */ + const parserCallback = parser => { + parser.hooks.new.for("URL").tap("URLPlugin", _expr => { + const expr = /** @type {NewExpressionNode} */ (_expr); + + if (expr.arguments.length !== 2) return; + + const [arg1, arg2] = expr.arguments; + + if ( + arg2.type !== "MemberExpression" || + arg1.type === "SpreadElement" + ) + return; + + const chain = parser.extractMemberExpressionChain(arg2); + + if ( + chain.members.length !== 1 || + chain.object.type !== "MetaProperty" || + chain.object.property.name !== "meta" || + chain.members[0] !== "url" + ) + return; + + const request = parser.evaluateExpression(arg1).asString(); + + if (!request) return; + + const dep = new URLDependency(request, expr.range); + dep.loc = expr.loc; + parser.state.module.addDependency(dep); + return true; + }); + }; + + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("URLPlugin", parserCallback); + + normalModuleFactory.hooks.parser + .for("javascript/esm") + .tap("URLPlugin", parserCallback); + } + ); + } +} + +module.exports = URLPlugin; diff --git a/schemas/WebpackOptions.json b/schemas/WebpackOptions.json index 1ccc7198a..d35fa4719 100644 --- a/schemas/WebpackOptions.json +++ b/schemas/WebpackOptions.json @@ -2551,6 +2551,10 @@ } ] }, + "dependency": { + "description": "Match dependency type.", + "type": "string" + }, "descriptionData": { "description": "Match values of properties in the description file (usually package.json).", "type": "object", diff --git a/test/configCases/asset-url/target-node1/index.css b/test/configCases/asset-url/target-node1/index.css new file mode 100644 index 000000000..077f6dd7c --- /dev/null +++ b/test/configCases/asset-url/target-node1/index.css @@ -0,0 +1 @@ +a {} diff --git a/test/configCases/asset-url/target-node1/index.js b/test/configCases/asset-url/target-node1/index.js new file mode 100644 index 000000000..8f761ae67 --- /dev/null +++ b/test/configCases/asset-url/target-node1/index.js @@ -0,0 +1,7 @@ +const currentDir = require("url").pathToFileURL(__dirname); + +it("should handle import.meta.url in URL()", () => { + const {href} = new URL("./index.css", import.meta.url); + + expect(href).toBe(currentDir + "/public/index.css"); +}); diff --git a/test/configCases/asset-url/target-node1/webpack.config.js b/test/configCases/asset-url/target-node1/webpack.config.js new file mode 100644 index 000000000..9b30bc67d --- /dev/null +++ b/test/configCases/asset-url/target-node1/webpack.config.js @@ -0,0 +1,21 @@ +/** @type {import("../../../../").Configuration} */ +module.exports = { + mode: "development", + target: "node", + devtool: false, + output: { + assetModuleFilename: "[name][ext]", + publicPath: "public/" + }, + module: { + rules: [ + { + test: /\.css$/, + type: "asset/resource" + } + ] + }, + experiments: { + asset: true + } +}; diff --git a/test/configCases/asset-url/target-node2/index.css b/test/configCases/asset-url/target-node2/index.css new file mode 100644 index 000000000..077f6dd7c --- /dev/null +++ b/test/configCases/asset-url/target-node2/index.css @@ -0,0 +1 @@ +a {} diff --git a/test/configCases/asset-url/target-node2/index.js b/test/configCases/asset-url/target-node2/index.js new file mode 100644 index 000000000..bdb9e62f7 --- /dev/null +++ b/test/configCases/asset-url/target-node2/index.js @@ -0,0 +1,7 @@ +const currentDir = require("url").pathToFileURL(__dirname); + +it("should handle import.meta.url in URL()", () => { + const {href} = new URL("./index.css", import.meta.url); + + expect(href).toBe(currentDir + "/index.css"); +}); diff --git a/test/configCases/asset-url/target-node2/webpack.config.js b/test/configCases/asset-url/target-node2/webpack.config.js new file mode 100644 index 000000000..67b8d99d8 --- /dev/null +++ b/test/configCases/asset-url/target-node2/webpack.config.js @@ -0,0 +1,20 @@ +/** @type {import("../../../../").Configuration} */ +module.exports = { + mode: "development", + target: "node", + devtool: false, + output: { + assetModuleFilename: "[name][ext]" + }, + module: { + rules: [ + { + test: /\.css$/, + type: "asset/resource" + } + ] + }, + experiments: { + asset: true + } +}; diff --git a/test/configCases/asset-url/target-node3/index.css b/test/configCases/asset-url/target-node3/index.css new file mode 100644 index 000000000..077f6dd7c --- /dev/null +++ b/test/configCases/asset-url/target-node3/index.css @@ -0,0 +1 @@ +a {} diff --git a/test/configCases/asset-url/target-node3/index.js b/test/configCases/asset-url/target-node3/index.js new file mode 100644 index 000000000..7852082a1 --- /dev/null +++ b/test/configCases/asset-url/target-node3/index.js @@ -0,0 +1,5 @@ +it("should handle import.meta.url in URL()", () => { + const {href} = new URL("./index.css", import.meta.url); + + expect(href).toBe("file:///index.css"); +}); diff --git a/test/configCases/asset-url/target-node3/webpack.config.js b/test/configCases/asset-url/target-node3/webpack.config.js new file mode 100644 index 000000000..655541812 --- /dev/null +++ b/test/configCases/asset-url/target-node3/webpack.config.js @@ -0,0 +1,21 @@ +/** @type {import("../../../../").Configuration} */ +module.exports = { + mode: "development", + target: "node", + devtool: false, + output: { + assetModuleFilename: "[name][ext]", + publicPath: "/" + }, + module: { + rules: [ + { + test: /\.css$/, + type: "asset/resource" + } + ] + }, + experiments: { + asset: true + } +}; diff --git a/test/configCases/asset-url/target-web1/index.css b/test/configCases/asset-url/target-web1/index.css new file mode 100644 index 000000000..077f6dd7c --- /dev/null +++ b/test/configCases/asset-url/target-web1/index.css @@ -0,0 +1 @@ +a {} diff --git a/test/configCases/asset-url/target-web1/index.js b/test/configCases/asset-url/target-web1/index.js new file mode 100644 index 000000000..5284c3ba8 --- /dev/null +++ b/test/configCases/asset-url/target-web1/index.js @@ -0,0 +1,5 @@ +it("should handle import.meta.url in URL()", () => { + const {href} = new URL("./index.css", import.meta.url); + + expect(href).toBe("https://test.cases/path/index.css"); +}); diff --git a/test/configCases/asset-url/target-web1/test.config.js b/test/configCases/asset-url/target-web1/test.config.js new file mode 100644 index 000000000..d13e779c1 --- /dev/null +++ b/test/configCases/asset-url/target-web1/test.config.js @@ -0,0 +1,9 @@ +let _URL = require("url").URL; + +module.exports = { + moduleScope(scope) { + scope.URL = function URL(a, b) { + return new _URL(a, b); + }; + } +}; diff --git a/test/configCases/asset-url/target-web1/webpack.config.js b/test/configCases/asset-url/target-web1/webpack.config.js new file mode 100644 index 000000000..4254fba83 --- /dev/null +++ b/test/configCases/asset-url/target-web1/webpack.config.js @@ -0,0 +1,20 @@ +/** @type {import("../../../../").Configuration} */ +module.exports = { + mode: "development", + target: "web", + devtool: false, + output: { + assetModuleFilename: "[name][ext]" + }, + module: { + rules: [ + { + test: /\.css$/, + type: "asset/resource" + } + ] + }, + experiments: { + asset: true + } +}; diff --git a/test/configCases/asset-url/target-web2/index.css b/test/configCases/asset-url/target-web2/index.css new file mode 100644 index 000000000..077f6dd7c --- /dev/null +++ b/test/configCases/asset-url/target-web2/index.css @@ -0,0 +1 @@ +a {} diff --git a/test/configCases/asset-url/target-web2/index.js b/test/configCases/asset-url/target-web2/index.js new file mode 100644 index 000000000..1b4ac148d --- /dev/null +++ b/test/configCases/asset-url/target-web2/index.js @@ -0,0 +1,5 @@ +it("should handle import.meta.url in URL()", () => { + const {href} = new URL("./index.css", import.meta.url); + + expect(href).toBe("https://test.cases/path2/index.css"); +}); diff --git a/test/configCases/asset-url/target-web2/test.config.js b/test/configCases/asset-url/target-web2/test.config.js new file mode 100644 index 000000000..d13e779c1 --- /dev/null +++ b/test/configCases/asset-url/target-web2/test.config.js @@ -0,0 +1,9 @@ +let _URL = require("url").URL; + +module.exports = { + moduleScope(scope) { + scope.URL = function URL(a, b) { + return new _URL(a, b); + }; + } +}; diff --git a/test/configCases/asset-url/target-web2/webpack.config.js b/test/configCases/asset-url/target-web2/webpack.config.js new file mode 100644 index 000000000..eb110554d --- /dev/null +++ b/test/configCases/asset-url/target-web2/webpack.config.js @@ -0,0 +1,21 @@ +/** @type {import("../../../../").Configuration} */ +module.exports = { + mode: "development", + target: "web", + devtool: false, + output: { + assetModuleFilename: "[name][ext]", + publicPath: "/path2/" + }, + module: { + rules: [ + { + test: /\.css$/, + type: "asset/resource" + } + ] + }, + experiments: { + asset: true + } +}; diff --git a/test/configCases/asset-url/target-webworker1/index.css b/test/configCases/asset-url/target-webworker1/index.css new file mode 100644 index 000000000..077f6dd7c --- /dev/null +++ b/test/configCases/asset-url/target-webworker1/index.css @@ -0,0 +1 @@ +a {} diff --git a/test/configCases/asset-url/target-webworker1/index.js b/test/configCases/asset-url/target-webworker1/index.js new file mode 100644 index 000000000..5284c3ba8 --- /dev/null +++ b/test/configCases/asset-url/target-webworker1/index.js @@ -0,0 +1,5 @@ +it("should handle import.meta.url in URL()", () => { + const {href} = new URL("./index.css", import.meta.url); + + expect(href).toBe("https://test.cases/path/index.css"); +}); diff --git a/test/configCases/asset-url/target-webworker1/test.config.js b/test/configCases/asset-url/target-webworker1/test.config.js new file mode 100644 index 000000000..d13e779c1 --- /dev/null +++ b/test/configCases/asset-url/target-webworker1/test.config.js @@ -0,0 +1,9 @@ +let _URL = require("url").URL; + +module.exports = { + moduleScope(scope) { + scope.URL = function URL(a, b) { + return new _URL(a, b); + }; + } +}; diff --git a/test/configCases/asset-url/target-webworker1/webpack.config.js b/test/configCases/asset-url/target-webworker1/webpack.config.js new file mode 100644 index 000000000..1bc423bb8 --- /dev/null +++ b/test/configCases/asset-url/target-webworker1/webpack.config.js @@ -0,0 +1,20 @@ +/** @type {import("../../../../").Configuration} */ +module.exports = { + mode: "development", + target: "webworker", + devtool: false, + output: { + assetModuleFilename: "[name][ext]" + }, + module: { + rules: [ + { + test: /\.css$/, + type: "asset/resource" + } + ] + }, + experiments: { + asset: true + } +}; diff --git a/test/configCases/asset-url/target-webworker2/index.css b/test/configCases/asset-url/target-webworker2/index.css new file mode 100644 index 000000000..077f6dd7c --- /dev/null +++ b/test/configCases/asset-url/target-webworker2/index.css @@ -0,0 +1 @@ +a {} diff --git a/test/configCases/asset-url/target-webworker2/index.js b/test/configCases/asset-url/target-webworker2/index.js new file mode 100644 index 000000000..ee80741fd --- /dev/null +++ b/test/configCases/asset-url/target-webworker2/index.js @@ -0,0 +1,5 @@ +it("should handle import.meta.url in URL()", () => { + const {href} = new URL("./index.css", import.meta.url); + + expect(href).toBe("https://test.cases/index.css"); +}); diff --git a/test/configCases/asset-url/target-webworker2/test.config.js b/test/configCases/asset-url/target-webworker2/test.config.js new file mode 100644 index 000000000..d13e779c1 --- /dev/null +++ b/test/configCases/asset-url/target-webworker2/test.config.js @@ -0,0 +1,9 @@ +let _URL = require("url").URL; + +module.exports = { + moduleScope(scope) { + scope.URL = function URL(a, b) { + return new _URL(a, b); + }; + } +}; diff --git a/test/configCases/asset-url/target-webworker2/webpack.config.js b/test/configCases/asset-url/target-webworker2/webpack.config.js new file mode 100644 index 000000000..cc8098d98 --- /dev/null +++ b/test/configCases/asset-url/target-webworker2/webpack.config.js @@ -0,0 +1,21 @@ +/** @type {import("../../../../").Configuration} */ +module.exports = { + mode: "development", + target: "webworker", + devtool: false, + output: { + assetModuleFilename: "[name][ext]", + publicPath: "/" + }, + module: { + rules: [ + { + test: /\.css$/, + type: "asset/resource" + } + ] + }, + experiments: { + asset: true + } +}; diff --git a/test/helpers/FakeDocument.js b/test/helpers/FakeDocument.js index a91992f86..1c6c7bc35 100644 --- a/test/helpers/FakeDocument.js +++ b/test/helpers/FakeDocument.js @@ -1,6 +1,7 @@ module.exports = class FakeDocument { constructor() { this.head = this.createElement("head"); + this.baseURI = "https://test.cases/path/index.html"; this._elementsByTagName = new Map([["head", [this.head]]]); } diff --git a/types.d.ts b/types.d.ts index ca71ea5e8..785e3343e 100644 --- a/types.d.ts +++ b/types.d.ts @@ -6948,6 +6948,11 @@ declare interface RuleSetRule { */ compiler?: RuleSetCondition; + /** + * Match dependency type. + */ + dependency?: string; + /** * Match values of properties in the description file (usually package.json). */ @@ -8990,6 +8995,7 @@ declare namespace exports { export let system: string; export let hasOwnProperty: string; export let systemContext: string; + export let baseURI: string; } export const UsageState: Readonly<{ Unused: 0;