feat: support function matcher in rule options (#19952)
Github Actions / lint (push) Waiting to run Details
Github Actions / validate-legacy-node (push) Waiting to run Details
Github Actions / benchmark (1/4) (push) Waiting to run Details
Github Actions / benchmark (2/4) (push) Waiting to run Details
Github Actions / benchmark (3/4) (push) Waiting to run Details
Github Actions / benchmark (4/4) (push) Waiting to run Details
Github Actions / basic (push) Waiting to run Details
Github Actions / unit (push) Waiting to run Details
Github Actions / integration (10.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (10.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (10.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (12.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (14.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (16.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (18.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (20.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (20.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (24.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (24.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (24.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (24.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (24.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (24.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (lts/*, ubuntu-latest, a, 1) (push) Blocked by required conditions Details
Github Actions / integration (lts/*, ubuntu-latest, b, 1) (push) Blocked by required conditions Details

This commit is contained in:
hai-x 2025-09-30 02:22:46 +08:00 committed by GitHub
parent 8c0fa9e9dc
commit 761b153060
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 91 additions and 30 deletions

View File

@ -23,7 +23,7 @@ export type Rules = Rule[] | Rule;
/**
* Filtering rule as regex or string.
*/
export type Rule = RegExp | string;
export type Rule = RegExp | string | ((str: string) => boolean);
export interface BannerPluginOptions {
/**

View File

@ -11,7 +11,7 @@ export type Rules = Rule[] | Rule;
/**
* Include source maps for modules based on their extension (defaults to .js and .css).
*/
export type Rule = RegExp | string;
export type Rule = RegExp | string | ((str: string) => boolean);
export interface SourceMapDevToolPluginOptions {
/**

View File

@ -38,15 +38,7 @@ class LoaderOptionsPlugin {
// If no options are set then generate empty options object
if (typeof options !== "object") options = {};
if (!options.test) {
/** @type {Partial<RegExp>} */
const defaultTrueMockRegExp = {
test: () => true
};
/** @type {RegExp} */
options.test =
/** @type {RegExp} */
(defaultTrueMockRegExp);
options.test = () => true;
}
this.options = options;
}

View File

@ -15,7 +15,7 @@ const memoize = require("./util/memoize");
/** @typedef {import("./Module")} Module */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {string | RegExp | (string | RegExp)[]} Matcher */
/** @typedef {string | RegExp | ((str: string) => boolean) | (string | RegExp | ((str: string) => boolean))[]} Matcher */
/** @typedef {{ test?: Matcher, include?: Matcher, exclude?: Matcher }} MatchObject */
const ModuleFilenameHelpers = module.exports;
@ -334,13 +334,15 @@ ModuleFilenameHelpers.replaceDuplicates = (array, fn, comparator) => {
*/
const matchPart = (str, test) => {
if (!test) return true;
if (Array.isArray(test)) {
return test.some((test) => matchPart(str, test));
}
if (typeof test === "string") {
if (test instanceof RegExp) {
return test.test(str);
} else if (typeof test === "string") {
return str.startsWith(test);
} else if (typeof test === "function") {
return test(str);
}
return test.test(str);
return test.some((test) => matchPart(str, test));
};
ModuleFilenameHelpers.matchPart = matchPart;

View File

@ -3,4 +3,4 @@
* DO NOT MODIFY BY HAND.
* Run `yarn fix:special` to update
*/
"use strict";function n(t,{instancePath:e="",parentData:s,parentDataProperty:l,rootData:a=t}={}){let r=null,o=0;const u=o;let i=!1;const p=o;if(o===p)if(Array.isArray(t)){const n=t.length;for(let e=0;e<n;e++){let n=t[e];const s=o,l=o;let a=!1,u=null;const i=o,p=o;let f=!1;const h=o;if(!(n instanceof RegExp)){const n={params:{}};null===r?r=[n]:r.push(n),o++}var c=h===o;if(f=f||c,!f){const t=o;if(o===t)if("string"==typeof n){if(n.length<1){const n={params:{}};null===r?r=[n]:r.push(n),o++}}else{const n={params:{type:"string"}};null===r?r=[n]:r.push(n),o++}c=t===o,f=f||c}if(f)o=p,null!==r&&(p?r.length=p:r=null);else{const n={params:{}};null===r?r=[n]:r.push(n),o++}if(i===o&&(a=!0,u=0),a)o=l,null!==r&&(l?r.length=l:r=null);else{const n={params:{passingSchemas:u}};null===r?r=[n]:r.push(n),o++}if(s!==o)break}}else{const n={params:{type:"array"}};null===r?r=[n]:r.push(n),o++}var f=p===o;if(i=i||f,!i){const n=o,e=o;let s=!1;const l=o;if(!(t instanceof RegExp)){const n={params:{}};null===r?r=[n]:r.push(n),o++}var h=l===o;if(s=s||h,!s){const n=o;if(o===n)if("string"==typeof t){if(t.length<1){const n={params:{}};null===r?r=[n]:r.push(n),o++}}else{const n={params:{type:"string"}};null===r?r=[n]:r.push(n),o++}h=n===o,s=s||h}if(s)o=e,null!==r&&(e?r.length=e:r=null);else{const n={params:{}};null===r?r=[n]:r.push(n),o++}f=n===o,i=i||f}if(!i){const t={params:{}};return null===r?r=[t]:r.push(t),o++,n.errors=r,!1}return o=u,null!==r&&(u?r.length=u:r=null),n.errors=r,0===o}function t(e,{instancePath:s="",parentData:l,parentDataProperty:a,rootData:r=e}={}){let o=null,u=0;const i=u;let p=!1;const c=u;if(u===c)if("string"==typeof e){if(e.length<1){const n={params:{}};null===o?o=[n]:o.push(n),u++}}else{const n={params:{type:"string"}};null===o?o=[n]:o.push(n),u++}var f=c===u;if(p=p||f,!p){const t=u;if(u===t)if(e&&"object"==typeof e&&!Array.isArray(e)){let t;if(void 0===e.banner&&(t="banner")){const n={params:{missingProperty:t}};null===o?o=[n]:o.push(n),u++}else{const t=u;for(const n in e)if("banner"!==n&&"entryOnly"!==n&&"exclude"!==n&&"footer"!==n&&"include"!==n&&"raw"!==n&&"stage"!==n&&"test"!==n){const t={params:{additionalProperty:n}};null===o?o=[t]:o.push(t),u++;break}if(t===u){if(void 0!==e.banner){let n=e.banner;const t=u,s=u;let l=!1;const a=u;if("string"!=typeof n){const n={params:{type:"string"}};null===o?o=[n]:o.push(n),u++}var h=a===u;if(l=l||h,!l){const t=u;if(!(n instanceof Function)){const n={params:{}};null===o?o=[n]:o.push(n),u++}h=t===u,l=l||h}if(l)u=s,null!==o&&(s?o.length=s:o=null);else{const n={params:{}};null===o?o=[n]:o.push(n),u++}var m=t===u}else m=!0;if(m){if(void 0!==e.entryOnly){const n=u;if("boolean"!=typeof e.entryOnly){const n={params:{type:"boolean"}};null===o?o=[n]:o.push(n),u++}m=n===u}else m=!0;if(m){if(void 0!==e.exclude){const t=u,l=u;let a=!1,i=null;const p=u;if(n(e.exclude,{instancePath:s+"/exclude",parentData:e,parentDataProperty:"exclude",rootData:r})||(o=null===o?n.errors:o.concat(n.errors),u=o.length),p===u&&(a=!0,i=0),a)u=l,null!==o&&(l?o.length=l:o=null);else{const n={params:{passingSchemas:i}};null===o?o=[n]:o.push(n),u++}m=t===u}else m=!0;if(m){if(void 0!==e.footer){const n=u;if("boolean"!=typeof e.footer){const n={params:{type:"boolean"}};null===o?o=[n]:o.push(n),u++}m=n===u}else m=!0;if(m){if(void 0!==e.include){const t=u,l=u;let a=!1,i=null;const p=u;if(n(e.include,{instancePath:s+"/include",parentData:e,parentDataProperty:"include",rootData:r})||(o=null===o?n.errors:o.concat(n.errors),u=o.length),p===u&&(a=!0,i=0),a)u=l,null!==o&&(l?o.length=l:o=null);else{const n={params:{passingSchemas:i}};null===o?o=[n]:o.push(n),u++}m=t===u}else m=!0;if(m){if(void 0!==e.raw){const n=u;if("boolean"!=typeof e.raw){const n={params:{type:"boolean"}};null===o?o=[n]:o.push(n),u++}m=n===u}else m=!0;if(m){if(void 0!==e.stage){const n=u;if("number"!=typeof e.stage){const n={params:{type:"number"}};null===o?o=[n]:o.push(n),u++}m=n===u}else m=!0;if(m)if(void 0!==e.test){const t=u,l=u;let a=!1,i=null;const p=u;if(n(e.test,{instancePath:s+"/test",parentData:e,parentDataProperty:"test",rootData:r})||(o=null===o?n.errors:o.concat(n.errors),u=o.length),p===u&&(a=!0,i=0),a)u=l,null!==o&&(l?o.length=l:o=null);else{const n={params:{passingSchemas:i}};null===o?o=[n]:o.push(n),u++}m=t===u}else m=!0}}}}}}}}}else{const n={params:{type:"object"}};null===o?o=[n]:o.push(n),u++}if(f=t===u,p=p||f,!p){const n=u;if(!(e instanceof Function)){const n={params:{}};null===o?o=[n]:o.push(n),u++}f=n===u,p=p||f}}if(!p){const n={params:{}};return null===o?o=[n]:o.push(n),u++,t.errors=o,!1}return u=i,null!==o&&(i?o.length=i:o=null),t.errors=o,0===u}module.exports=t,module.exports.default=t;
"use strict";function n(t,{instancePath:s="",parentData:e,parentDataProperty:l,rootData:a=t}={}){let o=null,r=0;const u=r;let i=!1;const p=r;if(r===p)if(Array.isArray(t)){const n=t.length;for(let s=0;s<n;s++){let n=t[s];const e=r,l=r;let a=!1,u=null;const i=r,p=r;let f=!1;const h=r;if(!(n instanceof RegExp)){const n={params:{}};null===o?o=[n]:o.push(n),r++}var c=h===r;if(f=f||c,!f){const t=r;if(r===t)if("string"==typeof n){if(n.length<1){const n={params:{}};null===o?o=[n]:o.push(n),r++}}else{const n={params:{type:"string"}};null===o?o=[n]:o.push(n),r++}if(c=t===r,f=f||c,!f){const t=r;if(!(n instanceof Function)){const n={params:{}};null===o?o=[n]:o.push(n),r++}c=t===r,f=f||c}}if(f)r=p,null!==o&&(p?o.length=p:o=null);else{const n={params:{}};null===o?o=[n]:o.push(n),r++}if(i===r&&(a=!0,u=0),a)r=l,null!==o&&(l?o.length=l:o=null);else{const n={params:{passingSchemas:u}};null===o?o=[n]:o.push(n),r++}if(e!==r)break}}else{const n={params:{type:"array"}};null===o?o=[n]:o.push(n),r++}var f=p===r;if(i=i||f,!i){const n=r,s=r;let e=!1;const l=r;if(!(t instanceof RegExp)){const n={params:{}};null===o?o=[n]:o.push(n),r++}var h=l===r;if(e=e||h,!e){const n=r;if(r===n)if("string"==typeof t){if(t.length<1){const n={params:{}};null===o?o=[n]:o.push(n),r++}}else{const n={params:{type:"string"}};null===o?o=[n]:o.push(n),r++}if(h=n===r,e=e||h,!e){const n=r;if(!(t instanceof Function)){const n={params:{}};null===o?o=[n]:o.push(n),r++}h=n===r,e=e||h}}if(e)r=s,null!==o&&(s?o.length=s:o=null);else{const n={params:{}};null===o?o=[n]:o.push(n),r++}f=n===r,i=i||f}if(!i){const t={params:{}};return null===o?o=[t]:o.push(t),r++,n.errors=o,!1}return r=u,null!==o&&(u?o.length=u:o=null),n.errors=o,0===r}function t(s,{instancePath:e="",parentData:l,parentDataProperty:a,rootData:o=s}={}){let r=null,u=0;const i=u;let p=!1;const c=u;if(u===c)if("string"==typeof s){if(s.length<1){const n={params:{}};null===r?r=[n]:r.push(n),u++}}else{const n={params:{type:"string"}};null===r?r=[n]:r.push(n),u++}var f=c===u;if(p=p||f,!p){const t=u;if(u===t)if(s&&"object"==typeof s&&!Array.isArray(s)){let t;if(void 0===s.banner&&(t="banner")){const n={params:{missingProperty:t}};null===r?r=[n]:r.push(n),u++}else{const t=u;for(const n in s)if("banner"!==n&&"entryOnly"!==n&&"exclude"!==n&&"footer"!==n&&"include"!==n&&"raw"!==n&&"stage"!==n&&"test"!==n){const t={params:{additionalProperty:n}};null===r?r=[t]:r.push(t),u++;break}if(t===u){if(void 0!==s.banner){let n=s.banner;const t=u,e=u;let l=!1;const a=u;if("string"!=typeof n){const n={params:{type:"string"}};null===r?r=[n]:r.push(n),u++}var h=a===u;if(l=l||h,!l){const t=u;if(!(n instanceof Function)){const n={params:{}};null===r?r=[n]:r.push(n),u++}h=t===u,l=l||h}if(l)u=e,null!==r&&(e?r.length=e:r=null);else{const n={params:{}};null===r?r=[n]:r.push(n),u++}var m=t===u}else m=!0;if(m){if(void 0!==s.entryOnly){const n=u;if("boolean"!=typeof s.entryOnly){const n={params:{type:"boolean"}};null===r?r=[n]:r.push(n),u++}m=n===u}else m=!0;if(m){if(void 0!==s.exclude){const t=u,l=u;let a=!1,i=null;const p=u;if(n(s.exclude,{instancePath:e+"/exclude",parentData:s,parentDataProperty:"exclude",rootData:o})||(r=null===r?n.errors:r.concat(n.errors),u=r.length),p===u&&(a=!0,i=0),a)u=l,null!==r&&(l?r.length=l:r=null);else{const n={params:{passingSchemas:i}};null===r?r=[n]:r.push(n),u++}m=t===u}else m=!0;if(m){if(void 0!==s.footer){const n=u;if("boolean"!=typeof s.footer){const n={params:{type:"boolean"}};null===r?r=[n]:r.push(n),u++}m=n===u}else m=!0;if(m){if(void 0!==s.include){const t=u,l=u;let a=!1,i=null;const p=u;if(n(s.include,{instancePath:e+"/include",parentData:s,parentDataProperty:"include",rootData:o})||(r=null===r?n.errors:r.concat(n.errors),u=r.length),p===u&&(a=!0,i=0),a)u=l,null!==r&&(l?r.length=l:r=null);else{const n={params:{passingSchemas:i}};null===r?r=[n]:r.push(n),u++}m=t===u}else m=!0;if(m){if(void 0!==s.raw){const n=u;if("boolean"!=typeof s.raw){const n={params:{type:"boolean"}};null===r?r=[n]:r.push(n),u++}m=n===u}else m=!0;if(m){if(void 0!==s.stage){const n=u;if("number"!=typeof s.stage){const n={params:{type:"number"}};null===r?r=[n]:r.push(n),u++}m=n===u}else m=!0;if(m)if(void 0!==s.test){const t=u,l=u;let a=!1,i=null;const p=u;if(n(s.test,{instancePath:e+"/test",parentData:s,parentDataProperty:"test",rootData:o})||(r=null===r?n.errors:r.concat(n.errors),u=r.length),p===u&&(a=!0,i=0),a)u=l,null!==r&&(l?r.length=l:r=null);else{const n={params:{passingSchemas:i}};null===r?r=[n]:r.push(n),u++}m=t===u}else m=!0}}}}}}}}}else{const n={params:{type:"object"}};null===r?r=[n]:r.push(n),u++}if(f=t===u,p=p||f,!p){const n=u;if(!(s instanceof Function)){const n={params:{}};null===r?r=[n]:r.push(n),u++}f=n===u,p=p||f}}if(!p){const n={params:{}};return null===r?r=[n]:r.push(n),u++,t.errors=r,!1}return u=i,null!==r&&(i?r.length=i:r=null),t.errors=r,0===u}module.exports=t,module.exports.default=t;

View File

@ -15,6 +15,10 @@
{
"type": "string",
"minLength": 1
},
{
"instanceof": "Function",
"tsType": "((str: string) => boolean)"
}
]
},

File diff suppressed because one or more lines are too long

View File

@ -10,6 +10,10 @@
{
"type": "string",
"minLength": 1
},
{
"instanceof": "Function",
"tsType": "((str: string) => boolean)"
}
]
},

View File

@ -0,0 +1,8 @@
it("bundle1 should include eval sourcemapped test1.js and test2.js as is", function() {
var fs = require("fs");
var path = require("path");
var bundle1 = fs.readFileSync(path.join(__dirname, "bundle1.js"), "utf-8");
expect(bundle1).toMatch("eval(\"{var test1marker");
expect(bundle1).toMatch("var test2marker");
expect(bundle1).not.toMatch("eval(\"{var test2marker");
});

View File

@ -0,0 +1,3 @@
var test1marker = {};
module.exports = test1marker;

View File

@ -0,0 +1,3 @@
var test2marker = {};
module.exports = test2marker;

View File

@ -0,0 +1,29 @@
"use strict";
const webpack = require("../../../../");
/** @type {import("../../../../").Configuration} */
module.exports = {
node: {
__dirname: false,
__filename: false
},
entry: {
bundle0: ["./index.js"],
bundle1: ["./test1.js", "./test2.js"]
},
output: {
filename: "[name].js"
},
plugins: [
new webpack.EvalSourceMapDevToolPlugin({
test: (str) => {
if (str.endsWith(".js")) return true;
return false;
},
exclude: /test2\.js/,
module: true,
columns: false
})
]
};

38
types.d.ts vendored
View File

@ -516,7 +516,7 @@ declare interface BannerPluginOptions {
/**
* Exclude all modules matching any of these conditions.
*/
exclude?: string | RegExp | Rule[];
exclude?: string | RegExp | Rule[] | ((str: string) => boolean);
/**
* If true, banner will be placed at the end of the output.
@ -526,7 +526,7 @@ declare interface BannerPluginOptions {
/**
* Include all modules matching any of these conditions.
*/
include?: string | RegExp | Rule[];
include?: string | RegExp | Rule[] | ((str: string) => boolean);
/**
* If true, banner will not be wrapped in a comment.
@ -541,7 +541,7 @@ declare interface BannerPluginOptions {
/**
* Include all modules that pass test assertion.
*/
test?: string | RegExp | Rule[];
test?: string | RegExp | Rule[] | ((str: string) => boolean);
}
declare interface BaseResolveRequest {
/**
@ -9801,11 +9801,27 @@ declare interface MapOptions {
module?: boolean;
}
declare interface MatchObject {
test?: string | RegExp | (string | RegExp)[];
include?: string | RegExp | (string | RegExp)[];
exclude?: string | RegExp | (string | RegExp)[];
test?:
| string
| RegExp
| ((str: string) => boolean)
| (string | RegExp | ((str: string) => boolean))[];
include?:
| string
| RegExp
| ((str: string) => boolean)
| (string | RegExp | ((str: string) => boolean))[];
exclude?:
| string
| RegExp
| ((str: string) => boolean)
| (string | RegExp | ((str: string) => boolean))[];
}
type Matcher = string | RegExp | (string | RegExp)[];
type Matcher =
| string
| RegExp
| ((str: string) => boolean)
| (string | RegExp | ((str: string) => boolean))[];
declare interface MaybeMergeableInitFragment<GenerateContext> {
key?: string;
stage: number;
@ -15062,7 +15078,7 @@ declare interface Rmdir {
callback: (err: null | NodeJS.ErrnoException) => void
): void;
}
type Rule = string | RegExp;
type Rule = string | RegExp | ((str: string) => boolean);
declare interface RuleSet {
/**
* map of references in the rule set (may grow over time)
@ -16478,7 +16494,7 @@ declare interface SourceMapDevToolPluginOptions {
/**
* Exclude modules that match the given value from source map generation.
*/
exclude?: string | RegExp | Rule[];
exclude?: string | RegExp | Rule[] | ((str: string) => boolean);
/**
* Generator string or function to create identifiers of modules for the 'sources' array in the SourceMap used only if 'moduleFilenameTemplate' would result in a conflict.
@ -16500,7 +16516,7 @@ declare interface SourceMapDevToolPluginOptions {
/**
* Include source maps for module paths that match the given value.
*/
include?: string | RegExp | Rule[];
include?: string | RegExp | Rule[] | ((str: string) => boolean);
/**
* Indicates whether SourceMaps from loaders should be used (defaults to true).
@ -16537,7 +16553,7 @@ declare interface SourceMapDevToolPluginOptions {
/**
* Include source maps for modules based on their extension (defaults to .js and .css).
*/
test?: string | RegExp | Rule[];
test?: string | RegExp | Rule[] | ((str: string) => boolean);
}
declare class SourceMapSource extends Source {
constructor(