Skip to content

Commit

Permalink
Merge pull request #7462 from webpack/feature/match-resource
Browse files Browse the repository at this point in the history
Add matchResource feature (for loaders)
  • Loading branch information
sokra committed Jun 4, 2018
2 parents 2491f5d + 530e1fb commit fe3ca80
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 26 deletions.
28 changes: 22 additions & 6 deletions lib/NormalModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,18 @@ const contextify = (context, request) => {
.split("!")
.map(r => {
const splitPath = r.split("?");
splitPath[0] = path.relative(context, splitPath[0]);
if (path.sep === "\\") splitPath[0] = splitPath[0].replace(/\\/g, "/");
if (splitPath[0].indexOf("../") !== 0) splitPath[0] = "./" + splitPath[0];
if (/^[a-zA-Z]:\\/.test(splitPath[0])) {
splitPath[0] = path.win32.relative(context, splitPath[0]);
if (!/^[a-zA-Z]:\\/.test(splitPath[0])) {
splitPath[0] = splitPath[0].replace(/\\/g, "/");
}
}
if (/^\//.test(splitPath[0])) {
splitPath[0] = path.posix.relative(context, splitPath[0]);
}
if (!/^(\.\.\/|\/|[a-zA-Z]:\\)/.test(splitPath[0])) {
splitPath[0] = "./" + splitPath[0];
}
return splitPath.join("?");
})
.join("!");
Expand Down Expand Up @@ -76,6 +85,7 @@ class NormalModule extends Module {
rawRequest,
loaders,
resource,
matchResource,
parser,
generator,
resolveOptions
Expand All @@ -90,6 +100,7 @@ class NormalModule extends Module {
this.parser = parser;
this.generator = generator;
this.resource = resource;
this.matchResource = matchResource;
this.loaders = loaders;
if (resolveOptions !== undefined) this.resolveOptions = resolveOptions;

Expand Down Expand Up @@ -123,16 +134,21 @@ class NormalModule extends Module {
}

nameForCondition() {
const idx = this.resource.indexOf("?");
if (idx >= 0) return this.resource.substr(0, idx);
return this.resource;
const resource = this.matchResource || this.resource;
const idx = resource.indexOf("?");
if (idx >= 0) return resource.substr(0, idx);
return resource;
}

updateCacheModule(module) {
this.type = module.type;
this.request = module.request;
this.userRequest = module.userRequest;
this.rawRequest = module.rawRequest;
this.parser = module.parser;
this.generator = module.generator;
this.resource = module.resource;
this.matchResource = module.matchResource;
this.loaders = module.loaders;
this.resolveOptions = module.resolveOptions;
}
Expand Down
49 changes: 37 additions & 12 deletions lib/NormalModuleFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
"use strict";

const path = require("path");
const asyncLib = require("neo-async");
const {
Tapable,
Expand All @@ -20,6 +21,8 @@ const cachedMerge = require("./util/cachedMerge");

const EMPTY_RESOLVE_OPTIONS = {};

const MATCH_RESOURCE_REGEX = /^([^!]+)!=!/;

const loaderToIdent = data => {
if (!data.options) {
return data.loader;
Expand Down Expand Up @@ -158,19 +161,33 @@ class NormalModuleFactory extends Tapable {
const context = data.context;
const request = data.request;

const noPreAutoLoaders = request.startsWith("-!");
const noAutoLoaders = noPreAutoLoaders || request.startsWith("!");
const noPrePostAutoLoaders = request.startsWith("!!");
let elements = request
const loaderResolver = this.getResolver("loader");
const normalResolver = this.getResolver("normal", data.resolveOptions);

let matchResource = undefined;
let requestWithoutMatchResource = request;
const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request);
if (matchResourceMatch) {
matchResource = matchResourceMatch[1];
if (/^\.\.?\//.test(matchResource)) {
matchResource = path.join(context, matchResource);
}
requestWithoutMatchResource = request.substr(
matchResourceMatch[0].length
);
}

const noPreAutoLoaders = requestWithoutMatchResource.startsWith("-!");
const noAutoLoaders =
noPreAutoLoaders || requestWithoutMatchResource.startsWith("!");
const noPrePostAutoLoaders = requestWithoutMatchResource.startsWith("!!");
let elements = requestWithoutMatchResource
.replace(/^-?!+/, "")
.replace(/!!+/g, "!")
.split("!");
let resource = elements.pop();
elements = elements.map(identToLoaderRequest);

const loaderResolver = this.getResolver("loader");
const normalResolver = this.getResolver("normal", data.resolveOptions);

asyncLib.parallel(
[
callback =>
Expand Down Expand Up @@ -234,12 +251,15 @@ class NormalModuleFactory extends Tapable {
);
}

const userRequest = loaders
.map(loaderToIdent)
.concat([resource])
.join("!");
const userRequest =
(matchResource !== undefined ? `${matchResource}!=!` : "") +
loaders
.map(loaderToIdent)
.concat([resource])
.join("!");

let resourcePath = resource;
let resourcePath =
matchResource !== undefined ? matchResource : resource;
let resourceQuery = "";
const queryIndex = resourcePath.indexOf("?");
if (queryIndex >= 0) {
Expand All @@ -249,6 +269,10 @@ class NormalModuleFactory extends Tapable {

const result = this.ruleSet.exec({
resource: resourcePath,
realResource:
matchResource !== undefined
? resource.replace(/\?.*/, "")
: resourcePath,
resourceQuery,
issuer: contextInfo.issuer,
compiler: contextInfo.compiler
Expand Down Expand Up @@ -326,6 +350,7 @@ class NormalModuleFactory extends Tapable {
rawRequest: request,
loaders,
resource,
matchResource,
resourceResolveData,
settings,
type,
Expand Down
2 changes: 2 additions & 0 deletions lib/RequestShortener.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const PATH_CHARS_REGEXP = /[-[\]{}()*+?.,\\^$|#\s]/g;
const SEPARATOR_REGEXP = /[/\\]$/;
const FRONT_OR_BACK_BANG_REGEXP = /^!|!$/g;
const INDEX_JS_REGEXP = /\/index.js(!|\?|\(query\))/g;
const MATCH_RESOURCE_REGEXP = /!=!/;

const normalizeBackSlashDirection = request => {
return request.replace(NORMALIZE_SLASH_DIRECTION_REGEXP, "/");
Expand Down Expand Up @@ -73,6 +74,7 @@ class RequestShortener {
}
result = result.replace(INDEX_JS_REGEXP, "$1");
result = result.replace(FRONT_OR_BACK_BANG_REGEXP, "");
result = result.replace(MATCH_RESOURCE_REGEXP, " = ");
this.cache.set(request, result);
return result;
}
Expand Down
12 changes: 12 additions & 0 deletions lib/RuleSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,14 @@ module.exports = class RuleSet {
}
}

if (rule.realResource) {
try {
newRule.realResource = RuleSet.normalizeCondition(rule.realResource);
} catch (error) {
throw new Error(RuleSet.buildErrorMessage(rule.realResource, error));
}
}

if (rule.resourceQuery) {
try {
newRule.resourceQuery = RuleSet.normalizeCondition(rule.resourceQuery);
Expand Down Expand Up @@ -477,10 +485,13 @@ module.exports = class RuleSet {
_run(data, rule, result) {
// test conditions
if (rule.resource && !data.resource) return false;
if (rule.realResource && !data.realResource) return false;
if (rule.resourceQuery && !data.resourceQuery) return false;
if (rule.compiler && !data.compiler) return false;
if (rule.issuer && !data.issuer) return false;
if (rule.resource && !rule.resource(data.resource)) return false;
if (rule.realResource && !rule.realResource(data.realResource))
return false;
if (data.issuer && rule.issuer && !rule.issuer(data.issuer)) return false;
if (
data.resourceQuery &&
Expand All @@ -497,6 +508,7 @@ module.exports = class RuleSet {
const keys = Object.keys(rule).filter(key => {
return ![
"resource",
"realResource",
"resourceQuery",
"compiler",
"issuer",
Expand Down
16 changes: 8 additions & 8 deletions test/NormalModule.unittest.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ describe("NormalModule", () => {
let resource;
let parser;
beforeEach(() => {
request = "some/request";
userRequest = "some/userRequest";
request = "/some/request";
userRequest = "/some/userRequest";
rawRequest = "some/rawRequest";
loaders = [];
resource = "some/resource";
resource = "/some/resource";
parser = {
parse() {}
};
Expand Down Expand Up @@ -66,14 +66,14 @@ describe("NormalModule", () => {
it("contextifies the userRequest of the module", () => {
expect(
normalModule.libIdent({
context: "some/context"
context: "/some/context"
})
).toBe("../userRequest");
});
describe("given a userRequest containing loaders", () => {
beforeEach(() => {
userRequest =
"some/userRequest!some/other/userRequest!some/thing/is/off/here";
"/some/userRequest!/some/other/userRequest!/some/thing/is/off/here";
normalModule = new NormalModule({
type: "javascript/auto",
request,
Expand All @@ -87,15 +87,15 @@ describe("NormalModule", () => {
it("contextifies every path in the userRequest", () => {
expect(
normalModule.libIdent({
context: "some/context"
context: "/some/context"
})
).toBe("../userRequest!../other/userRequest!../thing/is/off/here");
});
});
describe("given a userRequest containing query parameters", () => {
it("ignores paths in query parameters", () => {
userRequest =
"some/context/loader?query=foo\\bar&otherPath=testpath/other";
"F:\\some\\context\\loader?query=foo\\bar&otherPath=testpath/other";
normalModule = new NormalModule({
type: "javascript/auto",
request,
Expand All @@ -107,7 +107,7 @@ describe("NormalModule", () => {
});
expect(
normalModule.libIdent({
context: "some/context"
context: "F:\\some\\context"
})
).toBe("./loader?query=foo\\bar&otherPath=testpath/other");
});
Expand Down
11 changes: 11 additions & 0 deletions test/cases/wasm/two-files-loader/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
it("should be able to create two modules from loader", function() {
return import("./wrapper-loader!./src/wasm.dat").then(function(wasm) {
expect(wasm.getString()).toEqual("Hello World");
});
});

it("should be able to create two modules from loader with remaining request", function() {
return import("./wrapper-loader2!./src/wasm.dat?2").then(function(wasm) {
expect(wasm.getString()).toEqual("Hello World");
});
});
8 changes: 8 additions & 0 deletions test/cases/wasm/two-files-loader/src/wasm.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
(module
(memory (export "memory") 1)
(data (i32.const 16) "Hello World\00")
(func (export "getString") (result i32)
(i32.const 16)
)
)

5 changes: 5 additions & 0 deletions test/cases/wasm/two-files-loader/test.filter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");

module.exports = function(config) {
return supportsWebAssembly();
};
17 changes: 17 additions & 0 deletions test/cases/wasm/two-files-loader/wrapper-loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const stringifyRequest = require("loader-utils").stringifyRequest;

module.exports.pitch = function(remainingRequest) {
return `
import { getString as _getString, memory } from ${stringifyRequest(this,
`${this.resourcePath}.wat!=!${remainingRequest}`
)};
export function getString() {
const strBuf = new Uint8Array(memory.buffer, _getString());
const idx = strBuf.indexOf(0);
const strBuf2 = strBuf.slice(0, idx);
const str = Buffer.from(strBuf2).toString("utf-8");
return str;
};
`;
};
18 changes: 18 additions & 0 deletions test/cases/wasm/two-files-loader/wrapper-loader2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const stringifyRequest = require("loader-utils").stringifyRequest;

module.exports.pitch = function(remainingRequest) {
return `
import { getString as _getString, memory } from ${stringifyRequest(
this,
`${this.resourcePath}.wasm!=!wast-loader!${remainingRequest}`
)};
export function getString() {
const strBuf = new Uint8Array(memory.buffer, _getString());
const idx = strBuf.indexOf(0);
const strBuf2 = strBuf.slice(0, idx);
const str = Buffer.from(strBuf2).toString("utf-8");
return str;
};
`;
};

0 comments on commit fe3ca80

Please sign in to comment.