diff --git a/lib/Compilation.ts b/lib/Compilation.ts index 5469d47d8a6..4324acbeea1 100644 --- a/lib/Compilation.ts +++ b/lib/Compilation.ts @@ -1037,11 +1037,12 @@ class Compilation extends Tapable { for (let i = 0; i < this.modules.length; i++) { const module = this.modules[i]; if (module.assets) { - Object.keys(module.assets).forEach(function (name) { - const file = this.getPath(name); - this.assets[file] = module.assets[name]; - this.applyPlugins('module-asset', module, file); - }, this); + Object.keys(module.assets) + .forEach(name => { + const file = this.getPath(name); + this.assets[file] = module.assets[name]; + this.applyPlugins('module-asset', module, file); + }); } } } diff --git a/lib/Parser.ts b/lib/Parser.ts index 28643448770..a5e8bae2934 100644 --- a/lib/Parser.ts +++ b/lib/Parser.ts @@ -20,12 +20,12 @@ const POSSIBLE_AST_OPTIONS = [ { ranges: true, locations: true, - ecmaVersion: 6, + ecmaVersion: 2017, sourceType: 'module' }, { ranges: true, locations: true, - ecmaVersion: 6, + ecmaVersion: 2017, sourceType: 'script' } ] as ASTOPTION[]; @@ -829,6 +829,13 @@ class Parser extends Tapable { } } + walkAwaitExpression(expression) { + const argument = expression.argument + if (this["walk" + argument.type]) { + return this["walk" + argument.type](argument); + } + } + walkSpreadElement(expression) { if (expression.argument) { this.walkExpression(expression.argument); @@ -1105,7 +1112,7 @@ class Parser extends Tapable { } enterPattern(pattern, onIdent) { - if (this[`enter${pattern.type}`]) { + if (pattern != null && this[`enter${pattern.type}`]) { return this[`enter${pattern.type}`](pattern, onIdent); } } @@ -1251,7 +1258,7 @@ class Parser extends Tapable { ast = acorn.parse(source, { ranges: true, locations: true, - ecmaVersion: 6, + ecmaVersion: 2017, sourceType: 'module', onComment: comments }); @@ -1279,7 +1286,7 @@ class Parser extends Tapable { const ast = acorn.parse(`(${source})`, { ranges: true, locations: true, - ecmaVersion: 6, + ecmaVersion: 2017, sourceType: 'module' }); if (!ast || typeof ast !== 'object' || ast.type !== 'Program') { diff --git a/lib/RuleSet.ts b/lib/RuleSet.ts index cb1bea9a788..a0fa88d0860 100644 --- a/lib/RuleSet.ts +++ b/lib/RuleSet.ts @@ -51,7 +51,7 @@ : { and: [] } : { or: [] } : { not: [] } - : { test: , include: , exclude: } + : { test: , include: , exclude: } normalized: @@ -163,20 +163,33 @@ class RuleSet { if (rule.test || rule.include || rule.exclude) { checkResourceSource('test + include + exclude'); - newRule.resource = RuleSet.normalizeCondition({ + let condition = { test: rule.test, include: rule.include, exclude: rule.exclude - }); + }; + try { + newRule.resource = RuleSet.normalizeCondition(condition); + } catch(error) { + throw new Error(RuleSet.buildErrorMessage(condition, error)); + } } if (rule.resource) { checkResourceSource('resource'); - newRule.resource = RuleSet.normalizeCondition(rule.resource); + try { + newRule.resource = RuleSet.normalizeCondition(rule.resource); + } catch(error) { + throw new Error(RuleSet.buildErrorMessage(rule.resource, error)); + } } if (rule.issuer) { - newRule.issuer = RuleSet.normalizeCondition(rule.issuer); + try { + newRule.issuer = RuleSet.normalizeCondition(rule.issuer); + } catch(error) { + throw new Error(RuleSet.buildErrorMessage(rule.issuer, error)); + } } if (rule.loader && rule.loaders) { @@ -350,6 +363,15 @@ class RuleSet { return andMatcher(matchers); } + static buildErrorMessage(condition, error) { + const conditionAsText = JSON.stringify( + condition, + (key, value) => value === undefined ? "undefined" : value, + 2 + ) + return error.message + " in " + conditionAsText; + } + exec(data) { const result = []; this._run(data, { diff --git a/lib/UmdMainTemplatePlugin.ts b/lib/UmdMainTemplatePlugin.ts index 5041f37a88e..64669bcc803 100644 --- a/lib/UmdMainTemplatePlugin.ts +++ b/lib/UmdMainTemplatePlugin.ts @@ -153,7 +153,7 @@ ${(externals.length > 0 + `})(this, function(${externalsArguments(externals)}) {\nreturn `, 'webpack/universalModuleDefinition'), source, - '\n});\n' + ';\n})' ); }); mainTemplate.plugin('global-hash-paths', paths => { diff --git a/lib/WebpackOptionsDefaulter.ts b/lib/WebpackOptionsDefaulter.ts index 5eccab07692..c15e64c7121 100644 --- a/lib/WebpackOptionsDefaulter.ts +++ b/lib/WebpackOptionsDefaulter.ts @@ -94,7 +94,6 @@ class WebpackOptionsDefaulter extends OptionsDefaulter { this.set('resolveLoader.unsafeCache', true); this.set('resolveLoader.mainFields', ['loader', 'main']); this.set('resolveLoader.extensions', ['.js', '.json']); - this.set('resolveLoader.moduleExtensions', ['-loader']); } } diff --git a/lib/WebpackOptionsValidationError.ts b/lib/WebpackOptionsValidationError.ts index 7c7b84d9613..1a45b3cf5be 100644 --- a/lib/WebpackOptionsValidationError.ts +++ b/lib/WebpackOptionsValidationError.ts @@ -65,6 +65,8 @@ For loader options: webpack 2 no longer allows custom properties in configuratio return `${dataPath} should be a number.`; } return `${dataPath} should be ${err.params.type}:\n${getSchemaPartText(err.parentSchema)}`; + case "instanceof": + return `${dataPath} should be an instance of ${getSchemaPartText(err.parentSchema)}.`; case 'required': const missingProperty = err.params.missingProperty.replace(/^\./, ''); return `${dataPath} misses the property '${missingProperty}'.\n${getSchemaPartText(err.parentSchema, [ diff --git a/lib/validateWebpackOptions.ts b/lib/validateSchema.ts similarity index 71% rename from lib/validateWebpackOptions.ts rename to lib/validateSchema.ts index ada97ef69f8..2efbc96da11 100644 --- a/lib/validateWebpackOptions.ts +++ b/lib/validateSchema.ts @@ -1,9 +1,9 @@ /* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Gajus Kuizinas @gajus - */ + MIT License http://www.opensource.org/licenses/mit-license.php + Author Gajus Kuizinas @gajus +*/ import Ajv = require('ajv'); -const webpackOptionsSchema = require('../schemas/webpackOptionsSchema.json'); +import defineKeywords = require('ajv-keywords') const ajv = new Ajv({ errorDataPath: 'configuration', @@ -11,14 +11,16 @@ const ajv = new Ajv({ verbose: true }); -const validate = ajv.compile(webpackOptionsSchema); +defineKeywords(ajv); -function validateWebpackOptions(options) { +function validateSchema(schema, options) { + const validate = ajv.compile(schema); if (Array.isArray(options)) { const errors = options.map(validateObject); - errors.forEach((list, idx) => { + + errors.forEach(function (list, idx) { list.forEach(function applyPrefix(err) { - err.dataPath = `[${idx}]${err.dataPath}`; + err.dataPath = "[" + idx + "]" + err.dataPath; if (err.children) { err.children.forEach(applyPrefix); } @@ -29,11 +31,11 @@ function validateWebpackOptions(options) { else { return validateObject(options); } -} -function validateObject(options) { - const valid = validate(options); - return valid ? [] : filterErrors(validate.errors); + function validateObject(options) { + const valid = validate(options); + return valid ? [] : filterErrors(validate.errors); + } } function filterErrors(errors) { @@ -62,4 +64,4 @@ function filterErrors(errors) { return newErrors; } -export = validateWebpackOptions; +export = validateSchema; diff --git a/lib/webpack.ts b/lib/webpack.ts index a8371a9aded..6d64286f7a8 100644 --- a/lib/webpack.ts +++ b/lib/webpack.ts @@ -7,14 +7,16 @@ import MultiCompiler = require('./MultiCompiler'); import NodeEnvironmentPlugin = require('./node/NodeEnvironmentPlugin'); import WebpackOptionsApply = require('./WebpackOptionsApply'); import WebpackOptionsDefaulter = require('./WebpackOptionsDefaulter'); -import validateWebpackOptions = require('./validateWebpackOptions'); +import validateSchema = require("./validateSchema"); import WebpackOptionsValidationError = require('./WebpackOptionsValidationError'); +const webpackOptionsSchema = require("../schemas/webpackOptionsSchema.json"); + function webpack(options, callback): Watching function webpack(options): MultiCompiler | Compiler function webpack(options, callback?) { - const webpackOptionsValidationErrors = validateWebpackOptions(options); + const webpackOptionsValidationErrors = validateSchema(webpackOptionsSchema, options); if (webpackOptionsValidationErrors.length) { throw new WebpackOptionsValidationError(webpackOptionsValidationErrors); } @@ -57,7 +59,9 @@ webpack.WebpackOptionsApply = WebpackOptionsApply; webpack.Compiler = Compiler; webpack.MultiCompiler = MultiCompiler; webpack.NodeEnvironmentPlugin = NodeEnvironmentPlugin; -webpack.validate = validateWebpackOptions; +webpack.validate = validateSchema.bind(this, webpackOptionsSchema); +webpack.validateSchema = validateSchema; +webpack.WebpackOptionsValidationError = WebpackOptionsValidationError; function exportPlugins(exports, path, plugins) { plugins.forEach(name => {