1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- const escapeStringRegexp = require('escape-string-regexp');
- /**
- * WARNING! The following globals must be correctly assigned using wrapper-webpack-plugin.
- * toStringTag = Symbol.toStringTag
- * defineProperty = Object.defineProperty
- * hasOwnProperty = Object.prototype.hasOwnProperty
- * safeCall = Function.prototype.call.bind(Function.prototype.call)
- */
- class WebpackProtectBootstrapPlugin {
- apply(compiler) {
- const NAME = this.constructor.name;
- const NULL_PROTO = '__proto__: null';
- const NULL_OBJ = `{ ${NULL_PROTO} }`;
- compiler.hooks.compilation.tap(NAME, (compilation) => {
- const { hooks, requireFn } = compilation.mainTemplate;
- hooks.localVars.tap(NAME, src => replace(src, [[
- 'installedModules = {};',
- `installedModules = ${NULL_OBJ}; \
- for (let i = 0, c, str = "cdmnoprt"; i < str.length && (c = str[i++]);) \
- defineProperty(${requireFn}, c, { value: undefined, writable: true });`,
- ]]));
- hooks.moduleObj.tap(NAME, src => replace(src, [[
- 'exports: {}',
- `exports: ${NULL_OBJ}, ${NULL_PROTO}`,
- ]]));
- hooks.require.tap(NAME, src => replace(src, [[
- 'modules[moduleId].call(',
- 'safeCall(modules[moduleId], ',
- ]]));
- hooks.requireExtensions.tap(NAME, src => replace(src, [
- ["(typeof Symbol !== 'undefined' && Symbol.toStringTag)", '(true)'],
- ['Symbol.toStringTag', 'toStringTag'],
- ['Object.defineProperty', 'defineProperty'],
- ['Object.create(null)', NULL_OBJ],
- ['for(var key in value)', 'for(const key in value)'],
- ['function(key) { return value[key]; }.bind(null, key)',
- '() => value[key]'],
- [/function[^{]+{[^}]+?hasOwnProperty\.call[^}]+}/g,
- '(obj, key) => safeCall(hasOwnProperty, obj, key)'],
- ]));
- });
- }
- }
- function replace(src, fromTo) {
- const origSrc = src;
- for (const [from, to] of fromTo) {
- const fromRe = typeof from === 'string'
- ? new RegExp(escapeStringRegexp(from), 'g')
- : from;
- const dst = src.replace(fromRe, to);
- if (dst === src) {
- throw new Error(`${WebpackProtectBootstrapPlugin.constructor.name}: `
- + `"${from}" not found in "${origSrc}"`);
- }
- src = dst;
- }
- return src;
- }
- module.exports = WebpackProtectBootstrapPlugin;
|