Browse Source

fix: conditional patchBootstrap

tophf 3 years ago
parent
commit
a2f21b6413
1 changed files with 28 additions and 16 deletions
  1. 28 16
      scripts/webpack-protect-bootstrap-plugin.js

+ 28 - 16
scripts/webpack-protect-bootstrap-plugin.js

@@ -2,29 +2,39 @@ const escapeStringRegexp = require('escape-string-regexp');
 const webpack = require('webpack');
 
 const G = webpack.RuntimeGlobals;
-const OPTIONAL = false;
 const OBJ_RULE = [
   /([[(,=:]\s*{)(?!__proto__:)\s*(.)/g,
-  (_, str, next) => `${str}__proto__: null${next === '}' ? '' : ','}${next}`
+  (_, str, next) => `${str}__proto__: null${next === '}' ? '' : ','}${next}`,
 ];
 const BOOTSTRAP_RULES = [
   OBJ_RULE,
-  ["typeof Symbol !== 'undefined' && Symbol.toStringTag",
-    'true'],
-  ['Symbol.toStringTag',
-    'toStringTagSym'],
-  ['Object.defineProperty(',
-    'defineProperty('],
-  ['Object.prototype.hasOwnProperty.call(',
-    'safeCall(hasOwnProperty, '],
-  [`${G.hasOwnProperty}(definition, key) && !${G.hasOwnProperty}(exports, key)`,
-    '!(key in exports)'], // these objects have null proto
+  [
+    "typeof Symbol !== 'undefined' && Symbol.toStringTag",
+    'true',
+    G.makeNamespaceObject,
+  ], [
+    'Symbol.toStringTag',
+    'toStringTagSym',
+    G.makeNamespaceObject,
+  ], [
+    'Object.defineProperty(',
+    'defineProperty(',
+    G.definePropertyGetters,
+  ], [
+    `${G.hasOwnProperty}(definition, key) && !${G.hasOwnProperty}(exports, key)`,
+    '!(key in exports)',
+    G.definePropertyGetters,
+  ], [
+    'Object.prototype.hasOwnProperty.call(',
+    'safeCall(hasOwnProperty, ',
+    G.hasOwnProperty,
+  ],
 ];
 const MAIN_RULES = [
   [
     /(__webpack_modules__\[moduleId])\.call\(/g,
     'safeCall($1, ',
-    OPTIONAL,
+    false,
   ], [
     new RegExp(`var (__webpack_module_cache__|${G.require}) = {};.*?var ${G.exports} =`, 's'),
     patchBootstrap,
@@ -62,19 +72,21 @@ function patchBootstrap(src) {
     ? `for (let i = 0, props=${JSON.stringify(uniq)}; i < props.length; i++)
       defineProperty(${G.require}, props[i], {__proto__: null, value: 0, writable: 1});\n`
     : '';
-  const rules = uniq ? BOOTSTRAP_RULES : [OBJ_RULE];
-  return guard + replace(rules, src, this);
+  return guard + replace(BOOTSTRAP_RULES, src, this);
 }
 
 function replace(rules, src, info) {
   src = src.source?.() || src;
   let res = src;
   for (const rule of rules) {
-    const [from, to, mandatory = true] = rule;
+    const [from, to, test = true] = rule;
     const fromRe = typeof from === 'string'
       ? new RegExp(escapeStringRegexp(from), 'g')
       : from;
     const dst = res.replace(fromRe, to.bind?.(info) || to);
+    const mandatory = test === true
+      || test.test?.(src)
+      || typeof test === 'string' && src.includes(test);
     if (dst === res && mandatory) {
       const err = `[${WebpackProtectBootstrapPlugin.name}] `
         + `"${from}" not found in ${info.chunk.name || 'bootstrap'}`;