Created
December 23, 2021 09:47
-
-
Save SukkaW/7a398707e14fd3c910aeb552d7b2a405 to your computer and use it in GitHub Desktop.
This file has been truncated, but you can view the full file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******/ (function() { // webpackBootstrap | |
/******/ var __webpack_modules__ = ({ | |
/***/ 1145: | |
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { | |
"use strict"; | |
Object.defineProperty(exports, "__esModule", ({ value: true })); | |
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } | |
var path = _interopDefault(__webpack_require__(6470)); | |
var minimatch = _interopDefault(__webpack_require__(1171)); | |
var createDebug = _interopDefault(__webpack_require__(1227)); | |
var objectSchema = __webpack_require__(9174); | |
/** | |
* @fileoverview ConfigSchema | |
* @author Nicholas C. Zakas | |
*/ | |
//------------------------------------------------------------------------------ | |
// Helpers | |
//------------------------------------------------------------------------------ | |
/** | |
* Assets that a given value is an array. | |
* @param {*} value The value to check. | |
* @returns {void} | |
* @throws {TypeError} When the value is not an array. | |
*/ | |
function assertIsArray(value) { | |
if (!Array.isArray(value)) { | |
throw new TypeError('Expected value to be an array.'); | |
} | |
} | |
/** | |
* Assets that a given value is an array containing only strings and functions. | |
* @param {*} value The value to check. | |
* @returns {void} | |
* @throws {TypeError} When the value is not an array of strings and functions. | |
*/ | |
function assertIsArrayOfStringsAndFunctions(value, name) { | |
assertIsArray(value); | |
if (value.some(item => typeof item !== 'string' && typeof item !== 'function')) { | |
throw new TypeError('Expected array to only contain strings.'); | |
} | |
} | |
//------------------------------------------------------------------------------ | |
// Exports | |
//------------------------------------------------------------------------------ | |
/** | |
* The base schema that every ConfigArray uses. | |
* @type Object | |
*/ | |
const baseSchema = Object.freeze({ | |
name: { | |
required: false, | |
merge() { | |
return undefined; | |
}, | |
validate(value) { | |
if (typeof value !== 'string') { | |
throw new TypeError('Property must be a string.'); | |
} | |
} | |
}, | |
files: { | |
required: false, | |
merge() { | |
return undefined; | |
}, | |
validate(value) { | |
// first check if it's an array | |
assertIsArray(value); | |
// then check each member | |
value.forEach(item => { | |
if (Array.isArray(item)) { | |
assertIsArrayOfStringsAndFunctions(item); | |
} else if (typeof item !== 'string' && typeof item !== 'function') { | |
throw new TypeError('Items must be a string, a function, or an array of strings and functions.'); | |
} | |
}); | |
} | |
}, | |
ignores: { | |
required: false, | |
merge() { | |
return undefined; | |
}, | |
validate: assertIsArrayOfStringsAndFunctions | |
} | |
}); | |
/** | |
* @fileoverview ConfigArray | |
* @author Nicholas C. Zakas | |
*/ | |
//------------------------------------------------------------------------------ | |
// Helpers | |
//------------------------------------------------------------------------------ | |
const debug = createDebug('@hwc/config-array'); | |
const MINIMATCH_OPTIONS = { | |
matchBase: true | |
}; | |
const CONFIG_TYPES = new Set(['array', 'function']); | |
/** | |
* Shorthand for checking if a value is a string. | |
* @param {any} value The value to check. | |
* @returns {boolean} True if a string, false if not. | |
*/ | |
function isString(value) { | |
return typeof value === 'string'; | |
} | |
/** | |
* Normalizes a `ConfigArray` by flattening it and executing any functions | |
* that are found inside. | |
* @param {Array} items The items in a `ConfigArray`. | |
* @param {Object} context The context object to pass into any function | |
* found. | |
* @param {Array<string>} extraConfigTypes The config types to check. | |
* @returns {Promise<Array>} A flattened array containing only config objects. | |
* @throws {TypeError} When a config function returns a function. | |
*/ | |
async function normalize(items, context, extraConfigTypes) { | |
const allowFunctions = extraConfigTypes.includes('function'); | |
const allowArrays = extraConfigTypes.includes('array'); | |
async function *flatTraverse(array) { | |
for (let item of array) { | |
if (typeof item === 'function') { | |
if (!allowFunctions) { | |
throw new TypeError('Unexpected function.'); | |
} | |
item = item(context); | |
if (item.then) { | |
item = await item; | |
} | |
} | |
if (Array.isArray(item)) { | |
if (!allowArrays) { | |
throw new TypeError('Unexpected array.'); | |
} | |
yield * flatTraverse(item); | |
} else if (typeof item === 'function') { | |
throw new TypeError('A config function can only return an object or array.'); | |
} else { | |
yield item; | |
} | |
} | |
} | |
/* | |
* Async iterables cannot be used with the spread operator, so we need to manually | |
* create the array to return. | |
*/ | |
const asyncIterable = await flatTraverse(items); | |
const configs = []; | |
for await (const config of asyncIterable) { | |
configs.push(config); | |
} | |
return configs; | |
} | |
/** | |
* Normalizes a `ConfigArray` by flattening it and executing any functions | |
* that are found inside. | |
* @param {Array} items The items in a `ConfigArray`. | |
* @param {Object} context The context object to pass into any function | |
* found. | |
* @param {Array<string>} extraConfigTypes The config types to check. | |
* @returns {Array} A flattened array containing only config objects. | |
* @throws {TypeError} When a config function returns a function. | |
*/ | |
function normalizeSync(items, context, extraConfigTypes) { | |
const allowFunctions = extraConfigTypes.includes('function'); | |
const allowArrays = extraConfigTypes.includes('array'); | |
function *flatTraverse(array) { | |
for (let item of array) { | |
if (typeof item === 'function') { | |
if (!allowFunctions) { | |
throw new TypeError('Unexpected function.'); | |
} | |
item = item(context); | |
if (item.then) { | |
throw new TypeError('Async config functions are not supported.'); | |
} | |
} | |
if (Array.isArray(item)) { | |
if (!allowArrays) { | |
throw new TypeError('Unexpected array.'); | |
} | |
yield * flatTraverse(item); | |
} else if (typeof item === 'function') { | |
throw new TypeError('A config function can only return an object or array.'); | |
} else { | |
yield item; | |
} | |
} | |
} | |
return [...flatTraverse(items)]; | |
} | |
/** | |
* Determines if a given file path should be ignored based on the given | |
* matcher. | |
* @param {string|() => boolean} matcher The pattern to match. | |
* @param {string} filePath The absolute path of the file to check. | |
* @param {string} relativeFilePath The relative path of the file to check. | |
* @returns {boolean} True if the path should be ignored and false if not. | |
*/ | |
function shouldIgnoreFilePath(matcher, filePath, relativeFilePath) { | |
if (typeof matcher === 'function') { | |
return matcher(filePath); | |
} | |
return minimatch(relativeFilePath, matcher, MINIMATCH_OPTIONS); | |
} | |
/** | |
* Determines if a given file path is matched by a config. If the config | |
* has no `files` field, then it matches; otherwise, if a `files` field | |
* is present then we match the globs in `files` and exclude any globs in | |
* `ignores`. | |
* @param {string} filePath The absolute file path to check. | |
* @param {Object} config The config object to check. | |
* @returns {boolean} True if the file path is matched by the config, | |
* false if not. | |
*/ | |
function pathMatches(filePath, basePath, config) { | |
// a config without `files` field always match | |
if (!config.files) { | |
return true; | |
} | |
/* | |
* For both files and ignores, functions are passed the absolute | |
* file path while strings are compared against the relative | |
* file path. | |
*/ | |
const relativeFilePath = path.relative(basePath, filePath); | |
// if files isn't an array, throw an error | |
if (!Array.isArray(config.files) || config.files.length === 0) { | |
throw new TypeError('The files key must be a non-empty array.'); | |
} | |
// match both strings and functions | |
const match = pattern => { | |
if (isString(pattern)) { | |
return minimatch(relativeFilePath, pattern, MINIMATCH_OPTIONS); | |
} | |
if (typeof pattern === 'function') { | |
return pattern(filePath); | |
} | |
throw new TypeError(`Unexpected matcher type ${pattern}.`); | |
}; | |
const isFilePathIgnored = matcher => { | |
return shouldIgnoreFilePath(matcher, filePath, relativeFilePath); | |
}; | |
// check for all matches to config.files | |
let filePathMatchesPattern = config.files.some(pattern => { | |
if (Array.isArray(pattern)) { | |
return pattern.every(match); | |
} | |
return match(pattern); | |
}); | |
/* | |
* If the file path matches the config.files patterns, then check to see | |
* if there are any files to ignore. | |
*/ | |
if (filePathMatchesPattern && config.ignores) { | |
filePathMatchesPattern = !config.ignores.some(isFilePathIgnored); | |
} | |
return filePathMatchesPattern; | |
} | |
/** | |
* Ensures that a ConfigArray has been normalized. | |
* @param {ConfigArray} configArray The ConfigArray to check. | |
* @returns {void} | |
* @throws {Error} When the `ConfigArray` is not normalized. | |
*/ | |
function assertNormalized(configArray) { | |
// TODO: Throw more verbose error | |
if (!configArray.isNormalized()) { | |
throw new Error('ConfigArray must be normalized to perform this operation.'); | |
} | |
} | |
/** | |
* Ensures that config types are valid. | |
* @param {Array<string>} extraConfigTypes The config types to check. | |
* @returns {void} | |
* @throws {Error} When the config types array is invalid. | |
*/ | |
function assertExtraConfigTypes(extraConfigTypes) { | |
if (extraConfigTypes.length > 2) { | |
throw new TypeError('configTypes must be an array with at most two items.'); | |
} | |
for (const configType of extraConfigTypes) { | |
if (!CONFIG_TYPES.has(configType)) { | |
throw new TypeError(`Unexpected config type "${configType}" found. Expected one of: "object", "array", "function".`); | |
} | |
} | |
} | |
//------------------------------------------------------------------------------ | |
// Public Interface | |
//------------------------------------------------------------------------------ | |
const ConfigArraySymbol = { | |
isNormalized: Symbol('isNormalized'), | |
configCache: Symbol('configCache'), | |
schema: Symbol('schema'), | |
finalizeConfig: Symbol('finalizeConfig'), | |
preprocessConfig: Symbol('preprocessConfig') | |
}; | |
// used to store calculate data for faster lookup | |
const dataCache = new WeakMap(); | |
/** | |
* Represents an array of config objects and provides method for working with | |
* those config objects. | |
*/ | |
class ConfigArray extends Array { | |
/** | |
* Creates a new instance of ConfigArray. | |
* @param {Iterable|Function|Object} configs An iterable yielding config | |
* objects, or a config function, or a config object. | |
* @param {string} [options.basePath=""] The path of the config file | |
* @param {boolean} [options.normalized=false] Flag indicating if the | |
* configs have already been normalized. | |
* @param {Object} [options.schema] The additional schema | |
* definitions to use for the ConfigArray schema. | |
* @param {Array<string>} [options.configTypes] List of config types supported. | |
*/ | |
constructor(configs, | |
{ | |
basePath = '', | |
normalized = false, | |
schema: customSchema, | |
extraConfigTypes = [] | |
} = {} | |
) { | |
super(); | |
/** | |
* Tracks if the array has been normalized. | |
* @property isNormalized | |
* @type boolean | |
* @private | |
*/ | |
this[ConfigArraySymbol.isNormalized] = normalized; | |
/** | |
* The schema used for validating and merging configs. | |
* @property schema | |
* @type ObjectSchema | |
* @private | |
*/ | |
this[ConfigArraySymbol.schema] = new objectSchema.ObjectSchema({ | |
...customSchema, | |
...baseSchema | |
}); | |
/** | |
* The path of the config file that this array was loaded from. | |
* This is used to calculate filename matches. | |
* @property basePath | |
* @type string | |
*/ | |
this.basePath = basePath; | |
assertExtraConfigTypes(extraConfigTypes); | |
/** | |
* The supported config types. | |
* @property configTypes | |
* @type Array<string> | |
*/ | |
this.extraConfigTypes = Object.freeze([...extraConfigTypes]); | |
/** | |
* A cache to store calculated configs for faster repeat lookup. | |
* @property configCache | |
* @type Map | |
* @private | |
*/ | |
this[ConfigArraySymbol.configCache] = new Map(); | |
// init cache | |
dataCache.set(this, {}); | |
// load the configs into this array | |
if (Array.isArray(configs)) { | |
this.push(...configs); | |
} else { | |
this.push(configs); | |
} | |
} | |
/** | |
* Prevent normal array methods from creating a new `ConfigArray` instance. | |
* This is to ensure that methods such as `slice()` won't try to create a | |
* new instance of `ConfigArray` behind the scenes as doing so may throw | |
* an error due to the different constructor signature. | |
* @returns {Function} The `Array` constructor. | |
*/ | |
static get [Symbol.species]() { | |
return Array; | |
} | |
/** | |
* Returns the `files` globs from every config object in the array. | |
* This can be used to determine which files will be matched by a | |
* config array or to use as a glob pattern when no patterns are provided | |
* for a command line interface. | |
* @returns {Array<string|Function>} An array of matchers. | |
*/ | |
get files() { | |
assertNormalized(this); | |
// if this data has been cached, retrieve it | |
const cache = dataCache.get(this); | |
if (cache.files) { | |
return cache.files; | |
} | |
// otherwise calculate it | |
const result = []; | |
for (const config of this) { | |
if (config.files) { | |
config.files.forEach(filePattern => { | |
result.push(filePattern); | |
}); | |
} | |
} | |
// store result | |
cache.files = result; | |
dataCache.set(this, cache); | |
return result; | |
} | |
/** | |
* Returns ignore matchers that should always be ignored regardless of | |
* the matching `files` fields in any configs. This is necessary to mimic | |
* the behavior of things like .gitignore and .eslintignore, allowing a | |
* globbing operation to be faster. | |
* @returns {string[]} An array of string patterns and functions to be ignored. | |
*/ | |
get ignores() { | |
assertNormalized(this); | |
// if this data has been cached, retrieve it | |
const cache = dataCache.get(this); | |
if (cache.ignores) { | |
return cache.ignores; | |
} | |
// otherwise calculate it | |
const result = []; | |
for (const config of this) { | |
if (config.ignores && !config.files) { | |
result.push(...config.ignores); | |
} | |
} | |
// store result | |
cache.ignores = result; | |
dataCache.set(this, cache); | |
return result; | |
} | |
/** | |
* Indicates if the config array has been normalized. | |
* @returns {boolean} True if the config array is normalized, false if not. | |
*/ | |
isNormalized() { | |
return this[ConfigArraySymbol.isNormalized]; | |
} | |
/** | |
* Normalizes a config array by flattening embedded arrays and executing | |
* config functions. | |
* @param {ConfigContext} context The context object for config functions. | |
* @returns {Promise<ConfigArray>} The current ConfigArray instance. | |
*/ | |
async normalize(context = {}) { | |
if (!this.isNormalized()) { | |
const normalizedConfigs = await normalize(this, context, this.extraConfigTypes); | |
this.length = 0; | |
this.push(...normalizedConfigs.map(this[ConfigArraySymbol.preprocessConfig])); | |
this[ConfigArraySymbol.isNormalized] = true; | |
// prevent further changes | |
Object.freeze(this); | |
} | |
return this; | |
} | |
/** | |
* Normalizes a config array by flattening embedded arrays and executing | |
* config functions. | |
* @param {ConfigContext} context The context object for config functions. | |
* @returns {ConfigArray} The current ConfigArray instance. | |
*/ | |
normalizeSync(context = {}) { | |
if (!this.isNormalized()) { | |
const normalizedConfigs = normalizeSync(this, context, this.extraConfigTypes); | |
this.length = 0; | |
this.push(...normalizedConfigs.map(this[ConfigArraySymbol.preprocessConfig])); | |
this[ConfigArraySymbol.isNormalized] = true; | |
// prevent further changes | |
Object.freeze(this); | |
} | |
return this; | |
} | |
/** | |
* Finalizes the state of a config before being cached and returned by | |
* `getConfig()`. Does nothing by default but is provided to be | |
* overridden by subclasses as necessary. | |
* @param {Object} config The config to finalize. | |
* @returns {Object} The finalized config. | |
*/ | |
[ConfigArraySymbol.finalizeConfig](config) { | |
return config; | |
} | |
/** | |
* Preprocesses a config during the normalization process. This is the | |
* method to override if you want to convert an array item before it is | |
* validated for the first time. For example, if you want to replace a | |
* string with an object, this is the method to override. | |
* @param {Object} config The config to preprocess. | |
* @returns {Object} The config to use in place of the argument. | |
*/ | |
[ConfigArraySymbol.preprocessConfig](config) { | |
return config; | |
} | |
/** | |
* Returns the config object for a given file path. | |
* @param {string} filePath The complete path of a file to get a config for. | |
* @returns {Object} The config object for this file. | |
*/ | |
getConfig(filePath) { | |
assertNormalized(this); | |
// first check the cache to avoid duplicate work | |
let finalConfig = this[ConfigArraySymbol.configCache].get(filePath); | |
if (finalConfig) { | |
return finalConfig; | |
} | |
// TODO: Maybe move elsewhere? | |
const relativeFilePath = path.relative(this.basePath, filePath); | |
// if there is a global matcher ignoring this file, just return null | |
for (const shouldIgnore of this.ignores) { | |
if (shouldIgnoreFilePath(shouldIgnore, filePath, relativeFilePath)) { | |
// cache and return result - finalConfig is undefined at this point | |
this[ConfigArraySymbol.configCache].set(filePath, finalConfig); | |
return finalConfig; | |
} | |
} | |
// filePath isn't automatically ignored, so try to construct config | |
const matchingConfigs = []; | |
for (const config of this) { | |
if (pathMatches(filePath, this.basePath, config)) { | |
debug(`Matching config found for ${filePath}`); | |
matchingConfigs.push(config); | |
} else { | |
debug(`No matching config found for ${filePath}`); | |
} | |
} | |
// if matching both files and ignores, there will be no config to create | |
if (matchingConfigs.length === 0) { | |
// cache and return result - finalConfig is undefined at this point | |
this[ConfigArraySymbol.configCache].set(filePath, finalConfig); | |
return finalConfig; | |
} | |
// otherwise construct the config | |
finalConfig = matchingConfigs.reduce((result, config) => { | |
return this[ConfigArraySymbol.schema].merge(result, config); | |
}, {}, this); | |
finalConfig = this[ConfigArraySymbol.finalizeConfig](finalConfig); | |
this[ConfigArraySymbol.configCache].set(filePath, finalConfig); | |
return finalConfig; | |
} | |
/** | |
* Determines if the given filepath is ignored based on the configs. | |
* @param {string} filePath The complete path of a file to check. | |
* @returns {boolean} True if the path is ignored, false if not. | |
*/ | |
isIgnored(filePath) { | |
return this.getConfig(filePath) === undefined; | |
} | |
} | |
exports.ConfigArray = ConfigArray; | |
exports.ConfigArraySymbol = ConfigArraySymbol; | |
/***/ }), | |
/***/ 9174: | |
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { | |
/** | |
* @filedescription Object Schema Package | |
*/ | |
exports.ObjectSchema = __webpack_require__(6507).ObjectSchema; | |
exports.MergeStrategy = __webpack_require__(5182).MergeStrategy; | |
exports.ValidationStrategy = __webpack_require__(4814).ValidationStrategy; | |
/***/ }), | |
/***/ 5182: | |
/***/ (function(__unused_webpack_module, exports) { | |
"use strict"; | |
/** | |
* @filedescription Merge Strategy | |
*/ | |
//----------------------------------------------------------------------------- | |
// Class | |
//----------------------------------------------------------------------------- | |
/** | |
* Container class for several different merge strategies. | |
*/ | |
class MergeStrategy { | |
/** | |
* Merges two keys by overwriting the first with the second. | |
* @param {*} value1 The value from the first object key. | |
* @param {*} value2 The value from the second object key. | |
* @returns {*} The second value. | |
*/ | |
static overwrite(value1, value2) { | |
return value2; | |
} | |
/** | |
* Merges two keys by replacing the first with the second only if the | |
* second is defined. | |
* @param {*} value1 The value from the first object key. | |
* @param {*} value2 The value from the second object key. | |
* @returns {*} The second value if it is defined. | |
*/ | |
static replace(value1, value2) { | |
if (typeof value2 !== "undefined") { | |
return value2; | |
} | |
return value1; | |
} | |
/** | |
* Merges two properties by assigning properties from the second to the first. | |
* @param {*} value1 The value from the first object key. | |
* @param {*} value2 The value from the second object key. | |
* @returns {*} A new object containing properties from both value1 and | |
* value2. | |
*/ | |
static assign(value1, value2) { | |
return Object.assign({}, value1, value2); | |
} | |
} | |
exports.MergeStrategy = MergeStrategy; | |
/***/ }), | |
/***/ 6507: | |
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @filedescription Object Schema | |
*/ | |
//----------------------------------------------------------------------------- | |
// Requirements | |
//----------------------------------------------------------------------------- | |
const { MergeStrategy } = __webpack_require__(5182); | |
const { ValidationStrategy } = __webpack_require__(4814); | |
//----------------------------------------------------------------------------- | |
// Private | |
//----------------------------------------------------------------------------- | |
const strategies = Symbol("strategies"); | |
const requiredKeys = Symbol("requiredKeys"); | |
/** | |
* Validates a schema strategy. | |
* @param {string} name The name of the key this strategy is for. | |
* @param {Object} strategy The strategy for the object key. | |
* @param {boolean} [strategy.required=true] Whether the key is required. | |
* @param {string[]} [strategy.requires] Other keys that are required when | |
* this key is present. | |
* @param {Function} strategy.merge A method to call when merging two objects | |
* with the same key. | |
* @param {Function} strategy.validate A method to call when validating an | |
* object with the key. | |
* @returns {void} | |
* @throws {Error} When the strategy is missing a name. | |
* @throws {Error} When the strategy is missing a merge() method. | |
* @throws {Error} When the strategy is missing a validate() method. | |
*/ | |
function validateDefinition(name, strategy) { | |
let hasSchema = false; | |
if (strategy.schema) { | |
if (typeof strategy.schema === "object") { | |
hasSchema = true; | |
} else { | |
throw new TypeError("Schema must be an object."); | |
} | |
} | |
if (typeof strategy.merge === "string") { | |
if (!(strategy.merge in MergeStrategy)) { | |
throw new TypeError(`Definition for key "${name}" missing valid merge strategy.`); | |
} | |
} else if (!hasSchema && typeof strategy.merge !== "function") { | |
throw new TypeError(`Definition for key "${name}" must have a merge property.`); | |
} | |
if (typeof strategy.validate === "string") { | |
if (!(strategy.validate in ValidationStrategy)) { | |
throw new TypeError(`Definition for key "${name}" missing valid validation strategy.`); | |
} | |
} else if (!hasSchema && typeof strategy.validate !== "function") { | |
throw new TypeError(`Definition for key "${name}" must have a validate() method.`); | |
} | |
} | |
//----------------------------------------------------------------------------- | |
// Class | |
//----------------------------------------------------------------------------- | |
/** | |
* Represents an object validation/merging schema. | |
*/ | |
class ObjectSchema { | |
/** | |
* Creates a new instance. | |
*/ | |
constructor(definitions) { | |
if (!definitions) { | |
throw new Error("Schema definitions missing."); | |
} | |
/** | |
* Track all strategies in the schema by key. | |
* @type {Map} | |
* @property strategies | |
*/ | |
this[strategies] = new Map(); | |
/** | |
* Separately track any keys that are required for faster validation. | |
* @type {Map} | |
* @property requiredKeys | |
*/ | |
this[requiredKeys] = new Map(); | |
// add in all strategies | |
for (const key of Object.keys(definitions)) { | |
validateDefinition(key, definitions[key]); | |
// normalize merge and validate methods if subschema is present | |
if (typeof definitions[key].schema === "object") { | |
const schema = new ObjectSchema(definitions[key].schema); | |
definitions[key] = { | |
...definitions[key], | |
merge(first = {}, second = {}) { | |
return schema.merge(first, second); | |
}, | |
validate(value) { | |
ValidationStrategy.object(value); | |
schema.validate(value); | |
} | |
}; | |
} | |
// normalize the merge method in case there's a string | |
if (typeof definitions[key].merge === "string") { | |
definitions[key] = { | |
...definitions[key], | |
merge: MergeStrategy[definitions[key].merge] | |
}; | |
}; | |
// normalize the validate method in case there's a string | |
if (typeof definitions[key].validate === "string") { | |
definitions[key] = { | |
...definitions[key], | |
validate: ValidationStrategy[definitions[key].validate] | |
}; | |
}; | |
this[strategies].set(key, definitions[key]); | |
if (definitions[key].required) { | |
this[requiredKeys].set(key, definitions[key]); | |
} | |
} | |
} | |
/** | |
* Determines if a strategy has been registered for the given object key. | |
* @param {string} key The object key to find a strategy for. | |
* @returns {boolean} True if the key has a strategy registered, false if not. | |
*/ | |
hasKey(key) { | |
return this[strategies].has(key); | |
} | |
/** | |
* Merges objects together to create a new object comprised of the keys | |
* of the all objects. Keys are merged based on the each key's merge | |
* strategy. | |
* @param {...Object} objects The objects to merge. | |
* @returns {Object} A new object with a mix of all objects' keys. | |
* @throws {Error} If any object is invalid. | |
*/ | |
merge(...objects) { | |
// double check arguments | |
if (objects.length < 2) { | |
throw new Error("merge() requires at least two arguments."); | |
} | |
if (objects.some(object => (object == null || typeof object !== "object"))) { | |
throw new Error("All arguments must be objects."); | |
} | |
return objects.reduce((result, object) => { | |
this.validate(object); | |
for (const [key, strategy] of this[strategies]) { | |
try { | |
if (key in result || key in object) { | |
const value = strategy.merge.call(this, result[key], object[key]); | |
if (value !== undefined) { | |
result[key] = value; | |
} | |
} | |
} catch (ex) { | |
ex.message = `Key "${key}": ` + ex.message; | |
throw ex; | |
} | |
} | |
return result; | |
}, {}); | |
} | |
/** | |
* Validates an object's keys based on the validate strategy for each key. | |
* @param {Object} object The object to validate. | |
* @returns {void} | |
* @throws {Error} When the object is invalid. | |
*/ | |
validate(object) { | |
// check existing keys first | |
for (const key of Object.keys(object)) { | |
// check to see if the key is defined | |
if (!this.hasKey(key)) { | |
throw new Error(`Unexpected key "${key}" found.`); | |
} | |
// validate existing keys | |
const strategy = this[strategies].get(key); | |
// first check to see if any other keys are required | |
if (Array.isArray(strategy.requires)) { | |
if (!strategy.requires.every(otherKey => otherKey in object)) { | |
throw new Error(`Key "${key}" requires keys "${strategy.requires.join("\", \"")}".`); | |
} | |
} | |
// now apply remaining validation strategy | |
try { | |
strategy.validate.call(strategy, object[key]); | |
} catch (ex) { | |
ex.message = `Key "${key}": ` + ex.message; | |
throw ex; | |
} | |
} | |
// ensure required keys aren't missing | |
for (const [key] of this[requiredKeys]) { | |
if (!(key in object)) { | |
throw new Error(`Missing required key "${key}".`); | |
} | |
} | |
} | |
} | |
exports.ObjectSchema = ObjectSchema; | |
/***/ }), | |
/***/ 4814: | |
/***/ (function(__unused_webpack_module, exports) { | |
"use strict"; | |
/** | |
* @filedescription Validation Strategy | |
*/ | |
//----------------------------------------------------------------------------- | |
// Class | |
//----------------------------------------------------------------------------- | |
/** | |
* Container class for several different validation strategies. | |
*/ | |
class ValidationStrategy { | |
/** | |
* Validates that a value is an array. | |
* @param {*} value The value to validate. | |
* @returns {void} | |
* @throws {TypeError} If the value is invalid. | |
*/ | |
static array(value) { | |
if (!Array.isArray(value)) { | |
throw new TypeError("Expected an array."); | |
} | |
} | |
/** | |
* Validates that a value is a boolean. | |
* @param {*} value The value to validate. | |
* @returns {void} | |
* @throws {TypeError} If the value is invalid. | |
*/ | |
static boolean(value) { | |
if (typeof value !== "boolean") { | |
throw new TypeError("Expected a Boolean."); | |
} | |
} | |
/** | |
* Validates that a value is a number. | |
* @param {*} value The value to validate. | |
* @returns {void} | |
* @throws {TypeError} If the value is invalid. | |
*/ | |
static number(value) { | |
if (typeof value !== "number") { | |
throw new TypeError("Expected a number."); | |
} | |
} | |
/** | |
* Validates that a value is a object. | |
* @param {*} value The value to validate. | |
* @returns {void} | |
* @throws {TypeError} If the value is invalid. | |
*/ | |
static object(value) { | |
if (!value || typeof value !== "object") { | |
throw new TypeError("Expected an object."); | |
} | |
} | |
/** | |
* Validates that a value is a object or null. | |
* @param {*} value The value to validate. | |
* @returns {void} | |
* @throws {TypeError} If the value is invalid. | |
*/ | |
static "object?"(value) { | |
if (typeof value !== "object") { | |
throw new TypeError("Expected an object or null."); | |
} | |
} | |
/** | |
* Validates that a value is a string. | |
* @param {*} value The value to validate. | |
* @returns {void} | |
* @throws {TypeError} If the value is invalid. | |
*/ | |
static string(value) { | |
if (typeof value !== "string") { | |
throw new TypeError("Expected a string."); | |
} | |
} | |
/** | |
* Validates that a value is a non-empty string. | |
* @param {*} value The value to validate. | |
* @returns {void} | |
* @throws {TypeError} If the value is invalid. | |
*/ | |
static "string!"(value) { | |
if (typeof value !== "string" || value.length === 0) { | |
throw new TypeError("Expected a non-empty string."); | |
} | |
} | |
} | |
exports.ValidationStrategy = ValidationStrategy; | |
/***/ }), | |
/***/ 5977: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
const XHTMLEntities = __webpack_require__(3325); | |
const hexNumber = /^[\da-fA-F]+$/; | |
const decimalNumber = /^\d+$/; | |
// The map to `acorn-jsx` tokens from `acorn` namespace objects. | |
const acornJsxMap = new WeakMap(); | |
// Get the original tokens for the given `acorn` namespace object. | |
function getJsxTokens(acorn) { | |
acorn = acorn.Parser.acorn || acorn; | |
let acornJsx = acornJsxMap.get(acorn); | |
if (!acornJsx) { | |
const tt = acorn.tokTypes; | |
const TokContext = acorn.TokContext; | |
const TokenType = acorn.TokenType; | |
const tc_oTag = new TokContext('<tag', false); | |
const tc_cTag = new TokContext('</tag', false); | |
const tc_expr = new TokContext('<tag>...</tag>', true, true); | |
const tokContexts = { | |
tc_oTag: tc_oTag, | |
tc_cTag: tc_cTag, | |
tc_expr: tc_expr | |
}; | |
const tokTypes = { | |
jsxName: new TokenType('jsxName'), | |
jsxText: new TokenType('jsxText', {beforeExpr: true}), | |
jsxTagStart: new TokenType('jsxTagStart', {startsExpr: true}), | |
jsxTagEnd: new TokenType('jsxTagEnd') | |
}; | |
tokTypes.jsxTagStart.updateContext = function() { | |
this.context.push(tc_expr); // treat as beginning of JSX expression | |
this.context.push(tc_oTag); // start opening tag context | |
this.exprAllowed = false; | |
}; | |
tokTypes.jsxTagEnd.updateContext = function(prevType) { | |
let out = this.context.pop(); | |
if (out === tc_oTag && prevType === tt.slash || out === tc_cTag) { | |
this.context.pop(); | |
this.exprAllowed = this.curContext() === tc_expr; | |
} else { | |
this.exprAllowed = true; | |
} | |
}; | |
acornJsx = { tokContexts: tokContexts, tokTypes: tokTypes }; | |
acornJsxMap.set(acorn, acornJsx); | |
} | |
return acornJsx; | |
} | |
// Transforms JSX element name to string. | |
function getQualifiedJSXName(object) { | |
if (!object) | |
return object; | |
if (object.type === 'JSXIdentifier') | |
return object.name; | |
if (object.type === 'JSXNamespacedName') | |
return object.namespace.name + ':' + object.name.name; | |
if (object.type === 'JSXMemberExpression') | |
return getQualifiedJSXName(object.object) + '.' + | |
getQualifiedJSXName(object.property); | |
} | |
module.exports = function(options) { | |
options = options || {}; | |
return function(Parser) { | |
return plugin({ | |
allowNamespaces: options.allowNamespaces !== false, | |
allowNamespacedObjects: !!options.allowNamespacedObjects | |
}, Parser); | |
}; | |
}; | |
// This is `tokTypes` of the peer dep. | |
// This can be different instances from the actual `tokTypes` this plugin uses. | |
Object.defineProperty(module.exports, "tokTypes", ({ | |
get: function get_tokTypes() { | |
return getJsxTokens(__webpack_require__(1234)).tokTypes; | |
}, | |
configurable: true, | |
enumerable: true | |
})); | |
function plugin(options, Parser) { | |
const acorn = Parser.acorn || __webpack_require__(1234); | |
const acornJsx = getJsxTokens(acorn); | |
const tt = acorn.tokTypes; | |
const tok = acornJsx.tokTypes; | |
const tokContexts = acorn.tokContexts; | |
const tc_oTag = acornJsx.tokContexts.tc_oTag; | |
const tc_cTag = acornJsx.tokContexts.tc_cTag; | |
const tc_expr = acornJsx.tokContexts.tc_expr; | |
const isNewLine = acorn.isNewLine; | |
const isIdentifierStart = acorn.isIdentifierStart; | |
const isIdentifierChar = acorn.isIdentifierChar; | |
return class extends Parser { | |
// Expose actual `tokTypes` and `tokContexts` to other plugins. | |
static get acornJsx() { | |
return acornJsx; | |
} | |
// Reads inline JSX contents token. | |
jsx_readToken() { | |
let out = '', chunkStart = this.pos; | |
for (;;) { | |
if (this.pos >= this.input.length) | |
this.raise(this.start, 'Unterminated JSX contents'); | |
let ch = this.input.charCodeAt(this.pos); | |
switch (ch) { | |
case 60: // '<' | |
case 123: // '{' | |
if (this.pos === this.start) { | |
if (ch === 60 && this.exprAllowed) { | |
++this.pos; | |
return this.finishToken(tok.jsxTagStart); | |
} | |
return this.getTokenFromCode(ch); | |
} | |
out += this.input.slice(chunkStart, this.pos); | |
return this.finishToken(tok.jsxText, out); | |
case 38: // '&' | |
out += this.input.slice(chunkStart, this.pos); | |
out += this.jsx_readEntity(); | |
chunkStart = this.pos; | |
break; | |
case 62: // '>' | |
case 125: // '}' | |
this.raise( | |
this.pos, | |
"Unexpected token `" + this.input[this.pos] + "`. Did you mean `" + | |
(ch === 62 ? ">" : "}") + "` or " + "`{\"" + this.input[this.pos] + "\"}" + "`?" | |
); | |
default: | |
if (isNewLine(ch)) { | |
out += this.input.slice(chunkStart, this.pos); | |
out += this.jsx_readNewLine(true); | |
chunkStart = this.pos; | |
} else { | |
++this.pos; | |
} | |
} | |
} | |
} | |
jsx_readNewLine(normalizeCRLF) { | |
let ch = this.input.charCodeAt(this.pos); | |
let out; | |
++this.pos; | |
if (ch === 13 && this.input.charCodeAt(this.pos) === 10) { | |
++this.pos; | |
out = normalizeCRLF ? '\n' : '\r\n'; | |
} else { | |
out = String.fromCharCode(ch); | |
} | |
if (this.options.locations) { | |
++this.curLine; | |
this.lineStart = this.pos; | |
} | |
return out; | |
} | |
jsx_readString(quote) { | |
let out = '', chunkStart = ++this.pos; | |
for (;;) { | |
if (this.pos >= this.input.length) | |
this.raise(this.start, 'Unterminated string constant'); | |
let ch = this.input.charCodeAt(this.pos); | |
if (ch === quote) break; | |
if (ch === 38) { // '&' | |
out += this.input.slice(chunkStart, this.pos); | |
out += this.jsx_readEntity(); | |
chunkStart = this.pos; | |
} else if (isNewLine(ch)) { | |
out += this.input.slice(chunkStart, this.pos); | |
out += this.jsx_readNewLine(false); | |
chunkStart = this.pos; | |
} else { | |
++this.pos; | |
} | |
} | |
out += this.input.slice(chunkStart, this.pos++); | |
return this.finishToken(tt.string, out); | |
} | |
jsx_readEntity() { | |
let str = '', count = 0, entity; | |
let ch = this.input[this.pos]; | |
if (ch !== '&') | |
this.raise(this.pos, 'Entity must start with an ampersand'); | |
let startPos = ++this.pos; | |
while (this.pos < this.input.length && count++ < 10) { | |
ch = this.input[this.pos++]; | |
if (ch === ';') { | |
if (str[0] === '#') { | |
if (str[1] === 'x') { | |
str = str.substr(2); | |
if (hexNumber.test(str)) | |
entity = String.fromCharCode(parseInt(str, 16)); | |
} else { | |
str = str.substr(1); | |
if (decimalNumber.test(str)) | |
entity = String.fromCharCode(parseInt(str, 10)); | |
} | |
} else { | |
entity = XHTMLEntities[str]; | |
} | |
break; | |
} | |
str += ch; | |
} | |
if (!entity) { | |
this.pos = startPos; | |
return '&'; | |
} | |
return entity; | |
} | |
// Read a JSX identifier (valid tag or attribute name). | |
// | |
// Optimized version since JSX identifiers can't contain | |
// escape characters and so can be read as single slice. | |
// Also assumes that first character was already checked | |
// by isIdentifierStart in readToken. | |
jsx_readWord() { | |
let ch, start = this.pos; | |
do { | |
ch = this.input.charCodeAt(++this.pos); | |
} while (isIdentifierChar(ch) || ch === 45); // '-' | |
return this.finishToken(tok.jsxName, this.input.slice(start, this.pos)); | |
} | |
// Parse next token as JSX identifier | |
jsx_parseIdentifier() { | |
let node = this.startNode(); | |
if (this.type === tok.jsxName) | |
node.name = this.value; | |
else if (this.type.keyword) | |
node.name = this.type.keyword; | |
else | |
this.unexpected(); | |
this.next(); | |
return this.finishNode(node, 'JSXIdentifier'); | |
} | |
// Parse namespaced identifier. | |
jsx_parseNamespacedName() { | |
let startPos = this.start, startLoc = this.startLoc; | |
let name = this.jsx_parseIdentifier(); | |
if (!options.allowNamespaces || !this.eat(tt.colon)) return name; | |
var node = this.startNodeAt(startPos, startLoc); | |
node.namespace = name; | |
node.name = this.jsx_parseIdentifier(); | |
return this.finishNode(node, 'JSXNamespacedName'); | |
} | |
// Parses element name in any form - namespaced, member | |
// or single identifier. | |
jsx_parseElementName() { | |
if (this.type === tok.jsxTagEnd) return ''; | |
let startPos = this.start, startLoc = this.startLoc; | |
let node = this.jsx_parseNamespacedName(); | |
if (this.type === tt.dot && node.type === 'JSXNamespacedName' && !options.allowNamespacedObjects) { | |
this.unexpected(); | |
} | |
while (this.eat(tt.dot)) { | |
let newNode = this.startNodeAt(startPos, startLoc); | |
newNode.object = node; | |
newNode.property = this.jsx_parseIdentifier(); | |
node = this.finishNode(newNode, 'JSXMemberExpression'); | |
} | |
return node; | |
} | |
// Parses any type of JSX attribute value. | |
jsx_parseAttributeValue() { | |
switch (this.type) { | |
case tt.braceL: | |
let node = this.jsx_parseExpressionContainer(); | |
if (node.expression.type === 'JSXEmptyExpression') | |
this.raise(node.start, 'JSX attributes must only be assigned a non-empty expression'); | |
return node; | |
case tok.jsxTagStart: | |
case tt.string: | |
return this.parseExprAtom(); | |
default: | |
this.raise(this.start, 'JSX value should be either an expression or a quoted JSX text'); | |
} | |
} | |
// JSXEmptyExpression is unique type since it doesn't actually parse anything, | |
// and so it should start at the end of last read token (left brace) and finish | |
// at the beginning of the next one (right brace). | |
jsx_parseEmptyExpression() { | |
let node = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc); | |
return this.finishNodeAt(node, 'JSXEmptyExpression', this.start, this.startLoc); | |
} | |
// Parses JSX expression enclosed into curly brackets. | |
jsx_parseExpressionContainer() { | |
let node = this.startNode(); | |
this.next(); | |
node.expression = this.type === tt.braceR | |
? this.jsx_parseEmptyExpression() | |
: this.parseExpression(); | |
this.expect(tt.braceR); | |
return this.finishNode(node, 'JSXExpressionContainer'); | |
} | |
// Parses following JSX attribute name-value pair. | |
jsx_parseAttribute() { | |
let node = this.startNode(); | |
if (this.eat(tt.braceL)) { | |
this.expect(tt.ellipsis); | |
node.argument = this.parseMaybeAssign(); | |
this.expect(tt.braceR); | |
return this.finishNode(node, 'JSXSpreadAttribute'); | |
} | |
node.name = this.jsx_parseNamespacedName(); | |
node.value = this.eat(tt.eq) ? this.jsx_parseAttributeValue() : null; | |
return this.finishNode(node, 'JSXAttribute'); | |
} | |
// Parses JSX opening tag starting after '<'. | |
jsx_parseOpeningElementAt(startPos, startLoc) { | |
let node = this.startNodeAt(startPos, startLoc); | |
node.attributes = []; | |
let nodeName = this.jsx_parseElementName(); | |
if (nodeName) node.name = nodeName; | |
while (this.type !== tt.slash && this.type !== tok.jsxTagEnd) | |
node.attributes.push(this.jsx_parseAttribute()); | |
node.selfClosing = this.eat(tt.slash); | |
this.expect(tok.jsxTagEnd); | |
return this.finishNode(node, nodeName ? 'JSXOpeningElement' : 'JSXOpeningFragment'); | |
} | |
// Parses JSX closing tag starting after '</'. | |
jsx_parseClosingElementAt(startPos, startLoc) { | |
let node = this.startNodeAt(startPos, startLoc); | |
let nodeName = this.jsx_parseElementName(); | |
if (nodeName) node.name = nodeName; | |
this.expect(tok.jsxTagEnd); | |
return this.finishNode(node, nodeName ? 'JSXClosingElement' : 'JSXClosingFragment'); | |
} | |
// Parses entire JSX element, including it's opening tag | |
// (starting after '<'), attributes, contents and closing tag. | |
jsx_parseElementAt(startPos, startLoc) { | |
let node = this.startNodeAt(startPos, startLoc); | |
let children = []; | |
let openingElement = this.jsx_parseOpeningElementAt(startPos, startLoc); | |
let closingElement = null; | |
if (!openingElement.selfClosing) { | |
contents: for (;;) { | |
switch (this.type) { | |
case tok.jsxTagStart: | |
startPos = this.start; startLoc = this.startLoc; | |
this.next(); | |
if (this.eat(tt.slash)) { | |
closingElement = this.jsx_parseClosingElementAt(startPos, startLoc); | |
break contents; | |
} | |
children.push(this.jsx_parseElementAt(startPos, startLoc)); | |
break; | |
case tok.jsxText: | |
children.push(this.parseExprAtom()); | |
break; | |
case tt.braceL: | |
children.push(this.jsx_parseExpressionContainer()); | |
break; | |
default: | |
this.unexpected(); | |
} | |
} | |
if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) { | |
this.raise( | |
closingElement.start, | |
'Expected corresponding JSX closing tag for <' + getQualifiedJSXName(openingElement.name) + '>'); | |
} | |
} | |
let fragmentOrElement = openingElement.name ? 'Element' : 'Fragment'; | |
node['opening' + fragmentOrElement] = openingElement; | |
node['closing' + fragmentOrElement] = closingElement; | |
node.children = children; | |
if (this.type === tt.relational && this.value === "<") { | |
this.raise(this.start, "Adjacent JSX elements must be wrapped in an enclosing tag"); | |
} | |
return this.finishNode(node, 'JSX' + fragmentOrElement); | |
} | |
// Parse JSX text | |
jsx_parseText() { | |
let node = this.parseLiteral(this.value); | |
node.type = "JSXText"; | |
return node; | |
} | |
// Parses entire JSX element from current position. | |
jsx_parseElement() { | |
let startPos = this.start, startLoc = this.startLoc; | |
this.next(); | |
return this.jsx_parseElementAt(startPos, startLoc); | |
} | |
parseExprAtom(refShortHandDefaultPos) { | |
if (this.type === tok.jsxText) | |
return this.jsx_parseText(); | |
else if (this.type === tok.jsxTagStart) | |
return this.jsx_parseElement(); | |
else | |
return super.parseExprAtom(refShortHandDefaultPos); | |
} | |
readToken(code) { | |
let context = this.curContext(); | |
if (context === tc_expr) return this.jsx_readToken(); | |
if (context === tc_oTag || context === tc_cTag) { | |
if (isIdentifierStart(code)) return this.jsx_readWord(); | |
if (code == 62) { | |
++this.pos; | |
return this.finishToken(tok.jsxTagEnd); | |
} | |
if ((code === 34 || code === 39) && context == tc_oTag) | |
return this.jsx_readString(code); | |
} | |
if (code === 60 && this.exprAllowed && this.input.charCodeAt(this.pos + 1) !== 33) { | |
++this.pos; | |
return this.finishToken(tok.jsxTagStart); | |
} | |
return super.readToken(code); | |
} | |
updateContext(prevType) { | |
if (this.type == tt.braceL) { | |
var curContext = this.curContext(); | |
if (curContext == tc_oTag) this.context.push(tokContexts.b_expr); | |
else if (curContext == tc_expr) this.context.push(tokContexts.b_tmpl); | |
else super.updateContext(prevType); | |
this.exprAllowed = true; | |
} else if (this.type === tt.slash && prevType === tok.jsxTagStart) { | |
this.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore | |
this.context.push(tc_cTag); // reconsider as closing tag context | |
this.exprAllowed = false; | |
} else { | |
return super.updateContext(prevType); | |
} | |
} | |
}; | |
} | |
/***/ }), | |
/***/ 3325: | |
/***/ (function(module) { | |
module.exports = { | |
quot: '\u0022', | |
amp: '&', | |
apos: '\u0027', | |
lt: '<', | |
gt: '>', | |
nbsp: '\u00A0', | |
iexcl: '\u00A1', | |
cent: '\u00A2', | |
pound: '\u00A3', | |
curren: '\u00A4', | |
yen: '\u00A5', | |
brvbar: '\u00A6', | |
sect: '\u00A7', | |
uml: '\u00A8', | |
copy: '\u00A9', | |
ordf: '\u00AA', | |
laquo: '\u00AB', | |
not: '\u00AC', | |
shy: '\u00AD', | |
reg: '\u00AE', | |
macr: '\u00AF', | |
deg: '\u00B0', | |
plusmn: '\u00B1', | |
sup2: '\u00B2', | |
sup3: '\u00B3', | |
acute: '\u00B4', | |
micro: '\u00B5', | |
para: '\u00B6', | |
middot: '\u00B7', | |
cedil: '\u00B8', | |
sup1: '\u00B9', | |
ordm: '\u00BA', | |
raquo: '\u00BB', | |
frac14: '\u00BC', | |
frac12: '\u00BD', | |
frac34: '\u00BE', | |
iquest: '\u00BF', | |
Agrave: '\u00C0', | |
Aacute: '\u00C1', | |
Acirc: '\u00C2', | |
Atilde: '\u00C3', | |
Auml: '\u00C4', | |
Aring: '\u00C5', | |
AElig: '\u00C6', | |
Ccedil: '\u00C7', | |
Egrave: '\u00C8', | |
Eacute: '\u00C9', | |
Ecirc: '\u00CA', | |
Euml: '\u00CB', | |
Igrave: '\u00CC', | |
Iacute: '\u00CD', | |
Icirc: '\u00CE', | |
Iuml: '\u00CF', | |
ETH: '\u00D0', | |
Ntilde: '\u00D1', | |
Ograve: '\u00D2', | |
Oacute: '\u00D3', | |
Ocirc: '\u00D4', | |
Otilde: '\u00D5', | |
Ouml: '\u00D6', | |
times: '\u00D7', | |
Oslash: '\u00D8', | |
Ugrave: '\u00D9', | |
Uacute: '\u00DA', | |
Ucirc: '\u00DB', | |
Uuml: '\u00DC', | |
Yacute: '\u00DD', | |
THORN: '\u00DE', | |
szlig: '\u00DF', | |
agrave: '\u00E0', | |
aacute: '\u00E1', | |
acirc: '\u00E2', | |
atilde: '\u00E3', | |
auml: '\u00E4', | |
aring: '\u00E5', | |
aelig: '\u00E6', | |
ccedil: '\u00E7', | |
egrave: '\u00E8', | |
eacute: '\u00E9', | |
ecirc: '\u00EA', | |
euml: '\u00EB', | |
igrave: '\u00EC', | |
iacute: '\u00ED', | |
icirc: '\u00EE', | |
iuml: '\u00EF', | |
eth: '\u00F0', | |
ntilde: '\u00F1', | |
ograve: '\u00F2', | |
oacute: '\u00F3', | |
ocirc: '\u00F4', | |
otilde: '\u00F5', | |
ouml: '\u00F6', | |
divide: '\u00F7', | |
oslash: '\u00F8', | |
ugrave: '\u00F9', | |
uacute: '\u00FA', | |
ucirc: '\u00FB', | |
uuml: '\u00FC', | |
yacute: '\u00FD', | |
thorn: '\u00FE', | |
yuml: '\u00FF', | |
OElig: '\u0152', | |
oelig: '\u0153', | |
Scaron: '\u0160', | |
scaron: '\u0161', | |
Yuml: '\u0178', | |
fnof: '\u0192', | |
circ: '\u02C6', | |
tilde: '\u02DC', | |
Alpha: '\u0391', | |
Beta: '\u0392', | |
Gamma: '\u0393', | |
Delta: '\u0394', | |
Epsilon: '\u0395', | |
Zeta: '\u0396', | |
Eta: '\u0397', | |
Theta: '\u0398', | |
Iota: '\u0399', | |
Kappa: '\u039A', | |
Lambda: '\u039B', | |
Mu: '\u039C', | |
Nu: '\u039D', | |
Xi: '\u039E', | |
Omicron: '\u039F', | |
Pi: '\u03A0', | |
Rho: '\u03A1', | |
Sigma: '\u03A3', | |
Tau: '\u03A4', | |
Upsilon: '\u03A5', | |
Phi: '\u03A6', | |
Chi: '\u03A7', | |
Psi: '\u03A8', | |
Omega: '\u03A9', | |
alpha: '\u03B1', | |
beta: '\u03B2', | |
gamma: '\u03B3', | |
delta: '\u03B4', | |
epsilon: '\u03B5', | |
zeta: '\u03B6', | |
eta: '\u03B7', | |
theta: '\u03B8', | |
iota: '\u03B9', | |
kappa: '\u03BA', | |
lambda: '\u03BB', | |
mu: '\u03BC', | |
nu: '\u03BD', | |
xi: '\u03BE', | |
omicron: '\u03BF', | |
pi: '\u03C0', | |
rho: '\u03C1', | |
sigmaf: '\u03C2', | |
sigma: '\u03C3', | |
tau: '\u03C4', | |
upsilon: '\u03C5', | |
phi: '\u03C6', | |
chi: '\u03C7', | |
psi: '\u03C8', | |
omega: '\u03C9', | |
thetasym: '\u03D1', | |
upsih: '\u03D2', | |
piv: '\u03D6', | |
ensp: '\u2002', | |
emsp: '\u2003', | |
thinsp: '\u2009', | |
zwnj: '\u200C', | |
zwj: '\u200D', | |
lrm: '\u200E', | |
rlm: '\u200F', | |
ndash: '\u2013', | |
mdash: '\u2014', | |
lsquo: '\u2018', | |
rsquo: '\u2019', | |
sbquo: '\u201A', | |
ldquo: '\u201C', | |
rdquo: '\u201D', | |
bdquo: '\u201E', | |
dagger: '\u2020', | |
Dagger: '\u2021', | |
bull: '\u2022', | |
hellip: '\u2026', | |
permil: '\u2030', | |
prime: '\u2032', | |
Prime: '\u2033', | |
lsaquo: '\u2039', | |
rsaquo: '\u203A', | |
oline: '\u203E', | |
frasl: '\u2044', | |
euro: '\u20AC', | |
image: '\u2111', | |
weierp: '\u2118', | |
real: '\u211C', | |
trade: '\u2122', | |
alefsym: '\u2135', | |
larr: '\u2190', | |
uarr: '\u2191', | |
rarr: '\u2192', | |
darr: '\u2193', | |
harr: '\u2194', | |
crarr: '\u21B5', | |
lArr: '\u21D0', | |
uArr: '\u21D1', | |
rArr: '\u21D2', | |
dArr: '\u21D3', | |
hArr: '\u21D4', | |
forall: '\u2200', | |
part: '\u2202', | |
exist: '\u2203', | |
empty: '\u2205', | |
nabla: '\u2207', | |
isin: '\u2208', | |
notin: '\u2209', | |
ni: '\u220B', | |
prod: '\u220F', | |
sum: '\u2211', | |
minus: '\u2212', | |
lowast: '\u2217', | |
radic: '\u221A', | |
prop: '\u221D', | |
infin: '\u221E', | |
ang: '\u2220', | |
and: '\u2227', | |
or: '\u2228', | |
cap: '\u2229', | |
cup: '\u222A', | |
'int': '\u222B', | |
there4: '\u2234', | |
sim: '\u223C', | |
cong: '\u2245', | |
asymp: '\u2248', | |
ne: '\u2260', | |
equiv: '\u2261', | |
le: '\u2264', | |
ge: '\u2265', | |
sub: '\u2282', | |
sup: '\u2283', | |
nsub: '\u2284', | |
sube: '\u2286', | |
supe: '\u2287', | |
oplus: '\u2295', | |
otimes: '\u2297', | |
perp: '\u22A5', | |
sdot: '\u22C5', | |
lceil: '\u2308', | |
rceil: '\u2309', | |
lfloor: '\u230A', | |
rfloor: '\u230B', | |
lang: '\u2329', | |
rang: '\u232A', | |
loz: '\u25CA', | |
spades: '\u2660', | |
clubs: '\u2663', | |
hearts: '\u2665', | |
diams: '\u2666' | |
}; | |
/***/ }), | |
/***/ 1234: | |
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { | |
/* provided dependency */ var console = __webpack_require__(5108); | |
(function (global, factory) { | |
true ? factory(exports) : | |
0; | |
})(this, (function (exports) { 'use strict'; | |
// Reserved word lists for various dialects of the language | |
var reservedWords = { | |
3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", | |
5: "class enum extends super const export import", | |
6: "enum", | |
strict: "implements interface let package private protected public static yield", | |
strictBind: "eval arguments" | |
}; | |
// And the keywords | |
var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; | |
var keywords$1 = { | |
5: ecma5AndLessKeywords, | |
"5module": ecma5AndLessKeywords + " export import", | |
6: ecma5AndLessKeywords + " const class extends export import super" | |
}; | |
var keywordRelationalOperator = /^in(stanceof)?$/; | |
// ## Character categories | |
// Big ugly regular expressions that match characters in the | |
// whitespace, identifier, and identifier-start categories. These | |
// are only applied when a character is found to actually have a | |
// code point above 128. | |
// Generated by `bin/generate-identifier-regex.js`. | |
var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08c7\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\u9ffc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7ca\ua7f5-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; | |
var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf\u1ac0\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; | |
var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); | |
var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); | |
nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; | |
// These are a run-length and offset encoded representation of the | |
// >0xffff code points that are a valid part of identifiers. The | |
// offset starts at 0x10000, and each pair of numbers represents an | |
// offset to the next range, and then a size of the range. They were | |
// generated by bin/generate-identifier-regex.js | |
// eslint-disable-next-line comma-spacing | |
var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,349,41,7,1,79,28,11,0,9,21,107,20,28,22,13,52,76,44,33,24,27,35,30,0,3,0,9,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,21,2,31,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,14,0,72,26,230,43,117,63,32,7,3,0,3,7,2,1,2,23,16,0,2,0,95,7,3,38,17,0,2,0,29,0,11,39,8,0,22,0,12,45,20,0,35,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,190,0,80,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,689,63,129,74,6,0,67,12,65,1,2,0,29,6135,9,1237,43,8,8952,286,50,2,18,3,9,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,2357,44,11,6,17,0,370,43,1301,196,60,67,8,0,1205,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42717,35,4148,12,221,3,5761,15,7472,3104,541,1507,4938]; | |
// eslint-disable-next-line comma-spacing | |
var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,370,1,154,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,2,11,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9,71,5,2,1,3,3,2,0,2,1,13,9,120,6,3,6,4,0,29,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,19306,9,135,4,60,6,26,9,1014,0,2,54,8,3,82,0,12,1,19628,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,262,6,10,9,419,13,1495,6,110,6,6,9,4759,9,787719,239]; | |
// This has a complexity linear to the value of the code. The | |
// assumption is that looking up astral identifier characters is | |
// rare. | |
function isInAstralSet(code, set) { | |
var pos = 0x10000; | |
for (var i = 0; i < set.length; i += 2) { | |
pos += set[i]; | |
if (pos > code) { return false } | |
pos += set[i + 1]; | |
if (pos >= code) { return true } | |
} | |
} | |
// Test whether a given character code starts an identifier. | |
function isIdentifierStart(code, astral) { | |
if (code < 65) { return code === 36 } | |
if (code < 91) { return true } | |
if (code < 97) { return code === 95 } | |
if (code < 123) { return true } | |
if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } | |
if (astral === false) { return false } | |
return isInAstralSet(code, astralIdentifierStartCodes) | |
} | |
// Test whether a given character is part of an identifier. | |
function isIdentifierChar(code, astral) { | |
if (code < 48) { return code === 36 } | |
if (code < 58) { return true } | |
if (code < 65) { return false } | |
if (code < 91) { return true } | |
if (code < 97) { return code === 95 } | |
if (code < 123) { return true } | |
if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } | |
if (astral === false) { return false } | |
return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) | |
} | |
// ## Token types | |
// The assignment of fine-grained, information-carrying type objects | |
// allows the tokenizer to store the information it has about a | |
// token in a way that is very cheap for the parser to look up. | |
// All token type variables start with an underscore, to make them | |
// easy to recognize. | |
// The `beforeExpr` property is used to disambiguate between regular | |
// expressions and divisions. It is set on all token types that can | |
// be followed by an expression (thus, a slash after them would be a | |
// regular expression). | |
// | |
// The `startsExpr` property is used to check if the token ends a | |
// `yield` expression. It is set on all token types that either can | |
// directly start an expression (like a quotation mark) or can | |
// continue an expression (like the body of a string). | |
// | |
// `isLoop` marks a keyword as starting a loop, which is important | |
// to know when parsing a label, in order to allow or disallow | |
// continue jumps to that label. | |
var TokenType = function TokenType(label, conf) { | |
if ( conf === void 0 ) conf = {}; | |
this.label = label; | |
this.keyword = conf.keyword; | |
this.beforeExpr = !!conf.beforeExpr; | |
this.startsExpr = !!conf.startsExpr; | |
this.isLoop = !!conf.isLoop; | |
this.isAssign = !!conf.isAssign; | |
this.prefix = !!conf.prefix; | |
this.postfix = !!conf.postfix; | |
this.binop = conf.binop || null; | |
this.updateContext = null; | |
}; | |
function binop(name, prec) { | |
return new TokenType(name, {beforeExpr: true, binop: prec}) | |
} | |
var beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true}; | |
// Map keyword names to token types. | |
var keywords = {}; | |
// Succinct definitions of keyword token types | |
function kw(name, options) { | |
if ( options === void 0 ) options = {}; | |
options.keyword = name; | |
return keywords[name] = new TokenType(name, options) | |
} | |
var types$1 = { | |
num: new TokenType("num", startsExpr), | |
regexp: new TokenType("regexp", startsExpr), | |
string: new TokenType("string", startsExpr), | |
name: new TokenType("name", startsExpr), | |
privateId: new TokenType("privateId", startsExpr), | |
eof: new TokenType("eof"), | |
// Punctuation token types. | |
bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), | |
bracketR: new TokenType("]"), | |
braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), | |
braceR: new TokenType("}"), | |
parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), | |
parenR: new TokenType(")"), | |
comma: new TokenType(",", beforeExpr), | |
semi: new TokenType(";", beforeExpr), | |
colon: new TokenType(":", beforeExpr), | |
dot: new TokenType("."), | |
question: new TokenType("?", beforeExpr), | |
questionDot: new TokenType("?."), | |
arrow: new TokenType("=>", beforeExpr), | |
template: new TokenType("template"), | |
invalidTemplate: new TokenType("invalidTemplate"), | |
ellipsis: new TokenType("...", beforeExpr), | |
backQuote: new TokenType("`", startsExpr), | |
dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), | |
// Operators. These carry several kinds of properties to help the | |
// parser use them properly (the presence of these properties is | |
// what categorizes them as operators). | |
// | |
// `binop`, when present, specifies that this operator is a binary | |
// operator, and will refer to its precedence. | |
// | |
// `prefix` and `postfix` mark the operator as a prefix or postfix | |
// unary operator. | |
// | |
// `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as | |
// binary operators with a very low precedence, that should result | |
// in AssignmentExpression nodes. | |
eq: new TokenType("=", {beforeExpr: true, isAssign: true}), | |
assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), | |
incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), | |
prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}), | |
logicalOR: binop("||", 1), | |
logicalAND: binop("&&", 2), | |
bitwiseOR: binop("|", 3), | |
bitwiseXOR: binop("^", 4), | |
bitwiseAND: binop("&", 5), | |
equality: binop("==/!=/===/!==", 6), | |
relational: binop("</>/<=/>=", 7), | |
bitShift: binop("<</>>/>>>", 8), | |
plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), | |
modulo: binop("%", 10), | |
star: binop("*", 10), | |
slash: binop("/", 10), | |
starstar: new TokenType("**", {beforeExpr: true}), | |
coalesce: binop("??", 1), | |
// Keyword token types. | |
_break: kw("break"), | |
_case: kw("case", beforeExpr), | |
_catch: kw("catch"), | |
_continue: kw("continue"), | |
_debugger: kw("debugger"), | |
_default: kw("default", beforeExpr), | |
_do: kw("do", {isLoop: true, beforeExpr: true}), | |
_else: kw("else", beforeExpr), | |
_finally: kw("finally"), | |
_for: kw("for", {isLoop: true}), | |
_function: kw("function", startsExpr), | |
_if: kw("if"), | |
_return: kw("return", beforeExpr), | |
_switch: kw("switch"), | |
_throw: kw("throw", beforeExpr), | |
_try: kw("try"), | |
_var: kw("var"), | |
_const: kw("const"), | |
_while: kw("while", {isLoop: true}), | |
_with: kw("with"), | |
_new: kw("new", {beforeExpr: true, startsExpr: true}), | |
_this: kw("this", startsExpr), | |
_super: kw("super", startsExpr), | |
_class: kw("class", startsExpr), | |
_extends: kw("extends", beforeExpr), | |
_export: kw("export"), | |
_import: kw("import", startsExpr), | |
_null: kw("null", startsExpr), | |
_true: kw("true", startsExpr), | |
_false: kw("false", startsExpr), | |
_in: kw("in", {beforeExpr: true, binop: 7}), | |
_instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), | |
_typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), | |
_void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), | |
_delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) | |
}; | |
// Matches a whole line break (where CRLF is considered a single | |
// line break). Used to count lines. | |
var lineBreak = /\r\n?|\n|\u2028|\u2029/; | |
var lineBreakG = new RegExp(lineBreak.source, "g"); | |
function isNewLine(code) { | |
return code === 10 || code === 13 || code === 0x2028 || code === 0x2029 | |
} | |
var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/; | |
var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; | |
var ref = Object.prototype; | |
var hasOwnProperty = ref.hasOwnProperty; | |
var toString = ref.toString; | |
// Checks if an object has a property. | |
function has(obj, propName) { | |
return hasOwnProperty.call(obj, propName) | |
} | |
var isArray = Array.isArray || (function (obj) { return ( | |
toString.call(obj) === "[object Array]" | |
); }); | |
function wordsRegexp(words) { | |
return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") | |
} | |
// These are used when `options.locations` is on, for the | |
// `startLoc` and `endLoc` properties. | |
var Position = function Position(line, col) { | |
this.line = line; | |
this.column = col; | |
}; | |
Position.prototype.offset = function offset (n) { | |
return new Position(this.line, this.column + n) | |
}; | |
var SourceLocation = function SourceLocation(p, start, end) { | |
this.start = start; | |
this.end = end; | |
if (p.sourceFile !== null) { this.source = p.sourceFile; } | |
}; | |
// The `getLineInfo` function is mostly useful when the | |
// `locations` option is off (for performance reasons) and you | |
// want to find the line/column position for a given character | |
// offset. `input` should be the code string that the offset refers | |
// into. | |
function getLineInfo(input, offset) { | |
for (var line = 1, cur = 0;;) { | |
lineBreakG.lastIndex = cur; | |
var match = lineBreakG.exec(input); | |
if (match && match.index < offset) { | |
++line; | |
cur = match.index + match[0].length; | |
} else { | |
return new Position(line, offset - cur) | |
} | |
} | |
} | |
// A second argument must be given to configure the parser process. | |
// These options are recognized (only `ecmaVersion` is required): | |
var defaultOptions = { | |
// `ecmaVersion` indicates the ECMAScript version to parse. Must be | |
// either 3, 5, 6 (or 2015), 7 (2016), 8 (2017), 9 (2018), 10 | |
// (2019), 11 (2020), 12 (2021), 13 (2022), or `"latest"` (the | |
// latest version the library supports). This influences support | |
// for strict mode, the set of reserved words, and support for | |
// new syntax features. | |
ecmaVersion: null, | |
// `sourceType` indicates the mode the code should be parsed in. | |
// Can be either `"script"` or `"module"`. This influences global | |
// strict mode and parsing of `import` and `export` declarations. | |
sourceType: "script", | |
// `onInsertedSemicolon` can be a callback that will be called | |
// when a semicolon is automatically inserted. It will be passed | |
// the position of the comma as an offset, and if `locations` is | |
// enabled, it is given the location as a `{line, column}` object | |
// as second argument. | |
onInsertedSemicolon: null, | |
// `onTrailingComma` is similar to `onInsertedSemicolon`, but for | |
// trailing commas. | |
onTrailingComma: null, | |
// By default, reserved words are only enforced if ecmaVersion >= 5. | |
// Set `allowReserved` to a boolean value to explicitly turn this on | |
// an off. When this option has the value "never", reserved words | |
// and keywords can also not be used as property names. | |
allowReserved: null, | |
// When enabled, a return at the top level is not considered an | |
// error. | |
allowReturnOutsideFunction: false, | |
// When enabled, import/export statements are not constrained to | |
// appearing at the top of the program, and an import.meta expression | |
// in a script isn't considered an error. | |
allowImportExportEverywhere: false, | |
// By default, await identifiers are allowed to appear at the top-level scope only if ecmaVersion >= 2022. | |
// When enabled, await identifiers are allowed to appear at the top-level scope, | |
// but they are still not allowed in non-async functions. | |
allowAwaitOutsideFunction: null, | |
// When enabled, super identifiers are not constrained to | |
// appearing in methods and do not raise an error when they appear elsewhere. | |
allowSuperOutsideMethod: null, | |
// When enabled, hashbang directive in the beginning of file | |
// is allowed and treated as a line comment. | |
allowHashBang: false, | |
// When `locations` is on, `loc` properties holding objects with | |
// `start` and `end` properties in `{line, column}` form (with | |
// line being 1-based and column 0-based) will be attached to the | |
// nodes. | |
locations: false, | |
// A function can be passed as `onToken` option, which will | |
// cause Acorn to call that function with object in the same | |
// format as tokens returned from `tokenizer().getToken()`. Note | |
// that you are not allowed to call the parser from the | |
// callback—that will corrupt its internal state. | |
onToken: null, | |
// A function can be passed as `onComment` option, which will | |
// cause Acorn to call that function with `(block, text, start, | |
// end)` parameters whenever a comment is skipped. `block` is a | |
// boolean indicating whether this is a block (`/* */`) comment, | |
// `text` is the content of the comment, and `start` and `end` are | |
// character offsets that denote the start and end of the comment. | |
// When the `locations` option is on, two more parameters are | |
// passed, the full `{line, column}` locations of the start and | |
// end of the comments. Note that you are not allowed to call the | |
// parser from the callback—that will corrupt its internal state. | |
onComment: null, | |
// Nodes have their start and end characters offsets recorded in | |
// `start` and `end` properties (directly on the node, rather than | |
// the `loc` object, which holds line/column data. To also add a | |
// [semi-standardized][range] `range` property holding a `[start, | |
// end]` array with the same numbers, set the `ranges` option to | |
// `true`. | |
// | |
// [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 | |
ranges: false, | |
// It is possible to parse multiple files into a single AST by | |
// passing the tree produced by parsing the first file as | |
// `program` option in subsequent parses. This will add the | |
// toplevel forms of the parsed file to the `Program` (top) node | |
// of an existing parse tree. | |
program: null, | |
// When `locations` is on, you can pass this to record the source | |
// file in every node's `loc` object. | |
sourceFile: null, | |
// This value, if given, is stored in every node, whether | |
// `locations` is on or off. | |
directSourceFile: null, | |
// When enabled, parenthesized expressions are represented by | |
// (non-standard) ParenthesizedExpression nodes | |
preserveParens: false | |
}; | |
// Interpret and default an options object | |
var warnedAboutEcmaVersion = false; | |
function getOptions(opts) { | |
var options = {}; | |
for (var opt in defaultOptions) | |
{ options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; } | |
if (options.ecmaVersion === "latest") { | |
options.ecmaVersion = 1e8; | |
} else if (options.ecmaVersion == null) { | |
if (!warnedAboutEcmaVersion && typeof console === "object" && console.warn) { | |
warnedAboutEcmaVersion = true; | |
console.warn("Since Acorn 8.0.0, options.ecmaVersion is required.\nDefaulting to 2020, but this will stop working in the future."); | |
} | |
options.ecmaVersion = 11; | |
} else if (options.ecmaVersion >= 2015) { | |
options.ecmaVersion -= 2009; | |
} | |
if (options.allowReserved == null) | |
{ options.allowReserved = options.ecmaVersion < 5; } | |
if (isArray(options.onToken)) { | |
var tokens = options.onToken; | |
options.onToken = function (token) { return tokens.push(token); }; | |
} | |
if (isArray(options.onComment)) | |
{ options.onComment = pushComment(options, options.onComment); } | |
return options | |
} | |
function pushComment(options, array) { | |
return function(block, text, start, end, startLoc, endLoc) { | |
var comment = { | |
type: block ? "Block" : "Line", | |
value: text, | |
start: start, | |
end: end | |
}; | |
if (options.locations) | |
{ comment.loc = new SourceLocation(this, startLoc, endLoc); } | |
if (options.ranges) | |
{ comment.range = [start, end]; } | |
array.push(comment); | |
} | |
} | |
// Each scope gets a bitset that may contain these flags | |
var | |
SCOPE_TOP = 1, | |
SCOPE_FUNCTION = 2, | |
SCOPE_ASYNC = 4, | |
SCOPE_GENERATOR = 8, | |
SCOPE_ARROW = 16, | |
SCOPE_SIMPLE_CATCH = 32, | |
SCOPE_SUPER = 64, | |
SCOPE_DIRECT_SUPER = 128, | |
SCOPE_CLASS_STATIC_BLOCK = 256, | |
SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK; | |
function functionFlags(async, generator) { | |
return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0) | |
} | |
// Used in checkLVal* and declareName to determine the type of a binding | |
var | |
BIND_NONE = 0, // Not a binding | |
BIND_VAR = 1, // Var-style binding | |
BIND_LEXICAL = 2, // Let- or const-style binding | |
BIND_FUNCTION = 3, // Function declaration | |
BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding | |
BIND_OUTSIDE = 5; // Special case for function names as bound inside the function | |
var Parser = function Parser(options, input, startPos) { | |
this.options = options = getOptions(options); | |
this.sourceFile = options.sourceFile; | |
this.keywords = wordsRegexp(keywords$1[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]); | |
var reserved = ""; | |
if (options.allowReserved !== true) { | |
reserved = reservedWords[options.ecmaVersion >= 6 ? 6 : options.ecmaVersion === 5 ? 5 : 3]; | |
if (options.sourceType === "module") { reserved += " await"; } | |
} | |
this.reservedWords = wordsRegexp(reserved); | |
var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; | |
this.reservedWordsStrict = wordsRegexp(reservedStrict); | |
this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind); | |
this.input = String(input); | |
// Used to signal to callers of `readWord1` whether the word | |
// contained any escape sequences. This is needed because words with | |
// escape sequences must not be interpreted as keywords. | |
this.containsEsc = false; | |
// Set up token state | |
// The current position of the tokenizer in the input. | |
if (startPos) { | |
this.pos = startPos; | |
this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; | |
this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; | |
} else { | |
this.pos = this.lineStart = 0; | |
this.curLine = 1; | |
} | |
// Properties of the current token: | |
// Its type | |
this.type = types$1.eof; | |
// For tokens that include more information than their type, the value | |
this.value = null; | |
// Its start and end offset | |
this.start = this.end = this.pos; | |
// And, if locations are used, the {line, column} object | |
// corresponding to those offsets | |
this.startLoc = this.endLoc = this.curPosition(); | |
// Position information for the previous token | |
this.lastTokEndLoc = this.lastTokStartLoc = null; | |
this.lastTokStart = this.lastTokEnd = this.pos; | |
// The context stack is used to superficially track syntactic | |
// context to predict whether a regular expression is allowed in a | |
// given position. | |
this.context = this.initialContext(); | |
this.exprAllowed = true; | |
// Figure out if it's a module code. | |
this.inModule = options.sourceType === "module"; | |
this.strict = this.inModule || this.strictDirective(this.pos); | |
// Used to signify the start of a potential arrow function | |
this.potentialArrowAt = -1; | |
this.potentialArrowInForAwait = false; | |
// Positions to delayed-check that yield/await does not exist in default parameters. | |
this.yieldPos = this.awaitPos = this.awaitIdentPos = 0; | |
// Labels in scope. | |
this.labels = []; | |
// Thus-far undefined exports. | |
this.undefinedExports = Object.create(null); | |
// If enabled, skip leading hashbang line. | |
if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") | |
{ this.skipLineComment(2); } | |
// Scope tracking for duplicate variable names (see scope.js) | |
this.scopeStack = []; | |
this.enterScope(SCOPE_TOP); | |
// For RegExp validation | |
this.regexpState = null; | |
// The stack of private names. | |
// Each element has two properties: 'declared' and 'used'. | |
// When it exited from the outermost class definition, all used private names must be declared. | |
this.privateNameStack = []; | |
}; | |
var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },canAwait: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true },allowNewDotTarget: { configurable: true },inClassStaticBlock: { configurable: true } }; | |
Parser.prototype.parse = function parse () { | |
var node = this.options.program || this.startNode(); | |
this.nextToken(); | |
return this.parseTopLevel(node) | |
}; | |
prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 }; | |
prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 && !this.currentVarScope().inClassFieldInit }; | |
prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 && !this.currentVarScope().inClassFieldInit }; | |
prototypeAccessors.canAwait.get = function () { | |
for (var i = this.scopeStack.length - 1; i >= 0; i--) { | |
var scope = this.scopeStack[i]; | |
if (scope.inClassFieldInit || scope.flags & SCOPE_CLASS_STATIC_BLOCK) { return false } | |
if (scope.flags & SCOPE_FUNCTION) { return (scope.flags & SCOPE_ASYNC) > 0 } | |
} | |
return (this.inModule && this.options.ecmaVersion >= 13) || this.options.allowAwaitOutsideFunction | |
}; | |
prototypeAccessors.allowSuper.get = function () { | |
var ref = this.currentThisScope(); | |
var flags = ref.flags; | |
var inClassFieldInit = ref.inClassFieldInit; | |
return (flags & SCOPE_SUPER) > 0 || inClassFieldInit || this.options.allowSuperOutsideMethod | |
}; | |
prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 }; | |
prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) }; | |
prototypeAccessors.allowNewDotTarget.get = function () { | |
var ref = this.currentThisScope(); | |
var flags = ref.flags; | |
var inClassFieldInit = ref.inClassFieldInit; | |
return (flags & (SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK)) > 0 || inClassFieldInit | |
}; | |
prototypeAccessors.inClassStaticBlock.get = function () { | |
return (this.currentVarScope().flags & SCOPE_CLASS_STATIC_BLOCK) > 0 | |
}; | |
Parser.extend = function extend () { | |
var plugins = [], len = arguments.length; | |
while ( len-- ) plugins[ len ] = arguments[ len ]; | |
var cls = this; | |
for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); } | |
return cls | |
}; | |
Parser.parse = function parse (input, options) { | |
return new this(options, input).parse() | |
}; | |
Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) { | |
var parser = new this(options, input, pos); | |
parser.nextToken(); | |
return parser.parseExpression() | |
}; | |
Parser.tokenizer = function tokenizer (input, options) { | |
return new this(options, input) | |
}; | |
Object.defineProperties( Parser.prototype, prototypeAccessors ); | |
var pp$9 = Parser.prototype; | |
// ## Parser utilities | |
var literal = /^(?:'((?:\\.|[^'\\])*?)'|"((?:\\.|[^"\\])*?)")/; | |
pp$9.strictDirective = function(start) { | |
for (;;) { | |
// Try to find string literal. | |
skipWhiteSpace.lastIndex = start; | |
start += skipWhiteSpace.exec(this.input)[0].length; | |
var match = literal.exec(this.input.slice(start)); | |
if (!match) { return false } | |
if ((match[1] || match[2]) === "use strict") { | |
skipWhiteSpace.lastIndex = start + match[0].length; | |
var spaceAfter = skipWhiteSpace.exec(this.input), end = spaceAfter.index + spaceAfter[0].length; | |
var next = this.input.charAt(end); | |
return next === ";" || next === "}" || | |
(lineBreak.test(spaceAfter[0]) && | |
!(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "=")) | |
} | |
start += match[0].length; | |
// Skip semicolon, if any. | |
skipWhiteSpace.lastIndex = start; | |
start += skipWhiteSpace.exec(this.input)[0].length; | |
if (this.input[start] === ";") | |
{ start++; } | |
} | |
}; | |
// Predicate that tests whether the next token is of the given | |
// type, and if yes, consumes it as a side effect. | |
pp$9.eat = function(type) { | |
if (this.type === type) { | |
this.next(); | |
return true | |
} else { | |
return false | |
} | |
}; | |
// Tests whether parsed token is a contextual keyword. | |
pp$9.isContextual = function(name) { | |
return this.type === types$1.name && this.value === name && !this.containsEsc | |
}; | |
// Consumes contextual keyword if possible. | |
pp$9.eatContextual = function(name) { | |
if (!this.isContextual(name)) { return false } | |
this.next(); | |
return true | |
}; | |
// Asserts that following token is given contextual keyword. | |
pp$9.expectContextual = function(name) { | |
if (!this.eatContextual(name)) { this.unexpected(); } | |
}; | |
// Test whether a semicolon can be inserted at the current position. | |
pp$9.canInsertSemicolon = function() { | |
return this.type === types$1.eof || | |
this.type === types$1.braceR || | |
lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) | |
}; | |
pp$9.insertSemicolon = function() { | |
if (this.canInsertSemicolon()) { | |
if (this.options.onInsertedSemicolon) | |
{ this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } | |
return true | |
} | |
}; | |
// Consume a semicolon, or, failing that, see if we are allowed to | |
// pretend that there is a semicolon at this position. | |
pp$9.semicolon = function() { | |
if (!this.eat(types$1.semi) && !this.insertSemicolon()) { this.unexpected(); } | |
}; | |
pp$9.afterTrailingComma = function(tokType, notNext) { | |
if (this.type === tokType) { | |
if (this.options.onTrailingComma) | |
{ this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } | |
if (!notNext) | |
{ this.next(); } | |
return true | |
} | |
}; | |
// Expect a token of a given type. If found, consume it, otherwise, | |
// raise an unexpected token error. | |
pp$9.expect = function(type) { | |
this.eat(type) || this.unexpected(); | |
}; | |
// Raise an unexpected token error. | |
pp$9.unexpected = function(pos) { | |
this.raise(pos != null ? pos : this.start, "Unexpected token"); | |
}; | |
function DestructuringErrors() { | |
this.shorthandAssign = | |
this.trailingComma = | |
this.parenthesizedAssign = | |
this.parenthesizedBind = | |
this.doubleProto = | |
-1; | |
} | |
pp$9.checkPatternErrors = function(refDestructuringErrors, isAssign) { | |
if (!refDestructuringErrors) { return } | |
if (refDestructuringErrors.trailingComma > -1) | |
{ this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } | |
var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; | |
if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); } | |
}; | |
pp$9.checkExpressionErrors = function(refDestructuringErrors, andThrow) { | |
if (!refDestructuringErrors) { return false } | |
var shorthandAssign = refDestructuringErrors.shorthandAssign; | |
var doubleProto = refDestructuringErrors.doubleProto; | |
if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 } | |
if (shorthandAssign >= 0) | |
{ this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); } | |
if (doubleProto >= 0) | |
{ this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); } | |
}; | |
pp$9.checkYieldAwaitInDefaultParams = function() { | |
if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) | |
{ this.raise(this.yieldPos, "Yield expression cannot be a default value"); } | |
if (this.awaitPos) | |
{ this.raise(this.awaitPos, "Await expression cannot be a default value"); } | |
}; | |
pp$9.isSimpleAssignTarget = function(expr) { | |
if (expr.type === "ParenthesizedExpression") | |
{ return this.isSimpleAssignTarget(expr.expression) } | |
return expr.type === "Identifier" || expr.type === "MemberExpression" | |
}; | |
var pp$8 = Parser.prototype; | |
// ### Statement parsing | |
// Parse a program. Initializes the parser, reads any number of | |
// statements, and wraps them in a Program node. Optionally takes a | |
// `program` argument. If present, the statements will be appended | |
// to its body instead of creating a new node. | |
pp$8.parseTopLevel = function(node) { | |
var exports = Object.create(null); | |
if (!node.body) { node.body = []; } | |
while (this.type !== types$1.eof) { | |
var stmt = this.parseStatement(null, true, exports); | |
node.body.push(stmt); | |
} | |
if (this.inModule) | |
{ for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1) | |
{ | |
var name = list[i]; | |
this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined")); | |
} } | |
this.adaptDirectivePrologue(node.body); | |
this.next(); | |
node.sourceType = this.options.sourceType; | |
return this.finishNode(node, "Program") | |
}; | |
var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"}; | |
pp$8.isLet = function(context) { | |
if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false } | |
skipWhiteSpace.lastIndex = this.pos; | |
var skip = skipWhiteSpace.exec(this.input); | |
var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); | |
// For ambiguous cases, determine if a LexicalDeclaration (or only a | |
// Statement) is allowed here. If context is not empty then only a Statement | |
// is allowed. However, `let [` is an explicit negative lookahead for | |
// ExpressionStatement, so special-case it first. | |
if (nextCh === 91 || nextCh === 92 || nextCh > 0xd7ff && nextCh < 0xdc00) { return true } // '[', '/', astral | |
if (context) { return false } | |
if (nextCh === 123) { return true } // '{' | |
if (isIdentifierStart(nextCh, true)) { | |
var pos = next + 1; | |
while (isIdentifierChar(nextCh = this.input.charCodeAt(pos), true)) { ++pos; } | |
if (nextCh === 92 || nextCh > 0xd7ff && nextCh < 0xdc00) { return true } | |
var ident = this.input.slice(next, pos); | |
if (!keywordRelationalOperator.test(ident)) { return true } | |
} | |
return false | |
}; | |
// check 'async [no LineTerminator here] function' | |
// - 'async /*foo*/ function' is OK. | |
// - 'async /*\n*/ function' is invalid. | |
pp$8.isAsyncFunction = function() { | |
if (this.options.ecmaVersion < 8 || !this.isContextual("async")) | |
{ return false } | |
skipWhiteSpace.lastIndex = this.pos; | |
var skip = skipWhiteSpace.exec(this.input); | |
var next = this.pos + skip[0].length, after; | |
return !lineBreak.test(this.input.slice(this.pos, next)) && | |
this.input.slice(next, next + 8) === "function" && | |
(next + 8 === this.input.length || | |
!(isIdentifierChar(after = this.input.charCodeAt(next + 8)) || after > 0xd7ff && after < 0xdc00)) | |
}; | |
// Parse a single statement. | |
// | |
// If expecting a statement and finding a slash operator, parse a | |
// regular expression literal. This is to handle cases like | |
// `if (foo) /blah/.exec(foo)`, where looking at the previous token | |
// does not help. | |
pp$8.parseStatement = function(context, topLevel, exports) { | |
var starttype = this.type, node = this.startNode(), kind; | |
if (this.isLet(context)) { | |
starttype = types$1._var; | |
kind = "let"; | |
} | |
// Most types of statements are recognized by the keyword they | |
// start with. Many are trivial to parse, some require a bit of | |
// complexity. | |
switch (starttype) { | |
case types$1._break: case types$1._continue: return this.parseBreakContinueStatement(node, starttype.keyword) | |
case types$1._debugger: return this.parseDebuggerStatement(node) | |
case types$1._do: return this.parseDoStatement(node) | |
case types$1._for: return this.parseForStatement(node) | |
case types$1._function: | |
// Function as sole body of either an if statement or a labeled statement | |
// works, but not when it is part of a labeled statement that is the sole | |
// body of an if statement. | |
if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); } | |
return this.parseFunctionStatement(node, false, !context) | |
case types$1._class: | |
if (context) { this.unexpected(); } | |
return this.parseClass(node, true) | |
case types$1._if: return this.parseIfStatement(node) | |
case types$1._return: return this.parseReturnStatement(node) | |
case types$1._switch: return this.parseSwitchStatement(node) | |
case types$1._throw: return this.parseThrowStatement(node) | |
case types$1._try: return this.parseTryStatement(node) | |
case types$1._const: case types$1._var: | |
kind = kind || this.value; | |
if (context && kind !== "var") { this.unexpected(); } | |
return this.parseVarStatement(node, kind) | |
case types$1._while: return this.parseWhileStatement(node) | |
case types$1._with: return this.parseWithStatement(node) | |
case types$1.braceL: return this.parseBlock(true, node) | |
case types$1.semi: return this.parseEmptyStatement(node) | |
case types$1._export: | |
case types$1._import: | |
if (this.options.ecmaVersion > 10 && starttype === types$1._import) { | |
skipWhiteSpace.lastIndex = this.pos; | |
var skip = skipWhiteSpace.exec(this.input); | |
var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); | |
if (nextCh === 40 || nextCh === 46) // '(' or '.' | |
{ return this.parseExpressionStatement(node, this.parseExpression()) } | |
} | |
if (!this.options.allowImportExportEverywhere) { | |
if (!topLevel) | |
{ this.raise(this.start, "'import' and 'export' may only appear at the top level"); } | |
if (!this.inModule) | |
{ this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } | |
} | |
return starttype === types$1._import ? this.parseImport(node) : this.parseExport(node, exports) | |
// If the statement does not start with a statement keyword or a | |
// brace, it's an ExpressionStatement or LabeledStatement. We | |
// simply start parsing an expression, and afterwards, if the | |
// next token is a colon and the expression was a simple | |
// Identifier node, we switch to interpreting it as a label. | |
default: | |
if (this.isAsyncFunction()) { | |
if (context) { this.unexpected(); } | |
this.next(); | |
return this.parseFunctionStatement(node, true, !context) | |
} | |
var maybeName = this.value, expr = this.parseExpression(); | |
if (starttype === types$1.name && expr.type === "Identifier" && this.eat(types$1.colon)) | |
{ return this.parseLabeledStatement(node, maybeName, expr, context) } | |
else { return this.parseExpressionStatement(node, expr) } | |
} | |
}; | |
pp$8.parseBreakContinueStatement = function(node, keyword) { | |
var isBreak = keyword === "break"; | |
this.next(); | |
if (this.eat(types$1.semi) || this.insertSemicolon()) { node.label = null; } | |
else if (this.type !== types$1.name) { this.unexpected(); } | |
else { | |
node.label = this.parseIdent(); | |
this.semicolon(); | |
} | |
// Verify that there is an actual destination to break or | |
// continue to. | |
var i = 0; | |
for (; i < this.labels.length; ++i) { | |
var lab = this.labels[i]; | |
if (node.label == null || lab.name === node.label.name) { | |
if (lab.kind != null && (isBreak || lab.kind === "loop")) { break } | |
if (node.label && isBreak) { break } | |
} | |
} | |
if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); } | |
return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") | |
}; | |
pp$8.parseDebuggerStatement = function(node) { | |
this.next(); | |
this.semicolon(); | |
return this.finishNode(node, "DebuggerStatement") | |
}; | |
pp$8.parseDoStatement = function(node) { | |
this.next(); | |
this.labels.push(loopLabel); | |
node.body = this.parseStatement("do"); | |
this.labels.pop(); | |
this.expect(types$1._while); | |
node.test = this.parseParenExpression(); | |
if (this.options.ecmaVersion >= 6) | |
{ this.eat(types$1.semi); } | |
else | |
{ this.semicolon(); } | |
return this.finishNode(node, "DoWhileStatement") | |
}; | |
// Disambiguating between a `for` and a `for`/`in` or `for`/`of` | |
// loop is non-trivial. Basically, we have to parse the init `var` | |
// statement or expression, disallowing the `in` operator (see | |
// the second parameter to `parseExpression`), and then check | |
// whether the next token is `in` or `of`. When there is no init | |
// part (semicolon immediately after the opening parenthesis), it | |
// is a regular `for` loop. | |
pp$8.parseForStatement = function(node) { | |
this.next(); | |
var awaitAt = (this.options.ecmaVersion >= 9 && this.canAwait && this.eatContextual("await")) ? this.lastTokStart : -1; | |
this.labels.push(loopLabel); | |
this.enterScope(0); | |
this.expect(types$1.parenL); | |
if (this.type === types$1.semi) { | |
if (awaitAt > -1) { this.unexpected(awaitAt); } | |
return this.parseFor(node, null) | |
} | |
var isLet = this.isLet(); | |
if (this.type === types$1._var || this.type === types$1._const || isLet) { | |
var init$1 = this.startNode(), kind = isLet ? "let" : this.value; | |
this.next(); | |
this.parseVar(init$1, true, kind); | |
this.finishNode(init$1, "VariableDeclaration"); | |
if ((this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1) { | |
if (this.options.ecmaVersion >= 9) { | |
if (this.type === types$1._in) { | |
if (awaitAt > -1) { this.unexpected(awaitAt); } | |
} else { node.await = awaitAt > -1; } | |
} | |
return this.parseForIn(node, init$1) | |
} | |
if (awaitAt > -1) { this.unexpected(awaitAt); } | |
return this.parseFor(node, init$1) | |
} | |
var startsWithLet = this.isContextual("let"), isForOf = false; | |
var refDestructuringErrors = new DestructuringErrors; | |
var init = this.parseExpression(awaitAt > -1 ? "await" : true, refDestructuringErrors); | |
if (this.type === types$1._in || (isForOf = this.options.ecmaVersion >= 6 && this.isContextual("of"))) { | |
if (this.options.ecmaVersion >= 9) { | |
if (this.type === types$1._in) { | |
if (awaitAt > -1) { this.unexpected(awaitAt); } | |
} else { node.await = awaitAt > -1; } | |
} | |
if (startsWithLet && isForOf) { this.raise(init.start, "The left-hand side of a for-of loop may not start with 'let'."); } | |
this.toAssignable(init, false, refDestructuringErrors); | |
this.checkLValPattern(init); | |
return this.parseForIn(node, init) | |
} else { | |
this.checkExpressionErrors(refDestructuringErrors, true); | |
} | |
if (awaitAt > -1) { this.unexpected(awaitAt); } | |
return this.parseFor(node, init) | |
}; | |
pp$8.parseFunctionStatement = function(node, isAsync, declarationPosition) { | |
this.next(); | |
return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync) | |
}; | |
pp$8.parseIfStatement = function(node) { | |
this.next(); | |
node.test = this.parseParenExpression(); | |
// allow function declarations in branches, but only in non-strict mode | |
node.consequent = this.parseStatement("if"); | |
node.alternate = this.eat(types$1._else) ? this.parseStatement("if") : null; | |
return this.finishNode(node, "IfStatement") | |
}; | |
pp$8.parseReturnStatement = function(node) { | |
if (!this.inFunction && !this.options.allowReturnOutsideFunction) | |
{ this.raise(this.start, "'return' outside of function"); } | |
this.next(); | |
// In `return` (and `break`/`continue`), the keywords with | |
// optional arguments, we eagerly look for a semicolon or the | |
// possibility to insert one. | |
if (this.eat(types$1.semi) || this.insertSemicolon()) { node.argument = null; } | |
else { node.argument = this.parseExpression(); this.semicolon(); } | |
return this.finishNode(node, "ReturnStatement") | |
}; | |
pp$8.parseSwitchStatement = function(node) { | |
this.next(); | |
node.discriminant = this.parseParenExpression(); | |
node.cases = []; | |
this.expect(types$1.braceL); | |
this.labels.push(switchLabel); | |
this.enterScope(0); | |
// Statements under must be grouped (by label) in SwitchCase | |
// nodes. `cur` is used to keep the node that we are currently | |
// adding statements to. | |
var cur; | |
for (var sawDefault = false; this.type !== types$1.braceR;) { | |
if (this.type === types$1._case || this.type === types$1._default) { | |
var isCase = this.type === types$1._case; | |
if (cur) { this.finishNode(cur, "SwitchCase"); } | |
node.cases.push(cur = this.startNode()); | |
cur.consequent = []; | |
this.next(); | |
if (isCase) { | |
cur.test = this.parseExpression(); | |
} else { | |
if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); } | |
sawDefault = true; | |
cur.test = null; | |
} | |
this.expect(types$1.colon); | |
} else { | |
if (!cur) { this.unexpected(); } | |
cur.consequent.push(this.parseStatement(null)); | |
} | |
} | |
this.exitScope(); | |
if (cur) { this.finishNode(cur, "SwitchCase"); } | |
this.next(); // Closing brace | |
this.labels.pop(); | |
return this.finishNode(node, "SwitchStatement") | |
}; | |
pp$8.parseThrowStatement = function(node) { | |
this.next(); | |
if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) | |
{ this.raise(this.lastTokEnd, "Illegal newline after throw"); } | |
node.argument = this.parseExpression(); | |
this.semicolon(); | |
return this.finishNode(node, "ThrowStatement") | |
}; | |
// Reused empty array added for node fields that are always empty. | |
var empty$1 = []; | |
pp$8.parseTryStatement = function(node) { | |
this.next(); | |
node.block = this.parseBlock(); | |
node.handler = null; | |
if (this.type === types$1._catch) { | |
var clause = this.startNode(); | |
this.next(); | |
if (this.eat(types$1.parenL)) { | |
clause.param = this.parseBindingAtom(); | |
var simple = clause.param.type === "Identifier"; | |
this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0); | |
this.checkLValPattern(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL); | |
this.expect(types$1.parenR); | |
} else { | |
if (this.options.ecmaVersion < 10) { this.unexpected(); } | |
clause.param = null; | |
this.enterScope(0); | |
} | |
clause.body = this.parseBlock(false); | |
this.exitScope(); | |
node.handler = this.finishNode(clause, "CatchClause"); | |
} | |
node.finalizer = this.eat(types$1._finally) ? this.parseBlock() : null; | |
if (!node.handler && !node.finalizer) | |
{ this.raise(node.start, "Missing catch or finally clause"); } | |
return this.finishNode(node, "TryStatement") | |
}; | |
pp$8.parseVarStatement = function(node, kind) { | |
this.next(); | |
this.parseVar(node, false, kind); | |
this.semicolon(); | |
return this.finishNode(node, "VariableDeclaration") | |
}; | |
pp$8.parseWhileStatement = function(node) { | |
this.next(); | |
node.test = this.parseParenExpression(); | |
this.labels.push(loopLabel); | |
node.body = this.parseStatement("while"); | |
this.labels.pop(); | |
return this.finishNode(node, "WhileStatement") | |
}; | |
pp$8.parseWithStatement = function(node) { | |
if (this.strict) { this.raise(this.start, "'with' in strict mode"); } | |
this.next(); | |
node.object = this.parseParenExpression(); | |
node.body = this.parseStatement("with"); | |
return this.finishNode(node, "WithStatement") | |
}; | |
pp$8.parseEmptyStatement = function(node) { | |
this.next(); | |
return this.finishNode(node, "EmptyStatement") | |
}; | |
pp$8.parseLabeledStatement = function(node, maybeName, expr, context) { | |
for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1) | |
{ | |
var label = list[i$1]; | |
if (label.name === maybeName) | |
{ this.raise(expr.start, "Label '" + maybeName + "' is already declared"); | |
} } | |
var kind = this.type.isLoop ? "loop" : this.type === types$1._switch ? "switch" : null; | |
for (var i = this.labels.length - 1; i >= 0; i--) { | |
var label$1 = this.labels[i]; | |
if (label$1.statementStart === node.start) { | |
// Update information about previous labels on this node | |
label$1.statementStart = this.start; | |
label$1.kind = kind; | |
} else { break } | |
} | |
this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); | |
node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label"); | |
this.labels.pop(); | |
node.label = expr; | |
return this.finishNode(node, "LabeledStatement") | |
}; | |
pp$8.parseExpressionStatement = function(node, expr) { | |
node.expression = expr; | |
this.semicolon(); | |
return this.finishNode(node, "ExpressionStatement") | |
}; | |
// Parse a semicolon-enclosed block of statements, handling `"use | |
// strict"` declarations when `allowStrict` is true (used for | |
// function bodies). | |
pp$8.parseBlock = function(createNewLexicalScope, node, exitStrict) { | |
if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; | |
if ( node === void 0 ) node = this.startNode(); | |
node.body = []; | |
this.expect(types$1.braceL); | |
if (createNewLexicalScope) { this.enterScope(0); } | |
while (this.type !== types$1.braceR) { | |
var stmt = this.parseStatement(null); | |
node.body.push(stmt); | |
} | |
if (exitStrict) { this.strict = false; } | |
this.next(); | |
if (createNewLexicalScope) { this.exitScope(); } | |
return this.finishNode(node, "BlockStatement") | |
}; | |
// Parse a regular `for` loop. The disambiguation code in | |
// `parseStatement` will already have parsed the init statement or | |
// expression. | |
pp$8.parseFor = function(node, init) { | |
node.init = init; | |
this.expect(types$1.semi); | |
node.test = this.type === types$1.semi ? null : this.parseExpression(); | |
this.expect(types$1.semi); | |
node.update = this.type === types$1.parenR ? null : this.parseExpression(); | |
this.expect(types$1.parenR); | |
node.body = this.parseStatement("for"); | |
this.exitScope(); | |
this.labels.pop(); | |
return this.finishNode(node, "ForStatement") | |
}; | |
// Parse a `for`/`in` and `for`/`of` loop, which are almost | |
// same from parser's perspective. | |
pp$8.parseForIn = function(node, init) { | |
var isForIn = this.type === types$1._in; | |
this.next(); | |
if ( | |
init.type === "VariableDeclaration" && | |
init.declarations[0].init != null && | |
( | |
!isForIn || | |
this.options.ecmaVersion < 8 || | |
this.strict || | |
init.kind !== "var" || | |
init.declarations[0].id.type !== "Identifier" | |
) | |
) { | |
this.raise( | |
init.start, | |
((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer") | |
); | |
} | |
node.left = init; | |
node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign(); | |
this.expect(types$1.parenR); | |
node.body = this.parseStatement("for"); | |
this.exitScope(); | |
this.labels.pop(); | |
return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement") | |
}; | |
// Parse a list of variable declarations. | |
pp$8.parseVar = function(node, isFor, kind) { | |
node.declarations = []; | |
node.kind = kind; | |
for (;;) { | |
var decl = this.startNode(); | |
this.parseVarId(decl, kind); | |
if (this.eat(types$1.eq)) { | |
decl.init = this.parseMaybeAssign(isFor); | |
} else if (kind === "const" && !(this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) { | |
this.unexpected(); | |
} else if (decl.id.type !== "Identifier" && !(isFor && (this.type === types$1._in || this.isContextual("of")))) { | |
this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value"); | |
} else { | |
decl.init = null; | |
} | |
node.declarations.push(this.finishNode(decl, "VariableDeclarator")); | |
if (!this.eat(types$1.comma)) { break } | |
} | |
return node | |
}; | |
pp$8.parseVarId = function(decl, kind) { | |
decl.id = this.parseBindingAtom(); | |
this.checkLValPattern(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false); | |
}; | |
var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4; | |
// Parse a function declaration or literal (depending on the | |
// `statement & FUNC_STATEMENT`). | |
// Remove `allowExpressionBody` for 7.0.0, as it is only called with false | |
pp$8.parseFunction = function(node, statement, allowExpressionBody, isAsync, forInit) { | |
this.initFunction(node); | |
if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) { | |
if (this.type === types$1.star && (statement & FUNC_HANGING_STATEMENT)) | |
{ this.unexpected(); } | |
node.generator = this.eat(types$1.star); | |
} | |
if (this.options.ecmaVersion >= 8) | |
{ node.async = !!isAsync; } | |
if (statement & FUNC_STATEMENT) { | |
node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types$1.name ? null : this.parseIdent(); | |
if (node.id && !(statement & FUNC_HANGING_STATEMENT)) | |
// If it is a regular function declaration in sloppy mode, then it is | |
// subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding | |
// mode depends on properties of the current scope (see | |
// treatFunctionsAsVar). | |
{ this.checkLValSimple(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); } | |
} | |
var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; | |
this.yieldPos = 0; | |
this.awaitPos = 0; | |
this.awaitIdentPos = 0; | |
this.enterScope(functionFlags(node.async, node.generator)); | |
if (!(statement & FUNC_STATEMENT)) | |
{ node.id = this.type === types$1.name ? this.parseIdent() : null; } | |
this.parseFunctionParams(node); | |
this.parseFunctionBody(node, allowExpressionBody, false, forInit); | |
this.yieldPos = oldYieldPos; | |
this.awaitPos = oldAwaitPos; | |
this.awaitIdentPos = oldAwaitIdentPos; | |
return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression") | |
}; | |
pp$8.parseFunctionParams = function(node) { | |
this.expect(types$1.parenL); | |
node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8); | |
this.checkYieldAwaitInDefaultParams(); | |
}; | |
// Parse a class declaration or literal (depending on the | |
// `isStatement` parameter). | |
pp$8.parseClass = function(node, isStatement) { | |
this.next(); | |
// ecma-262 14.6 Class Definitions | |
// A class definition is always strict mode code. | |
var oldStrict = this.strict; | |
this.strict = true; | |
this.parseClassId(node, isStatement); | |
this.parseClassSuper(node); | |
var privateNameMap = this.enterClassBody(); | |
var classBody = this.startNode(); | |
var hadConstructor = false; | |
classBody.body = []; | |
this.expect(types$1.braceL); | |
while (this.type !== types$1.braceR) { | |
var element = this.parseClassElement(node.superClass !== null); | |
if (element) { | |
classBody.body.push(element); | |
if (element.type === "MethodDefinition" && element.kind === "constructor") { | |
if (hadConstructor) { this.raise(element.start, "Duplicate constructor in the same class"); } | |
hadConstructor = true; | |
} else if (element.key && element.key.type === "PrivateIdentifier" && isPrivateNameConflicted(privateNameMap, element)) { | |
this.raiseRecoverable(element.key.start, ("Identifier '#" + (element.key.name) + "' has already been declared")); | |
} | |
} | |
} | |
this.strict = oldStrict; | |
this.next(); | |
node.body = this.finishNode(classBody, "ClassBody"); | |
this.exitClassBody(); | |
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") | |
}; | |
pp$8.parseClassElement = function(constructorAllowsSuper) { | |
if (this.eat(types$1.semi)) { return null } | |
var ecmaVersion = this.options.ecmaVersion; | |
var node = this.startNode(); | |
var keyName = ""; | |
var isGenerator = false; | |
var isAsync = false; | |
var kind = "method"; | |
var isStatic = false; | |
if (this.eatContextual("static")) { | |
// Parse static init block | |
if (ecmaVersion >= 13 && this.eat(types$1.braceL)) { | |
this.parseClassStaticBlock(node); | |
return node | |
} | |
if (this.isClassElementNameStart() || this.type === types$1.star) { | |
isStatic = true; | |
} else { | |
keyName = "static"; | |
} | |
} | |
node.static = isStatic; | |
if (!keyName && ecmaVersion >= 8 && this.eatContextual("async")) { | |
if ((this.isClassElementNameStart() || this.type === types$1.star) && !this.canInsertSemicolon()) { | |
isAsync = true; | |
} else { | |
keyName = "async"; | |
} | |
} | |
if (!keyName && (ecmaVersion >= 9 || !isAsync) && this.eat(types$1.star)) { | |
isGenerator = true; | |
} | |
if (!keyName && !isAsync && !isGenerator) { | |
var lastValue = this.value; | |
if (this.eatContextual("get") || this.eatContextual("set")) { | |
if (this.isClassElementNameStart()) { | |
kind = lastValue; | |
} else { | |
keyName = lastValue; | |
} | |
} | |
} | |
// Parse element name | |
if (keyName) { | |
// 'async', 'get', 'set', or 'static' were not a keyword contextually. | |
// The last token is any of those. Make it the element name. | |
node.computed = false; | |
node.key = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc); | |
node.key.name = keyName; | |
this.finishNode(node.key, "Identifier"); | |
} else { | |
this.parseClassElementName(node); | |
} | |
// Parse element value | |
if (ecmaVersion < 13 || this.type === types$1.parenL || kind !== "method" || isGenerator || isAsync) { | |
var isConstructor = !node.static && checkKeyName(node, "constructor"); | |
var allowsDirectSuper = isConstructor && constructorAllowsSuper; | |
// Couldn't move this check into the 'parseClassMethod' method for backward compatibility. | |
if (isConstructor && kind !== "method") { this.raise(node.key.start, "Constructor can't have get/set modifier"); } | |
node.kind = isConstructor ? "constructor" : kind; | |
this.parseClassMethod(node, isGenerator, isAsync, allowsDirectSuper); | |
} else { | |
this.parseClassField(node); | |
} | |
return node | |
}; | |
pp$8.isClassElementNameStart = function() { | |
return ( | |
this.type === types$1.name || | |
this.type === types$1.privateId || | |
this.type === types$1.num || | |
this.type === types$1.string || | |
this.type === types$1.bracketL || | |
this.type.keyword | |
) | |
}; | |
pp$8.parseClassElementName = function(element) { | |
if (this.type === types$1.privateId) { | |
if (this.value === "constructor") { | |
this.raise(this.start, "Classes can't have an element named '#constructor'"); | |
} | |
element.computed = false; | |
element.key = this.parsePrivateIdent(); | |
} else { | |
this.parsePropertyName(element); | |
} | |
}; | |
pp$8.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) { | |
// Check key and flags | |
var key = method.key; | |
if (method.kind === "constructor") { | |
if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); } | |
if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); } | |
} else if (method.static && checkKeyName(method, "prototype")) { | |
this.raise(key.start, "Classes may not have a static property named prototype"); | |
} | |
// Parse value | |
var value = method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper); | |
// Check value | |
if (method.kind === "get" && value.params.length !== 0) | |
{ this.raiseRecoverable(value.start, "getter should have no params"); } | |
if (method.kind === "set" && value.params.length !== 1) | |
{ this.raiseRecoverable(value.start, "setter should have exactly one param"); } | |
if (method.kind === "set" && value.params[0].type === "RestElement") | |
{ this.raiseRecoverable(value.params[0].start, "Setter cannot use rest params"); } | |
return this.finishNode(method, "MethodDefinition") | |
}; | |
pp$8.parseClassField = function(field) { | |
if (checkKeyName(field, "constructor")) { | |
this.raise(field.key.start, "Classes can't have a field named 'constructor'"); | |
} else if (field.static && checkKeyName(field, "prototype")) { | |
this.raise(field.key.start, "Classes can't have a static field named 'prototype'"); | |
} | |
if (this.eat(types$1.eq)) { | |
// To raise SyntaxError if 'arguments' exists in the initializer. | |
var scope = this.currentThisScope(); | |
var inClassFieldInit = scope.inClassFieldInit; | |
scope.inClassFieldInit = true; | |
field.value = this.parseMaybeAssign(); | |
scope.inClassFieldInit = inClassFieldInit; | |
} else { | |
field.value = null; | |
} | |
this.semicolon(); | |
return this.finishNode(field, "PropertyDefinition") | |
}; | |
pp$8.parseClassStaticBlock = function(node) { | |
node.body = []; | |
var oldLabels = this.labels; | |
this.labels = []; | |
this.enterScope(SCOPE_CLASS_STATIC_BLOCK | SCOPE_SUPER); | |
while (this.type !== types$1.braceR) { | |
var stmt = this.parseStatement(null); | |
node.body.push(stmt); | |
} | |
this.next(); | |
this.exitScope(); | |
this.labels = oldLabels; | |
return this.finishNode(node, "StaticBlock") | |
}; | |
pp$8.parseClassId = function(node, isStatement) { | |
if (this.type === types$1.name) { | |
node.id = this.parseIdent(); | |
if (isStatement) | |
{ this.checkLValSimple(node.id, BIND_LEXICAL, false); } | |
} else { | |
if (isStatement === true) | |
{ this.unexpected(); } | |
node.id = null; | |
} | |
}; | |
pp$8.parseClassSuper = function(node) { | |
node.superClass = this.eat(types$1._extends) ? this.parseExprSubscripts(false) : null; | |
}; | |
pp$8.enterClassBody = function() { | |
var element = {declared: Object.create(null), used: []}; | |
this.privateNameStack.push(element); | |
return element.declared | |
}; | |
pp$8.exitClassBody = function() { | |
var ref = this.privateNameStack.pop(); | |
var declared = ref.declared; | |
var used = ref.used; | |
var len = this.privateNameStack.length; | |
var parent = len === 0 ? null : this.privateNameStack[len - 1]; | |
for (var i = 0; i < used.length; ++i) { | |
var id = used[i]; | |
if (!has(declared, id.name)) { | |
if (parent) { | |
parent.used.push(id); | |
} else { | |
this.raiseRecoverable(id.start, ("Private field '#" + (id.name) + "' must be declared in an enclosing class")); | |
} | |
} | |
} | |
}; | |
function isPrivateNameConflicted(privateNameMap, element) { | |
var name = element.key.name; | |
var curr = privateNameMap[name]; | |
var next = "true"; | |
if (element.type === "MethodDefinition" && (element.kind === "get" || element.kind === "set")) { | |
next = (element.static ? "s" : "i") + element.kind; | |
} | |
// `class { get #a(){}; static set #a(_){} }` is also conflict. | |
if ( | |
curr === "iget" && next === "iset" || | |
curr === "iset" && next === "iget" || | |
curr === "sget" && next === "sset" || | |
curr === "sset" && next === "sget" | |
) { | |
privateNameMap[name] = "true"; | |
return false | |
} else if (!curr) { | |
privateNameMap[name] = next; | |
return false | |
} else { | |
return true | |
} | |
} | |
function checkKeyName(node, name) { | |
var computed = node.computed; | |
var key = node.key; | |
return !computed && ( | |
key.type === "Identifier" && key.name === name || | |
key.type === "Literal" && key.value === name | |
) | |
} | |
// Parses module export declaration. | |
pp$8.parseExport = function(node, exports) { | |
this.next(); | |
// export * from '...' | |
if (this.eat(types$1.star)) { | |
if (this.options.ecmaVersion >= 11) { | |
if (this.eatContextual("as")) { | |
node.exported = this.parseIdent(true); | |
this.checkExport(exports, node.exported.name, this.lastTokStart); | |
} else { | |
node.exported = null; | |
} | |
} | |
this.expectContextual("from"); | |
if (this.type !== types$1.string) { this.unexpected(); } | |
node.source = this.parseExprAtom(); | |
this.semicolon(); | |
return this.finishNode(node, "ExportAllDeclaration") | |
} | |
if (this.eat(types$1._default)) { // export default ... | |
this.checkExport(exports, "default", this.lastTokStart); | |
var isAsync; | |
if (this.type === types$1._function || (isAsync = this.isAsyncFunction())) { | |
var fNode = this.startNode(); | |
this.next(); | |
if (isAsync) { this.next(); } | |
node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync); | |
} else if (this.type === types$1._class) { | |
var cNode = this.startNode(); | |
node.declaration = this.parseClass(cNode, "nullableID"); | |
} else { | |
node.declaration = this.parseMaybeAssign(); | |
this.semicolon(); | |
} | |
return this.finishNode(node, "ExportDefaultDeclaration") | |
} | |
// export var|const|let|function|class ... | |
if (this.shouldParseExportStatement()) { | |
node.declaration = this.parseStatement(null); | |
if (node.declaration.type === "VariableDeclaration") | |
{ this.checkVariableExport(exports, node.declaration.declarations); } | |
else | |
{ this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); } | |
node.specifiers = []; | |
node.source = null; | |
} else { // export { x, y as z } [from '...'] | |
node.declaration = null; | |
node.specifiers = this.parseExportSpecifiers(exports); | |
if (this.eatContextual("from")) { | |
if (this.type !== types$1.string) { this.unexpected(); } | |
node.source = this.parseExprAtom(); | |
} else { | |
for (var i = 0, list = node.specifiers; i < list.length; i += 1) { | |
// check for keywords used as local names | |
var spec = list[i]; | |
this.checkUnreserved(spec.local); | |
// check if export is defined | |
this.checkLocalExport(spec.local); | |
} | |
node.source = null; | |
} | |
this.semicolon(); | |
} | |
return this.finishNode(node, "ExportNamedDeclaration") | |
}; | |
pp$8.checkExport = function(exports, name, pos) { | |
if (!exports) { return } | |
if (has(exports, name)) | |
{ this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } | |
exports[name] = true; | |
}; | |
pp$8.checkPatternExport = function(exports, pat) { | |
var type = pat.type; | |
if (type === "Identifier") | |
{ this.checkExport(exports, pat.name, pat.start); } | |
else if (type === "ObjectPattern") | |
{ for (var i = 0, list = pat.properties; i < list.length; i += 1) | |
{ | |
var prop = list[i]; | |
this.checkPatternExport(exports, prop); | |
} } | |
else if (type === "ArrayPattern") | |
{ for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { | |
var elt = list$1[i$1]; | |
if (elt) { this.checkPatternExport(exports, elt); } | |
} } | |
else if (type === "Property") | |
{ this.checkPatternExport(exports, pat.value); } | |
else if (type === "AssignmentPattern") | |
{ this.checkPatternExport(exports, pat.left); } | |
else if (type === "RestElement") | |
{ this.checkPatternExport(exports, pat.argument); } | |
else if (type === "ParenthesizedExpression") | |
{ this.checkPatternExport(exports, pat.expression); } | |
}; | |
pp$8.checkVariableExport = function(exports, decls) { | |
if (!exports) { return } | |
for (var i = 0, list = decls; i < list.length; i += 1) | |
{ | |
var decl = list[i]; | |
this.checkPatternExport(exports, decl.id); | |
} | |
}; | |
pp$8.shouldParseExportStatement = function() { | |
return this.type.keyword === "var" || | |
this.type.keyword === "const" || | |
this.type.keyword === "class" || | |
this.type.keyword === "function" || | |
this.isLet() || | |
this.isAsyncFunction() | |
}; | |
// Parses a comma-separated list of module exports. | |
pp$8.parseExportSpecifiers = function(exports) { | |
var nodes = [], first = true; | |
// export { x, y as z } [from '...'] | |
this.expect(types$1.braceL); | |
while (!this.eat(types$1.braceR)) { | |
if (!first) { | |
this.expect(types$1.comma); | |
if (this.afterTrailingComma(types$1.braceR)) { break } | |
} else { first = false; } | |
var node = this.startNode(); | |
node.local = this.parseIdent(true); | |
node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local; | |
this.checkExport(exports, node.exported.name, node.exported.start); | |
nodes.push(this.finishNode(node, "ExportSpecifier")); | |
} | |
return nodes | |
}; | |
// Parses import declaration. | |
pp$8.parseImport = function(node) { | |
this.next(); | |
// import '...' | |
if (this.type === types$1.string) { | |
node.specifiers = empty$1; | |
node.source = this.parseExprAtom(); | |
} else { | |
node.specifiers = this.parseImportSpecifiers(); | |
this.expectContextual("from"); | |
node.source = this.type === types$1.string ? this.parseExprAtom() : this.unexpected(); | |
} | |
this.semicolon(); | |
return this.finishNode(node, "ImportDeclaration") | |
}; | |
// Parses a comma-separated list of module imports. | |
pp$8.parseImportSpecifiers = function() { | |
var nodes = [], first = true; | |
if (this.type === types$1.name) { | |
// import defaultObj, { x, y as z } from '...' | |
var node = this.startNode(); | |
node.local = this.parseIdent(); | |
this.checkLValSimple(node.local, BIND_LEXICAL); | |
nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); | |
if (!this.eat(types$1.comma)) { return nodes } | |
} | |
if (this.type === types$1.star) { | |
var node$1 = this.startNode(); | |
this.next(); | |
this.expectContextual("as"); | |
node$1.local = this.parseIdent(); | |
this.checkLValSimple(node$1.local, BIND_LEXICAL); | |
nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")); | |
return nodes | |
} | |
this.expect(types$1.braceL); | |
while (!this.eat(types$1.braceR)) { | |
if (!first) { | |
this.expect(types$1.comma); | |
if (this.afterTrailingComma(types$1.braceR)) { break } | |
} else { first = false; } | |
var node$2 = this.startNode(); | |
node$2.imported = this.parseIdent(true); | |
if (this.eatContextual("as")) { | |
node$2.local = this.parseIdent(); | |
} else { | |
this.checkUnreserved(node$2.imported); | |
node$2.local = node$2.imported; | |
} | |
this.checkLValSimple(node$2.local, BIND_LEXICAL); | |
nodes.push(this.finishNode(node$2, "ImportSpecifier")); | |
} | |
return nodes | |
}; | |
// Set `ExpressionStatement#directive` property for directive prologues. | |
pp$8.adaptDirectivePrologue = function(statements) { | |
for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { | |
statements[i].directive = statements[i].expression.raw.slice(1, -1); | |
} | |
}; | |
pp$8.isDirectiveCandidate = function(statement) { | |
return ( | |
statement.type === "ExpressionStatement" && | |
statement.expression.type === "Literal" && | |
typeof statement.expression.value === "string" && | |
// Reject parenthesized strings. | |
(this.input[statement.start] === "\"" || this.input[statement.start] === "'") | |
) | |
}; | |
var pp$7 = Parser.prototype; | |
// Convert existing expression atom to assignable pattern | |
// if possible. | |
pp$7.toAssignable = function(node, isBinding, refDestructuringErrors) { | |
if (this.options.ecmaVersion >= 6 && node) { | |
switch (node.type) { | |
case "Identifier": | |
if (this.inAsync && node.name === "await") | |
{ this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); } | |
break | |
case "ObjectPattern": | |
case "ArrayPattern": | |
case "AssignmentPattern": | |
case "RestElement": | |
break | |
case "ObjectExpression": | |
node.type = "ObjectPattern"; | |
if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } | |
for (var i = 0, list = node.properties; i < list.length; i += 1) { | |
var prop = list[i]; | |
this.toAssignable(prop, isBinding); | |
// Early error: | |
// AssignmentRestProperty[Yield, Await] : | |
// `...` DestructuringAssignmentTarget[Yield, Await] | |
// | |
// It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|. | |
if ( | |
prop.type === "RestElement" && | |
(prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern") | |
) { | |
this.raise(prop.argument.start, "Unexpected token"); | |
} | |
} | |
break | |
case "Property": | |
// AssignmentProperty has type === "Property" | |
if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); } | |
this.toAssignable(node.value, isBinding); | |
break | |
case "ArrayExpression": | |
node.type = "ArrayPattern"; | |
if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } | |
this.toAssignableList(node.elements, isBinding); | |
break | |
case "SpreadElement": | |
node.type = "RestElement"; | |
this.toAssignable(node.argument, isBinding); | |
if (node.argument.type === "AssignmentPattern") | |
{ this.raise(node.argument.start, "Rest elements cannot have a default value"); } | |
break | |
case "AssignmentExpression": | |
if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); } | |
node.type = "AssignmentPattern"; | |
delete node.operator; | |
this.toAssignable(node.left, isBinding); | |
break | |
case "ParenthesizedExpression": | |
this.toAssignable(node.expression, isBinding, refDestructuringErrors); | |
break | |
case "ChainExpression": | |
this.raiseRecoverable(node.start, "Optional chaining cannot appear in left-hand side"); | |
break | |
case "MemberExpression": | |
if (!isBinding) { break } | |
default: | |
this.raise(node.start, "Assigning to rvalue"); | |
} | |
} else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } | |
return node | |
}; | |
// Convert list of expression atoms to binding list. | |
pp$7.toAssignableList = function(exprList, isBinding) { | |
var end = exprList.length; | |
for (var i = 0; i < end; i++) { | |
var elt = exprList[i]; | |
if (elt) { this.toAssignable(elt, isBinding); } | |
} | |
if (end) { | |
var last = exprList[end - 1]; | |
if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") | |
{ this.unexpected(last.argument.start); } | |
} | |
return exprList | |
}; | |
// Parses spread element. | |
pp$7.parseSpread = function(refDestructuringErrors) { | |
var node = this.startNode(); | |
this.next(); | |
node.argument = this.parseMaybeAssign(false, refDestructuringErrors); | |
return this.finishNode(node, "SpreadElement") | |
}; | |
pp$7.parseRestBinding = function() { | |
var node = this.startNode(); | |
this.next(); | |
// RestElement inside of a function parameter must be an identifier | |
if (this.options.ecmaVersion === 6 && this.type !== types$1.name) | |
{ this.unexpected(); } | |
node.argument = this.parseBindingAtom(); | |
return this.finishNode(node, "RestElement") | |
}; | |
// Parses lvalue (assignable) atom. | |
pp$7.parseBindingAtom = function() { | |
if (this.options.ecmaVersion >= 6) { | |
switch (this.type) { | |
case types$1.bracketL: | |
var node = this.startNode(); | |
this.next(); | |
node.elements = this.parseBindingList(types$1.bracketR, true, true); | |
return this.finishNode(node, "ArrayPattern") | |
case types$1.braceL: | |
return this.parseObj(true) | |
} | |
} | |
return this.parseIdent() | |
}; | |
pp$7.parseBindingList = function(close, allowEmpty, allowTrailingComma) { | |
var elts = [], first = true; | |
while (!this.eat(close)) { | |
if (first) { first = false; } | |
else { this.expect(types$1.comma); } | |
if (allowEmpty && this.type === types$1.comma) { | |
elts.push(null); | |
} else if (allowTrailingComma && this.afterTrailingComma(close)) { | |
break | |
} else if (this.type === types$1.ellipsis) { | |
var rest = this.parseRestBinding(); | |
this.parseBindingListItem(rest); | |
elts.push(rest); | |
if (this.type === types$1.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); } | |
this.expect(close); | |
break | |
} else { | |
var elem = this.parseMaybeDefault(this.start, this.startLoc); | |
this.parseBindingListItem(elem); | |
elts.push(elem); | |
} | |
} | |
return elts | |
}; | |
pp$7.parseBindingListItem = function(param) { | |
return param | |
}; | |
// Parses assignment pattern around given atom if possible. | |
pp$7.parseMaybeDefault = function(startPos, startLoc, left) { | |
left = left || this.parseBindingAtom(); | |
if (this.options.ecmaVersion < 6 || !this.eat(types$1.eq)) { return left } | |
var node = this.startNodeAt(startPos, startLoc); | |
node.left = left; | |
node.right = this.parseMaybeAssign(); | |
return this.finishNode(node, "AssignmentPattern") | |
}; | |
// The following three functions all verify that a node is an lvalue — | |
// something that can be bound, or assigned to. In order to do so, they perform | |
// a variety of checks: | |
// | |
// - Check that none of the bound/assigned-to identifiers are reserved words. | |
// - Record name declarations for bindings in the appropriate scope. | |
// - Check duplicate argument names, if checkClashes is set. | |
// | |
// If a complex binding pattern is encountered (e.g., object and array | |
// destructuring), the entire pattern is recursively checked. | |
// | |
// There are three versions of checkLVal*() appropriate for different | |
// circumstances: | |
// | |
// - checkLValSimple() shall be used if the syntactic construct supports | |
// nothing other than identifiers and member expressions. Parenthesized | |
// expressions are also correctly handled. This is generally appropriate for | |
// constructs for which the spec says | |
// | |
// > It is a Syntax Error if AssignmentTargetType of [the production] is not | |
// > simple. | |
// | |
// It is also appropriate for checking if an identifier is valid and not | |
// defined elsewhere, like import declarations or function/class identifiers. | |
// | |
// Examples where this is used include: | |
// a += …; | |
// import a from '…'; | |
// where a is the node to be checked. | |
// | |
// - checkLValPattern() shall be used if the syntactic construct supports | |
// anything checkLValSimple() supports, as well as object and array | |
// destructuring patterns. This is generally appropriate for constructs for | |
// which the spec says | |
// | |
// > It is a Syntax Error if [the production] is neither an ObjectLiteral nor | |
// > an ArrayLiteral and AssignmentTargetType of [the production] is not | |
// > simple. | |
// | |
// Examples where this is used include: | |
// (a = …); | |
// const a = …; | |
// try { … } catch (a) { … } | |
// where a is the node to be checked. | |
// | |
// - checkLValInnerPattern() shall be used if the syntactic construct supports | |
// anything checkLValPattern() supports, as well as default assignment | |
// patterns, rest elements, and other constructs that may appear within an | |
// object or array destructuring pattern. | |
// | |
// As a special case, function parameters also use checkLValInnerPattern(), | |
// as they also support defaults and rest constructs. | |
// | |
// These functions deliberately support both assignment and binding constructs, | |
// as the logic for both is exceedingly similar. If the node is the target of | |
// an assignment, then bindingType should be set to BIND_NONE. Otherwise, it | |
// should be set to the appropriate BIND_* constant, like BIND_VAR or | |
// BIND_LEXICAL. | |
// | |
// If the function is called with a non-BIND_NONE bindingType, then | |
// additionally a checkClashes object may be specified to allow checking for | |
// duplicate argument names. checkClashes is ignored if the provided construct | |
// is an assignment (i.e., bindingType is BIND_NONE). | |
pp$7.checkLValSimple = function(expr, bindingType, checkClashes) { | |
if ( bindingType === void 0 ) bindingType = BIND_NONE; | |
var isBind = bindingType !== BIND_NONE; | |
switch (expr.type) { | |
case "Identifier": | |
if (this.strict && this.reservedWordsStrictBind.test(expr.name)) | |
{ this.raiseRecoverable(expr.start, (isBind ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } | |
if (isBind) { | |
if (bindingType === BIND_LEXICAL && expr.name === "let") | |
{ this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); } | |
if (checkClashes) { | |
if (has(checkClashes, expr.name)) | |
{ this.raiseRecoverable(expr.start, "Argument name clash"); } | |
checkClashes[expr.name] = true; | |
} | |
if (bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); } | |
} | |
break | |
case "ChainExpression": | |
this.raiseRecoverable(expr.start, "Optional chaining cannot appear in left-hand side"); | |
break | |
case "MemberExpression": | |
if (isBind) { this.raiseRecoverable(expr.start, "Binding member expression"); } | |
break | |
case "ParenthesizedExpression": | |
if (isBind) { this.raiseRecoverable(expr.start, "Binding parenthesized expression"); } | |
return this.checkLValSimple(expr.expression, bindingType, checkClashes) | |
default: | |
this.raise(expr.start, (isBind ? "Binding" : "Assigning to") + " rvalue"); | |
} | |
}; | |
pp$7.checkLValPattern = function(expr, bindingType, checkClashes) { | |
if ( bindingType === void 0 ) bindingType = BIND_NONE; | |
switch (expr.type) { | |
case "ObjectPattern": | |
for (var i = 0, list = expr.properties; i < list.length; i += 1) { | |
var prop = list[i]; | |
this.checkLValInnerPattern(prop, bindingType, checkClashes); | |
} | |
break | |
case "ArrayPattern": | |
for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { | |
var elem = list$1[i$1]; | |
if (elem) { this.checkLValInnerPattern(elem, bindingType, checkClashes); } | |
} | |
break | |
default: | |
this.checkLValSimple(expr, bindingType, checkClashes); | |
} | |
}; | |
pp$7.checkLValInnerPattern = function(expr, bindingType, checkClashes) { | |
if ( bindingType === void 0 ) bindingType = BIND_NONE; | |
switch (expr.type) { | |
case "Property": | |
// AssignmentProperty has type === "Property" | |
this.checkLValInnerPattern(expr.value, bindingType, checkClashes); | |
break | |
case "AssignmentPattern": | |
this.checkLValPattern(expr.left, bindingType, checkClashes); | |
break | |
case "RestElement": | |
this.checkLValPattern(expr.argument, bindingType, checkClashes); | |
break | |
default: | |
this.checkLValPattern(expr, bindingType, checkClashes); | |
} | |
}; | |
// The algorithm used to determine whether a regexp can appear at a | |
var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { | |
this.token = token; | |
this.isExpr = !!isExpr; | |
this.preserveSpace = !!preserveSpace; | |
this.override = override; | |
this.generator = !!generator; | |
}; | |
var types = { | |
b_stat: new TokContext("{", false), | |
b_expr: new TokContext("{", true), | |
b_tmpl: new TokContext("${", false), | |
p_stat: new TokContext("(", false), | |
p_expr: new TokContext("(", true), | |
q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), | |
f_stat: new TokContext("function", false), | |
f_expr: new TokContext("function", true), | |
f_expr_gen: new TokContext("function", true, false, null, true), | |
f_gen: new TokContext("function", false, false, null, true) | |
}; | |
var pp$6 = Parser.prototype; | |
pp$6.initialContext = function() { | |
return [types.b_stat] | |
}; | |
pp$6.curContext = function() { | |
return this.context[this.context.length - 1] | |
}; | |
pp$6.braceIsBlock = function(prevType) { | |
var parent = this.curContext(); | |
if (parent === types.f_expr || parent === types.f_stat) | |
{ return true } | |
if (prevType === types$1.colon && (parent === types.b_stat || parent === types.b_expr)) | |
{ return !parent.isExpr } | |
// The check for `tt.name && exprAllowed` detects whether we are | |
// after a `yield` or `of` construct. See the `updateContext` for | |
// `tt.name`. | |
if (prevType === types$1._return || prevType === types$1.name && this.exprAllowed) | |
{ return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } | |
if (prevType === types$1._else || prevType === types$1.semi || prevType === types$1.eof || prevType === types$1.parenR || prevType === types$1.arrow) | |
{ return true } | |
if (prevType === types$1.braceL) | |
{ return parent === types.b_stat } | |
if (prevType === types$1._var || prevType === types$1._const || prevType === types$1.name) | |
{ return false } | |
return !this.exprAllowed | |
}; | |
pp$6.inGeneratorContext = function() { | |
for (var i = this.context.length - 1; i >= 1; i--) { | |
var context = this.context[i]; | |
if (context.token === "function") | |
{ return context.generator } | |
} | |
return false | |
}; | |
pp$6.updateContext = function(prevType) { | |
var update, type = this.type; | |
if (type.keyword && prevType === types$1.dot) | |
{ this.exprAllowed = false; } | |
else if (update = type.updateContext) | |
{ update.call(this, prevType); } | |
else | |
{ this.exprAllowed = type.beforeExpr; } | |
}; | |
// Used to handle egde case when token context could not be inferred correctly in tokenize phase | |
pp$6.overrideContext = function(tokenCtx) { | |
if (this.curContext() !== tokenCtx) { | |
this.context[this.context.length - 1] = tokenCtx; | |
} | |
}; | |
// Token-specific context update code | |
types$1.parenR.updateContext = types$1.braceR.updateContext = function() { | |
if (this.context.length === 1) { | |
this.exprAllowed = true; | |
return | |
} | |
var out = this.context.pop(); | |
if (out === types.b_stat && this.curContext().token === "function") { | |
out = this.context.pop(); | |
} | |
this.exprAllowed = !out.isExpr; | |
}; | |
types$1.braceL.updateContext = function(prevType) { | |
this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr); | |
this.exprAllowed = true; | |
}; | |
types$1.dollarBraceL.updateContext = function() { | |
this.context.push(types.b_tmpl); | |
this.exprAllowed = true; | |
}; | |
types$1.parenL.updateContext = function(prevType) { | |
var statementParens = prevType === types$1._if || prevType === types$1._for || prevType === types$1._with || prevType === types$1._while; | |
this.context.push(statementParens ? types.p_stat : types.p_expr); | |
this.exprAllowed = true; | |
}; | |
types$1.incDec.updateContext = function() { | |
// tokExprAllowed stays unchanged | |
}; | |
types$1._function.updateContext = types$1._class.updateContext = function(prevType) { | |
if (prevType.beforeExpr && prevType !== types$1._else && | |
!(prevType === types$1.semi && this.curContext() !== types.p_stat) && | |
!(prevType === types$1._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) && | |
!((prevType === types$1.colon || prevType === types$1.braceL) && this.curContext() === types.b_stat)) | |
{ this.context.push(types.f_expr); } | |
else | |
{ this.context.push(types.f_stat); } | |
this.exprAllowed = false; | |
}; | |
types$1.backQuote.updateContext = function() { | |
if (this.curContext() === types.q_tmpl) | |
{ this.context.pop(); } | |
else | |
{ this.context.push(types.q_tmpl); } | |
this.exprAllowed = false; | |
}; | |
types$1.star.updateContext = function(prevType) { | |
if (prevType === types$1._function) { | |
var index = this.context.length - 1; | |
if (this.context[index] === types.f_expr) | |
{ this.context[index] = types.f_expr_gen; } | |
else | |
{ this.context[index] = types.f_gen; } | |
} | |
this.exprAllowed = true; | |
}; | |
types$1.name.updateContext = function(prevType) { | |
var allowed = false; | |
if (this.options.ecmaVersion >= 6 && prevType !== types$1.dot) { | |
if (this.value === "of" && !this.exprAllowed || | |
this.value === "yield" && this.inGeneratorContext()) | |
{ allowed = true; } | |
} | |
this.exprAllowed = allowed; | |
}; | |
// A recursive descent parser operates by defining functions for all | |
var pp$5 = Parser.prototype; | |
// Check if property name clashes with already added. | |
// Object/class getters and setters are not allowed to clash — | |
// either with each other or with an init property — and in | |
// strict mode, init properties are also not allowed to be repeated. | |
pp$5.checkPropClash = function(prop, propHash, refDestructuringErrors) { | |
if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement") | |
{ return } | |
if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) | |
{ return } | |
var key = prop.key; | |
var name; | |
switch (key.type) { | |
case "Identifier": name = key.name; break | |
case "Literal": name = String(key.value); break | |
default: return | |
} | |
var kind = prop.kind; | |
if (this.options.ecmaVersion >= 6) { | |
if (name === "__proto__" && kind === "init") { | |
if (propHash.proto) { | |
if (refDestructuringErrors) { | |
if (refDestructuringErrors.doubleProto < 0) { | |
refDestructuringErrors.doubleProto = key.start; | |
} | |
} else { | |
this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); | |
} | |
} | |
propHash.proto = true; | |
} | |
return | |
} | |
name = "$" + name; | |
var other = propHash[name]; | |
if (other) { | |
var redefinition; | |
if (kind === "init") { | |
redefinition = this.strict && other.init || other.get || other.set; | |
} else { | |
redefinition = other.init || other[kind]; | |
} | |
if (redefinition) | |
{ this.raiseRecoverable(key.start, "Redefinition of property"); } | |
} else { | |
other = propHash[name] = { | |
init: false, | |
get: false, | |
set: false | |
}; | |
} | |
other[kind] = true; | |
}; | |
// ### Expression parsing | |
// These nest, from the most general expression type at the top to | |
// 'atomic', nondivisible expression types at the bottom. Most of | |
// the functions will simply let the function(s) below them parse, | |
// and, *if* the syntactic construct they handle is present, wrap | |
// the AST node that the inner parser gave them in another node. | |
// Parse a full expression. The optional arguments are used to | |
// forbid the `in` operator (in for loops initalization expressions) | |
// and provide reference for storing '=' operator inside shorthand | |
// property assignment in contexts where both object expression | |
// and object pattern might appear (so it's possible to raise | |
// delayed syntax error at correct position). | |
pp$5.parseExpression = function(forInit, refDestructuringErrors) { | |
var startPos = this.start, startLoc = this.startLoc; | |
var expr = this.parseMaybeAssign(forInit, refDestructuringErrors); | |
if (this.type === types$1.comma) { | |
var node = this.startNodeAt(startPos, startLoc); | |
node.expressions = [expr]; | |
while (this.eat(types$1.comma)) { node.expressions.push(this.parseMaybeAssign(forInit, refDestructuringErrors)); } | |
return this.finishNode(node, "SequenceExpression") | |
} | |
return expr | |
}; | |
// Parse an assignment expression. This includes applications of | |
// operators like `+=`. | |
pp$5.parseMaybeAssign = function(forInit, refDestructuringErrors, afterLeftParse) { | |
if (this.isContextual("yield")) { | |
if (this.inGenerator) { return this.parseYield(forInit) } | |
// The tokenizer will assume an expression is allowed after | |
// `yield`, but this isn't that kind of yield | |
else { this.exprAllowed = false; } | |
} | |
var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1, oldDoubleProto = -1; | |
if (refDestructuringErrors) { | |
oldParenAssign = refDestructuringErrors.parenthesizedAssign; | |
oldTrailingComma = refDestructuringErrors.trailingComma; | |
oldDoubleProto = refDestructuringErrors.doubleProto; | |
refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1; | |
} else { | |
refDestructuringErrors = new DestructuringErrors; | |
ownDestructuringErrors = true; | |
} | |
var startPos = this.start, startLoc = this.startLoc; | |
if (this.type === types$1.parenL || this.type === types$1.name) { | |
this.potentialArrowAt = this.start; | |
this.potentialArrowInForAwait = forInit === "await"; | |
} | |
var left = this.parseMaybeConditional(forInit, refDestructuringErrors); | |
if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } | |
if (this.type.isAssign) { | |
var node = this.startNodeAt(startPos, startLoc); | |
node.operator = this.value; | |
if (this.type === types$1.eq) | |
{ left = this.toAssignable(left, false, refDestructuringErrors); } | |
if (!ownDestructuringErrors) { | |
refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1; | |
} | |
if (refDestructuringErrors.shorthandAssign >= left.start) | |
{ refDestructuringErrors.shorthandAssign = -1; } // reset because shorthand default was used correctly | |
if (this.type === types$1.eq) | |
{ this.checkLValPattern(left); } | |
else | |
{ this.checkLValSimple(left); } | |
node.left = left; | |
this.next(); | |
node.right = this.parseMaybeAssign(forInit); | |
if (oldDoubleProto > -1) { refDestructuringErrors.doubleProto = oldDoubleProto; } | |
return this.finishNode(node, "AssignmentExpression") | |
} else { | |
if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } | |
} | |
if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } | |
if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } | |
return left | |
}; | |
// Parse a ternary conditional (`?:`) operator. | |
pp$5.parseMaybeConditional = function(forInit, refDestructuringErrors) { | |
var startPos = this.start, startLoc = this.startLoc; | |
var expr = this.parseExprOps(forInit, refDestructuringErrors); | |
if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } | |
if (this.eat(types$1.question)) { | |
var node = this.startNodeAt(startPos, startLoc); | |
node.test = expr; | |
node.consequent = this.parseMaybeAssign(); | |
this.expect(types$1.colon); | |
node.alternate = this.parseMaybeAssign(forInit); | |
return this.finishNode(node, "ConditionalExpression") | |
} | |
return expr | |
}; | |
// Start the precedence parser. | |
pp$5.parseExprOps = function(forInit, refDestructuringErrors) { | |
var startPos = this.start, startLoc = this.startLoc; | |
var expr = this.parseMaybeUnary(refDestructuringErrors, false, false, forInit); | |
if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } | |
return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, forInit) | |
}; | |
// Parse binary operators with the operator precedence parsing | |
// algorithm. `left` is the left-hand side of the operator. | |
// `minPrec` provides context that allows the function to stop and | |
// defer further parser to one of its callers when it encounters an | |
// operator that has a lower precedence than the set it is parsing. | |
pp$5.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, forInit) { | |
var prec = this.type.binop; | |
if (prec != null && (!forInit || this.type !== types$1._in)) { | |
if (prec > minPrec) { | |
var logical = this.type === types$1.logicalOR || this.type === types$1.logicalAND; | |
var coalesce = this.type === types$1.coalesce; | |
if (coalesce) { | |
// Handle the precedence of `tt.coalesce` as equal to the range of logical expressions. | |
// In other words, `node.right` shouldn't contain logical expressions in order to check the mixed error. | |
prec = types$1.logicalAND.binop; | |
} | |
var op = this.value; | |
this.next(); | |
var startPos = this.start, startLoc = this.startLoc; | |
var right = this.parseExprOp(this.parseMaybeUnary(null, false, false, forInit), startPos, startLoc, prec, forInit); | |
var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce); | |
if ((logical && this.type === types$1.coalesce) || (coalesce && (this.type === types$1.logicalOR || this.type === types$1.logicalAND))) { | |
this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses"); | |
} | |
return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, forInit) | |
} | |
} | |
return left | |
}; | |
pp$5.buildBinary = function(startPos, startLoc, left, right, op, logical) { | |
if (right.type === "PrivateIdentifier") { this.raise(right.start, "Private identifier can only be left side of binary expression"); } | |
var node = this.startNodeAt(startPos, startLoc); | |
node.left = left; | |
node.operator = op; | |
node.right = right; | |
return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") | |
}; | |
// Parse unary operators, both prefix and postfix. | |
pp$5.parseMaybeUnary = function(refDestructuringErrors, sawUnary, incDec, forInit) { | |
var startPos = this.start, startLoc = this.startLoc, expr; | |
if (this.isContextual("await") && this.canAwait) { | |
expr = this.parseAwait(forInit); | |
sawUnary = true; | |
} else if (this.type.prefix) { | |
var node = this.startNode(), update = this.type === types$1.incDec; | |
node.operator = this.value; | |
node.prefix = true; | |
this.next(); | |
node.argument = this.parseMaybeUnary(null, true, update, forInit); | |
this.checkExpressionErrors(refDestructuringErrors, true); | |
if (update) { this.checkLValSimple(node.argument); } | |
else if (this.strict && node.operator === "delete" && | |
node.argument.type === "Identifier") | |
{ this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } | |
else if (node.operator === "delete" && isPrivateFieldAccess(node.argument)) | |
{ this.raiseRecoverable(node.start, "Private fields can not be deleted"); } | |
else { sawUnary = true; } | |
expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); | |
} else if (!sawUnary && this.type === types$1.privateId) { | |
if (forInit || this.privateNameStack.length === 0) { this.unexpected(); } | |
expr = this.parsePrivateIdent(); | |
// only could be private fields in 'in', such as #x in obj | |
if (this.type !== types$1._in) { this.unexpected(); } | |
} else { | |
expr = this.parseExprSubscripts(refDestructuringErrors, forInit); | |
if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } | |
while (this.type.postfix && !this.canInsertSemicolon()) { | |
var node$1 = this.startNodeAt(startPos, startLoc); | |
node$1.operator = this.value; | |
node$1.prefix = false; | |
node$1.argument = expr; | |
this.checkLValSimple(expr); | |
this.next(); | |
expr = this.finishNode(node$1, "UpdateExpression"); | |
} | |
} | |
if (!incDec && this.eat(types$1.starstar)) { | |
if (sawUnary) | |
{ this.unexpected(this.lastTokStart); } | |
else | |
{ return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false, false, forInit), "**", false) } | |
} else { | |
return expr | |
} | |
}; | |
function isPrivateFieldAccess(node) { | |
return ( | |
node.type === "MemberExpression" && node.property.type === "PrivateIdentifier" || | |
node.type === "ChainExpression" && isPrivateFieldAccess(node.expression) | |
) | |
} | |
// Parse call, dot, and `[]`-subscript expressions. | |
pp$5.parseExprSubscripts = function(refDestructuringErrors, forInit) { | |
var startPos = this.start, startLoc = this.startLoc; | |
var expr = this.parseExprAtom(refDestructuringErrors, forInit); | |
if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")") | |
{ return expr } | |
var result = this.parseSubscripts(expr, startPos, startLoc, false, forInit); | |
if (refDestructuringErrors && result.type === "MemberExpression") { | |
if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } | |
if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } | |
if (refDestructuringErrors.trailingComma >= result.start) { refDestructuringErrors.trailingComma = -1; } | |
} | |
return result | |
}; | |
pp$5.parseSubscripts = function(base, startPos, startLoc, noCalls, forInit) { | |
var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && | |
this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 && | |
this.potentialArrowAt === base.start; | |
var optionalChained = false; | |
while (true) { | |
var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit); | |
if (element.optional) { optionalChained = true; } | |
if (element === base || element.type === "ArrowFunctionExpression") { | |
if (optionalChained) { | |
var chainNode = this.startNodeAt(startPos, startLoc); | |
chainNode.expression = element; | |
element = this.finishNode(chainNode, "ChainExpression"); | |
} | |
return element | |
} | |
base = element; | |
} | |
}; | |
pp$5.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) { | |
var optionalSupported = this.options.ecmaVersion >= 11; | |
var optional = optionalSupported && this.eat(types$1.questionDot); | |
if (noCalls && optional) { this.raise(this.lastTokStart, "Optional chaining cannot appear in the callee of new expressions"); } | |
var computed = this.eat(types$1.bracketL); | |
if (computed || (optional && this.type !== types$1.parenL && this.type !== types$1.backQuote) || this.eat(types$1.dot)) { | |
var node = this.startNodeAt(startPos, startLoc); | |
node.object = base; | |
if (computed) { | |
node.property = this.parseExpression(); | |
this.expect(types$1.bracketR); | |
} else if (this.type === types$1.privateId && base.type !== "Super") { | |
node.property = this.parsePrivateIdent(); | |
} else { | |
node.property = this.parseIdent(this.options.allowReserved !== "never"); | |
} | |
node.computed = !!computed; | |
if (optionalSupported) { | |
node.optional = optional; | |
} | |
base = this.finishNode(node, "MemberExpression"); | |
} else if (!noCalls && this.eat(types$1.parenL)) { | |
var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; | |
this.yieldPos = 0; | |
this.awaitPos = 0; | |
this.awaitIdentPos = 0; | |
var exprList = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors); | |
if (maybeAsyncArrow && !optional && !this.canInsertSemicolon() && this.eat(types$1.arrow)) { | |
this.checkPatternErrors(refDestructuringErrors, false); | |
this.checkYieldAwaitInDefaultParams(); | |
if (this.awaitIdentPos > 0) | |
{ this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); } | |
this.yieldPos = oldYieldPos; | |
this.awaitPos = oldAwaitPos; | |
this.awaitIdentPos = oldAwaitIdentPos; | |
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true, forInit) | |
} | |
this.checkExpressionErrors(refDestructuringErrors, true); | |
this.yieldPos = oldYieldPos || this.yieldPos; | |
this.awaitPos = oldAwaitPos || this.awaitPos; | |
this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos; | |
var node$1 = this.startNodeAt(startPos, startLoc); | |
node$1.callee = base; | |
node$1.arguments = exprList; | |
if (optionalSupported) { | |
node$1.optional = optional; | |
} | |
base = this.finishNode(node$1, "CallExpression"); | |
} else if (this.type === types$1.backQuote) { | |
if (optional || optionalChained) { | |
this.raise(this.start, "Optional chaining cannot appear in the tag of tagged template expressions"); | |
} | |
var node$2 = this.startNodeAt(startPos, startLoc); | |
node$2.tag = base; | |
node$2.quasi = this.parseTemplate({isTagged: true}); | |
base = this.finishNode(node$2, "TaggedTemplateExpression"); | |
} | |
return base | |
}; | |
// Parse an atomic expression — either a single token that is an | |
// expression, an expression started by a keyword like `function` or | |
// `new`, or an expression wrapped in punctuation like `()`, `[]`, | |
// or `{}`. | |
pp$5.parseExprAtom = function(refDestructuringErrors, forInit) { | |
// If a division operator appears in an expression position, the | |
// tokenizer got confused, and we force it to read a regexp instead. | |
if (this.type === types$1.slash) { this.readRegexp(); } | |
var node, canBeArrow = this.potentialArrowAt === this.start; | |
switch (this.type) { | |
case types$1._super: | |
if (!this.allowSuper) | |
{ this.raise(this.start, "'super' keyword outside a method"); } | |
node = this.startNode(); | |
this.next(); | |
if (this.type === types$1.parenL && !this.allowDirectSuper) | |
{ this.raise(node.start, "super() call outside constructor of a subclass"); } | |
// The `super` keyword can appear at below: | |
// SuperProperty: | |
// super [ Expression ] | |
// super . IdentifierName | |
// SuperCall: | |
// super ( Arguments ) | |
if (this.type !== types$1.dot && this.type !== types$1.bracketL && this.type !== types$1.parenL) | |
{ this.unexpected(); } | |
return this.finishNode(node, "Super") | |
case types$1._this: | |
node = this.startNode(); | |
this.next(); | |
return this.finishNode(node, "ThisExpression") | |
case types$1.name: | |
var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc; | |
var id = this.parseIdent(false); | |
if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types$1._function)) { | |
this.overrideContext(types.f_expr); | |
return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true, forInit) | |
} | |
if (canBeArrow && !this.canInsertSemicolon()) { | |
if (this.eat(types$1.arrow)) | |
{ return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false, forInit) } | |
if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types$1.name && !containsEsc && | |
(!this.potentialArrowInForAwait || this.value !== "of" || this.containsEsc)) { | |
id = this.parseIdent(false); | |
if (this.canInsertSemicolon() || !this.eat(types$1.arrow)) | |
{ this.unexpected(); } | |
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true, forInit) | |
} | |
} | |
return id | |
case types$1.regexp: | |
var value = this.value; | |
node = this.parseLiteral(value.value); | |
node.regex = {pattern: value.pattern, flags: value.flags}; | |
return node | |
case types$1.num: case types$1.string: | |
return this.parseLiteral(this.value) | |
case types$1._null: case types$1._true: case types$1._false: | |
node = this.startNode(); | |
node.value = this.type === types$1._null ? null : this.type === types$1._true; | |
node.raw = this.type.keyword; | |
this.next(); | |
return this.finishNode(node, "Literal") | |
case types$1.parenL: | |
var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow, forInit); | |
if (refDestructuringErrors) { | |
if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) | |
{ refDestructuringErrors.parenthesizedAssign = start; } | |
if (refDestructuringErrors.parenthesizedBind < 0) | |
{ refDestructuringErrors.parenthesizedBind = start; } | |
} | |
return expr | |
case types$1.bracketL: | |
node = this.startNode(); | |
this.next(); | |
node.elements = this.parseExprList(types$1.bracketR, true, true, refDestructuringErrors); | |
return this.finishNode(node, "ArrayExpression") | |
case types$1.braceL: | |
this.overrideContext(types.b_expr); | |
return this.parseObj(false, refDestructuringErrors) | |
case types$1._function: | |
node = this.startNode(); | |
this.next(); | |
return this.parseFunction(node, 0) | |
case types$1._class: | |
return this.parseClass(this.startNode(), false) | |
case types$1._new: | |
return this.parseNew() | |
case types$1.backQuote: | |
return this.parseTemplate() | |
case types$1._import: | |
if (this.options.ecmaVersion >= 11) { | |
return this.parseExprImport() | |
} else { | |
return this.unexpected() | |
} | |
default: | |
this.unexpected(); | |
} | |
}; | |
pp$5.parseExprImport = function() { | |
var node = this.startNode(); | |
// Consume `import` as an identifier for `import.meta`. | |
// Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`. | |
if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import"); } | |
var meta = this.parseIdent(true); | |
switch (this.type) { | |
case types$1.parenL: | |
return this.parseDynamicImport(node) | |
case types$1.dot: | |
node.meta = meta; | |
return this.parseImportMeta(node) | |
default: | |
this.unexpected(); | |
} | |
}; | |
pp$5.parseDynamicImport = function(node) { | |
this.next(); // skip `(` | |
// Parse node.source. | |
node.source = this.parseMaybeAssign(); | |
// Verify ending. | |
if (!this.eat(types$1.parenR)) { | |
var errorPos = this.start; | |
if (this.eat(types$1.comma) && this.eat(types$1.parenR)) { | |
this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()"); | |
} else { | |
this.unexpected(errorPos); | |
} | |
} | |
return this.finishNode(node, "ImportExpression") | |
}; | |
pp$5.parseImportMeta = function(node) { | |
this.next(); // skip `.` | |
var containsEsc = this.containsEsc; | |
node.property = this.parseIdent(true); | |
if (node.property.name !== "meta") | |
{ this.raiseRecoverable(node.property.start, "The only valid meta property for import is 'import.meta'"); } | |
if (containsEsc) | |
{ this.raiseRecoverable(node.start, "'import.meta' must not contain escaped characters"); } | |
if (this.options.sourceType !== "module" && !this.options.allowImportExportEverywhere) | |
{ this.raiseRecoverable(node.start, "Cannot use 'import.meta' outside a module"); } | |
return this.finishNode(node, "MetaProperty") | |
}; | |
pp$5.parseLiteral = function(value) { | |
var node = this.startNode(); | |
node.value = value; | |
node.raw = this.input.slice(this.start, this.end); | |
if (node.raw.charCodeAt(node.raw.length - 1) === 110) { node.bigint = node.raw.slice(0, -1).replace(/_/g, ""); } | |
this.next(); | |
return this.finishNode(node, "Literal") | |
}; | |
pp$5.parseParenExpression = function() { | |
this.expect(types$1.parenL); | |
var val = this.parseExpression(); | |
this.expect(types$1.parenR); | |
return val | |
}; | |
pp$5.parseParenAndDistinguishExpression = function(canBeArrow, forInit) { | |
var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; | |
if (this.options.ecmaVersion >= 6) { | |
this.next(); | |
var innerStartPos = this.start, innerStartLoc = this.startLoc; | |
var exprList = [], first = true, lastIsComma = false; | |
var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart; | |
this.yieldPos = 0; | |
this.awaitPos = 0; | |
// Do not save awaitIdentPos to allow checking awaits nested in parameters | |
while (this.type !== types$1.parenR) { | |
first ? first = false : this.expect(types$1.comma); | |
if (allowTrailingComma && this.afterTrailingComma(types$1.parenR, true)) { | |
lastIsComma = true; | |
break | |
} else if (this.type === types$1.ellipsis) { | |
spreadStart = this.start; | |
exprList.push(this.parseParenItem(this.parseRestBinding())); | |
if (this.type === types$1.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); } | |
break | |
} else { | |
exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); | |
} | |
} | |
var innerEndPos = this.lastTokEnd, innerEndLoc = this.lastTokEndLoc; | |
this.expect(types$1.parenR); | |
if (canBeArrow && !this.canInsertSemicolon() && this.eat(types$1.arrow)) { | |
this.checkPatternErrors(refDestructuringErrors, false); | |
this.checkYieldAwaitInDefaultParams(); | |
this.yieldPos = oldYieldPos; | |
this.awaitPos = oldAwaitPos; | |
return this.parseParenArrowList(startPos, startLoc, exprList, forInit) | |
} | |
if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } | |
if (spreadStart) { this.unexpected(spreadStart); } | |
this.checkExpressionErrors(refDestructuringErrors, true); | |
this.yieldPos = oldYieldPos || this.yieldPos; | |
this.awaitPos = oldAwaitPos || this.awaitPos; | |
if (exprList.length > 1) { | |
val = this.startNodeAt(innerStartPos, innerStartLoc); | |
val.expressions = exprList; | |
this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); | |
} else { | |
val = exprList[0]; | |
} | |
} else { | |
val = this.parseParenExpression(); | |
} | |
if (this.options.preserveParens) { | |
var par = this.startNodeAt(startPos, startLoc); | |
par.expression = val; | |
return this.finishNode(par, "ParenthesizedExpression") | |
} else { | |
return val | |
} | |
}; | |
pp$5.parseParenItem = function(item) { | |
return item | |
}; | |
pp$5.parseParenArrowList = function(startPos, startLoc, exprList, forInit) { | |
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, false, forInit) | |
}; | |
// New's precedence is slightly tricky. It must allow its argument to | |
// be a `[]` or dot subscript expression, but not a call — at least, | |
// not without wrapping it in parentheses. Thus, it uses the noCalls | |
// argument to parseSubscripts to prevent it from consuming the | |
// argument list. | |
var empty = []; | |
pp$5.parseNew = function() { | |
if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); } | |
var node = this.startNode(); | |
var meta = this.parseIdent(true); | |
if (this.options.ecmaVersion >= 6 && this.eat(types$1.dot)) { | |
node.meta = meta; | |
var containsEsc = this.containsEsc; | |
node.property = this.parseIdent(true); | |
if (node.property.name !== "target") | |
{ this.raiseRecoverable(node.property.start, "The only valid meta property for new is 'new.target'"); } | |
if (containsEsc) | |
{ this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters"); } | |
if (!this.allowNewDotTarget) | |
{ this.raiseRecoverable(node.start, "'new.target' can only be used in functions and class static block"); } | |
return this.finishNode(node, "MetaProperty") | |
} | |
var startPos = this.start, startLoc = this.startLoc, isImport = this.type === types$1._import; | |
node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true, false); | |
if (isImport && node.callee.type === "ImportExpression") { | |
this.raise(startPos, "Cannot use new with import()"); | |
} | |
if (this.eat(types$1.parenL)) { node.arguments = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false); } | |
else { node.arguments = empty; } | |
return this.finishNode(node, "NewExpression") | |
}; | |
// Parse template expression. | |
pp$5.parseTemplateElement = function(ref) { | |
var isTagged = ref.isTagged; | |
var elem = this.startNode(); | |
if (this.type === types$1.invalidTemplate) { | |
if (!isTagged) { | |
this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); | |
} | |
elem.value = { | |
raw: this.value, | |
cooked: null | |
}; | |
} else { | |
elem.value = { | |
raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), | |
cooked: this.value | |
}; | |
} | |
this.next(); | |
elem.tail = this.type === types$1.backQuote; | |
return this.finishNode(elem, "TemplateElement") | |
}; | |
pp$5.parseTemplate = function(ref) { | |
if ( ref === void 0 ) ref = {}; | |
var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false; | |
var node = this.startNode(); | |
this.next(); | |
node.expressions = []; | |
var curElt = this.parseTemplateElement({isTagged: isTagged}); | |
node.quasis = [curElt]; | |
while (!curElt.tail) { | |
if (this.type === types$1.eof) { this.raise(this.pos, "Unterminated template literal"); } | |
this.expect(types$1.dollarBraceL); | |
node.expressions.push(this.parseExpression()); | |
this.expect(types$1.braceR); | |
node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged})); | |
} | |
this.next(); | |
return this.finishNode(node, "TemplateLiteral") | |
}; | |
pp$5.isAsyncProp = function(prop) { | |
return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && | |
(this.type === types$1.name || this.type === types$1.num || this.type === types$1.string || this.type === types$1.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types$1.star)) && | |
!lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) | |
}; | |
// Parse an object literal or binding pattern. | |
pp$5.parseObj = function(isPattern, refDestructuringErrors) { | |
var node = this.startNode(), first = true, propHash = {}; | |
node.properties = []; | |
this.next(); | |
while (!this.eat(types$1.braceR)) { | |
if (!first) { | |
this.expect(types$1.comma); | |
if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types$1.braceR)) { break } | |
} else { first = false; } | |
var prop = this.parseProperty(isPattern, refDestructuringErrors); | |
if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); } | |
node.properties.push(prop); | |
} | |
return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") | |
}; | |
pp$5.parseProperty = function(isPattern, refDestructuringErrors) { | |
var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc; | |
if (this.options.ecmaVersion >= 9 && this.eat(types$1.ellipsis)) { | |
if (isPattern) { | |
prop.argument = this.parseIdent(false); | |
if (this.type === types$1.comma) { | |
this.raise(this.start, "Comma is not permitted after the rest element"); | |
} | |
return this.finishNode(prop, "RestElement") | |
} | |
// To disallow parenthesized identifier via `this.toAssignable()`. | |
if (this.type === types$1.parenL && refDestructuringErrors) { | |
if (refDestructuringErrors.parenthesizedAssign < 0) { | |
refDestructuringErrors.parenthesizedAssign = this.start; | |
} | |
if (refDestructuringErrors.parenthesizedBind < 0) { | |
refDestructuringErrors.parenthesizedBind = this.start; | |
} | |
} | |
// Parse argument. | |
prop.argument = this.parseMaybeAssign(false, refDestructuringErrors); | |
// To disallow trailing comma via `this.toAssignable()`. | |
if (this.type === types$1.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) { | |
refDestructuringErrors.trailingComma = this.start; | |
} | |
// Finish | |
return this.finishNode(prop, "SpreadElement") | |
} | |
if (this.options.ecmaVersion >= 6) { | |
prop.method = false; | |
prop.shorthand = false; | |
if (isPattern || refDestructuringErrors) { | |
startPos = this.start; | |
startLoc = this.startLoc; | |
} | |
if (!isPattern) | |
{ isGenerator = this.eat(types$1.star); } | |
} | |
var containsEsc = this.containsEsc; | |
this.parsePropertyName(prop); | |
if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { | |
isAsync = true; | |
isGenerator = this.options.ecmaVersion >= 9 && this.eat(types$1.star); | |
this.parsePropertyName(prop, refDestructuringErrors); | |
} else { | |
isAsync = false; | |
} | |
this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc); | |
return this.finishNode(prop, "Property") | |
}; | |
pp$5.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) { | |
if ((isGenerator || isAsync) && this.type === types$1.colon) | |
{ this.unexpected(); } | |
if (this.eat(types$1.colon)) { | |
prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); | |
prop.kind = "init"; | |
} else if (this.options.ecmaVersion >= 6 && this.type === types$1.parenL) { | |
if (isPattern) { this.unexpected(); } | |
prop.kind = "init"; | |
prop.method = true; | |
prop.value = this.parseMethod(isGenerator, isAsync); | |
} else if (!isPattern && !containsEsc && | |
this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && | |
(prop.key.name === "get" || prop.key.name === "set") && | |
(this.type !== types$1.comma && this.type !== types$1.braceR && this.type !== types$1.eq)) { | |
if (isGenerator || isAsync) { this.unexpected(); } | |
prop.kind = prop.key.name; | |
this.parsePropertyName(prop); | |
prop.value = this.parseMethod(false); | |
var paramCount = prop.kind === "get" ? 0 : 1; | |
if (prop.value.params.length !== paramCount) { | |
var start = prop.value.start; | |
if (prop.kind === "get") | |
{ this.raiseRecoverable(start, "getter should have no params"); } | |
else | |
{ this.raiseRecoverable(start, "setter should have exactly one param"); } | |
} else { | |
if (prop.kind === "set" && prop.value.params[0].type === "RestElement") | |
{ this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } | |
} | |
} else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { | |
if (isGenerator || isAsync) { this.unexpected(); } | |
this.checkUnreserved(prop.key); | |
if (prop.key.name === "await" && !this.awaitIdentPos) | |
{ this.awaitIdentPos = startPos; } | |
prop.kind = "init"; | |
if (isPattern) { | |
prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key)); | |
} else if (this.type === types$1.eq && refDestructuringErrors) { | |
if (refDestructuringErrors.shorthandAssign < 0) | |
{ refDestructuringErrors.shorthandAssign = this.start; } | |
prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key)); | |
} else { | |
prop.value = this.copyNode(prop.key); | |
} | |
prop.shorthand = true; | |
} else { this.unexpected(); } | |
}; | |
pp$5.parsePropertyName = function(prop) { | |
if (this.options.ecmaVersion >= 6) { | |
if (this.eat(types$1.bracketL)) { | |
prop.computed = true; | |
prop.key = this.parseMaybeAssign(); | |
this.expect(types$1.bracketR); | |
return prop.key | |
} else { | |
prop.computed = false; | |
} | |
} | |
return prop.key = this.type === types$1.num || this.type === types$1.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never") | |
}; | |
// Initialize empty function node. | |
pp$5.initFunction = function(node) { | |
node.id = null; | |
if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; } | |
if (this.options.ecmaVersion >= 8) { node.async = false; } | |
}; | |
// Parse object or class method. | |
pp$5.parseMethod = function(isGenerator, isAsync, allowDirectSuper) { | |
var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; | |
this.initFunction(node); | |
if (this.options.ecmaVersion >= 6) | |
{ node.generator = isGenerator; } | |
if (this.options.ecmaVersion >= 8) | |
{ node.async = !!isAsync; } | |
this.yieldPos = 0; | |
this.awaitPos = 0; | |
this.awaitIdentPos = 0; | |
this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0)); | |
this.expect(types$1.parenL); | |
node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8); | |
this.checkYieldAwaitInDefaultParams(); | |
this.parseFunctionBody(node, false, true, false); | |
this.yieldPos = oldYieldPos; | |
this.awaitPos = oldAwaitPos; | |
this.awaitIdentPos = oldAwaitIdentPos; | |
return this.finishNode(node, "FunctionExpression") | |
}; | |
// Parse arrow function expression with given parameters. | |
pp$5.parseArrowExpression = function(node, params, isAsync, forInit) { | |
var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; | |
this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW); | |
this.initFunction(node); | |
if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } | |
this.yieldPos = 0; | |
this.awaitPos = 0; | |
this.awaitIdentPos = 0; | |
node.params = this.toAssignableList(params, true); | |
this.parseFunctionBody(node, true, false, forInit); | |
this.yieldPos = oldYieldPos; | |
this.awaitPos = oldAwaitPos; | |
this.awaitIdentPos = oldAwaitIdentPos; | |
return this.finishNode(node, "ArrowFunctionExpression") | |
}; | |
// Parse function body and check parameters. | |
pp$5.parseFunctionBody = function(node, isArrowFunction, isMethod, forInit) { | |
var isExpression = isArrowFunction && this.type !== types$1.braceL; | |
var oldStrict = this.strict, useStrict = false; | |
if (isExpression) { | |
node.body = this.parseMaybeAssign(forInit); | |
node.expression = true; | |
this.checkParams(node, false); | |
} else { | |
var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); | |
if (!oldStrict || nonSimple) { | |
useStrict = this.strictDirective(this.end); | |
// If this is a strict mode function, verify that argument names | |
// are not repeated, and it does not try to bind the words `eval` | |
// or `arguments`. | |
if (useStrict && nonSimple) | |
{ this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } | |
} | |
// Start a new scope with regard to labels and the `inFunction` | |
// flag (restore them to their old value afterwards). | |
var oldLabels = this.labels; | |
this.labels = []; | |
if (useStrict) { this.strict = true; } | |
// Add the params to varDeclaredNames to ensure that an error is thrown | |
// if a let/const declaration in the function clashes with one of the params. | |
this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params)); | |
// Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' | |
if (this.strict && node.id) { this.checkLValSimple(node.id, BIND_OUTSIDE); } | |
node.body = this.parseBlock(false, undefined, useStrict && !oldStrict); | |
node.expression = false; | |
this.adaptDirectivePrologue(node.body.body); | |
this.labels = oldLabels; | |
} | |
this.exitScope(); | |
}; | |
pp$5.isSimpleParamList = function(params) { | |
for (var i = 0, list = params; i < list.length; i += 1) | |
{ | |
var param = list[i]; | |
if (param.type !== "Identifier") { return false | |
} } | |
return true | |
}; | |
// Checks function params for various disallowed patterns such as using "eval" | |
// or "arguments" and duplicate parameters. | |
pp$5.checkParams = function(node, allowDuplicates) { | |
var nameHash = Object.create(null); | |
for (var i = 0, list = node.params; i < list.length; i += 1) | |
{ | |
var param = list[i]; | |
this.checkLValInnerPattern(param, BIND_VAR, allowDuplicates ? null : nameHash); | |
} | |
}; | |
// Parses a comma-separated list of expressions, and returns them as | |
// an array. `close` is the token type that ends the list, and | |
// `allowEmpty` can be turned on to allow subsequent commas with | |
// nothing in between them to be parsed as `null` (which is needed | |
// for array literals). | |
pp$5.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { | |
var elts = [], first = true; | |
while (!this.eat(close)) { | |
if (!first) { | |
this.expect(types$1.comma); | |
if (allowTrailingComma && this.afterTrailingComma(close)) { break } | |
} else { first = false; } | |
var elt = (void 0); | |
if (allowEmpty && this.type === types$1.comma) | |
{ elt = null; } | |
else if (this.type === types$1.ellipsis) { | |
elt = this.parseSpread(refDestructuringErrors); | |
if (refDestructuringErrors && this.type === types$1.comma && refDestructuringErrors.trailingComma < 0) | |
{ refDestructuringErrors.trailingComma = this.start; } | |
} else { | |
elt = this.parseMaybeAssign(false, refDestructuringErrors); | |
} | |
elts.push(elt); | |
} | |
return elts | |
}; | |
pp$5.checkUnreserved = function(ref) { | |
var start = ref.start; | |
var end = ref.end; | |
var name = ref.name; | |
if (this.inGenerator && name === "yield") | |
{ this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); } | |
if (this.inAsync && name === "await") | |
{ this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); } | |
if (this.currentThisScope().inClassFieldInit && name === "arguments") | |
{ this.raiseRecoverable(start, "Cannot use 'arguments' in class field initializer"); } | |
if (this.inClassStaticBlock && (name === "arguments" || name === "await")) | |
{ this.raise(start, ("Cannot use " + name + " in class static initialization block")); } | |
if (this.keywords.test(name)) | |
{ this.raise(start, ("Unexpected keyword '" + name + "'")); } | |
if (this.options.ecmaVersion < 6 && | |
this.input.slice(start, end).indexOf("\\") !== -1) { return } | |
var re = this.strict ? this.reservedWordsStrict : this.reservedWords; | |
if (re.test(name)) { | |
if (!this.inAsync && name === "await") | |
{ this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); } | |
this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); | |
} | |
}; | |
// Parse the next token as an identifier. If `liberal` is true (used | |
// when parsing properties), it will also convert keywords into | |
// identifiers. | |
pp$5.parseIdent = function(liberal, isBinding) { | |
var node = this.startNode(); | |
if (this.type === types$1.name) { | |
node.name = this.value; | |
} else if (this.type.keyword) { | |
node.name = this.type.keyword; | |
// To fix https://github.com/acornjs/acorn/issues/575 | |
// `class` and `function` keywords push new context into this.context. | |
// But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name. | |
// If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword | |
if ((node.name === "class" || node.name === "function") && | |
(this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { | |
this.context.pop(); | |
} | |
} else { | |
this.unexpected(); | |
} | |
this.next(!!liberal); | |
this.finishNode(node, "Identifier"); | |
if (!liberal) { | |
this.checkUnreserved(node); | |
if (node.name === "await" && !this.awaitIdentPos) | |
{ this.awaitIdentPos = node.start; } | |
} | |
return node | |
}; | |
pp$5.parsePrivateIdent = function() { | |
var node = this.startNode(); | |
if (this.type === types$1.privateId) { | |
node.name = this.value; | |
} else { | |
this.unexpected(); | |
} | |
this.next(); | |
this.finishNode(node, "PrivateIdentifier"); | |
// For validating existence | |
if (this.privateNameStack.length === 0) { | |
this.raise(node.start, ("Private field '#" + (node.name) + "' must be declared in an enclosing class")); | |
} else { | |
this.privateNameStack[this.privateNameStack.length - 1].used.push(node); | |
} | |
return node | |
}; | |
// Parses yield expression inside generator. | |
pp$5.parseYield = function(forInit) { | |
if (!this.yieldPos) { this.yieldPos = this.start; } | |
var node = this.startNode(); | |
this.next(); | |
if (this.type === types$1.semi || this.canInsertSemicolon() || (this.type !== types$1.star && !this.type.startsExpr)) { | |
node.delegate = false; | |
node.argument = null; | |
} else { | |
node.delegate = this.eat(types$1.star); | |
node.argument = this.parseMaybeAssign(forInit); | |
} | |
return this.finishNode(node, "YieldExpression") | |
}; | |
pp$5.parseAwait = function(forInit) { | |
if (!this.awaitPos) { this.awaitPos = this.start; } | |
var node = this.startNode(); | |
this.next(); | |
node.argument = this.parseMaybeUnary(null, true, false, forInit); | |
return this.finishNode(node, "AwaitExpression") | |
}; | |
var pp$4 = Parser.prototype; | |
// This function is used to raise exceptions on parse errors. It | |
// takes an offset integer (into the current `input`) to indicate | |
// the location of the error, attaches the position to the end | |
// of the error message, and then raises a `SyntaxError` with that | |
// message. | |
pp$4.raise = function(pos, message) { | |
var loc = getLineInfo(this.input, pos); | |
message += " (" + loc.line + ":" + loc.column + ")"; | |
var err = new SyntaxError(message); | |
err.pos = pos; err.loc = loc; err.raisedAt = this.pos; | |
throw err | |
}; | |
pp$4.raiseRecoverable = pp$4.raise; | |
pp$4.curPosition = function() { | |
if (this.options.locations) { | |
return new Position(this.curLine, this.pos - this.lineStart) | |
} | |
}; | |
var pp$3 = Parser.prototype; | |
var Scope = function Scope(flags) { | |
this.flags = flags; | |
// A list of var-declared names in the current lexical scope | |
this.var = []; | |
// A list of lexically-declared names in the current lexical scope | |
this.lexical = []; | |
// A list of lexically-declared FunctionDeclaration names in the current lexical scope | |
this.functions = []; | |
// A switch to disallow the identifier reference 'arguments' | |
this.inClassFieldInit = false; | |
}; | |
// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. | |
pp$3.enterScope = function(flags) { | |
this.scopeStack.push(new Scope(flags)); | |
}; | |
pp$3.exitScope = function() { | |
this.scopeStack.pop(); | |
}; | |
// The spec says: | |
// > At the top level of a function, or script, function declarations are | |
// > treated like var declarations rather than like lexical declarations. | |
pp$3.treatFunctionsAsVarInScope = function(scope) { | |
return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP) | |
}; | |
pp$3.declareName = function(name, bindingType, pos) { | |
var redeclared = false; | |
if (bindingType === BIND_LEXICAL) { | |
var scope = this.currentScope(); | |
redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1; | |
scope.lexical.push(name); | |
if (this.inModule && (scope.flags & SCOPE_TOP)) | |
{ delete this.undefinedExports[name]; } | |
} else if (bindingType === BIND_SIMPLE_CATCH) { | |
var scope$1 = this.currentScope(); | |
scope$1.lexical.push(name); | |
} else if (bindingType === BIND_FUNCTION) { | |
var scope$2 = this.currentScope(); | |
if (this.treatFunctionsAsVar) | |
{ redeclared = scope$2.lexical.indexOf(name) > -1; } | |
else | |
{ redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; } | |
scope$2.functions.push(name); | |
} else { | |
for (var i = this.scopeStack.length - 1; i >= 0; --i) { | |
var scope$3 = this.scopeStack[i]; | |
if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) || | |
!this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) { | |
redeclared = true; | |
break | |
} | |
scope$3.var.push(name); | |
if (this.inModule && (scope$3.flags & SCOPE_TOP)) | |
{ delete this.undefinedExports[name]; } | |
if (scope$3.flags & SCOPE_VAR) { break } | |
} | |
} | |
if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); } | |
}; | |
pp$3.checkLocalExport = function(id) { | |
// scope.functions must be empty as Module code is always strict. | |
if (this.scopeStack[0].lexical.indexOf(id.name) === -1 && | |
this.scopeStack[0].var.indexOf(id.name) === -1) { | |
this.undefinedExports[id.name] = id; | |
} | |
}; | |
pp$3.currentScope = function() { | |
return this.scopeStack[this.scopeStack.length - 1] | |
}; | |
pp$3.currentVarScope = function() { | |
for (var i = this.scopeStack.length - 1;; i--) { | |
var scope = this.scopeStack[i]; | |
if (scope.flags & SCOPE_VAR) { return scope } | |
} | |
}; | |
// Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`. | |
pp$3.currentThisScope = function() { | |
for (var i = this.scopeStack.length - 1;; i--) { | |
var scope = this.scopeStack[i]; | |
if (scope.flags & SCOPE_VAR && !(scope.flags & SCOPE_ARROW)) { return scope } | |
} | |
}; | |
var Node = function Node(parser, pos, loc) { | |
this.type = ""; | |
this.start = pos; | |
this.end = 0; | |
if (parser.options.locations) | |
{ this.loc = new SourceLocation(parser, loc); } | |
if (parser.options.directSourceFile) | |
{ this.sourceFile = parser.options.directSourceFile; } | |
if (parser.options.ranges) | |
{ this.range = [pos, 0]; } | |
}; | |
// Start an AST node, attaching a start offset. | |
var pp$2 = Parser.prototype; | |
pp$2.startNode = function() { | |
return new Node(this, this.start, this.startLoc) | |
}; | |
pp$2.startNodeAt = function(pos, loc) { | |
return new Node(this, pos, loc) | |
}; | |
// Finish an AST node, adding `type` and `end` properties. | |
function finishNodeAt(node, type, pos, loc) { | |
node.type = type; | |
node.end = pos; | |
if (this.options.locations) | |
{ node.loc.end = loc; } | |
if (this.options.ranges) | |
{ node.range[1] = pos; } | |
return node | |
} | |
pp$2.finishNode = function(node, type) { | |
return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) | |
}; | |
// Finish node at given position | |
pp$2.finishNodeAt = function(node, type, pos, loc) { | |
return finishNodeAt.call(this, node, type, pos, loc) | |
}; | |
pp$2.copyNode = function(node) { | |
var newNode = new Node(this, node.start, this.startLoc); | |
for (var prop in node) { newNode[prop] = node[prop]; } | |
return newNode | |
}; | |
// This file contains Unicode properties extracted from the ECMAScript | |
// specification. The lists are extracted like so: | |
// $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText) | |
// #table-binary-unicode-properties | |
var ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS"; | |
var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic"; | |
var ecma11BinaryProperties = ecma10BinaryProperties; | |
var ecma12BinaryProperties = ecma11BinaryProperties + " EBase EComp EMod EPres ExtPict"; | |
var unicodeBinaryProperties = { | |
9: ecma9BinaryProperties, | |
10: ecma10BinaryProperties, | |
11: ecma11BinaryProperties, | |
12: ecma12BinaryProperties | |
}; | |
// #table-unicode-general-category-values | |
var unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu"; | |
// #table-unicode-script-values | |
var ecma9ScriptValues = "Adlam Adlm Ahom Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb"; | |
var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd"; | |
var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho"; | |
var ecma12ScriptValues = ecma11ScriptValues + " Chorasmian Chrs Diak Dives_Akuru Khitan_Small_Script Kits Yezi Yezidi"; | |
var unicodeScriptValues = { | |
9: ecma9ScriptValues, | |
10: ecma10ScriptValues, | |
11: ecma11ScriptValues, | |
12: ecma12ScriptValues | |
}; | |
var data = {}; | |
function buildUnicodeData(ecmaVersion) { | |
var d = data[ecmaVersion] = { | |
binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues), | |
nonBinary: { | |
General_Category: wordsRegexp(unicodeGeneralCategoryValues), | |
Script: wordsRegexp(unicodeScriptValues[ecmaVersion]) | |
} | |
}; | |
d.nonBinary.Script_Extensions = d.nonBinary.Script; | |
d.nonBinary.gc = d.nonBinary.General_Category; | |
d.nonBinary.sc = d.nonBinary.Script; | |
d.nonBinary.scx = d.nonBinary.Script_Extensions; | |
} | |
buildUnicodeData(9); | |
buildUnicodeData(10); | |
buildUnicodeData(11); | |
buildUnicodeData(12); | |
var pp$1 = Parser.prototype; | |
var RegExpValidationState = function RegExpValidationState(parser) { | |
this.parser = parser; | |
this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "") + (parser.options.ecmaVersion >= 13 ? "d" : ""); | |
this.unicodeProperties = data[parser.options.ecmaVersion >= 12 ? 12 : parser.options.ecmaVersion]; | |
this.source = ""; | |
this.flags = ""; | |
this.start = 0; | |
this.switchU = false; | |
this.switchN = false; | |
this.pos = 0; | |
this.lastIntValue = 0; | |
this.lastStringValue = ""; | |
this.lastAssertionIsQuantifiable = false; | |
this.numCapturingParens = 0; | |
this.maxBackReference = 0; | |
this.groupNames = []; | |
this.backReferenceNames = []; | |
}; | |
RegExpValidationState.prototype.reset = function reset (start, pattern, flags) { | |
var unicode = flags.indexOf("u") !== -1; | |
this.start = start | 0; | |
this.source = pattern + ""; | |
this.flags = flags; | |
this.switchU = unicode && this.parser.options.ecmaVersion >= 6; | |
this.switchN = unicode && this.parser.options.ecmaVersion >= 9; | |
}; | |
RegExpValidationState.prototype.raise = function raise (message) { | |
this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message)); | |
}; | |
// If u flag is given, this returns the code point at the index (it combines a surrogate pair). | |
// Otherwise, this returns the code unit of the index (can be a part of a surrogate pair). | |
RegExpValidationState.prototype.at = function at (i, forceU) { | |
if ( forceU === void 0 ) forceU = false; | |
var s = this.source; | |
var l = s.length; | |
if (i >= l) { | |
return -1 | |
} | |
var c = s.charCodeAt(i); | |
if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { | |
return c | |
} | |
var next = s.charCodeAt(i + 1); | |
return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c | |
}; | |
RegExpValidationState.prototype.nextIndex = function nextIndex (i, forceU) { | |
if ( forceU === void 0 ) forceU = false; | |
var s = this.source; | |
var l = s.length; | |
if (i >= l) { | |
return l | |
} | |
var c = s.charCodeAt(i), next; | |
if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l || | |
(next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) { | |
return i + 1 | |
} | |
return i + 2 | |
}; | |
RegExpValidationState.prototype.current = function current (forceU) { | |
if ( forceU === void 0 ) forceU = false; | |
return this.at(this.pos, forceU) | |
}; | |
RegExpValidationState.prototype.lookahead = function lookahead (forceU) { | |
if ( forceU === void 0 ) forceU = false; | |
return this.at(this.nextIndex(this.pos, forceU), forceU) | |
}; | |
RegExpValidationState.prototype.advance = function advance (forceU) { | |
if ( forceU === void 0 ) forceU = false; | |
this.pos = this.nextIndex(this.pos, forceU); | |
}; | |
RegExpValidationState.prototype.eat = function eat (ch, forceU) { | |
if ( forceU === void 0 ) forceU = false; | |
if (this.current(forceU) === ch) { | |
this.advance(forceU); | |
return true | |
} | |
return false | |
}; | |
function codePointToString$1(ch) { | |
if (ch <= 0xFFFF) { return String.fromCharCode(ch) } | |
ch -= 0x10000; | |
return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00) | |
} | |
/** | |
* Validate the flags part of a given RegExpLiteral. | |
* | |
* @param {RegExpValidationState} state The state to validate RegExp. | |
* @returns {void} | |
*/ | |
pp$1.validateRegExpFlags = function(state) { | |
var validFlags = state.validFlags; | |
var flags = state.flags; | |
for (var i = 0; i < flags.length; i++) { | |
var flag = flags.charAt(i); | |
if (validFlags.indexOf(flag) === -1) { | |
this.raise(state.start, "Invalid regular expression flag"); | |
} | |
if (flags.indexOf(flag, i + 1) > -1) { | |
this.raise(state.start, "Duplicate regular expression flag"); | |
} | |
} | |
}; | |
/** | |
* Validate the pattern part of a given RegExpLiteral. | |
* | |
* @param {RegExpValidationState} state The state to validate RegExp. | |
* @returns {void} | |
*/ | |
pp$1.validateRegExpPattern = function(state) { | |
this.regexp_pattern(state); | |
// The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of | |
// parsing contains a |GroupName|, reparse with the goal symbol | |
// |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError* | |
// exception if _P_ did not conform to the grammar, if any elements of _P_ | |
// were not matched by the parse, or if any Early Error conditions exist. | |
if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) { | |
state.switchN = true; | |
this.regexp_pattern(state); | |
} | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern | |
pp$1.regexp_pattern = function(state) { | |
state.pos = 0; | |
state.lastIntValue = 0; | |
state.lastStringValue = ""; | |
state.lastAssertionIsQuantifiable = false; | |
state.numCapturingParens = 0; | |
state.maxBackReference = 0; | |
state.groupNames.length = 0; | |
state.backReferenceNames.length = 0; | |
this.regexp_disjunction(state); | |
if (state.pos !== state.source.length) { | |
// Make the same messages as V8. | |
if (state.eat(0x29 /* ) */)) { | |
state.raise("Unmatched ')'"); | |
} | |
if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) { | |
state.raise("Lone quantifier brackets"); | |
} | |
} | |
if (state.maxBackReference > state.numCapturingParens) { | |
state.raise("Invalid escape"); | |
} | |
for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) { | |
var name = list[i]; | |
if (state.groupNames.indexOf(name) === -1) { | |
state.raise("Invalid named capture referenced"); | |
} | |
} | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction | |
pp$1.regexp_disjunction = function(state) { | |
this.regexp_alternative(state); | |
while (state.eat(0x7C /* | */)) { | |
this.regexp_alternative(state); | |
} | |
// Make the same message as V8. | |
if (this.regexp_eatQuantifier(state, true)) { | |
state.raise("Nothing to repeat"); | |
} | |
if (state.eat(0x7B /* { */)) { | |
state.raise("Lone quantifier brackets"); | |
} | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative | |
pp$1.regexp_alternative = function(state) { | |
while (state.pos < state.source.length && this.regexp_eatTerm(state)) | |
{ } | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term | |
pp$1.regexp_eatTerm = function(state) { | |
if (this.regexp_eatAssertion(state)) { | |
// Handle `QuantifiableAssertion Quantifier` alternative. | |
// `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion | |
// is a QuantifiableAssertion. | |
if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) { | |
// Make the same message as V8. | |
if (state.switchU) { | |
state.raise("Invalid quantifier"); | |
} | |
} | |
return true | |
} | |
if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) { | |
this.regexp_eatQuantifier(state); | |
return true | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion | |
pp$1.regexp_eatAssertion = function(state) { | |
var start = state.pos; | |
state.lastAssertionIsQuantifiable = false; | |
// ^, $ | |
if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) { | |
return true | |
} | |
// \b \B | |
if (state.eat(0x5C /* \ */)) { | |
if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) { | |
return true | |
} | |
state.pos = start; | |
} | |
// Lookahead / Lookbehind | |
if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) { | |
var lookbehind = false; | |
if (this.options.ecmaVersion >= 9) { | |
lookbehind = state.eat(0x3C /* < */); | |
} | |
if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) { | |
this.regexp_disjunction(state); | |
if (!state.eat(0x29 /* ) */)) { | |
state.raise("Unterminated group"); | |
} | |
state.lastAssertionIsQuantifiable = !lookbehind; | |
return true | |
} | |
} | |
state.pos = start; | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier | |
pp$1.regexp_eatQuantifier = function(state, noError) { | |
if ( noError === void 0 ) noError = false; | |
if (this.regexp_eatQuantifierPrefix(state, noError)) { | |
state.eat(0x3F /* ? */); | |
return true | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix | |
pp$1.regexp_eatQuantifierPrefix = function(state, noError) { | |
return ( | |
state.eat(0x2A /* * */) || | |
state.eat(0x2B /* + */) || | |
state.eat(0x3F /* ? */) || | |
this.regexp_eatBracedQuantifier(state, noError) | |
) | |
}; | |
pp$1.regexp_eatBracedQuantifier = function(state, noError) { | |
var start = state.pos; | |
if (state.eat(0x7B /* { */)) { | |
var min = 0, max = -1; | |
if (this.regexp_eatDecimalDigits(state)) { | |
min = state.lastIntValue; | |
if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) { | |
max = state.lastIntValue; | |
} | |
if (state.eat(0x7D /* } */)) { | |
// SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term | |
if (max !== -1 && max < min && !noError) { | |
state.raise("numbers out of order in {} quantifier"); | |
} | |
return true | |
} | |
} | |
if (state.switchU && !noError) { | |
state.raise("Incomplete quantifier"); | |
} | |
state.pos = start; | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-Atom | |
pp$1.regexp_eatAtom = function(state) { | |
return ( | |
this.regexp_eatPatternCharacters(state) || | |
state.eat(0x2E /* . */) || | |
this.regexp_eatReverseSolidusAtomEscape(state) || | |
this.regexp_eatCharacterClass(state) || | |
this.regexp_eatUncapturingGroup(state) || | |
this.regexp_eatCapturingGroup(state) | |
) | |
}; | |
pp$1.regexp_eatReverseSolidusAtomEscape = function(state) { | |
var start = state.pos; | |
if (state.eat(0x5C /* \ */)) { | |
if (this.regexp_eatAtomEscape(state)) { | |
return true | |
} | |
state.pos = start; | |
} | |
return false | |
}; | |
pp$1.regexp_eatUncapturingGroup = function(state) { | |
var start = state.pos; | |
if (state.eat(0x28 /* ( */)) { | |
if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) { | |
this.regexp_disjunction(state); | |
if (state.eat(0x29 /* ) */)) { | |
return true | |
} | |
state.raise("Unterminated group"); | |
} | |
state.pos = start; | |
} | |
return false | |
}; | |
pp$1.regexp_eatCapturingGroup = function(state) { | |
if (state.eat(0x28 /* ( */)) { | |
if (this.options.ecmaVersion >= 9) { | |
this.regexp_groupSpecifier(state); | |
} else if (state.current() === 0x3F /* ? */) { | |
state.raise("Invalid group"); | |
} | |
this.regexp_disjunction(state); | |
if (state.eat(0x29 /* ) */)) { | |
state.numCapturingParens += 1; | |
return true | |
} | |
state.raise("Unterminated group"); | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom | |
pp$1.regexp_eatExtendedAtom = function(state) { | |
return ( | |
state.eat(0x2E /* . */) || | |
this.regexp_eatReverseSolidusAtomEscape(state) || | |
this.regexp_eatCharacterClass(state) || | |
this.regexp_eatUncapturingGroup(state) || | |
this.regexp_eatCapturingGroup(state) || | |
this.regexp_eatInvalidBracedQuantifier(state) || | |
this.regexp_eatExtendedPatternCharacter(state) | |
) | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier | |
pp$1.regexp_eatInvalidBracedQuantifier = function(state) { | |
if (this.regexp_eatBracedQuantifier(state, true)) { | |
state.raise("Nothing to repeat"); | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter | |
pp$1.regexp_eatSyntaxCharacter = function(state) { | |
var ch = state.current(); | |
if (isSyntaxCharacter(ch)) { | |
state.lastIntValue = ch; | |
state.advance(); | |
return true | |
} | |
return false | |
}; | |
function isSyntaxCharacter(ch) { | |
return ( | |
ch === 0x24 /* $ */ || | |
ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ || | |
ch === 0x2E /* . */ || | |
ch === 0x3F /* ? */ || | |
ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ || | |
ch >= 0x7B /* { */ && ch <= 0x7D /* } */ | |
) | |
} | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter | |
// But eat eager. | |
pp$1.regexp_eatPatternCharacters = function(state) { | |
var start = state.pos; | |
var ch = 0; | |
while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) { | |
state.advance(); | |
} | |
return state.pos !== start | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter | |
pp$1.regexp_eatExtendedPatternCharacter = function(state) { | |
var ch = state.current(); | |
if ( | |
ch !== -1 && | |
ch !== 0x24 /* $ */ && | |
!(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) && | |
ch !== 0x2E /* . */ && | |
ch !== 0x3F /* ? */ && | |
ch !== 0x5B /* [ */ && | |
ch !== 0x5E /* ^ */ && | |
ch !== 0x7C /* | */ | |
) { | |
state.advance(); | |
return true | |
} | |
return false | |
}; | |
// GroupSpecifier :: | |
// [empty] | |
// `?` GroupName | |
pp$1.regexp_groupSpecifier = function(state) { | |
if (state.eat(0x3F /* ? */)) { | |
if (this.regexp_eatGroupName(state)) { | |
if (state.groupNames.indexOf(state.lastStringValue) !== -1) { | |
state.raise("Duplicate capture group name"); | |
} | |
state.groupNames.push(state.lastStringValue); | |
return | |
} | |
state.raise("Invalid group"); | |
} | |
}; | |
// GroupName :: | |
// `<` RegExpIdentifierName `>` | |
// Note: this updates `state.lastStringValue` property with the eaten name. | |
pp$1.regexp_eatGroupName = function(state) { | |
state.lastStringValue = ""; | |
if (state.eat(0x3C /* < */)) { | |
if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) { | |
return true | |
} | |
state.raise("Invalid capture group name"); | |
} | |
return false | |
}; | |
// RegExpIdentifierName :: | |
// RegExpIdentifierStart | |
// RegExpIdentifierName RegExpIdentifierPart | |
// Note: this updates `state.lastStringValue` property with the eaten name. | |
pp$1.regexp_eatRegExpIdentifierName = function(state) { | |
state.lastStringValue = ""; | |
if (this.regexp_eatRegExpIdentifierStart(state)) { | |
state.lastStringValue += codePointToString$1(state.lastIntValue); | |
while (this.regexp_eatRegExpIdentifierPart(state)) { | |
state.lastStringValue += codePointToString$1(state.lastIntValue); | |
} | |
return true | |
} | |
return false | |
}; | |
// RegExpIdentifierStart :: | |
// UnicodeIDStart | |
// `$` | |
// `_` | |
// `\` RegExpUnicodeEscapeSequence[+U] | |
pp$1.regexp_eatRegExpIdentifierStart = function(state) { | |
var start = state.pos; | |
var forceU = this.options.ecmaVersion >= 11; | |
var ch = state.current(forceU); | |
state.advance(forceU); | |
if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) { | |
ch = state.lastIntValue; | |
} | |
if (isRegExpIdentifierStart(ch)) { | |
state.lastIntValue = ch; | |
return true | |
} | |
state.pos = start; | |
return false | |
}; | |
function isRegExpIdentifierStart(ch) { | |
return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ | |
} | |
// RegExpIdentifierPart :: | |
// UnicodeIDContinue | |
// `$` | |
// `_` | |
// `\` RegExpUnicodeEscapeSequence[+U] | |
// <ZWNJ> | |
// <ZWJ> | |
pp$1.regexp_eatRegExpIdentifierPart = function(state) { | |
var start = state.pos; | |
var forceU = this.options.ecmaVersion >= 11; | |
var ch = state.current(forceU); | |
state.advance(forceU); | |
if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) { | |
ch = state.lastIntValue; | |
} | |
if (isRegExpIdentifierPart(ch)) { | |
state.lastIntValue = ch; | |
return true | |
} | |
state.pos = start; | |
return false | |
}; | |
function isRegExpIdentifierPart(ch) { | |
return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */ | |
} | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape | |
pp$1.regexp_eatAtomEscape = function(state) { | |
if ( | |
this.regexp_eatBackReference(state) || | |
this.regexp_eatCharacterClassEscape(state) || | |
this.regexp_eatCharacterEscape(state) || | |
(state.switchN && this.regexp_eatKGroupName(state)) | |
) { | |
return true | |
} | |
if (state.switchU) { | |
// Make the same message as V8. | |
if (state.current() === 0x63 /* c */) { | |
state.raise("Invalid unicode escape"); | |
} | |
state.raise("Invalid escape"); | |
} | |
return false | |
}; | |
pp$1.regexp_eatBackReference = function(state) { | |
var start = state.pos; | |
if (this.regexp_eatDecimalEscape(state)) { | |
var n = state.lastIntValue; | |
if (state.switchU) { | |
// For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape | |
if (n > state.maxBackReference) { | |
state.maxBackReference = n; | |
} | |
return true | |
} | |
if (n <= state.numCapturingParens) { | |
return true | |
} | |
state.pos = start; | |
} | |
return false | |
}; | |
pp$1.regexp_eatKGroupName = function(state) { | |
if (state.eat(0x6B /* k */)) { | |
if (this.regexp_eatGroupName(state)) { | |
state.backReferenceNames.push(state.lastStringValue); | |
return true | |
} | |
state.raise("Invalid named reference"); | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape | |
pp$1.regexp_eatCharacterEscape = function(state) { | |
return ( | |
this.regexp_eatControlEscape(state) || | |
this.regexp_eatCControlLetter(state) || | |
this.regexp_eatZero(state) || | |
this.regexp_eatHexEscapeSequence(state) || | |
this.regexp_eatRegExpUnicodeEscapeSequence(state, false) || | |
(!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) || | |
this.regexp_eatIdentityEscape(state) | |
) | |
}; | |
pp$1.regexp_eatCControlLetter = function(state) { | |
var start = state.pos; | |
if (state.eat(0x63 /* c */)) { | |
if (this.regexp_eatControlLetter(state)) { | |
return true | |
} | |
state.pos = start; | |
} | |
return false | |
}; | |
pp$1.regexp_eatZero = function(state) { | |
if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) { | |
state.lastIntValue = 0; | |
state.advance(); | |
return true | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape | |
pp$1.regexp_eatControlEscape = function(state) { | |
var ch = state.current(); | |
if (ch === 0x74 /* t */) { | |
state.lastIntValue = 0x09; /* \t */ | |
state.advance(); | |
return true | |
} | |
if (ch === 0x6E /* n */) { | |
state.lastIntValue = 0x0A; /* \n */ | |
state.advance(); | |
return true | |
} | |
if (ch === 0x76 /* v */) { | |
state.lastIntValue = 0x0B; /* \v */ | |
state.advance(); | |
return true | |
} | |
if (ch === 0x66 /* f */) { | |
state.lastIntValue = 0x0C; /* \f */ | |
state.advance(); | |
return true | |
} | |
if (ch === 0x72 /* r */) { | |
state.lastIntValue = 0x0D; /* \r */ | |
state.advance(); | |
return true | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter | |
pp$1.regexp_eatControlLetter = function(state) { | |
var ch = state.current(); | |
if (isControlLetter(ch)) { | |
state.lastIntValue = ch % 0x20; | |
state.advance(); | |
return true | |
} | |
return false | |
}; | |
function isControlLetter(ch) { | |
return ( | |
(ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) || | |
(ch >= 0x61 /* a */ && ch <= 0x7A /* z */) | |
) | |
} | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence | |
pp$1.regexp_eatRegExpUnicodeEscapeSequence = function(state, forceU) { | |
if ( forceU === void 0 ) forceU = false; | |
var start = state.pos; | |
var switchU = forceU || state.switchU; | |
if (state.eat(0x75 /* u */)) { | |
if (this.regexp_eatFixedHexDigits(state, 4)) { | |
var lead = state.lastIntValue; | |
if (switchU && lead >= 0xD800 && lead <= 0xDBFF) { | |
var leadSurrogateEnd = state.pos; | |
if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) { | |
var trail = state.lastIntValue; | |
if (trail >= 0xDC00 && trail <= 0xDFFF) { | |
state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000; | |
return true | |
} | |
} | |
state.pos = leadSurrogateEnd; | |
state.lastIntValue = lead; | |
} | |
return true | |
} | |
if ( | |
switchU && | |
state.eat(0x7B /* { */) && | |
this.regexp_eatHexDigits(state) && | |
state.eat(0x7D /* } */) && | |
isValidUnicode(state.lastIntValue) | |
) { | |
return true | |
} | |
if (switchU) { | |
state.raise("Invalid unicode escape"); | |
} | |
state.pos = start; | |
} | |
return false | |
}; | |
function isValidUnicode(ch) { | |
return ch >= 0 && ch <= 0x10FFFF | |
} | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape | |
pp$1.regexp_eatIdentityEscape = function(state) { | |
if (state.switchU) { | |
if (this.regexp_eatSyntaxCharacter(state)) { | |
return true | |
} | |
if (state.eat(0x2F /* / */)) { | |
state.lastIntValue = 0x2F; /* / */ | |
return true | |
} | |
return false | |
} | |
var ch = state.current(); | |
if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) { | |
state.lastIntValue = ch; | |
state.advance(); | |
return true | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape | |
pp$1.regexp_eatDecimalEscape = function(state) { | |
state.lastIntValue = 0; | |
var ch = state.current(); | |
if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) { | |
do { | |
state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); | |
state.advance(); | |
} while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) | |
return true | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape | |
pp$1.regexp_eatCharacterClassEscape = function(state) { | |
var ch = state.current(); | |
if (isCharacterClassEscape(ch)) { | |
state.lastIntValue = -1; | |
state.advance(); | |
return true | |
} | |
if ( | |
state.switchU && | |
this.options.ecmaVersion >= 9 && | |
(ch === 0x50 /* P */ || ch === 0x70 /* p */) | |
) { | |
state.lastIntValue = -1; | |
state.advance(); | |
if ( | |
state.eat(0x7B /* { */) && | |
this.regexp_eatUnicodePropertyValueExpression(state) && | |
state.eat(0x7D /* } */) | |
) { | |
return true | |
} | |
state.raise("Invalid property name"); | |
} | |
return false | |
}; | |
function isCharacterClassEscape(ch) { | |
return ( | |
ch === 0x64 /* d */ || | |
ch === 0x44 /* D */ || | |
ch === 0x73 /* s */ || | |
ch === 0x53 /* S */ || | |
ch === 0x77 /* w */ || | |
ch === 0x57 /* W */ | |
) | |
} | |
// UnicodePropertyValueExpression :: | |
// UnicodePropertyName `=` UnicodePropertyValue | |
// LoneUnicodePropertyNameOrValue | |
pp$1.regexp_eatUnicodePropertyValueExpression = function(state) { | |
var start = state.pos; | |
// UnicodePropertyName `=` UnicodePropertyValue | |
if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) { | |
var name = state.lastStringValue; | |
if (this.regexp_eatUnicodePropertyValue(state)) { | |
var value = state.lastStringValue; | |
this.regexp_validateUnicodePropertyNameAndValue(state, name, value); | |
return true | |
} | |
} | |
state.pos = start; | |
// LoneUnicodePropertyNameOrValue | |
if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) { | |
var nameOrValue = state.lastStringValue; | |
this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue); | |
return true | |
} | |
return false | |
}; | |
pp$1.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) { | |
if (!has(state.unicodeProperties.nonBinary, name)) | |
{ state.raise("Invalid property name"); } | |
if (!state.unicodeProperties.nonBinary[name].test(value)) | |
{ state.raise("Invalid property value"); } | |
}; | |
pp$1.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) { | |
if (!state.unicodeProperties.binary.test(nameOrValue)) | |
{ state.raise("Invalid property name"); } | |
}; | |
// UnicodePropertyName :: | |
// UnicodePropertyNameCharacters | |
pp$1.regexp_eatUnicodePropertyName = function(state) { | |
var ch = 0; | |
state.lastStringValue = ""; | |
while (isUnicodePropertyNameCharacter(ch = state.current())) { | |
state.lastStringValue += codePointToString$1(ch); | |
state.advance(); | |
} | |
return state.lastStringValue !== "" | |
}; | |
function isUnicodePropertyNameCharacter(ch) { | |
return isControlLetter(ch) || ch === 0x5F /* _ */ | |
} | |
// UnicodePropertyValue :: | |
// UnicodePropertyValueCharacters | |
pp$1.regexp_eatUnicodePropertyValue = function(state) { | |
var ch = 0; | |
state.lastStringValue = ""; | |
while (isUnicodePropertyValueCharacter(ch = state.current())) { | |
state.lastStringValue += codePointToString$1(ch); | |
state.advance(); | |
} | |
return state.lastStringValue !== "" | |
}; | |
function isUnicodePropertyValueCharacter(ch) { | |
return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch) | |
} | |
// LoneUnicodePropertyNameOrValue :: | |
// UnicodePropertyValueCharacters | |
pp$1.regexp_eatLoneUnicodePropertyNameOrValue = function(state) { | |
return this.regexp_eatUnicodePropertyValue(state) | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass | |
pp$1.regexp_eatCharacterClass = function(state) { | |
if (state.eat(0x5B /* [ */)) { | |
state.eat(0x5E /* ^ */); | |
this.regexp_classRanges(state); | |
if (state.eat(0x5D /* ] */)) { | |
return true | |
} | |
// Unreachable since it threw "unterminated regular expression" error before. | |
state.raise("Unterminated character class"); | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash | |
pp$1.regexp_classRanges = function(state) { | |
while (this.regexp_eatClassAtom(state)) { | |
var left = state.lastIntValue; | |
if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) { | |
var right = state.lastIntValue; | |
if (state.switchU && (left === -1 || right === -1)) { | |
state.raise("Invalid character class"); | |
} | |
if (left !== -1 && right !== -1 && left > right) { | |
state.raise("Range out of order in character class"); | |
} | |
} | |
} | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash | |
pp$1.regexp_eatClassAtom = function(state) { | |
var start = state.pos; | |
if (state.eat(0x5C /* \ */)) { | |
if (this.regexp_eatClassEscape(state)) { | |
return true | |
} | |
if (state.switchU) { | |
// Make the same message as V8. | |
var ch$1 = state.current(); | |
if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) { | |
state.raise("Invalid class escape"); | |
} | |
state.raise("Invalid escape"); | |
} | |
state.pos = start; | |
} | |
var ch = state.current(); | |
if (ch !== 0x5D /* ] */) { | |
state.lastIntValue = ch; | |
state.advance(); | |
return true | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape | |
pp$1.regexp_eatClassEscape = function(state) { | |
var start = state.pos; | |
if (state.eat(0x62 /* b */)) { | |
state.lastIntValue = 0x08; /* <BS> */ | |
return true | |
} | |
if (state.switchU && state.eat(0x2D /* - */)) { | |
state.lastIntValue = 0x2D; /* - */ | |
return true | |
} | |
if (!state.switchU && state.eat(0x63 /* c */)) { | |
if (this.regexp_eatClassControlLetter(state)) { | |
return true | |
} | |
state.pos = start; | |
} | |
return ( | |
this.regexp_eatCharacterClassEscape(state) || | |
this.regexp_eatCharacterEscape(state) | |
) | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter | |
pp$1.regexp_eatClassControlLetter = function(state) { | |
var ch = state.current(); | |
if (isDecimalDigit(ch) || ch === 0x5F /* _ */) { | |
state.lastIntValue = ch % 0x20; | |
state.advance(); | |
return true | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence | |
pp$1.regexp_eatHexEscapeSequence = function(state) { | |
var start = state.pos; | |
if (state.eat(0x78 /* x */)) { | |
if (this.regexp_eatFixedHexDigits(state, 2)) { | |
return true | |
} | |
if (state.switchU) { | |
state.raise("Invalid escape"); | |
} | |
state.pos = start; | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits | |
pp$1.regexp_eatDecimalDigits = function(state) { | |
var start = state.pos; | |
var ch = 0; | |
state.lastIntValue = 0; | |
while (isDecimalDigit(ch = state.current())) { | |
state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); | |
state.advance(); | |
} | |
return state.pos !== start | |
}; | |
function isDecimalDigit(ch) { | |
return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */ | |
} | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits | |
pp$1.regexp_eatHexDigits = function(state) { | |
var start = state.pos; | |
var ch = 0; | |
state.lastIntValue = 0; | |
while (isHexDigit(ch = state.current())) { | |
state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); | |
state.advance(); | |
} | |
return state.pos !== start | |
}; | |
function isHexDigit(ch) { | |
return ( | |
(ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) || | |
(ch >= 0x41 /* A */ && ch <= 0x46 /* F */) || | |
(ch >= 0x61 /* a */ && ch <= 0x66 /* f */) | |
) | |
} | |
function hexToInt(ch) { | |
if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) { | |
return 10 + (ch - 0x41 /* A */) | |
} | |
if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) { | |
return 10 + (ch - 0x61 /* a */) | |
} | |
return ch - 0x30 /* 0 */ | |
} | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence | |
// Allows only 0-377(octal) i.e. 0-255(decimal). | |
pp$1.regexp_eatLegacyOctalEscapeSequence = function(state) { | |
if (this.regexp_eatOctalDigit(state)) { | |
var n1 = state.lastIntValue; | |
if (this.regexp_eatOctalDigit(state)) { | |
var n2 = state.lastIntValue; | |
if (n1 <= 3 && this.regexp_eatOctalDigit(state)) { | |
state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue; | |
} else { | |
state.lastIntValue = n1 * 8 + n2; | |
} | |
} else { | |
state.lastIntValue = n1; | |
} | |
return true | |
} | |
return false | |
}; | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit | |
pp$1.regexp_eatOctalDigit = function(state) { | |
var ch = state.current(); | |
if (isOctalDigit(ch)) { | |
state.lastIntValue = ch - 0x30; /* 0 */ | |
state.advance(); | |
return true | |
} | |
state.lastIntValue = 0; | |
return false | |
}; | |
function isOctalDigit(ch) { | |
return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */ | |
} | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits | |
// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit | |
// And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence | |
pp$1.regexp_eatFixedHexDigits = function(state, length) { | |
var start = state.pos; | |
state.lastIntValue = 0; | |
for (var i = 0; i < length; ++i) { | |
var ch = state.current(); | |
if (!isHexDigit(ch)) { | |
state.pos = start; | |
return false | |
} | |
state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); | |
state.advance(); | |
} | |
return true | |
}; | |
// Object type used to represent tokens. Note that normally, tokens | |
// simply exist as properties on the parser object. This is only | |
// used for the onToken callback and the external tokenizer. | |
var Token = function Token(p) { | |
this.type = p.type; | |
this.value = p.value; | |
this.start = p.start; | |
this.end = p.end; | |
if (p.options.locations) | |
{ this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } | |
if (p.options.ranges) | |
{ this.range = [p.start, p.end]; } | |
}; | |
// ## Tokenizer | |
var pp = Parser.prototype; | |
// Move to the next token | |
pp.next = function(ignoreEscapeSequenceInKeyword) { | |
if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc) | |
{ this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword); } | |
if (this.options.onToken) | |
{ this.options.onToken(new Token(this)); } | |
this.lastTokEnd = this.end; | |
this.lastTokStart = this.start; | |
this.lastTokEndLoc = this.endLoc; | |
this.lastTokStartLoc = this.startLoc; | |
this.nextToken(); | |
}; | |
pp.getToken = function() { | |
this.next(); | |
return new Token(this) | |
}; | |
// If we're in an ES6 environment, make parsers iterable | |
if (typeof Symbol !== "undefined") | |
{ pp[Symbol.iterator] = function() { | |
var this$1$1 = this; | |
return { | |
next: function () { | |
var token = this$1$1.getToken(); | |
return { | |
done: token.type === types$1.eof, | |
value: token | |
} | |
} | |
} | |
}; } | |
// Toggle strict mode. Re-reads the next number or string to please | |
// pedantic tests (`"use strict"; 010;` should fail). | |
// Read a single token, updating the parser object's token-related | |
// properties. | |
pp.nextToken = function() { | |
var curContext = this.curContext(); | |
if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } | |
this.start = this.pos; | |
if (this.options.locations) { this.startLoc = this.curPosition(); } | |
if (this.pos >= this.input.length) { return this.finishToken(types$1.eof) } | |
if (curContext.override) { return curContext.override(this) } | |
else { this.readToken(this.fullCharCodeAtPos()); } | |
}; | |
pp.readToken = function(code) { | |
// Identifier or keyword. '\uXXXX' sequences are allowed in | |
// identifiers, so '\' also dispatches to that. | |
if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) | |
{ return this.readWord() } | |
return this.getTokenFromCode(code) | |
}; | |
pp.fullCharCodeAtPos = function() { | |
var code = this.input.charCodeAt(this.pos); | |
if (code <= 0xd7ff || code >= 0xdc00) { return code } | |
var next = this.input.charCodeAt(this.pos + 1); | |
return next <= 0xdbff || next >= 0xe000 ? code : (code << 10) + next - 0x35fdc00 | |
}; | |
pp.skipBlockComment = function() { | |
var startLoc = this.options.onComment && this.curPosition(); | |
var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); | |
if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } | |
this.pos = end + 2; | |
if (this.options.locations) { | |
lineBreakG.lastIndex = start; | |
var match; | |
while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) { | |
++this.curLine; | |
this.lineStart = match.index + match[0].length; | |
} | |
} | |
if (this.options.onComment) | |
{ this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, | |
startLoc, this.curPosition()); } | |
}; | |
pp.skipLineComment = function(startSkip) { | |
var start = this.pos; | |
var startLoc = this.options.onComment && this.curPosition(); | |
var ch = this.input.charCodeAt(this.pos += startSkip); | |
while (this.pos < this.input.length && !isNewLine(ch)) { | |
ch = this.input.charCodeAt(++this.pos); | |
} | |
if (this.options.onComment) | |
{ this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, | |
startLoc, this.curPosition()); } | |
}; | |
// Called at the start of the parse and after every token. Skips | |
// whitespace and comments, and. | |
pp.skipSpace = function() { | |
loop: while (this.pos < this.input.length) { | |
var ch = this.input.charCodeAt(this.pos); | |
switch (ch) { | |
case 32: case 160: // ' ' | |
++this.pos; | |
break | |
case 13: | |
if (this.input.charCodeAt(this.pos + 1) === 10) { | |
++this.pos; | |
} | |
case 10: case 8232: case 8233: | |
++this.pos; | |
if (this.options.locations) { | |
++this.curLine; | |
this.lineStart = this.pos; | |
} | |
break | |
case 47: // '/' | |
switch (this.input.charCodeAt(this.pos + 1)) { | |
case 42: // '*' | |
this.skipBlockComment(); | |
break | |
case 47: | |
this.skipLineComment(2); | |
break | |
default: | |
break loop | |
} | |
break | |
default: | |
if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { | |
++this.pos; | |
} else { | |
break loop | |
} | |
} | |
} | |
}; | |
// Called at the end of every token. Sets `end`, `val`, and | |
// maintains `context` and `exprAllowed`, and skips the space after | |
// the token, so that the next one's `start` will point at the | |
// right position. | |
pp.finishToken = function(type, val) { | |
this.end = this.pos; | |
if (this.options.locations) { this.endLoc = this.curPosition(); } | |
var prevType = this.type; | |
this.type = type; | |
this.value = val; | |
this.updateContext(prevType); | |
}; | |
// ### Token reading | |
// This is the function that is called to fetch the next token. It | |
// is somewhat obscure, because it works in character codes rather | |
// than characters, and because operator parsing has been inlined | |
// into it. | |
// | |
// All in the name of speed. | |
// | |
pp.readToken_dot = function() { | |
var next = this.input.charCodeAt(this.pos + 1); | |
if (next >= 48 && next <= 57) { return this.readNumber(true) } | |
var next2 = this.input.charCodeAt(this.pos + 2); | |
if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' | |
this.pos += 3; | |
return this.finishToken(types$1.ellipsis) | |
} else { | |
++this.pos; | |
return this.finishToken(types$1.dot) | |
} | |
}; | |
pp.readToken_slash = function() { // '/' | |
var next = this.input.charCodeAt(this.pos + 1); | |
if (this.exprAllowed) { ++this.pos; return this.readRegexp() } | |
if (next === 61) { return this.finishOp(types$1.assign, 2) } | |
return this.finishOp(types$1.slash, 1) | |
}; | |
pp.readToken_mult_modulo_exp = function(code) { // '%*' | |
var next = this.input.charCodeAt(this.pos + 1); | |
var size = 1; | |
var tokentype = code === 42 ? types$1.star : types$1.modulo; | |
// exponentiation operator ** and **= | |
if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) { | |
++size; | |
tokentype = types$1.starstar; | |
next = this.input.charCodeAt(this.pos + 2); | |
} | |
if (next === 61) { return this.finishOp(types$1.assign, size + 1) } | |
return this.finishOp(tokentype, size) | |
}; | |
pp.readToken_pipe_amp = function(code) { // '|&' | |
var next = this.input.charCodeAt(this.pos + 1); | |
if (next === code) { | |
if (this.options.ecmaVersion >= 12) { | |
var next2 = this.input.charCodeAt(this.pos + 2); | |
if (next2 === 61) { return this.finishOp(types$1.assign, 3) } | |
} | |
return this.finishOp(code === 124 ? types$1.logicalOR : types$1.logicalAND, 2) | |
} | |
if (next === 61) { return this.finishOp(types$1.assign, 2) } | |
return this.finishOp(code === 124 ? types$1.bitwiseOR : types$1.bitwiseAND, 1) | |
}; | |
pp.readToken_caret = function() { // '^' | |
var next = this.input.charCodeAt(this.pos + 1); | |
if (next === 61) { return this.finishOp(types$1.assign, 2) } | |
return this.finishOp(types$1.bitwiseXOR, 1) | |
}; | |
pp.readToken_plus_min = function(code) { // '+-' | |
var next = this.input.charCodeAt(this.pos + 1); | |
if (next === code) { | |
if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 && | |
(this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { | |
// A `-->` line comment | |
this.skipLineComment(3); | |
this.skipSpace(); | |
return this.nextToken() | |
} | |
return this.finishOp(types$1.incDec, 2) | |
} | |
if (next === 61) { return this.finishOp(types$1.assign, 2) } | |
return this.finishOp(types$1.plusMin, 1) | |
}; | |
pp.readToken_lt_gt = function(code) { // '<>' | |
var next = this.input.charCodeAt(this.pos + 1); | |
var size = 1; | |
if (next === code) { | |
size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; | |
if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types$1.assign, size + 1) } | |
return this.finishOp(types$1.bitShift, size) | |
} | |
if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && | |
this.input.charCodeAt(this.pos + 3) === 45) { | |
// `<!--`, an XML-style comment that should be interpreted as a line comment | |
this.skipLineComment(4); | |
this.skipSpace(); | |
return this.nextToken() | |
} | |
if (next === 61) { size = 2; } | |
return this.finishOp(types$1.relational, size) | |
}; | |
pp.readToken_eq_excl = function(code) { // '=!' | |
var next = this.input.charCodeAt(this.pos + 1); | |
if (next === 61) { return this.finishOp(types$1.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) } | |
if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>' | |
this.pos += 2; | |
return this.finishToken(types$1.arrow) | |
} | |
return this.finishOp(code === 61 ? types$1.eq : types$1.prefix, 1) | |
}; | |
pp.readToken_question = function() { // '?' | |
var ecmaVersion = this.options.ecmaVersion; | |
if (ecmaVersion >= 11) { | |
var next = this.input.charCodeAt(this.pos + 1); | |
if (next === 46) { | |
var next2 = this.input.charCodeAt(this.pos + 2); | |
if (next2 < 48 || next2 > 57) { return this.finishOp(types$1.questionDot, 2) } | |
} | |
if (next === 63) { | |
if (ecmaVersion >= 12) { | |
var next2$1 = this.input.charCodeAt(this.pos + 2); | |
if (next2$1 === 61) { return this.finishOp(types$1.assign, 3) } | |
} | |
return this.finishOp(types$1.coalesce, 2) | |
} | |
} | |
return this.finishOp(types$1.question, 1) | |
}; | |
pp.readToken_numberSign = function() { // '#' | |
var ecmaVersion = this.options.ecmaVersion; | |
var code = 35; // '#' | |
if (ecmaVersion >= 13) { | |
++this.pos; | |
code = this.fullCharCodeAtPos(); | |
if (isIdentifierStart(code, true) || code === 92 /* '\' */) { | |
return this.finishToken(types$1.privateId, this.readWord1()) | |
} | |
} | |
this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'"); | |
}; | |
pp.getTokenFromCode = function(code) { | |
switch (code) { | |
// The interpretation of a dot depends on whether it is followed | |
// by a digit or another two dots. | |
case 46: // '.' | |
return this.readToken_dot() | |
// Punctuation tokens. | |
case 40: ++this.pos; return this.finishToken(types$1.parenL) | |
case 41: ++this.pos; return this.finishToken(types$1.parenR) | |
case 59: ++this.pos; return this.finishToken(types$1.semi) | |
case 44: ++this.pos; return this.finishToken(types$1.comma) | |
case 91: ++this.pos; return this.finishToken(types$1.bracketL) | |
case 93: ++this.pos; return this.finishToken(types$1.bracketR) | |
case 123: ++this.pos; return this.finishToken(types$1.braceL) | |
case 125: ++this.pos; return this.finishToken(types$1.braceR) | |
case 58: ++this.pos; return this.finishToken(types$1.colon) | |
case 96: // '`' | |
if (this.options.ecmaVersion < 6) { break } | |
++this.pos; | |
return this.finishToken(types$1.backQuote) | |
case 48: // '0' | |
var next = this.input.charCodeAt(this.pos + 1); | |
if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number | |
if (this.options.ecmaVersion >= 6) { | |
if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number | |
if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number | |
} | |
// Anything else beginning with a digit is an integer, octal | |
// number, or float. | |
case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9 | |
return this.readNumber(false) | |
// Quotes produce strings. | |
case 34: case 39: // '"', "'" | |
return this.readString(code) | |
// Operators are parsed inline in tiny state machines. '=' (61) is | |
// often referred to. `finishOp` simply skips the amount of | |
// characters it is given as second argument, and returns a token | |
// of the type given by its first argument. | |
case 47: // '/' | |
return this.readToken_slash() | |
case 37: case 42: // '%*' | |
return this.readToken_mult_modulo_exp(code) | |
case 124: case 38: // '|&' | |
return this.readToken_pipe_amp(code) | |
case 94: // '^' | |
return this.readToken_caret() | |
case 43: case 45: // '+-' | |
return this.readToken_plus_min(code) | |
case 60: case 62: // '<>' | |
return this.readToken_lt_gt(code) | |
case 61: case 33: // '=!' | |
return this.readToken_eq_excl(code) | |
case 63: // '?' | |
return this.readToken_question() | |
case 126: // '~' | |
return this.finishOp(types$1.prefix, 1) | |
case 35: // '#' | |
return this.readToken_numberSign() | |
} | |
this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'"); | |
}; | |
pp.finishOp = function(type, size) { | |
var str = this.input.slice(this.pos, this.pos + size); | |
this.pos += size; | |
return this.finishToken(type, str) | |
}; | |
pp.readRegexp = function() { | |
var escaped, inClass, start = this.pos; | |
for (;;) { | |
if (this.pos >= this.input.length) { this.raise(start, "Unterminated regular expression"); } | |
var ch = this.input.charAt(this.pos); | |
if (lineBreak.test(ch)) { this.raise(start, "Unterminated regular expression"); } | |
if (!escaped) { | |
if (ch === "[") { inClass = true; } | |
else if (ch === "]" && inClass) { inClass = false; } | |
else if (ch === "/" && !inClass) { break } | |
escaped = ch === "\\"; | |
} else { escaped = false; } | |
++this.pos; | |
} | |
var pattern = this.input.slice(start, this.pos); | |
++this.pos; | |
var flagsStart = this.pos; | |
var flags = this.readWord1(); | |
if (this.containsEsc) { this.unexpected(flagsStart); } | |
// Validate pattern | |
var state = this.regexpState || (this.regexpState = new RegExpValidationState(this)); | |
state.reset(start, pattern, flags); | |
this.validateRegExpFlags(state); | |
this.validateRegExpPattern(state); | |
// Create Literal#value property value. | |
var value = null; | |
try { | |
value = new RegExp(pattern, flags); | |
} catch (e) { | |
// ESTree requires null if it failed to instantiate RegExp object. | |
// https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral | |
} | |
return this.finishToken(types$1.regexp, {pattern: pattern, flags: flags, value: value}) | |
}; | |
// Read an integer in the given radix. Return null if zero digits | |
// were read, the integer value otherwise. When `len` is given, this | |
// will return `null` unless the integer has exactly `len` digits. | |
pp.readInt = function(radix, len, maybeLegacyOctalNumericLiteral) { | |
// `len` is used for character escape sequences. In that case, disallow separators. | |
var allowSeparators = this.options.ecmaVersion >= 12 && len === undefined; | |
// `maybeLegacyOctalNumericLiteral` is true if it doesn't have prefix (0x,0o,0b) | |
// and isn't fraction part nor exponent part. In that case, if the first digit | |
// is zero then disallow separators. | |
var isLegacyOctalNumericLiteral = maybeLegacyOctalNumericLiteral && this.input.charCodeAt(this.pos) === 48; | |
var start = this.pos, total = 0, lastCode = 0; | |
for (var i = 0, e = len == null ? Infinity : len; i < e; ++i, ++this.pos) { | |
var code = this.input.charCodeAt(this.pos), val = (void 0); | |
if (allowSeparators && code === 95) { | |
if (isLegacyOctalNumericLiteral) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed in legacy octal numeric literals"); } | |
if (lastCode === 95) { this.raiseRecoverable(this.pos, "Numeric separator must be exactly one underscore"); } | |
if (i === 0) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed at the first of digits"); } | |
lastCode = code; | |
continue | |
} | |
if (code >= 97) { val = code - 97 + 10; } // a | |
else if (code >= 65) { val = code - 65 + 10; } // A | |
else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9 | |
else { val = Infinity; } | |
if (val >= radix) { break } | |
lastCode = code; | |
total = total * radix + val; | |
} | |
if (allowSeparators && lastCode === 95) { this.raiseRecoverable(this.pos - 1, "Numeric separator is not allowed at the last of digits"); } | |
if (this.pos === start || len != null && this.pos - start !== len) { return null } | |
return total | |
}; | |
function stringToNumber(str, isLegacyOctalNumericLiteral) { | |
if (isLegacyOctalNumericLiteral) { | |
return parseInt(str, 8) | |
} | |
// `parseFloat(value)` stops parsing at the first numeric separator then returns a wrong value. | |
return parseFloat(str.replace(/_/g, "")) | |
} | |
function stringToBigInt(str) { | |
if (typeof BigInt !== "function") { | |
return null | |
} | |
// `BigInt(value)` throws syntax error if the string contains numeric separators. | |
return BigInt(str.replace(/_/g, "")) | |
} | |
pp.readRadixNumber = function(radix) { | |
var start = this.pos; | |
this.pos += 2; // 0x | |
var val = this.readInt(radix); | |
if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); } | |
if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) { | |
val = stringToBigInt(this.input.slice(start, this.pos)); | |
++this.pos; | |
} else if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } | |
return this.finishToken(types$1.num, val) | |
}; | |
// Read an integer, octal integer, or floating-point number. | |
pp.readNumber = function(startsWithDot) { | |
var start = this.pos; | |
if (!startsWithDot && this.readInt(10, undefined, true) === null) { this.raise(start, "Invalid number"); } | |
var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48; | |
if (octal && this.strict) { this.raise(start, "Invalid number"); } | |
var next = this.input.charCodeAt(this.pos); | |
if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) { | |
var val$1 = stringToBigInt(this.input.slice(start, this.pos)); | |
++this.pos; | |
if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } | |
return this.finishToken(types$1.num, val$1) | |
} | |
if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; } | |
if (next === 46 && !octal) { // '.' | |
++this.pos; | |
this.readInt(10); | |
next = this.input.charCodeAt(this.pos); | |
} | |
if ((next === 69 || next === 101) && !octal) { // 'eE' | |
next = this.input.charCodeAt(++this.pos); | |
if (next === 43 || next === 45) { ++this.pos; } // '+-' | |
if (this.readInt(10) === null) { this.raise(start, "Invalid number"); } | |
} | |
if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } | |
var val = stringToNumber(this.input.slice(start, this.pos), octal); | |
return this.finishToken(types$1.num, val) | |
}; | |
// Read a string value, interpreting backslash-escapes. | |
pp.readCodePoint = function() { | |
var ch = this.input.charCodeAt(this.pos), code; | |
if (ch === 123) { // '{' | |
if (this.options.ecmaVersion < 6) { this.unexpected(); } | |
var codePos = ++this.pos; | |
code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos); | |
++this.pos; | |
if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); } | |
} else { | |
code = this.readHexChar(4); | |
} | |
return code | |
}; | |
function codePointToString(code) { | |
// UTF-16 Decoding | |
if (code <= 0xFFFF) { return String.fromCharCode(code) } | |
code -= 0x10000; | |
return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00) | |
} | |
pp.readString = function(quote) { | |
var out = "", chunkStart = ++this.pos; | |
for (;;) { | |
if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated string constant"); } | |
var ch = this.input.charCodeAt(this.pos); | |
if (ch === quote) { break } | |
if (ch === 92) { // '\' | |
out += this.input.slice(chunkStart, this.pos); | |
out += this.readEscapedChar(false); | |
chunkStart = this.pos; | |
} else if (ch === 0x2028 || ch === 0x2029) { | |
if (this.options.ecmaVersion < 10) { this.raise(this.start, "Unterminated string constant"); } | |
++this.pos; | |
if (this.options.locations) { | |
this.curLine++; | |
this.lineStart = this.pos; | |
} | |
} else { | |
if (isNewLine(ch)) { this.raise(this.start, "Unterminated string constant"); } | |
++this.pos; | |
} | |
} | |
out += this.input.slice(chunkStart, this.pos++); | |
return this.finishToken(types$1.string, out) | |
}; | |
// Reads template string tokens. | |
var INVALID_TEMPLATE_ESCAPE_ERROR = {}; | |
pp.tryReadTemplateToken = function() { | |
this.inTemplateElement = true; | |
try { | |
this.readTmplToken(); | |
} catch (err) { | |
if (err === INVALID_TEMPLATE_ESCAPE_ERROR) { | |
this.readInvalidTemplateToken(); | |
} else { | |
throw err | |
} | |
} | |
this.inTemplateElement = false; | |
}; | |
pp.invalidStringToken = function(position, message) { | |
if (this.inTemplateElement && this.options.ecmaVersion >= 9) { | |
throw INVALID_TEMPLATE_ESCAPE_ERROR | |
} else { | |
this.raise(position, message); | |
} | |
}; | |
pp.readTmplToken = function() { | |
var out = "", chunkStart = this.pos; | |
for (;;) { | |
if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated template"); } | |
var ch = this.input.charCodeAt(this.pos); | |
if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${' | |
if (this.pos === this.start && (this.type === types$1.template || this.type === types$1.invalidTemplate)) { | |
if (ch === 36) { | |
this.pos += 2; | |
return this.finishToken(types$1.dollarBraceL) | |
} else { | |
++this.pos; | |
return this.finishToken(types$1.backQuote) | |
} | |
} | |
out += this.input.slice(chunkStart, this.pos); | |
return this.finishToken(types$1.template, out) | |
} | |
if (ch === 92) { // '\' | |
out += this.input.slice(chunkStart, this.pos); | |
out += this.readEscapedChar(true); | |
chunkStart = this.pos; | |
} else if (isNewLine(ch)) { | |
out += this.input.slice(chunkStart, this.pos); | |
++this.pos; | |
switch (ch) { | |
case 13: | |
if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } | |
case 10: | |
out += "\n"; | |
break | |
default: | |
out += String.fromCharCode(ch); | |
break | |
} | |
if (this.options.locations) { | |
++this.curLine; | |
this.lineStart = this.pos; | |
} | |
chunkStart = this.pos; | |
} else { | |
++this.pos; | |
} | |
} | |
}; | |
// Reads a template token to search for the end, without validating any escape sequences | |
pp.readInvalidTemplateToken = function() { | |
for (; this.pos < this.input.length; this.pos++) { | |
switch (this.input[this.pos]) { | |
case "\\": | |
++this.pos; | |
break | |
case "$": | |
if (this.input[this.pos + 1] !== "{") { | |
break | |
} | |
// falls through | |
case "`": | |
return this.finishToken(types$1.invalidTemplate, this.input.slice(this.start, this.pos)) | |
// no default | |
} | |
} | |
this.raise(this.start, "Unterminated template"); | |
}; | |
// Used to read escaped characters | |
pp.readEscapedChar = function(inTemplate) { | |
var ch = this.input.charCodeAt(++this.pos); | |
++this.pos; | |
switch (ch) { | |
case 110: return "\n" // 'n' -> '\n' | |
case 114: return "\r" // 'r' -> '\r' | |
case 120: return String.fromCharCode(this.readHexChar(2)) // 'x' | |
case 117: return codePointToString(this.readCodePoint()) // 'u' | |
case 116: return "\t" // 't' -> '\t' | |
case 98: return "\b" // 'b' -> '\b' | |
case 118: return "\u000b" // 'v' -> '\u000b' | |
case 102: return "\f" // 'f' -> '\f' | |
case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n' | |
case 10: // ' \n' | |
if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; } | |
return "" | |
case 56: | |
case 57: | |
if (this.strict) { | |
this.invalidStringToken( | |
this.pos - 1, | |
"Invalid escape sequence" | |
); | |
} | |
if (inTemplate) { | |
var codePos = this.pos - 1; | |
this.invalidStringToken( | |
codePos, | |
"Invalid escape sequence in template string" | |
); | |
return null | |
} | |
default: | |
if (ch >= 48 && ch <= 55) { | |
var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0]; | |
var octal = parseInt(octalStr, 8); | |
if (octal > 255) { | |
octalStr = octalStr.slice(0, -1); | |
octal = parseInt(octalStr, 8); | |
} | |
this.pos += octalStr.length - 1; | |
ch = this.input.charCodeAt(this.pos); | |
if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) { | |
this.invalidStringToken( | |
this.pos - 1 - octalStr.length, | |
inTemplate | |
? "Octal literal in template string" | |
: "Octal literal in strict mode" | |
); | |
} | |
return String.fromCharCode(octal) | |
} | |
if (isNewLine(ch)) { | |
// Unicode new line characters after \ get removed from output in both | |
// template literals and strings | |
return "" | |
} | |
return String.fromCharCode(ch) | |
} | |
}; | |
// Used to read character escape sequences ('\x', '\u', '\U'). | |
pp.readHexChar = function(len) { | |
var codePos = this.pos; | |
var n = this.readInt(16, len); | |
if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); } | |
return n | |
}; | |
// Read an identifier, and return it as a string. Sets `this.containsEsc` | |
// to whether the word contained a '\u' escape. | |
// | |
// Incrementally adds only escaped chars, adding other chunks as-is | |
// as a micro-optimization. | |
pp.readWord1 = function() { | |
this.containsEsc = false; | |
var word = "", first = true, chunkStart = this.pos; | |
var astral = this.options.ecmaVersion >= 6; | |
while (this.pos < this.input.length) { | |
var ch = this.fullCharCodeAtPos(); | |
if (isIdentifierChar(ch, astral)) { | |
this.pos += ch <= 0xffff ? 1 : 2; | |
} else if (ch === 92) { // "\" | |
this.containsEsc = true; | |
word += this.input.slice(chunkStart, this.pos); | |
var escStart = this.pos; | |
if (this.input.charCodeAt(++this.pos) !== 117) // "u" | |
{ this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX"); } | |
++this.pos; | |
var esc = this.readCodePoint(); | |
if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral)) | |
{ this.invalidStringToken(escStart, "Invalid Unicode escape"); } | |
word += codePointToString(esc); | |
chunkStart = this.pos; | |
} else { | |
break | |
} | |
first = false; | |
} | |
return word + this.input.slice(chunkStart, this.pos) | |
}; | |
// Read an identifier or keyword token. Will check for reserved | |
// words when necessary. | |
pp.readWord = function() { | |
var word = this.readWord1(); | |
var type = types$1.name; | |
if (this.keywords.test(word)) { | |
type = keywords[word]; | |
} | |
return this.finishToken(type, word) | |
}; | |
// Acorn is a tiny, fast JavaScript parser written in JavaScript. | |
var version = "8.6.0"; | |
Parser.acorn = { | |
Parser: Parser, | |
version: version, | |
defaultOptions: defaultOptions, | |
Position: Position, | |
SourceLocation: SourceLocation, | |
getLineInfo: getLineInfo, | |
Node: Node, | |
TokenType: TokenType, | |
tokTypes: types$1, | |
keywordTypes: keywords, | |
TokContext: TokContext, | |
tokContexts: types, | |
isIdentifierChar: isIdentifierChar, | |
isIdentifierStart: isIdentifierStart, | |
Token: Token, | |
isNewLine: isNewLine, | |
lineBreak: lineBreak, | |
lineBreakG: lineBreakG, | |
nonASCIIwhitespace: nonASCIIwhitespace | |
}; | |
// The main exported interface (under `self.acorn` when in the | |
// browser) is a `parse` function that takes a code string and | |
// returns an abstract syntax tree as specified by [Mozilla parser | |
// API][api]. | |
// | |
// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API | |
function parse(input, options) { | |
return Parser.parse(input, options) | |
} | |
// This function tries to parse a single expression at a given | |
// offset in a string. Useful for parsing mixed-language formats | |
// that embed JavaScript expressions. | |
function parseExpressionAt(input, pos, options) { | |
return Parser.parseExpressionAt(input, pos, options) | |
} | |
// Acorn is organized as a tokenizer and a recursive-descent parser. | |
// The `tokenizer` export provides an interface to the tokenizer. | |
function tokenizer(input, options) { | |
return Parser.tokenizer(input, options) | |
} | |
exports.Node = Node; | |
exports.Parser = Parser; | |
exports.Position = Position; | |
exports.SourceLocation = SourceLocation; | |
exports.TokContext = TokContext; | |
exports.Token = Token; | |
exports.TokenType = TokenType; | |
exports.defaultOptions = defaultOptions; | |
exports.getLineInfo = getLineInfo; | |
exports.isIdentifierChar = isIdentifierChar; | |
exports.isIdentifierStart = isIdentifierStart; | |
exports.isNewLine = isNewLine; | |
exports.keywordTypes = keywords; | |
exports.lineBreak = lineBreak; | |
exports.lineBreakG = lineBreakG; | |
exports.nonASCIIwhitespace = nonASCIIwhitespace; | |
exports.parse = parse; | |
exports.parseExpressionAt = parseExpressionAt; | |
exports.tokContexts = types; | |
exports.tokTypes = types$1; | |
exports.tokenizer = tokenizer; | |
exports.version = version; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
})); | |
/***/ }), | |
/***/ 5096: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/* provided dependency */ var console = __webpack_require__(5108); | |
var compileSchema = __webpack_require__(7153) | |
, resolve = __webpack_require__(3610) | |
, Cache = __webpack_require__(7531) | |
, SchemaObject = __webpack_require__(4022) | |
, stableStringify = __webpack_require__(5035) | |
, formats = __webpack_require__(1516) | |
, rules = __webpack_require__(7753) | |
, $dataMetaSchema = __webpack_require__(3978) | |
, util = __webpack_require__(2889); | |
module.exports = Ajv; | |
Ajv.prototype.validate = validate; | |
Ajv.prototype.compile = compile; | |
Ajv.prototype.addSchema = addSchema; | |
Ajv.prototype.addMetaSchema = addMetaSchema; | |
Ajv.prototype.validateSchema = validateSchema; | |
Ajv.prototype.getSchema = getSchema; | |
Ajv.prototype.removeSchema = removeSchema; | |
Ajv.prototype.addFormat = addFormat; | |
Ajv.prototype.errorsText = errorsText; | |
Ajv.prototype._addSchema = _addSchema; | |
Ajv.prototype._compile = _compile; | |
Ajv.prototype.compileAsync = __webpack_require__(2931); | |
var customKeyword = __webpack_require__(4895); | |
Ajv.prototype.addKeyword = customKeyword.add; | |
Ajv.prototype.getKeyword = customKeyword.get; | |
Ajv.prototype.removeKeyword = customKeyword.remove; | |
Ajv.prototype.validateKeyword = customKeyword.validate; | |
var errorClasses = __webpack_require__(7802); | |
Ajv.ValidationError = errorClasses.Validation; | |
Ajv.MissingRefError = errorClasses.MissingRef; | |
Ajv.$dataMetaSchema = $dataMetaSchema; | |
var META_SCHEMA_ID = 'http://json-schema.org/draft-07/schema'; | |
var META_IGNORE_OPTIONS = [ 'removeAdditional', 'useDefaults', 'coerceTypes', 'strictDefaults' ]; | |
var META_SUPPORT_DATA = ['/properties']; | |
/** | |
* Creates validator instance. | |
* Usage: `Ajv(opts)` | |
* @param {Object} opts optional options | |
* @return {Object} ajv instance | |
*/ | |
function Ajv(opts) { | |
if (!(this instanceof Ajv)) return new Ajv(opts); | |
opts = this._opts = util.copy(opts) || {}; | |
setLogger(this); | |
this._schemas = {}; | |
this._refs = {}; | |
this._fragments = {}; | |
this._formats = formats(opts.format); | |
this._cache = opts.cache || new Cache; | |
this._loadingSchemas = {}; | |
this._compilations = []; | |
this.RULES = rules(); | |
this._getId = chooseGetId(opts); | |
opts.loopRequired = opts.loopRequired || Infinity; | |
if (opts.errorDataPath == 'property') opts._errorDataPathProperty = true; | |
if (opts.serialize === undefined) opts.serialize = stableStringify; | |
this._metaOpts = getMetaSchemaOptions(this); | |
if (opts.formats) addInitialFormats(this); | |
if (opts.keywords) addInitialKeywords(this); | |
addDefaultMetaSchema(this); | |
if (typeof opts.meta == 'object') this.addMetaSchema(opts.meta); | |
if (opts.nullable) this.addKeyword('nullable', {metaSchema: {type: 'boolean'}}); | |
addInitialSchemas(this); | |
} | |
/** | |
* Validate data using schema | |
* Schema will be compiled and cached (using serialized JSON as key. [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize. | |
* @this Ajv | |
* @param {String|Object} schemaKeyRef key, ref or schema object | |
* @param {Any} data to be validated | |
* @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`). | |
*/ | |
function validate(schemaKeyRef, data) { | |
var v; | |
if (typeof schemaKeyRef == 'string') { | |
v = this.getSchema(schemaKeyRef); | |
if (!v) throw new Error('no schema with key or ref "' + schemaKeyRef + '"'); | |
} else { | |
var schemaObj = this._addSchema(schemaKeyRef); | |
v = schemaObj.validate || this._compile(schemaObj); | |
} | |
var valid = v(data); | |
if (v.$async !== true) this.errors = v.errors; | |
return valid; | |
} | |
/** | |
* Create validating function for passed schema. | |
* @this Ajv | |
* @param {Object} schema schema object | |
* @param {Boolean} _meta true if schema is a meta-schema. Used internally to compile meta schemas of custom keywords. | |
* @return {Function} validating function | |
*/ | |
function compile(schema, _meta) { | |
var schemaObj = this._addSchema(schema, undefined, _meta); | |
return schemaObj.validate || this._compile(schemaObj); | |
} | |
/** | |
* Adds schema to the instance. | |
* @this Ajv | |
* @param {Object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored. | |
* @param {String} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`. | |
* @param {Boolean} _skipValidation true to skip schema validation. Used internally, option validateSchema should be used instead. | |
* @param {Boolean} _meta true if schema is a meta-schema. Used internally, addMetaSchema should be used instead. | |
* @return {Ajv} this for method chaining | |
*/ | |
function addSchema(schema, key, _skipValidation, _meta) { | |
if (Array.isArray(schema)){ | |
for (var i=0; i<schema.length; i++) this.addSchema(schema[i], undefined, _skipValidation, _meta); | |
return this; | |
} | |
var id = this._getId(schema); | |
if (id !== undefined && typeof id != 'string') | |
throw new Error('schema id must be string'); | |
key = resolve.normalizeId(key || id); | |
checkUnique(this, key); | |
this._schemas[key] = this._addSchema(schema, _skipValidation, _meta, true); | |
return this; | |
} | |
/** | |
* Add schema that will be used to validate other schemas | |
* options in META_IGNORE_OPTIONS are alway set to false | |
* @this Ajv | |
* @param {Object} schema schema object | |
* @param {String} key optional schema key | |
* @param {Boolean} skipValidation true to skip schema validation, can be used to override validateSchema option for meta-schema | |
* @return {Ajv} this for method chaining | |
*/ | |
function addMetaSchema(schema, key, skipValidation) { | |
this.addSchema(schema, key, skipValidation, true); | |
return this; | |
} | |
/** | |
* Validate schema | |
* @this Ajv | |
* @param {Object} schema schema to validate | |
* @param {Boolean} throwOrLogError pass true to throw (or log) an error if invalid | |
* @return {Boolean} true if schema is valid | |
*/ | |
function validateSchema(schema, throwOrLogError) { | |
var $schema = schema.$schema; | |
if ($schema !== undefined && typeof $schema != 'string') | |
throw new Error('$schema must be a string'); | |
$schema = $schema || this._opts.defaultMeta || defaultMeta(this); | |
if (!$schema) { | |
this.logger.warn('meta-schema not available'); | |
this.errors = null; | |
return true; | |
} | |
var valid = this.validate($schema, schema); | |
if (!valid && throwOrLogError) { | |
var message = 'schema is invalid: ' + this.errorsText(); | |
if (this._opts.validateSchema == 'log') this.logger.error(message); | |
else throw new Error(message); | |
} | |
return valid; | |
} | |
function defaultMeta(self) { | |
var meta = self._opts.meta; | |
self._opts.defaultMeta = typeof meta == 'object' | |
? self._getId(meta) || meta | |
: self.getSchema(META_SCHEMA_ID) | |
? META_SCHEMA_ID | |
: undefined; | |
return self._opts.defaultMeta; | |
} | |
/** | |
* Get compiled schema from the instance by `key` or `ref`. | |
* @this Ajv | |
* @param {String} keyRef `key` that was passed to `addSchema` or full schema reference (`schema.id` or resolved id). | |
* @return {Function} schema validating function (with property `schema`). | |
*/ | |
function getSchema(keyRef) { | |
var schemaObj = _getSchemaObj(this, keyRef); | |
switch (typeof schemaObj) { | |
case 'object': return schemaObj.validate || this._compile(schemaObj); | |
case 'string': return this.getSchema(schemaObj); | |
case 'undefined': return _getSchemaFragment(this, keyRef); | |
} | |
} | |
function _getSchemaFragment(self, ref) { | |
var res = resolve.schema.call(self, { schema: {} }, ref); | |
if (res) { | |
var schema = res.schema | |
, root = res.root | |
, baseId = res.baseId; | |
var v = compileSchema.call(self, schema, root, undefined, baseId); | |
self._fragments[ref] = new SchemaObject({ | |
ref: ref, | |
fragment: true, | |
schema: schema, | |
root: root, | |
baseId: baseId, | |
validate: v | |
}); | |
return v; | |
} | |
} | |
function _getSchemaObj(self, keyRef) { | |
keyRef = resolve.normalizeId(keyRef); | |
return self._schemas[keyRef] || self._refs[keyRef] || self._fragments[keyRef]; | |
} | |
/** | |
* Remove cached schema(s). | |
* If no parameter is passed all schemas but meta-schemas are removed. | |
* If RegExp is passed all schemas with key/id matching pattern but meta-schemas are removed. | |
* Even if schema is referenced by other schemas it still can be removed as other schemas have local references. | |
* @this Ajv | |
* @param {String|Object|RegExp} schemaKeyRef key, ref, pattern to match key/ref or schema object | |
* @return {Ajv} this for method chaining | |
*/ | |
function removeSchema(schemaKeyRef) { | |
if (schemaKeyRef instanceof RegExp) { | |
_removeAllSchemas(this, this._schemas, schemaKeyRef); | |
_removeAllSchemas(this, this._refs, schemaKeyRef); | |
return this; | |
} | |
switch (typeof schemaKeyRef) { | |
case 'undefined': | |
_removeAllSchemas(this, this._schemas); | |
_removeAllSchemas(this, this._refs); | |
this._cache.clear(); | |
return this; | |
case 'string': | |
var schemaObj = _getSchemaObj(this, schemaKeyRef); | |
if (schemaObj) this._cache.del(schemaObj.cacheKey); | |
delete this._schemas[schemaKeyRef]; | |
delete this._refs[schemaKeyRef]; | |
return this; | |
case 'object': | |
var serialize = this._opts.serialize; | |
var cacheKey = serialize ? serialize(schemaKeyRef) : schemaKeyRef; | |
this._cache.del(cacheKey); | |
var id = this._getId(schemaKeyRef); | |
if (id) { | |
id = resolve.normalizeId(id); | |
delete this._schemas[id]; | |
delete this._refs[id]; | |
} | |
} | |
return this; | |
} | |
function _removeAllSchemas(self, schemas, regex) { | |
for (var keyRef in schemas) { | |
var schemaObj = schemas[keyRef]; | |
if (!schemaObj.meta && (!regex || regex.test(keyRef))) { | |
self._cache.del(schemaObj.cacheKey); | |
delete schemas[keyRef]; | |
} | |
} | |
} | |
/* @this Ajv */ | |
function _addSchema(schema, skipValidation, meta, shouldAddSchema) { | |
if (typeof schema != 'object' && typeof schema != 'boolean') | |
throw new Error('schema should be object or boolean'); | |
var serialize = this._opts.serialize; | |
var cacheKey = serialize ? serialize(schema) : schema; | |
var cached = this._cache.get(cacheKey); | |
if (cached) return cached; | |
shouldAddSchema = shouldAddSchema || this._opts.addUsedSchema !== false; | |
var id = resolve.normalizeId(this._getId(schema)); | |
if (id && shouldAddSchema) checkUnique(this, id); | |
var willValidate = this._opts.validateSchema !== false && !skipValidation; | |
var recursiveMeta; | |
if (willValidate && !(recursiveMeta = id && id == resolve.normalizeId(schema.$schema))) | |
this.validateSchema(schema, true); | |
var localRefs = resolve.ids.call(this, schema); | |
var schemaObj = new SchemaObject({ | |
id: id, | |
schema: schema, | |
localRefs: localRefs, | |
cacheKey: cacheKey, | |
meta: meta | |
}); | |
if (id[0] != '#' && shouldAddSchema) this._refs[id] = schemaObj; | |
this._cache.put(cacheKey, schemaObj); | |
if (willValidate && recursiveMeta) this.validateSchema(schema, true); | |
return schemaObj; | |
} | |
/* @this Ajv */ | |
function _compile(schemaObj, root) { | |
if (schemaObj.compiling) { | |
schemaObj.validate = callValidate; | |
callValidate.schema = schemaObj.schema; | |
callValidate.errors = null; | |
callValidate.root = root ? root : callValidate; | |
if (schemaObj.schema.$async === true) | |
callValidate.$async = true; | |
return callValidate; | |
} | |
schemaObj.compiling = true; | |
var currentOpts; | |
if (schemaObj.meta) { | |
currentOpts = this._opts; | |
this._opts = this._metaOpts; | |
} | |
var v; | |
try { v = compileSchema.call(this, schemaObj.schema, root, schemaObj.localRefs); } | |
catch(e) { | |
delete schemaObj.validate; | |
throw e; | |
} | |
finally { | |
schemaObj.compiling = false; | |
if (schemaObj.meta) this._opts = currentOpts; | |
} | |
schemaObj.validate = v; | |
schemaObj.refs = v.refs; | |
schemaObj.refVal = v.refVal; | |
schemaObj.root = v.root; | |
return v; | |
/* @this {*} - custom context, see passContext option */ | |
function callValidate() { | |
/* jshint validthis: true */ | |
var _validate = schemaObj.validate; | |
var result = _validate.apply(this, arguments); | |
callValidate.errors = _validate.errors; | |
return result; | |
} | |
} | |
function chooseGetId(opts) { | |
switch (opts.schemaId) { | |
case 'auto': return _get$IdOrId; | |
case 'id': return _getId; | |
default: return _get$Id; | |
} | |
} | |
/* @this Ajv */ | |
function _getId(schema) { | |
if (schema.$id) this.logger.warn('schema $id ignored', schema.$id); | |
return schema.id; | |
} | |
/* @this Ajv */ | |
function _get$Id(schema) { | |
if (schema.id) this.logger.warn('schema id ignored', schema.id); | |
return schema.$id; | |
} | |
function _get$IdOrId(schema) { | |
if (schema.$id && schema.id && schema.$id != schema.id) | |
throw new Error('schema $id is different from id'); | |
return schema.$id || schema.id; | |
} | |
/** | |
* Convert array of error message objects to string | |
* @this Ajv | |
* @param {Array<Object>} errors optional array of validation errors, if not passed errors from the instance are used. | |
* @param {Object} options optional options with properties `separator` and `dataVar`. | |
* @return {String} human readable string with all errors descriptions | |
*/ | |
function errorsText(errors, options) { | |
errors = errors || this.errors; | |
if (!errors) return 'No errors'; | |
options = options || {}; | |
var separator = options.separator === undefined ? ', ' : options.separator; | |
var dataVar = options.dataVar === undefined ? 'data' : options.dataVar; | |
var text = ''; | |
for (var i=0; i<errors.length; i++) { | |
var e = errors[i]; | |
if (e) text += dataVar + e.dataPath + ' ' + e.message + separator; | |
} | |
return text.slice(0, -separator.length); | |
} | |
/** | |
* Add custom format | |
* @this Ajv | |
* @param {String} name format name | |
* @param {String|RegExp|Function} format string is converted to RegExp; function should return boolean (true when valid) | |
* @return {Ajv} this for method chaining | |
*/ | |
function addFormat(name, format) { | |
if (typeof format == 'string') format = new RegExp(format); | |
this._formats[name] = format; | |
return this; | |
} | |
function addDefaultMetaSchema(self) { | |
var $dataSchema; | |
if (self._opts.$data) { | |
$dataSchema = __webpack_require__(894); | |
self.addMetaSchema($dataSchema, $dataSchema.$id, true); | |
} | |
if (self._opts.meta === false) return; | |
var metaSchema = __webpack_require__(6680); | |
if (self._opts.$data) metaSchema = $dataMetaSchema(metaSchema, META_SUPPORT_DATA); | |
self.addMetaSchema(metaSchema, META_SCHEMA_ID, true); | |
self._refs['http://json-schema.org/schema'] = META_SCHEMA_ID; | |
} | |
function addInitialSchemas(self) { | |
var optsSchemas = self._opts.schemas; | |
if (!optsSchemas) return; | |
if (Array.isArray(optsSchemas)) self.addSchema(optsSchemas); | |
else for (var key in optsSchemas) self.addSchema(optsSchemas[key], key); | |
} | |
function addInitialFormats(self) { | |
for (var name in self._opts.formats) { | |
var format = self._opts.formats[name]; | |
self.addFormat(name, format); | |
} | |
} | |
function addInitialKeywords(self) { | |
for (var name in self._opts.keywords) { | |
var keyword = self._opts.keywords[name]; | |
self.addKeyword(name, keyword); | |
} | |
} | |
function checkUnique(self, id) { | |
if (self._schemas[id] || self._refs[id]) | |
throw new Error('schema with key or id "' + id + '" already exists'); | |
} | |
function getMetaSchemaOptions(self) { | |
var metaOpts = util.copy(self._opts); | |
for (var i=0; i<META_IGNORE_OPTIONS.length; i++) | |
delete metaOpts[META_IGNORE_OPTIONS[i]]; | |
return metaOpts; | |
} | |
function setLogger(self) { | |
var logger = self._opts.logger; | |
if (logger === false) { | |
self.logger = {log: noop, warn: noop, error: noop}; | |
} else { | |
if (logger === undefined) logger = console; | |
if (!(typeof logger == 'object' && logger.log && logger.warn && logger.error)) | |
throw new Error('logger must implement log, warn and error methods'); | |
self.logger = logger; | |
} | |
} | |
function noop() {} | |
/***/ }), | |
/***/ 7531: | |
/***/ (function(module) { | |
"use strict"; | |
var Cache = module.exports = function Cache() { | |
this._cache = {}; | |
}; | |
Cache.prototype.put = function Cache_put(key, value) { | |
this._cache[key] = value; | |
}; | |
Cache.prototype.get = function Cache_get(key) { | |
return this._cache[key]; | |
}; | |
Cache.prototype.del = function Cache_del(key) { | |
delete this._cache[key]; | |
}; | |
Cache.prototype.clear = function Cache_clear() { | |
this._cache = {}; | |
}; | |
/***/ }), | |
/***/ 2931: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
var MissingRefError = (__webpack_require__(7802).MissingRef); | |
module.exports = compileAsync; | |
/** | |
* Creates validating function for passed schema with asynchronous loading of missing schemas. | |
* `loadSchema` option should be a function that accepts schema uri and returns promise that resolves with the schema. | |
* @this Ajv | |
* @param {Object} schema schema object | |
* @param {Boolean} meta optional true to compile meta-schema; this parameter can be skipped | |
* @param {Function} callback an optional node-style callback, it is called with 2 parameters: error (or null) and validating function. | |
* @return {Promise} promise that resolves with a validating function. | |
*/ | |
function compileAsync(schema, meta, callback) { | |
/* eslint no-shadow: 0 */ | |
/* global Promise */ | |
/* jshint validthis: true */ | |
var self = this; | |
if (typeof this._opts.loadSchema != 'function') | |
throw new Error('options.loadSchema should be a function'); | |
if (typeof meta == 'function') { | |
callback = meta; | |
meta = undefined; | |
} | |
var p = loadMetaSchemaOf(schema).then(function () { | |
var schemaObj = self._addSchema(schema, undefined, meta); | |
return schemaObj.validate || _compileAsync(schemaObj); | |
}); | |
if (callback) { | |
p.then( | |
function(v) { callback(null, v); }, | |
callback | |
); | |
} | |
return p; | |
function loadMetaSchemaOf(sch) { | |
var $schema = sch.$schema; | |
return $schema && !self.getSchema($schema) | |
? compileAsync.call(self, { $ref: $schema }, true) | |
: Promise.resolve(); | |
} | |
function _compileAsync(schemaObj) { | |
try { return self._compile(schemaObj); } | |
catch(e) { | |
if (e instanceof MissingRefError) return loadMissingSchema(e); | |
throw e; | |
} | |
function loadMissingSchema(e) { | |
var ref = e.missingSchema; | |
if (added(ref)) throw new Error('Schema ' + ref + ' is loaded but ' + e.missingRef + ' cannot be resolved'); | |
var schemaPromise = self._loadingSchemas[ref]; | |
if (!schemaPromise) { | |
schemaPromise = self._loadingSchemas[ref] = self._opts.loadSchema(ref); | |
schemaPromise.then(removePromise, removePromise); | |
} | |
return schemaPromise.then(function (sch) { | |
if (!added(ref)) { | |
return loadMetaSchemaOf(sch).then(function () { | |
if (!added(ref)) self.addSchema(sch, ref, undefined, meta); | |
}); | |
} | |
}).then(function() { | |
return _compileAsync(schemaObj); | |
}); | |
function removePromise() { | |
delete self._loadingSchemas[ref]; | |
} | |
function added(ref) { | |
return self._refs[ref] || self._schemas[ref]; | |
} | |
} | |
} | |
} | |
/***/ }), | |
/***/ 7802: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
var resolve = __webpack_require__(3610); | |
module.exports = { | |
Validation: errorSubclass(ValidationError), | |
MissingRef: errorSubclass(MissingRefError) | |
}; | |
function ValidationError(errors) { | |
this.message = 'validation failed'; | |
this.errors = errors; | |
this.ajv = this.validation = true; | |
} | |
MissingRefError.message = function (baseId, ref) { | |
return 'can\'t resolve reference ' + ref + ' from id ' + baseId; | |
}; | |
function MissingRefError(baseId, ref, message) { | |
this.message = message || MissingRefError.message(baseId, ref); | |
this.missingRef = resolve.url(baseId, ref); | |
this.missingSchema = resolve.normalizeId(resolve.fullPath(this.missingRef)); | |
} | |
function errorSubclass(Subclass) { | |
Subclass.prototype = Object.create(Error.prototype); | |
Subclass.prototype.constructor = Subclass; | |
return Subclass; | |
} | |
/***/ }), | |
/***/ 1516: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
var util = __webpack_require__(2889); | |
var DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/; | |
var DAYS = [0,31,28,31,30,31,30,31,31,30,31,30,31]; | |
var TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d(?::?\d\d)?)?$/i; | |
var HOSTNAME = /^(?=.{1,253}\.?$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*\.?$/i; | |
var URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i; | |
var URIREF = /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i; | |
// uri-template: https://tools.ietf.org/html/rfc6570 | |
var URITEMPLATE = /^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i; | |
// For the source: https://gist.github.com/dperini/729294 | |
// For test cases: https://mathiasbynens.be/demo/url-regex | |
// @todo Delete current URL in favour of the commented out URL rule when this issue is fixed https://github.com/eslint/eslint/issues/7983. | |
// var URL = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u{00a1}-\u{ffff}0-9]+-)*[a-z\u{00a1}-\u{ffff}0-9]+)(?:\.(?:[a-z\u{00a1}-\u{ffff}0-9]+-)*[a-z\u{00a1}-\u{ffff}0-9]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu; | |
var URL = /^(?:(?:http[s\u017F]?|ftp):\/\/)(?:(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+(?::(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?@)?(?:(?!10(?:\.[0-9]{1,3}){3})(?!127(?:\.[0-9]{1,3}){3})(?!169\.254(?:\.[0-9]{1,3}){2})(?!192\.168(?:\.[0-9]{1,3}){2})(?!172\.(?:1[6-9]|2[0-9]|3[01])(?:\.[0-9]{1,3}){2})(?:[1-9][0-9]?|1[0-9][0-9]|2[01][0-9]|22[0-3])(?:\.(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])){2}(?:\.(?:[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))|(?:(?:(?:[0-9a-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-)*(?:[0-9a-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)(?:\.(?:(?:[0-9a-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-)*(?:[0-9a-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)*(?:\.(?:(?:[a-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){2,})))(?::[0-9]{2,5})?(?:\/(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?$/i; | |
var UUID = /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i; | |
var JSON_POINTER = /^(?:\/(?:[^~/]|~0|~1)*)*$/; | |
var JSON_POINTER_URI_FRAGMENT = /^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i; | |
var RELATIVE_JSON_POINTER = /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/; | |
module.exports = formats; | |
function formats(mode) { | |
mode = mode == 'full' ? 'full' : 'fast'; | |
return util.copy(formats[mode]); | |
} | |
formats.fast = { | |
// date: http://tools.ietf.org/html/rfc3339#section-5.6 | |
date: /^\d\d\d\d-[0-1]\d-[0-3]\d$/, | |
// date-time: http://tools.ietf.org/html/rfc3339#section-5.6 | |
time: /^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)?$/i, | |
'date-time': /^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)$/i, | |
// uri: https://github.com/mafintosh/is-my-json-valid/blob/master/formats.js | |
uri: /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/)?[^\s]*$/i, | |
'uri-reference': /^(?:(?:[a-z][a-z0-9+\-.]*:)?\/?\/)?(?:[^\\\s#][^\s#]*)?(?:#[^\\\s]*)?$/i, | |
'uri-template': URITEMPLATE, | |
url: URL, | |
// email (sources from jsen validator): | |
// http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address#answer-8829363 | |
// http://www.w3.org/TR/html5/forms.html#valid-e-mail-address (search for 'willful violation') | |
email: /^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i, | |
hostname: HOSTNAME, | |
// optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html | |
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/, | |
// optimized http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses | |
ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i, | |
regex: regex, | |
// uuid: http://tools.ietf.org/html/rfc4122 | |
uuid: UUID, | |
// JSON-pointer: https://tools.ietf.org/html/rfc6901 | |
// uri fragment: https://tools.ietf.org/html/rfc3986#appendix-A | |
'json-pointer': JSON_POINTER, | |
'json-pointer-uri-fragment': JSON_POINTER_URI_FRAGMENT, | |
// relative JSON-pointer: http://tools.ietf.org/html/draft-luff-relative-json-pointer-00 | |
'relative-json-pointer': RELATIVE_JSON_POINTER | |
}; | |
formats.full = { | |
date: date, | |
time: time, | |
'date-time': date_time, | |
uri: uri, | |
'uri-reference': URIREF, | |
'uri-template': URITEMPLATE, | |
url: URL, | |
email: /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i, | |
hostname: HOSTNAME, | |
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/, | |
ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i, | |
regex: regex, | |
uuid: UUID, | |
'json-pointer': JSON_POINTER, | |
'json-pointer-uri-fragment': JSON_POINTER_URI_FRAGMENT, | |
'relative-json-pointer': RELATIVE_JSON_POINTER | |
}; | |
function isLeapYear(year) { | |
// https://tools.ietf.org/html/rfc3339#appendix-C | |
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); | |
} | |
function date(str) { | |
// full-date from http://tools.ietf.org/html/rfc3339#section-5.6 | |
var matches = str.match(DATE); | |
if (!matches) return false; | |
var year = +matches[1]; | |
var month = +matches[2]; | |
var day = +matches[3]; | |
return month >= 1 && month <= 12 && day >= 1 && | |
day <= (month == 2 && isLeapYear(year) ? 29 : DAYS[month]); | |
} | |
function time(str, full) { | |
var matches = str.match(TIME); | |
if (!matches) return false; | |
var hour = matches[1]; | |
var minute = matches[2]; | |
var second = matches[3]; | |
var timeZone = matches[5]; | |
return ((hour <= 23 && minute <= 59 && second <= 59) || | |
(hour == 23 && minute == 59 && second == 60)) && | |
(!full || timeZone); | |
} | |
var DATE_TIME_SEPARATOR = /t|\s/i; | |
function date_time(str) { | |
// http://tools.ietf.org/html/rfc3339#section-5.6 | |
var dateTime = str.split(DATE_TIME_SEPARATOR); | |
return dateTime.length == 2 && date(dateTime[0]) && time(dateTime[1], true); | |
} | |
var NOT_URI_FRAGMENT = /\/|:/; | |
function uri(str) { | |
// http://jmrware.com/articles/2009/uri_regexp/URI_regex.html + optional protocol + required "." | |
return NOT_URI_FRAGMENT.test(str) && URI.test(str); | |
} | |
var Z_ANCHOR = /[^\\]\\Z/; | |
function regex(str) { | |
if (Z_ANCHOR.test(str)) return false; | |
try { | |
new RegExp(str); | |
return true; | |
} catch(e) { | |
return false; | |
} | |
} | |
/***/ }), | |
/***/ 7153: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
var resolve = __webpack_require__(3610) | |
, util = __webpack_require__(2889) | |
, errorClasses = __webpack_require__(7802) | |
, stableStringify = __webpack_require__(5035); | |
var validateGenerator = __webpack_require__(9508); | |
/** | |
* Functions below are used inside compiled validations function | |
*/ | |
var ucs2length = util.ucs2length; | |
var equal = __webpack_require__(4063); | |
// this error is thrown by async schemas to return validation errors via exception | |
var ValidationError = errorClasses.Validation; | |
module.exports = compile; | |
/** | |
* Compiles schema to validation function | |
* @this Ajv | |
* @param {Object} schema schema object | |
* @param {Object} root object with information about the root schema for this schema | |
* @param {Object} localRefs the hash of local references inside the schema (created by resolve.id), used for inline resolution | |
* @param {String} baseId base ID for IDs in the schema | |
* @return {Function} validation function | |
*/ | |
function compile(schema, root, localRefs, baseId) { | |
/* jshint validthis: true, evil: true */ | |
/* eslint no-shadow: 0 */ | |
var self = this | |
, opts = this._opts | |
, refVal = [ undefined ] | |
, refs = {} | |
, patterns = [] | |
, patternsHash = {} | |
, defaults = [] | |
, defaultsHash = {} | |
, customRules = []; | |
root = root || { schema: schema, refVal: refVal, refs: refs }; | |
var c = checkCompiling.call(this, schema, root, baseId); | |
var compilation = this._compilations[c.index]; | |
if (c.compiling) return (compilation.callValidate = callValidate); | |
var formats = this._formats; | |
var RULES = this.RULES; | |
try { | |
var v = localCompile(schema, root, localRefs, baseId); | |
compilation.validate = v; | |
var cv = compilation.callValidate; | |
if (cv) { | |
cv.schema = v.schema; | |
cv.errors = null; | |
cv.refs = v.refs; | |
cv.refVal = v.refVal; | |
cv.root = v.root; | |
cv.$async = v.$async; | |
if (opts.sourceCode) cv.source = v.source; | |
} | |
return v; | |
} finally { | |
endCompiling.call(this, schema, root, baseId); | |
} | |
/* @this {*} - custom context, see passContext option */ | |
function callValidate() { | |
/* jshint validthis: true */ | |
var validate = compilation.validate; | |
var result = validate.apply(this, arguments); | |
callValidate.errors = validate.errors; | |
return result; | |
} | |
function localCompile(_schema, _root, localRefs, baseId) { | |
var isRoot = !_root || (_root && _root.schema == _schema); | |
if (_root.schema != root.schema) | |
return compile.call(self, _schema, _root, localRefs, baseId); | |
var $async = _schema.$async === true; | |
var sourceCode = validateGenerator({ | |
isTop: true, | |
schema: _schema, | |
isRoot: isRoot, | |
baseId: baseId, | |
root: _root, | |
schemaPath: '', | |
errSchemaPath: '#', | |
errorPath: '""', | |
MissingRefError: errorClasses.MissingRef, | |
RULES: RULES, | |
validate: validateGenerator, | |
util: util, | |
resolve: resolve, | |
resolveRef: resolveRef, | |
usePattern: usePattern, | |
useDefault: useDefault, | |
useCustomRule: useCustomRule, | |
opts: opts, | |
formats: formats, | |
logger: self.logger, | |
self: self | |
}); | |
sourceCode = vars(refVal, refValCode) + vars(patterns, patternCode) | |
+ vars(defaults, defaultCode) + vars(customRules, customRuleCode) | |
+ sourceCode; | |
if (opts.processCode) sourceCode = opts.processCode(sourceCode, _schema); | |
// console.log('\n\n\n *** \n', JSON.stringify(sourceCode)); | |
var validate; | |
try { | |
var makeValidate = new Function( | |
'self', | |
'RULES', | |
'formats', | |
'root', | |
'refVal', | |
'defaults', | |
'customRules', | |
'equal', | |
'ucs2length', | |
'ValidationError', | |
sourceCode | |
); | |
validate = makeValidate( | |
self, | |
RULES, | |
formats, | |
root, | |
refVal, | |
defaults, | |
customRules, | |
equal, | |
ucs2length, | |
ValidationError | |
); | |
refVal[0] = validate; | |
} catch(e) { | |
self.logger.error('Error compiling schema, function code:', sourceCode); | |
throw e; | |
} | |
validate.schema = _schema; | |
validate.errors = null; | |
validate.refs = refs; | |
validate.refVal = refVal; | |
validate.root = isRoot ? validate : _root; | |
if ($async) validate.$async = true; | |
if (opts.sourceCode === true) { | |
validate.source = { | |
code: sourceCode, | |
patterns: patterns, | |
defaults: defaults | |
}; | |
} | |
return validate; | |
} | |
function resolveRef(baseId, ref, isRoot) { | |
ref = resolve.url(baseId, ref); | |
var refIndex = refs[ref]; | |
var _refVal, refCode; | |
if (refIndex !== undefined) { | |
_refVal = refVal[refIndex]; | |
refCode = 'refVal[' + refIndex + ']'; | |
return resolvedRef(_refVal, refCode); | |
} | |
if (!isRoot && root.refs) { | |
var rootRefId = root.refs[ref]; | |
if (rootRefId !== undefined) { | |
_refVal = root.refVal[rootRefId]; | |
refCode = addLocalRef(ref, _refVal); | |
return resolvedRef(_refVal, refCode); | |
} | |
} | |
refCode = addLocalRef(ref); | |
var v = resolve.call(self, localCompile, root, ref); | |
if (v === undefined) { | |
var localSchema = localRefs && localRefs[ref]; | |
if (localSchema) { | |
v = resolve.inlineRef(localSchema, opts.inlineRefs) | |
? localSchema | |
: compile.call(self, localSchema, root, localRefs, baseId); | |
} | |
} | |
if (v === undefined) { | |
removeLocalRef(ref); | |
} else { | |
replaceLocalRef(ref, v); | |
return resolvedRef(v, refCode); | |
} | |
} | |
function addLocalRef(ref, v) { | |
var refId = refVal.length; | |
refVal[refId] = v; | |
refs[ref] = refId; | |
return 'refVal' + refId; | |
} | |
function removeLocalRef(ref) { | |
delete refs[ref]; | |
} | |
function replaceLocalRef(ref, v) { | |
var refId = refs[ref]; | |
refVal[refId] = v; | |
} | |
function resolvedRef(refVal, code) { | |
return typeof refVal == 'object' || typeof refVal == 'boolean' | |
? { code: code, schema: refVal, inline: true } | |
: { code: code, $async: refVal && !!refVal.$async }; | |
} | |
function usePattern(regexStr) { | |
var index = patternsHash[regexStr]; | |
if (index === undefined) { | |
index = patternsHash[regexStr] = patterns.length; | |
patterns[index] = regexStr; | |
} | |
return 'pattern' + index; | |
} | |
function useDefault(value) { | |
switch (typeof value) { | |
case 'boolean': | |
case 'number': | |
return '' + value; | |
case 'string': | |
return util.toQuotedString(value); | |
case 'object': | |
if (value === null) return 'null'; | |
var valueStr = stableStringify(value); | |
var index = defaultsHash[valueStr]; | |
if (index === undefined) { | |
index = defaultsHash[valueStr] = defaults.length; | |
defaults[index] = value; | |
} | |
return 'default' + index; | |
} | |
} | |
function useCustomRule(rule, schema, parentSchema, it) { | |
if (self._opts.validateSchema !== false) { | |
var deps = rule.definition.dependencies; | |
if (deps && !deps.every(function(keyword) { | |
return Object.prototype.hasOwnProperty.call(parentSchema, keyword); | |
})) | |
throw new Error('parent schema must have all required keywords: ' + deps.join(',')); | |
var validateSchema = rule.definition.validateSchema; | |
if (validateSchema) { | |
var valid = validateSchema(schema); | |
if (!valid) { | |
var message = 'keyword schema is invalid: ' + self.errorsText(validateSchema.errors); | |
if (self._opts.validateSchema == 'log') self.logger.error(message); | |
else throw new Error(message); | |
} | |
} | |
} | |
var compile = rule.definition.compile | |
, inline = rule.definition.inline | |
, macro = rule.definition.macro; | |
var validate; | |
if (compile) { | |
validate = compile.call(self, schema, parentSchema, it); | |
} else if (macro) { | |
validate = macro.call(self, schema, parentSchema, it); | |
if (opts.validateSchema !== false) self.validateSchema(validate, true); | |
} else if (inline) { | |
validate = inline.call(self, it, rule.keyword, schema, parentSchema); | |
} else { | |
validate = rule.definition.validate; | |
if (!validate) return; | |
} | |
if (validate === undefined) | |
throw new Error('custom keyword "' + rule.keyword + '"failed to compile'); | |
var index = customRules.length; | |
customRules[index] = validate; | |
return { | |
code: 'customRule' + index, | |
validate: validate | |
}; | |
} | |
} | |
/** | |
* Checks if the schema is currently compiled | |
* @this Ajv | |
* @param {Object} schema schema to compile | |
* @param {Object} root root object | |
* @param {String} baseId base schema ID | |
* @return {Object} object with properties "index" (compilation index) and "compiling" (boolean) | |
*/ | |
function checkCompiling(schema, root, baseId) { | |
/* jshint validthis: true */ | |
var index = compIndex.call(this, schema, root, baseId); | |
if (index >= 0) return { index: index, compiling: true }; | |
index = this._compilations.length; | |
this._compilations[index] = { | |
schema: schema, | |
root: root, | |
baseId: baseId | |
}; | |
return { index: index, compiling: false }; | |
} | |
/** | |
* Removes the schema from the currently compiled list | |
* @this Ajv | |
* @param {Object} schema schema to compile | |
* @param {Object} root root object | |
* @param {String} baseId base schema ID | |
*/ | |
function endCompiling(schema, root, baseId) { | |
/* jshint validthis: true */ | |
var i = compIndex.call(this, schema, root, baseId); | |
if (i >= 0) this._compilations.splice(i, 1); | |
} | |
/** | |
* Index of schema compilation in the currently compiled list | |
* @this Ajv | |
* @param {Object} schema schema to compile | |
* @param {Object} root root object | |
* @param {String} baseId base schema ID | |
* @return {Integer} compilation index | |
*/ | |
function compIndex(schema, root, baseId) { | |
/* jshint validthis: true */ | |
for (var i=0; i<this._compilations.length; i++) { | |
var c = this._compilations[i]; | |
if (c.schema == schema && c.root == root && c.baseId == baseId) return i; | |
} | |
return -1; | |
} | |
function patternCode(i, patterns) { | |
return 'var pattern' + i + ' = new RegExp(' + util.toQuotedString(patterns[i]) + ');'; | |
} | |
function defaultCode(i) { | |
return 'var default' + i + ' = defaults[' + i + '];'; | |
} | |
function refValCode(i, refVal) { | |
return refVal[i] === undefined ? '' : 'var refVal' + i + ' = refVal[' + i + '];'; | |
} | |
function customRuleCode(i) { | |
return 'var customRule' + i + ' = customRules[' + i + '];'; | |
} | |
function vars(arr, statement) { | |
if (!arr.length) return ''; | |
var code = ''; | |
for (var i=0; i<arr.length; i++) | |
code += statement(i, arr); | |
return code; | |
} | |
/***/ }), | |
/***/ 3610: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
var URI = __webpack_require__(540) | |
, equal = __webpack_require__(4063) | |
, util = __webpack_require__(2889) | |
, SchemaObject = __webpack_require__(4022) | |
, traverse = __webpack_require__(9461); | |
module.exports = resolve; | |
resolve.normalizeId = normalizeId; | |
resolve.fullPath = getFullPath; | |
resolve.url = resolveUrl; | |
resolve.ids = resolveIds; | |
resolve.inlineRef = inlineRef; | |
resolve.schema = resolveSchema; | |
/** | |
* [resolve and compile the references ($ref)] | |
* @this Ajv | |
* @param {Function} compile reference to schema compilation funciton (localCompile) | |
* @param {Object} root object with information about the root schema for the current schema | |
* @param {String} ref reference to resolve | |
* @return {Object|Function} schema object (if the schema can be inlined) or validation function | |
*/ | |
function resolve(compile, root, ref) { | |
/* jshint validthis: true */ | |
var refVal = this._refs[ref]; | |
if (typeof refVal == 'string') { | |
if (this._refs[refVal]) refVal = this._refs[refVal]; | |
else return resolve.call(this, compile, root, refVal); | |
} | |
refVal = refVal || this._schemas[ref]; | |
if (refVal instanceof SchemaObject) { | |
return inlineRef(refVal.schema, this._opts.inlineRefs) | |
? refVal.schema | |
: refVal.validate || this._compile(refVal); | |
} | |
var res = resolveSchema.call(this, root, ref); | |
var schema, v, baseId; | |
if (res) { | |
schema = res.schema; | |
root = res.root; | |
baseId = res.baseId; | |
} | |
if (schema instanceof SchemaObject) { | |
v = schema.validate || compile.call(this, schema.schema, root, undefined, baseId); | |
} else if (schema !== undefined) { | |
v = inlineRef(schema, this._opts.inlineRefs) | |
? schema | |
: compile.call(this, schema, root, undefined, baseId); | |
} | |
return v; | |
} | |
/** | |
* Resolve schema, its root and baseId | |
* @this Ajv | |
* @param {Object} root root object with properties schema, refVal, refs | |
* @param {String} ref reference to resolve | |
* @return {Object} object with properties schema, root, baseId | |
*/ | |
function resolveSchema(root, ref) { | |
/* jshint validthis: true */ | |
var p = URI.parse(ref) | |
, refPath = _getFullPath(p) | |
, baseId = getFullPath(this._getId(root.schema)); | |
if (Object.keys(root.schema).length === 0 || refPath !== baseId) { | |
var id = normalizeId(refPath); | |
var refVal = this._refs[id]; | |
if (typeof refVal == 'string') { | |
return resolveRecursive.call(this, root, refVal, p); | |
} else if (refVal instanceof SchemaObject) { | |
if (!refVal.validate) this._compile(refVal); | |
root = refVal; | |
} else { | |
refVal = this._schemas[id]; | |
if (refVal instanceof SchemaObject) { | |
if (!refVal.validate) this._compile(refVal); | |
if (id == normalizeId(ref)) | |
return { schema: refVal, root: root, baseId: baseId }; | |
root = refVal; | |
} else { | |
return; | |
} | |
} | |
if (!root.schema) return; | |
baseId = getFullPath(this._getId(root.schema)); | |
} | |
return getJsonPointer.call(this, p, baseId, root.schema, root); | |
} | |
/* @this Ajv */ | |
function resolveRecursive(root, ref, parsedRef) { | |
/* jshint validthis: true */ | |
var res = resolveSchema.call(this, root, ref); | |
if (res) { | |
var schema = res.schema; | |
var baseId = res.baseId; | |
root = res.root; | |
var id = this._getId(schema); | |
if (id) baseId = resolveUrl(baseId, id); | |
return getJsonPointer.call(this, parsedRef, baseId, schema, root); | |
} | |
} | |
var PREVENT_SCOPE_CHANGE = util.toHash(['properties', 'patternProperties', 'enum', 'dependencies', 'definitions']); | |
/* @this Ajv */ | |
function getJsonPointer(parsedRef, baseId, schema, root) { | |
/* jshint validthis: true */ | |
parsedRef.fragment = parsedRef.fragment || ''; | |
if (parsedRef.fragment.slice(0,1) != '/') return; | |
var parts = parsedRef.fragment.split('/'); | |
for (var i = 1; i < parts.length; i++) { | |
var part = parts[i]; | |
if (part) { | |
part = util.unescapeFragment(part); | |
schema = schema[part]; | |
if (schema === undefined) break; | |
var id; | |
if (!PREVENT_SCOPE_CHANGE[part]) { | |
id = this._getId(schema); | |
if (id) baseId = resolveUrl(baseId, id); | |
if (schema.$ref) { | |
var $ref = resolveUrl(baseId, schema.$ref); | |
var res = resolveSchema.call(this, root, $ref); | |
if (res) { | |
schema = res.schema; | |
root = res.root; | |
baseId = res.baseId; | |
} | |
} | |
} | |
} | |
} | |
if (schema !== undefined && schema !== root.schema) | |
return { schema: schema, root: root, baseId: baseId }; | |
} | |
var SIMPLE_INLINED = util.toHash([ | |
'type', 'format', 'pattern', | |
'maxLength', 'minLength', | |
'maxProperties', 'minProperties', | |
'maxItems', 'minItems', | |
'maximum', 'minimum', | |
'uniqueItems', 'multipleOf', | |
'required', 'enum' | |
]); | |
function inlineRef(schema, limit) { | |
if (limit === false) return false; | |
if (limit === undefined || limit === true) return checkNoRef(schema); | |
else if (limit) return countKeys(schema) <= limit; | |
} | |
function checkNoRef(schema) { | |
var item; | |
if (Array.isArray(schema)) { | |
for (var i=0; i<schema.length; i++) { | |
item = schema[i]; | |
if (typeof item == 'object' && !checkNoRef(item)) return false; | |
} | |
} else { | |
for (var key in schema) { | |
if (key == '$ref') return false; | |
item = schema[key]; | |
if (typeof item == 'object' && !checkNoRef(item)) return false; | |
} | |
} | |
return true; | |
} | |
function countKeys(schema) { | |
var count = 0, item; | |
if (Array.isArray(schema)) { | |
for (var i=0; i<schema.length; i++) { | |
item = schema[i]; | |
if (typeof item == 'object') count += countKeys(item); | |
if (count == Infinity) return Infinity; | |
} | |
} else { | |
for (var key in schema) { | |
if (key == '$ref') return Infinity; | |
if (SIMPLE_INLINED[key]) { | |
count++; | |
} else { | |
item = schema[key]; | |
if (typeof item == 'object') count += countKeys(item) + 1; | |
if (count == Infinity) return Infinity; | |
} | |
} | |
} | |
return count; | |
} | |
function getFullPath(id, normalize) { | |
if (normalize !== false) id = normalizeId(id); | |
var p = URI.parse(id); | |
return _getFullPath(p); | |
} | |
function _getFullPath(p) { | |
return URI.serialize(p).split('#')[0] + '#'; | |
} | |
var TRAILING_SLASH_HASH = /#\/?$/; | |
function normalizeId(id) { | |
return id ? id.replace(TRAILING_SLASH_HASH, '') : ''; | |
} | |
function resolveUrl(baseId, id) { | |
id = normalizeId(id); | |
return URI.resolve(baseId, id); | |
} | |
/* @this Ajv */ | |
function resolveIds(schema) { | |
var schemaId = normalizeId(this._getId(schema)); | |
var baseIds = {'': schemaId}; | |
var fullPaths = {'': getFullPath(schemaId, false)}; | |
var localRefs = {}; | |
var self = this; | |
traverse(schema, {allKeys: true}, function(sch, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) { | |
if (jsonPtr === '') return; | |
var id = self._getId(sch); | |
var baseId = baseIds[parentJsonPtr]; | |
var fullPath = fullPaths[parentJsonPtr] + '/' + parentKeyword; | |
if (keyIndex !== undefined) | |
fullPath += '/' + (typeof keyIndex == 'number' ? keyIndex : util.escapeFragment(keyIndex)); | |
if (typeof id == 'string') { | |
id = baseId = normalizeId(baseId ? URI.resolve(baseId, id) : id); | |
var refVal = self._refs[id]; | |
if (typeof refVal == 'string') refVal = self._refs[refVal]; | |
if (refVal && refVal.schema) { | |
if (!equal(sch, refVal.schema)) | |
throw new Error('id "' + id + '" resolves to more than one schema'); | |
} else if (id != normalizeId(fullPath)) { | |
if (id[0] == '#') { | |
if (localRefs[id] && !equal(sch, localRefs[id])) | |
throw new Error('id "' + id + '" resolves to more than one schema'); | |
localRefs[id] = sch; | |
} else { | |
self._refs[id] = fullPath; | |
} | |
} | |
} | |
baseIds[jsonPtr] = baseId; | |
fullPaths[jsonPtr] = fullPath; | |
}); | |
return localRefs; | |
} | |
/***/ }), | |
/***/ 7753: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
var ruleModules = __webpack_require__(6674) | |
, toHash = (__webpack_require__(2889).toHash); | |
module.exports = function rules() { | |
var RULES = [ | |
{ type: 'number', | |
rules: [ { 'maximum': ['exclusiveMaximum'] }, | |
{ 'minimum': ['exclusiveMinimum'] }, 'multipleOf', 'format'] }, | |
{ type: 'string', | |
rules: [ 'maxLength', 'minLength', 'pattern', 'format' ] }, | |
{ type: 'array', | |
rules: [ 'maxItems', 'minItems', 'items', 'contains', 'uniqueItems' ] }, | |
{ type: 'object', | |
rules: [ 'maxProperties', 'minProperties', 'required', 'dependencies', 'propertyNames', | |
{ 'properties': ['additionalProperties', 'patternProperties'] } ] }, | |
{ rules: [ '$ref', 'const', 'enum', 'not', 'anyOf', 'oneOf', 'allOf', 'if' ] } | |
]; | |
var ALL = [ 'type', '$comment' ]; | |
var KEYWORDS = [ | |
'$schema', '$id', 'id', '$data', '$async', 'title', | |
'description', 'default', 'definitions', | |
'examples', 'readOnly', 'writeOnly', | |
'contentMediaType', 'contentEncoding', | |
'additionalItems', 'then', 'else' | |
]; | |
var TYPES = [ 'number', 'integer', 'string', 'array', 'object', 'boolean', 'null' ]; | |
RULES.all = toHash(ALL); | |
RULES.types = toHash(TYPES); | |
RULES.forEach(function (group) { | |
group.rules = group.rules.map(function (keyword) { | |
var implKeywords; | |
if (typeof keyword == 'object') { | |
var key = Object.keys(keyword)[0]; | |
implKeywords = keyword[key]; | |
keyword = key; | |
implKeywords.forEach(function (k) { | |
ALL.push(k); | |
RULES.all[k] = true; | |
}); | |
} | |
ALL.push(keyword); | |
var rule = RULES.all[keyword] = { | |
keyword: keyword, | |
code: ruleModules[keyword], | |
implements: implKeywords | |
}; | |
return rule; | |
}); | |
RULES.all.$comment = { | |
keyword: '$comment', | |
code: ruleModules.$comment | |
}; | |
if (group.type) RULES.types[group.type] = group; | |
}); | |
RULES.keywords = toHash(ALL.concat(KEYWORDS)); | |
RULES.custom = {}; | |
return RULES; | |
}; | |
/***/ }), | |
/***/ 4022: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
var util = __webpack_require__(2889); | |
module.exports = SchemaObject; | |
function SchemaObject(obj) { | |
util.copy(obj, this); | |
} | |
/***/ }), | |
/***/ 4442: | |
/***/ (function(module) { | |
"use strict"; | |
// https://mathiasbynens.be/notes/javascript-encoding | |
// https://github.com/bestiejs/punycode.js - punycode.ucs2.decode | |
module.exports = function ucs2length(str) { | |
var length = 0 | |
, len = str.length | |
, pos = 0 | |
, value; | |
while (pos < len) { | |
length++; | |
value = str.charCodeAt(pos++); | |
if (value >= 0xD800 && value <= 0xDBFF && pos < len) { | |
// high surrogate, and there is a next character | |
value = str.charCodeAt(pos); | |
if ((value & 0xFC00) == 0xDC00) pos++; // low surrogate | |
} | |
} | |
return length; | |
}; | |
/***/ }), | |
/***/ 2889: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
module.exports = { | |
copy: copy, | |
checkDataType: checkDataType, | |
checkDataTypes: checkDataTypes, | |
coerceToTypes: coerceToTypes, | |
toHash: toHash, | |
getProperty: getProperty, | |
escapeQuotes: escapeQuotes, | |
equal: __webpack_require__(4063), | |
ucs2length: __webpack_require__(4442), | |
varOccurences: varOccurences, | |
varReplace: varReplace, | |
schemaHasRules: schemaHasRules, | |
schemaHasRulesExcept: schemaHasRulesExcept, | |
schemaUnknownRules: schemaUnknownRules, | |
toQuotedString: toQuotedString, | |
getPathExpr: getPathExpr, | |
getPath: getPath, | |
getData: getData, | |
unescapeFragment: unescapeFragment, | |
unescapeJsonPointer: unescapeJsonPointer, | |
escapeFragment: escapeFragment, | |
escapeJsonPointer: escapeJsonPointer | |
}; | |
function copy(o, to) { | |
to = to || {}; | |
for (var key in o) to[key] = o[key]; | |
return to; | |
} | |
function checkDataType(dataType, data, strictNumbers, negate) { | |
var EQUAL = negate ? ' !== ' : ' === ' | |
, AND = negate ? ' || ' : ' && ' | |
, OK = negate ? '!' : '' | |
, NOT = negate ? '' : '!'; | |
switch (dataType) { | |
case 'null': return data + EQUAL + 'null'; | |
case 'array': return OK + 'Array.isArray(' + data + ')'; | |
case 'object': return '(' + OK + data + AND + | |
'typeof ' + data + EQUAL + '"object"' + AND + | |
NOT + 'Array.isArray(' + data + '))'; | |
case 'integer': return '(typeof ' + data + EQUAL + '"number"' + AND + | |
NOT + '(' + data + ' % 1)' + | |
AND + data + EQUAL + data + | |
(strictNumbers ? (AND + OK + 'isFinite(' + data + ')') : '') + ')'; | |
case 'number': return '(typeof ' + data + EQUAL + '"' + dataType + '"' + | |
(strictNumbers ? (AND + OK + 'isFinite(' + data + ')') : '') + ')'; | |
default: return 'typeof ' + data + EQUAL + '"' + dataType + '"'; | |
} | |
} | |
function checkDataTypes(dataTypes, data, strictNumbers) { | |
switch (dataTypes.length) { | |
case 1: return checkDataType(dataTypes[0], data, strictNumbers, true); | |
default: | |
var code = ''; | |
var types = toHash(dataTypes); | |
if (types.array && types.object) { | |
code = types.null ? '(': '(!' + data + ' || '; | |
code += 'typeof ' + data + ' !== "object")'; | |
delete types.null; | |
delete types.array; | |
delete types.object; | |
} | |
if (types.number) delete types.integer; | |
for (var t in types) | |
code += (code ? ' && ' : '' ) + checkDataType(t, data, strictNumbers, true); | |
return code; | |
} | |
} | |
var COERCE_TO_TYPES = toHash([ 'string', 'number', 'integer', 'boolean', 'null' ]); | |
function coerceToTypes(optionCoerceTypes, dataTypes) { | |
if (Array.isArray(dataTypes)) { | |
var types = []; | |
for (var i=0; i<dataTypes.length; i++) { | |
var t = dataTypes[i]; | |
if (COERCE_TO_TYPES[t]) types[types.length] = t; | |
else if (optionCoerceTypes === 'array' && t === 'array') types[types.length] = t; | |
} | |
if (types.length) return types; | |
} else if (COERCE_TO_TYPES[dataTypes]) { | |
return [dataTypes]; | |
} else if (optionCoerceTypes === 'array' && dataTypes === 'array') { | |
return ['array']; | |
} | |
} | |
function toHash(arr) { | |
var hash = {}; | |
for (var i=0; i<arr.length; i++) hash[arr[i]] = true; | |
return hash; | |
} | |
var IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i; | |
var SINGLE_QUOTE = /'|\\/g; | |
function getProperty(key) { | |
return typeof key == 'number' | |
? '[' + key + ']' | |
: IDENTIFIER.test(key) | |
? '.' + key | |
: "['" + escapeQuotes(key) + "']"; | |
} | |
function escapeQuotes(str) { | |
return str.replace(SINGLE_QUOTE, '\\$&') | |
.replace(/\n/g, '\\n') | |
.replace(/\r/g, '\\r') | |
.replace(/\f/g, '\\f') | |
.replace(/\t/g, '\\t'); | |
} | |
function varOccurences(str, dataVar) { | |
dataVar += '[^0-9]'; | |
var matches = str.match(new RegExp(dataVar, 'g')); | |
return matches ? matches.length : 0; | |
} | |
function varReplace(str, dataVar, expr) { | |
dataVar += '([^0-9])'; | |
expr = expr.replace(/\$/g, '$$$$'); | |
return str.replace(new RegExp(dataVar, 'g'), expr + '$1'); | |
} | |
function schemaHasRules(schema, rules) { | |
if (typeof schema == 'boolean') return !schema; | |
for (var key in schema) if (rules[key]) return true; | |
} | |
function schemaHasRulesExcept(schema, rules, exceptKeyword) { | |
if (typeof schema == 'boolean') return !schema && exceptKeyword != 'not'; | |
for (var key in schema) if (key != exceptKeyword && rules[key]) return true; | |
} | |
function schemaUnknownRules(schema, rules) { | |
if (typeof schema == 'boolean') return; | |
for (var key in schema) if (!rules[key]) return key; | |
} | |
function toQuotedString(str) { | |
return '\'' + escapeQuotes(str) + '\''; | |
} | |
function getPathExpr(currentPath, expr, jsonPointers, isNumber) { | |
var path = jsonPointers // false by default | |
? '\'/\' + ' + expr + (isNumber ? '' : '.replace(/~/g, \'~0\').replace(/\\//g, \'~1\')') | |
: (isNumber ? '\'[\' + ' + expr + ' + \']\'' : '\'[\\\'\' + ' + expr + ' + \'\\\']\''); | |
return joinPaths(currentPath, path); | |
} | |
function getPath(currentPath, prop, jsonPointers) { | |
var path = jsonPointers // false by default | |
? toQuotedString('/' + escapeJsonPointer(prop)) | |
: toQuotedString(getProperty(prop)); | |
return joinPaths(currentPath, path); | |
} | |
var JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/; | |
var RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/; | |
function getData($data, lvl, paths) { | |
var up, jsonPointer, data, matches; | |
if ($data === '') return 'rootData'; | |
if ($data[0] == '/') { | |
if (!JSON_POINTER.test($data)) throw new Error('Invalid JSON-pointer: ' + $data); | |
jsonPointer = $data; | |
data = 'rootData'; | |
} else { | |
matches = $data.match(RELATIVE_JSON_POINTER); | |
if (!matches) throw new Error('Invalid JSON-pointer: ' + $data); | |
up = +matches[1]; | |
jsonPointer = matches[2]; | |
if (jsonPointer == '#') { | |
if (up >= lvl) throw new Error('Cannot access property/index ' + up + ' levels up, current level is ' + lvl); | |
return paths[lvl - up]; | |
} | |
if (up > lvl) throw new Error('Cannot access data ' + up + ' levels up, current level is ' + lvl); | |
data = 'data' + ((lvl - up) || ''); | |
if (!jsonPointer) return data; | |
} | |
var expr = data; | |
var segments = jsonPointer.split('/'); | |
for (var i=0; i<segments.length; i++) { | |
var segment = segments[i]; | |
if (segment) { | |
data += getProperty(unescapeJsonPointer(segment)); | |
expr += ' && ' + data; | |
} | |
} | |
return expr; | |
} | |
function joinPaths (a, b) { | |
if (a == '""') return b; | |
return (a + ' + ' + b).replace(/([^\\])' \+ '/g, '$1'); | |
} | |
function unescapeFragment(str) { | |
return unescapeJsonPointer(decodeURIComponent(str)); | |
} | |
function escapeFragment(str) { | |
return encodeURIComponent(escapeJsonPointer(str)); | |
} | |
function escapeJsonPointer(str) { | |
return str.replace(/~/g, '~0').replace(/\//g, '~1'); | |
} | |
function unescapeJsonPointer(str) { | |
return str.replace(/~1/g, '/').replace(/~0/g, '~'); | |
} | |
/***/ }), | |
/***/ 3978: | |
/***/ (function(module) { | |
"use strict"; | |
var KEYWORDS = [ | |
'multipleOf', | |
'maximum', | |
'exclusiveMaximum', | |
'minimum', | |
'exclusiveMinimum', | |
'maxLength', | |
'minLength', | |
'pattern', | |
'additionalItems', | |
'maxItems', | |
'minItems', | |
'uniqueItems', | |
'maxProperties', | |
'minProperties', | |
'required', | |
'additionalProperties', | |
'enum', | |
'format', | |
'const' | |
]; | |
module.exports = function (metaSchema, keywordsJsonPointers) { | |
for (var i=0; i<keywordsJsonPointers.length; i++) { | |
metaSchema = JSON.parse(JSON.stringify(metaSchema)); | |
var segments = keywordsJsonPointers[i].split('/'); | |
var keywords = metaSchema; | |
var j; | |
for (j=1; j<segments.length; j++) | |
keywords = keywords[segments[j]]; | |
for (j=0; j<KEYWORDS.length; j++) { | |
var key = KEYWORDS[j]; | |
var schema = keywords[key]; | |
if (schema) { | |
keywords[key] = { | |
anyOf: [ | |
schema, | |
{ $ref: 'https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#' } | |
] | |
}; | |
} | |
} | |
} | |
return metaSchema; | |
}; | |
/***/ }), | |
/***/ 1128: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
var metaSchema = __webpack_require__(6680); | |
module.exports = { | |
$id: 'https://github.com/ajv-validator/ajv/blob/master/lib/definition_schema.js', | |
definitions: { | |
simpleTypes: metaSchema.definitions.simpleTypes | |
}, | |
type: 'object', | |
dependencies: { | |
schema: ['validate'], | |
$data: ['validate'], | |
statements: ['inline'], | |
valid: {not: {required: ['macro']}} | |
}, | |
properties: { | |
type: metaSchema.properties.type, | |
schema: {type: 'boolean'}, | |
statements: {type: 'boolean'}, | |
dependencies: { | |
type: 'array', | |
items: {type: 'string'} | |
}, | |
metaSchema: {type: 'object'}, | |
modifying: {type: 'boolean'}, | |
valid: {type: 'boolean'}, | |
$data: {type: 'boolean'}, | |
async: {type: 'boolean'}, | |
errors: { | |
anyOf: [ | |
{type: 'boolean'}, | |
{const: 'full'} | |
] | |
} | |
} | |
}; | |
/***/ }), | |
/***/ 8210: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate__limit(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $errorKeyword; | |
var $data = 'data' + ($dataLvl || ''); | |
var $isData = it.opts.$data && $schema && $schema.$data, | |
$schemaValue; | |
if ($isData) { | |
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; | |
$schemaValue = 'schema' + $lvl; | |
} else { | |
$schemaValue = $schema; | |
} | |
var $isMax = $keyword == 'maximum', | |
$exclusiveKeyword = $isMax ? 'exclusiveMaximum' : 'exclusiveMinimum', | |
$schemaExcl = it.schema[$exclusiveKeyword], | |
$isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data, | |
$op = $isMax ? '<' : '>', | |
$notOp = $isMax ? '>' : '<', | |
$errorKeyword = undefined; | |
if (!($isData || typeof $schema == 'number' || $schema === undefined)) { | |
throw new Error($keyword + ' must be number'); | |
} | |
if (!($isDataExcl || $schemaExcl === undefined || typeof $schemaExcl == 'number' || typeof $schemaExcl == 'boolean')) { | |
throw new Error($exclusiveKeyword + ' must be number or boolean'); | |
} | |
if ($isDataExcl) { | |
var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr), | |
$exclusive = 'exclusive' + $lvl, | |
$exclType = 'exclType' + $lvl, | |
$exclIsNumber = 'exclIsNumber' + $lvl, | |
$opExpr = 'op' + $lvl, | |
$opStr = '\' + ' + $opExpr + ' + \''; | |
out += ' var schemaExcl' + ($lvl) + ' = ' + ($schemaValueExcl) + '; '; | |
$schemaValueExcl = 'schemaExcl' + $lvl; | |
out += ' var ' + ($exclusive) + '; var ' + ($exclType) + ' = typeof ' + ($schemaValueExcl) + '; if (' + ($exclType) + ' != \'boolean\' && ' + ($exclType) + ' != \'undefined\' && ' + ($exclType) + ' != \'number\') { '; | |
var $errorKeyword = $exclusiveKeyword; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || '_exclusiveLimit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'' + ($exclusiveKeyword) + ' should be boolean\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' } else if ( '; | |
if ($isData) { | |
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; | |
} | |
out += ' ' + ($exclType) + ' == \'number\' ? ( (' + ($exclusive) + ' = ' + ($schemaValue) + ' === undefined || ' + ($schemaValueExcl) + ' ' + ($op) + '= ' + ($schemaValue) + ') ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaValueExcl) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) : ( (' + ($exclusive) + ' = ' + ($schemaValueExcl) + ' === true) ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaValue) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) || ' + ($data) + ' !== ' + ($data) + ') { var op' + ($lvl) + ' = ' + ($exclusive) + ' ? \'' + ($op) + '\' : \'' + ($op) + '=\'; '; | |
if ($schema === undefined) { | |
$errorKeyword = $exclusiveKeyword; | |
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword; | |
$schemaValue = $schemaValueExcl; | |
$isData = $isDataExcl; | |
} | |
} else { | |
var $exclIsNumber = typeof $schemaExcl == 'number', | |
$opStr = $op; | |
if ($exclIsNumber && $isData) { | |
var $opExpr = '\'' + $opStr + '\''; | |
out += ' if ( '; | |
if ($isData) { | |
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; | |
} | |
out += ' ( ' + ($schemaValue) + ' === undefined || ' + ($schemaExcl) + ' ' + ($op) + '= ' + ($schemaValue) + ' ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaExcl) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) || ' + ($data) + ' !== ' + ($data) + ') { '; | |
} else { | |
if ($exclIsNumber && $schema === undefined) { | |
$exclusive = true; | |
$errorKeyword = $exclusiveKeyword; | |
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword; | |
$schemaValue = $schemaExcl; | |
$notOp += '='; | |
} else { | |
if ($exclIsNumber) $schemaValue = Math[$isMax ? 'min' : 'max']($schemaExcl, $schema); | |
if ($schemaExcl === ($exclIsNumber ? $schemaValue : true)) { | |
$exclusive = true; | |
$errorKeyword = $exclusiveKeyword; | |
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword; | |
$notOp += '='; | |
} else { | |
$exclusive = false; | |
$opStr += '='; | |
} | |
} | |
var $opExpr = '\'' + $opStr + '\''; | |
out += ' if ( '; | |
if ($isData) { | |
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; | |
} | |
out += ' ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' || ' + ($data) + ' !== ' + ($data) + ') { '; | |
} | |
} | |
$errorKeyword = $errorKeyword || $keyword; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || '_limit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { comparison: ' + ($opExpr) + ', limit: ' + ($schemaValue) + ', exclusive: ' + ($exclusive) + ' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should be ' + ($opStr) + ' '; | |
if ($isData) { | |
out += '\' + ' + ($schemaValue); | |
} else { | |
out += '' + ($schemaValue) + '\''; | |
} | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: '; | |
if ($isData) { | |
out += 'validate.schema' + ($schemaPath); | |
} else { | |
out += '' + ($schema); | |
} | |
out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' } '; | |
if ($breakOnError) { | |
out += ' else { '; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 3038: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate__limitItems(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $errorKeyword; | |
var $data = 'data' + ($dataLvl || ''); | |
var $isData = it.opts.$data && $schema && $schema.$data, | |
$schemaValue; | |
if ($isData) { | |
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; | |
$schemaValue = 'schema' + $lvl; | |
} else { | |
$schemaValue = $schema; | |
} | |
if (!($isData || typeof $schema == 'number')) { | |
throw new Error($keyword + ' must be number'); | |
} | |
var $op = $keyword == 'maxItems' ? '>' : '<'; | |
out += 'if ( '; | |
if ($isData) { | |
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; | |
} | |
out += ' ' + ($data) + '.length ' + ($op) + ' ' + ($schemaValue) + ') { '; | |
var $errorKeyword = $keyword; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || '_limitItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schemaValue) + ' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should NOT have '; | |
if ($keyword == 'maxItems') { | |
out += 'more'; | |
} else { | |
out += 'fewer'; | |
} | |
out += ' than '; | |
if ($isData) { | |
out += '\' + ' + ($schemaValue) + ' + \''; | |
} else { | |
out += '' + ($schema); | |
} | |
out += ' items\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: '; | |
if ($isData) { | |
out += 'validate.schema' + ($schemaPath); | |
} else { | |
out += '' + ($schema); | |
} | |
out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += '} '; | |
if ($breakOnError) { | |
out += ' else { '; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 425: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate__limitLength(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $errorKeyword; | |
var $data = 'data' + ($dataLvl || ''); | |
var $isData = it.opts.$data && $schema && $schema.$data, | |
$schemaValue; | |
if ($isData) { | |
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; | |
$schemaValue = 'schema' + $lvl; | |
} else { | |
$schemaValue = $schema; | |
} | |
if (!($isData || typeof $schema == 'number')) { | |
throw new Error($keyword + ' must be number'); | |
} | |
var $op = $keyword == 'maxLength' ? '>' : '<'; | |
out += 'if ( '; | |
if ($isData) { | |
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; | |
} | |
if (it.opts.unicode === false) { | |
out += ' ' + ($data) + '.length '; | |
} else { | |
out += ' ucs2length(' + ($data) + ') '; | |
} | |
out += ' ' + ($op) + ' ' + ($schemaValue) + ') { '; | |
var $errorKeyword = $keyword; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || '_limitLength') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schemaValue) + ' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should NOT be '; | |
if ($keyword == 'maxLength') { | |
out += 'longer'; | |
} else { | |
out += 'shorter'; | |
} | |
out += ' than '; | |
if ($isData) { | |
out += '\' + ' + ($schemaValue) + ' + \''; | |
} else { | |
out += '' + ($schema); | |
} | |
out += ' characters\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: '; | |
if ($isData) { | |
out += 'validate.schema' + ($schemaPath); | |
} else { | |
out += '' + ($schema); | |
} | |
out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += '} '; | |
if ($breakOnError) { | |
out += ' else { '; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 8204: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate__limitProperties(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $errorKeyword; | |
var $data = 'data' + ($dataLvl || ''); | |
var $isData = it.opts.$data && $schema && $schema.$data, | |
$schemaValue; | |
if ($isData) { | |
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; | |
$schemaValue = 'schema' + $lvl; | |
} else { | |
$schemaValue = $schema; | |
} | |
if (!($isData || typeof $schema == 'number')) { | |
throw new Error($keyword + ' must be number'); | |
} | |
var $op = $keyword == 'maxProperties' ? '>' : '<'; | |
out += 'if ( '; | |
if ($isData) { | |
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; | |
} | |
out += ' Object.keys(' + ($data) + ').length ' + ($op) + ' ' + ($schemaValue) + ') { '; | |
var $errorKeyword = $keyword; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || '_limitProperties') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schemaValue) + ' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should NOT have '; | |
if ($keyword == 'maxProperties') { | |
out += 'more'; | |
} else { | |
out += 'fewer'; | |
} | |
out += ' than '; | |
if ($isData) { | |
out += '\' + ' + ($schemaValue) + ' + \''; | |
} else { | |
out += '' + ($schema); | |
} | |
out += ' properties\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: '; | |
if ($isData) { | |
out += 'validate.schema' + ($schemaPath); | |
} else { | |
out += '' + ($schema); | |
} | |
out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += '} '; | |
if ($breakOnError) { | |
out += ' else { '; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 2988: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_allOf(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $it = it.util.copy(it); | |
var $closingBraces = ''; | |
$it.level++; | |
var $nextValid = 'valid' + $it.level; | |
var $currentBaseId = $it.baseId, | |
$allSchemasEmpty = true; | |
var arr1 = $schema; | |
if (arr1) { | |
var $sch, $i = -1, | |
l1 = arr1.length - 1; | |
while ($i < l1) { | |
$sch = arr1[$i += 1]; | |
if ((it.opts.strictKeywords ? (typeof $sch == 'object' && Object.keys($sch).length > 0) || $sch === false : it.util.schemaHasRules($sch, it.RULES.all))) { | |
$allSchemasEmpty = false; | |
$it.schema = $sch; | |
$it.schemaPath = $schemaPath + '[' + $i + ']'; | |
$it.errSchemaPath = $errSchemaPath + '/' + $i; | |
out += ' ' + (it.validate($it)) + ' '; | |
$it.baseId = $currentBaseId; | |
if ($breakOnError) { | |
out += ' if (' + ($nextValid) + ') { '; | |
$closingBraces += '}'; | |
} | |
} | |
} | |
} | |
if ($breakOnError) { | |
if ($allSchemasEmpty) { | |
out += ' if (true) { '; | |
} else { | |
out += ' ' + ($closingBraces.slice(0, -1)) + ' '; | |
} | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 9996: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_anyOf(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $valid = 'valid' + $lvl; | |
var $errs = 'errs__' + $lvl; | |
var $it = it.util.copy(it); | |
var $closingBraces = ''; | |
$it.level++; | |
var $nextValid = 'valid' + $it.level; | |
var $noEmptySchema = $schema.every(function($sch) { | |
return (it.opts.strictKeywords ? (typeof $sch == 'object' && Object.keys($sch).length > 0) || $sch === false : it.util.schemaHasRules($sch, it.RULES.all)); | |
}); | |
if ($noEmptySchema) { | |
var $currentBaseId = $it.baseId; | |
out += ' var ' + ($errs) + ' = errors; var ' + ($valid) + ' = false; '; | |
var $wasComposite = it.compositeRule; | |
it.compositeRule = $it.compositeRule = true; | |
var arr1 = $schema; | |
if (arr1) { | |
var $sch, $i = -1, | |
l1 = arr1.length - 1; | |
while ($i < l1) { | |
$sch = arr1[$i += 1]; | |
$it.schema = $sch; | |
$it.schemaPath = $schemaPath + '[' + $i + ']'; | |
$it.errSchemaPath = $errSchemaPath + '/' + $i; | |
out += ' ' + (it.validate($it)) + ' '; | |
$it.baseId = $currentBaseId; | |
out += ' ' + ($valid) + ' = ' + ($valid) + ' || ' + ($nextValid) + '; if (!' + ($valid) + ') { '; | |
$closingBraces += '}'; | |
} | |
} | |
it.compositeRule = $it.compositeRule = $wasComposite; | |
out += ' ' + ($closingBraces) + ' if (!' + ($valid) + ') { var err = '; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('anyOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should match some schema in anyOf\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError(vErrors); '; | |
} else { | |
out += ' validate.errors = vErrors; return false; '; | |
} | |
} | |
out += ' } else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; | |
if (it.opts.allErrors) { | |
out += ' } '; | |
} | |
} else { | |
if ($breakOnError) { | |
out += ' if (true) { '; | |
} | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 7812: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_comment(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $schema = it.schema[$keyword]; | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $comment = it.util.toQuotedString($schema); | |
if (it.opts.$comment === true) { | |
out += ' console.log(' + ($comment) + ');'; | |
} else if (typeof it.opts.$comment == 'function') { | |
out += ' self._opts.$comment(' + ($comment) + ', ' + (it.util.toQuotedString($errSchemaPath)) + ', validate.root.schema);'; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 5306: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_const(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $valid = 'valid' + $lvl; | |
var $isData = it.opts.$data && $schema && $schema.$data, | |
$schemaValue; | |
if ($isData) { | |
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; | |
$schemaValue = 'schema' + $lvl; | |
} else { | |
$schemaValue = $schema; | |
} | |
if (!$isData) { | |
out += ' var schema' + ($lvl) + ' = validate.schema' + ($schemaPath) + ';'; | |
} | |
out += 'var ' + ($valid) + ' = equal(' + ($data) + ', schema' + ($lvl) + '); if (!' + ($valid) + ') { '; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('const') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { allowedValue: schema' + ($lvl) + ' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should be equal to constant\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' }'; | |
if ($breakOnError) { | |
out += ' else { '; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 2840: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_contains(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $valid = 'valid' + $lvl; | |
var $errs = 'errs__' + $lvl; | |
var $it = it.util.copy(it); | |
var $closingBraces = ''; | |
$it.level++; | |
var $nextValid = 'valid' + $it.level; | |
var $idx = 'i' + $lvl, | |
$dataNxt = $it.dataLevel = it.dataLevel + 1, | |
$nextData = 'data' + $dataNxt, | |
$currentBaseId = it.baseId, | |
$nonEmptySchema = (it.opts.strictKeywords ? (typeof $schema == 'object' && Object.keys($schema).length > 0) || $schema === false : it.util.schemaHasRules($schema, it.RULES.all)); | |
out += 'var ' + ($errs) + ' = errors;var ' + ($valid) + ';'; | |
if ($nonEmptySchema) { | |
var $wasComposite = it.compositeRule; | |
it.compositeRule = $it.compositeRule = true; | |
$it.schema = $schema; | |
$it.schemaPath = $schemaPath; | |
$it.errSchemaPath = $errSchemaPath; | |
out += ' var ' + ($nextValid) + ' = false; for (var ' + ($idx) + ' = 0; ' + ($idx) + ' < ' + ($data) + '.length; ' + ($idx) + '++) { '; | |
$it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true); | |
var $passData = $data + '[' + $idx + ']'; | |
$it.dataPathArr[$dataNxt] = $idx; | |
var $code = it.validate($it); | |
$it.baseId = $currentBaseId; | |
if (it.util.varOccurences($code, $nextData) < 2) { | |
out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; | |
} else { | |
out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; | |
} | |
out += ' if (' + ($nextValid) + ') break; } '; | |
it.compositeRule = $it.compositeRule = $wasComposite; | |
out += ' ' + ($closingBraces) + ' if (!' + ($nextValid) + ') {'; | |
} else { | |
out += ' if (' + ($data) + '.length == 0) {'; | |
} | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('contains') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should contain a valid item\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' } else { '; | |
if ($nonEmptySchema) { | |
out += ' errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; | |
} | |
if (it.opts.allErrors) { | |
out += ' } '; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 4165: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_custom(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $errorKeyword; | |
var $data = 'data' + ($dataLvl || ''); | |
var $valid = 'valid' + $lvl; | |
var $errs = 'errs__' + $lvl; | |
var $isData = it.opts.$data && $schema && $schema.$data, | |
$schemaValue; | |
if ($isData) { | |
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; | |
$schemaValue = 'schema' + $lvl; | |
} else { | |
$schemaValue = $schema; | |
} | |
var $rule = this, | |
$definition = 'definition' + $lvl, | |
$rDef = $rule.definition, | |
$closingBraces = ''; | |
var $compile, $inline, $macro, $ruleValidate, $validateCode; | |
if ($isData && $rDef.$data) { | |
$validateCode = 'keywordValidate' + $lvl; | |
var $validateSchema = $rDef.validateSchema; | |
out += ' var ' + ($definition) + ' = RULES.custom[\'' + ($keyword) + '\'].definition; var ' + ($validateCode) + ' = ' + ($definition) + '.validate;'; | |
} else { | |
$ruleValidate = it.useCustomRule($rule, $schema, it.schema, it); | |
if (!$ruleValidate) return; | |
$schemaValue = 'validate.schema' + $schemaPath; | |
$validateCode = $ruleValidate.code; | |
$compile = $rDef.compile; | |
$inline = $rDef.inline; | |
$macro = $rDef.macro; | |
} | |
var $ruleErrs = $validateCode + '.errors', | |
$i = 'i' + $lvl, | |
$ruleErr = 'ruleErr' + $lvl, | |
$asyncKeyword = $rDef.async; | |
if ($asyncKeyword && !it.async) throw new Error('async keyword in sync schema'); | |
if (!($inline || $macro)) { | |
out += '' + ($ruleErrs) + ' = null;'; | |
} | |
out += 'var ' + ($errs) + ' = errors;var ' + ($valid) + ';'; | |
if ($isData && $rDef.$data) { | |
$closingBraces += '}'; | |
out += ' if (' + ($schemaValue) + ' === undefined) { ' + ($valid) + ' = true; } else { '; | |
if ($validateSchema) { | |
$closingBraces += '}'; | |
out += ' ' + ($valid) + ' = ' + ($definition) + '.validateSchema(' + ($schemaValue) + '); if (' + ($valid) + ') { '; | |
} | |
} | |
if ($inline) { | |
if ($rDef.statements) { | |
out += ' ' + ($ruleValidate.validate) + ' '; | |
} else { | |
out += ' ' + ($valid) + ' = ' + ($ruleValidate.validate) + '; '; | |
} | |
} else if ($macro) { | |
var $it = it.util.copy(it); | |
var $closingBraces = ''; | |
$it.level++; | |
var $nextValid = 'valid' + $it.level; | |
$it.schema = $ruleValidate.validate; | |
$it.schemaPath = ''; | |
var $wasComposite = it.compositeRule; | |
it.compositeRule = $it.compositeRule = true; | |
var $code = it.validate($it).replace(/validate\.schema/g, $validateCode); | |
it.compositeRule = $it.compositeRule = $wasComposite; | |
out += ' ' + ($code); | |
} else { | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; | |
out += ' ' + ($validateCode) + '.call( '; | |
if (it.opts.passContext) { | |
out += 'this'; | |
} else { | |
out += 'self'; | |
} | |
if ($compile || $rDef.schema === false) { | |
out += ' , ' + ($data) + ' '; | |
} else { | |
out += ' , ' + ($schemaValue) + ' , ' + ($data) + ' , validate.schema' + (it.schemaPath) + ' '; | |
} | |
out += ' , (dataPath || \'\')'; | |
if (it.errorPath != '""') { | |
out += ' + ' + (it.errorPath); | |
} | |
var $parentData = $dataLvl ? 'data' + (($dataLvl - 1) || '') : 'parentData', | |
$parentDataProperty = $dataLvl ? it.dataPathArr[$dataLvl] : 'parentDataProperty'; | |
out += ' , ' + ($parentData) + ' , ' + ($parentDataProperty) + ' , rootData ) '; | |
var def_callRuleValidate = out; | |
out = $$outStack.pop(); | |
if ($rDef.errors === false) { | |
out += ' ' + ($valid) + ' = '; | |
if ($asyncKeyword) { | |
out += 'await '; | |
} | |
out += '' + (def_callRuleValidate) + '; '; | |
} else { | |
if ($asyncKeyword) { | |
$ruleErrs = 'customErrors' + $lvl; | |
out += ' var ' + ($ruleErrs) + ' = null; try { ' + ($valid) + ' = await ' + (def_callRuleValidate) + '; } catch (e) { ' + ($valid) + ' = false; if (e instanceof ValidationError) ' + ($ruleErrs) + ' = e.errors; else throw e; } '; | |
} else { | |
out += ' ' + ($ruleErrs) + ' = null; ' + ($valid) + ' = ' + (def_callRuleValidate) + '; '; | |
} | |
} | |
} | |
if ($rDef.modifying) { | |
out += ' if (' + ($parentData) + ') ' + ($data) + ' = ' + ($parentData) + '[' + ($parentDataProperty) + '];'; | |
} | |
out += '' + ($closingBraces); | |
if ($rDef.valid) { | |
if ($breakOnError) { | |
out += ' if (true) { '; | |
} | |
} else { | |
out += ' if ( '; | |
if ($rDef.valid === undefined) { | |
out += ' !'; | |
if ($macro) { | |
out += '' + ($nextValid); | |
} else { | |
out += '' + ($valid); | |
} | |
} else { | |
out += ' ' + (!$rDef.valid) + ' '; | |
} | |
out += ') { '; | |
$errorKeyword = $rule.keyword; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || 'custom') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { keyword: \'' + ($rule.keyword) + '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should pass "' + ($rule.keyword) + '" keyword validation\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
var def_customError = out; | |
out = $$outStack.pop(); | |
if ($inline) { | |
if ($rDef.errors) { | |
if ($rDef.errors != 'full') { | |
out += ' for (var ' + ($i) + '=' + ($errs) + '; ' + ($i) + '<errors; ' + ($i) + '++) { var ' + ($ruleErr) + ' = vErrors[' + ($i) + ']; if (' + ($ruleErr) + '.dataPath === undefined) ' + ($ruleErr) + '.dataPath = (dataPath || \'\') + ' + (it.errorPath) + '; if (' + ($ruleErr) + '.schemaPath === undefined) { ' + ($ruleErr) + '.schemaPath = "' + ($errSchemaPath) + '"; } '; | |
if (it.opts.verbose) { | |
out += ' ' + ($ruleErr) + '.schema = ' + ($schemaValue) + '; ' + ($ruleErr) + '.data = ' + ($data) + '; '; | |
} | |
out += ' } '; | |
} | |
} else { | |
if ($rDef.errors === false) { | |
out += ' ' + (def_customError) + ' '; | |
} else { | |
out += ' if (' + ($errs) + ' == errors) { ' + (def_customError) + ' } else { for (var ' + ($i) + '=' + ($errs) + '; ' + ($i) + '<errors; ' + ($i) + '++) { var ' + ($ruleErr) + ' = vErrors[' + ($i) + ']; if (' + ($ruleErr) + '.dataPath === undefined) ' + ($ruleErr) + '.dataPath = (dataPath || \'\') + ' + (it.errorPath) + '; if (' + ($ruleErr) + '.schemaPath === undefined) { ' + ($ruleErr) + '.schemaPath = "' + ($errSchemaPath) + '"; } '; | |
if (it.opts.verbose) { | |
out += ' ' + ($ruleErr) + '.schema = ' + ($schemaValue) + '; ' + ($ruleErr) + '.data = ' + ($data) + '; '; | |
} | |
out += ' } } '; | |
} | |
} | |
} else if ($macro) { | |
out += ' var err = '; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || 'custom') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { keyword: \'' + ($rule.keyword) + '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should pass "' + ($rule.keyword) + '" keyword validation\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError(vErrors); '; | |
} else { | |
out += ' validate.errors = vErrors; return false; '; | |
} | |
} | |
} else { | |
if ($rDef.errors === false) { | |
out += ' ' + (def_customError) + ' '; | |
} else { | |
out += ' if (Array.isArray(' + ($ruleErrs) + ')) { if (vErrors === null) vErrors = ' + ($ruleErrs) + '; else vErrors = vErrors.concat(' + ($ruleErrs) + '); errors = vErrors.length; for (var ' + ($i) + '=' + ($errs) + '; ' + ($i) + '<errors; ' + ($i) + '++) { var ' + ($ruleErr) + ' = vErrors[' + ($i) + ']; if (' + ($ruleErr) + '.dataPath === undefined) ' + ($ruleErr) + '.dataPath = (dataPath || \'\') + ' + (it.errorPath) + '; ' + ($ruleErr) + '.schemaPath = "' + ($errSchemaPath) + '"; '; | |
if (it.opts.verbose) { | |
out += ' ' + ($ruleErr) + '.schema = ' + ($schemaValue) + '; ' + ($ruleErr) + '.data = ' + ($data) + '; '; | |
} | |
out += ' } } else { ' + (def_customError) + ' } '; | |
} | |
} | |
out += ' } '; | |
if ($breakOnError) { | |
out += ' else { '; | |
} | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 6659: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_dependencies(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $errs = 'errs__' + $lvl; | |
var $it = it.util.copy(it); | |
var $closingBraces = ''; | |
$it.level++; | |
var $nextValid = 'valid' + $it.level; | |
var $schemaDeps = {}, | |
$propertyDeps = {}, | |
$ownProperties = it.opts.ownProperties; | |
for ($property in $schema) { | |
if ($property == '__proto__') continue; | |
var $sch = $schema[$property]; | |
var $deps = Array.isArray($sch) ? $propertyDeps : $schemaDeps; | |
$deps[$property] = $sch; | |
} | |
out += 'var ' + ($errs) + ' = errors;'; | |
var $currentErrorPath = it.errorPath; | |
out += 'var missing' + ($lvl) + ';'; | |
for (var $property in $propertyDeps) { | |
$deps = $propertyDeps[$property]; | |
if ($deps.length) { | |
out += ' if ( ' + ($data) + (it.util.getProperty($property)) + ' !== undefined '; | |
if ($ownProperties) { | |
out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($property)) + '\') '; | |
} | |
if ($breakOnError) { | |
out += ' && ( '; | |
var arr1 = $deps; | |
if (arr1) { | |
var $propertyKey, $i = -1, | |
l1 = arr1.length - 1; | |
while ($i < l1) { | |
$propertyKey = arr1[$i += 1]; | |
if ($i) { | |
out += ' || '; | |
} | |
var $prop = it.util.getProperty($propertyKey), | |
$useData = $data + $prop; | |
out += ' ( ( ' + ($useData) + ' === undefined '; | |
if ($ownProperties) { | |
out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; | |
} | |
out += ') && (missing' + ($lvl) + ' = ' + (it.util.toQuotedString(it.opts.jsonPointers ? $propertyKey : $prop)) + ') ) '; | |
} | |
} | |
out += ')) { '; | |
var $propertyPath = 'missing' + $lvl, | |
$missingProperty = '\' + ' + $propertyPath + ' + \''; | |
if (it.opts._errorDataPathProperty) { | |
it.errorPath = it.opts.jsonPointers ? it.util.getPathExpr($currentErrorPath, $propertyPath, true) : $currentErrorPath + ' + ' + $propertyPath; | |
} | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('dependencies') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { property: \'' + (it.util.escapeQuotes($property)) + '\', missingProperty: \'' + ($missingProperty) + '\', depsCount: ' + ($deps.length) + ', deps: \'' + (it.util.escapeQuotes($deps.length == 1 ? $deps[0] : $deps.join(", "))) + '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should have '; | |
if ($deps.length == 1) { | |
out += 'property ' + (it.util.escapeQuotes($deps[0])); | |
} else { | |
out += 'properties ' + (it.util.escapeQuotes($deps.join(", "))); | |
} | |
out += ' when property ' + (it.util.escapeQuotes($property)) + ' is present\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
} else { | |
out += ' ) { '; | |
var arr2 = $deps; | |
if (arr2) { | |
var $propertyKey, i2 = -1, | |
l2 = arr2.length - 1; | |
while (i2 < l2) { | |
$propertyKey = arr2[i2 += 1]; | |
var $prop = it.util.getProperty($propertyKey), | |
$missingProperty = it.util.escapeQuotes($propertyKey), | |
$useData = $data + $prop; | |
if (it.opts._errorDataPathProperty) { | |
it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers); | |
} | |
out += ' if ( ' + ($useData) + ' === undefined '; | |
if ($ownProperties) { | |
out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; | |
} | |
out += ') { var err = '; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('dependencies') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { property: \'' + (it.util.escapeQuotes($property)) + '\', missingProperty: \'' + ($missingProperty) + '\', depsCount: ' + ($deps.length) + ', deps: \'' + (it.util.escapeQuotes($deps.length == 1 ? $deps[0] : $deps.join(", "))) + '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should have '; | |
if ($deps.length == 1) { | |
out += 'property ' + (it.util.escapeQuotes($deps[0])); | |
} else { | |
out += 'properties ' + (it.util.escapeQuotes($deps.join(", "))); | |
} | |
out += ' when property ' + (it.util.escapeQuotes($property)) + ' is present\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } '; | |
} | |
} | |
} | |
out += ' } '; | |
if ($breakOnError) { | |
$closingBraces += '}'; | |
out += ' else { '; | |
} | |
} | |
} | |
it.errorPath = $currentErrorPath; | |
var $currentBaseId = $it.baseId; | |
for (var $property in $schemaDeps) { | |
var $sch = $schemaDeps[$property]; | |
if ((it.opts.strictKeywords ? (typeof $sch == 'object' && Object.keys($sch).length > 0) || $sch === false : it.util.schemaHasRules($sch, it.RULES.all))) { | |
out += ' ' + ($nextValid) + ' = true; if ( ' + ($data) + (it.util.getProperty($property)) + ' !== undefined '; | |
if ($ownProperties) { | |
out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($property)) + '\') '; | |
} | |
out += ') { '; | |
$it.schema = $sch; | |
$it.schemaPath = $schemaPath + it.util.getProperty($property); | |
$it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($property); | |
out += ' ' + (it.validate($it)) + ' '; | |
$it.baseId = $currentBaseId; | |
out += ' } '; | |
if ($breakOnError) { | |
out += ' if (' + ($nextValid) + ') { '; | |
$closingBraces += '}'; | |
} | |
} | |
} | |
if ($breakOnError) { | |
out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 1740: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_enum(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $valid = 'valid' + $lvl; | |
var $isData = it.opts.$data && $schema && $schema.$data, | |
$schemaValue; | |
if ($isData) { | |
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; | |
$schemaValue = 'schema' + $lvl; | |
} else { | |
$schemaValue = $schema; | |
} | |
var $i = 'i' + $lvl, | |
$vSchema = 'schema' + $lvl; | |
if (!$isData) { | |
out += ' var ' + ($vSchema) + ' = validate.schema' + ($schemaPath) + ';'; | |
} | |
out += 'var ' + ($valid) + ';'; | |
if ($isData) { | |
out += ' if (schema' + ($lvl) + ' === undefined) ' + ($valid) + ' = true; else if (!Array.isArray(schema' + ($lvl) + ')) ' + ($valid) + ' = false; else {'; | |
} | |
out += '' + ($valid) + ' = false;for (var ' + ($i) + '=0; ' + ($i) + '<' + ($vSchema) + '.length; ' + ($i) + '++) if (equal(' + ($data) + ', ' + ($vSchema) + '[' + ($i) + '])) { ' + ($valid) + ' = true; break; }'; | |
if ($isData) { | |
out += ' } '; | |
} | |
out += ' if (!' + ($valid) + ') { '; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('enum') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { allowedValues: schema' + ($lvl) + ' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should be equal to one of the allowed values\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' }'; | |
if ($breakOnError) { | |
out += ' else { '; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 9014: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_format(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
if (it.opts.format === false) { | |
if ($breakOnError) { | |
out += ' if (true) { '; | |
} | |
return out; | |
} | |
var $isData = it.opts.$data && $schema && $schema.$data, | |
$schemaValue; | |
if ($isData) { | |
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; | |
$schemaValue = 'schema' + $lvl; | |
} else { | |
$schemaValue = $schema; | |
} | |
var $unknownFormats = it.opts.unknownFormats, | |
$allowUnknown = Array.isArray($unknownFormats); | |
if ($isData) { | |
var $format = 'format' + $lvl, | |
$isObject = 'isObject' + $lvl, | |
$formatType = 'formatType' + $lvl; | |
out += ' var ' + ($format) + ' = formats[' + ($schemaValue) + ']; var ' + ($isObject) + ' = typeof ' + ($format) + ' == \'object\' && !(' + ($format) + ' instanceof RegExp) && ' + ($format) + '.validate; var ' + ($formatType) + ' = ' + ($isObject) + ' && ' + ($format) + '.type || \'string\'; if (' + ($isObject) + ') { '; | |
if (it.async) { | |
out += ' var async' + ($lvl) + ' = ' + ($format) + '.async; '; | |
} | |
out += ' ' + ($format) + ' = ' + ($format) + '.validate; } if ( '; | |
if ($isData) { | |
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'string\') || '; | |
} | |
out += ' ('; | |
if ($unknownFormats != 'ignore') { | |
out += ' (' + ($schemaValue) + ' && !' + ($format) + ' '; | |
if ($allowUnknown) { | |
out += ' && self._opts.unknownFormats.indexOf(' + ($schemaValue) + ') == -1 '; | |
} | |
out += ') || '; | |
} | |
out += ' (' + ($format) + ' && ' + ($formatType) + ' == \'' + ($ruleType) + '\' && !(typeof ' + ($format) + ' == \'function\' ? '; | |
if (it.async) { | |
out += ' (async' + ($lvl) + ' ? await ' + ($format) + '(' + ($data) + ') : ' + ($format) + '(' + ($data) + ')) '; | |
} else { | |
out += ' ' + ($format) + '(' + ($data) + ') '; | |
} | |
out += ' : ' + ($format) + '.test(' + ($data) + '))))) {'; | |
} else { | |
var $format = it.formats[$schema]; | |
if (!$format) { | |
if ($unknownFormats == 'ignore') { | |
it.logger.warn('unknown format "' + $schema + '" ignored in schema at path "' + it.errSchemaPath + '"'); | |
if ($breakOnError) { | |
out += ' if (true) { '; | |
} | |
return out; | |
} else if ($allowUnknown && $unknownFormats.indexOf($schema) >= 0) { | |
if ($breakOnError) { | |
out += ' if (true) { '; | |
} | |
return out; | |
} else { | |
throw new Error('unknown format "' + $schema + '" is used in schema at path "' + it.errSchemaPath + '"'); | |
} | |
} | |
var $isObject = typeof $format == 'object' && !($format instanceof RegExp) && $format.validate; | |
var $formatType = $isObject && $format.type || 'string'; | |
if ($isObject) { | |
var $async = $format.async === true; | |
$format = $format.validate; | |
} | |
if ($formatType != $ruleType) { | |
if ($breakOnError) { | |
out += ' if (true) { '; | |
} | |
return out; | |
} | |
if ($async) { | |
if (!it.async) throw new Error('async format in sync schema'); | |
var $formatRef = 'formats' + it.util.getProperty($schema) + '.validate'; | |
out += ' if (!(await ' + ($formatRef) + '(' + ($data) + '))) { '; | |
} else { | |
out += ' if (! '; | |
var $formatRef = 'formats' + it.util.getProperty($schema); | |
if ($isObject) $formatRef += '.validate'; | |
if (typeof $format == 'function') { | |
out += ' ' + ($formatRef) + '(' + ($data) + ') '; | |
} else { | |
out += ' ' + ($formatRef) + '.test(' + ($data) + ') '; | |
} | |
out += ') { '; | |
} | |
} | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('format') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { format: '; | |
if ($isData) { | |
out += '' + ($schemaValue); | |
} else { | |
out += '' + (it.util.toQuotedString($schema)); | |
} | |
out += ' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should match format "'; | |
if ($isData) { | |
out += '\' + ' + ($schemaValue) + ' + \''; | |
} else { | |
out += '' + (it.util.escapeQuotes($schema)); | |
} | |
out += '"\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: '; | |
if ($isData) { | |
out += 'validate.schema' + ($schemaPath); | |
} else { | |
out += '' + (it.util.toQuotedString($schema)); | |
} | |
out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' } '; | |
if ($breakOnError) { | |
out += ' else { '; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 7231: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_if(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $valid = 'valid' + $lvl; | |
var $errs = 'errs__' + $lvl; | |
var $it = it.util.copy(it); | |
$it.level++; | |
var $nextValid = 'valid' + $it.level; | |
var $thenSch = it.schema['then'], | |
$elseSch = it.schema['else'], | |
$thenPresent = $thenSch !== undefined && (it.opts.strictKeywords ? (typeof $thenSch == 'object' && Object.keys($thenSch).length > 0) || $thenSch === false : it.util.schemaHasRules($thenSch, it.RULES.all)), | |
$elsePresent = $elseSch !== undefined && (it.opts.strictKeywords ? (typeof $elseSch == 'object' && Object.keys($elseSch).length > 0) || $elseSch === false : it.util.schemaHasRules($elseSch, it.RULES.all)), | |
$currentBaseId = $it.baseId; | |
if ($thenPresent || $elsePresent) { | |
var $ifClause; | |
$it.createErrors = false; | |
$it.schema = $schema; | |
$it.schemaPath = $schemaPath; | |
$it.errSchemaPath = $errSchemaPath; | |
out += ' var ' + ($errs) + ' = errors; var ' + ($valid) + ' = true; '; | |
var $wasComposite = it.compositeRule; | |
it.compositeRule = $it.compositeRule = true; | |
out += ' ' + (it.validate($it)) + ' '; | |
$it.baseId = $currentBaseId; | |
$it.createErrors = true; | |
out += ' errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; | |
it.compositeRule = $it.compositeRule = $wasComposite; | |
if ($thenPresent) { | |
out += ' if (' + ($nextValid) + ') { '; | |
$it.schema = it.schema['then']; | |
$it.schemaPath = it.schemaPath + '.then'; | |
$it.errSchemaPath = it.errSchemaPath + '/then'; | |
out += ' ' + (it.validate($it)) + ' '; | |
$it.baseId = $currentBaseId; | |
out += ' ' + ($valid) + ' = ' + ($nextValid) + '; '; | |
if ($thenPresent && $elsePresent) { | |
$ifClause = 'ifClause' + $lvl; | |
out += ' var ' + ($ifClause) + ' = \'then\'; '; | |
} else { | |
$ifClause = '\'then\''; | |
} | |
out += ' } '; | |
if ($elsePresent) { | |
out += ' else { '; | |
} | |
} else { | |
out += ' if (!' + ($nextValid) + ') { '; | |
} | |
if ($elsePresent) { | |
$it.schema = it.schema['else']; | |
$it.schemaPath = it.schemaPath + '.else'; | |
$it.errSchemaPath = it.errSchemaPath + '/else'; | |
out += ' ' + (it.validate($it)) + ' '; | |
$it.baseId = $currentBaseId; | |
out += ' ' + ($valid) + ' = ' + ($nextValid) + '; '; | |
if ($thenPresent && $elsePresent) { | |
$ifClause = 'ifClause' + $lvl; | |
out += ' var ' + ($ifClause) + ' = \'else\'; '; | |
} else { | |
$ifClause = '\'else\''; | |
} | |
out += ' } '; | |
} | |
out += ' if (!' + ($valid) + ') { var err = '; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('if') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { failingKeyword: ' + ($ifClause) + ' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should match "\' + ' + ($ifClause) + ' + \'" schema\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError(vErrors); '; | |
} else { | |
out += ' validate.errors = vErrors; return false; '; | |
} | |
} | |
out += ' } '; | |
if ($breakOnError) { | |
out += ' else { '; | |
} | |
} else { | |
if ($breakOnError) { | |
out += ' if (true) { '; | |
} | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 6674: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
//all requires must be explicit because browserify won't work with dynamic requires | |
module.exports = { | |
'$ref': __webpack_require__(2392), | |
allOf: __webpack_require__(2988), | |
anyOf: __webpack_require__(9996), | |
'$comment': __webpack_require__(7812), | |
const: __webpack_require__(5306), | |
contains: __webpack_require__(2840), | |
dependencies: __webpack_require__(6659), | |
'enum': __webpack_require__(1740), | |
format: __webpack_require__(9014), | |
'if': __webpack_require__(7231), | |
items: __webpack_require__(7482), | |
maximum: __webpack_require__(8210), | |
minimum: __webpack_require__(8210), | |
maxItems: __webpack_require__(3038), | |
minItems: __webpack_require__(3038), | |
maxLength: __webpack_require__(425), | |
minLength: __webpack_require__(425), | |
maxProperties: __webpack_require__(8204), | |
minProperties: __webpack_require__(8204), | |
multipleOf: __webpack_require__(3673), | |
not: __webpack_require__(8528), | |
oneOf: __webpack_require__(9709), | |
pattern: __webpack_require__(9614), | |
properties: __webpack_require__(1175), | |
propertyNames: __webpack_require__(8441), | |
required: __webpack_require__(1287), | |
uniqueItems: __webpack_require__(3603), | |
validate: __webpack_require__(9508) | |
}; | |
/***/ }), | |
/***/ 7482: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_items(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $valid = 'valid' + $lvl; | |
var $errs = 'errs__' + $lvl; | |
var $it = it.util.copy(it); | |
var $closingBraces = ''; | |
$it.level++; | |
var $nextValid = 'valid' + $it.level; | |
var $idx = 'i' + $lvl, | |
$dataNxt = $it.dataLevel = it.dataLevel + 1, | |
$nextData = 'data' + $dataNxt, | |
$currentBaseId = it.baseId; | |
out += 'var ' + ($errs) + ' = errors;var ' + ($valid) + ';'; | |
if (Array.isArray($schema)) { | |
var $additionalItems = it.schema.additionalItems; | |
if ($additionalItems === false) { | |
out += ' ' + ($valid) + ' = ' + ($data) + '.length <= ' + ($schema.length) + '; '; | |
var $currErrSchemaPath = $errSchemaPath; | |
$errSchemaPath = it.errSchemaPath + '/additionalItems'; | |
out += ' if (!' + ($valid) + ') { '; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('additionalItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schema.length) + ' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should NOT have more than ' + ($schema.length) + ' items\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' } '; | |
$errSchemaPath = $currErrSchemaPath; | |
if ($breakOnError) { | |
$closingBraces += '}'; | |
out += ' else { '; | |
} | |
} | |
var arr1 = $schema; | |
if (arr1) { | |
var $sch, $i = -1, | |
l1 = arr1.length - 1; | |
while ($i < l1) { | |
$sch = arr1[$i += 1]; | |
if ((it.opts.strictKeywords ? (typeof $sch == 'object' && Object.keys($sch).length > 0) || $sch === false : it.util.schemaHasRules($sch, it.RULES.all))) { | |
out += ' ' + ($nextValid) + ' = true; if (' + ($data) + '.length > ' + ($i) + ') { '; | |
var $passData = $data + '[' + $i + ']'; | |
$it.schema = $sch; | |
$it.schemaPath = $schemaPath + '[' + $i + ']'; | |
$it.errSchemaPath = $errSchemaPath + '/' + $i; | |
$it.errorPath = it.util.getPathExpr(it.errorPath, $i, it.opts.jsonPointers, true); | |
$it.dataPathArr[$dataNxt] = $i; | |
var $code = it.validate($it); | |
$it.baseId = $currentBaseId; | |
if (it.util.varOccurences($code, $nextData) < 2) { | |
out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; | |
} else { | |
out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; | |
} | |
out += ' } '; | |
if ($breakOnError) { | |
out += ' if (' + ($nextValid) + ') { '; | |
$closingBraces += '}'; | |
} | |
} | |
} | |
} | |
if (typeof $additionalItems == 'object' && (it.opts.strictKeywords ? (typeof $additionalItems == 'object' && Object.keys($additionalItems).length > 0) || $additionalItems === false : it.util.schemaHasRules($additionalItems, it.RULES.all))) { | |
$it.schema = $additionalItems; | |
$it.schemaPath = it.schemaPath + '.additionalItems'; | |
$it.errSchemaPath = it.errSchemaPath + '/additionalItems'; | |
out += ' ' + ($nextValid) + ' = true; if (' + ($data) + '.length > ' + ($schema.length) + ') { for (var ' + ($idx) + ' = ' + ($schema.length) + '; ' + ($idx) + ' < ' + ($data) + '.length; ' + ($idx) + '++) { '; | |
$it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true); | |
var $passData = $data + '[' + $idx + ']'; | |
$it.dataPathArr[$dataNxt] = $idx; | |
var $code = it.validate($it); | |
$it.baseId = $currentBaseId; | |
if (it.util.varOccurences($code, $nextData) < 2) { | |
out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; | |
} else { | |
out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; | |
} | |
if ($breakOnError) { | |
out += ' if (!' + ($nextValid) + ') break; '; | |
} | |
out += ' } } '; | |
if ($breakOnError) { | |
out += ' if (' + ($nextValid) + ') { '; | |
$closingBraces += '}'; | |
} | |
} | |
} else if ((it.opts.strictKeywords ? (typeof $schema == 'object' && Object.keys($schema).length > 0) || $schema === false : it.util.schemaHasRules($schema, it.RULES.all))) { | |
$it.schema = $schema; | |
$it.schemaPath = $schemaPath; | |
$it.errSchemaPath = $errSchemaPath; | |
out += ' for (var ' + ($idx) + ' = ' + (0) + '; ' + ($idx) + ' < ' + ($data) + '.length; ' + ($idx) + '++) { '; | |
$it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true); | |
var $passData = $data + '[' + $idx + ']'; | |
$it.dataPathArr[$dataNxt] = $idx; | |
var $code = it.validate($it); | |
$it.baseId = $currentBaseId; | |
if (it.util.varOccurences($code, $nextData) < 2) { | |
out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; | |
} else { | |
out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; | |
} | |
if ($breakOnError) { | |
out += ' if (!' + ($nextValid) + ') break; '; | |
} | |
out += ' }'; | |
} | |
if ($breakOnError) { | |
out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 3673: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_multipleOf(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $isData = it.opts.$data && $schema && $schema.$data, | |
$schemaValue; | |
if ($isData) { | |
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; | |
$schemaValue = 'schema' + $lvl; | |
} else { | |
$schemaValue = $schema; | |
} | |
if (!($isData || typeof $schema == 'number')) { | |
throw new Error($keyword + ' must be number'); | |
} | |
out += 'var division' + ($lvl) + ';if ('; | |
if ($isData) { | |
out += ' ' + ($schemaValue) + ' !== undefined && ( typeof ' + ($schemaValue) + ' != \'number\' || '; | |
} | |
out += ' (division' + ($lvl) + ' = ' + ($data) + ' / ' + ($schemaValue) + ', '; | |
if (it.opts.multipleOfPrecision) { | |
out += ' Math.abs(Math.round(division' + ($lvl) + ') - division' + ($lvl) + ') > 1e-' + (it.opts.multipleOfPrecision) + ' '; | |
} else { | |
out += ' division' + ($lvl) + ' !== parseInt(division' + ($lvl) + ') '; | |
} | |
out += ' ) '; | |
if ($isData) { | |
out += ' ) '; | |
} | |
out += ' ) { '; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('multipleOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { multipleOf: ' + ($schemaValue) + ' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should be multiple of '; | |
if ($isData) { | |
out += '\' + ' + ($schemaValue); | |
} else { | |
out += '' + ($schemaValue) + '\''; | |
} | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: '; | |
if ($isData) { | |
out += 'validate.schema' + ($schemaPath); | |
} else { | |
out += '' + ($schema); | |
} | |
out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += '} '; | |
if ($breakOnError) { | |
out += ' else { '; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 8528: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_not(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $errs = 'errs__' + $lvl; | |
var $it = it.util.copy(it); | |
$it.level++; | |
var $nextValid = 'valid' + $it.level; | |
if ((it.opts.strictKeywords ? (typeof $schema == 'object' && Object.keys($schema).length > 0) || $schema === false : it.util.schemaHasRules($schema, it.RULES.all))) { | |
$it.schema = $schema; | |
$it.schemaPath = $schemaPath; | |
$it.errSchemaPath = $errSchemaPath; | |
out += ' var ' + ($errs) + ' = errors; '; | |
var $wasComposite = it.compositeRule; | |
it.compositeRule = $it.compositeRule = true; | |
$it.createErrors = false; | |
var $allErrorsOption; | |
if ($it.opts.allErrors) { | |
$allErrorsOption = $it.opts.allErrors; | |
$it.opts.allErrors = false; | |
} | |
out += ' ' + (it.validate($it)) + ' '; | |
$it.createErrors = true; | |
if ($allErrorsOption) $it.opts.allErrors = $allErrorsOption; | |
it.compositeRule = $it.compositeRule = $wasComposite; | |
out += ' if (' + ($nextValid) + ') { '; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should NOT be valid\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' } else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; | |
if (it.opts.allErrors) { | |
out += ' } '; | |
} | |
} else { | |
out += ' var err = '; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should NOT be valid\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
if ($breakOnError) { | |
out += ' if (false) { '; | |
} | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 9709: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_oneOf(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $valid = 'valid' + $lvl; | |
var $errs = 'errs__' + $lvl; | |
var $it = it.util.copy(it); | |
var $closingBraces = ''; | |
$it.level++; | |
var $nextValid = 'valid' + $it.level; | |
var $currentBaseId = $it.baseId, | |
$prevValid = 'prevValid' + $lvl, | |
$passingSchemas = 'passingSchemas' + $lvl; | |
out += 'var ' + ($errs) + ' = errors , ' + ($prevValid) + ' = false , ' + ($valid) + ' = false , ' + ($passingSchemas) + ' = null; '; | |
var $wasComposite = it.compositeRule; | |
it.compositeRule = $it.compositeRule = true; | |
var arr1 = $schema; | |
if (arr1) { | |
var $sch, $i = -1, | |
l1 = arr1.length - 1; | |
while ($i < l1) { | |
$sch = arr1[$i += 1]; | |
if ((it.opts.strictKeywords ? (typeof $sch == 'object' && Object.keys($sch).length > 0) || $sch === false : it.util.schemaHasRules($sch, it.RULES.all))) { | |
$it.schema = $sch; | |
$it.schemaPath = $schemaPath + '[' + $i + ']'; | |
$it.errSchemaPath = $errSchemaPath + '/' + $i; | |
out += ' ' + (it.validate($it)) + ' '; | |
$it.baseId = $currentBaseId; | |
} else { | |
out += ' var ' + ($nextValid) + ' = true; '; | |
} | |
if ($i) { | |
out += ' if (' + ($nextValid) + ' && ' + ($prevValid) + ') { ' + ($valid) + ' = false; ' + ($passingSchemas) + ' = [' + ($passingSchemas) + ', ' + ($i) + ']; } else { '; | |
$closingBraces += '}'; | |
} | |
out += ' if (' + ($nextValid) + ') { ' + ($valid) + ' = ' + ($prevValid) + ' = true; ' + ($passingSchemas) + ' = ' + ($i) + '; }'; | |
} | |
} | |
it.compositeRule = $it.compositeRule = $wasComposite; | |
out += '' + ($closingBraces) + 'if (!' + ($valid) + ') { var err = '; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('oneOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { passingSchemas: ' + ($passingSchemas) + ' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should match exactly one schema in oneOf\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError(vErrors); '; | |
} else { | |
out += ' validate.errors = vErrors; return false; '; | |
} | |
} | |
out += '} else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; }'; | |
if (it.opts.allErrors) { | |
out += ' } '; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 9614: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_pattern(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $isData = it.opts.$data && $schema && $schema.$data, | |
$schemaValue; | |
if ($isData) { | |
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; | |
$schemaValue = 'schema' + $lvl; | |
} else { | |
$schemaValue = $schema; | |
} | |
var $regexp = $isData ? '(new RegExp(' + $schemaValue + '))' : it.usePattern($schema); | |
out += 'if ( '; | |
if ($isData) { | |
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'string\') || '; | |
} | |
out += ' !' + ($regexp) + '.test(' + ($data) + ') ) { '; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('pattern') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { pattern: '; | |
if ($isData) { | |
out += '' + ($schemaValue); | |
} else { | |
out += '' + (it.util.toQuotedString($schema)); | |
} | |
out += ' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should match pattern "'; | |
if ($isData) { | |
out += '\' + ' + ($schemaValue) + ' + \''; | |
} else { | |
out += '' + (it.util.escapeQuotes($schema)); | |
} | |
out += '"\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: '; | |
if ($isData) { | |
out += 'validate.schema' + ($schemaPath); | |
} else { | |
out += '' + (it.util.toQuotedString($schema)); | |
} | |
out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += '} '; | |
if ($breakOnError) { | |
out += ' else { '; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 1175: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_properties(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $errs = 'errs__' + $lvl; | |
var $it = it.util.copy(it); | |
var $closingBraces = ''; | |
$it.level++; | |
var $nextValid = 'valid' + $it.level; | |
var $key = 'key' + $lvl, | |
$idx = 'idx' + $lvl, | |
$dataNxt = $it.dataLevel = it.dataLevel + 1, | |
$nextData = 'data' + $dataNxt, | |
$dataProperties = 'dataProperties' + $lvl; | |
var $schemaKeys = Object.keys($schema || {}).filter(notProto), | |
$pProperties = it.schema.patternProperties || {}, | |
$pPropertyKeys = Object.keys($pProperties).filter(notProto), | |
$aProperties = it.schema.additionalProperties, | |
$someProperties = $schemaKeys.length || $pPropertyKeys.length, | |
$noAdditional = $aProperties === false, | |
$additionalIsSchema = typeof $aProperties == 'object' && Object.keys($aProperties).length, | |
$removeAdditional = it.opts.removeAdditional, | |
$checkAdditional = $noAdditional || $additionalIsSchema || $removeAdditional, | |
$ownProperties = it.opts.ownProperties, | |
$currentBaseId = it.baseId; | |
var $required = it.schema.required; | |
if ($required && !(it.opts.$data && $required.$data) && $required.length < it.opts.loopRequired) { | |
var $requiredHash = it.util.toHash($required); | |
} | |
function notProto(p) { | |
return p !== '__proto__'; | |
} | |
out += 'var ' + ($errs) + ' = errors;var ' + ($nextValid) + ' = true;'; | |
if ($ownProperties) { | |
out += ' var ' + ($dataProperties) + ' = undefined;'; | |
} | |
if ($checkAdditional) { | |
if ($ownProperties) { | |
out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; | |
} else { | |
out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; | |
} | |
if ($someProperties) { | |
out += ' var isAdditional' + ($lvl) + ' = !(false '; | |
if ($schemaKeys.length) { | |
if ($schemaKeys.length > 8) { | |
out += ' || validate.schema' + ($schemaPath) + '.hasOwnProperty(' + ($key) + ') '; | |
} else { | |
var arr1 = $schemaKeys; | |
if (arr1) { | |
var $propertyKey, i1 = -1, | |
l1 = arr1.length - 1; | |
while (i1 < l1) { | |
$propertyKey = arr1[i1 += 1]; | |
out += ' || ' + ($key) + ' == ' + (it.util.toQuotedString($propertyKey)) + ' '; | |
} | |
} | |
} | |
} | |
if ($pPropertyKeys.length) { | |
var arr2 = $pPropertyKeys; | |
if (arr2) { | |
var $pProperty, $i = -1, | |
l2 = arr2.length - 1; | |
while ($i < l2) { | |
$pProperty = arr2[$i += 1]; | |
out += ' || ' + (it.usePattern($pProperty)) + '.test(' + ($key) + ') '; | |
} | |
} | |
} | |
out += ' ); if (isAdditional' + ($lvl) + ') { '; | |
} | |
if ($removeAdditional == 'all') { | |
out += ' delete ' + ($data) + '[' + ($key) + ']; '; | |
} else { | |
var $currentErrorPath = it.errorPath; | |
var $additionalProperty = '\' + ' + $key + ' + \''; | |
if (it.opts._errorDataPathProperty) { | |
it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); | |
} | |
if ($noAdditional) { | |
if ($removeAdditional) { | |
out += ' delete ' + ($data) + '[' + ($key) + ']; '; | |
} else { | |
out += ' ' + ($nextValid) + ' = false; '; | |
var $currErrSchemaPath = $errSchemaPath; | |
$errSchemaPath = it.errSchemaPath + '/additionalProperties'; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('additionalProperties') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { additionalProperty: \'' + ($additionalProperty) + '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \''; | |
if (it.opts._errorDataPathProperty) { | |
out += 'is an invalid additional property'; | |
} else { | |
out += 'should NOT have additional properties'; | |
} | |
out += '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
$errSchemaPath = $currErrSchemaPath; | |
if ($breakOnError) { | |
out += ' break; '; | |
} | |
} | |
} else if ($additionalIsSchema) { | |
if ($removeAdditional == 'failing') { | |
out += ' var ' + ($errs) + ' = errors; '; | |
var $wasComposite = it.compositeRule; | |
it.compositeRule = $it.compositeRule = true; | |
$it.schema = $aProperties; | |
$it.schemaPath = it.schemaPath + '.additionalProperties'; | |
$it.errSchemaPath = it.errSchemaPath + '/additionalProperties'; | |
$it.errorPath = it.opts._errorDataPathProperty ? it.errorPath : it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); | |
var $passData = $data + '[' + $key + ']'; | |
$it.dataPathArr[$dataNxt] = $key; | |
var $code = it.validate($it); | |
$it.baseId = $currentBaseId; | |
if (it.util.varOccurences($code, $nextData) < 2) { | |
out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; | |
} else { | |
out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; | |
} | |
out += ' if (!' + ($nextValid) + ') { errors = ' + ($errs) + '; if (validate.errors !== null) { if (errors) validate.errors.length = errors; else validate.errors = null; } delete ' + ($data) + '[' + ($key) + ']; } '; | |
it.compositeRule = $it.compositeRule = $wasComposite; | |
} else { | |
$it.schema = $aProperties; | |
$it.schemaPath = it.schemaPath + '.additionalProperties'; | |
$it.errSchemaPath = it.errSchemaPath + '/additionalProperties'; | |
$it.errorPath = it.opts._errorDataPathProperty ? it.errorPath : it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); | |
var $passData = $data + '[' + $key + ']'; | |
$it.dataPathArr[$dataNxt] = $key; | |
var $code = it.validate($it); | |
$it.baseId = $currentBaseId; | |
if (it.util.varOccurences($code, $nextData) < 2) { | |
out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; | |
} else { | |
out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; | |
} | |
if ($breakOnError) { | |
out += ' if (!' + ($nextValid) + ') break; '; | |
} | |
} | |
} | |
it.errorPath = $currentErrorPath; | |
} | |
if ($someProperties) { | |
out += ' } '; | |
} | |
out += ' } '; | |
if ($breakOnError) { | |
out += ' if (' + ($nextValid) + ') { '; | |
$closingBraces += '}'; | |
} | |
} | |
var $useDefaults = it.opts.useDefaults && !it.compositeRule; | |
if ($schemaKeys.length) { | |
var arr3 = $schemaKeys; | |
if (arr3) { | |
var $propertyKey, i3 = -1, | |
l3 = arr3.length - 1; | |
while (i3 < l3) { | |
$propertyKey = arr3[i3 += 1]; | |
var $sch = $schema[$propertyKey]; | |
if ((it.opts.strictKeywords ? (typeof $sch == 'object' && Object.keys($sch).length > 0) || $sch === false : it.util.schemaHasRules($sch, it.RULES.all))) { | |
var $prop = it.util.getProperty($propertyKey), | |
$passData = $data + $prop, | |
$hasDefault = $useDefaults && $sch.default !== undefined; | |
$it.schema = $sch; | |
$it.schemaPath = $schemaPath + $prop; | |
$it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($propertyKey); | |
$it.errorPath = it.util.getPath(it.errorPath, $propertyKey, it.opts.jsonPointers); | |
$it.dataPathArr[$dataNxt] = it.util.toQuotedString($propertyKey); | |
var $code = it.validate($it); | |
$it.baseId = $currentBaseId; | |
if (it.util.varOccurences($code, $nextData) < 2) { | |
$code = it.util.varReplace($code, $nextData, $passData); | |
var $useData = $passData; | |
} else { | |
var $useData = $nextData; | |
out += ' var ' + ($nextData) + ' = ' + ($passData) + '; '; | |
} | |
if ($hasDefault) { | |
out += ' ' + ($code) + ' '; | |
} else { | |
if ($requiredHash && $requiredHash[$propertyKey]) { | |
out += ' if ( ' + ($useData) + ' === undefined '; | |
if ($ownProperties) { | |
out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; | |
} | |
out += ') { ' + ($nextValid) + ' = false; '; | |
var $currentErrorPath = it.errorPath, | |
$currErrSchemaPath = $errSchemaPath, | |
$missingProperty = it.util.escapeQuotes($propertyKey); | |
if (it.opts._errorDataPathProperty) { | |
it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers); | |
} | |
$errSchemaPath = it.errSchemaPath + '/required'; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \''; | |
if (it.opts._errorDataPathProperty) { | |
out += 'is a required property'; | |
} else { | |
out += 'should have required property \\\'' + ($missingProperty) + '\\\''; | |
} | |
out += '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
$errSchemaPath = $currErrSchemaPath; | |
it.errorPath = $currentErrorPath; | |
out += ' } else { '; | |
} else { | |
if ($breakOnError) { | |
out += ' if ( ' + ($useData) + ' === undefined '; | |
if ($ownProperties) { | |
out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; | |
} | |
out += ') { ' + ($nextValid) + ' = true; } else { '; | |
} else { | |
out += ' if (' + ($useData) + ' !== undefined '; | |
if ($ownProperties) { | |
out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; | |
} | |
out += ' ) { '; | |
} | |
} | |
out += ' ' + ($code) + ' } '; | |
} | |
} | |
if ($breakOnError) { | |
out += ' if (' + ($nextValid) + ') { '; | |
$closingBraces += '}'; | |
} | |
} | |
} | |
} | |
if ($pPropertyKeys.length) { | |
var arr4 = $pPropertyKeys; | |
if (arr4) { | |
var $pProperty, i4 = -1, | |
l4 = arr4.length - 1; | |
while (i4 < l4) { | |
$pProperty = arr4[i4 += 1]; | |
var $sch = $pProperties[$pProperty]; | |
if ((it.opts.strictKeywords ? (typeof $sch == 'object' && Object.keys($sch).length > 0) || $sch === false : it.util.schemaHasRules($sch, it.RULES.all))) { | |
$it.schema = $sch; | |
$it.schemaPath = it.schemaPath + '.patternProperties' + it.util.getProperty($pProperty); | |
$it.errSchemaPath = it.errSchemaPath + '/patternProperties/' + it.util.escapeFragment($pProperty); | |
if ($ownProperties) { | |
out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; | |
} else { | |
out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; | |
} | |
out += ' if (' + (it.usePattern($pProperty)) + '.test(' + ($key) + ')) { '; | |
$it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); | |
var $passData = $data + '[' + $key + ']'; | |
$it.dataPathArr[$dataNxt] = $key; | |
var $code = it.validate($it); | |
$it.baseId = $currentBaseId; | |
if (it.util.varOccurences($code, $nextData) < 2) { | |
out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; | |
} else { | |
out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; | |
} | |
if ($breakOnError) { | |
out += ' if (!' + ($nextValid) + ') break; '; | |
} | |
out += ' } '; | |
if ($breakOnError) { | |
out += ' else ' + ($nextValid) + ' = true; '; | |
} | |
out += ' } '; | |
if ($breakOnError) { | |
out += ' if (' + ($nextValid) + ') { '; | |
$closingBraces += '}'; | |
} | |
} | |
} | |
} | |
} | |
if ($breakOnError) { | |
out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 8441: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_propertyNames(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $errs = 'errs__' + $lvl; | |
var $it = it.util.copy(it); | |
var $closingBraces = ''; | |
$it.level++; | |
var $nextValid = 'valid' + $it.level; | |
out += 'var ' + ($errs) + ' = errors;'; | |
if ((it.opts.strictKeywords ? (typeof $schema == 'object' && Object.keys($schema).length > 0) || $schema === false : it.util.schemaHasRules($schema, it.RULES.all))) { | |
$it.schema = $schema; | |
$it.schemaPath = $schemaPath; | |
$it.errSchemaPath = $errSchemaPath; | |
var $key = 'key' + $lvl, | |
$idx = 'idx' + $lvl, | |
$i = 'i' + $lvl, | |
$invalidName = '\' + ' + $key + ' + \'', | |
$dataNxt = $it.dataLevel = it.dataLevel + 1, | |
$nextData = 'data' + $dataNxt, | |
$dataProperties = 'dataProperties' + $lvl, | |
$ownProperties = it.opts.ownProperties, | |
$currentBaseId = it.baseId; | |
if ($ownProperties) { | |
out += ' var ' + ($dataProperties) + ' = undefined; '; | |
} | |
if ($ownProperties) { | |
out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; | |
} else { | |
out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; | |
} | |
out += ' var startErrs' + ($lvl) + ' = errors; '; | |
var $passData = $key; | |
var $wasComposite = it.compositeRule; | |
it.compositeRule = $it.compositeRule = true; | |
var $code = it.validate($it); | |
$it.baseId = $currentBaseId; | |
if (it.util.varOccurences($code, $nextData) < 2) { | |
out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; | |
} else { | |
out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; | |
} | |
it.compositeRule = $it.compositeRule = $wasComposite; | |
out += ' if (!' + ($nextValid) + ') { for (var ' + ($i) + '=startErrs' + ($lvl) + '; ' + ($i) + '<errors; ' + ($i) + '++) { vErrors[' + ($i) + '].propertyName = ' + ($key) + '; } var err = '; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('propertyNames') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { propertyName: \'' + ($invalidName) + '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'property name \\\'' + ($invalidName) + '\\\' is invalid\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError(vErrors); '; | |
} else { | |
out += ' validate.errors = vErrors; return false; '; | |
} | |
} | |
if ($breakOnError) { | |
out += ' break; '; | |
} | |
out += ' } }'; | |
} | |
if ($breakOnError) { | |
out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 2392: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_ref(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $valid = 'valid' + $lvl; | |
var $async, $refCode; | |
if ($schema == '#' || $schema == '#/') { | |
if (it.isRoot) { | |
$async = it.async; | |
$refCode = 'validate'; | |
} else { | |
$async = it.root.schema.$async === true; | |
$refCode = 'root.refVal[0]'; | |
} | |
} else { | |
var $refVal = it.resolveRef(it.baseId, $schema, it.isRoot); | |
if ($refVal === undefined) { | |
var $message = it.MissingRefError.message(it.baseId, $schema); | |
if (it.opts.missingRefs == 'fail') { | |
it.logger.error($message); | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('$ref') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { ref: \'' + (it.util.escapeQuotes($schema)) + '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'can\\\'t resolve reference ' + (it.util.escapeQuotes($schema)) + '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: ' + (it.util.toQuotedString($schema)) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
if ($breakOnError) { | |
out += ' if (false) { '; | |
} | |
} else if (it.opts.missingRefs == 'ignore') { | |
it.logger.warn($message); | |
if ($breakOnError) { | |
out += ' if (true) { '; | |
} | |
} else { | |
throw new it.MissingRefError(it.baseId, $schema, $message); | |
} | |
} else if ($refVal.inline) { | |
var $it = it.util.copy(it); | |
$it.level++; | |
var $nextValid = 'valid' + $it.level; | |
$it.schema = $refVal.schema; | |
$it.schemaPath = ''; | |
$it.errSchemaPath = $schema; | |
var $code = it.validate($it).replace(/validate\.schema/g, $refVal.code); | |
out += ' ' + ($code) + ' '; | |
if ($breakOnError) { | |
out += ' if (' + ($nextValid) + ') { '; | |
} | |
} else { | |
$async = $refVal.$async === true || (it.async && $refVal.$async !== false); | |
$refCode = $refVal.code; | |
} | |
} | |
if ($refCode) { | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; | |
if (it.opts.passContext) { | |
out += ' ' + ($refCode) + '.call(this, '; | |
} else { | |
out += ' ' + ($refCode) + '( '; | |
} | |
out += ' ' + ($data) + ', (dataPath || \'\')'; | |
if (it.errorPath != '""') { | |
out += ' + ' + (it.errorPath); | |
} | |
var $parentData = $dataLvl ? 'data' + (($dataLvl - 1) || '') : 'parentData', | |
$parentDataProperty = $dataLvl ? it.dataPathArr[$dataLvl] : 'parentDataProperty'; | |
out += ' , ' + ($parentData) + ' , ' + ($parentDataProperty) + ', rootData) '; | |
var __callValidate = out; | |
out = $$outStack.pop(); | |
if ($async) { | |
if (!it.async) throw new Error('async schema referenced by sync schema'); | |
if ($breakOnError) { | |
out += ' var ' + ($valid) + '; '; | |
} | |
out += ' try { await ' + (__callValidate) + '; '; | |
if ($breakOnError) { | |
out += ' ' + ($valid) + ' = true; '; | |
} | |
out += ' } catch (e) { if (!(e instanceof ValidationError)) throw e; if (vErrors === null) vErrors = e.errors; else vErrors = vErrors.concat(e.errors); errors = vErrors.length; '; | |
if ($breakOnError) { | |
out += ' ' + ($valid) + ' = false; '; | |
} | |
out += ' } '; | |
if ($breakOnError) { | |
out += ' if (' + ($valid) + ') { '; | |
} | |
} else { | |
out += ' if (!' + (__callValidate) + ') { if (vErrors === null) vErrors = ' + ($refCode) + '.errors; else vErrors = vErrors.concat(' + ($refCode) + '.errors); errors = vErrors.length; } '; | |
if ($breakOnError) { | |
out += ' else { '; | |
} | |
} | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 1287: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_required(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $valid = 'valid' + $lvl; | |
var $isData = it.opts.$data && $schema && $schema.$data, | |
$schemaValue; | |
if ($isData) { | |
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; | |
$schemaValue = 'schema' + $lvl; | |
} else { | |
$schemaValue = $schema; | |
} | |
var $vSchema = 'schema' + $lvl; | |
if (!$isData) { | |
if ($schema.length < it.opts.loopRequired && it.schema.properties && Object.keys(it.schema.properties).length) { | |
var $required = []; | |
var arr1 = $schema; | |
if (arr1) { | |
var $property, i1 = -1, | |
l1 = arr1.length - 1; | |
while (i1 < l1) { | |
$property = arr1[i1 += 1]; | |
var $propertySch = it.schema.properties[$property]; | |
if (!($propertySch && (it.opts.strictKeywords ? (typeof $propertySch == 'object' && Object.keys($propertySch).length > 0) || $propertySch === false : it.util.schemaHasRules($propertySch, it.RULES.all)))) { | |
$required[$required.length] = $property; | |
} | |
} | |
} | |
} else { | |
var $required = $schema; | |
} | |
} | |
if ($isData || $required.length) { | |
var $currentErrorPath = it.errorPath, | |
$loopRequired = $isData || $required.length >= it.opts.loopRequired, | |
$ownProperties = it.opts.ownProperties; | |
if ($breakOnError) { | |
out += ' var missing' + ($lvl) + '; '; | |
if ($loopRequired) { | |
if (!$isData) { | |
out += ' var ' + ($vSchema) + ' = validate.schema' + ($schemaPath) + '; '; | |
} | |
var $i = 'i' + $lvl, | |
$propertyPath = 'schema' + $lvl + '[' + $i + ']', | |
$missingProperty = '\' + ' + $propertyPath + ' + \''; | |
if (it.opts._errorDataPathProperty) { | |
it.errorPath = it.util.getPathExpr($currentErrorPath, $propertyPath, it.opts.jsonPointers); | |
} | |
out += ' var ' + ($valid) + ' = true; '; | |
if ($isData) { | |
out += ' if (schema' + ($lvl) + ' === undefined) ' + ($valid) + ' = true; else if (!Array.isArray(schema' + ($lvl) + ')) ' + ($valid) + ' = false; else {'; | |
} | |
out += ' for (var ' + ($i) + ' = 0; ' + ($i) + ' < ' + ($vSchema) + '.length; ' + ($i) + '++) { ' + ($valid) + ' = ' + ($data) + '[' + ($vSchema) + '[' + ($i) + ']] !== undefined '; | |
if ($ownProperties) { | |
out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', ' + ($vSchema) + '[' + ($i) + ']) '; | |
} | |
out += '; if (!' + ($valid) + ') break; } '; | |
if ($isData) { | |
out += ' } '; | |
} | |
out += ' if (!' + ($valid) + ') { '; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \''; | |
if (it.opts._errorDataPathProperty) { | |
out += 'is a required property'; | |
} else { | |
out += 'should have required property \\\'' + ($missingProperty) + '\\\''; | |
} | |
out += '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' } else { '; | |
} else { | |
out += ' if ( '; | |
var arr2 = $required; | |
if (arr2) { | |
var $propertyKey, $i = -1, | |
l2 = arr2.length - 1; | |
while ($i < l2) { | |
$propertyKey = arr2[$i += 1]; | |
if ($i) { | |
out += ' || '; | |
} | |
var $prop = it.util.getProperty($propertyKey), | |
$useData = $data + $prop; | |
out += ' ( ( ' + ($useData) + ' === undefined '; | |
if ($ownProperties) { | |
out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; | |
} | |
out += ') && (missing' + ($lvl) + ' = ' + (it.util.toQuotedString(it.opts.jsonPointers ? $propertyKey : $prop)) + ') ) '; | |
} | |
} | |
out += ') { '; | |
var $propertyPath = 'missing' + $lvl, | |
$missingProperty = '\' + ' + $propertyPath + ' + \''; | |
if (it.opts._errorDataPathProperty) { | |
it.errorPath = it.opts.jsonPointers ? it.util.getPathExpr($currentErrorPath, $propertyPath, true) : $currentErrorPath + ' + ' + $propertyPath; | |
} | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \''; | |
if (it.opts._errorDataPathProperty) { | |
out += 'is a required property'; | |
} else { | |
out += 'should have required property \\\'' + ($missingProperty) + '\\\''; | |
} | |
out += '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' } else { '; | |
} | |
} else { | |
if ($loopRequired) { | |
if (!$isData) { | |
out += ' var ' + ($vSchema) + ' = validate.schema' + ($schemaPath) + '; '; | |
} | |
var $i = 'i' + $lvl, | |
$propertyPath = 'schema' + $lvl + '[' + $i + ']', | |
$missingProperty = '\' + ' + $propertyPath + ' + \''; | |
if (it.opts._errorDataPathProperty) { | |
it.errorPath = it.util.getPathExpr($currentErrorPath, $propertyPath, it.opts.jsonPointers); | |
} | |
if ($isData) { | |
out += ' if (' + ($vSchema) + ' && !Array.isArray(' + ($vSchema) + ')) { var err = '; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \''; | |
if (it.opts._errorDataPathProperty) { | |
out += 'is a required property'; | |
} else { | |
out += 'should have required property \\\'' + ($missingProperty) + '\\\''; | |
} | |
out += '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } else if (' + ($vSchema) + ' !== undefined) { '; | |
} | |
out += ' for (var ' + ($i) + ' = 0; ' + ($i) + ' < ' + ($vSchema) + '.length; ' + ($i) + '++) { if (' + ($data) + '[' + ($vSchema) + '[' + ($i) + ']] === undefined '; | |
if ($ownProperties) { | |
out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', ' + ($vSchema) + '[' + ($i) + ']) '; | |
} | |
out += ') { var err = '; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \''; | |
if (it.opts._errorDataPathProperty) { | |
out += 'is a required property'; | |
} else { | |
out += 'should have required property \\\'' + ($missingProperty) + '\\\''; | |
} | |
out += '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } } '; | |
if ($isData) { | |
out += ' } '; | |
} | |
} else { | |
var arr3 = $required; | |
if (arr3) { | |
var $propertyKey, i3 = -1, | |
l3 = arr3.length - 1; | |
while (i3 < l3) { | |
$propertyKey = arr3[i3 += 1]; | |
var $prop = it.util.getProperty($propertyKey), | |
$missingProperty = it.util.escapeQuotes($propertyKey), | |
$useData = $data + $prop; | |
if (it.opts._errorDataPathProperty) { | |
it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers); | |
} | |
out += ' if ( ' + ($useData) + ' === undefined '; | |
if ($ownProperties) { | |
out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; | |
} | |
out += ') { var err = '; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \''; | |
if (it.opts._errorDataPathProperty) { | |
out += 'is a required property'; | |
} else { | |
out += 'should have required property \\\'' + ($missingProperty) + '\\\''; | |
} | |
out += '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } '; | |
} | |
} | |
} | |
} | |
it.errorPath = $currentErrorPath; | |
} else if ($breakOnError) { | |
out += ' if (true) {'; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 3603: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_uniqueItems(it, $keyword, $ruleType) { | |
var out = ' '; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $data = 'data' + ($dataLvl || ''); | |
var $valid = 'valid' + $lvl; | |
var $isData = it.opts.$data && $schema && $schema.$data, | |
$schemaValue; | |
if ($isData) { | |
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; | |
$schemaValue = 'schema' + $lvl; | |
} else { | |
$schemaValue = $schema; | |
} | |
if (($schema || $isData) && it.opts.uniqueItems !== false) { | |
if ($isData) { | |
out += ' var ' + ($valid) + '; if (' + ($schemaValue) + ' === false || ' + ($schemaValue) + ' === undefined) ' + ($valid) + ' = true; else if (typeof ' + ($schemaValue) + ' != \'boolean\') ' + ($valid) + ' = false; else { '; | |
} | |
out += ' var i = ' + ($data) + '.length , ' + ($valid) + ' = true , j; if (i > 1) { '; | |
var $itemType = it.schema.items && it.schema.items.type, | |
$typeIsArray = Array.isArray($itemType); | |
if (!$itemType || $itemType == 'object' || $itemType == 'array' || ($typeIsArray && ($itemType.indexOf('object') >= 0 || $itemType.indexOf('array') >= 0))) { | |
out += ' outer: for (;i--;) { for (j = i; j--;) { if (equal(' + ($data) + '[i], ' + ($data) + '[j])) { ' + ($valid) + ' = false; break outer; } } } '; | |
} else { | |
out += ' var itemIndices = {}, item; for (;i--;) { var item = ' + ($data) + '[i]; '; | |
var $method = 'checkDataType' + ($typeIsArray ? 's' : ''); | |
out += ' if (' + (it.util[$method]($itemType, 'item', it.opts.strictNumbers, true)) + ') continue; '; | |
if ($typeIsArray) { | |
out += ' if (typeof item == \'string\') item = \'"\' + item; '; | |
} | |
out += ' if (typeof itemIndices[item] == \'number\') { ' + ($valid) + ' = false; j = itemIndices[item]; break; } itemIndices[item] = i; } '; | |
} | |
out += ' } '; | |
if ($isData) { | |
out += ' } '; | |
} | |
out += ' if (!' + ($valid) + ') { '; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ('uniqueItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { i: i, j: j } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should NOT have duplicate items (items ## \' + j + \' and \' + i + \' are identical)\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: '; | |
if ($isData) { | |
out += 'validate.schema' + ($schemaPath); | |
} else { | |
out += '' + ($schema); | |
} | |
out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' } '; | |
if ($breakOnError) { | |
out += ' else { '; | |
} | |
} else { | |
if ($breakOnError) { | |
out += ' if (true) { '; | |
} | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 9508: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = function generate_validate(it, $keyword, $ruleType) { | |
var out = ''; | |
var $async = it.schema.$async === true, | |
$refKeywords = it.util.schemaHasRulesExcept(it.schema, it.RULES.all, '$ref'), | |
$id = it.self._getId(it.schema); | |
if (it.opts.strictKeywords) { | |
var $unknownKwd = it.util.schemaUnknownRules(it.schema, it.RULES.keywords); | |
if ($unknownKwd) { | |
var $keywordsMsg = 'unknown keyword: ' + $unknownKwd; | |
if (it.opts.strictKeywords === 'log') it.logger.warn($keywordsMsg); | |
else throw new Error($keywordsMsg); | |
} | |
} | |
if (it.isTop) { | |
out += ' var validate = '; | |
if ($async) { | |
it.async = true; | |
out += 'async '; | |
} | |
out += 'function(data, dataPath, parentData, parentDataProperty, rootData) { \'use strict\'; '; | |
if ($id && (it.opts.sourceCode || it.opts.processCode)) { | |
out += ' ' + ('/\*# sourceURL=' + $id + ' */') + ' '; | |
} | |
} | |
if (typeof it.schema == 'boolean' || !($refKeywords || it.schema.$ref)) { | |
var $keyword = 'false schema'; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $errorKeyword; | |
var $data = 'data' + ($dataLvl || ''); | |
var $valid = 'valid' + $lvl; | |
if (it.schema === false) { | |
if (it.isTop) { | |
$breakOnError = true; | |
} else { | |
out += ' var ' + ($valid) + ' = false; '; | |
} | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || 'false schema') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'boolean schema is false\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
} else { | |
if (it.isTop) { | |
if ($async) { | |
out += ' return data; '; | |
} else { | |
out += ' validate.errors = null; return true; '; | |
} | |
} else { | |
out += ' var ' + ($valid) + ' = true; '; | |
} | |
} | |
if (it.isTop) { | |
out += ' }; return validate; '; | |
} | |
return out; | |
} | |
if (it.isTop) { | |
var $top = it.isTop, | |
$lvl = it.level = 0, | |
$dataLvl = it.dataLevel = 0, | |
$data = 'data'; | |
it.rootId = it.resolve.fullPath(it.self._getId(it.root.schema)); | |
it.baseId = it.baseId || it.rootId; | |
delete it.isTop; | |
it.dataPathArr = [""]; | |
if (it.schema.default !== undefined && it.opts.useDefaults && it.opts.strictDefaults) { | |
var $defaultMsg = 'default is ignored in the schema root'; | |
if (it.opts.strictDefaults === 'log') it.logger.warn($defaultMsg); | |
else throw new Error($defaultMsg); | |
} | |
out += ' var vErrors = null; '; | |
out += ' var errors = 0; '; | |
out += ' if (rootData === undefined) rootData = data; '; | |
} else { | |
var $lvl = it.level, | |
$dataLvl = it.dataLevel, | |
$data = 'data' + ($dataLvl || ''); | |
if ($id) it.baseId = it.resolve.url(it.baseId, $id); | |
if ($async && !it.async) throw new Error('async schema in sync schema'); | |
out += ' var errs_' + ($lvl) + ' = errors;'; | |
} | |
var $valid = 'valid' + $lvl, | |
$breakOnError = !it.opts.allErrors, | |
$closingBraces1 = '', | |
$closingBraces2 = ''; | |
var $errorKeyword; | |
var $typeSchema = it.schema.type, | |
$typeIsArray = Array.isArray($typeSchema); | |
if ($typeSchema && it.opts.nullable && it.schema.nullable === true) { | |
if ($typeIsArray) { | |
if ($typeSchema.indexOf('null') == -1) $typeSchema = $typeSchema.concat('null'); | |
} else if ($typeSchema != 'null') { | |
$typeSchema = [$typeSchema, 'null']; | |
$typeIsArray = true; | |
} | |
} | |
if ($typeIsArray && $typeSchema.length == 1) { | |
$typeSchema = $typeSchema[0]; | |
$typeIsArray = false; | |
} | |
if (it.schema.$ref && $refKeywords) { | |
if (it.opts.extendRefs == 'fail') { | |
throw new Error('$ref: validation keywords used in schema at path "' + it.errSchemaPath + '" (see option extendRefs)'); | |
} else if (it.opts.extendRefs !== true) { | |
$refKeywords = false; | |
it.logger.warn('$ref: keywords ignored in schema at path "' + it.errSchemaPath + '"'); | |
} | |
} | |
if (it.schema.$comment && it.opts.$comment) { | |
out += ' ' + (it.RULES.all.$comment.code(it, '$comment')); | |
} | |
if ($typeSchema) { | |
if (it.opts.coerceTypes) { | |
var $coerceToTypes = it.util.coerceToTypes(it.opts.coerceTypes, $typeSchema); | |
} | |
var $rulesGroup = it.RULES.types[$typeSchema]; | |
if ($coerceToTypes || $typeIsArray || $rulesGroup === true || ($rulesGroup && !$shouldUseGroup($rulesGroup))) { | |
var $schemaPath = it.schemaPath + '.type', | |
$errSchemaPath = it.errSchemaPath + '/type'; | |
var $schemaPath = it.schemaPath + '.type', | |
$errSchemaPath = it.errSchemaPath + '/type', | |
$method = $typeIsArray ? 'checkDataTypes' : 'checkDataType'; | |
out += ' if (' + (it.util[$method]($typeSchema, $data, it.opts.strictNumbers, true)) + ') { '; | |
if ($coerceToTypes) { | |
var $dataType = 'dataType' + $lvl, | |
$coerced = 'coerced' + $lvl; | |
out += ' var ' + ($dataType) + ' = typeof ' + ($data) + '; var ' + ($coerced) + ' = undefined; '; | |
if (it.opts.coerceTypes == 'array') { | |
out += ' if (' + ($dataType) + ' == \'object\' && Array.isArray(' + ($data) + ') && ' + ($data) + '.length == 1) { ' + ($data) + ' = ' + ($data) + '[0]; ' + ($dataType) + ' = typeof ' + ($data) + '; if (' + (it.util.checkDataType(it.schema.type, $data, it.opts.strictNumbers)) + ') ' + ($coerced) + ' = ' + ($data) + '; } '; | |
} | |
out += ' if (' + ($coerced) + ' !== undefined) ; '; | |
var arr1 = $coerceToTypes; | |
if (arr1) { | |
var $type, $i = -1, | |
l1 = arr1.length - 1; | |
while ($i < l1) { | |
$type = arr1[$i += 1]; | |
if ($type == 'string') { | |
out += ' else if (' + ($dataType) + ' == \'number\' || ' + ($dataType) + ' == \'boolean\') ' + ($coerced) + ' = \'\' + ' + ($data) + '; else if (' + ($data) + ' === null) ' + ($coerced) + ' = \'\'; '; | |
} else if ($type == 'number' || $type == 'integer') { | |
out += ' else if (' + ($dataType) + ' == \'boolean\' || ' + ($data) + ' === null || (' + ($dataType) + ' == \'string\' && ' + ($data) + ' && ' + ($data) + ' == +' + ($data) + ' '; | |
if ($type == 'integer') { | |
out += ' && !(' + ($data) + ' % 1)'; | |
} | |
out += ')) ' + ($coerced) + ' = +' + ($data) + '; '; | |
} else if ($type == 'boolean') { | |
out += ' else if (' + ($data) + ' === \'false\' || ' + ($data) + ' === 0 || ' + ($data) + ' === null) ' + ($coerced) + ' = false; else if (' + ($data) + ' === \'true\' || ' + ($data) + ' === 1) ' + ($coerced) + ' = true; '; | |
} else if ($type == 'null') { | |
out += ' else if (' + ($data) + ' === \'\' || ' + ($data) + ' === 0 || ' + ($data) + ' === false) ' + ($coerced) + ' = null; '; | |
} else if (it.opts.coerceTypes == 'array' && $type == 'array') { | |
out += ' else if (' + ($dataType) + ' == \'string\' || ' + ($dataType) + ' == \'number\' || ' + ($dataType) + ' == \'boolean\' || ' + ($data) + ' == null) ' + ($coerced) + ' = [' + ($data) + ']; '; | |
} | |
} | |
} | |
out += ' else { '; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \''; | |
if ($typeIsArray) { | |
out += '' + ($typeSchema.join(",")); | |
} else { | |
out += '' + ($typeSchema); | |
} | |
out += '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should be '; | |
if ($typeIsArray) { | |
out += '' + ($typeSchema.join(",")); | |
} else { | |
out += '' + ($typeSchema); | |
} | |
out += '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' } if (' + ($coerced) + ' !== undefined) { '; | |
var $parentData = $dataLvl ? 'data' + (($dataLvl - 1) || '') : 'parentData', | |
$parentDataProperty = $dataLvl ? it.dataPathArr[$dataLvl] : 'parentDataProperty'; | |
out += ' ' + ($data) + ' = ' + ($coerced) + '; '; | |
if (!$dataLvl) { | |
out += 'if (' + ($parentData) + ' !== undefined)'; | |
} | |
out += ' ' + ($parentData) + '[' + ($parentDataProperty) + '] = ' + ($coerced) + '; } '; | |
} else { | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \''; | |
if ($typeIsArray) { | |
out += '' + ($typeSchema.join(",")); | |
} else { | |
out += '' + ($typeSchema); | |
} | |
out += '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should be '; | |
if ($typeIsArray) { | |
out += '' + ($typeSchema.join(",")); | |
} else { | |
out += '' + ($typeSchema); | |
} | |
out += '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
} | |
out += ' } '; | |
} | |
} | |
if (it.schema.$ref && !$refKeywords) { | |
out += ' ' + (it.RULES.all.$ref.code(it, '$ref')) + ' '; | |
if ($breakOnError) { | |
out += ' } if (errors === '; | |
if ($top) { | |
out += '0'; | |
} else { | |
out += 'errs_' + ($lvl); | |
} | |
out += ') { '; | |
$closingBraces2 += '}'; | |
} | |
} else { | |
var arr2 = it.RULES; | |
if (arr2) { | |
var $rulesGroup, i2 = -1, | |
l2 = arr2.length - 1; | |
while (i2 < l2) { | |
$rulesGroup = arr2[i2 += 1]; | |
if ($shouldUseGroup($rulesGroup)) { | |
if ($rulesGroup.type) { | |
out += ' if (' + (it.util.checkDataType($rulesGroup.type, $data, it.opts.strictNumbers)) + ') { '; | |
} | |
if (it.opts.useDefaults) { | |
if ($rulesGroup.type == 'object' && it.schema.properties) { | |
var $schema = it.schema.properties, | |
$schemaKeys = Object.keys($schema); | |
var arr3 = $schemaKeys; | |
if (arr3) { | |
var $propertyKey, i3 = -1, | |
l3 = arr3.length - 1; | |
while (i3 < l3) { | |
$propertyKey = arr3[i3 += 1]; | |
var $sch = $schema[$propertyKey]; | |
if ($sch.default !== undefined) { | |
var $passData = $data + it.util.getProperty($propertyKey); | |
if (it.compositeRule) { | |
if (it.opts.strictDefaults) { | |
var $defaultMsg = 'default is ignored for: ' + $passData; | |
if (it.opts.strictDefaults === 'log') it.logger.warn($defaultMsg); | |
else throw new Error($defaultMsg); | |
} | |
} else { | |
out += ' if (' + ($passData) + ' === undefined '; | |
if (it.opts.useDefaults == 'empty') { | |
out += ' || ' + ($passData) + ' === null || ' + ($passData) + ' === \'\' '; | |
} | |
out += ' ) ' + ($passData) + ' = '; | |
if (it.opts.useDefaults == 'shared') { | |
out += ' ' + (it.useDefault($sch.default)) + ' '; | |
} else { | |
out += ' ' + (JSON.stringify($sch.default)) + ' '; | |
} | |
out += '; '; | |
} | |
} | |
} | |
} | |
} else if ($rulesGroup.type == 'array' && Array.isArray(it.schema.items)) { | |
var arr4 = it.schema.items; | |
if (arr4) { | |
var $sch, $i = -1, | |
l4 = arr4.length - 1; | |
while ($i < l4) { | |
$sch = arr4[$i += 1]; | |
if ($sch.default !== undefined) { | |
var $passData = $data + '[' + $i + ']'; | |
if (it.compositeRule) { | |
if (it.opts.strictDefaults) { | |
var $defaultMsg = 'default is ignored for: ' + $passData; | |
if (it.opts.strictDefaults === 'log') it.logger.warn($defaultMsg); | |
else throw new Error($defaultMsg); | |
} | |
} else { | |
out += ' if (' + ($passData) + ' === undefined '; | |
if (it.opts.useDefaults == 'empty') { | |
out += ' || ' + ($passData) + ' === null || ' + ($passData) + ' === \'\' '; | |
} | |
out += ' ) ' + ($passData) + ' = '; | |
if (it.opts.useDefaults == 'shared') { | |
out += ' ' + (it.useDefault($sch.default)) + ' '; | |
} else { | |
out += ' ' + (JSON.stringify($sch.default)) + ' '; | |
} | |
out += '; '; | |
} | |
} | |
} | |
} | |
} | |
} | |
var arr5 = $rulesGroup.rules; | |
if (arr5) { | |
var $rule, i5 = -1, | |
l5 = arr5.length - 1; | |
while (i5 < l5) { | |
$rule = arr5[i5 += 1]; | |
if ($shouldUseRule($rule)) { | |
var $code = $rule.code(it, $rule.keyword, $rulesGroup.type); | |
if ($code) { | |
out += ' ' + ($code) + ' '; | |
if ($breakOnError) { | |
$closingBraces1 += '}'; | |
} | |
} | |
} | |
} | |
} | |
if ($breakOnError) { | |
out += ' ' + ($closingBraces1) + ' '; | |
$closingBraces1 = ''; | |
} | |
if ($rulesGroup.type) { | |
out += ' } '; | |
if ($typeSchema && $typeSchema === $rulesGroup.type && !$coerceToTypes) { | |
out += ' else { '; | |
var $schemaPath = it.schemaPath + '.type', | |
$errSchemaPath = it.errSchemaPath + '/type'; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \''; | |
if ($typeIsArray) { | |
out += '' + ($typeSchema.join(",")); | |
} else { | |
out += '' + ($typeSchema); | |
} | |
out += '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should be '; | |
if ($typeIsArray) { | |
out += '' + ($typeSchema.join(",")); | |
} else { | |
out += '' + ($typeSchema); | |
} | |
out += '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' } '; | |
} | |
} | |
if ($breakOnError) { | |
out += ' if (errors === '; | |
if ($top) { | |
out += '0'; | |
} else { | |
out += 'errs_' + ($lvl); | |
} | |
out += ') { '; | |
$closingBraces2 += '}'; | |
} | |
} | |
} | |
} | |
} | |
if ($breakOnError) { | |
out += ' ' + ($closingBraces2) + ' '; | |
} | |
if ($top) { | |
if ($async) { | |
out += ' if (errors === 0) return data; '; | |
out += ' else throw new ValidationError(vErrors); '; | |
} else { | |
out += ' validate.errors = vErrors; '; | |
out += ' return errors === 0; '; | |
} | |
out += ' }; return validate;'; | |
} else { | |
out += ' var ' + ($valid) + ' = errors === errs_' + ($lvl) + ';'; | |
} | |
function $shouldUseGroup($rulesGroup) { | |
var rules = $rulesGroup.rules; | |
for (var i = 0; i < rules.length; i++) | |
if ($shouldUseRule(rules[i])) return true; | |
} | |
function $shouldUseRule($rule) { | |
return it.schema[$rule.keyword] !== undefined || ($rule.implements && $ruleImplementsSomeKeyword($rule)); | |
} | |
function $ruleImplementsSomeKeyword($rule) { | |
var impl = $rule.implements; | |
for (var i = 0; i < impl.length; i++) | |
if (it.schema[impl[i]] !== undefined) return true; | |
} | |
return out; | |
} | |
/***/ }), | |
/***/ 4895: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
var IDENTIFIER = /^[a-z_$][a-z0-9_$-]*$/i; | |
var customRuleCode = __webpack_require__(4165); | |
var definitionSchema = __webpack_require__(1128); | |
module.exports = { | |
add: addKeyword, | |
get: getKeyword, | |
remove: removeKeyword, | |
validate: validateKeyword | |
}; | |
/** | |
* Define custom keyword | |
* @this Ajv | |
* @param {String} keyword custom keyword, should be unique (including different from all standard, custom and macro keywords). | |
* @param {Object} definition keyword definition object with properties `type` (type(s) which the keyword applies to), `validate` or `compile`. | |
* @return {Ajv} this for method chaining | |
*/ | |
function addKeyword(keyword, definition) { | |
/* jshint validthis: true */ | |
/* eslint no-shadow: 0 */ | |
var RULES = this.RULES; | |
if (RULES.keywords[keyword]) | |
throw new Error('Keyword ' + keyword + ' is already defined'); | |
if (!IDENTIFIER.test(keyword)) | |
throw new Error('Keyword ' + keyword + ' is not a valid identifier'); | |
if (definition) { | |
this.validateKeyword(definition, true); | |
var dataType = definition.type; | |
if (Array.isArray(dataType)) { | |
for (var i=0; i<dataType.length; i++) | |
_addRule(keyword, dataType[i], definition); | |
} else { | |
_addRule(keyword, dataType, definition); | |
} | |
var metaSchema = definition.metaSchema; | |
if (metaSchema) { | |
if (definition.$data && this._opts.$data) { | |
metaSchema = { | |
anyOf: [ | |
metaSchema, | |
{ '$ref': 'https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#' } | |
] | |
}; | |
} | |
definition.validateSchema = this.compile(metaSchema, true); | |
} | |
} | |
RULES.keywords[keyword] = RULES.all[keyword] = true; | |
function _addRule(keyword, dataType, definition) { | |
var ruleGroup; | |
for (var i=0; i<RULES.length; i++) { | |
var rg = RULES[i]; | |
if (rg.type == dataType) { | |
ruleGroup = rg; | |
break; | |
} | |
} | |
if (!ruleGroup) { | |
ruleGroup = { type: dataType, rules: [] }; | |
RULES.push(ruleGroup); | |
} | |
var rule = { | |
keyword: keyword, | |
definition: definition, | |
custom: true, | |
code: customRuleCode, | |
implements: definition.implements | |
}; | |
ruleGroup.rules.push(rule); | |
RULES.custom[keyword] = rule; | |
} | |
return this; | |
} | |
/** | |
* Get keyword | |
* @this Ajv | |
* @param {String} keyword pre-defined or custom keyword. | |
* @return {Object|Boolean} custom keyword definition, `true` if it is a predefined keyword, `false` otherwise. | |
*/ | |
function getKeyword(keyword) { | |
/* jshint validthis: true */ | |
var rule = this.RULES.custom[keyword]; | |
return rule ? rule.definition : this.RULES.keywords[keyword] || false; | |
} | |
/** | |
* Remove keyword | |
* @this Ajv | |
* @param {String} keyword pre-defined or custom keyword. | |
* @return {Ajv} this for method chaining | |
*/ | |
function removeKeyword(keyword) { | |
/* jshint validthis: true */ | |
var RULES = this.RULES; | |
delete RULES.keywords[keyword]; | |
delete RULES.all[keyword]; | |
delete RULES.custom[keyword]; | |
for (var i=0; i<RULES.length; i++) { | |
var rules = RULES[i].rules; | |
for (var j=0; j<rules.length; j++) { | |
if (rules[j].keyword == keyword) { | |
rules.splice(j, 1); | |
break; | |
} | |
} | |
} | |
return this; | |
} | |
/** | |
* Validate keyword definition | |
* @this Ajv | |
* @param {Object} definition keyword definition object. | |
* @param {Boolean} throwError true to throw exception if definition is invalid | |
* @return {boolean} validation result | |
*/ | |
function validateKeyword(definition, throwError) { | |
validateKeyword.errors = null; | |
var v = this._validateKeyword = this._validateKeyword | |
|| this.compile(definitionSchema, true); | |
if (v(definition)) return true; | |
validateKeyword.errors = v.errors; | |
if (throwError) | |
throw new Error('custom keyword definition is invalid: ' + this.errorsText(v.errors)); | |
else | |
return false; | |
} | |
/***/ }), | |
/***/ 9282: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/* provided dependency */ var process = __webpack_require__(4155); | |
/* provided dependency */ var console = __webpack_require__(5108); | |
// Currently in sync with Node.js lib/assert.js | |
// https://github.com/nodejs/node/commit/2a51ae424a513ec9a6aa3466baa0cc1d55dd4f3b | |
// Originally from narwhal.js (http://narwhaljs.org) | |
// Copyright (c) 2009 Thomas Robinson <280north.com> | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files (the 'Software'), to | |
// deal in the Software without restriction, including without limitation the | |
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |
// sell copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included in | |
// all copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
var _require = __webpack_require__(2136), | |
_require$codes = _require.codes, | |
ERR_AMBIGUOUS_ARGUMENT = _require$codes.ERR_AMBIGUOUS_ARGUMENT, | |
ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE, | |
ERR_INVALID_ARG_VALUE = _require$codes.ERR_INVALID_ARG_VALUE, | |
ERR_INVALID_RETURN_VALUE = _require$codes.ERR_INVALID_RETURN_VALUE, | |
ERR_MISSING_ARGS = _require$codes.ERR_MISSING_ARGS; | |
var AssertionError = __webpack_require__(5961); | |
var _require2 = __webpack_require__(9539), | |
inspect = _require2.inspect; | |
var _require$types = (__webpack_require__(9539).types), | |
isPromise = _require$types.isPromise, | |
isRegExp = _require$types.isRegExp; | |
var objectAssign = Object.assign ? Object.assign : (__webpack_require__(8091).assign); | |
var objectIs = Object.is ? Object.is : __webpack_require__(609); | |
var errorCache = new Map(); | |
var isDeepEqual; | |
var isDeepStrictEqual; | |
var parseExpressionAt; | |
var findNodeAround; | |
var decoder; | |
function lazyLoadComparison() { | |
var comparison = __webpack_require__(9158); | |
isDeepEqual = comparison.isDeepEqual; | |
isDeepStrictEqual = comparison.isDeepStrictEqual; | |
} // Escape control characters but not \n and \t to keep the line breaks and | |
// indentation intact. | |
// eslint-disable-next-line no-control-regex | |
var escapeSequencesRegExp = /[\x00-\x08\x0b\x0c\x0e-\x1f]/g; | |
var meta = (/* unused pure expression or super */ null && (["\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007", '\\b', '', '', "\\u000b", '\\f', '', "\\u000e", "\\u000f", "\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f"])); | |
var escapeFn = function escapeFn(str) { | |
return meta[str.charCodeAt(0)]; | |
}; | |
var warned = false; // The assert module provides functions that throw | |
// AssertionError's when particular conditions are not met. The | |
// assert module must conform to the following interface. | |
var assert = module.exports = ok; | |
var NO_EXCEPTION_SENTINEL = {}; // All of the following functions must throw an AssertionError | |
// when a corresponding condition is not met, with a message that | |
// may be undefined if not provided. All assertion methods provide | |
// both the actual and expected values to the assertion error for | |
// display purposes. | |
function innerFail(obj) { | |
if (obj.message instanceof Error) throw obj.message; | |
throw new AssertionError(obj); | |
} | |
function fail(actual, expected, message, operator, stackStartFn) { | |
var argsLen = arguments.length; | |
var internalMessage; | |
if (argsLen === 0) { | |
internalMessage = 'Failed'; | |
} else if (argsLen === 1) { | |
message = actual; | |
actual = undefined; | |
} else { | |
if (warned === false) { | |
warned = true; | |
var warn = process.emitWarning ? process.emitWarning : console.warn.bind(console); | |
warn('assert.fail() with more than one argument is deprecated. ' + 'Please use assert.strictEqual() instead or only pass a message.', 'DeprecationWarning', 'DEP0094'); | |
} | |
if (argsLen === 2) operator = '!='; | |
} | |
if (message instanceof Error) throw message; | |
var errArgs = { | |
actual: actual, | |
expected: expected, | |
operator: operator === undefined ? 'fail' : operator, | |
stackStartFn: stackStartFn || fail | |
}; | |
if (message !== undefined) { | |
errArgs.message = message; | |
} | |
var err = new AssertionError(errArgs); | |
if (internalMessage) { | |
err.message = internalMessage; | |
err.generatedMessage = true; | |
} | |
throw err; | |
} | |
assert.fail = fail; // The AssertionError is defined in internal/error. | |
assert.AssertionError = AssertionError; | |
function innerOk(fn, argLen, value, message) { | |
if (!value) { | |
var generatedMessage = false; | |
if (argLen === 0) { | |
generatedMessage = true; | |
message = 'No value argument passed to `assert.ok()`'; | |
} else if (message instanceof Error) { | |
throw message; | |
} | |
var err = new AssertionError({ | |
actual: value, | |
expected: true, | |
message: message, | |
operator: '==', | |
stackStartFn: fn | |
}); | |
err.generatedMessage = generatedMessage; | |
throw err; | |
} | |
} // Pure assertion tests whether a value is truthy, as determined | |
// by !!value. | |
function ok() { | |
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | |
args[_key] = arguments[_key]; | |
} | |
innerOk.apply(void 0, [ok, args.length].concat(args)); | |
} | |
assert.ok = ok; // The equality assertion tests shallow, coercive equality with ==. | |
/* eslint-disable no-restricted-properties */ | |
assert.equal = function equal(actual, expected, message) { | |
if (arguments.length < 2) { | |
throw new ERR_MISSING_ARGS('actual', 'expected'); | |
} // eslint-disable-next-line eqeqeq | |
if (actual != expected) { | |
innerFail({ | |
actual: actual, | |
expected: expected, | |
message: message, | |
operator: '==', | |
stackStartFn: equal | |
}); | |
} | |
}; // The non-equality assertion tests for whether two objects are not | |
// equal with !=. | |
assert.notEqual = function notEqual(actual, expected, message) { | |
if (arguments.length < 2) { | |
throw new ERR_MISSING_ARGS('actual', 'expected'); | |
} // eslint-disable-next-line eqeqeq | |
if (actual == expected) { | |
innerFail({ | |
actual: actual, | |
expected: expected, | |
message: message, | |
operator: '!=', | |
stackStartFn: notEqual | |
}); | |
} | |
}; // The equivalence assertion tests a deep equality relation. | |
assert.deepEqual = function deepEqual(actual, expected, message) { | |
if (arguments.length < 2) { | |
throw new ERR_MISSING_ARGS('actual', 'expected'); | |
} | |
if (isDeepEqual === undefined) lazyLoadComparison(); | |
if (!isDeepEqual(actual, expected)) { | |
innerFail({ | |
actual: actual, | |
expected: expected, | |
message: message, | |
operator: 'deepEqual', | |
stackStartFn: deepEqual | |
}); | |
} | |
}; // The non-equivalence assertion tests for any deep inequality. | |
assert.notDeepEqual = function notDeepEqual(actual, expected, message) { | |
if (arguments.length < 2) { | |
throw new ERR_MISSING_ARGS('actual', 'expected'); | |
} | |
if (isDeepEqual === undefined) lazyLoadComparison(); | |
if (isDeepEqual(actual, expected)) { | |
innerFail({ | |
actual: actual, | |
expected: expected, | |
message: message, | |
operator: 'notDeepEqual', | |
stackStartFn: notDeepEqual | |
}); | |
} | |
}; | |
/* eslint-enable */ | |
assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) { | |
if (arguments.length < 2) { | |
throw new ERR_MISSING_ARGS('actual', 'expected'); | |
} | |
if (isDeepEqual === undefined) lazyLoadComparison(); | |
if (!isDeepStrictEqual(actual, expected)) { | |
innerFail({ | |
actual: actual, | |
expected: expected, | |
message: message, | |
operator: 'deepStrictEqual', | |
stackStartFn: deepStrictEqual | |
}); | |
} | |
}; | |
assert.notDeepStrictEqual = notDeepStrictEqual; | |
function notDeepStrictEqual(actual, expected, message) { | |
if (arguments.length < 2) { | |
throw new ERR_MISSING_ARGS('actual', 'expected'); | |
} | |
if (isDeepEqual === undefined) lazyLoadComparison(); | |
if (isDeepStrictEqual(actual, expected)) { | |
innerFail({ | |
actual: actual, | |
expected: expected, | |
message: message, | |
operator: 'notDeepStrictEqual', | |
stackStartFn: notDeepStrictEqual | |
}); | |
} | |
} | |
assert.strictEqual = function strictEqual(actual, expected, message) { | |
if (arguments.length < 2) { | |
throw new ERR_MISSING_ARGS('actual', 'expected'); | |
} | |
if (!objectIs(actual, expected)) { | |
innerFail({ | |
actual: actual, | |
expected: expected, | |
message: message, | |
operator: 'strictEqual', | |
stackStartFn: strictEqual | |
}); | |
} | |
}; | |
assert.notStrictEqual = function notStrictEqual(actual, expected, message) { | |
if (arguments.length < 2) { | |
throw new ERR_MISSING_ARGS('actual', 'expected'); | |
} | |
if (objectIs(actual, expected)) { | |
innerFail({ | |
actual: actual, | |
expected: expected, | |
message: message, | |
operator: 'notStrictEqual', | |
stackStartFn: notStrictEqual | |
}); | |
} | |
}; | |
var Comparison = function Comparison(obj, keys, actual) { | |
var _this = this; | |
_classCallCheck(this, Comparison); | |
keys.forEach(function (key) { | |
if (key in obj) { | |
if (actual !== undefined && typeof actual[key] === 'string' && isRegExp(obj[key]) && obj[key].test(actual[key])) { | |
_this[key] = actual[key]; | |
} else { | |
_this[key] = obj[key]; | |
} | |
} | |
}); | |
}; | |
function compareExceptionKey(actual, expected, key, message, keys, fn) { | |
if (!(key in actual) || !isDeepStrictEqual(actual[key], expected[key])) { | |
if (!message) { | |
// Create placeholder objects to create a nice output. | |
var a = new Comparison(actual, keys); | |
var b = new Comparison(expected, keys, actual); | |
var err = new AssertionError({ | |
actual: a, | |
expected: b, | |
operator: 'deepStrictEqual', | |
stackStartFn: fn | |
}); | |
err.actual = actual; | |
err.expected = expected; | |
err.operator = fn.name; | |
throw err; | |
} | |
innerFail({ | |
actual: actual, | |
expected: expected, | |
message: message, | |
operator: fn.name, | |
stackStartFn: fn | |
}); | |
} | |
} | |
function expectedException(actual, expected, msg, fn) { | |
if (typeof expected !== 'function') { | |
if (isRegExp(expected)) return expected.test(actual); // assert.doesNotThrow does not accept objects. | |
if (arguments.length === 2) { | |
throw new ERR_INVALID_ARG_TYPE('expected', ['Function', 'RegExp'], expected); | |
} // Handle primitives properly. | |
if (_typeof(actual) !== 'object' || actual === null) { | |
var err = new AssertionError({ | |
actual: actual, | |
expected: expected, | |
message: msg, | |
operator: 'deepStrictEqual', | |
stackStartFn: fn | |
}); | |
err.operator = fn.name; | |
throw err; | |
} | |
var keys = Object.keys(expected); // Special handle errors to make sure the name and the message are compared | |
// as well. | |
if (expected instanceof Error) { | |
keys.push('name', 'message'); | |
} else if (keys.length === 0) { | |
throw new ERR_INVALID_ARG_VALUE('error', expected, 'may not be an empty object'); | |
} | |
if (isDeepEqual === undefined) lazyLoadComparison(); | |
keys.forEach(function (key) { | |
if (typeof actual[key] === 'string' && isRegExp(expected[key]) && expected[key].test(actual[key])) { | |
return; | |
} | |
compareExceptionKey(actual, expected, key, msg, keys, fn); | |
}); | |
return true; | |
} // Guard instanceof against arrow functions as they don't have a prototype. | |
if (expected.prototype !== undefined && actual instanceof expected) { | |
return true; | |
} | |
if (Error.isPrototypeOf(expected)) { | |
return false; | |
} | |
return expected.call({}, actual) === true; | |
} | |
function getActual(fn) { | |
if (typeof fn !== 'function') { | |
throw new ERR_INVALID_ARG_TYPE('fn', 'Function', fn); | |
} | |
try { | |
fn(); | |
} catch (e) { | |
return e; | |
} | |
return NO_EXCEPTION_SENTINEL; | |
} | |
function checkIsPromise(obj) { | |
// Accept native ES6 promises and promises that are implemented in a similar | |
// way. Do not accept thenables that use a function as `obj` and that have no | |
// `catch` handler. | |
// TODO: thenables are checked up until they have the correct methods, | |
// but according to documentation, the `then` method should receive | |
// the `fulfill` and `reject` arguments as well or it may be never resolved. | |
return isPromise(obj) || obj !== null && _typeof(obj) === 'object' && typeof obj.then === 'function' && typeof obj.catch === 'function'; | |
} | |
function waitForActual(promiseFn) { | |
return Promise.resolve().then(function () { | |
var resultPromise; | |
if (typeof promiseFn === 'function') { | |
// Return a rejected promise if `promiseFn` throws synchronously. | |
resultPromise = promiseFn(); // Fail in case no promise is returned. | |
if (!checkIsPromise(resultPromise)) { | |
throw new ERR_INVALID_RETURN_VALUE('instance of Promise', 'promiseFn', resultPromise); | |
} | |
} else if (checkIsPromise(promiseFn)) { | |
resultPromise = promiseFn; | |
} else { | |
throw new ERR_INVALID_ARG_TYPE('promiseFn', ['Function', 'Promise'], promiseFn); | |
} | |
return Promise.resolve().then(function () { | |
return resultPromise; | |
}).then(function () { | |
return NO_EXCEPTION_SENTINEL; | |
}).catch(function (e) { | |
return e; | |
}); | |
}); | |
} | |
function expectsError(stackStartFn, actual, error, message) { | |
if (typeof error === 'string') { | |
if (arguments.length === 4) { | |
throw new ERR_INVALID_ARG_TYPE('error', ['Object', 'Error', 'Function', 'RegExp'], error); | |
} | |
if (_typeof(actual) === 'object' && actual !== null) { | |
if (actual.message === error) { | |
throw new ERR_AMBIGUOUS_ARGUMENT('error/message', "The error message \"".concat(actual.message, "\" is identical to the message.")); | |
} | |
} else if (actual === error) { | |
throw new ERR_AMBIGUOUS_ARGUMENT('error/message', "The error \"".concat(actual, "\" is identical to the message.")); | |
} | |
message = error; | |
error = undefined; | |
} else if (error != null && _typeof(error) !== 'object' && typeof error !== 'function') { | |
throw new ERR_INVALID_ARG_TYPE('error', ['Object', 'Error', 'Function', 'RegExp'], error); | |
} | |
if (actual === NO_EXCEPTION_SENTINEL) { | |
var details = ''; | |
if (error && error.name) { | |
details += " (".concat(error.name, ")"); | |
} | |
details += message ? ": ".concat(message) : '.'; | |
var fnType = stackStartFn.name === 'rejects' ? 'rejection' : 'exception'; | |
innerFail({ | |
actual: undefined, | |
expected: error, | |
operator: stackStartFn.name, | |
message: "Missing expected ".concat(fnType).concat(details), | |
stackStartFn: stackStartFn | |
}); | |
} | |
if (error && !expectedException(actual, error, message, stackStartFn)) { | |
throw actual; | |
} | |
} | |
function expectsNoError(stackStartFn, actual, error, message) { | |
if (actual === NO_EXCEPTION_SENTINEL) return; | |
if (typeof error === 'string') { | |
message = error; | |
error = undefined; | |
} | |
if (!error || expectedException(actual, error)) { | |
var details = message ? ": ".concat(message) : '.'; | |
var fnType = stackStartFn.name === 'doesNotReject' ? 'rejection' : 'exception'; | |
innerFail({ | |
actual: actual, | |
expected: error, | |
operator: stackStartFn.name, | |
message: "Got unwanted ".concat(fnType).concat(details, "\n") + "Actual message: \"".concat(actual && actual.message, "\""), | |
stackStartFn: stackStartFn | |
}); | |
} | |
throw actual; | |
} | |
assert.throws = function throws(promiseFn) { | |
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { | |
args[_key2 - 1] = arguments[_key2]; | |
} | |
expectsError.apply(void 0, [throws, getActual(promiseFn)].concat(args)); | |
}; | |
assert.rejects = function rejects(promiseFn) { | |
for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { | |
args[_key3 - 1] = arguments[_key3]; | |
} | |
return waitForActual(promiseFn).then(function (result) { | |
return expectsError.apply(void 0, [rejects, result].concat(args)); | |
}); | |
}; | |
assert.doesNotThrow = function doesNotThrow(fn) { | |
for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { | |
args[_key4 - 1] = arguments[_key4]; | |
} | |
expectsNoError.apply(void 0, [doesNotThrow, getActual(fn)].concat(args)); | |
}; | |
assert.doesNotReject = function doesNotReject(fn) { | |
for (var _len5 = arguments.length, args = new Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) { | |
args[_key5 - 1] = arguments[_key5]; | |
} | |
return waitForActual(fn).then(function (result) { | |
return expectsNoError.apply(void 0, [doesNotReject, result].concat(args)); | |
}); | |
}; | |
assert.ifError = function ifError(err) { | |
if (err !== null && err !== undefined) { | |
var message = 'ifError got unwanted exception: '; | |
if (_typeof(err) === 'object' && typeof err.message === 'string') { | |
if (err.message.length === 0 && err.constructor) { | |
message += err.constructor.name; | |
} else { | |
message += err.message; | |
} | |
} else { | |
message += inspect(err); | |
} | |
var newErr = new AssertionError({ | |
actual: err, | |
expected: null, | |
operator: 'ifError', | |
message: message, | |
stackStartFn: ifError | |
}); // Make sure we actually have a stack trace! | |
var origStack = err.stack; | |
if (typeof origStack === 'string') { | |
// This will remove any duplicated frames from the error frames taken | |
// from within `ifError` and add the original error frames to the newly | |
// created ones. | |
var tmp2 = origStack.split('\n'); | |
tmp2.shift(); // Filter all frames existing in err.stack. | |
var tmp1 = newErr.stack.split('\n'); | |
for (var i = 0; i < tmp2.length; i++) { | |
// Find the first occurrence of the frame. | |
var pos = tmp1.indexOf(tmp2[i]); | |
if (pos !== -1) { | |
// Only keep new frames. | |
tmp1 = tmp1.slice(0, pos); | |
break; | |
} | |
} | |
newErr.stack = "".concat(tmp1.join('\n'), "\n").concat(tmp2.join('\n')); | |
} | |
throw newErr; | |
} | |
}; // Expose a strict only variant of assert | |
function strict() { | |
for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) { | |
args[_key6] = arguments[_key6]; | |
} | |
innerOk.apply(void 0, [strict, args.length].concat(args)); | |
} | |
assert.strict = objectAssign(strict, assert, { | |
equal: assert.strictEqual, | |
deepEqual: assert.deepStrictEqual, | |
notEqual: assert.notStrictEqual, | |
notDeepEqual: assert.notDeepStrictEqual | |
}); | |
assert.strict.strict = assert.strict; | |
/***/ }), | |
/***/ 5961: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/* provided dependency */ var process = __webpack_require__(4155); | |
// Currently in sync with Node.js lib/internal/assert/assertion_error.js | |
// https://github.com/nodejs/node/commit/0817840f775032169ddd70c85ac059f18ffcc81c | |
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } | |
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } | |
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | |
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | |
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | |
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | |
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); } | |
function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } | |
function _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } | |
function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; } | |
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | |
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | |
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | |
var _require = __webpack_require__(9539), | |
inspect = _require.inspect; | |
var _require2 = __webpack_require__(2136), | |
ERR_INVALID_ARG_TYPE = _require2.codes.ERR_INVALID_ARG_TYPE; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith | |
function endsWith(str, search, this_len) { | |
if (this_len === undefined || this_len > str.length) { | |
this_len = str.length; | |
} | |
return str.substring(this_len - search.length, this_len) === search; | |
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat | |
function repeat(str, count) { | |
count = Math.floor(count); | |
if (str.length == 0 || count == 0) return ''; | |
var maxCount = str.length * count; | |
count = Math.floor(Math.log(count) / Math.log(2)); | |
while (count) { | |
str += str; | |
count--; | |
} | |
str += str.substring(0, maxCount - str.length); | |
return str; | |
} | |
var blue = ''; | |
var green = ''; | |
var red = ''; | |
var white = ''; | |
var kReadableOperator = { | |
deepStrictEqual: 'Expected values to be strictly deep-equal:', | |
strictEqual: 'Expected values to be strictly equal:', | |
strictEqualObject: 'Expected "actual" to be reference-equal to "expected":', | |
deepEqual: 'Expected values to be loosely deep-equal:', | |
equal: 'Expected values to be loosely equal:', | |
notDeepStrictEqual: 'Expected "actual" not to be strictly deep-equal to:', | |
notStrictEqual: 'Expected "actual" to be strictly unequal to:', | |
notStrictEqualObject: 'Expected "actual" not to be reference-equal to "expected":', | |
notDeepEqual: 'Expected "actual" not to be loosely deep-equal to:', | |
notEqual: 'Expected "actual" to be loosely unequal to:', | |
notIdentical: 'Values identical but not reference-equal:' | |
}; // Comparing short primitives should just show === / !== instead of using the | |
// diff. | |
var kMaxShortLength = 10; | |
function copyError(source) { | |
var keys = Object.keys(source); | |
var target = Object.create(Object.getPrototypeOf(source)); | |
keys.forEach(function (key) { | |
target[key] = source[key]; | |
}); | |
Object.defineProperty(target, 'message', { | |
value: source.message | |
}); | |
return target; | |
} | |
function inspectValue(val) { | |
// The util.inspect default values could be changed. This makes sure the | |
// error messages contain the necessary information nevertheless. | |
return inspect(val, { | |
compact: false, | |
customInspect: false, | |
depth: 1000, | |
maxArrayLength: Infinity, | |
// Assert compares only enumerable properties (with a few exceptions). | |
showHidden: false, | |
// Having a long line as error is better than wrapping the line for | |
// comparison for now. | |
// TODO(BridgeAR): `breakLength` should be limited as soon as soon as we | |
// have meta information about the inspected properties (i.e., know where | |
// in what line the property starts and ends). | |
breakLength: Infinity, | |
// Assert does not detect proxies currently. | |
showProxy: false, | |
sorted: true, | |
// Inspect getters as we also check them when comparing entries. | |
getters: true | |
}); | |
} | |
function createErrDiff(actual, expected, operator) { | |
var other = ''; | |
var res = ''; | |
var lastPos = 0; | |
var end = ''; | |
var skipped = false; | |
var actualInspected = inspectValue(actual); | |
var actualLines = actualInspected.split('\n'); | |
var expectedLines = inspectValue(expected).split('\n'); | |
var i = 0; | |
var indicator = ''; // In case both values are objects explicitly mark them as not reference equal | |
// for the `strictEqual` operator. | |
if (operator === 'strictEqual' && _typeof(actual) === 'object' && _typeof(expected) === 'object' && actual !== null && expected !== null) { | |
operator = 'strictEqualObject'; | |
} // If "actual" and "expected" fit on a single line and they are not strictly | |
// equal, check further special handling. | |
if (actualLines.length === 1 && expectedLines.length === 1 && actualLines[0] !== expectedLines[0]) { | |
var inputLength = actualLines[0].length + expectedLines[0].length; // If the character length of "actual" and "expected" together is less than | |
// kMaxShortLength and if neither is an object and at least one of them is | |
// not `zero`, use the strict equal comparison to visualize the output. | |
if (inputLength <= kMaxShortLength) { | |
if ((_typeof(actual) !== 'object' || actual === null) && (_typeof(expected) !== 'object' || expected === null) && (actual !== 0 || expected !== 0)) { | |
// -0 === +0 | |
return "".concat(kReadableOperator[operator], "\n\n") + "".concat(actualLines[0], " !== ").concat(expectedLines[0], "\n"); | |
} | |
} else if (operator !== 'strictEqualObject') { | |
// If the stderr is a tty and the input length is lower than the current | |
// columns per line, add a mismatch indicator below the output. If it is | |
// not a tty, use a default value of 80 characters. | |
var maxLength = process.stderr && process.stderr.isTTY ? process.stderr.columns : 80; | |
if (inputLength < maxLength) { | |
while (actualLines[0][i] === expectedLines[0][i]) { | |
i++; | |
} // Ignore the first characters. | |
if (i > 2) { | |
// Add position indicator for the first mismatch in case it is a | |
// single line and the input length is less than the column length. | |
indicator = "\n ".concat(repeat(' ', i), "^"); | |
i = 0; | |
} | |
} | |
} | |
} // Remove all ending lines that match (this optimizes the output for | |
// readability by reducing the number of total changed lines). | |
var a = actualLines[actualLines.length - 1]; | |
var b = expectedLines[expectedLines.length - 1]; | |
while (a === b) { | |
if (i++ < 2) { | |
end = "\n ".concat(a).concat(end); | |
} else { | |
other = a; | |
} | |
actualLines.pop(); | |
expectedLines.pop(); | |
if (actualLines.length === 0 || expectedLines.length === 0) break; | |
a = actualLines[actualLines.length - 1]; | |
b = expectedLines[expectedLines.length - 1]; | |
} | |
var maxLines = Math.max(actualLines.length, expectedLines.length); // Strict equal with identical objects that are not identical by reference. | |
// E.g., assert.deepStrictEqual({ a: Symbol() }, { a: Symbol() }) | |
if (maxLines === 0) { | |
// We have to get the result again. The lines were all removed before. | |
var _actualLines = actualInspected.split('\n'); // Only remove lines in case it makes sense to collapse those. | |
// TODO: Accept env to always show the full error. | |
if (_actualLines.length > 30) { | |
_actualLines[26] = "".concat(blue, "...").concat(white); | |
while (_actualLines.length > 27) { | |
_actualLines.pop(); | |
} | |
} | |
return "".concat(kReadableOperator.notIdentical, "\n\n").concat(_actualLines.join('\n'), "\n"); | |
} | |
if (i > 3) { | |
end = "\n".concat(blue, "...").concat(white).concat(end); | |
skipped = true; | |
} | |
if (other !== '') { | |
end = "\n ".concat(other).concat(end); | |
other = ''; | |
} | |
var printedLines = 0; | |
var msg = kReadableOperator[operator] + "\n".concat(green, "+ actual").concat(white, " ").concat(red, "- expected").concat(white); | |
var skippedMsg = " ".concat(blue, "...").concat(white, " Lines skipped"); | |
for (i = 0; i < maxLines; i++) { | |
// Only extra expected lines exist | |
var cur = i - lastPos; | |
if (actualLines.length < i + 1) { | |
// If the last diverging line is more than one line above and the | |
// current line is at least line three, add some of the former lines and | |
// also add dots to indicate skipped entries. | |
if (cur > 1 && i > 2) { | |
if (cur > 4) { | |
res += "\n".concat(blue, "...").concat(white); | |
skipped = true; | |
} else if (cur > 3) { | |
res += "\n ".concat(expectedLines[i - 2]); | |
printedLines++; | |
} | |
res += "\n ".concat(expectedLines[i - 1]); | |
printedLines++; | |
} // Mark the current line as the last diverging one. | |
lastPos = i; // Add the expected line to the cache. | |
other += "\n".concat(red, "-").concat(white, " ").concat(expectedLines[i]); | |
printedLines++; // Only extra actual lines exist | |
} else if (expectedLines.length < i + 1) { | |
// If the last diverging line is more than one line above and the | |
// current line is at least line three, add some of the former lines and | |
// also add dots to indicate skipped entries. | |
if (cur > 1 && i > 2) { | |
if (cur > 4) { | |
res += "\n".concat(blue, "...").concat(white); | |
skipped = true; | |
} else if (cur > 3) { | |
res += "\n ".concat(actualLines[i - 2]); | |
printedLines++; | |
} | |
res += "\n ".concat(actualLines[i - 1]); | |
printedLines++; | |
} // Mark the current line as the last diverging one. | |
lastPos = i; // Add the actual line to the result. | |
res += "\n".concat(green, "+").concat(white, " ").concat(actualLines[i]); | |
printedLines++; // Lines diverge | |
} else { | |
var expectedLine = expectedLines[i]; | |
var actualLine = actualLines[i]; // If the lines diverge, specifically check for lines that only diverge by | |
// a trailing comma. In that case it is actually identical and we should | |
// mark it as such. | |
var divergingLines = actualLine !== expectedLine && (!endsWith(actualLine, ',') || actualLine.slice(0, -1) !== expectedLine); // If the expected line has a trailing comma but is otherwise identical, | |
// add a comma at the end of the actual line. Otherwise the output could | |
// look weird as in: | |
// | |
// [ | |
// 1 // No comma at the end! | |
// + 2 | |
// ] | |
// | |
if (divergingLines && endsWith(expectedLine, ',') && expectedLine.slice(0, -1) === actualLine) { | |
divergingLines = false; | |
actualLine += ','; | |
} | |
if (divergingLines) { | |
// If the last diverging line is more than one line above and the | |
// current line is at least line three, add some of the former lines and | |
// also add dots to indicate skipped entries. | |
if (cur > 1 && i > 2) { | |
if (cur > 4) { | |
res += "\n".concat(blue, "...").concat(white); | |
skipped = true; | |
} else if (cur > 3) { | |
res += "\n ".concat(actualLines[i - 2]); | |
printedLines++; | |
} | |
res += "\n ".concat(actualLines[i - 1]); | |
printedLines++; | |
} // Mark the current line as the last diverging one. | |
lastPos = i; // Add the actual line to the result and cache the expected diverging | |
// line so consecutive diverging lines show up as +++--- and not +-+-+-. | |
res += "\n".concat(green, "+").concat(white, " ").concat(actualLine); | |
other += "\n".concat(red, "-").concat(white, " ").concat(expectedLine); | |
printedLines += 2; // Lines are identical | |
} else { | |
// Add all cached information to the result before adding other things | |
// and reset the cache. | |
res += other; | |
other = ''; // If the last diverging line is exactly one line above or if it is the | |
// very first line, add the line to the result. | |
if (cur === 1 || i === 0) { | |
res += "\n ".concat(actualLine); | |
printedLines++; | |
} | |
} | |
} // Inspected object to big (Show ~20 rows max) | |
if (printedLines > 20 && i < maxLines - 2) { | |
return "".concat(msg).concat(skippedMsg, "\n").concat(res, "\n").concat(blue, "...").concat(white).concat(other, "\n") + "".concat(blue, "...").concat(white); | |
} | |
} | |
return "".concat(msg).concat(skipped ? skippedMsg : '', "\n").concat(res).concat(other).concat(end).concat(indicator); | |
} | |
var AssertionError = | |
/*#__PURE__*/ | |
function (_Error) { | |
_inherits(AssertionError, _Error); | |
function AssertionError(options) { | |
var _this; | |
_classCallCheck(this, AssertionError); | |
if (_typeof(options) !== 'object' || options === null) { | |
throw new ERR_INVALID_ARG_TYPE('options', 'Object', options); | |
} | |
var message = options.message, | |
operator = options.operator, | |
stackStartFn = options.stackStartFn; | |
var actual = options.actual, | |
expected = options.expected; | |
var limit = Error.stackTraceLimit; | |
Error.stackTraceLimit = 0; | |
if (message != null) { | |
_this = _possibleConstructorReturn(this, _getPrototypeOf(AssertionError).call(this, String(message))); | |
} else { | |
if (process.stderr && process.stderr.isTTY) { | |
// Reset on each call to make sure we handle dynamically set environment | |
// variables correct. | |
if (process.stderr && process.stderr.getColorDepth && process.stderr.getColorDepth() !== 1) { | |
blue = "\x1B[34m"; | |
green = "\x1B[32m"; | |
white = "\x1B[39m"; | |
red = "\x1B[31m"; | |
} else { | |
blue = ''; | |
green = ''; | |
white = ''; | |
red = ''; | |
} | |
} // Prevent the error stack from being visible by duplicating the error | |
// in a very close way to the original in case both sides are actually | |
// instances of Error. | |
if (_typeof(actual) === 'object' && actual !== null && _typeof(expected) === 'object' && expected !== null && 'stack' in actual && actual instanceof Error && 'stack' in expected && expected instanceof Error) { | |
actual = copyError(actual); | |
expected = copyError(expected); | |
} | |
if (operator === 'deepStrictEqual' || operator === 'strictEqual') { | |
_this = _possibleConstructorReturn(this, _getPrototypeOf(AssertionError).call(this, createErrDiff(actual, expected, operator))); | |
} else if (operator === 'notDeepStrictEqual' || operator === 'notStrictEqual') { | |
// In case the objects are equal but the operator requires unequal, show | |
// the first object and say A equals B | |
var base = kReadableOperator[operator]; | |
var res = inspectValue(actual).split('\n'); // In case "actual" is an object, it should not be reference equal. | |
if (operator === 'notStrictEqual' && _typeof(actual) === 'object' && actual !== null) { | |
base = kReadableOperator.notStrictEqualObject; | |
} // Only remove lines in case it makes sense to collapse those. | |
// TODO: Accept env to always show the full error. | |
if (res.length > 30) { | |
res[26] = "".concat(blue, "...").concat(white); | |
while (res.length > 27) { | |
res.pop(); | |
} | |
} // Only print a single input. | |
if (res.length === 1) { | |
_this = _possibleConstructorReturn(this, _getPrototypeOf(AssertionError).call(this, "".concat(base, " ").concat(res[0]))); | |
} else { | |
_this = _possibleConstructorReturn(this, _getPrototypeOf(AssertionError).call(this, "".concat(base, "\n\n").concat(res.join('\n'), "\n"))); | |
} | |
} else { | |
var _res = inspectValue(actual); | |
var other = ''; | |
var knownOperators = kReadableOperator[operator]; | |
if (operator === 'notDeepEqual' || operator === 'notEqual') { | |
_res = "".concat(kReadableOperator[operator], "\n\n").concat(_res); | |
if (_res.length > 1024) { | |
_res = "".concat(_res.slice(0, 1021), "..."); | |
} | |
} else { | |
other = "".concat(inspectValue(expected)); | |
if (_res.length > 512) { | |
_res = "".concat(_res.slice(0, 509), "..."); | |
} | |
if (other.length > 512) { | |
other = "".concat(other.slice(0, 509), "..."); | |
} | |
if (operator === 'deepEqual' || operator === 'equal') { | |
_res = "".concat(knownOperators, "\n\n").concat(_res, "\n\nshould equal\n\n"); | |
} else { | |
other = " ".concat(operator, " ").concat(other); | |
} | |
} | |
_this = _possibleConstructorReturn(this, _getPrototypeOf(AssertionError).call(this, "".concat(_res).concat(other))); | |
} | |
} | |
Error.stackTraceLimit = limit; | |
_this.generatedMessage = !message; | |
Object.defineProperty(_assertThisInitialized(_this), 'name', { | |
value: 'AssertionError [ERR_ASSERTION]', | |
enumerable: false, | |
writable: true, | |
configurable: true | |
}); | |
_this.code = 'ERR_ASSERTION'; | |
_this.actual = actual; | |
_this.expected = expected; | |
_this.operator = operator; | |
if (Error.captureStackTrace) { | |
// eslint-disable-next-line no-restricted-syntax | |
Error.captureStackTrace(_assertThisInitialized(_this), stackStartFn); | |
} // Create error message including the error code in the name. | |
_this.stack; // Reset the name. | |
_this.name = 'AssertionError'; | |
return _possibleConstructorReturn(_this); | |
} | |
_createClass(AssertionError, [{ | |
key: "toString", | |
value: function toString() { | |
return "".concat(this.name, " [").concat(this.code, "]: ").concat(this.message); | |
} | |
}, { | |
key: inspect.custom, | |
value: function value(recurseTimes, ctx) { | |
// This limits the `actual` and `expected` property default inspection to | |
// the minimum depth. Otherwise those values would be too verbose compared | |
// to the actual error message which contains a combined view of these two | |
// input values. | |
return inspect(this, _objectSpread({}, ctx, { | |
customInspect: false, | |
depth: 0 | |
})); | |
} | |
}]); | |
return AssertionError; | |
}(_wrapNativeSuper(Error)); | |
module.exports = AssertionError; | |
/***/ }), | |
/***/ 2136: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
// Currently in sync with Node.js lib/internal/errors.js | |
// https://github.com/nodejs/node/commit/3b044962c48fe313905877a96b5d0894a5404f6f | |
/* eslint node-core/documented-errors: "error" */ | |
/* eslint node-core/alphabetize-errors: "error" */ | |
/* eslint node-core/prefer-util-format-errors: "error" */ | |
// The whole point behind this internal module is to allow Node.js to no | |
// longer be forced to treat every error message change as a semver-major | |
// change. The NodeError classes here all expose a `code` property whose | |
// value statically and permanently identifies the error. While the error | |
// message may change, the code should not. | |
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | |
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | |
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | |
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | |
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | |
var codes = {}; // Lazy loaded | |
var assert; | |
var util; | |
function createErrorType(code, message, Base) { | |
if (!Base) { | |
Base = Error; | |
} | |
function getMessage(arg1, arg2, arg3) { | |
if (typeof message === 'string') { | |
return message; | |
} else { | |
return message(arg1, arg2, arg3); | |
} | |
} | |
var NodeError = | |
/*#__PURE__*/ | |
function (_Base) { | |
_inherits(NodeError, _Base); | |
function NodeError(arg1, arg2, arg3) { | |
var _this; | |
_classCallCheck(this, NodeError); | |
_this = _possibleConstructorReturn(this, _getPrototypeOf(NodeError).call(this, getMessage(arg1, arg2, arg3))); | |
_this.code = code; | |
return _this; | |
} | |
return NodeError; | |
}(Base); | |
codes[code] = NodeError; | |
} // https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js | |
function oneOf(expected, thing) { | |
if (Array.isArray(expected)) { | |
var len = expected.length; | |
expected = expected.map(function (i) { | |
return String(i); | |
}); | |
if (len > 2) { | |
return "one of ".concat(thing, " ").concat(expected.slice(0, len - 1).join(', '), ", or ") + expected[len - 1]; | |
} else if (len === 2) { | |
return "one of ".concat(thing, " ").concat(expected[0], " or ").concat(expected[1]); | |
} else { | |
return "of ".concat(thing, " ").concat(expected[0]); | |
} | |
} else { | |
return "of ".concat(thing, " ").concat(String(expected)); | |
} | |
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith | |
function startsWith(str, search, pos) { | |
return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; | |
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith | |
function endsWith(str, search, this_len) { | |
if (this_len === undefined || this_len > str.length) { | |
this_len = str.length; | |
} | |
return str.substring(this_len - search.length, this_len) === search; | |
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes | |
function includes(str, search, start) { | |
if (typeof start !== 'number') { | |
start = 0; | |
} | |
if (start + search.length > str.length) { | |
return false; | |
} else { | |
return str.indexOf(search, start) !== -1; | |
} | |
} | |
createErrorType('ERR_AMBIGUOUS_ARGUMENT', 'The "%s" argument is ambiguous. %s', TypeError); | |
createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) { | |
if (assert === undefined) assert = __webpack_require__(9282); | |
assert(typeof name === 'string', "'name' must be a string"); // determiner: 'must be' or 'must not be' | |
var determiner; | |
if (typeof expected === 'string' && startsWith(expected, 'not ')) { | |
determiner = 'must not be'; | |
expected = expected.replace(/^not /, ''); | |
} else { | |
determiner = 'must be'; | |
} | |
var msg; | |
if (endsWith(name, ' argument')) { | |
// For cases like 'first argument' | |
msg = "The ".concat(name, " ").concat(determiner, " ").concat(oneOf(expected, 'type')); | |
} else { | |
var type = includes(name, '.') ? 'property' : 'argument'; | |
msg = "The \"".concat(name, "\" ").concat(type, " ").concat(determiner, " ").concat(oneOf(expected, 'type')); | |
} // TODO(BridgeAR): Improve the output by showing `null` and similar. | |
msg += ". Received type ".concat(_typeof(actual)); | |
return msg; | |
}, TypeError); | |
createErrorType('ERR_INVALID_ARG_VALUE', function (name, value) { | |
var reason = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'is invalid'; | |
if (util === undefined) util = __webpack_require__(9539); | |
var inspected = util.inspect(value); | |
if (inspected.length > 128) { | |
inspected = "".concat(inspected.slice(0, 128), "..."); | |
} | |
return "The argument '".concat(name, "' ").concat(reason, ". Received ").concat(inspected); | |
}, TypeError, RangeError); | |
createErrorType('ERR_INVALID_RETURN_VALUE', function (input, name, value) { | |
var type; | |
if (value && value.constructor && value.constructor.name) { | |
type = "instance of ".concat(value.constructor.name); | |
} else { | |
type = "type ".concat(_typeof(value)); | |
} | |
return "Expected ".concat(input, " to be returned from the \"").concat(name, "\"") + " function but got ".concat(type, "."); | |
}, TypeError); | |
createErrorType('ERR_MISSING_ARGS', function () { | |
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | |
args[_key] = arguments[_key]; | |
} | |
if (assert === undefined) assert = __webpack_require__(9282); | |
assert(args.length > 0, 'At least one arg needs to be specified'); | |
var msg = 'The '; | |
var len = args.length; | |
args = args.map(function (a) { | |
return "\"".concat(a, "\""); | |
}); | |
switch (len) { | |
case 1: | |
msg += "".concat(args[0], " argument"); | |
break; | |
case 2: | |
msg += "".concat(args[0], " and ").concat(args[1], " arguments"); | |
break; | |
default: | |
msg += args.slice(0, len - 1).join(', '); | |
msg += ", and ".concat(args[len - 1], " arguments"); | |
break; | |
} | |
return "".concat(msg, " must be specified"); | |
}, TypeError); | |
module.exports.codes = codes; | |
/***/ }), | |
/***/ 9158: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
// Currently in sync with Node.js lib/internal/util/comparisons.js | |
// https://github.com/nodejs/node/commit/112cc7c27551254aa2b17098fb774867f05ed0d9 | |
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } | |
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } | |
function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } | |
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } | |
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | |
var regexFlagsSupported = /a/g.flags !== undefined; | |
var arrayFromSet = function arrayFromSet(set) { | |
var array = []; | |
set.forEach(function (value) { | |
return array.push(value); | |
}); | |
return array; | |
}; | |
var arrayFromMap = function arrayFromMap(map) { | |
var array = []; | |
map.forEach(function (value, key) { | |
return array.push([key, value]); | |
}); | |
return array; | |
}; | |
var objectIs = Object.is ? Object.is : __webpack_require__(609); | |
var objectGetOwnPropertySymbols = Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols : function () { | |
return []; | |
}; | |
var numberIsNaN = Number.isNaN ? Number.isNaN : __webpack_require__(360); | |
function uncurryThis(f) { | |
return f.call.bind(f); | |
} | |
var hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty); | |
var propertyIsEnumerable = uncurryThis(Object.prototype.propertyIsEnumerable); | |
var objectToString = uncurryThis(Object.prototype.toString); | |
var _require$types = (__webpack_require__(9539).types), | |
isAnyArrayBuffer = _require$types.isAnyArrayBuffer, | |
isArrayBufferView = _require$types.isArrayBufferView, | |
isDate = _require$types.isDate, | |
isMap = _require$types.isMap, | |
isRegExp = _require$types.isRegExp, | |
isSet = _require$types.isSet, | |
isNativeError = _require$types.isNativeError, | |
isBoxedPrimitive = _require$types.isBoxedPrimitive, | |
isNumberObject = _require$types.isNumberObject, | |
isStringObject = _require$types.isStringObject, | |
isBooleanObject = _require$types.isBooleanObject, | |
isBigIntObject = _require$types.isBigIntObject, | |
isSymbolObject = _require$types.isSymbolObject, | |
isFloat32Array = _require$types.isFloat32Array, | |
isFloat64Array = _require$types.isFloat64Array; | |
function isNonIndex(key) { | |
if (key.length === 0 || key.length > 10) return true; | |
for (var i = 0; i < key.length; i++) { | |
var code = key.charCodeAt(i); | |
if (code < 48 || code > 57) return true; | |
} // The maximum size for an array is 2 ** 32 -1. | |
return key.length === 10 && key >= Math.pow(2, 32); | |
} | |
function getOwnNonIndexProperties(value) { | |
return Object.keys(value).filter(isNonIndex).concat(objectGetOwnPropertySymbols(value).filter(Object.prototype.propertyIsEnumerable.bind(value))); | |
} // Taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js | |
// original notice: | |
/*! | |
* The buffer module from node.js, for the browser. | |
* | |
* @author Feross Aboukhadijeh <[email protected]> <http://feross.org> | |
* @license MIT | |
*/ | |
function compare(a, b) { | |
if (a === b) { | |
return 0; | |
} | |
var x = a.length; | |
var y = b.length; | |
for (var i = 0, len = Math.min(x, y); i < len; ++i) { | |
if (a[i] !== b[i]) { | |
x = a[i]; | |
y = b[i]; | |
break; | |
} | |
} | |
if (x < y) { | |
return -1; | |
} | |
if (y < x) { | |
return 1; | |
} | |
return 0; | |
} | |
var ONLY_ENUMERABLE = undefined; | |
var kStrict = true; | |
var kLoose = false; | |
var kNoIterator = 0; | |
var kIsArray = 1; | |
var kIsSet = 2; | |
var kIsMap = 3; // Check if they have the same source and flags | |
function areSimilarRegExps(a, b) { | |
return regexFlagsSupported ? a.source === b.source && a.flags === b.flags : RegExp.prototype.toString.call(a) === RegExp.prototype.toString.call(b); | |
} | |
function areSimilarFloatArrays(a, b) { | |
if (a.byteLength !== b.byteLength) { | |
return false; | |
} | |
for (var offset = 0; offset < a.byteLength; offset++) { | |
if (a[offset] !== b[offset]) { | |
return false; | |
} | |
} | |
return true; | |
} | |
function areSimilarTypedArrays(a, b) { | |
if (a.byteLength !== b.byteLength) { | |
return false; | |
} | |
return compare(new Uint8Array(a.buffer, a.byteOffset, a.byteLength), new Uint8Array(b.buffer, b.byteOffset, b.byteLength)) === 0; | |
} | |
function areEqualArrayBuffers(buf1, buf2) { | |
return buf1.byteLength === buf2.byteLength && compare(new Uint8Array(buf1), new Uint8Array(buf2)) === 0; | |
} | |
function isEqualBoxedPrimitive(val1, val2) { | |
if (isNumberObject(val1)) { | |
return isNumberObject(val2) && objectIs(Number.prototype.valueOf.call(val1), Number.prototype.valueOf.call(val2)); | |
} | |
if (isStringObject(val1)) { | |
return isStringObject(val2) && String.prototype.valueOf.call(val1) === String.prototype.valueOf.call(val2); | |
} | |
if (isBooleanObject(val1)) { | |
return isBooleanObject(val2) && Boolean.prototype.valueOf.call(val1) === Boolean.prototype.valueOf.call(val2); | |
} | |
if (isBigIntObject(val1)) { | |
return isBigIntObject(val2) && BigInt.prototype.valueOf.call(val1) === BigInt.prototype.valueOf.call(val2); | |
} | |
return isSymbolObject(val2) && Symbol.prototype.valueOf.call(val1) === Symbol.prototype.valueOf.call(val2); | |
} // Notes: Type tags are historical [[Class]] properties that can be set by | |
// FunctionTemplate::SetClassName() in C++ or Symbol.toStringTag in JS | |
// and retrieved using Object.prototype.toString.call(obj) in JS | |
// See https://tc39.github.io/ecma262/#sec-object.prototype.tostring | |
// for a list of tags pre-defined in the spec. | |
// There are some unspecified tags in the wild too (e.g. typed array tags). | |
// Since tags can be altered, they only serve fast failures | |
// | |
// Typed arrays and buffers are checked by comparing the content in their | |
// underlying ArrayBuffer. This optimization requires that it's | |
// reasonable to interpret their underlying memory in the same way, | |
// which is checked by comparing their type tags. | |
// (e.g. a Uint8Array and a Uint16Array with the same memory content | |
// could still be different because they will be interpreted differently). | |
// | |
// For strict comparison, objects should have | |
// a) The same built-in type tags | |
// b) The same prototypes. | |
function innerDeepEqual(val1, val2, strict, memos) { | |
// All identical values are equivalent, as determined by ===. | |
if (val1 === val2) { | |
if (val1 !== 0) return true; | |
return strict ? objectIs(val1, val2) : true; | |
} // Check more closely if val1 and val2 are equal. | |
if (strict) { | |
if (_typeof(val1) !== 'object') { | |
return typeof val1 === 'number' && numberIsNaN(val1) && numberIsNaN(val2); | |
} | |
if (_typeof(val2) !== 'object' || val1 === null || val2 === null) { | |
return false; | |
} | |
if (Object.getPrototypeOf(val1) !== Object.getPrototypeOf(val2)) { | |
return false; | |
} | |
} else { | |
if (val1 === null || _typeof(val1) !== 'object') { | |
if (val2 === null || _typeof(val2) !== 'object') { | |
// eslint-disable-next-line eqeqeq | |
return val1 == val2; | |
} | |
return false; | |
} | |
if (val2 === null || _typeof(val2) !== 'object') { | |
return false; | |
} | |
} | |
var val1Tag = objectToString(val1); | |
var val2Tag = objectToString(val2); | |
if (val1Tag !== val2Tag) { | |
return false; | |
} | |
if (Array.isArray(val1)) { | |
// Check for sparse arrays and general fast path | |
if (val1.length !== val2.length) { | |
return false; | |
} | |
var keys1 = getOwnNonIndexProperties(val1, ONLY_ENUMERABLE); | |
var keys2 = getOwnNonIndexProperties(val2, ONLY_ENUMERABLE); | |
if (keys1.length !== keys2.length) { | |
return false; | |
} | |
return keyCheck(val1, val2, strict, memos, kIsArray, keys1); | |
} // [browserify] This triggers on certain types in IE (Map/Set) so we don't | |
// wan't to early return out of the rest of the checks. However we can check | |
// if the second value is one of these values and the first isn't. | |
if (val1Tag === '[object Object]') { | |
// return keyCheck(val1, val2, strict, memos, kNoIterator); | |
if (!isMap(val1) && isMap(val2) || !isSet(val1) && isSet(val2)) { | |
return false; | |
} | |
} | |
if (isDate(val1)) { | |
if (!isDate(val2) || Date.prototype.getTime.call(val1) !== Date.prototype.getTime.call(val2)) { | |
return false; | |
} | |
} else if (isRegExp(val1)) { | |
if (!isRegExp(val2) || !areSimilarRegExps(val1, val2)) { | |
return false; | |
} | |
} else if (isNativeError(val1) || val1 instanceof Error) { | |
// Do not compare the stack as it might differ even though the error itself | |
// is otherwise identical. | |
if (val1.message !== val2.message || val1.name !== val2.name) { | |
return false; | |
} | |
} else if (isArrayBufferView(val1)) { | |
if (!strict && (isFloat32Array(val1) || isFloat64Array(val1))) { | |
if (!areSimilarFloatArrays(val1, val2)) { | |
return false; | |
} | |
} else if (!areSimilarTypedArrays(val1, val2)) { | |
return false; | |
} // Buffer.compare returns true, so val1.length === val2.length. If they both | |
// only contain numeric keys, we don't need to exam further than checking | |
// the symbols. | |
var _keys = getOwnNonIndexProperties(val1, ONLY_ENUMERABLE); | |
var _keys2 = getOwnNonIndexProperties(val2, ONLY_ENUMERABLE); | |
if (_keys.length !== _keys2.length) { | |
return false; | |
} | |
return keyCheck(val1, val2, strict, memos, kNoIterator, _keys); | |
} else if (isSet(val1)) { | |
if (!isSet(val2) || val1.size !== val2.size) { | |
return false; | |
} | |
return keyCheck(val1, val2, strict, memos, kIsSet); | |
} else if (isMap(val1)) { | |
if (!isMap(val2) || val1.size !== val2.size) { | |
return false; | |
} | |
return keyCheck(val1, val2, strict, memos, kIsMap); | |
} else if (isAnyArrayBuffer(val1)) { | |
if (!areEqualArrayBuffers(val1, val2)) { | |
return false; | |
} | |
} else if (isBoxedPrimitive(val1) && !isEqualBoxedPrimitive(val1, val2)) { | |
return false; | |
} | |
return keyCheck(val1, val2, strict, memos, kNoIterator); | |
} | |
function getEnumerables(val, keys) { | |
return keys.filter(function (k) { | |
return propertyIsEnumerable(val, k); | |
}); | |
} | |
function keyCheck(val1, val2, strict, memos, iterationType, aKeys) { | |
// For all remaining Object pairs, including Array, objects and Maps, | |
// equivalence is determined by having: | |
// a) The same number of owned enumerable properties | |
// b) The same set of keys/indexes (although not necessarily the same order) | |
// c) Equivalent values for every corresponding key/index | |
// d) For Sets and Maps, equal contents | |
// Note: this accounts for both named and indexed properties on Arrays. | |
if (arguments.length === 5) { | |
aKeys = Object.keys(val1); | |
var bKeys = Object.keys(val2); // The pair must have the same number of owned properties. | |
if (aKeys.length !== bKeys.length) { | |
return false; | |
} | |
} // Cheap key test | |
var i = 0; | |
for (; i < aKeys.length; i++) { | |
if (!hasOwnProperty(val2, aKeys[i])) { | |
return false; | |
} | |
} | |
if (strict && arguments.length === 5) { | |
var symbolKeysA = objectGetOwnPropertySymbols(val1); | |
if (symbolKeysA.length !== 0) { | |
var count = 0; | |
for (i = 0; i < symbolKeysA.length; i++) { | |
var key = symbolKeysA[i]; | |
if (propertyIsEnumerable(val1, key)) { | |
if (!propertyIsEnumerable(val2, key)) { | |
return false; | |
} | |
aKeys.push(key); | |
count++; | |
} else if (propertyIsEnumerable(val2, key)) { | |
return false; | |
} | |
} | |
var symbolKeysB = objectGetOwnPropertySymbols(val2); | |
if (symbolKeysA.length !== symbolKeysB.length && getEnumerables(val2, symbolKeysB).length !== count) { | |
return false; | |
} | |
} else { | |
var _symbolKeysB = objectGetOwnPropertySymbols(val2); | |
if (_symbolKeysB.length !== 0 && getEnumerables(val2, _symbolKeysB).length !== 0) { | |
return false; | |
} | |
} | |
} | |
if (aKeys.length === 0 && (iterationType === kNoIterator || iterationType === kIsArray && val1.length === 0 || val1.size === 0)) { | |
return true; | |
} // Use memos to handle cycles. | |
if (memos === undefined) { | |
memos = { | |
val1: new Map(), | |
val2: new Map(), | |
position: 0 | |
}; | |
} else { | |
// We prevent up to two map.has(x) calls by directly retrieving the value | |
// and checking for undefined. The map can only contain numbers, so it is | |
// safe to check for undefined only. | |
var val2MemoA = memos.val1.get(val1); | |
if (val2MemoA !== undefined) { | |
var val2MemoB = memos.val2.get(val2); | |
if (val2MemoB !== undefined) { | |
return val2MemoA === val2MemoB; | |
} | |
} | |
memos.position++; | |
} | |
memos.val1.set(val1, memos.position); | |
memos.val2.set(val2, memos.position); | |
var areEq = objEquiv(val1, val2, strict, aKeys, memos, iterationType); | |
memos.val1.delete(val1); | |
memos.val2.delete(val2); | |
return areEq; | |
} | |
function setHasEqualElement(set, val1, strict, memo) { | |
// Go looking. | |
var setValues = arrayFromSet(set); | |
for (var i = 0; i < setValues.length; i++) { | |
var val2 = setValues[i]; | |
if (innerDeepEqual(val1, val2, strict, memo)) { | |
// Remove the matching element to make sure we do not check that again. | |
set.delete(val2); | |
return true; | |
} | |
} | |
return false; | |
} // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#Loose_equality_using | |
// Sadly it is not possible to detect corresponding values properly in case the | |
// type is a string, number, bigint or boolean. The reason is that those values | |
// can match lots of different string values (e.g., 1n == '+00001'). | |
function findLooseMatchingPrimitives(prim) { | |
switch (_typeof(prim)) { | |
case 'undefined': | |
return null; | |
case 'object': | |
// Only pass in null as object! | |
return undefined; | |
case 'symbol': | |
return false; | |
case 'string': | |
prim = +prim; | |
// Loose equal entries exist only if the string is possible to convert to | |
// a regular number and not NaN. | |
// Fall through | |
case 'number': | |
if (numberIsNaN(prim)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
function setMightHaveLoosePrim(a, b, prim) { | |
var altValue = findLooseMatchingPrimitives(prim); | |
if (altValue != null) return altValue; | |
return b.has(altValue) && !a.has(altValue); | |
} | |
function mapMightHaveLoosePrim(a, b, prim, item, memo) { | |
var altValue = findLooseMatchingPrimitives(prim); | |
if (altValue != null) { | |
return altValue; | |
} | |
var curB = b.get(altValue); | |
if (curB === undefined && !b.has(altValue) || !innerDeepEqual(item, curB, false, memo)) { | |
return false; | |
} | |
return !a.has(altValue) && innerDeepEqual(item, curB, false, memo); | |
} | |
function setEquiv(a, b, strict, memo) { | |
// This is a lazily initiated Set of entries which have to be compared | |
// pairwise. | |
var set = null; | |
var aValues = arrayFromSet(a); | |
for (var i = 0; i < aValues.length; i++) { | |
var val = aValues[i]; // Note: Checking for the objects first improves the performance for object | |
// heavy sets but it is a minor slow down for primitives. As they are fast | |
// to check this improves the worst case scenario instead. | |
if (_typeof(val) === 'object' && val !== null) { | |
if (set === null) { | |
set = new Set(); | |
} // If the specified value doesn't exist in the second set its an not null | |
// object (or non strict only: a not matching primitive) we'll need to go | |
// hunting for something thats deep-(strict-)equal to it. To make this | |
// O(n log n) complexity we have to copy these values in a new set first. | |
set.add(val); | |
} else if (!b.has(val)) { | |
if (strict) return false; // Fast path to detect missing string, symbol, undefined and null values. | |
if (!setMightHaveLoosePrim(a, b, val)) { | |
return false; | |
} | |
if (set === null) { | |
set = new Set(); | |
} | |
set.add(val); | |
} | |
} | |
if (set !== null) { | |
var bValues = arrayFromSet(b); | |
for (var _i = 0; _i < bValues.length; _i++) { | |
var _val = bValues[_i]; // We have to check if a primitive value is already | |
// matching and only if it's not, go hunting for it. | |
if (_typeof(_val) === 'object' && _val !== null) { | |
if (!setHasEqualElement(set, _val, strict, memo)) return false; | |
} else if (!strict && !a.has(_val) && !setHasEqualElement(set, _val, strict, memo)) { | |
return false; | |
} | |
} | |
return set.size === 0; | |
} | |
return true; | |
} | |
function mapHasEqualEntry(set, map, key1, item1, strict, memo) { | |
// To be able to handle cases like: | |
// Map([[{}, 'a'], [{}, 'b']]) vs Map([[{}, 'b'], [{}, 'a']]) | |
// ... we need to consider *all* matching keys, not just the first we find. | |
var setValues = arrayFromSet(set); | |
for (var i = 0; i < setValues.length; i++) { | |
var key2 = setValues[i]; | |
if (innerDeepEqual(key1, key2, strict, memo) && innerDeepEqual(item1, map.get(key2), strict, memo)) { | |
set.delete(key2); | |
return true; | |
} | |
} | |
return false; | |
} | |
function mapEquiv(a, b, strict, memo) { | |
var set = null; | |
var aEntries = arrayFromMap(a); | |
for (var i = 0; i < aEntries.length; i++) { | |
var _aEntries$i = _slicedToArray(aEntries[i], 2), | |
key = _aEntries$i[0], | |
item1 = _aEntries$i[1]; | |
if (_typeof(key) === 'object' && key !== null) { | |
if (set === null) { | |
set = new Set(); | |
} | |
set.add(key); | |
} else { | |
// By directly retrieving the value we prevent another b.has(key) check in | |
// almost all possible cases. | |
var item2 = b.get(key); | |
if (item2 === undefined && !b.has(key) || !innerDeepEqual(item1, item2, strict, memo)) { | |
if (strict) return false; // Fast path to detect missing string, symbol, undefined and null | |
// keys. | |
if (!mapMightHaveLoosePrim(a, b, key, item1, memo)) return false; | |
if (set === null) { | |
set = new Set(); | |
} | |
set.add(key); | |
} | |
} | |
} | |
if (set !== null) { | |
var bEntries = arrayFromMap(b); | |
for (var _i2 = 0; _i2 < bEntries.length; _i2++) { | |
var _bEntries$_i = _slicedToArray(bEntries[_i2], 2), | |
key = _bEntries$_i[0], | |
item = _bEntries$_i[1]; | |
if (_typeof(key) === 'object' && key !== null) { | |
if (!mapHasEqualEntry(set, a, key, item, strict, memo)) return false; | |
} else if (!strict && (!a.has(key) || !innerDeepEqual(a.get(key), item, false, memo)) && !mapHasEqualEntry(set, a, key, item, false, memo)) { | |
return false; | |
} | |
} | |
return set.size === 0; | |
} | |
return true; | |
} | |
function objEquiv(a, b, strict, keys, memos, iterationType) { | |
// Sets and maps don't have their entries accessible via normal object | |
// properties. | |
var i = 0; | |
if (iterationType === kIsSet) { | |
if (!setEquiv(a, b, strict, memos)) { | |
return false; | |
} | |
} else if (iterationType === kIsMap) { | |
if (!mapEquiv(a, b, strict, memos)) { | |
return false; | |
} | |
} else if (iterationType === kIsArray) { | |
for (; i < a.length; i++) { | |
if (hasOwnProperty(a, i)) { | |
if (!hasOwnProperty(b, i) || !innerDeepEqual(a[i], b[i], strict, memos)) { | |
return false; | |
} | |
} else if (hasOwnProperty(b, i)) { | |
return false; | |
} else { | |
// Array is sparse. | |
var keysA = Object.keys(a); | |
for (; i < keysA.length; i++) { | |
var key = keysA[i]; | |
if (!hasOwnProperty(b, key) || !innerDeepEqual(a[key], b[key], strict, memos)) { | |
return false; | |
} | |
} | |
if (keysA.length !== Object.keys(b).length) { | |
return false; | |
} | |
return true; | |
} | |
} | |
} // The pair must have equivalent values for every corresponding key. | |
// Possibly expensive deep test: | |
for (i = 0; i < keys.length; i++) { | |
var _key = keys[i]; | |
if (!innerDeepEqual(a[_key], b[_key], strict, memos)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
function isDeepEqual(val1, val2) { | |
return innerDeepEqual(val1, val2, kLoose); | |
} | |
function isDeepStrictEqual(val1, val2) { | |
return innerDeepEqual(val1, val2, kStrict); | |
} | |
module.exports = { | |
isDeepEqual: isDeepEqual, | |
isDeepStrictEqual: isDeepStrictEqual | |
}; | |
/***/ }), | |
/***/ 5623: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = balanced; | |
function balanced(a, b, str) { | |
if (a instanceof RegExp) a = maybeMatch(a, str); | |
if (b instanceof RegExp) b = maybeMatch(b, str); | |
var r = range(a, b, str); | |
return r && { | |
start: r[0], | |
end: r[1], | |
pre: str.slice(0, r[0]), | |
body: str.slice(r[0] + a.length, r[1]), | |
post: str.slice(r[1] + b.length) | |
}; | |
} | |
function maybeMatch(reg, str) { | |
var m = str.match(reg); | |
return m ? m[0] : null; | |
} | |
balanced.range = range; | |
function range(a, b, str) { | |
var begs, beg, left, right, result; | |
var ai = str.indexOf(a); | |
var bi = str.indexOf(b, ai + 1); | |
var i = ai; | |
if (ai >= 0 && bi > 0) { | |
if(a===b) { | |
return [ai, bi]; | |
} | |
begs = []; | |
left = str.length; | |
while (i >= 0 && !result) { | |
if (i == ai) { | |
begs.push(i); | |
ai = str.indexOf(a, i + 1); | |
} else if (begs.length == 1) { | |
result = [ begs.pop(), bi ]; | |
} else { | |
beg = begs.pop(); | |
if (beg < left) { | |
left = beg; | |
right = bi; | |
} | |
bi = str.indexOf(b, i + 1); | |
} | |
i = ai < bi && ai >= 0 ? ai : bi; | |
} | |
if (begs.length) { | |
result = [ left, right ]; | |
} | |
} | |
return result; | |
} | |
/***/ }), | |
/***/ 3644: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
var concatMap = __webpack_require__(1048); | |
var balanced = __webpack_require__(5623); | |
module.exports = expandTop; | |
var escSlash = '\0SLASH'+Math.random()+'\0'; | |
var escOpen = '\0OPEN'+Math.random()+'\0'; | |
var escClose = '\0CLOSE'+Math.random()+'\0'; | |
var escComma = '\0COMMA'+Math.random()+'\0'; | |
var escPeriod = '\0PERIOD'+Math.random()+'\0'; | |
function numeric(str) { | |
return parseInt(str, 10) == str | |
? parseInt(str, 10) | |
: str.charCodeAt(0); | |
} | |
function escapeBraces(str) { | |
return str.split('\\\\').join(escSlash) | |
.split('\\{').join(escOpen) | |
.split('\\}').join(escClose) | |
.split('\\,').join(escComma) | |
.split('\\.').join(escPeriod); | |
} | |
function unescapeBraces(str) { | |
return str.split(escSlash).join('\\') | |
.split(escOpen).join('{') | |
.split(escClose).join('}') | |
.split(escComma).join(',') | |
.split(escPeriod).join('.'); | |
} | |
// Basically just str.split(","), but handling cases | |
// where we have nested braced sections, which should be | |
// treated as individual members, like {a,{b,c},d} | |
function parseCommaParts(str) { | |
if (!str) | |
return ['']; | |
var parts = []; | |
var m = balanced('{', '}', str); | |
if (!m) | |
return str.split(','); | |
var pre = m.pre; | |
var body = m.body; | |
var post = m.post; | |
var p = pre.split(','); | |
p[p.length-1] += '{' + body + '}'; | |
var postParts = parseCommaParts(post); | |
if (post.length) { | |
p[p.length-1] += postParts.shift(); | |
p.push.apply(p, postParts); | |
} | |
parts.push.apply(parts, p); | |
return parts; | |
} | |
function expandTop(str) { | |
if (!str) | |
return []; | |
// I don't know why Bash 4.3 does this, but it does. | |
// Anything starting with {} will have the first two bytes preserved | |
// but *only* at the top level, so {},a}b will not expand to anything, | |
// but a{},b}c will be expanded to [a}c,abc]. | |
// One could argue that this is a bug in Bash, but since the goal of | |
// this module is to match Bash's rules, we escape a leading {} | |
if (str.substr(0, 2) === '{}') { | |
str = '\\{\\}' + str.substr(2); | |
} | |
return expand(escapeBraces(str), true).map(unescapeBraces); | |
} | |
function identity(e) { | |
return e; | |
} | |
function embrace(str) { | |
return '{' + str + '}'; | |
} | |
function isPadded(el) { | |
return /^-?0\d/.test(el); | |
} | |
function lte(i, y) { | |
return i <= y; | |
} | |
function gte(i, y) { | |
return i >= y; | |
} | |
function expand(str, isTop) { | |
var expansions = []; | |
var m = balanced('{', '}', str); | |
if (!m || /\$$/.test(m.pre)) return [str]; | |
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body); | |
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body); | |
var isSequence = isNumericSequence || isAlphaSequence; | |
var isOptions = m.body.indexOf(',') >= 0; | |
if (!isSequence && !isOptions) { | |
// {a},b} | |
if (m.post.match(/,.*\}/)) { | |
str = m.pre + '{' + m.body + escClose + m.post; | |
return expand(str); | |
} | |
return [str]; | |
} | |
var n; | |
if (isSequence) { | |
n = m.body.split(/\.\./); | |
} else { | |
n = parseCommaParts(m.body); | |
if (n.length === 1) { | |
// x{{a,b}}y ==> x{a}y x{b}y | |
n = expand(n[0], false).map(embrace); | |
if (n.length === 1) { | |
var post = m.post.length | |
? expand(m.post, false) | |
: ['']; | |
return post.map(function(p) { | |
return m.pre + n[0] + p; | |
}); | |
} | |
} | |
} | |
// at this point, n is the parts, and we know it's not a comma set | |
// with a single entry. | |
// no need to expand pre, since it is guaranteed to be free of brace-sets | |
var pre = m.pre; | |
var post = m.post.length | |
? expand(m.post, false) | |
: ['']; | |
var N; | |
if (isSequence) { | |
var x = numeric(n[0]); | |
var y = numeric(n[1]); | |
var width = Math.max(n[0].length, n[1].length) | |
var incr = n.length == 3 | |
? Math.abs(numeric(n[2])) | |
: 1; | |
var test = lte; | |
var reverse = y < x; | |
if (reverse) { | |
incr *= -1; | |
test = gte; | |
} | |
var pad = n.some(isPadded); | |
N = []; | |
for (var i = x; test(i, y); i += incr) { | |
var c; | |
if (isAlphaSequence) { | |
c = String.fromCharCode(i); | |
if (c === '\\') | |
c = ''; | |
} else { | |
c = String(i); | |
if (pad) { | |
var need = width - c.length; | |
if (need > 0) { | |
var z = new Array(need + 1).join('0'); | |
if (i < 0) | |
c = '-' + z + c.slice(1); | |
else | |
c = z + c; | |
} | |
} | |
} | |
N.push(c); | |
} | |
} else { | |
N = concatMap(n, function(el) { return expand(el, false) }); | |
} | |
for (var j = 0; j < N.length; j++) { | |
for (var k = 0; k < post.length; k++) { | |
var expansion = pre + N[j] + post[k]; | |
if (!isTop || isSequence || expansion) | |
expansions.push(expansion); | |
} | |
} | |
return expansions; | |
} | |
/***/ }), | |
/***/ 1924: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
var GetIntrinsic = __webpack_require__(210); | |
var callBind = __webpack_require__(5559); | |
var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf')); | |
module.exports = function callBoundIntrinsic(name, allowMissing) { | |
var intrinsic = GetIntrinsic(name, !!allowMissing); | |
if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) { | |
return callBind(intrinsic); | |
} | |
return intrinsic; | |
}; | |
/***/ }), | |
/***/ 5559: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
var bind = __webpack_require__(8612); | |
var GetIntrinsic = __webpack_require__(210); | |
var $apply = GetIntrinsic('%Function.prototype.apply%'); | |
var $call = GetIntrinsic('%Function.prototype.call%'); | |
var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply); | |
var $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%', true); | |
var $defineProperty = GetIntrinsic('%Object.defineProperty%', true); | |
var $max = GetIntrinsic('%Math.max%'); | |
if ($defineProperty) { | |
try { | |
$defineProperty({}, 'a', { value: 1 }); | |
} catch (e) { | |
// IE 8 has a broken defineProperty | |
$defineProperty = null; | |
} | |
} | |
module.exports = function callBind(originalFunction) { | |
var func = $reflectApply(bind, $call, arguments); | |
if ($gOPD && $defineProperty) { | |
var desc = $gOPD(func, 'length'); | |
if (desc.configurable) { | |
// original length, plus the receiver, minus any additional arguments (after the receiver) | |
$defineProperty( | |
func, | |
'length', | |
{ value: 1 + $max(0, originalFunction.length - (arguments.length - 1)) } | |
); | |
} | |
} | |
return func; | |
}; | |
var applyBind = function applyBind() { | |
return $reflectApply(bind, $apply, arguments); | |
}; | |
if ($defineProperty) { | |
$defineProperty(module.exports, 'apply', { value: applyBind }); | |
} else { | |
module.exports.apply = applyBind; | |
} | |
/***/ }), | |
/***/ 1048: | |
/***/ (function(module) { | |
module.exports = function (xs, fn) { | |
var res = []; | |
for (var i = 0; i < xs.length; i++) { | |
var x = fn(xs[i], i); | |
if (isArray(x)) res.push.apply(res, x); | |
else res.push(x); | |
} | |
return res; | |
}; | |
var isArray = Array.isArray || function (xs) { | |
return Object.prototype.toString.call(xs) === '[object Array]'; | |
}; | |
/***/ }), | |
/***/ 5108: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
/*global window, global*/ | |
var util = __webpack_require__(9539) | |
var assert = __webpack_require__(9282) | |
function now() { return new Date().getTime() } | |
var slice = Array.prototype.slice | |
var console | |
var times = {} | |
if (typeof __webpack_require__.g !== "undefined" && __webpack_require__.g.console) { | |
console = __webpack_require__.g.console | |
} else if (typeof window !== "undefined" && window.console) { | |
console = window.console | |
} else { | |
console = {} | |
} | |
var functions = [ | |
[log, "log"], | |
[info, "info"], | |
[warn, "warn"], | |
[error, "error"], | |
[time, "time"], | |
[timeEnd, "timeEnd"], | |
[trace, "trace"], | |
[dir, "dir"], | |
[consoleAssert, "assert"] | |
] | |
for (var i = 0; i < functions.length; i++) { | |
var tuple = functions[i] | |
var f = tuple[0] | |
var name = tuple[1] | |
if (!console[name]) { | |
console[name] = f | |
} | |
} | |
module.exports = console | |
function log() {} | |
function info() { | |
console.log.apply(console, arguments) | |
} | |
function warn() { | |
console.log.apply(console, arguments) | |
} | |
function error() { | |
console.warn.apply(console, arguments) | |
} | |
function time(label) { | |
times[label] = now() | |
} | |
function timeEnd(label) { | |
var time = times[label] | |
if (!time) { | |
throw new Error("No such label: " + label) | |
} | |
delete times[label] | |
var duration = now() - time | |
console.log(label + ": " + duration + "ms") | |
} | |
function trace() { | |
var err = new Error() | |
err.name = "Trace" | |
err.message = util.format.apply(null, arguments) | |
console.error(err.stack) | |
} | |
function dir(object) { | |
console.log(util.inspect(object) + "\n") | |
} | |
function consoleAssert(expression) { | |
if (!expression) { | |
var arr = slice.call(arguments, 1) | |
assert.ok(false, util.format.apply(null, arr)) | |
} | |
} | |
/***/ }), | |
/***/ 1227: | |
/***/ (function(module, exports, __webpack_require__) { | |
/* provided dependency */ var console = __webpack_require__(5108); | |
/* provided dependency */ var process = __webpack_require__(4155); | |
/* eslint-env browser */ | |
/** | |
* This is the web browser implementation of `debug()`. | |
*/ | |
exports.formatArgs = formatArgs; | |
exports.save = save; | |
exports.load = load; | |
exports.useColors = useColors; | |
exports.storage = localstorage(); | |
exports.destroy = (() => { | |
let warned = false; | |
return () => { | |
if (!warned) { | |
warned = true; | |
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); | |
} | |
}; | |
})(); | |
/** | |
* Colors. | |
*/ | |
exports.colors = [ | |
'#0000CC', | |
'#0000FF', | |
'#0033CC', | |
'#0033FF', | |
'#0066CC', | |
'#0066FF', | |
'#0099CC', | |
'#0099FF', | |
'#00CC00', | |
'#00CC33', | |
'#00CC66', | |
'#00CC99', | |
'#00CCCC', | |
'#00CCFF', | |
'#3300CC', | |
'#3300FF', | |
'#3333CC', | |
'#3333FF', | |
'#3366CC', | |
'#3366FF', | |
'#3399CC', | |
'#3399FF', | |
'#33CC00', | |
'#33CC33', | |
'#33CC66', | |
'#33CC99', | |
'#33CCCC', | |
'#33CCFF', | |
'#6600CC', | |
'#6600FF', | |
'#6633CC', | |
'#6633FF', | |
'#66CC00', | |
'#66CC33', | |
'#9900CC', | |
'#9900FF', | |
'#9933CC', | |
'#9933FF', | |
'#99CC00', | |
'#99CC33', | |
'#CC0000', | |
'#CC0033', | |
'#CC0066', | |
'#CC0099', | |
'#CC00CC', | |
'#CC00FF', | |
'#CC3300', | |
'#CC3333', | |
'#CC3366', | |
'#CC3399', | |
'#CC33CC', | |
'#CC33FF', | |
'#CC6600', | |
'#CC6633', | |
'#CC9900', | |
'#CC9933', | |
'#CCCC00', | |
'#CCCC33', | |
'#FF0000', | |
'#FF0033', | |
'#FF0066', | |
'#FF0099', | |
'#FF00CC', | |
'#FF00FF', | |
'#FF3300', | |
'#FF3333', | |
'#FF3366', | |
'#FF3399', | |
'#FF33CC', | |
'#FF33FF', | |
'#FF6600', | |
'#FF6633', | |
'#FF9900', | |
'#FF9933', | |
'#FFCC00', | |
'#FFCC33' | |
]; | |
/** | |
* Currently only WebKit-based Web Inspectors, Firefox >= v31, | |
* and the Firebug extension (any Firefox version) are known | |
* to support "%c" CSS customizations. | |
* | |
* TODO: add a `localStorage` variable to explicitly enable/disable colors | |
*/ | |
// eslint-disable-next-line complexity | |
function useColors() { | |
// NB: In an Electron preload script, document will be defined but not fully | |
// initialized. Since we know we're in Chrome, we'll just detect this case | |
// explicitly | |
if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { | |
return true; | |
} | |
// Internet Explorer and Edge do not support colors. | |
if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { | |
return false; | |
} | |
// Is webkit? http://stackoverflow.com/a/16459606/376773 | |
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 | |
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || | |
// Is firebug? http://stackoverflow.com/a/398120/376773 | |
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || | |
// Is firefox >= v31? | |
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages | |
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || | |
// Double check webkit in userAgent just in case we are in a worker | |
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); | |
} | |
/** | |
* Colorize log arguments if enabled. | |
* | |
* @api public | |
*/ | |
function formatArgs(args) { | |
args[0] = (this.useColors ? '%c' : '') + | |
this.namespace + | |
(this.useColors ? ' %c' : ' ') + | |
args[0] + | |
(this.useColors ? '%c ' : ' ') + | |
'+' + module.exports.humanize(this.diff); | |
if (!this.useColors) { | |
return; | |
} | |
const c = 'color: ' + this.color; | |
args.splice(1, 0, c, 'color: inherit'); | |
// The final "%c" is somewhat tricky, because there could be other | |
// arguments passed either before or after the %c, so we need to | |
// figure out the correct index to insert the CSS into | |
let index = 0; | |
let lastC = 0; | |
args[0].replace(/%[a-zA-Z%]/g, match => { | |
if (match === '%%') { | |
return; | |
} | |
index++; | |
if (match === '%c') { | |
// We only are interested in the *last* %c | |
// (the user may have provided their own) | |
lastC = index; | |
} | |
}); | |
args.splice(lastC, 0, c); | |
} | |
/** | |
* Invokes `console.debug()` when available. | |
* No-op when `console.debug` is not a "function". | |
* If `console.debug` is not available, falls back | |
* to `console.log`. | |
* | |
* @api public | |
*/ | |
exports.log = console.debug || console.log || (() => {}); | |
/** | |
* Save `namespaces`. | |
* | |
* @param {String} namespaces | |
* @api private | |
*/ | |
function save(namespaces) { | |
try { | |
if (namespaces) { | |
exports.storage.setItem('debug', namespaces); | |
} else { | |
exports.storage.removeItem('debug'); | |
} | |
} catch (error) { | |
// Swallow | |
// XXX (@Qix-) should we be logging these? | |
} | |
} | |
/** | |
* Load `namespaces`. | |
* | |
* @return {String} returns the previously persisted debug modes | |
* @api private | |
*/ | |
function load() { | |
let r; | |
try { | |
r = exports.storage.getItem('debug'); | |
} catch (error) { | |
// Swallow | |
// XXX (@Qix-) should we be logging these? | |
} | |
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG | |
if (!r && typeof process !== 'undefined' && 'env' in process) { | |
r = process.env.DEBUG; | |
} | |
return r; | |
} | |
/** | |
* Localstorage attempts to return the localstorage. | |
* | |
* This is necessary because safari throws | |
* when a user disables cookies/localstorage | |
* and you attempt to access it. | |
* | |
* @return {LocalStorage} | |
* @api private | |
*/ | |
function localstorage() { | |
try { | |
// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context | |
// The Browser also has localStorage in the global context. | |
return localStorage; | |
} catch (error) { | |
// Swallow | |
// XXX (@Qix-) should we be logging these? | |
} | |
} | |
module.exports = __webpack_require__(2447)(exports); | |
const {formatters} = module.exports; | |
/** | |
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. | |
*/ | |
formatters.j = function (v) { | |
try { | |
return JSON.stringify(v); | |
} catch (error) { | |
return '[UnexpectedJSONParseError]: ' + error.message; | |
} | |
}; | |
/***/ }), | |
/***/ 2447: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
/* provided dependency */ var console = __webpack_require__(5108); | |
/** | |
* This is the common logic for both the Node.js and web browser | |
* implementations of `debug()`. | |
*/ | |
function setup(env) { | |
createDebug.debug = createDebug; | |
createDebug.default = createDebug; | |
createDebug.coerce = coerce; | |
createDebug.disable = disable; | |
createDebug.enable = enable; | |
createDebug.enabled = enabled; | |
createDebug.humanize = __webpack_require__(7824); | |
createDebug.destroy = destroy; | |
Object.keys(env).forEach(key => { | |
createDebug[key] = env[key]; | |
}); | |
/** | |
* The currently active debug mode names, and names to skip. | |
*/ | |
createDebug.names = []; | |
createDebug.skips = []; | |
/** | |
* Map of special "%n" handling functions, for the debug "format" argument. | |
* | |
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". | |
*/ | |
createDebug.formatters = {}; | |
/** | |
* Selects a color for a debug namespace | |
* @param {String} namespace The namespace string for the debug instance to be colored | |
* @return {Number|String} An ANSI color code for the given namespace | |
* @api private | |
*/ | |
function selectColor(namespace) { | |
let hash = 0; | |
for (let i = 0; i < namespace.length; i++) { | |
hash = ((hash << 5) - hash) + namespace.charCodeAt(i); | |
hash |= 0; // Convert to 32bit integer | |
} | |
return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; | |
} | |
createDebug.selectColor = selectColor; | |
/** | |
* Create a debugger with the given `namespace`. | |
* | |
* @param {String} namespace | |
* @return {Function} | |
* @api public | |
*/ | |
function createDebug(namespace) { | |
let prevTime; | |
let enableOverride = null; | |
let namespacesCache; | |
let enabledCache; | |
function debug(...args) { | |
// Disabled? | |
if (!debug.enabled) { | |
return; | |
} | |
const self = debug; | |
// Set `diff` timestamp | |
const curr = Number(new Date()); | |
const ms = curr - (prevTime || curr); | |
self.diff = ms; | |
self.prev = prevTime; | |
self.curr = curr; | |
prevTime = curr; | |
args[0] = createDebug.coerce(args[0]); | |
if (typeof args[0] !== 'string') { | |
// Anything else let's inspect with %O | |
args.unshift('%O'); | |
} | |
// Apply any `formatters` transformations | |
let index = 0; | |
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { | |
// If we encounter an escaped % then don't increase the array index | |
if (match === '%%') { | |
return '%'; | |
} | |
index++; | |
const formatter = createDebug.formatters[format]; | |
if (typeof formatter === 'function') { | |
const val = args[index]; | |
match = formatter.call(self, val); | |
// Now we need to remove `args[index]` since it's inlined in the `format` | |
args.splice(index, 1); | |
index--; | |
} | |
return match; | |
}); | |
// Apply env-specific formatting (colors, etc.) | |
createDebug.formatArgs.call(self, args); | |
const logFn = self.log || createDebug.log; | |
logFn.apply(self, args); | |
} | |
debug.namespace = namespace; | |
debug.useColors = createDebug.useColors(); | |
debug.color = createDebug.selectColor(namespace); | |
debug.extend = extend; | |
debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release. | |
Object.defineProperty(debug, 'enabled', { | |
enumerable: true, | |
configurable: false, | |
get: () => { | |
if (enableOverride !== null) { | |
return enableOverride; | |
} | |
if (namespacesCache !== createDebug.namespaces) { | |
namespacesCache = createDebug.namespaces; | |
enabledCache = createDebug.enabled(namespace); | |
} | |
return enabledCache; | |
}, | |
set: v => { | |
enableOverride = v; | |
} | |
}); | |
// Env-specific initialization logic for debug instances | |
if (typeof createDebug.init === 'function') { | |
createDebug.init(debug); | |
} | |
return debug; | |
} | |
function extend(namespace, delimiter) { | |
const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); | |
newDebug.log = this.log; | |
return newDebug; | |
} | |
/** | |
* Enables a debug mode by namespaces. This can include modes | |
* separated by a colon and wildcards. | |
* | |
* @param {String} namespaces | |
* @api public | |
*/ | |
function enable(namespaces) { | |
createDebug.save(namespaces); | |
createDebug.namespaces = namespaces; | |
createDebug.names = []; | |
createDebug.skips = []; | |
let i; | |
const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); | |
const len = split.length; | |
for (i = 0; i < len; i++) { | |
if (!split[i]) { | |
// ignore empty strings | |
continue; | |
} | |
namespaces = split[i].replace(/\*/g, '.*?'); | |
if (namespaces[0] === '-') { | |
createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); | |
} else { | |
createDebug.names.push(new RegExp('^' + namespaces + '$')); | |
} | |
} | |
} | |
/** | |
* Disable debug output. | |
* | |
* @return {String} namespaces | |
* @api public | |
*/ | |
function disable() { | |
const namespaces = [ | |
...createDebug.names.map(toNamespace), | |
...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace) | |
].join(','); | |
createDebug.enable(''); | |
return namespaces; | |
} | |
/** | |
* Returns true if the given mode name is enabled, false otherwise. | |
* | |
* @param {String} name | |
* @return {Boolean} | |
* @api public | |
*/ | |
function enabled(name) { | |
if (name[name.length - 1] === '*') { | |
return true; | |
} | |
let i; | |
let len; | |
for (i = 0, len = createDebug.skips.length; i < len; i++) { | |
if (createDebug.skips[i].test(name)) { | |
return false; | |
} | |
} | |
for (i = 0, len = createDebug.names.length; i < len; i++) { | |
if (createDebug.names[i].test(name)) { | |
return true; | |
} | |
} | |
return false; | |
} | |
/** | |
* Convert regexp to namespace | |
* | |
* @param {RegExp} regxep | |
* @return {String} namespace | |
* @api private | |
*/ | |
function toNamespace(regexp) { | |
return regexp.toString() | |
.substring(2, regexp.toString().length - 2) | |
.replace(/\.\*\?$/, '*'); | |
} | |
/** | |
* Coerce `val`. | |
* | |
* @param {Mixed} val | |
* @return {Mixed} | |
* @api private | |
*/ | |
function coerce(val) { | |
if (val instanceof Error) { | |
return val.stack || val.message; | |
} | |
return val; | |
} | |
/** | |
* XXX DO NOT USE. This is a temporary stub function. | |
* XXX It WILL be removed in the next major release. | |
*/ | |
function destroy() { | |
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); | |
} | |
createDebug.enable(createDebug.load()); | |
return createDebug; | |
} | |
module.exports = setup; | |
/***/ }), | |
/***/ 4289: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
var keys = __webpack_require__(2215); | |
var hasSymbols = typeof Symbol === 'function' && typeof Symbol('foo') === 'symbol'; | |
var toStr = Object.prototype.toString; | |
var concat = Array.prototype.concat; | |
var origDefineProperty = Object.defineProperty; | |
var isFunction = function (fn) { | |
return typeof fn === 'function' && toStr.call(fn) === '[object Function]'; | |
}; | |
var arePropertyDescriptorsSupported = function () { | |
var obj = {}; | |
try { | |
origDefineProperty(obj, 'x', { enumerable: false, value: obj }); | |
// eslint-disable-next-line no-unused-vars, no-restricted-syntax | |
for (var _ in obj) { // jscs:ignore disallowUnusedVariables | |
return false; | |
} | |
return obj.x === obj; | |
} catch (e) { /* this is IE 8. */ | |
return false; | |
} | |
}; | |
var supportsDescriptors = origDefineProperty && arePropertyDescriptorsSupported(); | |
var defineProperty = function (object, name, value, predicate) { | |
if (name in object && (!isFunction(predicate) || !predicate())) { | |
return; | |
} | |
if (supportsDescriptors) { | |
origDefineProperty(object, name, { | |
configurable: true, | |
enumerable: false, | |
value: value, | |
writable: true | |
}); | |
} else { | |
object[name] = value; | |
} | |
}; | |
var defineProperties = function (object, map) { | |
var predicates = arguments.length > 2 ? arguments[2] : {}; | |
var props = keys(map); | |
if (hasSymbols) { | |
props = concat.call(props, Object.getOwnPropertySymbols(map)); | |
} | |
for (var i = 0; i < props.length; i += 1) { | |
defineProperty(object, props[i], map[props[i]], predicates[props[i]]); | |
} | |
}; | |
defineProperties.supportsDescriptors = !!supportsDescriptors; | |
module.exports = defineProperties; | |
/***/ }), | |
/***/ 5291: | |
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { | |
/* | |
* @fileoverview Main Doctrine object | |
* @author Yusuke Suzuki <[email protected]> | |
* @author Dan Tao <[email protected]> | |
* @author Andrew Eisenberg <[email protected]> | |
*/ | |
(function () { | |
'use strict'; | |
var typed, | |
utility, | |
jsdoc, | |
esutils, | |
hasOwnProperty; | |
esutils = __webpack_require__(649); | |
typed = __webpack_require__(2518); | |
utility = __webpack_require__(1408); | |
function sliceSource(source, index, last) { | |
return source.slice(index, last); | |
} | |
hasOwnProperty = (function () { | |
var func = Object.prototype.hasOwnProperty; | |
return function hasOwnProperty(obj, name) { | |
return func.call(obj, name); | |
}; | |
}()); | |
function shallowCopy(obj) { | |
var ret = {}, key; | |
for (key in obj) { | |
if (obj.hasOwnProperty(key)) { | |
ret[key] = obj[key]; | |
} | |
} | |
return ret; | |
} | |
function isASCIIAlphanumeric(ch) { | |
return (ch >= 0x61 /* 'a' */ && ch <= 0x7A /* 'z' */) || | |
(ch >= 0x41 /* 'A' */ && ch <= 0x5A /* 'Z' */) || | |
(ch >= 0x30 /* '0' */ && ch <= 0x39 /* '9' */); | |
} | |
function isParamTitle(title) { | |
return title === 'param' || title === 'argument' || title === 'arg'; | |
} | |
function isReturnTitle(title) { | |
return title === 'return' || title === 'returns'; | |
} | |
function isProperty(title) { | |
return title === 'property' || title === 'prop'; | |
} | |
function isNameParameterRequired(title) { | |
return isParamTitle(title) || isProperty(title) || | |
title === 'alias' || title === 'this' || title === 'mixes' || title === 'requires'; | |
} | |
function isAllowedName(title) { | |
return isNameParameterRequired(title) || title === 'const' || title === 'constant'; | |
} | |
function isAllowedNested(title) { | |
return isProperty(title) || isParamTitle(title); | |
} | |
function isAllowedOptional(title) { | |
return isProperty(title) || isParamTitle(title); | |
} | |
function isTypeParameterRequired(title) { | |
return isParamTitle(title) || isReturnTitle(title) || | |
title === 'define' || title === 'enum' || | |
title === 'implements' || title === 'this' || | |
title === 'type' || title === 'typedef' || isProperty(title); | |
} | |
// Consider deprecation instead using 'isTypeParameterRequired' and 'Rules' declaration to pick when a type is optional/required | |
// This would require changes to 'parseType' | |
function isAllowedType(title) { | |
return isTypeParameterRequired(title) || title === 'throws' || title === 'const' || title === 'constant' || | |
title === 'namespace' || title === 'member' || title === 'var' || title === 'module' || | |
title === 'constructor' || title === 'class' || title === 'extends' || title === 'augments' || | |
title === 'public' || title === 'private' || title === 'protected'; | |
} | |
// A regex character class that contains all whitespace except linebreak characters (\r, \n, \u2028, \u2029) | |
var WHITESPACE = '[ \\f\\t\\v\\u00a0\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000\\ufeff]'; | |
var STAR_MATCHER = '(' + WHITESPACE + '*(?:\\*' + WHITESPACE + '?)?)(.+|[\r\n\u2028\u2029])'; | |
function unwrapComment(doc) { | |
// JSDoc comment is following form | |
// /** | |
// * ....... | |
// */ | |
return doc. | |
// remove /** | |
replace(/^\/\*\*?/, ''). | |
// remove */ | |
replace(/\*\/$/, ''). | |
// remove ' * ' at the beginning of a line | |
replace(new RegExp(STAR_MATCHER, 'g'), '$2'). | |
// remove trailing whitespace | |
replace(/\s*$/, ''); | |
} | |
/** | |
* Converts an index in an "unwrapped" JSDoc comment to the corresponding index in the original "wrapped" version | |
* @param {string} originalSource The original wrapped comment | |
* @param {number} unwrappedIndex The index of a character in the unwrapped string | |
* @returns {number} The index of the corresponding character in the original wrapped string | |
*/ | |
function convertUnwrappedCommentIndex(originalSource, unwrappedIndex) { | |
var replacedSource = originalSource.replace(/^\/\*\*?/, ''); | |
var numSkippedChars = 0; | |
var matcher = new RegExp(STAR_MATCHER, 'g'); | |
var match; | |
while ((match = matcher.exec(replacedSource))) { | |
numSkippedChars += match[1].length; | |
if (match.index + match[0].length > unwrappedIndex + numSkippedChars) { | |
return unwrappedIndex + numSkippedChars + originalSource.length - replacedSource.length; | |
} | |
} | |
return originalSource.replace(/\*\/$/, '').replace(/\s*$/, '').length; | |
} | |
// JSDoc Tag Parser | |
(function (exports) { | |
var Rules, | |
index, | |
lineNumber, | |
length, | |
source, | |
originalSource, | |
recoverable, | |
sloppy, | |
strict; | |
function advance() { | |
var ch = source.charCodeAt(index); | |
index += 1; | |
if (esutils.code.isLineTerminator(ch) && !(ch === 0x0D /* '\r' */ && source.charCodeAt(index) === 0x0A /* '\n' */)) { | |
lineNumber += 1; | |
} | |
return String.fromCharCode(ch); | |
} | |
function scanTitle() { | |
var title = ''; | |
// waste '@' | |
advance(); | |
while (index < length && isASCIIAlphanumeric(source.charCodeAt(index))) { | |
title += advance(); | |
} | |
return title; | |
} | |
function seekContent() { | |
var ch, waiting, last = index; | |
waiting = false; | |
while (last < length) { | |
ch = source.charCodeAt(last); | |
if (esutils.code.isLineTerminator(ch) && !(ch === 0x0D /* '\r' */ && source.charCodeAt(last + 1) === 0x0A /* '\n' */)) { | |
waiting = true; | |
} else if (waiting) { | |
if (ch === 0x40 /* '@' */) { | |
break; | |
} | |
if (!esutils.code.isWhiteSpace(ch)) { | |
waiting = false; | |
} | |
} | |
last += 1; | |
} | |
return last; | |
} | |
// type expression may have nest brace, such as, | |
// { { ok: string } } | |
// | |
// therefore, scanning type expression with balancing braces. | |
function parseType(title, last, addRange) { | |
var ch, brace, type, startIndex, direct = false; | |
// search '{' | |
while (index < last) { | |
ch = source.charCodeAt(index); | |
if (esutils.code.isWhiteSpace(ch)) { | |
advance(); | |
} else if (ch === 0x7B /* '{' */) { | |
advance(); | |
break; | |
} else { | |
// this is direct pattern | |
direct = true; | |
break; | |
} | |
} | |
if (direct) { | |
return null; | |
} | |
// type expression { is found | |
brace = 1; | |
type = ''; | |
while (index < last) { | |
ch = source.charCodeAt(index); | |
if (esutils.code.isLineTerminator(ch)) { | |
advance(); | |
} else { | |
if (ch === 0x7D /* '}' */) { | |
brace -= 1; | |
if (brace === 0) { | |
advance(); | |
break; | |
} | |
} else if (ch === 0x7B /* '{' */) { | |
brace += 1; | |
} | |
if (type === '') { | |
startIndex = index; | |
} | |
type += advance(); | |
} | |
} | |
if (brace !== 0) { | |
// braces is not balanced | |
return utility.throwError('Braces are not balanced'); | |
} | |
if (isAllowedOptional(title)) { | |
return typed.parseParamType(type, {startIndex: convertIndex(startIndex), range: addRange}); | |
} | |
return typed.parseType(type, {startIndex: convertIndex(startIndex), range: addRange}); | |
} | |
function scanIdentifier(last) { | |
var identifier; | |
if (!esutils.code.isIdentifierStartES5(source.charCodeAt(index)) && !source[index].match(/[0-9]/)) { | |
return null; | |
} | |
identifier = advance(); | |
while (index < last && esutils.code.isIdentifierPartES5(source.charCodeAt(index))) { | |
identifier += advance(); | |
} | |
return identifier; | |
} | |
function skipWhiteSpace(last) { | |
while (index < last && (esutils.code.isWhiteSpace(source.charCodeAt(index)) || esutils.code.isLineTerminator(source.charCodeAt(index)))) { | |
advance(); | |
} | |
} | |
function parseName(last, allowBrackets, allowNestedParams) { | |
var name = '', | |
useBrackets, | |
insideString; | |
skipWhiteSpace(last); | |
if (index >= last) { | |
return null; | |
} | |
if (source.charCodeAt(index) === 0x5B /* '[' */) { | |
if (allowBrackets) { | |
useBrackets = true; | |
name = advance(); | |
} else { | |
return null; | |
} | |
} | |
name += scanIdentifier(last); | |
if (allowNestedParams) { | |
if (source.charCodeAt(index) === 0x3A /* ':' */ && ( | |
name === 'module' || | |
name === 'external' || | |
name === 'event')) { | |
name += advance(); | |
name += scanIdentifier(last); | |
} | |
if(source.charCodeAt(index) === 0x5B /* '[' */ && source.charCodeAt(index + 1) === 0x5D /* ']' */){ | |
name += advance(); | |
name += advance(); | |
} | |
while (source.charCodeAt(index) === 0x2E /* '.' */ || | |
source.charCodeAt(index) === 0x2F /* '/' */ || | |
source.charCodeAt(index) === 0x23 /* '#' */ || | |
source.charCodeAt(index) === 0x2D /* '-' */ || | |
source.charCodeAt(index) === 0x7E /* '~' */) { | |
name += advance(); | |
name += scanIdentifier(last); | |
} | |
} | |
if (useBrackets) { | |
skipWhiteSpace(last); | |
// do we have a default value for this? | |
if (source.charCodeAt(index) === 0x3D /* '=' */) { | |
// consume the '='' symbol | |
name += advance(); | |
skipWhiteSpace(last); | |
var ch; | |
var bracketDepth = 1; | |
// scan in the default value | |
while (index < last) { | |
ch = source.charCodeAt(index); | |
if (esutils.code.isWhiteSpace(ch)) { | |
if (!insideString) { | |
skipWhiteSpace(last); | |
ch = source.charCodeAt(index); | |
} | |
} | |
if (ch === 0x27 /* ''' */) { | |
if (!insideString) { | |
insideString = '\''; | |
} else { | |
if (insideString === '\'') { | |
insideString = ''; | |
} | |
} | |
} | |
if (ch === 0x22 /* '"' */) { | |
if (!insideString) { | |
insideString = '"'; | |
} else { | |
if (insideString === '"') { | |
insideString = ''; | |
} | |
} | |
} | |
if (ch === 0x5B /* '[' */) { | |
bracketDepth++; | |
} else if (ch === 0x5D /* ']' */ && | |
--bracketDepth === 0) { | |
break; | |
} | |
name += advance(); | |
} | |
} | |
skipWhiteSpace(last); | |
if (index >= last || source.charCodeAt(index) !== 0x5D /* ']' */) { | |
// we never found a closing ']' | |
return null; | |
} | |
// collect the last ']' | |
name += advance(); | |
} | |
return name; | |
} | |
function skipToTag() { | |
while (index < length && source.charCodeAt(index) !== 0x40 /* '@' */) { | |
advance(); | |
} | |
if (index >= length) { | |
return false; | |
} | |
utility.assert(source.charCodeAt(index) === 0x40 /* '@' */); | |
return true; | |
} | |
function convertIndex(rangeIndex) { | |
if (source === originalSource) { | |
return rangeIndex; | |
} | |
return convertUnwrappedCommentIndex(originalSource, rangeIndex); | |
} | |
function TagParser(options, title) { | |
this._options = options; | |
this._title = title.toLowerCase(); | |
this._tag = { | |
title: title, | |
description: null | |
}; | |
if (this._options.lineNumbers) { | |
this._tag.lineNumber = lineNumber; | |
} | |
this._first = index - title.length - 1; | |
this._last = 0; | |
// space to save special information for title parsers. | |
this._extra = { }; | |
} | |
// addError(err, ...) | |
TagParser.prototype.addError = function addError(errorText) { | |
var args = Array.prototype.slice.call(arguments, 1), | |
msg = errorText.replace( | |
/%(\d)/g, | |
function (whole, index) { | |
utility.assert(index < args.length, 'Message reference must be in range'); | |
return args[index]; | |
} | |
); | |
if (!this._tag.errors) { | |
this._tag.errors = []; | |
} | |
if (strict) { | |
utility.throwError(msg); | |
} | |
this._tag.errors.push(msg); | |
return recoverable; | |
}; | |
TagParser.prototype.parseType = function () { | |
// type required titles | |
if (isTypeParameterRequired(this._title)) { | |
try { | |
this._tag.type = parseType(this._title, this._last, this._options.range); | |
if (!this._tag.type) { | |
if (!isParamTitle(this._title) && !isReturnTitle(this._title)) { | |
if (!this.addError('Missing or invalid tag type')) { | |
return false; | |
} | |
} | |
} | |
} catch (error) { | |
this._tag.type = null; | |
if (!this.addError(error.message)) { | |
return false; | |
} | |
} | |
} else if (isAllowedType(this._title)) { | |
// optional types | |
try { | |
this._tag.type = parseType(this._title, this._last, this._options.range); | |
} catch (e) { | |
//For optional types, lets drop the thrown error when we hit the end of the file | |
} | |
} | |
return true; | |
}; | |
TagParser.prototype._parseNamePath = function (optional) { | |
var name; | |
name = parseName(this._last, sloppy && isAllowedOptional(this._title), true); | |
if (!name) { | |
if (!optional) { | |
if (!this.addError('Missing or invalid tag name')) { | |
return false; | |
} | |
} | |
} | |
this._tag.name = name; | |
return true; | |
}; | |
TagParser.prototype.parseNamePath = function () { | |
return this._parseNamePath(false); | |
}; | |
TagParser.prototype.parseNamePathOptional = function () { | |
return this._parseNamePath(true); | |
}; | |
TagParser.prototype.parseName = function () { | |
var assign, name; | |
// param, property requires name | |
if (isAllowedName(this._title)) { | |
this._tag.name = parseName(this._last, sloppy && isAllowedOptional(this._title), isAllowedNested(this._title)); | |
if (!this._tag.name) { | |
if (!isNameParameterRequired(this._title)) { | |
return true; | |
} | |
// it's possible the name has already been parsed but interpreted as a type | |
// it's also possible this is a sloppy declaration, in which case it will be | |
// fixed at the end | |
if (isParamTitle(this._title) && this._tag.type && this._tag.type.name) { | |
this._extra.name = this._tag.type; | |
this._tag.name = this._tag.type.name; | |
this._tag.type = null; | |
} else { | |
if (!this.addError('Missing or invalid tag name')) { | |
return false; | |
} | |
} | |
} else { | |
name = this._tag.name; | |
if (name.charAt(0) === '[' && name.charAt(name.length - 1) === ']') { | |
// extract the default value if there is one | |
// example: @param {string} [somebody=John Doe] description | |
assign = name.substring(1, name.length - 1).split('='); | |
if (assign.length > 1) { | |
this._tag['default'] = assign.slice(1).join('='); | |
} | |
this._tag.name = assign[0]; | |
// convert to an optional type | |
if (this._tag.type && this._tag.type.type !== 'OptionalType') { | |
this._tag.type = { | |
type: 'OptionalType', | |
expression: this._tag.type | |
}; | |
} | |
} | |
} | |
} | |
return true; | |
}; | |
TagParser.prototype.parseDescription = function parseDescription() { | |
var description = sliceSource(source, index, this._last).trim(); | |
if (description) { | |
if ((/^-\s+/).test(description)) { | |
description = description.substring(2); | |
} | |
this._tag.description = description; | |
} | |
return true; | |
}; | |
TagParser.prototype.parseCaption = function parseDescription() { | |
var description = sliceSource(source, index, this._last).trim(); | |
var captionStartTag = '<caption>'; | |
var captionEndTag = '</caption>'; | |
var captionStart = description.indexOf(captionStartTag); | |
var captionEnd = description.indexOf(captionEndTag); | |
if (captionStart >= 0 && captionEnd >= 0) { | |
this._tag.caption = description.substring( | |
captionStart + captionStartTag.length, captionEnd).trim(); | |
this._tag.description = description.substring(captionEnd + captionEndTag.length).trim(); | |
} else { | |
this._tag.description = description; | |
} | |
return true; | |
}; | |
TagParser.prototype.parseKind = function parseKind() { | |
var kind, kinds; | |
kinds = { | |
'class': true, | |
'constant': true, | |
'event': true, | |
'external': true, | |
'file': true, | |
'function': true, | |
'member': true, | |
'mixin': true, | |
'module': true, | |
'namespace': true, | |
'typedef': true | |
}; | |
kind = sliceSource(source, index, this._last).trim(); | |
this._tag.kind = kind; | |
if (!hasOwnProperty(kinds, kind)) { | |
if (!this.addError('Invalid kind name \'%0\'', kind)) { | |
return false; | |
} | |
} | |
return true; | |
}; | |
TagParser.prototype.parseAccess = function parseAccess() { | |
var access; | |
access = sliceSource(source, index, this._last).trim(); | |
this._tag.access = access; | |
if (access !== 'private' && access !== 'protected' && access !== 'public') { | |
if (!this.addError('Invalid access name \'%0\'', access)) { | |
return false; | |
} | |
} | |
return true; | |
}; | |
TagParser.prototype.parseThis = function parseThis() { | |
// this name may be a name expression (e.g. {foo.bar}), | |
// an union (e.g. {foo.bar|foo.baz}) or a name path (e.g. foo.bar) | |
var value = sliceSource(source, index, this._last).trim(); | |
if (value && value.charAt(0) === '{') { | |
var gotType = this.parseType(); | |
if (gotType && this._tag.type.type === 'NameExpression' || this._tag.type.type === 'UnionType') { | |
this._tag.name = this._tag.type.name; | |
return true; | |
} else { | |
return this.addError('Invalid name for this'); | |
} | |
} else { | |
return this.parseNamePath(); | |
} | |
}; | |
TagParser.prototype.parseVariation = function parseVariation() { | |
var variation, text; | |
text = sliceSource(source, index, this._last).trim(); | |
variation = parseFloat(text, 10); | |
this._tag.variation = variation; | |
if (isNaN(variation)) { | |
if (!this.addError('Invalid variation \'%0\'', text)) { | |
return false; | |
} | |
} | |
return true; | |
}; | |
TagParser.prototype.ensureEnd = function () { | |
var shouldBeEmpty = sliceSource(source, index, this._last).trim(); | |
if (shouldBeEmpty) { | |
if (!this.addError('Unknown content \'%0\'', shouldBeEmpty)) { | |
return false; | |
} | |
} | |
return true; | |
}; | |
TagParser.prototype.epilogue = function epilogue() { | |
var description; | |
description = this._tag.description; | |
// un-fix potentially sloppy declaration | |
if (isAllowedOptional(this._title) && !this._tag.type && description && description.charAt(0) === '[') { | |
this._tag.type = this._extra.name; | |
if (!this._tag.name) { | |
this._tag.name = undefined; | |
} | |
if (!sloppy) { | |
if (!this.addError('Missing or invalid tag name')) { | |
return false; | |
} | |
} | |
} | |
return true; | |
}; | |
Rules = { | |
// http://usejsdoc.org/tags-access.html | |
'access': ['parseAccess'], | |
// http://usejsdoc.org/tags-alias.html | |
'alias': ['parseNamePath', 'ensureEnd'], | |
// http://usejsdoc.org/tags-augments.html | |
'augments': ['parseType', 'parseNamePathOptional', 'ensureEnd'], | |
// http://usejsdoc.org/tags-constructor.html | |
'constructor': ['parseType', 'parseNamePathOptional', 'ensureEnd'], | |
// Synonym: http://usejsdoc.org/tags-constructor.html | |
'class': ['parseType', 'parseNamePathOptional', 'ensureEnd'], | |
// Synonym: http://usejsdoc.org/tags-extends.html | |
'extends': ['parseType', 'parseNamePathOptional', 'ensureEnd'], | |
// http://usejsdoc.org/tags-example.html | |
'example': ['parseCaption'], | |
// http://usejsdoc.org/tags-deprecated.html | |
'deprecated': ['parseDescription'], | |
// http://usejsdoc.org/tags-global.html | |
'global': ['ensureEnd'], | |
// http://usejsdoc.org/tags-inner.html | |
'inner': ['ensureEnd'], | |
// http://usejsdoc.org/tags-instance.html | |
'instance': ['ensureEnd'], | |
// http://usejsdoc.org/tags-kind.html | |
'kind': ['parseKind'], | |
// http://usejsdoc.org/tags-mixes.html | |
'mixes': ['parseNamePath', 'ensureEnd'], | |
// http://usejsdoc.org/tags-mixin.html | |
'mixin': ['parseNamePathOptional', 'ensureEnd'], | |
// http://usejsdoc.org/tags-member.html | |
'member': ['parseType', 'parseNamePathOptional', 'ensureEnd'], | |
// http://usejsdoc.org/tags-method.html | |
'method': ['parseNamePathOptional', 'ensureEnd'], | |
// http://usejsdoc.org/tags-module.html | |
'module': ['parseType', 'parseNamePathOptional', 'ensureEnd'], | |
// Synonym: http://usejsdoc.org/tags-method.html | |
'func': ['parseNamePathOptional', 'ensureEnd'], | |
// Synonym: http://usejsdoc.org/tags-method.html | |
'function': ['parseNamePathOptional', 'ensureEnd'], | |
// Synonym: http://usejsdoc.org/tags-member.html | |
'var': ['parseType', 'parseNamePathOptional', 'ensureEnd'], | |
// http://usejsdoc.org/tags-name.html | |
'name': ['parseNamePath', 'ensureEnd'], | |
// http://usejsdoc.org/tags-namespace.html | |
'namespace': ['parseType', 'parseNamePathOptional', 'ensureEnd'], | |
// http://usejsdoc.org/tags-private.html | |
'private': ['parseType', 'parseDescription'], | |
// http://usejsdoc.org/tags-protected.html | |
'protected': ['parseType', 'parseDescription'], | |
// http://usejsdoc.org/tags-public.html | |
'public': ['parseType', 'parseDescription'], | |
// http://usejsdoc.org/tags-readonly.html | |
'readonly': ['ensureEnd'], | |
// http://usejsdoc.org/tags-requires.html | |
'requires': ['parseNamePath', 'ensureEnd'], | |
// http://usejsdoc.org/tags-since.html | |
'since': ['parseDescription'], | |
// http://usejsdoc.org/tags-static.html | |
'static': ['ensureEnd'], | |
// http://usejsdoc.org/tags-summary.html | |
'summary': ['parseDescription'], | |
// http://usejsdoc.org/tags-this.html | |
'this': ['parseThis', 'ensureEnd'], | |
// http://usejsdoc.org/tags-todo.html | |
'todo': ['parseDescription'], | |
// http://usejsdoc.org/tags-typedef.html | |
'typedef': ['parseType', 'parseNamePathOptional'], | |
// http://usejsdoc.org/tags-variation.html | |
'variation': ['parseVariation'], | |
// http://usejsdoc.org/tags-version.html | |
'version': ['parseDescription'] | |
}; | |
TagParser.prototype.parse = function parse() { | |
var i, iz, sequences, method; | |
// empty title | |
if (!this._title) { | |
if (!this.addError('Missing or invalid title')) { | |
return null; | |
} | |
} | |
// Seek to content last index. | |
this._last = seekContent(this._title); | |
if (this._options.range) { | |
this._tag.range = [this._first, source.slice(0, this._last).replace(/\s*$/, '').length].map(convertIndex); | |
} | |
if (hasOwnProperty(Rules, this._title)) { | |
sequences = Rules[this._title]; | |
} else { | |
// default sequences | |
sequences = ['parseType', 'parseName', 'parseDescription', 'epilogue']; | |
} | |
for (i = 0, iz = sequences.length; i < iz; ++i) { | |
method = sequences[i]; | |
if (!this[method]()) { | |
return null; | |
} | |
} | |
return this._tag; | |
}; | |
function parseTag(options) { | |
var title, parser, tag; | |
// skip to tag | |
if (!skipToTag()) { | |
return null; | |
} | |
// scan title | |
title = scanTitle(); | |
// construct tag parser | |
parser = new TagParser(options, title); | |
tag = parser.parse(); | |
// Seek global index to end of this tag. | |
while (index < parser._last) { | |
advance(); | |
} | |
return tag; | |
} | |
// | |
// Parse JSDoc | |
// | |
function scanJSDocDescription(preserveWhitespace) { | |
var description = '', ch, atAllowed; | |
atAllowed = true; | |
while (index < length) { | |
ch = source.charCodeAt(index); | |
if (atAllowed && ch === 0x40 /* '@' */) { | |
break; | |
} | |
if (esutils.code.isLineTerminator(ch)) { | |
atAllowed = true; | |
} else if (atAllowed && !esutils.code.isWhiteSpace(ch)) { | |
atAllowed = false; | |
} | |
description += advance(); | |
} | |
return preserveWhitespace ? description : description.trim(); | |
} | |
function parse(comment, options) { | |
var tags = [], tag, description, interestingTags, i, iz; | |
if (options === undefined) { | |
options = {}; | |
} | |
if (typeof options.unwrap === 'boolean' && options.unwrap) { | |
source = unwrapComment(comment); | |
} else { | |
source = comment; | |
} | |
originalSource = comment; | |
// array of relevant tags | |
if (options.tags) { | |
if (Array.isArray(options.tags)) { | |
interestingTags = { }; | |
for (i = 0, iz = options.tags.length; i < iz; i++) { | |
if (typeof options.tags[i] === 'string') { | |
interestingTags[options.tags[i]] = true; | |
} else { | |
utility.throwError('Invalid "tags" parameter: ' + options.tags); | |
} | |
} | |
} else { | |
utility.throwError('Invalid "tags" parameter: ' + options.tags); | |
} | |
} | |
length = source.length; | |
index = 0; | |
lineNumber = 0; | |
recoverable = options.recoverable; | |
sloppy = options.sloppy; | |
strict = options.strict; | |
description = scanJSDocDescription(options.preserveWhitespace); | |
while (true) { | |
tag = parseTag(options); | |
if (!tag) { | |
break; | |
} | |
if (!interestingTags || interestingTags.hasOwnProperty(tag.title)) { | |
tags.push(tag); | |
} | |
} | |
return { | |
description: description, | |
tags: tags | |
}; | |
} | |
exports.parse = parse; | |
}(jsdoc = {})); | |
exports.version = utility.VERSION; | |
exports.parse = jsdoc.parse; | |
exports.parseType = typed.parseType; | |
exports.parseParamType = typed.parseParamType; | |
exports.unwrapComment = unwrapComment; | |
exports.Syntax = shallowCopy(typed.Syntax); | |
exports.Error = utility.DoctrineError; | |
exports.type = { | |
Syntax: exports.Syntax, | |
parseType: typed.parseType, | |
parseParamType: typed.parseParamType, | |
stringify: typed.stringify | |
}; | |
}()); | |
/* vim: set sw=4 ts=4 et tw=80 : */ | |
/***/ }), | |
/***/ 2518: | |
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { | |
/* | |
* @fileoverview Type expression parser. | |
* @author Yusuke Suzuki <[email protected]> | |
* @author Dan Tao <[email protected]> | |
* @author Andrew Eisenberg <[email protected]> | |
*/ | |
// "typed", the Type Expression Parser for doctrine. | |
(function () { | |
'use strict'; | |
var Syntax, | |
Token, | |
source, | |
length, | |
index, | |
previous, | |
token, | |
value, | |
esutils, | |
utility, | |
rangeOffset, | |
addRange; | |
esutils = __webpack_require__(649); | |
utility = __webpack_require__(1408); | |
Syntax = { | |
NullableLiteral: 'NullableLiteral', | |
AllLiteral: 'AllLiteral', | |
NullLiteral: 'NullLiteral', | |
UndefinedLiteral: 'UndefinedLiteral', | |
VoidLiteral: 'VoidLiteral', | |
UnionType: 'UnionType', | |
ArrayType: 'ArrayType', | |
RecordType: 'RecordType', | |
FieldType: 'FieldType', | |
FunctionType: 'FunctionType', | |
ParameterType: 'ParameterType', | |
RestType: 'RestType', | |
NonNullableType: 'NonNullableType', | |
OptionalType: 'OptionalType', | |
NullableType: 'NullableType', | |
NameExpression: 'NameExpression', | |
TypeApplication: 'TypeApplication', | |
StringLiteralType: 'StringLiteralType', | |
NumericLiteralType: 'NumericLiteralType', | |
BooleanLiteralType: 'BooleanLiteralType' | |
}; | |
Token = { | |
ILLEGAL: 0, // ILLEGAL | |
DOT_LT: 1, // .< | |
REST: 2, // ... | |
LT: 3, // < | |
GT: 4, // > | |
LPAREN: 5, // ( | |
RPAREN: 6, // ) | |
LBRACE: 7, // { | |
RBRACE: 8, // } | |
LBRACK: 9, // [ | |
RBRACK: 10, // ] | |
COMMA: 11, // , | |
COLON: 12, // : | |
STAR: 13, // * | |
PIPE: 14, // | | |
QUESTION: 15, // ? | |
BANG: 16, // ! | |
EQUAL: 17, // = | |
NAME: 18, // name token | |
STRING: 19, // string | |
NUMBER: 20, // number | |
EOF: 21 | |
}; | |
function isTypeName(ch) { | |
return '><(){}[],:*|?!='.indexOf(String.fromCharCode(ch)) === -1 && !esutils.code.isWhiteSpace(ch) && !esutils.code.isLineTerminator(ch); | |
} | |
function Context(previous, index, token, value) { | |
this._previous = previous; | |
this._index = index; | |
this._token = token; | |
this._value = value; | |
} | |
Context.prototype.restore = function () { | |
previous = this._previous; | |
index = this._index; | |
token = this._token; | |
value = this._value; | |
}; | |
Context.save = function () { | |
return new Context(previous, index, token, value); | |
}; | |
function maybeAddRange(node, range) { | |
if (addRange) { | |
node.range = [range[0] + rangeOffset, range[1] + rangeOffset]; | |
} | |
return node; | |
} | |
function advance() { | |
var ch = source.charAt(index); | |
index += 1; | |
return ch; | |
} | |
function scanHexEscape(prefix) { | |
var i, len, ch, code = 0; | |
len = (prefix === 'u') ? 4 : 2; | |
for (i = 0; i < len; ++i) { | |
if (index < length && esutils.code.isHexDigit(source.charCodeAt(index))) { | |
ch = advance(); | |
code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); | |
} else { | |
return ''; | |
} | |
} | |
return String.fromCharCode(code); | |
} | |
function scanString() { | |
var str = '', quote, ch, code, unescaped, restore; //TODO review removal octal = false | |
quote = source.charAt(index); | |
++index; | |
while (index < length) { | |
ch = advance(); | |
if (ch === quote) { | |
quote = ''; | |
break; | |
} else if (ch === '\\') { | |
ch = advance(); | |
if (!esutils.code.isLineTerminator(ch.charCodeAt(0))) { | |
switch (ch) { | |
case 'n': | |
str += '\n'; | |
break; | |
case 'r': | |
str += '\r'; | |
break; | |
case 't': | |
str += '\t'; | |
break; | |
case 'u': | |
case 'x': | |
restore = index; | |
unescaped = scanHexEscape(ch); | |
if (unescaped) { | |
str += unescaped; | |
} else { | |
index = restore; | |
str += ch; | |
} | |
break; | |
case 'b': | |
str += '\b'; | |
break; | |
case 'f': | |
str += '\f'; | |
break; | |
case 'v': | |
str += '\v'; | |
break; | |
default: | |
if (esutils.code.isOctalDigit(ch.charCodeAt(0))) { | |
code = '01234567'.indexOf(ch); | |
// \0 is not octal escape sequence | |
// Deprecating unused code. TODO review removal | |
//if (code !== 0) { | |
// octal = true; | |
//} | |
if (index < length && esutils.code.isOctalDigit(source.charCodeAt(index))) { | |
//TODO Review Removal octal = true; | |
code = code * 8 + '01234567'.indexOf(advance()); | |
// 3 digits are only allowed when string starts | |
// with 0, 1, 2, 3 | |
if ('0123'.indexOf(ch) >= 0 && | |
index < length && | |
esutils.code.isOctalDigit(source.charCodeAt(index))) { | |
code = code * 8 + '01234567'.indexOf(advance()); | |
} | |
} | |
str += String.fromCharCode(code); | |
} else { | |
str += ch; | |
} | |
break; | |
} | |
} else { | |
if (ch === '\r' && source.charCodeAt(index) === 0x0A /* '\n' */) { | |
++index; | |
} | |
} | |
} else if (esutils.code.isLineTerminator(ch.charCodeAt(0))) { | |
break; | |
} else { | |
str += ch; | |
} | |
} | |
if (quote !== '') { | |
utility.throwError('unexpected quote'); | |
} | |
value = str; | |
return Token.STRING; | |
} | |
function scanNumber() { | |
var number, ch; | |
number = ''; | |
ch = source.charCodeAt(index); | |
if (ch !== 0x2E /* '.' */) { | |
number = advance(); | |
ch = source.charCodeAt(index); | |
if (number === '0') { | |
if (ch === 0x78 /* 'x' */ || ch === 0x58 /* 'X' */) { | |
number += advance(); | |
while (index < length) { | |
ch = source.charCodeAt(index); | |
if (!esutils.code.isHexDigit(ch)) { | |
break; | |
} | |
number += advance(); | |
} | |
if (number.length <= 2) { | |
// only 0x | |
utility.throwError('unexpected token'); | |
} | |
if (index < length) { | |
ch = source.charCodeAt(index); | |
if (esutils.code.isIdentifierStartES5(ch)) { | |
utility.throwError('unexpected token'); | |
} | |
} | |
value = parseInt(number, 16); | |
return Token.NUMBER; | |
} | |
if (esutils.code.isOctalDigit(ch)) { | |
number += advance(); | |
while (index < length) { | |
ch = source.charCodeAt(index); | |
if (!esutils.code.isOctalDigit(ch)) { | |
break; | |
} | |
number += advance(); | |
} | |
if (index < length) { | |
ch = source.charCodeAt(index); | |
if (esutils.code.isIdentifierStartES5(ch) || esutils.code.isDecimalDigit(ch)) { | |
utility.throwError('unexpected token'); | |
} | |
} | |
value = parseInt(number, 8); | |
return Token.NUMBER; | |
} | |
if (esutils.code.isDecimalDigit(ch)) { | |
utility.throwError('unexpected token'); | |
} | |
} | |
while (index < length) { | |
ch = source.charCodeAt(index); | |
if (!esutils.code.isDecimalDigit(ch)) { | |
break; | |
} | |
number += advance(); | |
} | |
} | |
if (ch === 0x2E /* '.' */) { | |
number += advance(); | |
while (index < length) { | |
ch = source.charCodeAt(index); | |
if (!esutils.code.isDecimalDigit(ch)) { | |
break; | |
} | |
number += advance(); | |
} | |
} | |
if (ch === 0x65 /* 'e' */ || ch === 0x45 /* 'E' */) { | |
number += advance(); | |
ch = source.charCodeAt(index); | |
if (ch === 0x2B /* '+' */ || ch === 0x2D /* '-' */) { | |
number += advance(); | |
} | |
ch = source.charCodeAt(index); | |
if (esutils.code.isDecimalDigit(ch)) { | |
number += advance(); | |
while (index < length) { | |
ch = source.charCodeAt(index); | |
if (!esutils.code.isDecimalDigit(ch)) { | |
break; | |
} | |
number += advance(); | |
} | |
} else { | |
utility.throwError('unexpected token'); | |
} | |
} | |
if (index < length) { | |
ch = source.charCodeAt(index); | |
if (esutils.code.isIdentifierStartES5(ch)) { | |
utility.throwError('unexpected token'); | |
} | |
} | |
value = parseFloat(number); | |
return Token.NUMBER; | |
} | |
function scanTypeName() { | |
var ch, ch2; | |
value = advance(); | |
while (index < length && isTypeName(source.charCodeAt(index))) { | |
ch = source.charCodeAt(index); | |
if (ch === 0x2E /* '.' */) { | |
if ((index + 1) >= length) { | |
return Token.ILLEGAL; | |
} | |
ch2 = source.charCodeAt(index + 1); | |
if (ch2 === 0x3C /* '<' */) { | |
break; | |
} | |
} | |
value += advance(); | |
} | |
return Token.NAME; | |
} | |
function next() { | |
var ch; | |
previous = index; | |
while (index < length && esutils.code.isWhiteSpace(source.charCodeAt(index))) { | |
advance(); | |
} | |
if (index >= length) { | |
token = Token.EOF; | |
return token; | |
} | |
ch = source.charCodeAt(index); | |
switch (ch) { | |
case 0x27: /* ''' */ | |
case 0x22: /* '"' */ | |
token = scanString(); | |
return token; | |
case 0x3A: /* ':' */ | |
advance(); | |
token = Token.COLON; | |
return token; | |
case 0x2C: /* ',' */ | |
advance(); | |
token = Token.COMMA; | |
return token; | |
case 0x28: /* '(' */ | |
advance(); | |
token = Token.LPAREN; | |
return token; | |
case 0x29: /* ')' */ | |
advance(); | |
token = Token.RPAREN; | |
return token; | |
case 0x5B: /* '[' */ | |
advance(); | |
token = Token.LBRACK; | |
return token; | |
case 0x5D: /* ']' */ | |
advance(); | |
token = Token.RBRACK; | |
return token; | |
case 0x7B: /* '{' */ | |
advance(); | |
token = Token.LBRACE; | |
return token; | |
case 0x7D: /* '}' */ | |
advance(); | |
token = Token.RBRACE; | |
return token; | |
case 0x2E: /* '.' */ | |
if (index + 1 < length) { | |
ch = source.charCodeAt(index + 1); | |
if (ch === 0x3C /* '<' */) { | |
advance(); // '.' | |
advance(); // '<' | |
token = Token.DOT_LT; | |
return token; | |
} | |
if (ch === 0x2E /* '.' */ && index + 2 < length && source.charCodeAt(index + 2) === 0x2E /* '.' */) { | |
advance(); // '.' | |
advance(); // '.' | |
advance(); // '.' | |
token = Token.REST; | |
return token; | |
} | |
if (esutils.code.isDecimalDigit(ch)) { | |
token = scanNumber(); | |
return token; | |
} | |
} | |
token = Token.ILLEGAL; | |
return token; | |
case 0x3C: /* '<' */ | |
advance(); | |
token = Token.LT; | |
return token; | |
case 0x3E: /* '>' */ | |
advance(); | |
token = Token.GT; | |
return token; | |
case 0x2A: /* '*' */ | |
advance(); | |
token = Token.STAR; | |
return token; | |
case 0x7C: /* '|' */ | |
advance(); | |
token = Token.PIPE; | |
return token; | |
case 0x3F: /* '?' */ | |
advance(); | |
token = Token.QUESTION; | |
return token; | |
case 0x21: /* '!' */ | |
advance(); | |
token = Token.BANG; | |
return token; | |
case 0x3D: /* '=' */ | |
advance(); | |
token = Token.EQUAL; | |
return token; | |
case 0x2D: /* '-' */ | |
token = scanNumber(); | |
return token; | |
default: | |
if (esutils.code.isDecimalDigit(ch)) { | |
token = scanNumber(); | |
return token; | |
} | |
// type string permits following case, | |
// | |
// namespace.module.MyClass | |
// | |
// this reduced 1 token TK_NAME | |
utility.assert(isTypeName(ch)); | |
token = scanTypeName(); | |
return token; | |
} | |
} | |
function consume(target, text) { | |
utility.assert(token === target, text || 'consumed token not matched'); | |
next(); | |
} | |
function expect(target, message) { | |
if (token !== target) { | |
utility.throwError(message || 'unexpected token'); | |
} | |
next(); | |
} | |
// UnionType := '(' TypeUnionList ')' | |
// | |
// TypeUnionList := | |
// <<empty>> | |
// | NonemptyTypeUnionList | |
// | |
// NonemptyTypeUnionList := | |
// TypeExpression | |
// | TypeExpression '|' NonemptyTypeUnionList | |
function parseUnionType() { | |
var elements, startIndex = index - 1; | |
consume(Token.LPAREN, 'UnionType should start with ('); | |
elements = []; | |
if (token !== Token.RPAREN) { | |
while (true) { | |
elements.push(parseTypeExpression()); | |
if (token === Token.RPAREN) { | |
break; | |
} | |
expect(Token.PIPE); | |
} | |
} | |
consume(Token.RPAREN, 'UnionType should end with )'); | |
return maybeAddRange({ | |
type: Syntax.UnionType, | |
elements: elements | |
}, [startIndex, previous]); | |
} | |
// ArrayType := '[' ElementTypeList ']' | |
// | |
// ElementTypeList := | |
// <<empty>> | |
// | TypeExpression | |
// | '...' TypeExpression | |
// | TypeExpression ',' ElementTypeList | |
function parseArrayType() { | |
var elements, startIndex = index - 1, restStartIndex; | |
consume(Token.LBRACK, 'ArrayType should start with ['); | |
elements = []; | |
while (token !== Token.RBRACK) { | |
if (token === Token.REST) { | |
restStartIndex = index - 3; | |
consume(Token.REST); | |
elements.push(maybeAddRange({ | |
type: Syntax.RestType, | |
expression: parseTypeExpression() | |
}, [restStartIndex, previous])); | |
break; | |
} else { | |
elements.push(parseTypeExpression()); | |
} | |
if (token !== Token.RBRACK) { | |
expect(Token.COMMA); | |
} | |
} | |
expect(Token.RBRACK); | |
return maybeAddRange({ | |
type: Syntax.ArrayType, | |
elements: elements | |
}, [startIndex, previous]); | |
} | |
function parseFieldName() { | |
var v = value; | |
if (token === Token.NAME || token === Token.STRING) { | |
next(); | |
return v; | |
} | |
if (token === Token.NUMBER) { | |
consume(Token.NUMBER); | |
return String(v); | |
} | |
utility.throwError('unexpected token'); | |
} | |
// FieldType := | |
// FieldName | |
// | FieldName ':' TypeExpression | |
// | |
// FieldName := | |
// NameExpression | |
// | StringLiteral | |
// | NumberLiteral | |
// | ReservedIdentifier | |
function parseFieldType() { | |
var key, rangeStart = previous; | |
key = parseFieldName(); | |
if (token === Token.COLON) { | |
consume(Token.COLON); | |
return maybeAddRange({ | |
type: Syntax.FieldType, | |
key: key, | |
value: parseTypeExpression() | |
}, [rangeStart, previous]); | |
} | |
return maybeAddRange({ | |
type: Syntax.FieldType, | |
key: key, | |
value: null | |
}, [rangeStart, previous]); | |
} | |
// RecordType := '{' FieldTypeList '}' | |
// | |
// FieldTypeList := | |
// <<empty>> | |
// | FieldType | |
// | FieldType ',' FieldTypeList | |
function parseRecordType() { | |
var fields, rangeStart = index - 1, rangeEnd; | |
consume(Token.LBRACE, 'RecordType should start with {'); | |
fields = []; | |
if (token === Token.COMMA) { | |
consume(Token.COMMA); | |
} else { | |
while (token !== Token.RBRACE) { | |
fields.push(parseFieldType()); | |
if (token !== Token.RBRACE) { | |
expect(Token.COMMA); | |
} | |
} | |
} | |
rangeEnd = index; | |
expect(Token.RBRACE); | |
return maybeAddRange({ | |
type: Syntax.RecordType, | |
fields: fields | |
}, [rangeStart, rangeEnd]); | |
} | |
// NameExpression := | |
// Identifier | |
// | TagIdentifier ':' Identifier | |
// | |
// Tag identifier is one of "module", "external" or "event" | |
// Identifier is the same as Token.NAME, including any dots, something like | |
// namespace.module.MyClass | |
function parseNameExpression() { | |
var name = value, rangeStart = index - name.length; | |
expect(Token.NAME); | |
if (token === Token.COLON && ( | |
name === 'module' || | |
name === 'external' || | |
name === 'event')) { | |
consume(Token.COLON); | |
name += ':' + value; | |
expect(Token.NAME); | |
} | |
return maybeAddRange({ | |
type: Syntax.NameExpression, | |
name: name | |
}, [rangeStart, previous]); | |
} | |
// TypeExpressionList := | |
// TopLevelTypeExpression | |
// | TopLevelTypeExpression ',' TypeExpressionList | |
function parseTypeExpressionList() { | |
var elements = []; | |
elements.push(parseTop()); | |
while (token === Token.COMMA) { | |
consume(Token.COMMA); | |
elements.push(parseTop()); | |
} | |
return elements; | |
} | |
// TypeName := | |
// NameExpression | |
// | NameExpression TypeApplication | |
// | |
// TypeApplication := | |
// '.<' TypeExpressionList '>' | |
// | '<' TypeExpressionList '>' // this is extension of doctrine | |
function parseTypeName() { | |
var expr, applications, startIndex = index - value.length; | |
expr = parseNameExpression(); | |
if (token === Token.DOT_LT || token === Token.LT) { | |
next(); | |
applications = parseTypeExpressionList(); | |
expect(Token.GT); | |
return maybeAddRange({ | |
type: Syntax.TypeApplication, | |
expression: expr, | |
applications: applications | |
}, [startIndex, previous]); | |
} | |
return expr; | |
} | |
// ResultType := | |
// <<empty>> | |
// | ':' void | |
// | ':' TypeExpression | |
// | |
// BNF is above | |
// but, we remove <<empty>> pattern, so token is always TypeToken::COLON | |
function parseResultType() { | |
consume(Token.COLON, 'ResultType should start with :'); | |
if (token === Token.NAME && value === 'void') { | |
consume(Token.NAME); | |
return { | |
type: Syntax.VoidLiteral | |
}; | |
} | |
return parseTypeExpression(); | |
} | |
// ParametersType := | |
// RestParameterType | |
// | NonRestParametersType | |
// | NonRestParametersType ',' RestParameterType | |
// | |
// RestParameterType := | |
// '...' | |
// '...' Identifier | |
// | |
// NonRestParametersType := | |
// ParameterType ',' NonRestParametersType | |
// | ParameterType | |
// | OptionalParametersType | |
// | |
// OptionalParametersType := | |
// OptionalParameterType | |
// | OptionalParameterType, OptionalParametersType | |
// | |
// OptionalParameterType := ParameterType= | |
// | |
// ParameterType := TypeExpression | Identifier ':' TypeExpression | |
// | |
// Identifier is "new" or "this" | |
function parseParametersType() { | |
var params = [], optionalSequence = false, expr, rest = false, startIndex, restStartIndex = index - 3, nameStartIndex; | |
while (token !== Token.RPAREN) { | |
if (token === Token.REST) { | |
// RestParameterType | |
consume(Token.REST); | |
rest = true; | |
} | |
startIndex = previous; | |
expr = parseTypeExpression(); | |
if (expr.type === Syntax.NameExpression && token === Token.COLON) { | |
nameStartIndex = previous - expr.name.length; | |
// Identifier ':' TypeExpression | |
consume(Token.COLON); | |
expr = maybeAddRange({ | |
type: Syntax.ParameterType, | |
name: expr.name, | |
expression: parseTypeExpression() | |
}, [nameStartIndex, previous]); | |
} | |
if (token === Token.EQUAL) { | |
consume(Token.EQUAL); | |
expr = maybeAddRange({ | |
type: Syntax.OptionalType, | |
expression: expr | |
}, [startIndex, previous]); | |
optionalSequence = true; | |
} else { | |
if (optionalSequence) { | |
utility.throwError('unexpected token'); | |
} | |
} | |
if (rest) { | |
expr = maybeAddRange({ | |
type: Syntax.RestType, | |
expression: expr | |
}, [restStartIndex, previous]); | |
} | |
params.push(expr); | |
if (token !== Token.RPAREN) { | |
expect(Token.COMMA); | |
} | |
} | |
return params; | |
} | |
// FunctionType := 'function' FunctionSignatureType | |
// | |
// FunctionSignatureType := | |
// | TypeParameters '(' ')' ResultType | |
// | TypeParameters '(' ParametersType ')' ResultType | |
// | TypeParameters '(' 'this' ':' TypeName ')' ResultType | |
// | TypeParameters '(' 'this' ':' TypeName ',' ParametersType ')' ResultType | |
function parseFunctionType() { | |
var isNew, thisBinding, params, result, fnType, startIndex = index - value.length; | |
utility.assert(token === Token.NAME && value === 'function', 'FunctionType should start with \'function\''); | |
consume(Token.NAME); | |
// Google Closure Compiler is not implementing TypeParameters. | |
// So we do not. if we don't get '(', we see it as error. | |
expect(Token.LPAREN); | |
isNew = false; | |
params = []; | |
thisBinding = null; | |
if (token !== Token.RPAREN) { | |
// ParametersType or 'this' | |
if (token === Token.NAME && | |
(value === 'this' || value === 'new')) { | |
// 'this' or 'new' | |
// 'new' is Closure Compiler extension | |
isNew = value === 'new'; | |
consume(Token.NAME); | |
expect(Token.COLON); | |
thisBinding = parseTypeName(); | |
if (token === Token.COMMA) { | |
consume(Token.COMMA); | |
params = parseParametersType(); | |
} | |
} else { | |
params = parseParametersType(); | |
} | |
} | |
expect(Token.RPAREN); | |
result = null; | |
if (token === Token.COLON) { | |
result = parseResultType(); | |
} | |
fnType = maybeAddRange({ | |
type: Syntax.FunctionType, | |
params: params, | |
result: result | |
}, [startIndex, previous]); | |
if (thisBinding) { | |
// avoid adding null 'new' and 'this' properties | |
fnType['this'] = thisBinding; | |
if (isNew) { | |
fnType['new'] = true; | |
} | |
} | |
return fnType; | |
} | |
// BasicTypeExpression := | |
// '*' | |
// | 'null' | |
// | 'undefined' | |
// | TypeName | |
// | FunctionType | |
// | UnionType | |
// | RecordType | |
// | ArrayType | |
function parseBasicTypeExpression() { | |
var context, startIndex; | |
switch (token) { | |
case Token.STAR: | |
consume(Token.STAR); | |
return maybeAddRange({ | |
type: Syntax.AllLiteral | |
}, [previous - 1, previous]); | |
case Token.LPAREN: | |
return parseUnionType(); | |
case Token.LBRACK: | |
return parseArrayType(); | |
case Token.LBRACE: | |
return parseRecordType(); | |
case Token.NAME: | |
startIndex = index - value.length; | |
if (value === 'null') { | |
consume(Token.NAME); | |
return maybeAddRange({ | |
type: Syntax.NullLiteral | |
}, [startIndex, previous]); | |
} | |
if (value === 'undefined') { | |
consume(Token.NAME); | |
return maybeAddRange({ | |
type: Syntax.UndefinedLiteral | |
}, [startIndex, previous]); | |
} | |
if (value === 'true' || value === 'false') { | |
consume(Token.NAME); | |
return maybeAddRange({ | |
type: Syntax.BooleanLiteralType, | |
value: value === 'true' | |
}, [startIndex, previous]); | |
} | |
context = Context.save(); | |
if (value === 'function') { | |
try { | |
return parseFunctionType(); | |
} catch (e) { | |
context.restore(); | |
} | |
} | |
return parseTypeName(); | |
case Token.STRING: | |
next(); | |
return maybeAddRange({ | |
type: Syntax.StringLiteralType, | |
value: value | |
}, [previous - value.length - 2, previous]); | |
case Token.NUMBER: | |
next(); | |
return maybeAddRange({ | |
type: Syntax.NumericLiteralType, | |
value: value | |
}, [previous - String(value).length, previous]); | |
default: | |
utility.throwError('unexpected token'); | |
} | |
} | |
// TypeExpression := | |
// BasicTypeExpression | |
// | '?' BasicTypeExpression | |
// | '!' BasicTypeExpression | |
// | BasicTypeExpression '?' | |
// | BasicTypeExpression '!' | |
// | '?' | |
// | BasicTypeExpression '[]' | |
function parseTypeExpression() { | |
var expr, rangeStart; | |
if (token === Token.QUESTION) { | |
rangeStart = index - 1; | |
consume(Token.QUESTION); | |
if (token === Token.COMMA || token === Token.EQUAL || token === Token.RBRACE || | |
token === Token.RPAREN || token === Token.PIPE || token === Token.EOF || | |
token === Token.RBRACK || token === Token.GT) { | |
return maybeAddRange({ | |
type: Syntax.NullableLiteral | |
}, [rangeStart, previous]); | |
} | |
return maybeAddRange({ | |
type: Syntax.NullableType, | |
expression: parseBasicTypeExpression(), | |
prefix: true | |
}, [rangeStart, previous]); | |
} else if (token === Token.BANG) { | |
rangeStart = index - 1; | |
consume(Token.BANG); | |
return maybeAddRange({ | |
type: Syntax.NonNullableType, | |
expression: parseBasicTypeExpression(), | |
prefix: true | |
}, [rangeStart, previous]); | |
} else { | |
rangeStart = previous; | |
} | |
expr = parseBasicTypeExpression(); | |
if (token === Token.BANG) { | |
consume(Token.BANG); | |
return maybeAddRange({ | |
type: Syntax.NonNullableType, | |
expression: expr, | |
prefix: false | |
}, [rangeStart, previous]); | |
} | |
if (token === Token.QUESTION) { | |
consume(Token.QUESTION); | |
return maybeAddRange({ | |
type: Syntax.NullableType, | |
expression: expr, | |
prefix: false | |
}, [rangeStart, previous]); | |
} | |
if (token === Token.LBRACK) { | |
consume(Token.LBRACK); | |
expect(Token.RBRACK, 'expected an array-style type declaration (' + value + '[])'); | |
return maybeAddRange({ | |
type: Syntax.TypeApplication, | |
expression: maybeAddRange({ | |
type: Syntax.NameExpression, | |
name: 'Array' | |
}, [rangeStart, previous]), | |
applications: [expr] | |
}, [rangeStart, previous]); | |
} | |
return expr; | |
} | |
// TopLevelTypeExpression := | |
// TypeExpression | |
// | TypeUnionList | |
// | |
// This rule is Google Closure Compiler extension, not ES4 | |
// like, | |
// { number | string } | |
// If strict to ES4, we should write it as | |
// { (number|string) } | |
function parseTop() { | |
var expr, elements; | |
expr = parseTypeExpression(); | |
if (token !== Token.PIPE) { | |
return expr; | |
} | |
elements = [expr]; | |
consume(Token.PIPE); | |
while (true) { | |
elements.push(parseTypeExpression()); | |
if (token !== Token.PIPE) { | |
break; | |
} | |
consume(Token.PIPE); | |
} | |
return maybeAddRange({ | |
type: Syntax.UnionType, | |
elements: elements | |
}, [0, index]); | |
} | |
function parseTopParamType() { | |
var expr; | |
if (token === Token.REST) { | |
consume(Token.REST); | |
return maybeAddRange({ | |
type: Syntax.RestType, | |
expression: parseTop() | |
}, [0, index]); | |
} | |
expr = parseTop(); | |
if (token === Token.EQUAL) { | |
consume(Token.EQUAL); | |
return maybeAddRange({ | |
type: Syntax.OptionalType, | |
expression: expr | |
}, [0, index]); | |
} | |
return expr; | |
} | |
function parseType(src, opt) { | |
var expr; | |
source = src; | |
length = source.length; | |
index = 0; | |
previous = 0; | |
addRange = opt && opt.range; | |
rangeOffset = opt && opt.startIndex || 0; | |
next(); | |
expr = parseTop(); | |
if (opt && opt.midstream) { | |
return { | |
expression: expr, | |
index: previous | |
}; | |
} | |
if (token !== Token.EOF) { | |
utility.throwError('not reach to EOF'); | |
} | |
return expr; | |
} | |
function parseParamType(src, opt) { | |
var expr; | |
source = src; | |
length = source.length; | |
index = 0; | |
previous = 0; | |
addRange = opt && opt.range; | |
rangeOffset = opt && opt.startIndex || 0; | |
next(); | |
expr = parseTopParamType(); | |
if (opt && opt.midstream) { | |
return { | |
expression: expr, | |
index: previous | |
}; | |
} | |
if (token !== Token.EOF) { | |
utility.throwError('not reach to EOF'); | |
} | |
return expr; | |
} | |
function stringifyImpl(node, compact, topLevel) { | |
var result, i, iz; | |
switch (node.type) { | |
case Syntax.NullableLiteral: | |
result = '?'; | |
break; | |
case Syntax.AllLiteral: | |
result = '*'; | |
break; | |
case Syntax.NullLiteral: | |
result = 'null'; | |
break; | |
case Syntax.UndefinedLiteral: | |
result = 'undefined'; | |
break; | |
case Syntax.VoidLiteral: | |
result = 'void'; | |
break; | |
case Syntax.UnionType: | |
if (!topLevel) { | |
result = '('; | |
} else { | |
result = ''; | |
} | |
for (i = 0, iz = node.elements.length; i < iz; ++i) { | |
result += stringifyImpl(node.elements[i], compact); | |
if ((i + 1) !== iz) { | |
result += compact ? '|' : ' | '; | |
} | |
} | |
if (!topLevel) { | |
result += ')'; | |
} | |
break; | |
case Syntax.ArrayType: | |
result = '['; | |
for (i = 0, iz = node.elements.length; i < iz; ++i) { | |
result += stringifyImpl(node.elements[i], compact); | |
if ((i + 1) !== iz) { | |
result += compact ? ',' : ', '; | |
} | |
} | |
result += ']'; | |
break; | |
case Syntax.RecordType: | |
result = '{'; | |
for (i = 0, iz = node.fields.length; i < iz; ++i) { | |
result += stringifyImpl(node.fields[i], compact); | |
if ((i + 1) !== iz) { | |
result += compact ? ',' : ', '; | |
} | |
} | |
result += '}'; | |
break; | |
case Syntax.FieldType: | |
if (node.value) { | |
result = node.key + (compact ? ':' : ': ') + stringifyImpl(node.value, compact); | |
} else { | |
result = node.key; | |
} | |
break; | |
case Syntax.FunctionType: | |
result = compact ? 'function(' : 'function ('; | |
if (node['this']) { | |
if (node['new']) { | |
result += (compact ? 'new:' : 'new: '); | |
} else { | |
result += (compact ? 'this:' : 'this: '); | |
} | |
result += stringifyImpl(node['this'], compact); | |
if (node.params.length !== 0) { | |
result += compact ? ',' : ', '; | |
} | |
} | |
for (i = 0, iz = node.params.length; i < iz; ++i) { | |
result += stringifyImpl(node.params[i], compact); | |
if ((i + 1) !== iz) { | |
result += compact ? ',' : ', '; | |
} | |
} | |
result += ')'; | |
if (node.result) { | |
result += (compact ? ':' : ': ') + stringifyImpl(node.result, compact); | |
} | |
break; | |
case Syntax.ParameterType: | |
result = node.name + (compact ? ':' : ': ') + stringifyImpl(node.expression, compact); | |
break; | |
case Syntax.RestType: | |
result = '...'; | |
if (node.expression) { | |
result += stringifyImpl(node.expression, compact); | |
} | |
break; | |
case Syntax.NonNullableType: | |
if (node.prefix) { | |
result = '!' + stringifyImpl(node.expression, compact); | |
} else { | |
result = stringifyImpl(node.expression, compact) + '!'; | |
} | |
break; | |
case Syntax.OptionalType: | |
result = stringifyImpl(node.expression, compact) + '='; | |
break; | |
case Syntax.NullableType: | |
if (node.prefix) { | |
result = '?' + stringifyImpl(node.expression, compact); | |
} else { | |
result = stringifyImpl(node.expression, compact) + '?'; | |
} | |
break; | |
case Syntax.NameExpression: | |
result = node.name; | |
break; | |
case Syntax.TypeApplication: | |
result = stringifyImpl(node.expression, compact) + '.<'; | |
for (i = 0, iz = node.applications.length; i < iz; ++i) { | |
result += stringifyImpl(node.applications[i], compact); | |
if ((i + 1) !== iz) { | |
result += compact ? ',' : ', '; | |
} | |
} | |
result += '>'; | |
break; | |
case Syntax.StringLiteralType: | |
result = '"' + node.value + '"'; | |
break; | |
case Syntax.NumericLiteralType: | |
result = String(node.value); | |
break; | |
case Syntax.BooleanLiteralType: | |
result = String(node.value); | |
break; | |
default: | |
utility.throwError('Unknown type ' + node.type); | |
} | |
return result; | |
} | |
function stringify(node, options) { | |
if (options == null) { | |
options = {}; | |
} | |
return stringifyImpl(node, options.compact, options.topLevel); | |
} | |
exports.parseType = parseType; | |
exports.parseParamType = parseParamType; | |
exports.stringify = stringify; | |
exports.Syntax = Syntax; | |
}()); | |
/* vim: set sw=4 ts=4 et tw=80 : */ | |
/***/ }), | |
/***/ 1408: | |
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { | |
/* | |
* @fileoverview Utilities for Doctrine | |
* @author Yusuke Suzuki <[email protected]> | |
*/ | |
(function () { | |
'use strict'; | |
var VERSION; | |
VERSION = (__webpack_require__(2954)/* .version */ .i8); | |
exports.VERSION = VERSION; | |
function DoctrineError(message) { | |
this.name = 'DoctrineError'; | |
this.message = message; | |
} | |
DoctrineError.prototype = (function () { | |
var Middle = function () { }; | |
Middle.prototype = Error.prototype; | |
return new Middle(); | |
}()); | |
DoctrineError.prototype.constructor = DoctrineError; | |
exports.DoctrineError = DoctrineError; | |
function throwError(message) { | |
throw new DoctrineError(message); | |
} | |
exports.throwError = throwError; | |
exports.assert = __webpack_require__(9282); | |
}()); | |
/* vim: set sw=4 ts=4 et tw=80 : */ | |
/***/ }), | |
/***/ 8091: | |
/***/ (function(module) { | |
"use strict"; | |
/** | |
* Code refactored from Mozilla Developer Network: | |
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign | |
*/ | |
function assign(target, firstSource) { | |
if (target === undefined || target === null) { | |
throw new TypeError('Cannot convert first argument to object'); | |
} | |
var to = Object(target); | |
for (var i = 1; i < arguments.length; i++) { | |
var nextSource = arguments[i]; | |
if (nextSource === undefined || nextSource === null) { | |
continue; | |
} | |
var keysArray = Object.keys(Object(nextSource)); | |
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { | |
var nextKey = keysArray[nextIndex]; | |
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); | |
if (desc !== undefined && desc.enumerable) { | |
to[nextKey] = nextSource[nextKey]; | |
} | |
} | |
} | |
return to; | |
} | |
function polyfill() { | |
if (!Object.assign) { | |
Object.defineProperty(Object, 'assign', { | |
enumerable: false, | |
configurable: true, | |
writable: true, | |
value: assign | |
}); | |
} | |
} | |
module.exports = { | |
assign: assign, | |
polyfill: polyfill | |
}; | |
/***/ }), | |
/***/ 3150: | |
/***/ (function(module) { | |
"use strict"; | |
module.exports = string => { | |
if (typeof string !== 'string') { | |
throw new TypeError('Expected a string'); | |
} | |
// Escape characters with special meaning either inside or outside character sets. | |
// Use a simple backslash escape when it’s always valid, and a \unnnn escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar. | |
return string | |
.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') | |
.replace(/-/g, '\\x2d'); | |
}; | |
/***/ }), | |
/***/ 5830: | |
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { | |
"use strict"; | |
/*! @author Toru Nagashima <https://github.com/mysticatea> */ | |
Object.defineProperty(exports, "__esModule", ({ value: true })); | |
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } | |
var evk = _interopDefault(__webpack_require__(8727)); | |
/** | |
* Get the innermost scope which contains a given location. | |
* @param {Scope} initialScope The initial scope to search. | |
* @param {Node} node The location to search. | |
* @returns {Scope} The innermost scope. | |
*/ | |
function getInnermostScope(initialScope, node) { | |
const location = node.range[0]; | |
let scope = initialScope; | |
let found = false; | |
do { | |
found = false; | |
for (const childScope of scope.childScopes) { | |
const range = childScope.block.range; | |
if (range[0] <= location && location < range[1]) { | |
scope = childScope; | |
found = true; | |
break | |
} | |
} | |
} while (found) | |
return scope | |
} | |
/** | |
* Find the variable of a given name. | |
* @param {Scope} initialScope The scope to start finding. | |
* @param {string|Node} nameOrNode The variable name to find. If this is a Node object then it should be an Identifier node. | |
* @returns {Variable|null} The found variable or null. | |
*/ | |
function findVariable(initialScope, nameOrNode) { | |
let name = ""; | |
let scope = initialScope; | |
if (typeof nameOrNode === "string") { | |
name = nameOrNode; | |
} else { | |
name = nameOrNode.name; | |
scope = getInnermostScope(scope, nameOrNode); | |
} | |
while (scope != null) { | |
const variable = scope.set.get(name); | |
if (variable != null) { | |
return variable | |
} | |
scope = scope.upper; | |
} | |
return null | |
} | |
/** | |
* Negate the result of `this` calling. | |
* @param {Token} token The token to check. | |
* @returns {boolean} `true` if the result of `this(token)` is `false`. | |
*/ | |
function negate0(token) { | |
return !this(token) //eslint-disable-line no-invalid-this | |
} | |
/** | |
* Creates the negate function of the given function. | |
* @param {function(Token):boolean} f - The function to negate. | |
* @returns {function(Token):boolean} Negated function. | |
*/ | |
function negate(f) { | |
return negate0.bind(f) | |
} | |
/** | |
* Checks if the given token is a PunctuatorToken with the given value | |
* @param {Token} token - The token to check. | |
* @param {string} value - The value to check. | |
* @returns {boolean} `true` if the token is a PunctuatorToken with the given value. | |
*/ | |
function isPunctuatorTokenWithValue(token, value) { | |
return token.type === "Punctuator" && token.value === value | |
} | |
/** | |
* Checks if the given token is an arrow token or not. | |
* @param {Token} token - The token to check. | |
* @returns {boolean} `true` if the token is an arrow token. | |
*/ | |
function isArrowToken(token) { | |
return isPunctuatorTokenWithValue(token, "=>") | |
} | |
/** | |
* Checks if the given token is a comma token or not. | |
* @param {Token} token - The token to check. | |
* @returns {boolean} `true` if the token is a comma token. | |
*/ | |
function isCommaToken(token) { | |
return isPunctuatorTokenWithValue(token, ",") | |
} | |
/** | |
* Checks if the given token is a semicolon token or not. | |
* @param {Token} token - The token to check. | |
* @returns {boolean} `true` if the token is a semicolon token. | |
*/ | |
function isSemicolonToken(token) { | |
return isPunctuatorTokenWithValue(token, ";") | |
} | |
/** | |
* Checks if the given token is a colon token or not. | |
* @param {Token} token - The token to check. | |
* @returns {boolean} `true` if the token is a colon token. | |
*/ | |
function isColonToken(token) { | |
return isPunctuatorTokenWithValue(token, ":") | |
} | |
/** | |
* Checks if the given token is an opening parenthesis token or not. | |
* @param {Token} token - The token to check. | |
* @returns {boolean} `true` if the token is an opening parenthesis token. | |
*/ | |
function isOpeningParenToken(token) { | |
return isPunctuatorTokenWithValue(token, "(") | |
} | |
/** | |
* Checks if the given token is a closing parenthesis token or not. | |
* @param {Token} token - The token to check. | |
* @returns {boolean} `true` if the token is a closing parenthesis token. | |
*/ | |
function isClosingParenToken(token) { | |
return isPunctuatorTokenWithValue(token, ")") | |
} | |
/** | |
* Checks if the given token is an opening square bracket token or not. | |
* @param {Token} token - The token to check. | |
* @returns {boolean} `true` if the token is an opening square bracket token. | |
*/ | |
function isOpeningBracketToken(token) { | |
return isPunctuatorTokenWithValue(token, "[") | |
} | |
/** | |
* Checks if the given token is a closing square bracket token or not. | |
* @param {Token} token - The token to check. | |
* @returns {boolean} `true` if the token is a closing square bracket token. | |
*/ | |
function isClosingBracketToken(token) { | |
return isPunctuatorTokenWithValue(token, "]") | |
} | |
/** | |
* Checks if the given token is an opening brace token or not. | |
* @param {Token} token - The token to check. | |
* @returns {boolean} `true` if the token is an opening brace token. | |
*/ | |
function isOpeningBraceToken(token) { | |
return isPunctuatorTokenWithValue(token, "{") | |
} | |
/** | |
* Checks if the given token is a closing brace token or not. | |
* @param {Token} token - The token to check. | |
* @returns {boolean} `true` if the token is a closing brace token. | |
*/ | |
function isClosingBraceToken(token) { | |
return isPunctuatorTokenWithValue(token, "}") | |
} | |
/** | |
* Checks if the given token is a comment token or not. | |
* @param {Token} token - The token to check. | |
* @returns {boolean} `true` if the token is a comment token. | |
*/ | |
function isCommentToken(token) { | |
return ["Block", "Line", "Shebang"].includes(token.type) | |
} | |
const isNotArrowToken = negate(isArrowToken); | |
const isNotCommaToken = negate(isCommaToken); | |
const isNotSemicolonToken = negate(isSemicolonToken); | |
const isNotColonToken = negate(isColonToken); | |
const isNotOpeningParenToken = negate(isOpeningParenToken); | |
const isNotClosingParenToken = negate(isClosingParenToken); | |
const isNotOpeningBracketToken = negate(isOpeningBracketToken); | |
const isNotClosingBracketToken = negate(isClosingBracketToken); | |
const isNotOpeningBraceToken = negate(isOpeningBraceToken); | |
const isNotClosingBraceToken = negate(isClosingBraceToken); | |
const isNotCommentToken = negate(isCommentToken); | |
/** | |
* Get the `(` token of the given function node. | |
* @param {Node} node - The function node to get. | |
* @param {SourceCode} sourceCode - The source code object to get tokens. | |
* @returns {Token} `(` token. | |
*/ | |
function getOpeningParenOfParams(node, sourceCode) { | |
return node.id | |
? sourceCode.getTokenAfter(node.id, isOpeningParenToken) | |
: sourceCode.getFirstToken(node, isOpeningParenToken) | |
} | |
/** | |
* Get the location of the given function node for reporting. | |
* @param {Node} node - The function node to get. | |
* @param {SourceCode} sourceCode - The source code object to get tokens. | |
* @returns {string} The location of the function node for reporting. | |
*/ | |
function getFunctionHeadLocation(node, sourceCode) { | |
const parent = node.parent; | |
let start = null; | |
let end = null; | |
if (node.type === "ArrowFunctionExpression") { | |
const arrowToken = sourceCode.getTokenBefore(node.body, isArrowToken); | |
start = arrowToken.loc.start; | |
end = arrowToken.loc.end; | |
} else if ( | |
parent.type === "Property" || | |
parent.type === "MethodDefinition" || | |
parent.type === "PropertyDefinition" | |
) { | |
start = parent.loc.start; | |
end = getOpeningParenOfParams(node, sourceCode).loc.start; | |
} else { | |
start = node.loc.start; | |
end = getOpeningParenOfParams(node, sourceCode).loc.start; | |
} | |
return { | |
start: { ...start }, | |
end: { ...end }, | |
} | |
} | |
/* globals globalThis, global, self, window */ | |
const globalObject = | |
typeof globalThis !== "undefined" | |
? globalThis | |
: typeof self !== "undefined" | |
? self | |
: typeof window !== "undefined" | |
? window | |
: typeof __webpack_require__.g !== "undefined" | |
? __webpack_require__.g | |
: {}; | |
const builtinNames = Object.freeze( | |
new Set([ | |
"Array", | |
"ArrayBuffer", | |
"BigInt", | |
"BigInt64Array", | |
"BigUint64Array", | |
"Boolean", | |
"DataView", | |
"Date", | |
"decodeURI", | |
"decodeURIComponent", | |
"encodeURI", | |
"encodeURIComponent", | |
"escape", | |
"Float32Array", | |
"Float64Array", | |
"Function", | |
"Infinity", | |
"Int16Array", | |
"Int32Array", | |
"Int8Array", | |
"isFinite", | |
"isNaN", | |
"isPrototypeOf", | |
"JSON", | |
"Map", | |
"Math", | |
"NaN", | |
"Number", | |
"Object", | |
"parseFloat", | |
"parseInt", | |
"Promise", | |
"Proxy", | |
"Reflect", | |
"RegExp", | |
"Set", | |
"String", | |
"Symbol", | |
"Uint16Array", | |
"Uint32Array", | |
"Uint8Array", | |
"Uint8ClampedArray", | |
"undefined", | |
"unescape", | |
"WeakMap", | |
"WeakSet", | |
]), | |
); | |
const callAllowed = new Set( | |
[ | |
Array.isArray, | |
typeof BigInt === "function" ? BigInt : undefined, | |
Boolean, | |
Date, | |
Date.parse, | |
decodeURI, | |
decodeURIComponent, | |
encodeURI, | |
encodeURIComponent, | |
escape, | |
isFinite, | |
isNaN, | |
isPrototypeOf, | |
...Object.getOwnPropertyNames(Math) | |
.map((k) => Math[k]) | |
.filter((f) => typeof f === "function"), | |
Number, | |
Number.isFinite, | |
Number.isNaN, | |
Number.parseFloat, | |
Number.parseInt, | |
Object, | |
Object.entries, | |
Object.is, | |
Object.isExtensible, | |
Object.isFrozen, | |
Object.isSealed, | |
Object.keys, | |
Object.values, | |
parseFloat, | |
parseInt, | |
RegExp, | |
String, | |
String.fromCharCode, | |
String.fromCodePoint, | |
String.raw, | |
Symbol.for, | |
Symbol.keyFor, | |
unescape, | |
].filter((f) => typeof f === "function"), | |
); | |
const callPassThrough = new Set([ | |
Object.freeze, | |
Object.preventExtensions, | |
Object.seal, | |
]); | |
/** | |
* Get the property descriptor. | |
* @param {object} object The object to get. | |
* @param {string|number|symbol} name The property name to get. | |
*/ | |
function getPropertyDescriptor(object, name) { | |
let x = object; | |
while ((typeof x === "object" || typeof x === "function") && x !== null) { | |
const d = Object.getOwnPropertyDescriptor(x, name); | |
if (d) { | |
return d | |
} | |
x = Object.getPrototypeOf(x); | |
} | |
return null | |
} | |
/** | |
* Check if a property is getter or not. | |
* @param {object} object The object to check. | |
* @param {string|number|symbol} name The property name to check. | |
*/ | |
function isGetter(object, name) { | |
const d = getPropertyDescriptor(object, name); | |
return d != null && d.get != null | |
} | |
/** | |
* Get the element values of a given node list. | |
* @param {Node[]} nodeList The node list to get values. | |
* @param {Scope|undefined} initialScope The initial scope to find variables. | |
* @returns {any[]|null} The value list if all nodes are constant. Otherwise, null. | |
*/ | |
function getElementValues(nodeList, initialScope) { | |
const valueList = []; | |
for (let i = 0; i < nodeList.length; ++i) { | |
const elementNode = nodeList[i]; | |
if (elementNode == null) { | |
valueList.length = i + 1; | |
} else if (elementNode.type === "SpreadElement") { | |
const argument = getStaticValueR(elementNode.argument, initialScope); | |
if (argument == null) { | |
return null | |
} | |
valueList.push(...argument.value); | |
} else { | |
const element = getStaticValueR(elementNode, initialScope); | |
if (element == null) { | |
return null | |
} | |
valueList.push(element.value); | |
} | |
} | |
return valueList | |
} | |
const operations = Object.freeze({ | |
ArrayExpression(node, initialScope) { | |
const elements = getElementValues(node.elements, initialScope); | |
return elements != null ? { value: elements } : null | |
}, | |
AssignmentExpression(node, initialScope) { | |
if (node.operator === "=") { | |
return getStaticValueR(node.right, initialScope) | |
} | |
return null | |
}, | |
//eslint-disable-next-line complexity | |
BinaryExpression(node, initialScope) { | |
if (node.operator === "in" || node.operator === "instanceof") { | |
// Not supported. | |
return null | |
} | |
const left = getStaticValueR(node.left, initialScope); | |
const right = getStaticValueR(node.right, initialScope); | |
if (left != null && right != null) { | |
switch (node.operator) { | |
case "==": | |
return { value: left.value == right.value } //eslint-disable-line eqeqeq | |
case "!=": | |
return { value: left.value != right.value } //eslint-disable-line eqeqeq | |
case "===": | |
return { value: left.value === right.value } | |
case "!==": | |
return { value: left.value !== right.value } | |
case "<": | |
return { value: left.value < right.value } | |
case "<=": | |
return { value: left.value <= right.value } | |
case ">": | |
return { value: left.value > right.value } | |
case ">=": | |
return { value: left.value >= right.value } | |
case "<<": | |
return { value: left.value << right.value } | |
case ">>": | |
return { value: left.value >> right.value } | |
case ">>>": | |
return { value: left.value >>> right.value } | |
case "+": | |
return { value: left.value + right.value } | |
case "-": | |
return { value: left.value - right.value } | |
case "*": | |
return { value: left.value * right.value } | |
case "/": | |
return { value: left.value / right.value } | |
case "%": | |
return { value: left.value % right.value } | |
case "**": | |
return { value: Math.pow(left.value, right.value) } | |
case "|": | |
return { value: left.value | right.value } | |
case "^": | |
return { value: left.value ^ right.value } | |
case "&": | |
return { value: left.value & right.value } | |
// no default | |
} | |
} | |
return null | |
}, | |
CallExpression(node, initialScope) { | |
const calleeNode = node.callee; | |
const args = getElementValues(node.arguments, initialScope); | |
if (args != null) { | |
if (calleeNode.type === "MemberExpression") { | |
if (calleeNode.property.type === "PrivateIdentifier") { | |
return null | |
} | |
const object = getStaticValueR(calleeNode.object, initialScope); | |
if (object != null) { | |
if ( | |
object.value == null && | |
(object.optional || node.optional) | |
) { | |
return { value: undefined, optional: true } | |
} | |
const property = getStaticPropertyNameValue( | |
calleeNode, | |
initialScope, | |
); | |
if (property != null) { | |
const receiver = object.value; | |
const methodName = property.value; | |
if (callAllowed.has(receiver[methodName])) { | |
return { value: receiver[methodName](...args) } | |
} | |
if (callPassThrough.has(receiver[methodName])) { | |
return { value: args[0] } | |
} | |
} | |
} | |
} else { | |
const callee = getStaticValueR(calleeNode, initialScope); | |
if (callee != null) { | |
if (callee.value == null && node.optional) { | |
return { value: undefined, optional: true } | |
} | |
const func = callee.value; | |
if (callAllowed.has(func)) { | |
return { value: func(...args) } | |
} | |
if (callPassThrough.has(func)) { | |
return { value: args[0] } | |
} | |
} | |
} | |
} | |
return null | |
}, | |
ConditionalExpression(node, initialScope) { | |
const test = getStaticValueR(node.test, initialScope); | |
if (test != null) { | |
return test.value | |
? getStaticValueR(node.consequent, initialScope) | |
: getStaticValueR(node.alternate, initialScope) | |
} | |
return null | |
}, | |
ExpressionStatement(node, initialScope) { | |
return getStaticValueR(node.expression, initialScope) | |
}, | |
Identifier(node, initialScope) { | |
if (initialScope != null) { | |
const variable = findVariable(initialScope, node); | |
// Built-in globals. | |
if ( | |
variable != null && | |
variable.defs.length === 0 && | |
builtinNames.has(variable.name) && | |
variable.name in globalObject | |
) { | |
return { value: globalObject[variable.name] } | |
} | |
// Constants. | |
if (variable != null && variable.defs.length === 1) { | |
const def = variable.defs[0]; | |
if ( | |
def.parent && | |
def.parent.kind === "const" && | |
// TODO(mysticatea): don't support destructuring here. | |
def.node.id.type === "Identifier" | |
) { | |
return getStaticValueR(def.node.init, initialScope) | |
} | |
} | |
} | |
return null | |
}, | |
Literal(node) { | |
//istanbul ignore if : this is implementation-specific behavior. | |
if ((node.regex != null || node.bigint != null) && node.value == null) { | |
// It was a RegExp/BigInt literal, but Node.js didn't support it. | |
return null | |
} | |
return { value: node.value } | |
}, | |
LogicalExpression(node, initialScope) { | |
const left = getStaticValueR(node.left, initialScope); | |
if (left != null) { | |
if ( | |
(node.operator === "||" && Boolean(left.value) === true) || | |
(node.operator === "&&" && Boolean(left.value) === false) || | |
(node.operator === "??" && left.value != null) | |
) { | |
return left | |
} | |
const right = getStaticValueR(node.right, initialScope); | |
if (right != null) { | |
return right | |
} | |
} | |
return null | |
}, | |
MemberExpression(node, initialScope) { | |
if (node.property.type === "PrivateIdentifier") { | |
return null | |
} | |
const object = getStaticValueR(node.object, initialScope); | |
if (object != null) { | |
if (object.value == null && (object.optional || node.optional)) { | |
return { value: undefined, optional: true } | |
} | |
const property = getStaticPropertyNameValue(node, initialScope); | |
if (property != null && !isGetter(object.value, property.value)) { | |
return { value: object.value[property.value] } | |
} | |
} | |
return null | |
}, | |
ChainExpression(node, initialScope) { | |
const expression = getStaticValueR(node.expression, initialScope); | |
if (expression != null) { | |
return { value: expression.value } | |
} | |
return null | |
}, | |
NewExpression(node, initialScope) { | |
const callee = getStaticValueR(node.callee, initialScope); | |
const args = getElementValues(node.arguments, initialScope); | |
if (callee != null && args != null) { | |
const Func = callee.value; | |
if (callAllowed.has(Func)) { | |
return { value: new Func(...args) } | |
} | |
} | |
return null | |
}, | |
ObjectExpression(node, initialScope) { | |
const object = {}; | |
for (const propertyNode of node.properties) { | |
if (propertyNode.type === "Property") { | |
if (propertyNode.kind !== "init") { | |
return null | |
} | |
const key = getStaticPropertyNameValue( | |
propertyNode, | |
initialScope, | |
); | |
const value = getStaticValueR(propertyNode.value, initialScope); | |
if (key == null || value == null) { | |
return null | |
} | |
object[key.value] = value.value; | |
} else if ( | |
propertyNode.type === "SpreadElement" || | |
propertyNode.type === "ExperimentalSpreadProperty" | |
) { | |
const argument = getStaticValueR( | |
propertyNode.argument, | |
initialScope, | |
); | |
if (argument == null) { | |
return null | |
} | |
Object.assign(object, argument.value); | |
} else { | |
return null | |
} | |
} | |
return { value: object } | |
}, | |
SequenceExpression(node, initialScope) { | |
const last = node.expressions[node.expressions.length - 1]; | |
return getStaticValueR(last, initialScope) | |
}, | |
TaggedTemplateExpression(node, initialScope) { | |
const tag = getStaticValueR(node.tag, initialScope); | |
const expressions = getElementValues( | |
node.quasi.expressions, | |
initialScope, | |
); | |
if (tag != null && expressions != null) { | |
const func = tag.value; | |
const strings = node.quasi.quasis.map((q) => q.value.cooked); | |
strings.raw = node.quasi.quasis.map((q) => q.value.raw); | |
if (func === String.raw) { | |
return { value: func(strings, ...expressions) } | |
} | |
} | |
return null | |
}, | |
TemplateLiteral(node, initialScope) { | |
const expressions = getElementValues(node.expressions, initialScope); | |
if (expressions != null) { | |
let value = node.quasis[0].value.cooked; | |
for (let i = 0; i < expressions.length; ++i) { | |
value += expressions[i]; | |
value += node.quasis[i + 1].value.cooked; | |
} | |
return { value } | |
} | |
return null | |
}, | |
UnaryExpression(node, initialScope) { | |
if (node.operator === "delete") { | |
// Not supported. | |
return null | |
} | |
if (node.operator === "void") { | |
return { value: undefined } | |
} | |
const arg = getStaticValueR(node.argument, initialScope); | |
if (arg != null) { | |
switch (node.operator) { | |
case "-": | |
return { value: -arg.value } | |
case "+": | |
return { value: +arg.value } //eslint-disable-line no-implicit-coercion | |
case "!": | |
return { value: !arg.value } | |
case "~": | |
return { value: ~arg.value } | |
case "typeof": | |
return { value: typeof arg.value } | |
// no default | |
} | |
} | |
return null | |
}, | |
}); | |
/** | |
* Get the value of a given node if it's a static value. | |
* @param {Node} node The node to get. | |
* @param {Scope|undefined} initialScope The scope to start finding variable. | |
* @returns {{value:any}|{value:undefined,optional?:true}|null} The static value of the node, or `null`. | |
*/ | |
function getStaticValueR(node, initialScope) { | |
if (node != null && Object.hasOwnProperty.call(operations, node.type)) { | |
return operations[node.type](node, initialScope) | |
} | |
return null | |
} | |
/** | |
* Get the static value of property name from a MemberExpression node or a Property node. | |
* @param {Node} node The node to get. | |
* @param {Scope} [initialScope] The scope to start finding variable. Optional. If the node is a computed property node and this scope was given, this checks the computed property name by the `getStringIfConstant` function with the scope, and returns the value of it. | |
* @returns {{value:any}|{value:undefined,optional?:true}|null} The static value of the property name of the node, or `null`. | |
*/ | |
function getStaticPropertyNameValue(node, initialScope) { | |
const nameNode = node.type === "Property" ? node.key : node.property; | |
if (node.computed) { | |
return getStaticValueR(nameNode, initialScope) | |
} | |
if (nameNode.type === "Identifier") { | |
return { value: nameNode.name } | |
} | |
if (nameNode.type === "Literal") { | |
if (nameNode.bigint) { | |
return { value: nameNode.bigint } | |
} | |
return { value: String(nameNode.value) } | |
} | |
return null | |
} | |
/** | |
* Get the value of a given node if it's a static value. | |
* @param {Node} node The node to get. | |
* @param {Scope} [initialScope] The scope to start finding variable. Optional. If this scope was given, this tries to resolve identifier references which are in the given node as much as possible. | |
* @returns {{value:any}|{value:undefined,optional?:true}|null} The static value of the node, or `null`. | |
*/ | |
function getStaticValue(node, initialScope = null) { | |
try { | |
return getStaticValueR(node, initialScope) | |
} catch (_error) { | |
return null | |
} | |
} | |
/** | |
* Get the value of a given node if it's a literal or a template literal. | |
* @param {Node} node The node to get. | |
* @param {Scope} [initialScope] The scope to start finding variable. Optional. If the node is an Identifier node and this scope was given, this checks the variable of the identifier, and returns the value of it if the variable is a constant. | |
* @returns {string|null} The value of the node, or `null`. | |
*/ | |
function getStringIfConstant(node, initialScope = null) { | |
// Handle the literals that the platform doesn't support natively. | |
if (node && node.type === "Literal" && node.value === null) { | |
if (node.regex) { | |
return `/${node.regex.pattern}/${node.regex.flags}` | |
} | |
if (node.bigint) { | |
return node.bigint | |
} | |
} | |
const evaluated = getStaticValue(node, initialScope); | |
return evaluated && String(evaluated.value) | |
} | |
/** | |
* Get the property name from a MemberExpression node or a Property node. | |
* @param {Node} node The node to get. | |
* @param {Scope} [initialScope] The scope to start finding variable. Optional. If the node is a computed property node and this scope was given, this checks the computed property name by the `getStringIfConstant` function with the scope, and returns the value of it. | |
* @returns {string|null} The property name of the node. | |
*/ | |
function getPropertyName(node, initialScope) { | |
switch (node.type) { | |
case "MemberExpression": | |
if (node.computed) { | |
return getStringIfConstant(node.property, initialScope) | |
} | |
if (node.property.type === "PrivateIdentifier") { | |
return null | |
} | |
return node.property.name | |
case "Property": | |
case "MethodDefinition": | |
case "PropertyDefinition": | |
if (node.computed) { | |
return getStringIfConstant(node.key, initialScope) | |
} | |
if (node.key.type === "Literal") { | |
return String(node.key.value) | |
} | |
if (node.key.type === "PrivateIdentifier") { | |
return null | |
} | |
return node.key.name | |
// no default | |
} | |
return null | |
} | |
/** | |
* Get the name and kind of the given function node. | |
* @param {ASTNode} node - The function node to get. | |
* @param {SourceCode} [sourceCode] The source code object to get the code of computed property keys. | |
* @returns {string} The name and kind of the function node. | |
*/ | |
// eslint-disable-next-line complexity | |
function getFunctionNameWithKind(node, sourceCode) { | |
const parent = node.parent; | |
const tokens = []; | |
const isObjectMethod = parent.type === "Property" && parent.value === node; | |
const isClassMethod = | |
parent.type === "MethodDefinition" && parent.value === node; | |
const isClassFieldMethod = | |
parent.type === "PropertyDefinition" && parent.value === node; | |
// Modifiers. | |
if (isClassMethod || isClassFieldMethod) { | |
if (parent.static) { | |
tokens.push("static"); | |
} | |
if (parent.key.type === "PrivateIdentifier") { | |
tokens.push("private"); | |
} | |
} | |
if (node.async) { | |
tokens.push("async"); | |
} | |
if (node.generator) { | |
tokens.push("generator"); | |
} | |
// Kinds. | |
if (isObjectMethod || isClassMethod) { | |
if (parent.kind === "constructor") { | |
return "constructor" | |
} | |
if (parent.kind === "get") { | |
tokens.push("getter"); | |
} else if (parent.kind === "set") { | |
tokens.push("setter"); | |
} else { | |
tokens.push("method"); | |
} | |
} else if (isClassFieldMethod) { | |
tokens.push("method"); | |
} else { | |
if (node.type === "ArrowFunctionExpression") { | |
tokens.push("arrow"); | |
} | |
tokens.push("function"); | |
} | |
// Names. | |
if (isObjectMethod || isClassMethod || isClassFieldMethod) { | |
if (parent.key.type === "PrivateIdentifier") { | |
tokens.push(`#${parent.key.name}`); | |
} else { | |
const name = getPropertyName(parent); | |
if (name) { | |
tokens.push(`'${name}'`); | |
} else if (sourceCode) { | |
const keyText = sourceCode.getText(parent.key); | |
if (!keyText.includes("\n")) { | |
tokens.push(`[${keyText}]`); | |
} | |
} | |
} | |
} else if (node.id) { | |
tokens.push(`'${node.id.name}'`); | |
} else if ( | |
parent.type === "VariableDeclarator" && | |
parent.id && | |
parent.id.type === "Identifier" | |
) { | |
tokens.push(`'${parent.id.name}'`); | |
} else if ( | |
(parent.type === "AssignmentExpression" || | |
parent.type === "AssignmentPattern") && | |
parent.left && | |
parent.left.type === "Identifier" | |
) { | |
tokens.push(`'${parent.left.name}'`); | |
} | |
return tokens.join(" ") | |
} | |
const typeConversionBinaryOps = Object.freeze( | |
new Set([ | |
"==", | |
"!=", | |
"<", | |
"<=", | |
">", | |
">=", | |
"<<", | |
">>", | |
">>>", | |
"+", | |
"-", | |
"*", | |
"/", | |
"%", | |
"|", | |
"^", | |
"&", | |
"in", | |
]), | |
); | |
const typeConversionUnaryOps = Object.freeze(new Set(["-", "+", "!", "~"])); | |
/** | |
* Check whether the given value is an ASTNode or not. | |
* @param {any} x The value to check. | |
* @returns {boolean} `true` if the value is an ASTNode. | |
*/ | |
function isNode(x) { | |
return x !== null && typeof x === "object" && typeof x.type === "string" | |
} | |
const visitor = Object.freeze( | |
Object.assign(Object.create(null), { | |
$visit(node, options, visitorKeys) { | |
const { type } = node; | |
if (typeof this[type] === "function") { | |
return this[type](node, options, visitorKeys) | |
} | |
return this.$visitChildren(node, options, visitorKeys) | |
}, | |
$visitChildren(node, options, visitorKeys) { | |
const { type } = node; | |
for (const key of visitorKeys[type] || evk.getKeys(node)) { | |
const value = node[key]; | |
if (Array.isArray(value)) { | |
for (const element of value) { | |
if ( | |
isNode(element) && | |
this.$visit(element, options, visitorKeys) | |
) { | |
return true | |
} | |
} | |
} else if ( | |
isNode(value) && | |
this.$visit(value, options, visitorKeys) | |
) { | |
return true | |
} | |
} | |
return false | |
}, | |
ArrowFunctionExpression() { | |
return false | |
}, | |
AssignmentExpression() { | |
return true | |
}, | |
AwaitExpression() { | |
return true | |
}, | |
BinaryExpression(node, options, visitorKeys) { | |
if ( | |
options.considerImplicitTypeConversion && | |
typeConversionBinaryOps.has(node.operator) && | |
(node.left.type !== "Literal" || node.right.type !== "Literal") | |
) { | |
return true | |
} | |
return this.$visitChildren(node, options, visitorKeys) | |
}, | |
CallExpression() { | |
return true | |
}, | |
FunctionExpression() { | |
return false | |
}, | |
ImportExpression() { | |
return true | |
}, | |
MemberExpression(node, options, visitorKeys) { | |
if (options.considerGetters) { | |
return true | |
} | |
if ( | |
options.considerImplicitTypeConversion && | |
node.computed && | |
node.property.type !== "Literal" | |
) { | |
return true | |
} | |
return this.$visitChildren(node, options, visitorKeys) | |
}, | |
MethodDefinition(node, options, visitorKeys) { | |
if ( | |
options.considerImplicitTypeConversion && | |
node.computed && | |
node.key.type !== "Literal" | |
) { | |
return true | |
} | |
return this.$visitChildren(node, options, visitorKeys) | |
}, | |
NewExpression() { | |
return true | |
}, | |
Property(node, options, visitorKeys) { | |
if ( | |
options.considerImplicitTypeConversion && | |
node.computed && | |
node.key.type !== "Literal" | |
) { | |
return true | |
} | |
return this.$visitChildren(node, options, visitorKeys) | |
}, | |
PropertyDefinition(node, options, visitorKeys) { | |
if ( | |
options.considerImplicitTypeConversion && | |
node.computed && | |
node.key.type !== "Literal" | |
) { | |
return true | |
} | |
return this.$visitChildren(node, options, visitorKeys) | |
}, | |
UnaryExpression(node, options, visitorKeys) { | |
if (node.operator === "delete") { | |
return true | |
} | |
if ( | |
options.considerImplicitTypeConversion && | |
typeConversionUnaryOps.has(node.operator) && | |
node.argument.type !== "Literal" | |
) { | |
return true | |
} | |
return this.$visitChildren(node, options, visitorKeys) | |
}, | |
UpdateExpression() { | |
return true | |
}, | |
YieldExpression() { | |
return true | |
}, | |
}), | |
); | |
/** | |
* Check whether a given node has any side effect or not. | |
* @param {Node} node The node to get. | |
* @param {SourceCode} sourceCode The source code object. | |
* @param {object} [options] The option object. | |
* @param {boolean} [options.considerGetters=false] If `true` then it considers member accesses as the node which has side effects. | |
* @param {boolean} [options.considerImplicitTypeConversion=false] If `true` then it considers implicit type conversion as the node which has side effects. | |
* @param {object} [options.visitorKeys=evk.KEYS] The keys to traverse nodes. Use `context.getSourceCode().visitorKeys`. | |
* @returns {boolean} `true` if the node has a certain side effect. | |
*/ | |
function hasSideEffect( | |
node, | |
sourceCode, | |
{ considerGetters = false, considerImplicitTypeConversion = false } = {}, | |
) { | |
return visitor.$visit( | |
node, | |
{ considerGetters, considerImplicitTypeConversion }, | |
sourceCode.visitorKeys || evk.KEYS, | |
) | |
} | |
/** | |
* Get the left parenthesis of the parent node syntax if it exists. | |
* E.g., `if (a) {}` then the `(`. | |
* @param {Node} node The AST node to check. | |
* @param {SourceCode} sourceCode The source code object to get tokens. | |
* @returns {Token|null} The left parenthesis of the parent node syntax | |
*/ | |
function getParentSyntaxParen(node, sourceCode) { | |
const parent = node.parent; | |
switch (parent.type) { | |
case "CallExpression": | |
case "NewExpression": | |
if (parent.arguments.length === 1 && parent.arguments[0] === node) { | |
return sourceCode.getTokenAfter( | |
parent.callee, | |
isOpeningParenToken, | |
) | |
} | |
return null | |
case "DoWhileStatement": | |
if (parent.test === node) { | |
return sourceCode.getTokenAfter( | |
parent.body, | |
isOpeningParenToken, | |
) | |
} | |
return null | |
case "IfStatement": | |
case "WhileStatement": | |
if (parent.test === node) { | |
return sourceCode.getFirstToken(parent, 1) | |
} | |
return null | |
case "ImportExpression": | |
if (parent.source === node) { | |
return sourceCode.getFirstToken(parent, 1) | |
} | |
return null | |
case "SwitchStatement": | |
if (parent.discriminant === node) { | |
return sourceCode.getFirstToken(parent, 1) | |
} | |
return null | |
case "WithStatement": | |
if (parent.object === node) { | |
return sourceCode.getFirstToken(parent, 1) | |
} | |
return null | |
default: | |
return null | |
} | |
} | |
/** | |
* Check whether a given node is parenthesized or not. | |
* @param {number} times The number of parantheses. | |
* @param {Node} node The AST node to check. | |
* @param {SourceCode} sourceCode The source code object to get tokens. | |
* @returns {boolean} `true` if the node is parenthesized the given times. | |
*/ | |
/** | |
* Check whether a given node is parenthesized or not. | |
* @param {Node} node The AST node to check. | |
* @param {SourceCode} sourceCode The source code object to get tokens. | |
* @returns {boolean} `true` if the node is parenthesized. | |
*/ | |
function isParenthesized( | |
timesOrNode, | |
nodeOrSourceCode, | |
optionalSourceCode, | |
) { | |
let times, node, sourceCode, maybeLeftParen, maybeRightParen; | |
if (typeof timesOrNode === "number") { | |
times = timesOrNode | 0; | |
node = nodeOrSourceCode; | |
sourceCode = optionalSourceCode; | |
if (!(times >= 1)) { | |
throw new TypeError("'times' should be a positive integer.") | |
} | |
} else { | |
times = 1; | |
node = timesOrNode; | |
sourceCode = nodeOrSourceCode; | |
} | |
if ( | |
node == null || | |
// `CatchClause.param` can't be parenthesized, example `try {} catch (error) {}` | |
(node.parent.type === "CatchClause" && node.parent.param === node) | |
) { | |
return false | |
} | |
maybeLeftParen = maybeRightParen = node; | |
do { | |
maybeLeftParen = sourceCode.getTokenBefore(maybeLeftParen); | |
maybeRightParen = sourceCode.getTokenAfter(maybeRightParen); | |
} while ( | |
maybeLeftParen != null && | |
maybeRightParen != null && | |
isOpeningParenToken(maybeLeftParen) && | |
isClosingParenToken(maybeRightParen) && | |
// Avoid false positive such as `if (a) {}` | |
maybeLeftParen !== getParentSyntaxParen(node, sourceCode) && | |
--times > 0 | |
) | |
return times === 0 | |
} | |
/** | |
* @author Toru Nagashima <https://github.com/mysticatea> | |
* See LICENSE file in root directory for full license. | |
*/ | |
const placeholder = /\$(?:[$&`']|[1-9][0-9]?)/gu; | |
/** @type {WeakMap<PatternMatcher, {pattern:RegExp,escaped:boolean}>} */ | |
const internal = new WeakMap(); | |
/** | |
* Check whether a given character is escaped or not. | |
* @param {string} str The string to check. | |
* @param {number} index The location of the character to check. | |
* @returns {boolean} `true` if the character is escaped. | |
*/ | |
function isEscaped(str, index) { | |
let escaped = false; | |
for (let i = index - 1; i >= 0 && str.charCodeAt(i) === 0x5c; --i) { | |
escaped = !escaped; | |
} | |
return escaped | |
} | |
/** | |
* Replace a given string by a given matcher. | |
* @param {PatternMatcher} matcher The pattern matcher. | |
* @param {string} str The string to be replaced. | |
* @param {string} replacement The new substring to replace each matched part. | |
* @returns {string} The replaced string. | |
*/ | |
function replaceS(matcher, str, replacement) { | |
const chunks = []; | |
let index = 0; | |
/** @type {RegExpExecArray} */ | |
let match = null; | |
/** | |
* @param {string} key The placeholder. | |
* @returns {string} The replaced string. | |
*/ | |
function replacer(key) { | |
switch (key) { | |
case "$$": | |
return "$" | |
case "$&": | |
return match[0] | |
case "$`": | |
return str.slice(0, match.index) | |
case "$'": | |
return str.slice(match.index + match[0].length) | |
default: { | |
const i = key.slice(1); | |
if (i in match) { | |
return match[i] | |
} | |
return key | |
} | |
} | |
} | |
for (match of matcher.execAll(str)) { | |
chunks.push(str.slice(index, match.index)); | |
chunks.push(replacement.replace(placeholder, replacer)); | |
index = match.index + match[0].length; | |
} | |
chunks.push(str.slice(index)); | |
return chunks.join("") | |
} | |
/** | |
* Replace a given string by a given matcher. | |
* @param {PatternMatcher} matcher The pattern matcher. | |
* @param {string} str The string to be replaced. | |
* @param {(...strs[])=>string} replace The function to replace each matched part. | |
* @returns {string} The replaced string. | |
*/ | |
function replaceF(matcher, str, replace) { | |
const chunks = []; | |
let index = 0; | |
for (const match of matcher.execAll(str)) { | |
chunks.push(str.slice(index, match.index)); | |
chunks.push(String(replace(...match, match.index, match.input))); | |
index = match.index + match[0].length; | |
} | |
chunks.push(str.slice(index)); | |
return chunks.join("") | |
} | |
/** | |
* The class to find patterns as considering escape sequences. | |
*/ | |
class PatternMatcher { | |
/** | |
* Initialize this matcher. | |
* @param {RegExp} pattern The pattern to match. | |
* @param {{escaped:boolean}} options The options. | |
*/ | |
constructor(pattern, { escaped = false } = {}) { | |
if (!(pattern instanceof RegExp)) { | |
throw new TypeError("'pattern' should be a RegExp instance.") | |
} | |
if (!pattern.flags.includes("g")) { | |
throw new Error("'pattern' should contains 'g' flag.") | |
} | |
internal.set(this, { | |
pattern: new RegExp(pattern.source, pattern.flags), | |
escaped: Boolean(escaped), | |
}); | |
} | |
/** | |
* Find the pattern in a given string. | |
* @param {string} str The string to find. | |
* @returns {IterableIterator<RegExpExecArray>} The iterator which iterate the matched information. | |
*/ | |
*execAll(str) { | |
const { pattern, escaped } = internal.get(this); | |
let match = null; | |
let lastIndex = 0; | |
pattern.lastIndex = 0; | |
while ((match = pattern.exec(str)) != null) { | |
if (escaped || !isEscaped(str, match.index)) { | |
lastIndex = pattern.lastIndex; | |
yield match; | |
pattern.lastIndex = lastIndex; | |
} | |
} | |
} | |
/** | |
* Check whether the pattern is found in a given string. | |
* @param {string} str The string to check. | |
* @returns {boolean} `true` if the pattern was found in the string. | |
*/ | |
test(str) { | |
const it = this.execAll(str); | |
const ret = it.next(); | |
return !ret.done | |
} | |
/** | |
* Replace a given string. | |
* @param {string} str The string to be replaced. | |
* @param {(string|((...strs:string[])=>string))} replacer The string or function to replace. This is the same as the 2nd argument of `String.prototype.replace`. | |
* @returns {string} The replaced string. | |
*/ | |
[Symbol.replace](str, replacer) { | |
return typeof replacer === "function" | |
? replaceF(this, String(str), replacer) | |
: replaceS(this, String(str), String(replacer)) | |
} | |
} | |
const IMPORT_TYPE = /^(?:Import|Export(?:All|Default|Named))Declaration$/u; | |
const has = Function.call.bind(Object.hasOwnProperty); | |
const READ = Symbol("read"); | |
const CALL = Symbol("call"); | |
const CONSTRUCT = Symbol("construct"); | |
const ESM = Symbol("esm"); | |
const requireCall = { require: { [CALL]: true } }; | |
/** | |
* Check whether a given variable is modified or not. | |
* @param {Variable} variable The variable to check. | |
* @returns {boolean} `true` if the variable is modified. | |
*/ | |
function isModifiedGlobal(variable) { | |
return ( | |
variable == null || | |
variable.defs.length !== 0 || | |
variable.references.some((r) => r.isWrite()) | |
) | |
} | |
/** | |
* Check if the value of a given node is passed through to the parent syntax as-is. | |
* For example, `a` and `b` in (`a || b` and `c ? a : b`) are passed through. | |
* @param {Node} node A node to check. | |
* @returns {boolean} `true` if the node is passed through. | |
*/ | |
function isPassThrough(node) { | |
const parent = node.parent; | |
switch (parent && parent.type) { | |
case "ConditionalExpression": | |
return parent.consequent === node || parent.alternate === node | |
case "LogicalExpression": | |
return true | |
case "SequenceExpression": | |
return parent.expressions[parent.expressions.length - 1] === node | |
case "ChainExpression": | |
return true | |
default: | |
return false | |
} | |
} | |
/** | |
* The reference tracker. | |
*/ | |
class ReferenceTracker { | |
/** | |
* Initialize this tracker. | |
* @param {Scope} globalScope The global scope. | |
* @param {object} [options] The options. | |
* @param {"legacy"|"strict"} [options.mode="strict"] The mode to determine the ImportDeclaration's behavior for CJS modules. | |
* @param {string[]} [options.globalObjectNames=["global","globalThis","self","window"]] The variable names for Global Object. | |
*/ | |
constructor( | |
globalScope, | |
{ | |
mode = "strict", | |
globalObjectNames = ["global", "globalThis", "self", "window"], | |
} = {}, | |
) { | |
this.variableStack = []; | |
this.globalScope = globalScope; | |
this.mode = mode; | |
this.globalObjectNames = globalObjectNames.slice(0); | |
} | |
/** | |
* Iterate the references of global variables. | |
* @param {object} traceMap The trace map. | |
* @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references. | |
*/ | |
*iterateGlobalReferences(traceMap) { | |
for (const key of Object.keys(traceMap)) { | |
const nextTraceMap = traceMap[key]; | |
const path = [key]; | |
const variable = this.globalScope.set.get(key); | |
if (isModifiedGlobal(variable)) { | |
continue | |
} | |
yield* this._iterateVariableReferences( | |
variable, | |
path, | |
nextTraceMap, | |
true, | |
); | |
} | |
for (const key of this.globalObjectNames) { | |
const path = []; | |
const variable = this.globalScope.set.get(key); | |
if (isModifiedGlobal(variable)) { | |
continue | |
} | |
yield* this._iterateVariableReferences( | |
variable, | |
path, | |
traceMap, | |
false, | |
); | |
} | |
} | |
/** | |
* Iterate the references of CommonJS modules. | |
* @param {object} traceMap The trace map. | |
* @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references. | |
*/ | |
*iterateCjsReferences(traceMap) { | |
for (const { node } of this.iterateGlobalReferences(requireCall)) { | |
const key = getStringIfConstant(node.arguments[0]); | |
if (key == null || !has(traceMap, key)) { | |
continue | |
} | |
const nextTraceMap = traceMap[key]; | |
const path = [key]; | |
if (nextTraceMap[READ]) { | |
yield { | |
node, | |
path, | |
type: READ, | |
info: nextTraceMap[READ], | |
}; | |
} | |
yield* this._iteratePropertyReferences(node, path, nextTraceMap); | |
} | |
} | |
/** | |
* Iterate the references of ES modules. | |
* @param {object} traceMap The trace map. | |
* @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references. | |
*/ | |
*iterateEsmReferences(traceMap) { | |
const programNode = this.globalScope.block; | |
for (const node of programNode.body) { | |
if (!IMPORT_TYPE.test(node.type) || node.source == null) { | |
continue | |
} | |
const moduleId = node.source.value; | |
if (!has(traceMap, moduleId)) { | |
continue | |
} | |
const nextTraceMap = traceMap[moduleId]; | |
const path = [moduleId]; | |
if (nextTraceMap[READ]) { | |
yield { node, path, type: READ, info: nextTraceMap[READ] }; | |
} | |
if (node.type === "ExportAllDeclaration") { | |
for (const key of Object.keys(nextTraceMap)) { | |
const exportTraceMap = nextTraceMap[key]; | |
if (exportTraceMap[READ]) { | |
yield { | |
node, | |
path: path.concat(key), | |
type: READ, | |
info: exportTraceMap[READ], | |
}; | |
} | |
} | |
} else { | |
for (const specifier of node.specifiers) { | |
const esm = has(nextTraceMap, ESM); | |
const it = this._iterateImportReferences( | |
specifier, | |
path, | |
esm | |
? nextTraceMap | |
: this.mode === "legacy" | |
? { default: nextTraceMap, ...nextTraceMap } | |
: { default: nextTraceMap }, | |
); | |
if (esm) { | |
yield* it; | |
} else { | |
for (const report of it) { | |
report.path = report.path.filter(exceptDefault); | |
if ( | |
report.path.length >= 2 || | |
report.type !== READ | |
) { | |
yield report; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
/** | |
* Iterate the references for a given variable. | |
* @param {Variable} variable The variable to iterate that references. | |
* @param {string[]} path The current path. | |
* @param {object} traceMap The trace map. | |
* @param {boolean} shouldReport = The flag to report those references. | |
* @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references. | |
*/ | |
*_iterateVariableReferences(variable, path, traceMap, shouldReport) { | |
if (this.variableStack.includes(variable)) { | |
return | |
} | |
this.variableStack.push(variable); | |
try { | |
for (const reference of variable.references) { | |
if (!reference.isRead()) { | |
continue | |
} | |
const node = reference.identifier; | |
if (shouldReport && traceMap[READ]) { | |
yield { node, path, type: READ, info: traceMap[READ] }; | |
} | |
yield* this._iteratePropertyReferences(node, path, traceMap); | |
} | |
} finally { | |
this.variableStack.pop(); | |
} | |
} | |
/** | |
* Iterate the references for a given AST node. | |
* @param rootNode The AST node to iterate references. | |
* @param {string[]} path The current path. | |
* @param {object} traceMap The trace map. | |
* @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references. | |
*/ | |
//eslint-disable-next-line complexity | |
*_iteratePropertyReferences(rootNode, path, traceMap) { | |
let node = rootNode; | |
while (isPassThrough(node)) { | |
node = node.parent; | |
} | |
const parent = node.parent; | |
if (parent.type === "MemberExpression") { | |
if (parent.object === node) { | |
const key = getPropertyName(parent); | |
if (key == null || !has(traceMap, key)) { | |
return | |
} | |
path = path.concat(key); //eslint-disable-line no-param-reassign | |
const nextTraceMap = traceMap[key]; | |
if (nextTraceMap[READ]) { | |
yield { | |
node: parent, | |
path, | |
type: READ, | |
info: nextTraceMap[READ], | |
}; | |
} | |
yield* this._iteratePropertyReferences( | |
parent, | |
path, | |
nextTraceMap, | |
); | |
} | |
return | |
} | |
if (parent.type === "CallExpression") { | |
if (parent.callee === node && traceMap[CALL]) { | |
yield { node: parent, path, type: CALL, info: traceMap[CALL] }; | |
} | |
return | |
} | |
if (parent.type === "NewExpression") { | |
if (parent.callee === node && traceMap[CONSTRUCT]) { | |
yield { | |
node: parent, | |
path, | |
type: CONSTRUCT, | |
info: traceMap[CONSTRUCT], | |
}; | |
} | |
return | |
} | |
if (parent.type === "AssignmentExpression") { | |
if (parent.right === node) { | |
yield* this._iterateLhsReferences(parent.left, path, traceMap); | |
yield* this._iteratePropertyReferences(parent, path, traceMap); | |
} | |
return | |
} | |
if (parent.type === "AssignmentPattern") { | |
if (parent.right === node) { | |
yield* this._iterateLhsReferences(parent.left, path, traceMap); | |
} | |
return | |
} | |
if (parent.type === "VariableDeclarator") { | |
if (parent.init === node) { | |
yield* this._iterateLhsReferences(parent.id, path, traceMap); | |
} | |
} | |
} | |
/** | |
* Iterate the references for a given Pattern node. | |
* @param {Node} patternNode The Pattern node to iterate references. | |
* @param {string[]} path The current path. | |
* @param {object} traceMap The trace map. | |
* @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references. | |
*/ | |
*_iterateLhsReferences(patternNode, path, traceMap) { | |
if (patternNode.type === "Identifier") { | |
const variable = findVariable(this.globalScope, patternNode); | |
if (variable != null) { | |
yield* this._iterateVariableReferences( | |
variable, | |
path, | |
traceMap, | |
false, | |
); | |
} | |
return | |
} | |
if (patternNode.type === "ObjectPattern") { | |
for (const property of patternNode.properties) { | |
const key = getPropertyName(property); | |
if (key == null || !has(traceMap, key)) { | |
continue | |
} | |
const nextPath = path.concat(key); | |
const nextTraceMap = traceMap[key]; | |
if (nextTraceMap[READ]) { | |
yield { | |
node: property, | |
path: nextPath, | |
type: READ, | |
info: nextTraceMap[READ], | |
}; | |
} | |
yield* this._iterateLhsReferences( | |
property.value, | |
nextPath, | |
nextTraceMap, | |
); | |
} | |
return | |
} | |
if (patternNode.type === "AssignmentPattern") { | |
yield* this._iterateLhsReferences(patternNode.left, path, traceMap); | |
} | |
} | |
/** | |
* Iterate the references for a given ModuleSpecifier node. | |
* @param {Node} specifierNode The ModuleSpecifier node to iterate references. | |
* @param {string[]} path The current path. | |
* @param {object} traceMap The trace map. | |
* @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references. | |
*/ | |
*_iterateImportReferences(specifierNode, path, traceMap) { | |
const type = specifierNode.type; | |
if (type === "ImportSpecifier" || type === "ImportDefaultSpecifier") { | |
const key = | |
type === "ImportDefaultSpecifier" | |
? "default" | |
: specifierNode.imported.name; | |
if (!has(traceMap, key)) { | |
return | |
} | |
path = path.concat(key); //eslint-disable-line no-param-reassign | |
const nextTraceMap = traceMap[key]; | |
if (nextTraceMap[READ]) { | |
yield { | |
node: specifierNode, | |
path, | |
type: READ, | |
info: nextTraceMap[READ], | |
}; | |
} | |
yield* this._iterateVariableReferences( | |
findVariable(this.globalScope, specifierNode.local), | |
path, | |
nextTraceMap, | |
false, | |
); | |
return | |
} | |
if (type === "ImportNamespaceSpecifier") { | |
yield* this._iterateVariableReferences( | |
findVariable(this.globalScope, specifierNode.local), | |
path, | |
traceMap, | |
false, | |
); | |
return | |
} | |
if (type === "ExportSpecifier") { | |
const key = specifierNode.local.name; | |
if (!has(traceMap, key)) { | |
return | |
} | |
path = path.concat(key); //eslint-disable-line no-param-reassign | |
const nextTraceMap = traceMap[key]; | |
if (nextTraceMap[READ]) { | |
yield { | |
node: specifierNode, | |
path, | |
type: READ, | |
info: nextTraceMap[READ], | |
}; | |
} | |
} | |
} | |
} | |
ReferenceTracker.READ = READ; | |
ReferenceTracker.CALL = CALL; | |
ReferenceTracker.CONSTRUCT = CONSTRUCT; | |
ReferenceTracker.ESM = ESM; | |
/** | |
* This is a predicate function for Array#filter. | |
* @param {string} name A name part. | |
* @param {number} index The index of the name. | |
* @returns {boolean} `false` if it's default. | |
*/ | |
function exceptDefault(name, index) { | |
return !(index === 1 && name === "default") | |
} | |
var index = { | |
CALL, | |
CONSTRUCT, | |
ESM, | |
findVariable, | |
getFunctionHeadLocation, | |
getFunctionNameWithKind, | |
getInnermostScope, | |
getPropertyName, | |
getStaticValue, | |
getStringIfConstant, | |
hasSideEffect, | |
isArrowToken, | |
isClosingBraceToken, | |
isClosingBracketToken, | |
isClosingParenToken, | |
isColonToken, | |
isCommaToken, | |
isCommentToken, | |
isNotArrowToken, | |
isNotClosingBraceToken, | |
isNotClosingBracketToken, | |
isNotClosingParenToken, | |
isNotColonToken, | |
isNotCommaToken, | |
isNotCommentToken, | |
isNotOpeningBraceToken, | |
isNotOpeningBracketToken, | |
isNotOpeningParenToken, | |
isNotSemicolonToken, | |
isOpeningBraceToken, | |
isOpeningBracketToken, | |
isOpeningParenToken, | |
isParenthesized, | |
isSemicolonToken, | |
PatternMatcher, | |
READ, | |
ReferenceTracker, | |
}; | |
exports.CALL = CALL; | |
exports.CONSTRUCT = CONSTRUCT; | |
exports.ESM = ESM; | |
exports.PatternMatcher = PatternMatcher; | |
exports.READ = READ; | |
exports.ReferenceTracker = ReferenceTracker; | |
exports["default"] = index; | |
exports.findVariable = findVariable; | |
exports.getFunctionHeadLocation = getFunctionHeadLocation; | |
exports.getFunctionNameWithKind = getFunctionNameWithKind; | |
exports.getInnermostScope = getInnermostScope; | |
exports.getPropertyName = getPropertyName; | |
exports.getStaticValue = getStaticValue; | |
exports.getStringIfConstant = getStringIfConstant; | |
exports.hasSideEffect = hasSideEffect; | |
exports.isArrowToken = isArrowToken; | |
exports.isClosingBraceToken = isClosingBraceToken; | |
exports.isClosingBracketToken = isClosingBracketToken; | |
exports.isClosingParenToken = isClosingParenToken; | |
exports.isColonToken = isColonToken; | |
exports.isCommaToken = isCommaToken; | |
exports.isCommentToken = isCommentToken; | |
exports.isNotArrowToken = isNotArrowToken; | |
exports.isNotClosingBraceToken = isNotClosingBraceToken; | |
exports.isNotClosingBracketToken = isNotClosingBracketToken; | |
exports.isNotClosingParenToken = isNotClosingParenToken; | |
exports.isNotColonToken = isNotColonToken; | |
exports.isNotCommaToken = isNotCommaToken; | |
exports.isNotCommentToken = isNotCommentToken; | |
exports.isNotOpeningBraceToken = isNotOpeningBraceToken; | |
exports.isNotOpeningBracketToken = isNotOpeningBracketToken; | |
exports.isNotOpeningParenToken = isNotOpeningParenToken; | |
exports.isNotSemicolonToken = isNotSemicolonToken; | |
exports.isOpeningBraceToken = isOpeningBraceToken; | |
exports.isOpeningBracketToken = isOpeningBracketToken; | |
exports.isOpeningParenToken = isOpeningParenToken; | |
exports.isParenthesized = isParenthesized; | |
exports.isSemicolonToken = isSemicolonToken; | |
//# sourceMappingURL=index.js.map | |
/***/ }), | |
/***/ 8727: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @author Toru Nagashima <https://github.com/mysticatea> | |
* See LICENSE file in root directory for full license. | |
*/ | |
const KEYS = __webpack_require__(342); | |
// Types. | |
const NODE_TYPES = Object.freeze(Object.keys(KEYS)); | |
// Freeze the keys. | |
for (const type of NODE_TYPES) { | |
Object.freeze(KEYS[type]); | |
} | |
Object.freeze(KEYS); | |
// List to ignore keys. | |
const KEY_BLACKLIST = new Set([ | |
"parent", | |
"leadingComments", | |
"trailingComments" | |
]); | |
/** | |
* Check whether a given key should be used or not. | |
* @param {string} key The key to check. | |
* @returns {boolean} `true` if the key should be used. | |
*/ | |
function filterKey(key) { | |
return !KEY_BLACKLIST.has(key) && key[0] !== "_"; | |
} | |
//------------------------------------------------------------------------------ | |
// Public interfaces | |
//------------------------------------------------------------------------------ | |
module.exports = Object.freeze({ | |
/** | |
* Visitor keys. | |
* @type {{ [type: string]: string[] | undefined }} | |
*/ | |
KEYS, | |
/** | |
* Get visitor keys of a given node. | |
* @param {Object} node The AST node to get keys. | |
* @returns {string[]} Visitor keys of the node. | |
*/ | |
getKeys(node) { | |
return Object.keys(node).filter(filterKey); | |
}, | |
// Disable valid-jsdoc rule because it reports syntax error on the type of @returns. | |
// eslint-disable-next-line valid-jsdoc | |
/** | |
* Make the union set with `KEYS` and given keys. | |
* @param {Object} additionalKeys The additional keys. | |
* @returns {{ [type: string]: string[] | undefined }} The union set. | |
*/ | |
unionWith(additionalKeys) { | |
const retv = Object.assign({}, KEYS); | |
for (const type of Object.keys(additionalKeys)) { | |
if (retv.hasOwnProperty(type)) { | |
const keys = new Set(additionalKeys[type]); | |
for (const key of retv[type]) { | |
keys.add(key); | |
} | |
retv[type] = Object.freeze(Array.from(keys)); | |
} else { | |
retv[type] = Object.freeze(Array.from(additionalKeys[type])); | |
} | |
} | |
return Object.freeze(retv); | |
} | |
}); | |
/***/ }), | |
/***/ 1297: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @fileoverview Config to enable all rules. | |
* @author Robert Fletcher | |
*/ | |
//------------------------------------------------------------------------------ | |
// Requirements | |
//------------------------------------------------------------------------------ | |
const builtInRules = __webpack_require__(9514); | |
//------------------------------------------------------------------------------ | |
// Helpers | |
//------------------------------------------------------------------------------ | |
const allRules = {}; | |
for (const [ruleId, rule] of builtInRules) { | |
if (!rule.meta.deprecated) { | |
allRules[ruleId] = "error"; | |
} | |
} | |
//------------------------------------------------------------------------------ | |
// Public Interface | |
//------------------------------------------------------------------------------ | |
/** @type {import("../lib/shared/types").ConfigData} */ | |
module.exports = { rules: allRules }; | |
/***/ }), | |
/***/ 7670: | |
/***/ (function(module) { | |
"use strict"; | |
/** | |
* @fileoverview Configuration applied when a user configuration extends from | |
* eslint:recommended. | |
* @author Nicholas C. Zakas | |
*/ | |
/* eslint sort-keys: ["error", "asc"] -- Long, so make more readable */ | |
/** @type {import("../lib/shared/types").ConfigData} */ | |
module.exports = { | |
rules: { | |
"constructor-super": "error", | |
"for-direction": "error", | |
"getter-return": "error", | |
"no-async-promise-executor": "error", | |
"no-case-declarations": "error", | |
"no-class-assign": "error", | |
"no-compare-neg-zero": "error", | |
"no-cond-assign": "error", | |
"no-const-assign": "error", | |
"no-constant-condition": "error", | |
"no-control-regex": "error", | |
"no-debugger": "error", | |
"no-delete-var": "error", | |
"no-dupe-args": "error", | |
"no-dupe-class-members": "error", | |
"no-dupe-else-if": "error", | |
"no-dupe-keys": "error", | |
"no-duplicate-case": "error", | |
"no-empty": "error", | |
"no-empty-character-class": "error", | |
"no-empty-pattern": "error", | |
"no-ex-assign": "error", | |
"no-extra-boolean-cast": "error", | |
"no-extra-semi": "error", | |
"no-fallthrough": "error", | |
"no-func-assign": "error", | |
"no-global-assign": "error", | |
"no-import-assign": "error", | |
"no-inner-declarations": "error", | |
"no-invalid-regexp": "error", | |
"no-irregular-whitespace": "error", | |
"no-loss-of-precision": "error", | |
"no-misleading-character-class": "error", | |
"no-mixed-spaces-and-tabs": "error", | |
"no-new-symbol": "error", | |
"no-nonoctal-decimal-escape": "error", | |
"no-obj-calls": "error", | |
"no-octal": "error", | |
"no-prototype-builtins": "error", | |
"no-redeclare": "error", | |
"no-regex-spaces": "error", | |
"no-self-assign": "error", | |
"no-setter-return": "error", | |
"no-shadow-restricted-names": "error", | |
"no-sparse-arrays": "error", | |
"no-this-before-super": "error", | |
"no-undef": "error", | |
"no-unexpected-multiline": "error", | |
"no-unreachable": "error", | |
"no-unsafe-finally": "error", | |
"no-unsafe-negation": "error", | |
"no-unsafe-optional-chaining": "error", | |
"no-unused-labels": "error", | |
"no-unused-vars": "error", | |
"no-useless-backreference": "error", | |
"no-useless-catch": "error", | |
"no-useless-escape": "error", | |
"no-with": "error", | |
"require-yield": "error", | |
"use-isnan": "error", | |
"valid-typeof": "error" | |
} | |
}; | |
/***/ }), | |
/***/ 2478: | |
/***/ (function(module) { | |
"use strict"; | |
/** | |
* @fileoverview Globals for ecmaVersion/sourceType | |
* @author Nicholas C. Zakas | |
*/ | |
//----------------------------------------------------------------------------- | |
// Globals | |
//----------------------------------------------------------------------------- | |
const commonjs = { | |
exports: true, | |
global: false, | |
module: false, | |
require: false | |
}; | |
const es3 = { | |
Array: false, | |
Boolean: false, | |
constructor: false, | |
Date: false, | |
decodeURI: false, | |
decodeURIComponent: false, | |
encodeURI: false, | |
encodeURIComponent: false, | |
Error: false, | |
escape: false, | |
eval: false, | |
EvalError: false, | |
Function: false, | |
hasOwnProperty: false, | |
Infinity: false, | |
isFinite: false, | |
isNaN: false, | |
isPrototypeOf: false, | |
Math: false, | |
NaN: false, | |
Number: false, | |
Object: false, | |
parseFloat: false, | |
parseInt: false, | |
propertyIsEnumerable: false, | |
RangeError: false, | |
ReferenceError: false, | |
RegExp: false, | |
String: false, | |
SyntaxError: false, | |
toLocaleString: false, | |
toString: false, | |
TypeError: false, | |
undefined: false, | |
unescape: false, | |
URIError: false, | |
valueOf: false | |
}; | |
const es5 = { | |
...es3, | |
JSON: false | |
}; | |
const es2015 = { | |
...es5, | |
ArrayBuffer: false, | |
DataView: false, | |
Float32Array: false, | |
Float64Array: false, | |
Int16Array: false, | |
Int32Array: false, | |
Int8Array: false, | |
Map: false, | |
Promise: false, | |
Proxy: false, | |
Reflect: false, | |
Set: false, | |
Symbol: false, | |
Uint16Array: false, | |
Uint32Array: false, | |
Uint8Array: false, | |
Uint8ClampedArray: false, | |
WeakMap: false, | |
WeakSet: false | |
}; | |
// no new globals in ES2016 | |
const es2016 = { | |
...es2015 | |
}; | |
const es2017 = { | |
...es2016, | |
Atomics: false, | |
SharedArrayBuffer: false | |
}; | |
// no new globals in ES2018 | |
const es2018 = { | |
...es2017 | |
}; | |
// no new globals in ES2019 | |
const es2019 = { | |
...es2018 | |
}; | |
const es2020 = { | |
...es2019, | |
BigInt: false, | |
BigInt64Array: false, | |
BigUint64Array: false, | |
globalThis: false | |
}; | |
const es2021 = { | |
...es2020, | |
AggregateError: false, | |
FinalizationRegistry: false, | |
WeakRef: false | |
}; | |
const es2022 = { | |
...es2021 | |
}; | |
//----------------------------------------------------------------------------- | |
// Exports | |
//----------------------------------------------------------------------------- | |
module.exports = { | |
commonjs, | |
es3, | |
es5, | |
es2015, | |
es2016, | |
es2017, | |
es2018, | |
es2019, | |
es2020, | |
es2021, | |
es2022 | |
}; | |
/***/ }), | |
/***/ 2702: | |
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @fileoverview Default configuration | |
* @author Nicholas C. Zakas | |
*/ | |
//----------------------------------------------------------------------------- | |
// Requirements | |
//----------------------------------------------------------------------------- | |
const Rules = __webpack_require__(9514); | |
//----------------------------------------------------------------------------- | |
// Helpers | |
//----------------------------------------------------------------------------- | |
exports.defaultConfig = [ | |
{ | |
plugins: { | |
"@": { | |
parsers: { | |
espree: __webpack_require__(3962) | |
}, | |
/* | |
* Because we try to delay loading rules until absolutely | |
* necessary, a proxy allows us to hook into the lazy-loading | |
* aspect of the rules map while still keeping all of the | |
* relevant configuration inside of the config array. | |
*/ | |
rules: new Proxy({}, { | |
get(target, property) { | |
return Rules.get(property); | |
}, | |
has(target, property) { | |
return Rules.has(property); | |
} | |
}) | |
} | |
}, | |
ignores: [ | |
"**/node_modules/**", | |
".git/**" | |
], | |
languageOptions: { | |
ecmaVersion: "latest", | |
sourceType: "module", | |
parser: "@/espree", | |
parserOptions: {} | |
} | |
}, | |
{ | |
files: ["**/*.cjs"], | |
languageOptions: { | |
sourceType: "commonjs" | |
} | |
} | |
]; | |
/***/ }), | |
/***/ 2996: | |
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @fileoverview Flat Config Array | |
* @author Nicholas C. Zakas | |
*/ | |
//----------------------------------------------------------------------------- | |
// Requirements | |
//----------------------------------------------------------------------------- | |
const { ConfigArray, ConfigArraySymbol } = __webpack_require__(1145); | |
const { flatConfigSchema } = __webpack_require__(9972); | |
const { RuleValidator } = __webpack_require__(2297); | |
const { defaultConfig } = __webpack_require__(2702); | |
const recommendedConfig = __webpack_require__(7670); | |
const allConfig = __webpack_require__(1297); | |
//----------------------------------------------------------------------------- | |
// Helpers | |
//----------------------------------------------------------------------------- | |
const ruleValidator = new RuleValidator(); | |
/** | |
* Splits a plugin identifier in the form a/b/c into two parts: a/b and c. | |
* @param {string} identifier The identifier to parse. | |
* @returns {{objectName: string, pluginName: string}} The parts of the plugin | |
* name. | |
*/ | |
function splitPluginIdentifier(identifier) { | |
const parts = identifier.split("/"); | |
return { | |
objectName: parts.pop(), | |
pluginName: parts.join("/") | |
}; | |
} | |
//----------------------------------------------------------------------------- | |
// Exports | |
//----------------------------------------------------------------------------- | |
/** | |
* Represents an array containing configuration information for ESLint. | |
*/ | |
class FlatConfigArray extends ConfigArray { | |
/** | |
* Creates a new instance. | |
* @param {*[]} configs An array of configuration information. | |
* @param {{basePath: string, baseConfig: FlatConfig}} options The options | |
* to use for the config array instance. | |
*/ | |
constructor(configs, { basePath, baseConfig = defaultConfig } = {}) { | |
super(configs, { | |
basePath, | |
schema: flatConfigSchema | |
}); | |
this.unshift(...baseConfig); | |
} | |
/* eslint-disable class-methods-use-this -- Desired as instance method */ | |
/** | |
* Replaces a config with another config to allow us to put strings | |
* in the config array that will be replaced by objects before | |
* normalization. | |
* @param {Object} config The config to preprocess. | |
* @returns {Object} The preprocessed config. | |
*/ | |
[ConfigArraySymbol.preprocessConfig](config) { | |
if (config === "eslint:recommended") { | |
return recommendedConfig; | |
} | |
if (config === "eslint:all") { | |
return allConfig; | |
} | |
return config; | |
} | |
/** | |
* Finalizes the config by replacing plugin references with their objects | |
* and validating rule option schemas. | |
* @param {Object} config The config to finalize. | |
* @returns {Object} The finalized config. | |
* @throws {TypeError} If the config is invalid. | |
*/ | |
[ConfigArraySymbol.finalizeConfig](config) { | |
const { plugins, languageOptions, processor } = config; | |
// Check parser value | |
if (languageOptions && languageOptions.parser && typeof languageOptions.parser === "string") { | |
const { pluginName, objectName: parserName } = splitPluginIdentifier(languageOptions.parser); | |
if (!plugins || !plugins[pluginName] || !plugins[pluginName].parsers || !plugins[pluginName].parsers[parserName]) { | |
throw new TypeError(`Key "parser": Could not find "${parserName}" in plugin "${pluginName}".`); | |
} | |
languageOptions.parser = plugins[pluginName].parsers[parserName]; | |
} | |
// Check processor value | |
if (processor && typeof processor === "string") { | |
const { pluginName, objectName: processorName } = splitPluginIdentifier(processor); | |
if (!plugins || !plugins[pluginName] || !plugins[pluginName].processors || !plugins[pluginName].processors[processorName]) { | |
throw new TypeError(`Key "processor": Could not find "${processorName}" in plugin "${pluginName}".`); | |
} | |
config.processor = plugins[pluginName].processors[processorName]; | |
} | |
ruleValidator.validate(config); | |
return config; | |
} | |
/* eslint-enable class-methods-use-this -- Desired as instance method */ | |
} | |
exports.FlatConfigArray = FlatConfigArray; | |
/***/ }), | |
/***/ 4730: | |
/***/ (function(module) { | |
"use strict"; | |
/** | |
* @fileoverview Shared functions to work with configs. | |
* @author Nicholas C. Zakas | |
*/ | |
//----------------------------------------------------------------------------- | |
// Functions | |
//----------------------------------------------------------------------------- | |
/** | |
* Parses a ruleId into its plugin and rule parts. | |
* @param {string} ruleId The rule ID to parse. | |
* @returns {{pluginName:string,ruleName:string}} The plugin and rule | |
* parts of the ruleId; | |
*/ | |
function parseRuleId(ruleId) { | |
let pluginName, ruleName; | |
// distinguish between core rules and plugin rules | |
if (ruleId.includes("/")) { | |
pluginName = ruleId.slice(0, ruleId.lastIndexOf("/")); | |
ruleName = ruleId.slice(pluginName.length + 1); | |
} else { | |
pluginName = "@"; | |
ruleName = ruleId; | |
} | |
return { | |
pluginName, | |
ruleName | |
}; | |
} | |
/** | |
* Retrieves a rule instance from a given config based on the ruleId. | |
* @param {string} ruleId The rule ID to look for. | |
* @param {FlatConfig} config The config to search. | |
* @returns {import("../shared/types").Rule|undefined} The rule if found | |
* or undefined if not. | |
*/ | |
function getRuleFromConfig(ruleId, config) { | |
const { pluginName, ruleName } = parseRuleId(ruleId); | |
const plugin = config.plugins && config.plugins[pluginName]; | |
let rule = plugin && plugin.rules && plugin.rules[ruleName]; | |
// normalize function rules into objects | |
if (rule && typeof rule === "function") { | |
rule = { | |
create: rule | |
}; | |
} | |
return rule; | |
} | |
//----------------------------------------------------------------------------- | |
// Exports | |
//----------------------------------------------------------------------------- | |
module.exports = { | |
parseRuleId, | |
getRuleFromConfig | |
}; | |
/***/ }), | |
/***/ 9972: | |
/***/ (function(__unused_webpack_module, exports) { | |
"use strict"; | |
/** | |
* @fileoverview Flat config schema | |
* @author Nicholas C. Zakas | |
*/ | |
//----------------------------------------------------------------------------- | |
// Type Definitions | |
//----------------------------------------------------------------------------- | |
/** | |
* @typedef ObjectPropertySchema | |
* @property {Function|string} merge The function or name of the function to call | |
* to merge multiple objects with this property. | |
* @property {Function|string} validate The function or name of the function to call | |
* to validate the value of this property. | |
*/ | |
//----------------------------------------------------------------------------- | |
// Helpers | |
//----------------------------------------------------------------------------- | |
const ruleSeverities = new Map([ | |
[0, 0], ["off", 0], | |
[1, 1], ["warn", 1], | |
[2, 2], ["error", 2] | |
]); | |
const globalVariablesValues = new Set([ | |
true, "true", "writable", "writeable", | |
false, "false", "readonly", "readable", null, | |
"off" | |
]); | |
/** | |
* Check if a value is a non-null object. | |
* @param {any} value The value to check. | |
* @returns {boolean} `true` if the value is a non-null object. | |
*/ | |
function isNonNullObject(value) { | |
return typeof value === "object" && value !== null; | |
} | |
/** | |
* Check if a value is undefined. | |
* @param {any} value The value to check. | |
* @returns {boolean} `true` if the value is undefined. | |
*/ | |
function isUndefined(value) { | |
return typeof value === "undefined"; | |
} | |
/** | |
* Deeply merges two objects. | |
* @param {Object} first The base object. | |
* @param {Object} second The overrides object. | |
* @returns {Object} An object with properties from both first and second. | |
*/ | |
function deepMerge(first = {}, second = {}) { | |
/* | |
* If the second value is an array, just return it. We don't merge | |
* arrays because order matters and we can't know the correct order. | |
*/ | |
if (Array.isArray(second)) { | |
return second; | |
} | |
/* | |
* First create a result object where properties from the second object | |
* overwrite properties from the first. This sets up a baseline to use | |
* later rather than needing to inspect and change every property | |
* individually. | |
*/ | |
const result = { | |
...first, | |
...second | |
}; | |
for (const key of Object.keys(second)) { | |
// avoid hairy edge case | |
if (key === "__proto__") { | |
continue; | |
} | |
const firstValue = first[key]; | |
const secondValue = second[key]; | |
if (isNonNullObject(firstValue)) { | |
result[key] = deepMerge(firstValue, secondValue); | |
} else if (isUndefined(firstValue)) { | |
if (isNonNullObject(secondValue)) { | |
result[key] = deepMerge( | |
Array.isArray(secondValue) ? [] : {}, | |
secondValue | |
); | |
} else if (!isUndefined(secondValue)) { | |
result[key] = secondValue; | |
} | |
} | |
} | |
return result; | |
} | |
/** | |
* Normalizes the rule options config for a given rule by ensuring that | |
* it is an array and that the first item is 0, 1, or 2. | |
* @param {Array|string|number} ruleOptions The rule options config. | |
* @returns {Array} An array of rule options. | |
*/ | |
function normalizeRuleOptions(ruleOptions) { | |
const finalOptions = Array.isArray(ruleOptions) | |
? ruleOptions.slice(0) | |
: [ruleOptions]; | |
finalOptions[0] = ruleSeverities.get(finalOptions[0]); | |
return finalOptions; | |
} | |
//----------------------------------------------------------------------------- | |
// Assertions | |
//----------------------------------------------------------------------------- | |
/** | |
* Validates that a value is a valid rule options entry. | |
* @param {any} value The value to check. | |
* @returns {void} | |
* @throws {TypeError} If the value isn't a valid rule options. | |
*/ | |
function assertIsRuleOptions(value) { | |
if (typeof value !== "string" && typeof value !== "number" && !Array.isArray(value)) { | |
throw new TypeError("Expected a string, number, or array."); | |
} | |
} | |
/** | |
* Validates that a value is valid rule severity. | |
* @param {any} value The value to check. | |
* @returns {void} | |
* @throws {TypeError} If the value isn't a valid rule severity. | |
*/ | |
function assertIsRuleSeverity(value) { | |
const severity = typeof value === "string" | |
? ruleSeverities.get(value.toLowerCase()) | |
: ruleSeverities.get(value); | |
if (typeof severity === "undefined") { | |
throw new TypeError("Expected severity of \"off\", 0, \"warn\", 1, \"error\", or 2."); | |
} | |
} | |
/** | |
* Validates that a given string is the form pluginName/objectName. | |
* @param {string} value The string to check. | |
* @returns {void} | |
* @throws {TypeError} If the string isn't in the correct format. | |
*/ | |
function assertIsPluginMemberName(value) { | |
if (!/[@a-z0-9-_$]+(?:\/(?:[a-z0-9-_$]+))+$/iu.test(value)) { | |
throw new TypeError(`Expected string in the form "pluginName/objectName" but found "${value}".`); | |
} | |
} | |
/** | |
* Validates that a value is an object. | |
* @param {any} value The value to check. | |
* @returns {void} | |
* @throws {TypeError} If the value isn't an object. | |
*/ | |
function assertIsObject(value) { | |
if (!isNonNullObject(value)) { | |
throw new TypeError("Expected an object."); | |
} | |
} | |
/** | |
* Validates that a value is an object or a string. | |
* @param {any} value The value to check. | |
* @returns {void} | |
* @throws {TypeError} If the value isn't an object or a string. | |
*/ | |
function assertIsObjectOrString(value) { | |
if ((!value || typeof value !== "object") && typeof value !== "string") { | |
throw new TypeError("Expected an object or string."); | |
} | |
} | |
//----------------------------------------------------------------------------- | |
// Low-Level Schemas | |
//----------------------------------------------------------------------------- | |
/** @type {ObjectPropertySchema} */ | |
const booleanSchema = { | |
merge: "replace", | |
validate: "boolean" | |
}; | |
/** @type {ObjectPropertySchema} */ | |
const deepObjectAssignSchema = { | |
merge(first = {}, second = {}) { | |
return deepMerge(first, second); | |
}, | |
validate: "object" | |
}; | |
//----------------------------------------------------------------------------- | |
// High-Level Schemas | |
//----------------------------------------------------------------------------- | |
/** @type {ObjectPropertySchema} */ | |
const globalsSchema = { | |
merge: "assign", | |
validate(value) { | |
assertIsObject(value); | |
for (const key of Object.keys(value)) { | |
// avoid hairy edge case | |
if (key === "__proto__") { | |
continue; | |
} | |
if (key !== key.trim()) { | |
throw new TypeError(`Global "${key}" has leading or trailing whitespace.`); | |
} | |
if (!globalVariablesValues.has(value[key])) { | |
throw new TypeError(`Key "${key}": Expected "readonly", "writable", or "off".`); | |
} | |
} | |
} | |
}; | |
/** @type {ObjectPropertySchema} */ | |
const parserSchema = { | |
merge: "replace", | |
validate(value) { | |
assertIsObjectOrString(value); | |
if (typeof value === "object" && typeof value.parse !== "function" && typeof value.parseForESLint !== "function") { | |
throw new TypeError("Expected object to have a parse() or parseForESLint() method."); | |
} | |
if (typeof value === "string") { | |
assertIsPluginMemberName(value); | |
} | |
} | |
}; | |
/** @type {ObjectPropertySchema} */ | |
const pluginsSchema = { | |
merge(first = {}, second = {}) { | |
const keys = new Set([...Object.keys(first), ...Object.keys(second)]); | |
const result = {}; | |
// manually validate that plugins are not redefined | |
for (const key of keys) { | |
// avoid hairy edge case | |
if (key === "__proto__") { | |
continue; | |
} | |
if (key in first && key in second && first[key] !== second[key]) { | |
throw new TypeError(`Cannot redefine plugin "${key}".`); | |
} | |
result[key] = second[key] || first[key]; | |
} | |
return result; | |
}, | |
validate(value) { | |
// first check the value to be sure it's an object | |
if (value === null || typeof value !== "object") { | |
throw new TypeError("Expected an object."); | |
} | |
// second check the keys to make sure they are objects | |
for (const key of Object.keys(value)) { | |
// avoid hairy edge case | |
if (key === "__proto__") { | |
continue; | |
} | |
if (value[key] === null || typeof value[key] !== "object") { | |
throw new TypeError(`Key "${key}": Expected an object.`); | |
} | |
} | |
} | |
}; | |
/** @type {ObjectPropertySchema} */ | |
const processorSchema = { | |
merge: "replace", | |
validate(value) { | |
if (typeof value === "string") { | |
assertIsPluginMemberName(value); | |
} else if (value && typeof value === "object") { | |
if (typeof value.preprocess !== "function" || typeof value.postprocess !== "function") { | |
throw new TypeError("Object must have a preprocess() and a postprocess() method."); | |
} | |
} else { | |
throw new TypeError("Expected an object or a string."); | |
} | |
} | |
}; | |
/** @type {ObjectPropertySchema} */ | |
const rulesSchema = { | |
merge(first = {}, second = {}) { | |
const result = { | |
...first, | |
...second | |
}; | |
for (const ruleId of Object.keys(result)) { | |
// avoid hairy edge case | |
if (ruleId === "__proto__") { | |
/* eslint-disable-next-line no-proto -- Though deprecated, may still be present */ | |
delete result.__proto__; | |
continue; | |
} | |
result[ruleId] = normalizeRuleOptions(result[ruleId]); | |
/* | |
* If either rule config is missing, then the correct | |
* config is already present and we just need to normalize | |
* the severity. | |
*/ | |
if (!(ruleId in first) || !(ruleId in second)) { | |
continue; | |
} | |
const firstRuleOptions = normalizeRuleOptions(first[ruleId]); | |
const secondRuleOptions = normalizeRuleOptions(second[ruleId]); | |
/* | |
* If the second rule config only has a severity (length of 1), | |
* then use that severity and keep the rest of the options from | |
* the first rule config. | |
*/ | |
if (secondRuleOptions.length === 1) { | |
result[ruleId] = [secondRuleOptions[0], ...firstRuleOptions.slice(1)]; | |
continue; | |
} | |
/* | |
* In any other situation, then the second rule config takes | |
* precedence. That means the value at `result[ruleId]` is | |
* already correct and no further work is necessary. | |
*/ | |
} | |
return result; | |
}, | |
validate(value) { | |
assertIsObject(value); | |
let lastRuleId; | |
// Performance: One try-catch has less overhead than one per loop iteration | |
try { | |
/* | |
* We are not checking the rule schema here because there is no | |
* guarantee that the rule definition is present at this point. Instead | |
* we wait and check the rule schema during the finalization step | |
* of calculating a config. | |
*/ | |
for (const ruleId of Object.keys(value)) { | |
// avoid hairy edge case | |
if (ruleId === "__proto__") { | |
continue; | |
} | |
lastRuleId = ruleId; | |
const ruleOptions = value[ruleId]; | |
assertIsRuleOptions(ruleOptions); | |
if (Array.isArray(ruleOptions)) { | |
assertIsRuleSeverity(ruleOptions[0]); | |
} else { | |
assertIsRuleSeverity(ruleOptions); | |
} | |
} | |
} catch (error) { | |
error.message = `Key "${lastRuleId}": ${error.message}`; | |
throw error; | |
} | |
} | |
}; | |
/** @type {ObjectPropertySchema} */ | |
const ecmaVersionSchema = { | |
merge: "replace", | |
validate(value) { | |
if (typeof value === "number" || value === "latest") { | |
return; | |
} | |
throw new TypeError("Expected a number or \"latest\"."); | |
} | |
}; | |
/** @type {ObjectPropertySchema} */ | |
const sourceTypeSchema = { | |
merge: "replace", | |
validate(value) { | |
if (typeof value !== "string" || !/^(?:script|module|commonjs)$/u.test(value)) { | |
throw new TypeError("Expected \"script\", \"module\", or \"commonjs\"."); | |
} | |
} | |
}; | |
//----------------------------------------------------------------------------- | |
// Full schema | |
//----------------------------------------------------------------------------- | |
exports.flatConfigSchema = { | |
settings: deepObjectAssignSchema, | |
linterOptions: { | |
schema: { | |
noInlineConfig: booleanSchema, | |
reportUnusedDisableDirectives: booleanSchema | |
} | |
}, | |
languageOptions: { | |
schema: { | |
ecmaVersion: ecmaVersionSchema, | |
sourceType: sourceTypeSchema, | |
globals: globalsSchema, | |
parser: parserSchema, | |
parserOptions: deepObjectAssignSchema | |
} | |
}, | |
processor: processorSchema, | |
plugins: pluginsSchema, | |
rules: rulesSchema | |
}; | |
/***/ }), | |
/***/ 2297: | |
/***/ (function(__unused_webpack_module, exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @fileoverview Rule Validator | |
* @author Nicholas C. Zakas | |
*/ | |
//----------------------------------------------------------------------------- | |
// Requirements | |
//----------------------------------------------------------------------------- | |
const ajv = __webpack_require__(3360)(); | |
const { parseRuleId, getRuleFromConfig } = __webpack_require__(4730); | |
const ruleReplacements = __webpack_require__(4378); | |
//----------------------------------------------------------------------------- | |
// Helpers | |
//----------------------------------------------------------------------------- | |
/** | |
* Throws a helpful error when a rule cannot be found. | |
* @param {Object} ruleId The rule identifier. | |
* @param {string} ruleId.pluginName The ID of the rule to find. | |
* @param {string} ruleId.ruleName The ID of the rule to find. | |
* @param {Object} config The config to search in. | |
* @throws {TypeError} For missing plugin or rule. | |
* @returns {void} | |
*/ | |
function throwRuleNotFoundError({ pluginName, ruleName }, config) { | |
const ruleId = pluginName === "@" ? ruleName : `${pluginName}/${ruleName}`; | |
const errorMessageHeader = `Key "rules": Key "${ruleId}"`; | |
let errorMessage = `${errorMessageHeader}: Could not find plugin "${pluginName}".`; | |
// if the plugin exists then we need to check if the rule exists | |
if (config.plugins && config.plugins[pluginName]) { | |
const replacementRuleName = ruleReplacements.rules[ruleName]; | |
if (pluginName === "@" && replacementRuleName) { | |
errorMessage = `${errorMessageHeader}: Rule "${ruleName}" was removed and replaced by "${replacementRuleName}".`; | |
} else { | |
errorMessage = `${errorMessageHeader}: Could not find "${ruleName}" in plugin "${pluginName}".`; | |
// otherwise, let's see if we can find the rule name elsewhere | |
for (const [otherPluginName, otherPlugin] of Object.entries(config.plugins)) { | |
if (otherPlugin.rules && otherPlugin.rules[ruleName]) { | |
errorMessage += ` Did you mean "${otherPluginName}/${ruleName}"?`; | |
break; | |
} | |
} | |
} | |
// falls through to throw error | |
} | |
throw new TypeError(errorMessage); | |
} | |
/** | |
* Gets a complete options schema for a rule. | |
* @param {{create: Function, schema: (Array|null)}} rule A new-style rule object | |
* @returns {Object} JSON Schema for the rule's options. | |
*/ | |
function getRuleOptionsSchema(rule) { | |
if (!rule) { | |
return null; | |
} | |
const schema = rule.schema || rule.meta && rule.meta.schema; | |
if (Array.isArray(schema)) { | |
if (schema.length) { | |
return { | |
type: "array", | |
items: schema, | |
minItems: 0, | |
maxItems: schema.length | |
}; | |
} | |
return { | |
type: "array", | |
minItems: 0, | |
maxItems: 0 | |
}; | |
} | |
// Given a full schema, leave it alone | |
return schema || null; | |
} | |
//----------------------------------------------------------------------------- | |
// Exports | |
//----------------------------------------------------------------------------- | |
/** | |
* Implements validation functionality for the rules portion of a config. | |
*/ | |
class RuleValidator { | |
/** | |
* Creates a new instance. | |
*/ | |
constructor() { | |
/** | |
* A collection of compiled validators for rules that have already | |
* been validated. | |
* @type {WeakMap} | |
*/ | |
this.validators = new WeakMap(); | |
} | |
/** | |
* Validates all of the rule configurations in a config against each | |
* rule's schema. | |
* @param {Object} config The full config to validate. This object must | |
* contain both the rules section and the plugins section. | |
* @returns {void} | |
* @throws {Error} If a rule's configuration does not match its schema. | |
*/ | |
validate(config) { | |
if (!config.rules) { | |
return; | |
} | |
for (const [ruleId, ruleOptions] of Object.entries(config.rules)) { | |
// check for edge case | |
if (ruleId === "__proto__") { | |
continue; | |
} | |
/* | |
* If a rule is disabled, we don't do any validation. This allows | |
* users to safely set any value to 0 or "off" without worrying | |
* that it will cause a validation error. | |
* | |
* Note: ruleOptions is always an array at this point because | |
* this validation occurs after FlatConfigArray has merged and | |
* normalized values. | |
*/ | |
if (ruleOptions[0] === 0) { | |
continue; | |
} | |
const rule = getRuleFromConfig(ruleId, config); | |
if (!rule) { | |
throwRuleNotFoundError(parseRuleId(ruleId), config); | |
} | |
// Precompile and cache validator the first time | |
if (!this.validators.has(rule)) { | |
const schema = getRuleOptionsSchema(rule); | |
if (schema) { | |
this.validators.set(rule, ajv.compile(schema)); | |
} | |
} | |
const validateRule = this.validators.get(rule); | |
if (validateRule) { | |
validateRule(ruleOptions.slice(1)); | |
if (validateRule.errors) { | |
throw new Error(`Key "rules": Key "${ruleId}": ${ | |
validateRule.errors.map( | |
error => `\tValue ${JSON.stringify(error.data)} ${error.message}.\n` | |
).join("") | |
}`); | |
} | |
} | |
} | |
} | |
} | |
exports.RuleValidator = RuleValidator; | |
/***/ }), | |
/***/ 613: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @fileoverview A module that filters reported problems based on `eslint-disable` and `eslint-enable` comments | |
* @author Teddy Katz | |
*/ | |
const escapeRegExp = __webpack_require__(3150); | |
/** | |
* Compares the locations of two objects in a source file | |
* @param {{line: number, column: number}} itemA The first object | |
* @param {{line: number, column: number}} itemB The second object | |
* @returns {number} A value less than 1 if itemA appears before itemB in the source file, greater than 1 if | |
* itemA appears after itemB in the source file, or 0 if itemA and itemB have the same location. | |
*/ | |
function compareLocations(itemA, itemB) { | |
return itemA.line - itemB.line || itemA.column - itemB.column; | |
} | |
/** | |
* Groups a set of directives into sub-arrays by their parent comment. | |
* @param {Directive[]} directives Unused directives to be removed. | |
* @returns {Directive[][]} Directives grouped by their parent comment. | |
*/ | |
function groupByParentComment(directives) { | |
const groups = new Map(); | |
for (const directive of directives) { | |
const { unprocessedDirective: { parentComment } } = directive; | |
if (groups.has(parentComment)) { | |
groups.get(parentComment).push(directive); | |
} else { | |
groups.set(parentComment, [directive]); | |
} | |
} | |
return [...groups.values()]; | |
} | |
/** | |
* Creates removal details for a set of directives within the same comment. | |
* @param {Directive[]} directives Unused directives to be removed. | |
* @param {Token} commentToken The backing Comment token. | |
* @returns {{ description, fix, position }[]} Details for later creation of output Problems. | |
*/ | |
function createIndividualDirectivesRemoval(directives, commentToken) { | |
/* | |
* `commentToken.value` starts right after `//` or `/*`. | |
* All calculated offsets will be relative to this index. | |
*/ | |
const commentValueStart = commentToken.range[0] + "//".length; | |
// Find where the list of rules starts. `\S+` matches with the directive name (e.g. `eslint-disable-line`) | |
const listStartOffset = /^\s*\S+\s+/u.exec(commentToken.value)[0].length; | |
/* | |
* Get the list text without any surrounding whitespace. In order to preserve the original | |
* formatting, we don't want to change that whitespace. | |
* | |
* // eslint-disable-line rule-one , rule-two , rule-three -- comment | |
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
*/ | |
const listText = commentToken.value | |
.slice(listStartOffset) // remove directive name and all whitespace before the list | |
.split(/\s-{2,}\s/u)[0] // remove `-- comment`, if it exists | |
.trimRight(); // remove all whitespace after the list | |
/* | |
* We can assume that `listText` contains multiple elements. | |
* Otherwise, this function wouldn't be called - if there is | |
* only one rule in the list, then the whole comment must be removed. | |
*/ | |
return directives.map(directive => { | |
const { ruleId } = directive; | |
const regex = new RegExp(String.raw`(?:^|\s*,\s*)${escapeRegExp(ruleId)}(?:\s*,\s*|$)`, "u"); | |
const match = regex.exec(listText); | |
const matchedText = match[0]; | |
const matchStartOffset = listStartOffset + match.index; | |
const matchEndOffset = matchStartOffset + matchedText.length; | |
const firstIndexOfComma = matchedText.indexOf(","); | |
const lastIndexOfComma = matchedText.lastIndexOf(","); | |
let removalStartOffset, removalEndOffset; | |
if (firstIndexOfComma !== lastIndexOfComma) { | |
/* | |
* Since there are two commas, this must one of the elements in the middle of the list. | |
* Matched range starts where the previous rule name ends, and ends where the next rule name starts. | |
* | |
* // eslint-disable-line rule-one , rule-two , rule-three -- comment | |
* ^^^^^^^^^^^^^^ | |
* | |
* We want to remove only the content between the two commas, and also one of the commas. | |
* | |
* // eslint-disable-line rule-one , rule-two , rule-three -- comment | |
* ^^^^^^^^^^^ | |
*/ | |
removalStartOffset = matchStartOffset + firstIndexOfComma; | |
removalEndOffset = matchStartOffset + lastIndexOfComma; | |
} else { | |
/* | |
* This is either the first element or the last element. | |
* | |
* If this is the first element, matched range starts where the first rule name starts | |
* and ends where the second rule name starts. This is exactly the range we want | |
* to remove so that the second rule name will start where the first one was starting | |
* and thus preserve the original formatting. | |
* | |
* // eslint-disable-line rule-one , rule-two , rule-three -- comment | |
* ^^^^^^^^^^^ | |
* | |
* Similarly, if this is the last element, we've already matched the range we want to | |
* remove. The previous rule name will end where the last one was ending, relative | |
* to the content on the right side. | |
* | |
* // eslint-disable-line rule-one , rule-two , rule-three -- comment | |
* ^^^^^^^^^^^^^ | |
*/ | |
removalStartOffset = matchStartOffset; | |
removalEndOffset = matchEndOffset; | |
} | |
return { | |
description: `'${ruleId}'`, | |
fix: { | |
range: [ | |
commentValueStart + removalStartOffset, | |
commentValueStart + removalEndOffset | |
], | |
text: "" | |
}, | |
position: directive.unprocessedDirective | |
}; | |
}); | |
} | |
/** | |
* Creates a description of deleting an entire unused disable comment. | |
* @param {Directive[]} directives Unused directives to be removed. | |
* @param {Token} commentToken The backing Comment token. | |
* @returns {{ description, fix, position }} Details for later creation of an output Problem. | |
*/ | |
function createCommentRemoval(directives, commentToken) { | |
const { range } = commentToken; | |
const ruleIds = directives.filter(directive => directive.ruleId).map(directive => `'${directive.ruleId}'`); | |
return { | |
description: ruleIds.length <= 2 | |
? ruleIds.join(" or ") | |
: `${ruleIds.slice(0, ruleIds.length - 1).join(", ")}, or ${ruleIds[ruleIds.length - 1]}`, | |
fix: { | |
range, | |
text: " " | |
}, | |
position: directives[0].unprocessedDirective | |
}; | |
} | |
/** | |
* Parses details from directives to create output Problems. | |
* @param {Directive[]} allDirectives Unused directives to be removed. | |
* @returns {{ description, fix, position }[]} Details for later creation of output Problems. | |
*/ | |
function processUnusedDisableDirectives(allDirectives) { | |
const directiveGroups = groupByParentComment(allDirectives); | |
return directiveGroups.flatMap( | |
directives => { | |
const { parentComment } = directives[0].unprocessedDirective; | |
const remainingRuleIds = new Set(parentComment.ruleIds); | |
for (const directive of directives) { | |
remainingRuleIds.delete(directive.ruleId); | |
} | |
return remainingRuleIds.size | |
? createIndividualDirectivesRemoval(directives, parentComment.commentToken) | |
: [createCommentRemoval(directives, parentComment.commentToken)]; | |
} | |
); | |
} | |
/** | |
* This is the same as the exported function, except that it | |
* doesn't handle disable-line and disable-next-line directives, and it always reports unused | |
* disable directives. | |
* @param {Object} options options for applying directives. This is the same as the options | |
* for the exported function, except that `reportUnusedDisableDirectives` is not supported | |
* (this function always reports unused disable directives). | |
* @returns {{problems: Problem[], unusedDisableDirectives: Problem[]}} An object with a list | |
* of filtered problems and unused eslint-disable directives | |
*/ | |
function applyDirectives(options) { | |
const problems = []; | |
let nextDirectiveIndex = 0; | |
let currentGlobalDisableDirective = null; | |
const disabledRuleMap = new Map(); | |
// enabledRules is only used when there is a current global disable directive. | |
const enabledRules = new Set(); | |
const usedDisableDirectives = new Set(); | |
for (const problem of options.problems) { | |
while ( | |
nextDirectiveIndex < options.directives.length && | |
compareLocations(options.directives[nextDirectiveIndex], problem) <= 0 | |
) { | |
const directive = options.directives[nextDirectiveIndex++]; | |
switch (directive.type) { | |
case "disable": | |
if (directive.ruleId === null) { | |
currentGlobalDisableDirective = directive; | |
disabledRuleMap.clear(); | |
enabledRules.clear(); | |
} else if (currentGlobalDisableDirective) { | |
enabledRules.delete(directive.ruleId); | |
disabledRuleMap.set(directive.ruleId, directive); | |
} else { | |
disabledRuleMap.set(directive.ruleId, directive); | |
} | |
break; | |
case "enable": | |
if (directive.ruleId === null) { | |
currentGlobalDisableDirective = null; | |
disabledRuleMap.clear(); | |
} else if (currentGlobalDisableDirective) { | |
enabledRules.add(directive.ruleId); | |
disabledRuleMap.delete(directive.ruleId); | |
} else { | |
disabledRuleMap.delete(directive.ruleId); | |
} | |
break; | |
// no default | |
} | |
} | |
if (disabledRuleMap.has(problem.ruleId)) { | |
usedDisableDirectives.add(disabledRuleMap.get(problem.ruleId)); | |
} else if (currentGlobalDisableDirective && !enabledRules.has(problem.ruleId)) { | |
usedDisableDirectives.add(currentGlobalDisableDirective); | |
} else { | |
problems.push(problem); | |
} | |
} | |
const unusedDisableDirectivesToReport = options.directives | |
.filter(directive => directive.type === "disable" && !usedDisableDirectives.has(directive)); | |
const processed = processUnusedDisableDirectives(unusedDisableDirectivesToReport); | |
const unusedDisableDirectives = processed | |
.map(({ description, fix, position }) => ({ | |
ruleId: null, | |
message: description | |
? `Unused eslint-disable directive (no problems were reported from ${description}).` | |
: "Unused eslint-disable directive (no problems were reported).", | |
line: position.line, | |
column: position.column, | |
severity: options.reportUnusedDisableDirectives === "warn" ? 1 : 2, | |
nodeType: null, | |
...options.disableFixes ? {} : { fix } | |
})); | |
return { problems, unusedDisableDirectives }; | |
} | |
/** | |
* Given a list of directive comments (i.e. metadata about eslint-disable and eslint-enable comments) and a list | |
* of reported problems, determines which problems should be reported. | |
* @param {Object} options Information about directives and problems | |
* @param {{ | |
* type: ("disable"|"enable"|"disable-line"|"disable-next-line"), | |
* ruleId: (string|null), | |
* line: number, | |
* column: number | |
* }} options.directives Directive comments found in the file, with one-based columns. | |
* Two directive comments can only have the same location if they also have the same type (e.g. a single eslint-disable | |
* comment for two different rules is represented as two directives). | |
* @param {{ruleId: (string|null), line: number, column: number}[]} options.problems | |
* A list of problems reported by rules, sorted by increasing location in the file, with one-based columns. | |
* @param {"off" | "warn" | "error"} options.reportUnusedDisableDirectives If `"warn"` or `"error"`, adds additional problems for unused directives | |
* @param {boolean} options.disableFixes If true, it doesn't make `fix` properties. | |
* @returns {{ruleId: (string|null), line: number, column: number}[]} | |
* A list of reported problems that were not disabled by the directive comments. | |
*/ | |
module.exports = ({ directives, disableFixes, problems, reportUnusedDisableDirectives = "off" }) => { | |
const blockDirectives = directives | |
.filter(directive => directive.type === "disable" || directive.type === "enable") | |
.map(directive => Object.assign({}, directive, { unprocessedDirective: directive })) | |
.sort(compareLocations); | |
const lineDirectives = directives.flatMap(directive => { | |
switch (directive.type) { | |
case "disable": | |
case "enable": | |
return []; | |
case "disable-line": | |
return [ | |
{ type: "disable", line: directive.line, column: 1, ruleId: directive.ruleId, unprocessedDirective: directive }, | |
{ type: "enable", line: directive.line + 1, column: 0, ruleId: directive.ruleId, unprocessedDirective: directive } | |
]; | |
case "disable-next-line": | |
return [ | |
{ type: "disable", line: directive.line + 1, column: 1, ruleId: directive.ruleId, unprocessedDirective: directive }, | |
{ type: "enable", line: directive.line + 2, column: 0, ruleId: directive.ruleId, unprocessedDirective: directive } | |
]; | |
default: | |
throw new TypeError(`Unrecognized directive type '${directive.type}'`); | |
} | |
}).sort(compareLocations); | |
const blockDirectivesResult = applyDirectives({ | |
problems, | |
directives: blockDirectives, | |
disableFixes, | |
reportUnusedDisableDirectives | |
}); | |
const lineDirectivesResult = applyDirectives({ | |
problems: blockDirectivesResult.problems, | |
directives: lineDirectives, | |
disableFixes, | |
reportUnusedDisableDirectives | |
}); | |
return reportUnusedDisableDirectives !== "off" | |
? lineDirectivesResult.problems | |
.concat(blockDirectivesResult.unusedDisableDirectives) | |
.concat(lineDirectivesResult.unusedDisableDirectives) | |
.sort(compareLocations) | |
: lineDirectivesResult.problems; | |
}; | |
/***/ }), | |
/***/ 6873: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @fileoverview A class of the code path analyzer. | |
* @author Toru Nagashima | |
*/ | |
//------------------------------------------------------------------------------ | |
// Requirements | |
//------------------------------------------------------------------------------ | |
const assert = __webpack_require__(9282), | |
{ breakableTypePattern } = __webpack_require__(911), | |
CodePath = __webpack_require__(8451), | |
CodePathSegment = __webpack_require__(5100), | |
IdGenerator = __webpack_require__(7847), | |
debug = __webpack_require__(3072); | |
//------------------------------------------------------------------------------ | |
// Helpers | |
//------------------------------------------------------------------------------ | |
/** | |
* Checks whether or not a given node is a `case` node (not `default` node). | |
* @param {ASTNode} node A `SwitchCase` node to check. | |
* @returns {boolean} `true` if the node is a `case` node (not `default` node). | |
*/ | |
function isCaseNode(node) { | |
return Boolean(node.test); | |
} | |
/** | |
* Checks if a given node appears as the value of a PropertyDefinition node. | |
* @param {ASTNode} node THe node to check. | |
* @returns {boolean} `true` if the node is a PropertyDefinition value, | |
* false if not. | |
*/ | |
function isPropertyDefinitionValue(node) { | |
const parent = node.parent; | |
return parent && parent.type === "PropertyDefinition" && parent.value === node; | |
} | |
/** | |
* Checks whether the given logical operator is taken into account for the code | |
* path analysis. | |
* @param {string} operator The operator found in the LogicalExpression node | |
* @returns {boolean} `true` if the operator is "&&" or "||" or "??" | |
*/ | |
function isHandledLogicalOperator(operator) { | |
return operator === "&&" || operator === "||" || operator === "??"; | |
} | |
/** | |
* Checks whether the given assignment operator is a logical assignment operator. | |
* Logical assignments are taken into account for the code path analysis | |
* because of their short-circuiting semantics. | |
* @param {string} operator The operator found in the AssignmentExpression node | |
* @returns {boolean} `true` if the operator is "&&=" or "||=" or "??=" | |
*/ | |
function isLogicalAssignmentOperator(operator) { | |
return operator === "&&=" || operator === "||=" || operator === "??="; | |
} | |
/** | |
* Gets the label if the parent node of a given node is a LabeledStatement. | |
* @param {ASTNode} node A node to get. | |
* @returns {string|null} The label or `null`. | |
*/ | |
function getLabel(node) { | |
if (node.parent.type === "LabeledStatement") { | |
return node.parent.label.name; | |
} | |
return null; | |
} | |
/** | |
* Checks whether or not a given logical expression node goes different path | |
* between the `true` case and the `false` case. | |
* @param {ASTNode} node A node to check. | |
* @returns {boolean} `true` if the node is a test of a choice statement. | |
*/ | |
function isForkingByTrueOrFalse(node) { | |
const parent = node.parent; | |
switch (parent.type) { | |
case "ConditionalExpression": | |
case "IfStatement": | |
case "WhileStatement": | |
case "DoWhileStatement": | |
case "ForStatement": | |
return parent.test === node; | |
case "LogicalExpression": | |
return isHandledLogicalOperator(parent.operator); | |
case "AssignmentExpression": | |
return isLogicalAssignmentOperator(parent.operator); | |
default: | |
return false; | |
} | |
} | |
/** | |
* Gets the boolean value of a given literal node. | |
* | |
* This is used to detect infinity loops (e.g. `while (true) {}`). | |
* Statements preceded by an infinity loop are unreachable if the loop didn't | |
* have any `break` statement. | |
* @param {ASTNode} node A node to get. | |
* @returns {boolean|undefined} a boolean value if the node is a Literal node, | |
* otherwise `undefined`. | |
*/ | |
function getBooleanValueIfSimpleConstant(node) { | |
if (node.type === "Literal") { | |
return Boolean(node.value); | |
} | |
return void 0; | |
} | |
/** | |
* Checks that a given identifier node is a reference or not. | |
* | |
* This is used to detect the first throwable node in a `try` block. | |
* @param {ASTNode} node An Identifier node to check. | |
* @returns {boolean} `true` if the node is a reference. | |
*/ | |
function isIdentifierReference(node) { | |
const parent = node.parent; | |
switch (parent.type) { | |
case "LabeledStatement": | |
case "BreakStatement": | |
case "ContinueStatement": | |
case "ArrayPattern": | |
case "RestElement": | |
case "ImportSpecifier": | |
case "ImportDefaultSpecifier": | |
case "ImportNamespaceSpecifier": | |
case "CatchClause": | |
return false; | |
case "FunctionDeclaration": | |
case "FunctionExpression": | |
case "ArrowFunctionExpression": | |
case "ClassDeclaration": | |
case "ClassExpression": | |
case "VariableDeclarator": | |
return parent.id !== node; | |
case "Property": | |
case "PropertyDefinition": | |
case "MethodDefinition": | |
return ( | |
parent.key !== node || | |
parent.computed || | |
parent.shorthand | |
); | |
case "AssignmentPattern": | |
return parent.key !== node; | |
default: | |
return true; | |
} | |
} | |
/** | |
* Updates the current segment with the head segment. | |
* This is similar to local branches and tracking branches of git. | |
* | |
* To separate the current and the head is in order to not make useless segments. | |
* | |
* In this process, both "onCodePathSegmentStart" and "onCodePathSegmentEnd" | |
* events are fired. | |
* @param {CodePathAnalyzer} analyzer The instance. | |
* @param {ASTNode} node The current AST node. | |
* @returns {void} | |
*/ | |
function forwardCurrentToHead(analyzer, node) { | |
const codePath = analyzer.codePath; | |
const state = CodePath.getState(codePath); | |
const currentSegments = state.currentSegments; | |
const headSegments = state.headSegments; | |
const end = Math.max(currentSegments.length, headSegments.length); | |
let i, currentSegment, headSegment; | |
// Fires leaving events. | |
for (i = 0; i < end; ++i) { | |
currentSegment = currentSegments[i]; | |
headSegment = headSegments[i]; | |
if (currentSegment !== headSegment && currentSegment) { | |
debug.dump(`onCodePathSegmentEnd ${currentSegment.id}`); | |
if (currentSegment.reachable) { | |
analyzer.emitter.emit( | |
"onCodePathSegmentEnd", | |
currentSegment, | |
node | |
); | |
} | |
} | |
} | |
// Update state. | |
state.currentSegments = headSegments; | |
// Fires entering events. | |
for (i = 0; i < end; ++i) { | |
currentSegment = currentSegments[i]; | |
headSegment = headSegments[i]; | |
if (currentSegment !== headSegment && headSegment) { | |
debug.dump(`onCodePathSegmentStart ${headSegment.id}`); | |
CodePathSegment.markUsed(headSegment); | |
if (headSegment.reachable) { | |
analyzer.emitter.emit( | |
"onCodePathSegmentStart", | |
headSegment, | |
node | |
); | |
} | |
} | |
} | |
} | |
/** | |
* Updates the current segment with empty. | |
* This is called at the last of functions or the program. | |
* @param {CodePathAnalyzer} analyzer The instance. | |
* @param {ASTNode} node The current AST node. | |
* @returns {void} | |
*/ | |
function leaveFromCurrentSegment(analyzer, node) { | |
const state = CodePath.getState(analyzer.codePath); | |
const currentSegments = state.currentSegments; | |
for (let i = 0; i < currentSegments.length; ++i) { | |
const currentSegment = currentSegments[i]; | |
debug.dump(`onCodePathSegmentEnd ${currentSegment.id}`); | |
if (currentSegment.reachable) { | |
analyzer.emitter.emit( | |
"onCodePathSegmentEnd", | |
currentSegment, | |
node | |
); | |
} | |
} | |
state.currentSegments = []; | |
} | |
/** | |
* Updates the code path due to the position of a given node in the parent node | |
* thereof. | |
* | |
* For example, if the node is `parent.consequent`, this creates a fork from the | |
* current path. | |
* @param {CodePathAnalyzer} analyzer The instance. | |
* @param {ASTNode} node The current AST node. | |
* @returns {void} | |
*/ | |
function preprocess(analyzer, node) { | |
const codePath = analyzer.codePath; | |
const state = CodePath.getState(codePath); | |
const parent = node.parent; | |
switch (parent.type) { | |
// The `arguments.length == 0` case is in `postprocess` function. | |
case "CallExpression": | |
if (parent.optional === true && parent.arguments.length >= 1 && parent.arguments[0] === node) { | |
state.makeOptionalRight(); | |
} | |
break; | |
case "MemberExpression": | |
if (parent.optional === true && parent.property === node) { | |
state.makeOptionalRight(); | |
} | |
break; | |
case "LogicalExpression": | |
if ( | |
parent.right === node && | |
isHandledLogicalOperator(parent.operator) | |
) { | |
state.makeLogicalRight(); | |
} | |
break; | |
case "AssignmentExpression": | |
if ( | |
parent.right === node && | |
isLogicalAssignmentOperator(parent.operator) | |
) { | |
state.makeLogicalRight(); | |
} | |
break; | |
case "ConditionalExpression": | |
case "IfStatement": | |
/* | |
* Fork if this node is at `consequent`/`alternate`. | |
* `popForkContext()` exists at `IfStatement:exit` and | |
* `ConditionalExpression:exit`. | |
*/ | |
if (parent.consequent === node) { | |
state.makeIfConsequent(); | |
} else if (parent.alternate === node) { | |
state.makeIfAlternate(); | |
} | |
break; | |
case "SwitchCase": | |
if (parent.consequent[0] === node) { | |
state.makeSwitchCaseBody(false, !parent.test); | |
} | |
break; | |
case "TryStatement": | |
if (parent.handler === node) { | |
state.makeCatchBlock(); | |
} else if (parent.finalizer === node) { | |
state.makeFinallyBlock(); | |
} | |
break; | |
case "WhileStatement": | |
if (parent.test === node) { | |
state.makeWhileTest(getBooleanValueIfSimpleConstant(node)); | |
} else { | |
assert(parent.body === node); | |
state.makeWhileBody(); | |
} | |
break; | |
case "DoWhileStatement": | |
if (parent.body === node) { | |
state.makeDoWhileBody(); | |
} else { | |
assert(parent.test === node); | |
state.makeDoWhileTest(getBooleanValueIfSimpleConstant(node)); | |
} | |
break; | |
case "ForStatement": | |
if (parent.test === node) { | |
state.makeForTest(getBooleanValueIfSimpleConstant(node)); | |
} else if (parent.update === node) { | |
state.makeForUpdate(); | |
} else if (parent.body === node) { | |
state.makeForBody(); | |
} | |
break; | |
case "ForInStatement": | |
case "ForOfStatement": | |
if (parent.left === node) { | |
state.makeForInOfLeft(); | |
} else if (parent.right === node) { | |
state.makeForInOfRight(); | |
} else { | |
assert(parent.body === node); | |
state.makeForInOfBody(); | |
} | |
break; | |
case "AssignmentPattern": | |
/* | |
* Fork if this node is at `right`. | |
* `left` is executed always, so it uses the current path. | |
* `popForkContext()` exists at `AssignmentPattern:exit`. | |
*/ | |
if (parent.right === node) { | |
state.pushForkContext(); | |
state.forkBypassPath(); | |
state.forkPath(); | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
/** | |
* Updates the code path due to the type of a given node in entering. | |
* @param {CodePathAnalyzer} analyzer The instance. | |
* @param {ASTNode} node The current AST node. | |
* @returns {void} | |
*/ | |
function processCodePathToEnter(analyzer, node) { | |
let codePath = analyzer.codePath; | |
let state = codePath && CodePath.getState(codePath); | |
const parent = node.parent; | |
/** | |
* Creates a new code path and trigger the onCodePathStart event | |
* based on the currently selected node. | |
* @param {string} origin The reason the code path was started. | |
* @returns {void} | |
*/ | |
function startCodePath(origin) { | |
if (codePath) { | |
// Emits onCodePathSegmentStart events if updated. | |
forwardCurrentToHead(analyzer, node); | |
debug.dumpState(node, state, false); | |
} | |
// Create the code path of this scope. | |
codePath = analyzer.codePath = new CodePath({ | |
id: analyzer.idGenerator.next(), | |
origin, | |
upper: codePath, | |
onLooped: analyzer.onLooped | |
}); | |
state = CodePath.getState(codePath); | |
// Emits onCodePathStart events. | |
debug.dump(`onCodePathStart ${codePath.id}`); | |
analyzer.emitter.emit("onCodePathStart", codePath, node); | |
} | |
/* | |
* Special case: The right side of class field initializer is considered | |
* to be its own function, so we need to start a new code path in this | |
* case. | |
*/ | |
if (isPropertyDefinitionValue(node)) { | |
startCodePath("class-field-initializer"); | |
/* | |
* Intentional fall through because `node` needs to also be | |
* processed by the code below. For example, if we have: | |
* | |
* class Foo { | |
* a = () => {} | |
* } | |
* | |
* In this case, we also need start a second code path. | |
*/ | |
} | |
switch (node.type) { | |
case "Program": | |
startCodePath("program"); | |
break; | |
case "FunctionDeclaration": | |
case "FunctionExpression": | |
case "ArrowFunctionExpression": | |
startCodePath("function"); | |
break; | |
case "StaticBlock": | |
startCodePath("class-static-block"); | |
break; | |
case "ChainExpression": | |
state.pushChainContext(); | |
break; | |
case "CallExpression": | |
if (node.optional === true) { | |
state.makeOptionalNode(); | |
} | |
break; | |
case "MemberExpression": | |
if (node.optional === true) { | |
state.makeOptionalNode(); | |
} | |
break; | |
case "LogicalExpression": | |
if (isHandledLogicalOperator(node.operator)) { | |
state.pushChoiceContext( | |
node.operator, | |
isForkingByTrueOrFalse(node) | |
); | |
} | |
break; | |
case "AssignmentExpression": | |
if (isLogicalAssignmentOperator(node.operator)) { | |
state.pushChoiceContext( | |
node.operator.slice(0, -1), // removes `=` from the end | |
isForkingByTrueOrFalse(node) | |
); | |
} | |
break; | |
case "ConditionalExpression": | |
case "IfStatement": | |
state.pushChoiceContext("test", false); | |
break; | |
case "SwitchStatement": | |
state.pushSwitchContext( | |
node.cases.some(isCaseNode), | |
getLabel(node) | |
); | |
break; | |
case "TryStatement": | |
state.pushTryContext(Boolean(node.finalizer)); | |
break; | |
case "SwitchCase": | |
/* | |
* Fork if this node is after the 2st node in `cases`. | |
* It's similar to `else` blocks. | |
* The next `test` node is processed in this path. | |
*/ | |
if (parent.discriminant !== node && parent.cases[0] !== node) { | |
state.forkPath(); | |
} | |
break; | |
case "WhileStatement": | |
case "DoWhileStatement": | |
case "ForStatement": | |
case "ForInStatement": | |
case "ForOfStatement": | |
state.pushLoopContext(node.type, getLabel(node)); | |
break; | |
case "LabeledStatement": | |
if (!breakableTypePattern.test(node.body.type)) { | |
state.pushBreakContext(false, node.label.name); | |
} | |
break; | |
default: | |
break; | |
} | |
// Emits onCodePathSegmentStart events if updated. | |
forwardCurrentToHead(analyzer, node); | |
debug.dumpState(node, state, false); | |
} | |
/** | |
* Updates the code path due to the type of a given node in leaving. | |
* @param {CodePathAnalyzer} analyzer The instance. | |
* @param {ASTNode} node The current AST node. | |
* @returns {void} | |
*/ | |
function processCodePathToExit(analyzer, node) { | |
const codePath = analyzer.codePath; | |
const state = CodePath.getState(codePath); | |
let dontForward = false; | |
switch (node.type) { | |
case "ChainExpression": | |
state.popChainContext(); | |
break; | |
case "IfStatement": | |
case "ConditionalExpression": | |
state.popChoiceContext(); | |
break; | |
case "LogicalExpression": | |
if (isHandledLogicalOperator(node.operator)) { | |
state.popChoiceContext(); | |
} | |
break; | |
case "AssignmentExpression": | |
if (isLogicalAssignmentOperator(node.operator)) { | |
state.popChoiceContext(); | |
} | |
break; | |
case "SwitchStatement": | |
state.popSwitchContext(); | |
break; | |
case "SwitchCase": | |
/* | |
* This is the same as the process at the 1st `consequent` node in | |
* `preprocess` function. | |
* Must do if this `consequent` is empty. | |
*/ | |
if (node.consequent.length === 0) { | |
state.makeSwitchCaseBody(true, !node.test); | |
} | |
if (state.forkContext.reachable) { | |
dontForward = true; | |
} | |
break; | |
case "TryStatement": | |
state.popTryContext(); | |
break; | |
case "BreakStatement": | |
forwardCurrentToHead(analyzer, node); | |
state.makeBreak(node.label && node.label.name); | |
dontForward = true; | |
break; | |
case "ContinueStatement": | |
forwardCurrentToHead(analyzer, node); | |
state.makeContinue(node.label && node.label.name); | |
dontForward = true; | |
break; | |
case "ReturnStatement": | |
forwardCurrentToHead(analyzer, node); | |
state.makeReturn(); | |
dontForward = true; | |
break; | |
case "ThrowStatement": | |
forwardCurrentToHead(analyzer, node); | |
state.makeThrow(); | |
dontForward = true; | |
break; | |
case "Identifier": | |
if (isIdentifierReference(node)) { | |
state.makeFirstThrowablePathInTryBlock(); | |
dontForward = true; | |
} | |
break; | |
case "CallExpression": | |
case "ImportExpression": | |
case "MemberExpression": | |
case "NewExpression": | |
case "YieldExpression": | |
state.makeFirstThrowablePathInTryBlock(); | |
break; | |
case "WhileStatement": | |
case "DoWhileStatement": | |
case "ForStatement": | |
case "ForInStatement": | |
case "ForOfStatement": | |
state.popLoopContext(); | |
break; | |
case "AssignmentPattern": | |
state.popForkContext(); | |
break; | |
case "LabeledStatement": | |
if (!breakableTypePattern.test(node.body.type)) { | |
state.popBreakContext(); | |
} | |
break; | |
default: | |
break; | |
} | |
// Emits onCodePathSegmentStart events if updated. | |
if (!dontForward) { | |
forwardCurrentToHead(analyzer, node); | |
} | |
debug.dumpState(node, state, true); | |
} | |
/** | |
* Updates the code path to finalize the current code path. | |
* @param {CodePathAnalyzer} analyzer The instance. | |
* @param {ASTNode} node The current AST node. | |
* @returns {void} | |
*/ | |
function postprocess(analyzer, node) { | |
/** | |
* Ends the code path for the current node. | |
* @returns {void} | |
*/ | |
function endCodePath() { | |
let codePath = analyzer.codePath; | |
// Mark the current path as the final node. | |
CodePath.getState(codePath).makeFinal(); | |
// Emits onCodePathSegmentEnd event of the current segments. | |
leaveFromCurrentSegment(analyzer, node); | |
// Emits onCodePathEnd event of this code path. | |
debug.dump(`onCodePathEnd ${codePath.id}`); | |
analyzer.emitter.emit("onCodePathEnd", codePath, node); | |
debug.dumpDot(codePath); | |
codePath = analyzer.codePath = analyzer.codePath.upper; | |
if (codePath) { | |
debug.dumpState(node, CodePath.getState(codePath), true); | |
} | |
} | |
switch (node.type) { | |
case "Program": | |
case "FunctionDeclaration": | |
case "FunctionExpression": | |
case "ArrowFunctionExpression": | |
case "StaticBlock": { | |
endCodePath(); | |
break; | |
} | |
// The `arguments.length >= 1` case is in `preprocess` function. | |
case "CallExpression": | |
if (node.optional === true && node.arguments.length === 0) { | |
CodePath.getState(analyzer.codePath).makeOptionalRight(); | |
} | |
break; | |
default: | |
break; | |
} | |
/* | |
* Special case: The right side of class field initializer is considered | |
* to be its own function, so we need to end a code path in this | |
* case. | |
* | |
* We need to check after the other checks in order to close the | |
* code paths in the correct order for code like this: | |
* | |
* | |
* class Foo { | |
* a = () => {} | |
* } | |
* | |
* In this case, The ArrowFunctionExpression code path is closed first | |
* and then we need to close the code path for the PropertyDefinition | |
* value. | |
*/ | |
if (isPropertyDefinitionValue(node)) { | |
endCodePath(); | |
} | |
} | |
//------------------------------------------------------------------------------ | |
// Public Interface | |
//------------------------------------------------------------------------------ | |
/** | |
* The class to analyze code paths. | |
* This class implements the EventGenerator interface. | |
*/ | |
class CodePathAnalyzer { | |
/** | |
* @param {EventGenerator} eventGenerator An event generator to wrap. | |
*/ | |
constructor(eventGenerator) { | |
this.original = eventGenerator; | |
this.emitter = eventGenerator.emitter; | |
this.codePath = null; | |
this.idGenerator = new IdGenerator("s"); | |
this.currentNode = null; | |
this.onLooped = this.onLooped.bind(this); | |
} | |
/** | |
* Does the process to enter a given AST node. | |
* This updates state of analysis and calls `enterNode` of the wrapped. | |
* @param {ASTNode} node A node which is entering. | |
* @returns {void} | |
*/ | |
enterNode(node) { | |
this.currentNode = node; | |
// Updates the code path due to node's position in its parent node. | |
if (node.parent) { | |
preprocess(this, node); | |
} | |
/* | |
* Updates the code path. | |
* And emits onCodePathStart/onCodePathSegmentStart events. | |
*/ | |
processCodePathToEnter(this, node); | |
// Emits node events. | |
this.original.enterNode(node); | |
this.currentNode = null; | |
} | |
/** | |
* Does the process to leave a given AST node. | |
* This updates state of analysis and calls `leaveNode` of the wrapped. | |
* @param {ASTNode} node A node which is leaving. | |
* @returns {void} | |
*/ | |
leaveNode(node) { | |
this.currentNode = node; | |
/* | |
* Updates the code path. | |
* And emits onCodePathStart/onCodePathSegmentStart events. | |
*/ | |
processCodePathToExit(this, node); | |
// Emits node events. | |
this.original.leaveNode(node); | |
// Emits the last onCodePathStart/onCodePathSegmentStart events. | |
postprocess(this, node); | |
this.currentNode = null; | |
} | |
/** | |
* This is called on a code path looped. | |
* Then this raises a looped event. | |
* @param {CodePathSegment} fromSegment A segment of prev. | |
* @param {CodePathSegment} toSegment A segment of next. | |
* @returns {void} | |
*/ | |
onLooped(fromSegment, toSegment) { | |
if (fromSegment.reachable && toSegment.reachable) { | |
debug.dump(`onCodePathSegmentLoop ${fromSegment.id} -> ${toSegment.id}`); | |
this.emitter.emit( | |
"onCodePathSegmentLoop", | |
fromSegment, | |
toSegment, | |
this.currentNode | |
); | |
} | |
} | |
} | |
module.exports = CodePathAnalyzer; | |
/***/ }), | |
/***/ 5100: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @fileoverview A class of the code path segment. | |
* @author Toru Nagashima | |
*/ | |
//------------------------------------------------------------------------------ | |
// Requirements | |
//------------------------------------------------------------------------------ | |
const debug = __webpack_require__(3072); | |
//------------------------------------------------------------------------------ | |
// Helpers | |
//------------------------------------------------------------------------------ | |
/** | |
* Checks whether or not a given segment is reachable. | |
* @param {CodePathSegment} segment A segment to check. | |
* @returns {boolean} `true` if the segment is reachable. | |
*/ | |
function isReachable(segment) { | |
return segment.reachable; | |
} | |
//------------------------------------------------------------------------------ | |
// Public Interface | |
//------------------------------------------------------------------------------ | |
/** | |
* A code path segment. | |
*/ | |
class CodePathSegment { | |
/** | |
* @param {string} id An identifier. | |
* @param {CodePathSegment[]} allPrevSegments An array of the previous segments. | |
* This array includes unreachable segments. | |
* @param {boolean} reachable A flag which shows this is reachable. | |
*/ | |
constructor(id, allPrevSegments, reachable) { | |
/** | |
* The identifier of this code path. | |
* Rules use it to store additional information of each rule. | |
* @type {string} | |
*/ | |
this.id = id; | |
/** | |
* An array of the next segments. | |
* @type {CodePathSegment[]} | |
*/ | |
this.nextSegments = []; | |
/** | |
* An array of the previous segments. | |
* @type {CodePathSegment[]} | |
*/ | |
this.prevSegments = allPrevSegments.filter(isReachable); | |
/** | |
* An array of the next segments. | |
* This array includes unreachable segments. | |
* @type {CodePathSegment[]} | |
*/ | |
this.allNextSegments = []; | |
/** | |
* An array of the previous segments. | |
* This array includes unreachable segments. | |
* @type {CodePathSegment[]} | |
*/ | |
this.allPrevSegments = allPrevSegments; | |
/** | |
* A flag which shows this is reachable. | |
* @type {boolean} | |
*/ | |
this.reachable = reachable; | |
// Internal data. | |
Object.defineProperty(this, "internal", { | |
value: { | |
used: false, | |
loopedPrevSegments: [] | |
} | |
}); | |
/* istanbul ignore if */ | |
if (debug.enabled) { | |
this.internal.nodes = []; | |
} | |
} | |
/** | |
* Checks a given previous segment is coming from the end of a loop. | |
* @param {CodePathSegment} segment A previous segment to check. | |
* @returns {boolean} `true` if the segment is coming from the end of a loop. | |
*/ | |
isLoopedPrevSegment(segment) { | |
return this.internal.loopedPrevSegments.indexOf(segment) !== -1; | |
} | |
/** | |
* Creates the root segment. | |
* @param {string} id An identifier. | |
* @returns {CodePathSegment} The created segment. | |
*/ | |
static newRoot(id) { | |
return new CodePathSegment(id, [], true); | |
} | |
/** | |
* Creates a segment that follows given segments. | |
* @param {string} id An identifier. | |
* @param {CodePathSegment[]} allPrevSegments An array of the previous segments. | |
* @returns {CodePathSegment} The created segment. | |
*/ | |
static newNext(id, allPrevSegments) { | |
return new CodePathSegment( | |
id, | |
CodePathSegment.flattenUnusedSegments(allPrevSegments), | |
allPrevSegments.some(isReachable) | |
); | |
} | |
/** | |
* Creates an unreachable segment that follows given segments. | |
* @param {string} id An identifier. | |
* @param {CodePathSegment[]} allPrevSegments An array of the previous segments. | |
* @returns {CodePathSegment} The created segment. | |
*/ | |
static newUnreachable(id, allPrevSegments) { | |
const segment = new CodePathSegment(id, CodePathSegment.flattenUnusedSegments(allPrevSegments), false); | |
/* | |
* In `if (a) return a; foo();` case, the unreachable segment preceded by | |
* the return statement is not used but must not be remove. | |
*/ | |
CodePathSegment.markUsed(segment); | |
return segment; | |
} | |
/** | |
* Creates a segment that follows given segments. | |
* This factory method does not connect with `allPrevSegments`. | |
* But this inherits `reachable` flag. | |
* @param {string} id An identifier. | |
* @param {CodePathSegment[]} allPrevSegments An array of the previous segments. | |
* @returns {CodePathSegment} The created segment. | |
*/ | |
static newDisconnected(id, allPrevSegments) { | |
return new CodePathSegment(id, [], allPrevSegments.some(isReachable)); | |
} | |
/** | |
* Makes a given segment being used. | |
* | |
* And this function registers the segment into the previous segments as a next. | |
* @param {CodePathSegment} segment A segment to mark. | |
* @returns {void} | |
*/ | |
static markUsed(segment) { | |
if (segment.internal.used) { | |
return; | |
} | |
segment.internal.used = true; | |
let i; | |
if (segment.reachable) { | |
for (i = 0; i < segment.allPrevSegments.length; ++i) { | |
const prevSegment = segment.allPrevSegments[i]; | |
prevSegment.allNextSegments.push(segment); | |
prevSegment.nextSegments.push(segment); | |
} | |
} else { | |
for (i = 0; i < segment.allPrevSegments.length; ++i) { | |
segment.allPrevSegments[i].allNextSegments.push(segment); | |
} | |
} | |
} | |
/** | |
* Marks a previous segment as looped. | |
* @param {CodePathSegment} segment A segment. | |
* @param {CodePathSegment} prevSegment A previous segment to mark. | |
* @returns {void} | |
*/ | |
static markPrevSegmentAsLooped(segment, prevSegment) { | |
segment.internal.loopedPrevSegments.push(prevSegment); | |
} | |
/** | |
* Replaces unused segments with the previous segments of each unused segment. | |
* @param {CodePathSegment[]} segments An array of segments to replace. | |
* @returns {CodePathSegment[]} The replaced array. | |
*/ | |
static flattenUnusedSegments(segments) { | |
const done = Object.create(null); | |
const retv = []; | |
for (let i = 0; i < segments.length; ++i) { | |
const segment = segments[i]; | |
// Ignores duplicated. | |
if (done[segment.id]) { | |
continue; | |
} | |
// Use previous segments if unused. | |
if (!segment.internal.used) { | |
for (let j = 0; j < segment.allPrevSegments.length; ++j) { | |
const prevSegment = segment.allPrevSegments[j]; | |
if (!done[prevSegment.id]) { | |
done[prevSegment.id] = true; | |
retv.push(prevSegment); | |
} | |
} | |
} else { | |
done[segment.id] = true; | |
retv.push(segment); | |
} | |
} | |
return retv; | |
} | |
} | |
module.exports = CodePathSegment; | |
/***/ }), | |
/***/ 3562: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @fileoverview A class to manage state of generating a code path. | |
* @author Toru Nagashima | |
*/ | |
//------------------------------------------------------------------------------ | |
// Requirements | |
//------------------------------------------------------------------------------ | |
const CodePathSegment = __webpack_require__(5100), | |
ForkContext = __webpack_require__(4303); | |
//------------------------------------------------------------------------------ | |
// Helpers | |
//------------------------------------------------------------------------------ | |
/** | |
* Adds given segments into the `dest` array. | |
* If the `others` array does not includes the given segments, adds to the `all` | |
* array as well. | |
* | |
* This adds only reachable and used segments. | |
* @param {CodePathSegment[]} dest A destination array (`returnedSegments` or `thrownSegments`). | |
* @param {CodePathSegment[]} others Another destination array (`returnedSegments` or `thrownSegments`). | |
* @param {CodePathSegment[]} all The unified destination array (`finalSegments`). | |
* @param {CodePathSegment[]} segments Segments to add. | |
* @returns {void} | |
*/ | |
function addToReturnedOrThrown(dest, others, all, segments) { | |
for (let i = 0; i < segments.length; ++i) { | |
const segment = segments[i]; | |
dest.push(segment); | |
if (others.indexOf(segment) === -1) { | |
all.push(segment); | |
} | |
} | |
} | |
/** | |
* Gets a loop-context for a `continue` statement. | |
* @param {CodePathState} state A state to get. | |
* @param {string} label The label of a `continue` statement. | |
* @returns {LoopContext} A loop-context for a `continue` statement. | |
*/ | |
function getContinueContext(state, label) { | |
if (!label) { | |
return state.loopContext; | |
} | |
let context = state.loopContext; | |
while (context) { | |
if (context.label === label) { | |
return context; | |
} | |
context = context.upper; | |
} | |
/* istanbul ignore next: foolproof (syntax error) */ | |
return null; | |
} | |
/** | |
* Gets a context for a `break` statement. | |
* @param {CodePathState} state A state to get. | |
* @param {string} label The label of a `break` statement. | |
* @returns {LoopContext|SwitchContext} A context for a `break` statement. | |
*/ | |
function getBreakContext(state, label) { | |
let context = state.breakContext; | |
while (context) { | |
if (label ? context.label === label : context.breakable) { | |
return context; | |
} | |
context = context.upper; | |
} | |
/* istanbul ignore next: foolproof (syntax error) */ | |
return null; | |
} | |
/** | |
* Gets a context for a `return` statement. | |
* @param {CodePathState} state A state to get. | |
* @returns {TryContext|CodePathState} A context for a `return` statement. | |
*/ | |
function getReturnContext(state) { | |
let context = state.tryContext; | |
while (context) { | |
if (context.hasFinalizer && context.position !== "finally") { | |
return context; | |
} | |
context = context.upper; | |
} | |
return state; | |
} | |
/** | |
* Gets a context for a `throw` statement. | |
* @param {CodePathState} state A state to get. | |
* @returns {TryContext|CodePathState} A context for a `throw` statement. | |
*/ | |
function getThrowContext(state) { | |
let context = state.tryContext; | |
while (context) { | |
if (context.position === "try" || | |
(context.hasFinalizer && context.position === "catch") | |
) { | |
return context; | |
} | |
context = context.upper; | |
} | |
return state; | |
} | |
/** | |
* Removes a given element from a given array. | |
* @param {any[]} xs An array to remove the specific element. | |
* @param {any} x An element to be removed. | |
* @returns {void} | |
*/ | |
function remove(xs, x) { | |
xs.splice(xs.indexOf(x), 1); | |
} | |
/** | |
* Disconnect given segments. | |
* | |
* This is used in a process for switch statements. | |
* If there is the "default" chunk before other cases, the order is different | |
* between node's and running's. | |
* @param {CodePathSegment[]} prevSegments Forward segments to disconnect. | |
* @param {CodePathSegment[]} nextSegments Backward segments to disconnect. | |
* @returns {void} | |
*/ | |
function removeConnection(prevSegments, nextSegments) { | |
for (let i = 0; i < prevSegments.length; ++i) { | |
const prevSegment = prevSegments[i]; | |
const nextSegment = nextSegments[i]; | |
remove(prevSegment.nextSegments, nextSegment); | |
remove(prevSegment.allNextSegments, nextSegment); | |
remove(nextSegment.prevSegments, prevSegment); | |
remove(nextSegment.allPrevSegments, prevSegment); | |
} | |
} | |
/** | |
* Creates looping path. | |
* @param {CodePathState} state The instance. | |
* @param {CodePathSegment[]} unflattenedFromSegments Segments which are source. | |
* @param {CodePathSegment[]} unflattenedToSegments Segments which are destination. | |
* @returns {void} | |
*/ | |
function makeLooped(state, unflattenedFromSegments, unflattenedToSegments) { | |
const fromSegments = CodePathSegment.flattenUnusedSegments(unflattenedFromSegments); | |
const toSegments = CodePathSegment.flattenUnusedSegments(unflattenedToSegments); | |
const end = Math.min(fromSegments.length, toSegments.length); | |
for (let i = 0; i < end; ++i) { | |
const fromSegment = fromSegments[i]; | |
const toSegment = toSegments[i]; | |
if (toSegment.reachable) { | |
fromSegment.nextSegments.push(toSegment); | |
} | |
if (fromSegment.reachable) { | |
toSegment.prevSegments.push(fromSegment); | |
} | |
fromSegment.allNextSegments.push(toSegment); | |
toSegment.allPrevSegments.push(fromSegment); | |
if (toSegment.allPrevSegments.length >= 2) { | |
CodePathSegment.markPrevSegmentAsLooped(toSegment, fromSegment); | |
} | |
state.notifyLooped(fromSegment, toSegment); | |
} | |
} | |
/** | |
* Finalizes segments of `test` chunk of a ForStatement. | |
* | |
* - Adds `false` paths to paths which are leaving from the loop. | |
* - Sets `true` paths to paths which go to the body. | |
* @param {LoopContext} context A loop context to modify. | |
* @param {ChoiceContext} choiceContext A choice context of this loop. | |
* @param {CodePathSegment[]} head The current head paths. | |
* @returns {void} | |
*/ | |
function finalizeTestSegmentsOfFor(context, choiceContext, head) { | |
if (!choiceContext.processed) { | |
choiceContext.trueForkContext.add(head); | |
choiceContext.falseForkContext.add(head); | |
choiceContext.qqForkContext.add(head); | |
} | |
if (context.test !== true) { | |
context.brokenForkContext.addAll(choiceContext.falseForkContext); | |
} | |
context.endOfTestSegments = choiceContext.trueForkContext.makeNext(0, -1); | |
} | |
//------------------------------------------------------------------------------ | |
// Public Interface | |
//------------------------------------------------------------------------------ | |
/** | |
* A class which manages state to analyze code paths. | |
*/ | |
class CodePathState { | |
/** | |
* @param {IdGenerator} idGenerator An id generator to generate id for code | |
* path segments. | |
* @param {Function} onLooped A callback function to notify looping. | |
*/ | |
constructor(idGenerator, onLooped) { | |
this.idGenerator = idGenerator; | |
this.notifyLooped = onLooped; | |
this.forkContext = ForkContext.newRoot(idGenerator); | |
this.choiceContext = null; | |
this.switchContext = null; | |
this.tryContext = null; | |
this.loopContext = null; | |
this.breakContext = null; | |
this.chainContext = null; | |
this.currentSegments = []; | |
this.initialSegment = this.forkContext.head[0]; | |
// returnedSegments and thrownSegments push elements into finalSegments also. | |
const final = this.finalSegments = []; | |
const returned = this.returnedForkContext = []; | |
const thrown = this.thrownForkContext = []; | |
returned.add = addToReturnedOrThrown.bind(null, returned, thrown, final); | |
thrown.add = addToReturnedOrThrown.bind(null, thrown, returned, final); | |
} | |
/** | |
* The head segments. | |
* @type {CodePathSegment[]} | |
*/ | |
get headSegments() { | |
return this.forkContext.head; | |
} | |
/** | |
* The parent forking context. | |
* This is used for the root of new forks. | |
* @type {ForkContext} | |
*/ | |
get parentForkContext() { | |
const current = this.forkContext; | |
return current && current.upper; | |
} | |
/** | |
* Creates and stacks new forking context. | |
* @param {boolean} forkLeavingPath A flag which shows being in a | |
* "finally" block. | |
* @returns {ForkContext} The created context. | |
*/ | |
pushForkContext(forkLeavingPath) { | |
this.forkContext = ForkContext.newEmpty( | |
this.forkContext, | |
forkLeavingPath | |
); | |
return this.forkContext; | |
} | |
/** | |
* Pops and merges the last forking context. | |
* @returns {ForkContext} The last context. | |
*/ | |
popForkContext() { | |
const lastContext = this.forkContext; | |
this.forkContext = lastContext.upper; | |
this.forkContext.replaceHead(lastContext.makeNext(0, -1)); | |
return lastContext; | |
} | |
/** | |
* Creates a new path. | |
* @returns {void} | |
*/ | |
forkPath() { | |
this.forkContext.add(this.parentForkContext.makeNext(-1, -1)); | |
} | |
/** | |
* Creates a bypass path. | |
* This is used for such as IfStatement which does not have "else" chunk. | |
* @returns {void} | |
*/ | |
forkBypassPath() { | |
this.forkContext.add(this.parentForkContext.head); | |
} | |
//-------------------------------------------------------------------------- | |
// ConditionalExpression, LogicalExpression, IfStatement | |
//-------------------------------------------------------------------------- | |
/** | |
* Creates a context for ConditionalExpression, LogicalExpression, AssignmentExpression (logical assignments only), | |
* IfStatement, WhileStatement, DoWhileStatement, or ForStatement. | |
* | |
* LogicalExpressions have cases that it goes different paths between the | |
* `true` case and the `false` case. | |
* | |
* For Example: | |
* | |
* if (a || b) { | |
* foo(); | |
* } else { | |
* bar(); | |
* } | |
* | |
* In this case, `b` is evaluated always in the code path of the `else` | |
* block, but it's not so in the code path of the `if` block. | |
* So there are 3 paths. | |
* | |
* a -> foo(); | |
* a -> b -> foo(); | |
* a -> b -> bar(); | |
* @param {string} kind A kind string. | |
* If the new context is LogicalExpression's or AssignmentExpression's, this is `"&&"` or `"||"` or `"??"`. | |
* If it's IfStatement's or ConditionalExpression's, this is `"test"`. | |
* Otherwise, this is `"loop"`. | |
* @param {boolean} isForkingAsResult A flag that shows that goes different | |
* paths between `true` and `false`. | |
* @returns {void} | |
*/ | |
pushChoiceContext(kind, isForkingAsResult) { | |
this.choiceContext = { | |
upper: this.choiceContext, | |
kind, | |
isForkingAsResult, | |
trueForkContext: ForkContext.newEmpty(this.forkContext), | |
falseForkContext: ForkContext.newEmpty(this.forkContext), | |
qqForkContext: ForkContext.newEmpty(this.forkContext), | |
processed: false | |
}; | |
} | |
/** | |
* Pops the last choice context and finalizes it. | |
* @throws {Error} (Unreachable.) | |
* @returns {ChoiceContext} The popped context. | |
*/ | |
popChoiceContext() { | |
const context = this.choiceContext; | |
this.choiceContext = context.upper; | |
const forkContext = this.forkContext; | |
const headSegments = forkContext.head; | |
switch (context.kind) { | |
case "&&": | |
case "||": | |
case "??": | |
/* | |
* If any result were not transferred from child contexts, | |
* this sets the head segments to both cases. | |
* The head segments are the path of the right-hand operand. | |
*/ | |
if (!context.processed) { | |
context.trueForkContext.add(headSegments); | |
context.falseForkContext.add(headSegments); | |
context.qqForkContext.add(headSegments); | |
} | |
/* | |
* Transfers results to upper context if this context is in | |
* test chunk. | |
*/ | |
if (context.isForkingAsResult) { | |
const parentContext = this.choiceContext; | |
parentContext.trueForkContext.addAll(context.trueForkContext); | |
parentContext.falseForkContext.addAll(context.falseForkContext); | |
parentContext.qqForkContext.addAll(context.qqForkContext); | |
parentContext.processed = true; | |
return context; | |
} | |
break; | |
case "test": | |
if (!context.processed) { | |
/* | |
* The head segments are the path of the `if` block here. | |
* Updates the `true` path with the end of the `if` block. | |
*/ | |
context.trueForkContext.clear(); | |
context.trueForkContext.add(headSegments); | |
} else { | |
/* | |
* The head segments are the path of the `else` block here. | |
* Updates the `false` path with the end of the `else` | |
* block. | |
*/ | |
context.falseForkContext.clear(); | |
context.falseForkContext.add(headSegments); | |
} | |
break; | |
case "loop": | |
/* | |
* Loops are addressed in popLoopContext(). | |
* This is called from popLoopContext(). | |
*/ | |
return context; | |
/* istanbul ignore next */ | |
default: | |
throw new Error("unreachable"); | |
} | |
// Merges all paths. | |
const prevForkContext = context.trueForkContext; | |
prevForkContext.addAll(context.falseForkContext); | |
forkContext.replaceHead(prevForkContext.makeNext(0, -1)); | |
return context; | |
} | |
/** | |
* Makes a code path segment of the right-hand operand of a logical | |
* expression. | |
* @throws {Error} (Unreachable.) | |
* @returns {void} | |
*/ | |
makeLogicalRight() { | |
const context = this.choiceContext; | |
const forkContext = this.forkContext; | |
if (context.processed) { | |
/* | |
* This got segments already from the child choice context. | |
* Creates the next path from own true/false fork context. | |
*/ | |
let prevForkContext; | |
switch (context.kind) { | |
case "&&": // if true then go to the right-hand side. | |
prevForkContext = context.trueForkContext; | |
break; | |
case "||": // if false then go to the right-hand side. | |
prevForkContext = context.falseForkContext; | |
break; | |
case "??": // Both true/false can short-circuit, so needs the third path to go to the right-hand side. That's qqForkContext. | |
prevForkContext = context.qqForkContext; | |
break; | |
default: | |
throw new Error("unreachable"); | |
} | |
forkContext.replaceHead(prevForkContext.makeNext(0, -1)); | |
prevForkContext.clear(); | |
context.processed = false; | |
} else { | |
/* | |
* This did not get segments from the child choice context. | |
* So addresses the head segments. | |
* The head segments are the path of the left-hand operand. | |
*/ | |
switch (context.kind) { | |
case "&&": // the false path can short-circuit. | |
context.falseForkContext.add(forkContext.head); | |
break; | |
case "||": // the true path can short-circuit. | |
context.trueForkContext.add(forkContext.head); | |
break; | |
case "??": // both can short-circuit. | |
context.trueForkContext.add(forkContext.head); | |
context.falseForkContext.add(forkContext.head); | |
break; | |
default: | |
throw new Error("unreachable"); | |
} | |
forkContext.replaceHead(forkContext.makeNext(-1, -1)); | |
} | |
} | |
/** | |
* Makes a code path segment of the `if` block. | |
* @returns {void} | |
*/ | |
makeIfConsequent() { | |
const context = this.choiceContext; | |
const forkContext = this.forkContext; | |
/* | |
* If any result were not transferred from child contexts, | |
* this sets the head segments to both cases. | |
* The head segments are the path of the test expression. | |
*/ | |
if (!context.processed) { | |
context.trueForkContext.add(forkContext.head); | |
context.falseForkContext.add(forkContext.head); | |
context.qqForkContext.add(forkContext.head); | |
} | |
context.processed = false; | |
// Creates new path from the `true` case. | |
forkContext.replaceHead( | |
context.trueForkContext.makeNext(0, -1) | |
); | |
} | |
/** | |
* Makes a code path segment of the `else` block. | |
* @returns {void} | |
*/ | |
makeIfAlternate() { | |
const context = this.choiceContext; | |
const forkContext = this.forkContext; | |
/* | |
* The head segments are the path of the `if` block. | |
* Updates the `true` path with the end of the `if` block. | |
*/ | |
context.trueForkContext.clear(); | |
context.trueForkContext.add(forkContext.head); | |
context.processed = true; | |
// Creates new path from the `false` case. | |
forkContext.replaceHead( | |
context.falseForkContext.makeNext(0, -1) | |
); | |
} | |
//-------------------------------------------------------------------------- | |
// ChainExpression | |
//-------------------------------------------------------------------------- | |
/** | |
* Push a new `ChainExpression` context to the stack. | |
* This method is called on entering to each `ChainExpression` node. | |
* This context is used to count forking in the optional chain then merge them on the exiting from the `ChainExpression` node. | |
* @returns {void} | |
*/ | |
pushChainContext() { | |
this.chainContext = { | |
upper: this.chainContext, | |
countChoiceContexts: 0 | |
}; | |
} | |
/** | |
* Pop a `ChainExpression` context from the stack. | |
* This method is called on exiting from each `ChainExpression` node. | |
* This merges all forks of the last optional chaining. | |
* @returns {void} | |
*/ | |
popChainContext() { | |
const context = this.chainContext; | |
this.chainContext = context.upper; | |
// pop all choice contexts of this. | |
for (let i = context.countChoiceContexts; i > 0; --i) { | |
this.popChoiceContext(); | |
} | |
} | |
/** | |
* Create a choice context for optional access. | |
* This method is called on entering to each `(Call|Member)Expression[optional=true]` node. | |
* This creates a choice context as similar to `LogicalExpression[operator="??"]` node. | |
* @returns {void} | |
*/ | |
makeOptionalNode() { | |
if (this.chainContext) { | |
this.chainContext.countChoiceContexts += 1; | |
this.pushChoiceContext("??", false); | |
} | |
} | |
/** | |
* Create a fork. | |
* This method is called on entering to the `arguments|property` property of each `(Call|Member)Expression` node. | |
* @returns {void} | |
*/ | |
makeOptionalRight() { | |
if (this.chainContext) { | |
this.makeLogicalRight(); | |
} | |
} | |
//-------------------------------------------------------------------------- | |
// SwitchStatement | |
//-------------------------------------------------------------------------- | |
/** | |
* Creates a context object of SwitchStatement and stacks it. | |
* @param {boolean} hasCase `true` if the switch statement has one or more | |
* case parts. | |
* @param {string|null} label The label text. | |
* @returns {void} | |
*/ | |
pushSwitchContext(hasCase, label) { | |
this.switchContext = { | |
upper: this.switchContext, | |
hasCase, | |
defaultSegments: null, | |
defaultBodySegments: null, | |
foundDefault: false, | |
lastIsDefault: false, | |
countForks: 0 | |
}; | |
this.pushBreakContext(true, label); | |
} | |
/** | |
* Pops the last context of SwitchStatement and finalizes it. | |
* | |
* - Disposes all forking stack for `case` and `default`. | |
* - Creates the next code path segment from `context.brokenForkContext`. | |
* - If the last `SwitchCase` node is not a `default` part, creates a path | |
* to the `default` body. | |
* @returns {void} | |
*/ | |
popSwitchContext() { | |
const context = this.switchContext; | |
this.switchContext = context.upper; | |
const forkContext = this.forkContext; | |
const brokenForkContext = this.popBreakContext().brokenForkContext; | |
if (context.countForks === 0) { | |
/* | |
* When there is only one `default` chunk and there is one or more | |
* `break` statements, even if forks are nothing, it needs to merge | |
* those. | |
*/ | |
if (!brokenForkContext.empty) { | |
brokenForkContext.add(forkContext.makeNext(-1, -1)); | |
forkContext.replaceHead(brokenForkContext.makeNext(0, -1)); | |
} | |
return; | |
} | |
const lastSegments = forkContext.head; | |
this.forkBypassPath(); | |
const lastCaseSegments = forkContext.head; | |
/* | |
* `brokenForkContext` is used to make the next segment. | |
* It must add the last segment into `brokenForkContext`. | |
*/ | |
brokenForkContext.add(lastSegments); | |
/* | |
* A path which is failed in all case test should be connected to path | |
* of `default` chunk. | |
*/ | |
if (!context.lastIsDefault) { | |
if (context.defaultBodySegments) { | |
/* | |
* Remove a link from `default` label to its chunk. | |
* It's false route. | |
*/ | |
removeConnection(context.defaultSegments, context.defaultBodySegments); | |
makeLooped(this, lastCaseSegments, context.defaultBodySegments); | |
} else { | |
/* | |
* It handles the last case body as broken if `default` chunk | |
* does not exist. | |
*/ | |
brokenForkContext.add(lastCaseSegments); | |
} | |
} | |
// Pops the segment context stack until the entry segment. | |
for (let i = 0; i < context.countForks; ++i) { | |
this.forkContext = this.forkContext.upper; | |
} | |
/* | |
* Creates a path from all brokenForkContext paths. | |
* This is a path after switch statement. | |
*/ | |
this.forkContext.replaceHead(brokenForkContext.makeNext(0, -1)); | |
} | |
/** | |
* Makes a code path segment for a `SwitchCase` node. | |
* @param {boolean} isEmpty `true` if the body is empty. | |
* @param {boolean} isDefault `true` if the body is the default case. | |
* @returns {void} | |
*/ | |
makeSwitchCaseBody(isEmpty, isDefault) { | |
const context = this.switchContext; | |
if (!context.hasCase) { | |
return; | |
} | |
/* | |
* Merge forks. | |
* The parent fork context has two segments. | |
* Those are from the current case and the body of the previous case. | |
*/ | |
const parentForkContext = this.forkContext; | |
const forkContext = this.pushForkContext(); | |
forkContext.add(parentForkContext.makeNext(0, -1)); | |
/* | |
* Save `default` chunk info. | |
* If the `default` label is not at the last, we must make a path from | |
* the last `case` to the `default` chunk. | |
*/ | |
if (isDefault) { | |
context.defaultSegments = parentForkContext.head; | |
if (isEmpty) { | |
context.foundDefault = true; | |
} else { | |
context.defaultBodySegments = forkContext.head; | |
} | |
} else { | |
if (!isEmpty && context.foundDefault) { | |
context.foundDefault = false; | |
context.defaultBodySegments = forkContext.head; | |
} | |
} | |
context.lastIsDefault = isDefault; | |
context.countForks += 1; | |
} | |
//-------------------------------------------------------------------------- | |
// TryStatement | |
//-------------------------------------------------------------------------- | |
/** | |
* Creates a context object of TryStatement and stacks it. | |
* @param {boolean} hasFinalizer `true` if the try statement has a | |
* `finally` block. | |
* @returns {void} | |
*/ | |
pushTryContext(hasFinalizer) { | |
this.tryContext = { | |
upper: this.tryContext, | |
position: "try", | |
hasFinalizer, | |
returnedForkContext: hasFinalizer | |
? ForkContext.newEmpty(this.forkContext) | |
: null, | |
thrownForkContext: ForkContext.newEmpty(this.forkContext), | |
lastOfTryIsReachable: false, | |
lastOfCatchIsReachable: false | |
}; | |
} | |
/** | |
* Pops the last context of TryStatement and finalizes it. | |
* @returns {void} | |
*/ | |
popTryContext() { | |
const context = this.tryContext; | |
this.tryContext = context.upper; | |
if (context.position === "catch") { | |
// Merges two paths from the `try` block and `catch` block merely. | |
this.popForkContext(); | |
return; | |
} | |
/* | |
* The following process is executed only when there is the `finally` | |
* block. | |
*/ | |
const returned = context.returnedForkContext; | |
const thrown = context.thrownForkContext; | |
if (returned.empty && thrown.empty) { | |
return; | |
} | |
// Separate head to normal paths and leaving paths. | |
const headSegments = this.forkContext.head; | |
this.forkContext = this.forkContext.upper; | |
const normalSegments = headSegments.slice(0, headSegments.length / 2 | 0); | |
const leavingSegments = headSegments.slice(headSegments.length / 2 | 0); | |
// Forwards the leaving path to upper contexts. | |
if (!returned.empty) { | |
getReturnContext(this).returnedForkContext.add(leavingSegments); | |
} | |
if (!thrown.empty) { | |
getThrowContext(this).thrownForkContext.add(leavingSegments); | |
} | |
// Sets the normal path as the next. | |
this.forkContext.replaceHead(normalSegments); | |
/* | |
* If both paths of the `try` block and the `catch` block are | |
* unreachable, the next path becomes unreachable as well. | |
*/ | |
if (!context.lastOfTryIsReachable && !context.lastOfCatchIsReachable) { | |
this.forkContext.makeUnreachable(); | |
} | |
} | |
/** | |
* Makes a code path segment for a `catch` block. | |
* @returns {void} | |
*/ | |
makeCatchBlock() { | |
const context = this.tryContext; | |
const forkContext = this.forkContext; | |
const thrown = context.thrownForkContext; | |
// Update state. | |
context.position = "catch"; | |
context.thrownForkContext = ForkContext.newEmpty(forkContext); | |
context.lastOfTryIsReachable = forkContext.reachable; | |
// Merge thrown paths. | |
thrown.add(forkContext.head); | |
const thrownSegments = thrown.makeNext(0, -1); | |
// Fork to a bypass and the merged thrown path. | |
this.pushForkContext(); | |
this.forkBypassPath(); | |
this.forkContext.add(thrownSegments); | |
} | |
/** | |
* Makes a code path segment for a `finally` block. | |
* | |
* In the `finally` block, parallel paths are created. The parallel paths | |
* are used as leaving-paths. The leaving-paths are paths from `return` | |
* statements and `throw` statements in a `try` block or a `catch` block. | |
* @returns {void} | |
*/ | |
makeFinallyBlock() { | |
const context = this.tryContext; | |
let forkContext = this.forkContext; | |
const returned = context.returnedForkContext; | |
const thrown = context.thrownForkContext; | |
const headOfLeavingSegments = forkContext.head; | |
// Update state. | |
if (context.position === "catch") { | |
// Merges two paths from the `try` block and `catch` block. | |
this.popForkContext(); | |
forkContext = this.forkContext; | |
context.lastOfCatchIsReachable = forkContext.reachable; | |
} else { | |
context.lastOfTryIsReachable = forkContext.reachable; | |
} | |
context.position = "finally"; | |
if (returned.empty && thrown.empty) { | |
// This path does not leave. | |
return; | |
} | |
/* | |
* Create a parallel segment from merging returned and thrown. | |
* This segment will leave at the end of this finally block. | |
*/ | |
const segments = forkContext.makeNext(-1, -1); | |
for (let i = 0; i < forkContext.count; ++i) { | |
const prevSegsOfLeavingSegment = [headOfLeavingSegments[i]]; | |
for (let j = 0; j < returned.segmentsList.length; ++j) { | |
prevSegsOfLeavingSegment.push(returned.segmentsList[j][i]); | |
} | |
for (let j = 0; j < thrown.segmentsList.length; ++j) { | |
prevSegsOfLeavingSegment.push(thrown.segmentsList[j][i]); | |
} | |
segments.push( | |
CodePathSegment.newNext( | |
this.idGenerator.next(), | |
prevSegsOfLeavingSegment | |
) | |
); | |
} | |
this.pushForkContext(true); | |
this.forkContext.add(segments); | |
} | |
/** | |
* Makes a code path segment from the first throwable node to the `catch` | |
* block or the `finally` block. | |
* @returns {void} | |
*/ | |
makeFirstThrowablePathInTryBlock() { | |
const forkContext = this.forkContext; | |
if (!forkContext.reachable) { | |
return; | |
} | |
const context = getThrowContext(this); | |
if (context === this || | |
context.position !== "try" || | |
!context.thrownForkContext.empty | |
) { | |
return; | |
} | |
context.thrownForkContext.add(forkContext.head); | |
forkContext.replaceHead(forkContext.makeNext(-1, -1)); | |
} | |
//-------------------------------------------------------------------------- | |
// Loop Statements | |
//-------------------------------------------------------------------------- | |
/** | |
* Creates a context object of a loop statement and stacks it. | |
* @param {string} type The type of the node which was triggered. One of | |
* `WhileStatement`, `DoWhileStatement`, `ForStatement`, `ForInStatement`, | |
* and `ForStatement`. | |
* @param {string|null} label A label of the node which was triggered. | |
* @throws {Error} (Unreachable - unknown type.) | |
* @returns {void} | |
*/ | |
pushLoopContext(type, label) { | |
const forkContext = this.forkContext; | |
const breakContext = this.pushBreakContext(true, label); | |
switch (type) { | |
case "WhileStatement": | |
this.pushChoiceContext("loop", false); | |
this.loopContext = { | |
upper: this.loopContext, | |
type, | |
label, | |
test: void 0, | |
continueDestSegments: null, | |
brokenForkContext: breakContext.brokenForkContext | |
}; | |
break; | |
case "DoWhileStatement": | |
this.pushChoiceContext("loop", false); | |
this.loopContext = { | |
upper: this.loopContext, | |
type, | |
label, | |
test: void 0, | |
entrySegments: null, | |
continueForkContext: ForkContext.newEmpty(forkContext), | |
brokenForkContext: breakContext.brokenForkContext | |
}; | |
break; | |
case "ForStatement": | |
this.pushChoiceContext("loop", false); | |
this.loopContext = { | |
upper: this.loopContext, | |
type, | |
label, | |
test: void 0, | |
endOfInitSegments: null, | |
testSegments: null, | |
endOfTestSegments: null, | |
updateSegments: null, | |
endOfUpdateSegments: null, | |
continueDestSegments: null, | |
brokenForkContext: breakContext.brokenForkContext | |
}; | |
break; | |
case "ForInStatement": | |
case "ForOfStatement": | |
this.loopContext = { | |
upper: this.loopContext, | |
type, | |
label, | |
prevSegments: null, | |
leftSegments: null, | |
endOfLeftSegments: null, | |
continueDestSegments: null, | |
brokenForkContext: breakContext.brokenForkContext | |
}; | |
break; | |
/* istanbul ignore next */ | |
default: | |
throw new Error(`unknown type: "${type}"`); | |
} | |
} | |
/** | |
* Pops the last context of a loop statement and finalizes it. | |
* @throws {Error} (Unreachable - unknown type.) | |
* @returns {void} | |
*/ | |
popLoopContext() { | |
const context = this.loopContext; | |
this.loopContext = context.upper; | |
const forkContext = this.forkContext; | |
const brokenForkContext = this.popBreakContext().brokenForkContext; | |
// Creates a looped path. | |
switch (context.type) { | |
case "WhileStatement": | |
case "ForStatement": | |
this.popChoiceContext(); | |
makeLooped( | |
this, | |
forkContext.head, | |
context.continueDestSegments | |
); | |
break; | |
case "DoWhileStatement": { | |
const choiceContext = this.popChoiceContext(); | |
if (!choiceContext.processed) { | |
choiceContext.trueForkContext.add(forkContext.head); | |
choiceContext.falseForkContext.add(forkContext.head); | |
} | |
if (context.test !== true) { | |
brokenForkContext.addAll(choiceContext.falseForkContext); | |
} | |
// `true` paths go to looping. | |
const segmentsList = choiceContext.trueForkContext.segmentsList; | |
for (let i = 0; i < segmentsList.length; ++i) { | |
makeLooped( | |
this, | |
segmentsList[i], | |
context.entrySegments | |
); | |
} | |
break; | |
} | |
case "ForInStatement": | |
case "ForOfStatement": | |
brokenForkContext.add(forkContext.head); | |
makeLooped( | |
this, | |
forkContext.head, | |
context.leftSegments | |
); | |
break; | |
/* istanbul ignore next */ | |
default: | |
throw new Error("unreachable"); | |
} | |
// Go next. | |
if (brokenForkContext.empty) { | |
forkContext.replaceHead(forkContext.makeUnreachable(-1, -1)); | |
} else { | |
forkContext.replaceHead(brokenForkContext.makeNext(0, -1)); | |
} | |
} | |
/** | |
* Makes a code path segment for the test part of a WhileStatement. | |
* @param {boolean|undefined} test The test value (only when constant). | |
* @returns {void} | |
*/ | |
makeWhileTest(test) { | |
const context = this.loopContext; | |
const forkContext = this.forkContext; | |
const testSegments = forkContext.makeNext(0, -1); | |
// Update state. | |
context.test = test; | |
context.continueDestSegments = testSegments; | |
forkContext.replaceHead(testSegments); | |
} | |
/** | |
* Makes a code path segment for the body part of a WhileStatement. | |
* @returns {void} | |
*/ | |
makeWhileBody() { | |
const context = this.loopContext; | |
const choiceContext = this.choiceContext; | |
const forkContext = this.forkContext; | |
if (!choiceContext.processed) { | |
choiceContext.trueForkContext.add(forkContext.head); | |
choiceContext.falseForkContext.add(forkContext.head); | |
} | |
// Update state. | |
if (context.test !== true) { | |
context.brokenForkContext.addAll(choiceContext.falseForkContext); | |
} | |
forkContext.replaceHead(choiceContext.trueForkContext.makeNext(0, -1)); | |
} | |
/** | |
* Makes a code path segment for the body part of a DoWhileStatement. | |
* @returns {void} | |
*/ | |
makeDoWhileBody() { | |
const context = this.loopContext; | |
const forkContext = this.forkContext; | |
const bodySegments = forkContext.makeNext(-1, -1); | |
// Update state. | |
context.entrySegments = bodySegments; | |
forkContext.replaceHead(bodySegments); | |
} | |
/** | |
* Makes a code path segment for the test part of a DoWhileStatement. | |
* @param {boolean|undefined} test The test value (only when constant). | |
* @returns {void} | |
*/ | |
makeDoWhileTest(test) { | |
const context = this.loopContext; | |
const forkContext = this.forkContext; | |
context.test = test; | |
// Creates paths of `continue` statements. | |
if (!context.continueForkContext.empty) { | |
context.continueForkContext.add(forkContext.head); | |
const testSegments = context.continueForkContext.makeNext(0, -1); | |
forkContext.replaceHead(testSegments); | |
} | |
} | |
/** | |
* Makes a code path segment for the test part of a ForStatement. | |
* @param {boolean|undefined} test The test value (only when constant). | |
* @returns {void} | |
*/ | |
makeForTest(test) { | |
const context = this.loopContext; | |
const forkContext = this.forkContext; | |
const endOfInitSegments = forkContext.head; | |
const testSegments = forkContext.makeNext(-1, -1); | |
// Update state. | |
context.test = test; | |
context.endOfInitSegments = endOfInitSegments; | |
context.continueDestSegments = context.testSegments = testSegments; | |
forkContext.replaceHead(testSegments); | |
} | |
/** | |
* Makes a code path segment for the update part of a ForStatement. | |
* @returns {void} | |
*/ | |
makeForUpdate() { | |
const context = this.loopContext; | |
const choiceContext = this.choiceContext; | |
const forkContext = this.forkContext; | |
// Make the next paths of the test. | |
if (context.testSegments) { | |
finalizeTestSegmentsOfFor( | |
context, | |
choiceContext, | |
forkContext.head | |
); | |
} else { | |
context.endOfInitSegments = forkContext.head; | |
} | |
// Update state. | |
const updateSegments = forkContext.makeDisconnected(-1, -1); | |
context.continueDestSegments = context.updateSegments = updateSegments; | |
forkContext.replaceHead(updateSegments); | |
} | |
/** | |
* Makes a code path segment for the body part of a ForStatement. | |
* @returns {void} | |
*/ | |
makeForBody() { | |
const context = this.loopContext; | |
const choiceContext = this.choiceContext; | |
const forkContext = this.forkContext; | |
// Update state. | |
if (context.updateSegments) { | |
context.endOfUpdateSegments = forkContext.head; | |
// `update` -> `test` | |
if (context.testSegments) { | |
makeLooped( | |
this, | |
context.endOfUpdateSegments, | |
context.testSegments | |
); | |
} | |
} else if (context.testSegments) { | |
finalizeTestSegmentsOfFor( | |
context, | |
choiceContext, | |
forkContext.head | |
); | |
} else { | |
context.endOfInitSegments = forkContext.head; | |
} | |
let bodySegments = context.endOfTestSegments; | |
if (!bodySegments) { | |
/* | |
* If there is not the `test` part, the `body` path comes from the | |
* `init` part and the `update` part. | |
*/ | |
const prevForkContext = ForkContext.newEmpty(forkContext); | |
prevForkContext.add(context.endOfInitSegments); | |
if (context.endOfUpdateSegments) { | |
prevForkContext.add(context.endOfUpdateSegments); | |
} | |
bodySegments = prevForkContext.makeNext(0, -1); | |
} | |
context.continueDestSegments = context.continueDestSegments || bodySegments; | |
forkContext.replaceHead(bodySegments); | |
} | |
/** | |
* Makes a code path segment for the left part of a ForInStatement and a | |
* ForOfStatement. | |
* @returns {void} | |
*/ | |
makeForInOfLeft() { | |
const context = this.loopContext; | |
const forkContext = this.forkContext; | |
const leftSegments = forkContext.makeDisconnected(-1, -1); | |
// Update state. | |
context.prevSegments = forkContext.head; | |
context.leftSegments = context.continueDestSegments = leftSegments; | |
forkContext.replaceHead(leftSegments); | |
} | |
/** | |
* Makes a code path segment for the right part of a ForInStatement and a | |
* ForOfStatement. | |
* @returns {void} | |
*/ | |
makeForInOfRight() { | |
const context = this.loopContext; | |
const forkContext = this.forkContext; | |
const temp = ForkContext.newEmpty(forkContext); | |
temp.add(context.prevSegments); | |
const rightSegments = temp.makeNext(-1, -1); | |
// Update state. | |
context.endOfLeftSegments = forkContext.head; | |
forkContext.replaceHead(rightSegments); | |
} | |
/** | |
* Makes a code path segment for the body part of a ForInStatement and a | |
* ForOfStatement. | |
* @returns {void} | |
*/ | |
makeForInOfBody() { | |
const context = this.loopContext; | |
const forkContext = this.forkContext; | |
const temp = ForkContext.newEmpty(forkContext); | |
temp.add(context.endOfLeftSegments); | |
const bodySegments = temp.makeNext(-1, -1); | |
// Make a path: `right` -> `left`. | |
makeLooped(this, forkContext.head, context.leftSegments); | |
// Update state. | |
context.brokenForkContext.add(forkContext.head); | |
forkContext.replaceHead(bodySegments); | |
} | |
//-------------------------------------------------------------------------- | |
// Control Statements | |
//-------------------------------------------------------------------------- | |
/** | |
* Creates new context for BreakStatement. | |
* @param {boolean} breakable The flag to indicate it can break by | |
* an unlabeled BreakStatement. | |
* @param {string|null} label The label of this context. | |
* @returns {Object} The new context. | |
*/ | |
pushBreakContext(breakable, label) { | |
this.breakContext = { | |
upper: this.breakContext, | |
breakable, | |
label, | |
brokenForkContext: ForkContext.newEmpty(this.forkContext) | |
}; | |
return this.breakContext; | |
} | |
/** | |
* Removes the top item of the break context stack. | |
* @returns {Object} The removed context. | |
*/ | |
popBreakContext() { | |
const context = this.breakContext; | |
const forkContext = this.forkContext; | |
this.breakContext = context.upper; | |
// Process this context here for other than switches and loops. | |
if (!context.breakable) { | |
const brokenForkContext = context.brokenForkContext; | |
if (!brokenForkContext.empty) { | |
brokenForkContext.add(forkContext.head); | |
forkContext.replaceHead(brokenForkContext.makeNext(0, -1)); | |
} | |
} | |
return context; | |
} | |
/** | |
* Makes a path for a `break` statement. | |
* | |
* It registers the head segment to a context of `break`. | |
* It makes new unreachable segment, then it set the head with the segment. | |
* @param {string} label A label of the break statement. | |
* @returns {void} | |
*/ | |
makeBreak(label) { | |
const forkContext = this.forkContext; | |
if (!forkContext.reachable) { | |
return; | |
} | |
const context = getBreakContext(this, label); | |
/* istanbul ignore else: foolproof (syntax error) */ | |
if (context) { | |
context.brokenForkContext.add(forkContext.head); | |
} | |
forkContext.replaceHead(forkContext.makeUnreachable(-1, -1)); | |
} | |
/** | |
* Makes a path for a `continue` statement. | |
* | |
* It makes a looping path. | |
* It makes new unreachable segment, then it set the head with the segment. | |
* @param {string} label A label of the continue statement. | |
* @returns {void} | |
*/ | |
makeContinue(label) { | |
const forkContext = this.forkContext; | |
if (!forkContext.reachable) { | |
return; | |
} | |
const context = getContinueContext(this, label); | |
/* istanbul ignore else: foolproof (syntax error) */ | |
if (context) { | |
if (context.continueDestSegments) { | |
makeLooped(this, forkContext.head, context.continueDestSegments); | |
// If the context is a for-in/of loop, this effects a break also. | |
if (context.type === "ForInStatement" || | |
context.type === "ForOfStatement" | |
) { | |
context.brokenForkContext.add(forkContext.head); | |
} | |
} else { | |
context.continueForkContext.add(forkContext.head); | |
} | |
} | |
forkContext.replaceHead(forkContext.makeUnreachable(-1, -1)); | |
} | |
/** | |
* Makes a path for a `return` statement. | |
* | |
* It registers the head segment to a context of `return`. | |
* It makes new unreachable segment, then it set the head with the segment. | |
* @returns {void} | |
*/ | |
makeReturn() { | |
const forkContext = this.forkContext; | |
if (forkContext.reachable) { | |
getReturnContext(this).returnedForkContext.add(forkContext.head); | |
forkContext.replaceHead(forkContext.makeUnreachable(-1, -1)); | |
} | |
} | |
/** | |
* Makes a path for a `throw` statement. | |
* | |
* It registers the head segment to a context of `throw`. | |
* It makes new unreachable segment, then it set the head with the segment. | |
* @returns {void} | |
*/ | |
makeThrow() { | |
const forkContext = this.forkContext; | |
if (forkContext.reachable) { | |
getThrowContext(this).thrownForkContext.add(forkContext.head); | |
forkContext.replaceHead(forkContext.makeUnreachable(-1, -1)); | |
} | |
} | |
/** | |
* Makes the final path. | |
* @returns {void} | |
*/ | |
makeFinal() { | |
const segments = this.currentSegments; | |
if (segments.length > 0 && segments[0].reachable) { | |
this.returnedForkContext.add(segments); | |
} | |
} | |
} | |
module.exports = CodePathState; | |
/***/ }), | |
/***/ 8451: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @fileoverview A class of the code path. | |
* @author Toru Nagashima | |
*/ | |
//------------------------------------------------------------------------------ | |
// Requirements | |
//------------------------------------------------------------------------------ | |
const CodePathState = __webpack_require__(3562); | |
const IdGenerator = __webpack_require__(7847); | |
//------------------------------------------------------------------------------ | |
// Public Interface | |
//------------------------------------------------------------------------------ | |
/** | |
* A code path. | |
*/ | |
class CodePath { | |
/** | |
* Creates a new instance. | |
* @param {Object} options Options for the function (see below). | |
* @param {string} options.id An identifier. | |
* @param {string} options.origin The type of code path origin. | |
* @param {CodePath|null} options.upper The code path of the upper function scope. | |
* @param {Function} options.onLooped A callback function to notify looping. | |
*/ | |
constructor({ id, origin, upper, onLooped }) { | |
/** | |
* The identifier of this code path. | |
* Rules use it to store additional information of each rule. | |
* @type {string} | |
*/ | |
this.id = id; | |
/** | |
* The reason that this code path was started. May be "program", | |
* "function", "class-field-initializer", or "class-static-block". | |
* @type {string} | |
*/ | |
this.origin = origin; | |
/** | |
* The code path of the upper function scope. | |
* @type {CodePath|null} | |
*/ | |
this.upper = upper; | |
/** | |
* The code paths of nested function scopes. | |
* @type {CodePath[]} | |
*/ | |
this.childCodePaths = []; | |
// Initializes internal state. | |
Object.defineProperty( | |
this, | |
"internal", | |
{ value: new CodePathState(new IdGenerator(`${id}_`), onLooped) } | |
); | |
// Adds this into `childCodePaths` of `upper`. | |
if (upper) { | |
upper.childCodePaths.push(this); | |
} | |
} | |
/** | |
* Gets the state of a given code path. | |
* @param {CodePath} codePath A code path to get. | |
* @returns {CodePathState} The state of the code path. | |
*/ | |
static getState(codePath) { | |
return codePath.internal; | |
} | |
/** | |
* The initial code path segment. | |
* @type {CodePathSegment} | |
*/ | |
get initialSegment() { | |
return this.internal.initialSegment; | |
} | |
/** | |
* Final code path segments. | |
* This array is a mix of `returnedSegments` and `thrownSegments`. | |
* @type {CodePathSegment[]} | |
*/ | |
get finalSegments() { | |
return this.internal.finalSegments; | |
} | |
/** | |
* Final code path segments which is with `return` statements. | |
* This array contains the last path segment if it's reachable. | |
* Since the reachable last path returns `undefined`. | |
* @type {CodePathSegment[]} | |
*/ | |
get returnedSegments() { | |
return this.internal.returnedForkContext; | |
} | |
/** | |
* Final code path segments which is with `throw` statements. | |
* @type {CodePathSegment[]} | |
*/ | |
get thrownSegments() { | |
return this.internal.thrownForkContext; | |
} | |
/** | |
* Current code path segments. | |
* @type {CodePathSegment[]} | |
*/ | |
get currentSegments() { | |
return this.internal.currentSegments; | |
} | |
/** | |
* Traverses all segments in this code path. | |
* | |
* codePath.traverseSegments(function(segment, controller) { | |
* // do something. | |
* }); | |
* | |
* This method enumerates segments in order from the head. | |
* | |
* The `controller` object has two methods. | |
* | |
* - `controller.skip()` - Skip the following segments in this branch. | |
* - `controller.break()` - Skip all following segments. | |
* @param {Object} [options] Omittable. | |
* @param {CodePathSegment} [options.first] The first segment to traverse. | |
* @param {CodePathSegment} [options.last] The last segment to traverse. | |
* @param {Function} callback A callback function. | |
* @returns {void} | |
*/ | |
traverseSegments(options, callback) { | |
let resolvedOptions; | |
let resolvedCallback; | |
if (typeof options === "function") { | |
resolvedCallback = options; | |
resolvedOptions = {}; | |
} else { | |
resolvedOptions = options || {}; | |
resolvedCallback = callback; | |
} | |
const startSegment = resolvedOptions.first || this.internal.initialSegment; | |
const lastSegment = resolvedOptions.last; | |
let item = null; | |
let index = 0; | |
let end = 0; | |
let segment = null; | |
const visited = Object.create(null); | |
const stack = [[startSegment, 0]]; | |
let skippedSegment = null; | |
let broken = false; | |
const controller = { | |
skip() { | |
if (stack.length <= 1) { | |
broken = true; | |
} else { | |
skippedSegment = stack[stack.length - 2][0]; | |
} | |
}, | |
break() { | |
broken = true; | |
} | |
}; | |
/** | |
* Checks a given previous segment has been visited. | |
* @param {CodePathSegment} prevSegment A previous segment to check. | |
* @returns {boolean} `true` if the segment has been visited. | |
*/ | |
function isVisited(prevSegment) { | |
return ( | |
visited[prevSegment.id] || | |
segment.isLoopedPrevSegment(prevSegment) | |
); | |
} | |
while (stack.length > 0) { | |
item = stack[stack.length - 1]; | |
segment = item[0]; | |
index = item[1]; | |
if (index === 0) { | |
// Skip if this segment has been visited already. | |
if (visited[segment.id]) { | |
stack.pop(); | |
continue; | |
} | |
// Skip if all previous segments have not been visited. | |
if (segment !== startSegment && | |
segment.prevSegments.length > 0 && | |
!segment.prevSegments.every(isVisited) | |
) { | |
stack.pop(); | |
continue; | |
} | |
// Reset the flag of skipping if all branches have been skipped. | |
if (skippedSegment && segment.prevSegments.indexOf(skippedSegment) !== -1) { | |
skippedSegment = null; | |
} | |
visited[segment.id] = true; | |
// Call the callback when the first time. | |
if (!skippedSegment) { | |
resolvedCallback.call(this, segment, controller); | |
if (segment === lastSegment) { | |
controller.skip(); | |
} | |
if (broken) { | |
break; | |
} | |
} | |
} | |
// Update the stack. | |
end = segment.nextSegments.length - 1; | |
if (index < end) { | |
item[1] += 1; | |
stack.push([segment.nextSegments[index], 0]); | |
} else if (index === end) { | |
item[0] = segment.nextSegments[index]; | |
item[1] = 0; | |
} else { | |
stack.pop(); | |
} | |
} | |
} | |
} | |
module.exports = CodePath; | |
/***/ }), | |
/***/ 3072: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @fileoverview Helpers to debug for code path analysis. | |
* @author Toru Nagashima | |
*/ | |
//------------------------------------------------------------------------------ | |
// Requirements | |
//------------------------------------------------------------------------------ | |
const debug = __webpack_require__(1227)("eslint:code-path"); | |
//------------------------------------------------------------------------------ | |
// Helpers | |
//------------------------------------------------------------------------------ | |
/** | |
* Gets id of a given segment. | |
* @param {CodePathSegment} segment A segment to get. | |
* @returns {string} Id of the segment. | |
*/ | |
/* istanbul ignore next */ | |
function getId(segment) { // eslint-disable-line jsdoc/require-jsdoc -- Ignoring | |
return segment.id + (segment.reachable ? "" : "!"); | |
} | |
/** | |
* Get string for the given node and operation. | |
* @param {ASTNode} node The node to convert. | |
* @param {"enter" | "exit" | undefined} label The operation label. | |
* @returns {string} The string representation. | |
*/ | |
function nodeToString(node, label) { | |
const suffix = label ? `:${label}` : ""; | |
switch (node.type) { | |
case "Identifier": return `${node.type}${suffix} (${node.name})`; | |
case "Literal": return `${node.type}${suffix} (${node.value})`; | |
default: return `${node.type}${suffix}`; | |
} | |
} | |
//------------------------------------------------------------------------------ | |
// Public Interface | |
//------------------------------------------------------------------------------ | |
module.exports = { | |
/** | |
* A flag that debug dumping is enabled or not. | |
* @type {boolean} | |
*/ | |
enabled: debug.enabled, | |
/** | |
* Dumps given objects. | |
* @param {...any} args objects to dump. | |
* @returns {void} | |
*/ | |
dump: debug, | |
/** | |
* Dumps the current analyzing state. | |
* @param {ASTNode} node A node to dump. | |
* @param {CodePathState} state A state to dump. | |
* @param {boolean} leaving A flag whether or not it's leaving | |
* @returns {void} | |
*/ | |
dumpState: !debug.enabled ? debug : /* istanbul ignore next */ function(node, state, leaving) { | |
for (let i = 0; i < state.currentSegments.length; ++i) { | |
const segInternal = state.currentSegments[i].internal; | |
if (leaving) { | |
const last = segInternal.nodes.length - 1; | |
if (last >= 0 && segInternal.nodes[last] === nodeToString(node, "enter")) { | |
segInternal.nodes[last] = nodeToString(node, void 0); | |
} else { | |
segInternal.nodes.push(nodeToString(node, "exit")); | |
} | |
} else { | |
segInternal.nodes.push(nodeToString(node, "enter")); | |
} | |
} | |
debug([ | |
`${state.currentSegments.map(getId).join(",")})`, | |
`${node.type}${leaving ? ":exit" : ""}` | |
].join(" ")); | |
}, | |
/** | |
* Dumps a DOT code of a given code path. | |
* The DOT code can be visualized with Graphvis. | |
* @param {CodePath} codePath A code path to dump. | |
* @returns {void} | |
* @see http://www.graphviz.org | |
* @see http://www.webgraphviz.com | |
*/ | |
dumpDot: !debug.enabled ? debug : /* istanbul ignore next */ function(codePath) { | |
let text = | |
"\n" + | |
"digraph {\n" + | |
"node[shape=box,style=\"rounded,filled\",fillcolor=white];\n" + | |
"initial[label=\"\",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25];\n"; | |
if (codePath.returnedSegments.length > 0) { | |
text += "final[label=\"\",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25];\n"; | |
} | |
if (codePath.thrownSegments.length > 0) { | |
text += "thrown[label=\"✘\",shape=circle,width=0.3,height=0.3,fixedsize];\n"; | |
} | |
const traceMap = Object.create(null); | |
const arrows = this.makeDotArrows(codePath, traceMap); | |
for (const id in traceMap) { // eslint-disable-line guard-for-in -- Want ability to traverse prototype | |
const segment = traceMap[id]; | |
text += `${id}[`; | |
if (segment.reachable) { | |
text += "label=\""; | |
} else { | |
text += "style=\"rounded,dashed,filled\",fillcolor=\"#FF9800\",label=\"<<unreachable>>\\n"; | |
} | |
if (segment.internal.nodes.length > 0) { | |
text += segment.internal.nodes.join("\\n"); | |
} else { | |
text += "????"; | |
} | |
text += "\"];\n"; | |
} | |
text += `${arrows}\n`; | |
text += "}"; | |
debug("DOT", text); | |
}, | |
/** | |
* Makes a DOT code of a given code path. | |
* The DOT code can be visualized with Graphvis. | |
* @param {CodePath} codePath A code path to make DOT. | |
* @param {Object} traceMap Optional. A map to check whether or not segments had been done. | |
* @returns {string} A DOT code of the code path. | |
*/ | |
makeDotArrows(codePath, traceMap) { | |
const stack = [[codePath.initialSegment, 0]]; | |
const done = traceMap || Object.create(null); | |
let lastId = codePath.initialSegment.id; | |
let text = `initial->${codePath.initialSegment.id}`; | |
while (stack.length > 0) { | |
const item = stack.pop(); | |
const segment = item[0]; | |
const index = item[1]; | |
if (done[segment.id] && index === 0) { | |
continue; | |
} | |
done[segment.id] = segment; | |
const nextSegment = segment.allNextSegments[index]; | |
if (!nextSegment) { | |
continue; | |
} | |
if (lastId === segment.id) { | |
text += `->${nextSegment.id}`; | |
} else { | |
text += `;\n${segment.id}->${nextSegment.id}`; | |
} | |
lastId = nextSegment.id; | |
stack.unshift([segment, 1 + index]); | |
stack.push([nextSegment, 0]); | |
} | |
codePath.returnedSegments.forEach(finalSegment => { | |
if (lastId === finalSegment.id) { | |
text += "->final"; | |
} else { | |
text += `;\n${finalSegment.id}->final`; | |
} | |
lastId = null; | |
}); | |
codePath.thrownSegments.forEach(finalSegment => { | |
if (lastId === finalSegment.id) { | |
text += "->thrown"; | |
} else { | |
text += `;\n${finalSegment.id}->thrown`; | |
} | |
lastId = null; | |
}); | |
return `${text};`; | |
} | |
}; | |
/***/ }), | |
/***/ 4303: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @fileoverview A class to operate forking. | |
* | |
* This is state of forking. | |
* This has a fork list and manages it. | |
* | |
* @author Toru Nagashima | |
*/ | |
//------------------------------------------------------------------------------ | |
// Requirements | |
//------------------------------------------------------------------------------ | |
const assert = __webpack_require__(9282), | |
CodePathSegment = __webpack_require__(5100); | |
//------------------------------------------------------------------------------ | |
// Helpers | |
//------------------------------------------------------------------------------ | |
/** | |
* Gets whether or not a given segment is reachable. | |
* @param {CodePathSegment} segment A segment to get. | |
* @returns {boolean} `true` if the segment is reachable. | |
*/ | |
function isReachable(segment) { | |
return segment.reachable; | |
} | |
/** | |
* Creates new segments from the specific range of `context.segmentsList`. | |
* | |
* When `context.segmentsList` is `[[a, b], [c, d], [e, f]]`, `begin` is `0`, and | |
* `end` is `-1`, this creates `[g, h]`. This `g` is from `a`, `c`, and `e`. | |
* This `h` is from `b`, `d`, and `f`. | |
* @param {ForkContext} context An instance. | |
* @param {number} begin The first index of the previous segments. | |
* @param {number} end The last index of the previous segments. | |
* @param {Function} create A factory function of new segments. | |
* @returns {CodePathSegment[]} New segments. | |
*/ | |
function makeSegments(context, begin, end, create) { | |
const list = context.segmentsList; | |
const normalizedBegin = begin >= 0 ? begin : list.length + begin; | |
const normalizedEnd = end >= 0 ? end : list.length + end; | |
const segments = []; | |
for (let i = 0; i < context.count; ++i) { | |
const allPrevSegments = []; | |
for (let j = normalizedBegin; j <= normalizedEnd; ++j) { | |
allPrevSegments.push(list[j][i]); | |
} | |
segments.push(create(context.idGenerator.next(), allPrevSegments)); | |
} | |
return segments; | |
} | |
/** | |
* `segments` becomes doubly in a `finally` block. Then if a code path exits by a | |
* control statement (such as `break`, `continue`) from the `finally` block, the | |
* destination's segments may be half of the source segments. In that case, this | |
* merges segments. | |
* @param {ForkContext} context An instance. | |
* @param {CodePathSegment[]} segments Segments to merge. | |
* @returns {CodePathSegment[]} The merged segments. | |
*/ | |
function mergeExtraSegments(context, segments) { | |
let currentSegments = segments; | |
while (currentSegments.length > context.count) { | |
const merged = []; | |
for (let i = 0, length = currentSegments.length / 2 | 0; i < length; ++i) { | |
merged.push(CodePathSegment.newNext( | |
context.idGenerator.next(), | |
[currentSegments[i], currentSegments[i + length]] | |
)); | |
} | |
currentSegments = merged; | |
} | |
return currentSegments; | |
} | |
//------------------------------------------------------------------------------ | |
// Public Interface | |
//------------------------------------------------------------------------------ | |
/** | |
* A class to manage forking. | |
*/ | |
class ForkContext { | |
/** | |
* @param {IdGenerator} idGenerator An identifier generator for segments. | |
* @param {ForkContext|null} upper An upper fork context. | |
* @param {number} count A number of parallel segments. | |
*/ | |
constructor(idGenerator, upper, count) { | |
this.idGenerator = idGenerator; | |
this.upper = upper; | |
this.count = count; | |
this.segmentsList = []; | |
} | |
/** | |
* The head segments. | |
* @type {CodePathSegment[]} | |
*/ | |
get head() { | |
const list = this.segmentsList; | |
return list.length === 0 ? [] : list[list.length - 1]; | |
} | |
/** | |
* A flag which shows empty. | |
* @type {boolean} | |
*/ | |
get empty() { | |
return this.segmentsList.length === 0; | |
} | |
/** | |
* A flag which shows reachable. | |
* @type {boolean} | |
*/ | |
get reachable() { | |
const segments = this.head; | |
return segments.length > 0 && segments.some(isReachable); | |
} | |
/** | |
* Creates new segments from this context. | |
* @param {number} begin The first index of previous segments. | |
* @param {number} end The last index of previous segments. | |
* @returns {CodePathSegment[]} New segments. | |
*/ | |
makeNext(begin, end) { | |
return makeSegments(this, begin, end, CodePathSegment.newNext); | |
} | |
/** | |
* Creates new segments from this context. | |
* The new segments is always unreachable. | |
* @param {number} begin The first index of previous segments. | |
* @param {number} end The last index of previous segments. | |
* @returns {CodePathSegment[]} New segments. | |
*/ | |
makeUnreachable(begin, end) { | |
return makeSegments(this, begin, end, CodePathSegment.newUnreachable); | |
} | |
/** | |
* Creates new segments from this context. | |
* The new segments don't have connections for previous segments. | |
* But these inherit the reachable flag from this context. | |
* @param {number} begin The first index of previous segments. | |
* @param {number} end The last index of previous segments. | |
* @returns {CodePathSegment[]} New segments. | |
*/ | |
makeDisconnected(begin, end) { | |
return makeSegments(this, begin, end, CodePathSegment.newDisconnected); | |
} | |
/** | |
* Adds segments into this context. | |
* The added segments become the head. | |
* @param {CodePathSegment[]} segments Segments to add. | |
* @returns {void} | |
*/ | |
add(segments) { | |
assert(segments.length >= this.count, `${segments.length} >= ${this.count}`); | |
this.segmentsList.push(mergeExtraSegments(this, segments)); | |
} | |
/** | |
* Replaces the head segments with given segments. | |
* The current head segments are removed. | |
* @param {CodePathSegment[]} segments Segments to add. | |
* @returns {void} | |
*/ | |
replaceHead(segments) { | |
assert(segments.length >= this.count, `${segments.length} >= ${this.count}`); | |
this.segmentsList.splice(-1, 1, mergeExtraSegments(this, segments)); | |
} | |
/** | |
* Adds all segments of a given fork context into this context. | |
* @param {ForkContext} context A fork context to add. | |
* @returns {void} | |
*/ | |
addAll(context) { | |
assert(context.count === this.count); | |
const source = context.segmentsList; | |
for (let i = 0; i < source.length; ++i) { | |
this.segmentsList.push(source[i]); | |
} | |
} | |
/** | |
* Clears all segments in this context. | |
* @returns {void} | |
*/ | |
clear() { | |
this.segmentsList = []; | |
} | |
/** | |
* Creates the root fork context. | |
* @param {IdGenerator} idGenerator An identifier generator for segments. | |
* @returns {ForkContext} New fork context. | |
*/ | |
static newRoot(idGenerator) { | |
const context = new ForkContext(idGenerator, null, 1); | |
context.add([CodePathSegment.newRoot(idGenerator.next())]); | |
return context; | |
} | |
/** | |
* Creates an empty fork context preceded by a given context. | |
* @param {ForkContext} parentContext The parent fork context. | |
* @param {boolean} forkLeavingPath A flag which shows inside of `finally` block. | |
* @returns {ForkContext} New fork context. | |
*/ | |
static newEmpty(parentContext, forkLeavingPath) { | |
return new ForkContext( | |
parentContext.idGenerator, | |
parentContext, | |
(forkLeavingPath ? 2 : 1) * parentContext.count | |
); | |
} | |
} | |
module.exports = ForkContext; | |
/***/ }), | |
/***/ 7847: | |
/***/ (function(module) { | |
"use strict"; | |
/** | |
* @fileoverview A class of identifiers generator for code path segments. | |
* | |
* Each rule uses the identifier of code path segments to store additional | |
* information of the code path. | |
* | |
* @author Toru Nagashima | |
*/ | |
//------------------------------------------------------------------------------ | |
// Public Interface | |
//------------------------------------------------------------------------------ | |
/** | |
* A generator for unique ids. | |
*/ | |
class IdGenerator { | |
/** | |
* @param {string} prefix Optional. A prefix of generated ids. | |
*/ | |
constructor(prefix) { | |
this.prefix = String(prefix); | |
this.n = 0; | |
} | |
/** | |
* Generates id. | |
* @returns {string} A generated id. | |
*/ | |
next() { | |
this.n = 1 + this.n | 0; | |
/* istanbul ignore if */ | |
if (this.n < 0) { | |
this.n = 1; | |
} | |
return this.prefix + this.n; | |
} | |
} | |
module.exports = IdGenerator; | |
/***/ }), | |
/***/ 7555: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/** | |
* @fileoverview Config Comment Parser | |
* @author Nicholas C. Zakas | |
*/ | |
/* eslint class-methods-use-this: off -- Methods desired on instance */ | |
//------------------------------------------------------------------------------ | |
// Requirements | |
//------------------------------------------------------------------------------ | |
const levn = __webpack_require__(4727), | |
{ | |
Legacy: { | |
ConfigOps | |
} | |
} = __webpack_require__(6109); | |
const debug = __webpack_require__(1227)("eslint:config-comment-parser"); | |
//------------------------------------------------------------------------------ | |
// Public Interface | |
//------------------------------------------------------------------------------ | |
/** | |
* Object to parse ESLint configuration comments inside JavaScript files. | |
* @name ConfigCommentParser | |
*/ | |
module.exports = class ConfigCommentParser { | |
/** | |
* Parses a list of "name:string_value" or/and "name" options divided by comma or | |
* whitespace. Used for "global" and "exported" comments. | |
* @param {string} string The string to parse. | |
* @param {Comment} comment The comment node which has the string. | |
* @returns {Object} Result map object of names and string values, or null values if no value was provided | |
*/ | |
parseStringConfig(string, comment) { | |
debug("Parsing String config"); | |
const items = {}; | |
// Collapse whitespace around `:` and `,` to make parsing easier | |
const trimmedString = string.replace(/\s*([:,])\s*/gu, "$1"); | |
trimmedString.split(/\s|,+/u).forEach(name => { | |
if (!name) { | |
return; | |
} | |
// value defaults to null (if not provided), e.g: "foo" => ["foo", null] | |
const [key, value = null] = name.split(":"); | |
items[key] = { value, comment }; | |
}); | |
return items; | |
} | |
/** | |
* Parses a JSON-like config. | |
* @param {string} string The string to parse. | |
* @param {Object} location Start line and column of comments for potential error message. | |
* @returns {({success: true, config: Object}|{success: false, error: Problem})} Result map object | |
*/ | |
parseJsonConfig(string, location) { | |
debug("Parsing JSON config"); | |
let items = {}; | |
// Parses a JSON-like comment by the same way as parsing CLI option. | |
try { | |
items = levn.parse("Object", string) || {}; | |
// Some tests say that it should ignore invalid comments such as `/*eslint no-alert:abc*/`. | |
// Also, commaless notations have invalid severity: | |
// "no-alert: 2 no-console: 2" --> {"no-alert": "2 no-console: 2"} | |
// Should ignore that case as well. | |
if (ConfigOps.isEverySeverityValid(items)) { | |
return { | |
success: true, | |
config: items | |
}; | |
} | |
} catch { | |
debug("Levn parsing failed; falling back to manual parsing."); | |
// ignore to parse the string by a fallback. | |
} | |
/* | |
* Optionator cannot parse commaless notations. | |
* But we are supporting that. So this is a fallback for that. | |
*/ | |
items = {}; | |
const normalizedString = string.replace(/([-a-zA-Z0-9/]+):/gu, "\"$1\":").replace(/(\]|[0-9])\s+(?=")/u, "$1,"); | |
try { | |
items = JSON.parse(`{${normalizedString}}`); | |
} catch (ex) { | |
debug("Manual parsing failed."); | |
return { | |
success: false, | |
error: { | |
ruleId: null, | |
fatal: true, | |
severity: 2, | |
message: `Failed to parse JSON from '${normalizedString}': ${ex.message}`, | |
line: location.start.line, | |
column: location.start.column + 1 | |
} | |
}; | |
} | |
return { | |
success: true, | |
config: items | |
}; | |
} | |
/** | |
* Parses a config of values separated by comma. | |
* @param {string} string The string to parse. | |
* @returns {Object} Result map of values and true values | |
*/ | |
parseListConfig(string) { | |
debug("Parsing list config"); | |
const items = {}; | |
// Collapse whitespace around commas | |
string.replace(/\s*,\s*/gu, ",").split(/,+/u).forEach(name => { | |
const trimmedName = name.trim(); | |
if (trimmedName) { | |
items[trimmedName] = true; | |
} | |
}); | |
return items; | |
} | |
}; | |
/***/ }), | |
/***/ 5811: | |
/***/ (function(module) { | |
"use strict"; | |
/** | |
* @fileoverview Interpolate keys from an object into a string with {{ }} markers. | |
* @author Jed Fox | |
*/ | |
//------------------------------------------------------------------------------ | |
// Public Interface | |
//------------------------------------------------------------------------------ | |
module.exports = (text, data) => { | |
if (!data) { | |
return text; | |
} | |
// Substitution content for any {{ }} markers. | |
return text.replace(/\{\{([^{}]+?)\}\}/gu, (fullMatch, termWithWhitespace) => { | |
const term = termWithWhitespace.trim(); | |
if (term in data) { | |
return data[term]; | |
} | |
// Preserve old behavior: If parameter name not provided, don't replace it. | |
return fullMatch; | |
}); | |
}; | |
/***/ }), | |
/***/ 8500: | |
/***/ (function(module, __unused_webpack_exports, __webpack_require__) { | |
"use strict"; | |
/* provided dependency */ var process = __webpack_require__(4155); | |
/** | |
* @fileoverview Main Linter Class | |
* @author Gyandeep Singh | |
* @author aladdin-add | |
*/ | |
//------------------------------------------------------------------------------ | |
// Requirements | |
//------------------------------------------------------------------------------ | |
const | |
path = __webpack_require__(6470), | |
eslintScope = __webpack_require__(262), | |
evk = __webpack_require__(1286), | |
espree = __webpack_require__(3962), | |
merge = __webpack_require__(2378), | |
pkg = __webpack_require__(1810), | |
astUtils = __webpack_require__(911), | |
{ | |
Legacy: { | |
ConfigOps, | |
ConfigValidator, | |
environments: BuiltInEnvironments | |
} | |
} = __webpack_require__(6109), | |
Traverser = __webpack_require__(6151), | |
{ SourceCode } = __webpack_require__(9233), | |
CodePathAnalyzer = __webpack_require__(6873), | |
applyDisableDirectives = __webpack_require__(613), | |
ConfigCommentParser = __webpack_require__(7555), | |
NodeEventGenerator = __webpack_require__(5403), | |
createReportTranslator = __webpack_require__(6357), | |
Rules = __webpack_require__(3645), | |
createEmitter = __webpack_require__(6331), | |
SourceCodeFixer = __webpack_require__(173), | |
timing = __webpack_require__(7638), | |
ruleReplacements = __webpack_require__(4378); | |
const { getRuleFromConfig } = __webpack_require__(4730); | |
const { FlatConfigArray } = __webpack_require__(2996); | |
const debug = __webpack_require__(1227)("eslint:linter"); | |
const MAX_AUTOFIX_PASSES = 10; | |
const DEFAULT_PARSER_NAME = "espree"; | |
const DEFAULT_ECMA_VERSION = 5; | |
const commentParser = new ConfigCommentParser(); | |
const DEFAULT_ERROR_LOC = { start: { line: 1, column: 0 }, end: { line: 1, column: 1 } }; | |
const parserSymbol = Symbol.for("eslint.RuleTester.parser"); | |
const globals = __webpack_require__(2478); | |
//------------------------------------------------------------------------------ | |
// Typedefs | |
//------------------------------------------------------------------------------ | |
/** @typedef {InstanceType<import("../cli-engine/config-array").ConfigArray>} ConfigArray */ | |
/** @typedef {InstanceType<import("../cli-engine/config-array").ExtractedConfig>} ExtractedConfig */ | |
/** @typedef {import("../shared/types").ConfigData} ConfigData */ | |
/** @typedef {import("../shared/types").Environment} Environment */ | |
/** @typedef {import("../shared/types").GlobalConf} GlobalConf */ | |
/** @typedef {import("../shared/types").LintMessage} LintMessage */ | |
/** @typedef {import("../shared/types").ParserOptions} ParserOptions */ | |
/** @typedef {import("../shared/types").LanguageOptions} LanguageOptions */ | |
/** @typedef {import("../shared/types").Processor} Processor */ | |
/** @typedef {import("../shared/types").Rule} Rule */ | |
/* eslint-disable jsdoc/valid-types -- https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/4#issuecomment-778805577 */ | |
/** | |
* @template T | |
* @typedef {{ [P in keyof T]-?: T[P] }} Required | |
*/ | |
/* eslint-enable jsdoc/valid-types -- https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/4#issuecomment-778805577 */ | |
/** | |
* @typedef {Object} DisableDirective | |
* @property {("disable"|"enable"|"disable-line"|"disable-next-line")} type Type of directive | |
* @property {number} line The line number | |
* @property {number} column The column number | |
* @property {(string|null)} ruleId The rule ID | |
*/ | |
/** | |
* The private data for `Linter` instance. | |
* @typedef {Object} LinterInternalSlots | |
* @property {ConfigArray|null} lastConfigArray The `ConfigArray` instance that the last `verify()` call used. | |
* @property {SourceCode|null} lastSourceCode The `SourceCode` instance that the last `verify()` call used. | |
* @property {Map<string, Parser>} parserMap The loaded parsers. | |
* @property {Rules} ruleMap The loaded rules. | |
*/ | |
/** | |
* @typedef {Object} VerifyOptions | |
* @property {boolean} [allowInlineConfig] Allow/disallow inline comments' ability | |
* to change config once it is set. Defaults to true if not supplied. | |
* Useful if you want to validate JS without comments overriding rules. | |
* @property {boolean} [disableFixes] if `true` then the linter doesn't make `fix` | |
* properties into the lint result. | |
* @property {string} [filename] the filename of the source code. | |
* @property {boolean | "off" | "warn" | "error"} [reportUnusedDisableDirectives] Adds reported errors for | |
* unused `eslint-disable` directives. | |
*/ | |
/** | |
* @typedef {Object} ProcessorOptions | |
* @property {(filename:string, text:string) => boolean} [filterCodeBlock] the | |
* predicate function that selects adopt code blocks. | |
* @property {Processor.postprocess} [postprocess] postprocessor for report | |
* messages. If provided, this should accept an array of the message lists | |
* for each code block returned from the preprocessor, apply a mapping to | |
* the messages as appropriate, and return a one-dimensional array of | |
* messages. | |
* @property {Processor.preprocess} [preprocess] preprocessor for source text. | |
* If provided, this should accept a string of source text, and return an | |
* array of code blocks to lint. | |
*/ | |
/** | |
* @typedef {Object} FixOptions | |
* @property {boolean | ((message: LintMessage) => boolean)} [fix] Determines | |
* whether fixes should be applied. | |
*/ | |
/** | |
* @typedef {Object} InternalOptions | |
* @property {string | null} warnInlineConfig The config name what `noInlineConfig` setting came from. If `noInlineConfig` setting didn't exist, this is null. If this is a config name, then the linter warns directive comments. | |
* @property {"off" | "warn" | "error"} reportUnusedDisableDirectives (boolean values were normalized) | |
*/ | |
//------------------------------------------------------------------------------ | |
// Helpers | |
//------------------------------------------------------------------------------ | |
/** | |
* Determines if a given object is Espree. | |
* @param {Object} parser The parser to check. | |
* @returns {boolean} True if the parser is Espree or false if not. | |
*/ | |
function isEspree(parser) { | |
return !!(parser === espree || parser[parserSymbol] === espree); | |
} | |
/** | |
* Retrieves globals for the given ecmaVersion. | |
* @param {number} ecmaVersion The version to retrieve globals for. | |
* @returns {Object} The globals for the given ecmaVersion. | |
*/ | |
function getGlobalsForEcmaVersion(ecmaVersion) { | |
switch (ecmaVersion) { | |
case 3: | |
return globals.es3; | |
case 5: | |
return globals.es5; | |
default: | |
if (ecmaVersion < 2015) { | |
return globals[`es${ecmaVersion + 2009}`]; | |
} | |
return globals[`es${ecmaVersion}`]; | |
} | |
} | |
/** | |
* Ensures that variables representing built-in properties of the Global Object, | |
* and any globals declared by special block comments, are present in the global | |
* scope. | |
* @param {Scope} globalScope The global scope. | |
* @param {Object} configGlobals The globals declared in configuration | |
* @param {{exportedVariables: Object, enabledGlobals: Object}} commentDirectives Directives from comment configuration | |
* @returns {void} | |
*/ | |
function addDeclaredGlobals(globalScope, configGlobals, { exportedVariables, enabledGlobals }) { | |
// Define configured global variables. | |
for (const id of new Set([...Object.keys(configGlobals), ...Object.keys(enabledGlobals)])) { | |
/* | |
* `ConfigOps.normalizeConfigGlobal` will throw an error if a configured global value is invalid. However, these errors would | |
* typically be caught when validating a config anyway (validity for inline global comments is checked separately). | |
*/ | |
const configValue = configGlobals[id] === void 0 ? void 0 : ConfigOps.normalizeConfigGlobal(configGlobals[id]); | |
const commentValue = enabledGlobals[id] && enabledGlobals[id].value; | |
const value = commentValue || configValue; | |
const sourceComments = enabledGlobals[id] && enabledGlobals[id].comments; | |
if (value === "off") { | |
continue; | |
} | |
let variable = globalScope.set.get(id); | |
if (!variable) { | |
variable = new eslintScope.Variable(id, globalScope); | |
globalScope.variables.push(variable); | |
globalScope.set.set(id, variable); | |
} | |
variable.eslintImplicitGlobalSetting = configValue; | |
variable.eslintExplicitGlobal = sourceComments !== void 0; | |
variable.eslintExplicitGlobalComments = sourceComments; | |
variable.writeable = (value === "writable"); | |
} | |
// mark all exported variables as such | |
Object.keys(exportedVariables).forEach(name => { | |
const variable = globalScope.set.get(name); | |
if (variable) { | |
variable.eslintUsed = true; | |
} | |
}); | |
/* | |
* "through" contains all references which definitions cannot be found. | |
* Since we augment the global scope using configuration, we need to update | |
* references and remove the ones that were added by configuration. | |
*/ | |
globalScope.through = globalScope.through.filter(reference => { | |
const name = reference.identifier.name; | |
const variable = globalScope.set.get(name); | |
if (variable) { | |
/* | |
* Links the variable and the reference. | |
* And this reference is removed from `Scope#through`. | |
*/ | |
reference.resolved = variable; | |
variable.references.push(reference); | |
return false; | |
} | |
return true; | |
}); | |
} | |
/** | |
* creates a missing-rule message. | |
* @param {string} ruleId the ruleId to create | |
* @returns {string} created error message | |
* @private | |
*/ | |
function createMissingRuleMessage(ruleId) { | |
return Object.prototype.hasOwnProperty.call(ruleReplacements.rules, ruleId) | |
? `Rule '${ruleId}' was removed and replaced by: ${ruleReplacements.rules[ruleId].join(", ")}` | |
: `Definition for rule '${ruleId}' was not found.`; | |
} | |
/** | |
* creates a linting problem | |
* @param {Object} options to create linting error | |
* @param {string} [options.ruleId] the ruleId to report | |
* @param {Object} [options.loc] the loc to report | |
* @param {string} [options.message] the error message to report | |
* @param {string} [options.severity] the error message to report | |
* @returns {LintMessage} created problem, returns a missing-rule problem if only provided ruleId. | |
* @private | |
*/ | |
function createLintingProblem(options) { | |
const { | |
ruleId = null, | |
loc = DEFAULT_ERROR_LOC, | |
message = createMissingRuleMessage(options.ruleId), | |
severity = 2 | |
} = options; | |
return { | |
ruleId, | |
message, | |
line: loc.start.line, | |
column: loc.start.column + 1, | |
endLine: loc.end.line, | |
endColumn: loc.end.column + 1, | |
severity, | |
nodeType: null | |
}; | |
} | |
/** | |
* Creates a collection of disable directives from a comment | |
* @param {Object} options to create disable directives | |
* @param {("disable"|"enable"|"disable-line"|"disable-next-line")} options.type The type of directive comment | |
* @param {token} options.commentToken The Comment token | |
* @param {string} options.value The value after the directive in the comment | |
* comment specified no specific rules, so it applies to all rules (e.g. `eslint-disable`) | |
* @param {function(string): {create: Function}} options.ruleMapper A map from rule IDs to defined rules | |
* @returns {Object} Directives and problems from the comment | |
*/ | |
function createDisableDirectives(options) { | |
const { commentToken, type, value, ruleMapper } = options; | |
const ruleIds = Object.keys(commentParser.parseListConfig(value)); | |
const directiveRules = ruleIds.length ? ruleIds : [null]; | |
const result = { | |
directives: [], // valid disable directives | |
directiveProblems: [] // problems in directives | |
}; | |
const parentComment = { commentToken, ruleIds }; | |
for (const ruleId of directiveRules) { | |
// push to directives, if the rule is defined(including null, e.g. /*eslint enable*/) | |
if (ruleId === null || !!ruleMapper(ruleId)) { | |
result.directives.push({ parentComment, type, line: commentToken.loc.start.line, column: commentToken.loc.start.column + 1, ruleId }); | |
} else { | |
result.directiveProblems.push(createLintingProblem({ ruleId, loc: commentToken.loc })); | |
} | |
} | |
return result; | |
} | |
/** | |
* Remove the ignored part from a given directive comment and trim it. | |
* @param {string} value The comment text to strip. | |
* @returns {string} The stripped text. | |
*/ | |
function stripDirectiveComment(value) { | |
return value.split(/\s-{2,}\s/u)[0].trim(); | |
} | |
/** | |
* Parses comments in file to extract file-specific config of rules, globals | |
* and environments and merges them with global config; also code blocks | |
* where reporting is disabled or enabled and merges them with reporting config. | |
* @param {string} filename The file being checked. | |
* @param {ASTNode} ast The top node of the AST. | |
* @param {function(string): {create: Function}} ruleMapper A map from rule IDs to defined rules | |
* @param {string|null} warnInlineConfig If a string then it should warn directive comments as disabled. The string value is the config name what the setting came from. | |
* @returns {{configuredRules: Object, enabledGlobals: {value:string,comment:Token}[], exportedVariables: Object, problems: Problem[], disableDirectives: DisableDirective[]}} | |
* A collection of the directive comments that were found, along with any problems that occurred when parsing | |
*/ | |
function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) { | |
const configuredRules = {}; | |
const enabledGlobals = Object.create(null); | |
const exportedVariables = {}; | |
const problems = []; | |
const disableDirectives = []; | |
const validator = new ConfigValidator({ | |
builtInRules: Rules | |
}); | |
ast.comments.filter(token => token.type !== "Shebang").forEach(comment => { | |
const trimmedCommentText = stripDirectiveComment(comment.value); | |
const match = /^(eslint(?:-env|-enable|-disable(?:(?:-next)?-line)?)?|exported|globals?)(?:\s|$)/u.exec(trimmedCommentText); | |
if (!match) { | |
return; | |
} | |
const directiveText = match[1]; | |
const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(directiveText); | |
if (comment.type === "Line" && !lineCommentSupported) { | |
return; | |
} | |
if (warnInlineConfig) { | |
const kind = comment.type === "Block" ? `/*${directiveText}*/` : `//${directiveText}`; | |
problems.push(createLintingProblem({ | |
ruleId: null, | |
message: `'${kind}' has no effect because you have 'noInlineConfig' setting in ${warnInlineConfig}.`, | |
loc: comment.loc, | |
severity: 1 | |
})); | |
return; | |
} | |
if (lineCommentSupported && comment.loc.start.line !== comment.loc.end.line) { | |
const message = `${directiveText} comment should not span multiple lines.`; | |
problems.push(createLintingProblem({ | |
ruleId: null, | |
message, | |
loc: comment.loc | |
})); | |
return; | |
} | |
const directiveValue = trimmedCommentText.slice(match.index + directiveText.length); | |
switch (directiveText) { | |
case "eslint-disable": | |
case "eslint-enable": | |
case "eslint-disable-next-line": | |
case "eslint-disable-line": { | |
const directiveType = directiveText.slice("eslint-".length); | |
const options = { commentToken: comment, type: directiveType, value: directiveValue, ruleMapper }; | |
const { directives, directiveProblems } = createDisableDirectives(options); | |
disableDirectives.push(...directives); | |
problems.push(...directiveProblems); | |
break; | |
} | |
case "exported": | |
Object.assign(exportedVariables, commentParser.parseStringConfig(directiveValue, comment)); | |
break; | |
case "globals": | |
case "global": | |
for (const [id, { value }] of Object.entries(commentParser.parseStringConfig(directiveValue, comment))) { | |
let normalizedValue; | |
try { | |
normalizedValue = ConfigOps.normalizeConfigGlobal(value); | |
} catch (err) { | |
problems.push(createLintingProblem({ | |
ruleId: null, | |
loc: comment.loc, | |
message: err.message | |
})); | |
continue; | |
} | |
if (enabledGlobals[id]) { | |
enabledGlobals[id].comments.push(comment); | |
enabledGlobals[id].value = normalizedValue; | |
} else { | |
enabledGlobals[id] = { | |
comments: [comment], | |
value: normalizedValue | |
}; | |
} | |
} | |
break; | |
case "eslint": { | |
const parseResult = commentParser.parseJsonConfig(directiveValue, comment.loc); | |
if (parseResult.success) { | |
Object.keys(parseResult.config).forEach(name => { | |
const rule = ruleMapper(name); | |
const ruleValue = parseResult.config[name]; | |
if (!rule) { | |
problems.push(createLintingProblem({ ruleId: name, loc: comment.loc })); | |
return; | |
} | |
try { | |
validator.validateRuleOptions(rule, name, ruleValue); | |
} catch (err) { | |
problems.push(createLintingProblem({ | |
ruleId: name, | |
message: err.message, | |
loc: comment.loc | |
})); | |
// do not apply the config, if found invalid options. | |
return; | |
} | |
configuredRules[name] = ruleValue; | |
}); | |
} else { | |
problems.push(parseResult.error); | |
} | |
break; | |
} | |
// no default | |
} | |
}); | |
return { | |
configuredRules, | |
enabledGlobals, | |
exportedVariables, | |
problems, | |
disableDirectives | |
}; | |
} | |
/** | |
* Normalize ECMAScript version from the initial config | |
* @param {Parser} parser The parser which uses this options. | |
* @param {number} ecmaVersion ECMAScript version from the initial config | |
* @returns {number} normalized ECMAScript version | |
*/ | |
function normalizeEcmaVersion(parser, ecmaVersion) { | |
if (isEspree(parser)) { | |
if (ecmaVersion === "latest") { | |
return espree.latestEcmaVersion; | |
} | |
} | |
/* | |
* Calculate ECMAScript edition number from official year version starting with | |
* ES2015, which corresponds with ES6 (or a difference of 2009). | |
*/ | |
return ecmaVersion >= 2015 ? ecmaVersion - 2009 : ecmaVersion; | |
} | |
/** | |
* Normalize ECMAScript version from the initial config into languageOptions (year) | |
* format. | |
* @param {any} [ecmaVersion] ECMAScript version from the initial config | |
* @returns {number} normalized ECMAScript version | |
*/ | |
function normalizeEcmaVersionForLanguageOptions(ecmaVersion) { | |
switch (ecmaVersion) { | |
case 3: | |
return 3; | |
// void 0 = no ecmaVersion specified so use the default | |
case 5: | |
case void 0: | |
return 5; | |
default: | |
if (typeof ecmaVersion === "number") { | |
return ecmaVersion >= 2015 ? ecmaVersion : ecmaVersion + 2009; | |
} | |
} | |
/* | |
* We default to the latest supported ecmaVersion for everything else. | |
* Remember, this is for languageOptions.ecmaVersion, which sets the version | |
* that is used for a number of processes inside of ESLint. It's normally | |
* safe to assume people want the latest unless otherwise specified. | |
*/ | |
return espree.latestEcmaVersion + 2009; | |
} | |
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)(?:\*\/|$)/gsu; | |
/** | |
* Checks whether or not there is a comment which has "eslint-env *" in a given text. | |
* @param {string} text A source code text to check. | |
* @returns {Object|null} A result of parseListConfig() with "eslint-env *" comment. | |
*/ | |
function findEslintEnv(text) { | |
let match, retv; | |
eslintEnvPattern.lastIndex = 0; | |
while ((match = eslintEnvPattern.exec(text)) !== null) { | |
if (match[0].endsWith("*/")) { | |
retv = Object.assign( | |
retv || {}, | |
commentParser.parseListConfig(stripDirectiveComment(match[1])) | |
); | |
} | |
} | |
return retv; | |
} | |
/** | |
* Convert "/path/to/<text>" to "<text>". | |
* `CLIEngine#executeOnText()` method gives "/path/to/<text>" if the filename | |
* was omitted because `configArray.extractConfig()` requires an absolute path. | |
* But the linter should pass `<text>` to `RuleContext#getFilename()` in that | |
* case. | |
* Also, code blocks can have their virtual filename. If the parent filename was | |
* `<text>`, the virtual filename is `<text>/0_foo.js` or something like (i.e., | |
* it's not an absolute path). | |
* @param {string} filename The filename to normalize. | |
* @returns {string} The normalized filename. | |
*/ | |
function normalizeFilename(filename) { | |
const parts = filename.split(path.sep); | |
const index = parts.lastIndexOf("<text>"); | |
return index === -1 ? filename : parts.slice(index).join(path.sep); | |
} | |
/** | |
* Normalizes the possible options for `linter.verify` and `linter.verifyAndFix` to a | |
* consistent shape. | |
* @param {VerifyOptions} providedOptions Options | |
* @param {ConfigData} config Config. | |
* @returns {Required<VerifyOptions> & InternalOptions} Normalized options | |
*/ | |
function normalizeVerifyOptions(providedOptions, config) { | |
const linterOptions = config.linterOptions || config; | |
// .noInlineConfig for eslintrc, .linterOptions.noInlineConfig for flat | |
const disableInlineConfig = linterOptions.noInlineConfig === true; | |
const ignoreInlineConfig = providedOptions.allowInlineConfig === false; | |
const configNameOfNoInlineConfig = config.configNameOfNoInlineConfig | |
? ` (${config.configNameOfNoInlineConfig})` | |
: ""; | |
let reportUnusedDisableDirectives = providedOptions.reportUnusedDisableDirectives; | |
if (typeof reportUnusedDisableDirectives === "boolean") { | |
reportUnusedDisableDirectives = reportUnusedDisableDirectives ? "error" : "off"; | |
} | |
if (typeof reportUnusedDisableDirectives !== "string") { | |
reportUnusedDisableDirectives = | |
linterOptions.reportUnusedDisableDirectives | |
? "warn" : "off"; | |
} | |
return { | |
filename: normalizeFilename(providedOptions.filename || "<input>"), | |
allowInlineConfig: !ignoreInlineConfig, | |
warnInlineConfig: disableInlineConfig && !ignoreInlineConfig | |
? `your config${configNameOfNoInlineConfig}` | |
: null, | |
reportUnusedDisableDirectives, | |
disableFixes: Boolean(providedOptions.disableFixes) | |
}; | |
} | |
/** | |
* Combines the provided parserOptions with the options from environments | |
* @param {Parser} parser The parser which uses this options. | |
* @param {ParserOptions} providedOptions The provided 'parserOptions' key in a config | |
* @param {Environment[]} enabledEnvironments The environments enabled in configuration and with inline comments | |
* @returns {ParserOptions} Resulting parser options after merge | |
*/ | |
function resolveParserOptions(parser, providedOptions, enabledEnvironments) { | |
const parserOptionsFromEnv = enabledEnvironments | |
.filter(env => env.parserOptions) | |
.reduce((parserOptions, env) => merge(parserOptions, env.parserOptions), {}); | |
const mergedParserOptions = merge(parserOptionsFromEnv, providedOptions || {}); | |
const isModule = mergedParserOptions.sourceType === "module"; | |
if (isModule) { | |
/* | |
* can't have global return inside of modules | |
* TODO: espree validate parserOptions.globalReturn when sourceType is setting to module.(@aladdin-add) | |
*/ | |
mergedParserOptions.ecmaFeatures = Object.assign({}, mergedParserOptions.ecmaFeatures, { globalReturn: false }); | |
} | |
mergedParserOptions.ecmaVersion = normalizeEcmaVersion(parser, mergedParserOptions.ecmaVersion); | |
return mergedParserOptions; | |
} | |
/** | |
* Converts parserOptions to languageOptions for backwards compatibility with eslintrc. | |
* @param {ConfigData} config Config object. | |
* @param {Object} config.globals Global variable definitions. | |
* @param {Parser} config.parser The parser to use. | |
* @param {ParserOptions} config.parserOptions The parserOptions to use. | |
* @returns {LanguageOptions} The languageOptions equivalent. | |
*/ | |
function createLanguageOptions({ globals: configuredGlobals, parser, parserOptions }) { | |
const { | |
ecmaVersion, | |
sourceType | |
} = parserOptions; | |
return { | |
globals: configuredGlobals, | |
ecmaVersion: normalizeEcmaVersionForLanguageOptions(ecmaVersion), | |
sourceType, | |
parser, | |
parserOptions | |
}; | |
} | |
/** | |
* Combines the provided globals object with the globals from environments | |
* @param {Record<string, GlobalConf>} providedGlobals The 'globals' key in a config | |
* @param {Environment[]} enabledEnvironments The environments enabled in configuration and with inline comments | |
* @returns {Record<string, GlobalConf>} The resolved globals object | |
*/ | |
function resolveGlobals(providedGlobals, enabledEnvironments) { | |
return Object.assign( | |
{}, | |
...enabledEnvironments.filter(env => env.globals).map(env => env.globals), | |
providedGlobals | |
); | |
} | |
/** | |
* Strips Unicode BOM from a given text. | |
* @param {string} text A text to strip. | |
* @returns {string} The stripped text. | |
*/ | |
function stripUnicodeBOM(text) { | |
/* | |
* Check Unicode BOM. | |
* In JavaScript, string data is stored as UTF-16, so BOM is 0xFEFF. | |
* http://www.ecma-international.org/ecma-262/6.0/#sec-unicode-format-control-characters | |
*/ | |
if (text.charCodeAt(0) === 0xFEFF) { | |
return text.slice(1); | |
} | |
return text; | |
} | |
/** | |
* Get the options for a rule (not including severity), if any | |
* @param {Array|number} ruleConfig rule configuration | |
* @returns {Array} of rule options, empty Array if none | |
*/ | |
function getRuleOptions(ruleConfig) { | |
if (Array.isArray(ruleConfig)) { | |
return ruleConfig.slice(1); | |
} | |
return []; | |
} | |
/** | |
* Analyze scope of the given AST. | |
* @param {ASTNode} ast The `Program` node to analyze. | |
* @param {LanguageOptions} languageOptions The parser options. | |
* @param {Record<string, string[]>} visitorKeys The visitor keys. | |
* @returns {ScopeManager} The analysis result. | |
*/ | |
function analyzeScope(ast, languageOptions, visitorKeys) { | |
const parserOptions = languageOptions.parserOptions; | |
const ecmaFeatures = parserOptions.ecmaFeatures || {}; | |
const ecmaVersion = languageOptions.ecmaVersion || DEFAULT_ECMA_VERSION; | |
return eslintScope.analyze(ast, { | |
ignoreEval: true, | |
nodejsScope: ecmaFeatures.globalReturn, | |
impliedStrict: ecmaFeatures.impliedStrict, | |
ecmaVersion: typeof ecmaVersion === "number" ? ecmaVersion : 6, | |
sourceType: languageOptions.sourceType || "script", | |
childVisitorKeys: visitorKeys || evk.KEYS, | |
fallback: Traverser.getKeys | |
}); | |
} | |
/** | |
* Parses text into an AST. Moved out here because the try-catch prevents | |
* optimization of functions, so it's best to keep the try-catch as isolated | |
* as possible | |
* @param {string} text The text to parse. | |
* @param {LanguageOptions} languageOptions Options to pass to the parser | |
* @param {string} filePath The path to the file being parsed. | |
* @returns {{success: false, error: Problem}|{success: true, sourceCode: SourceCode}} | |
* An object containing the AST and parser services if parsing was successful, or the error if parsing failed | |
* @private | |
*/ | |
function parse(text, languageOptions, filePath) { | |
const textToParse = stripUnicodeBOM(text).replace(astUtils.shebangPattern, (match, captured) => `//${captured}`); | |
const { ecmaVersion, sourceType, parser } = languageOptions; | |
const parserOptions = Object.assign( | |
{ ecmaVersion, sourceType }, | |
languageOptions.parserOptions, | |
{ | |
loc: true, | |
range: true, | |
raw: true, | |
tokens: true, | |
comment: true, | |
eslintVisitorKeys: true, | |
eslintScopeManager: true, | |
filePath | |
} | |
); | |
/* | |
* Check for parsing errors first. If there's a parsing error, nothing | |
* else can happen. However, a parsing error does not throw an error | |
* from this method - it's just considered a fatal error message, a | |
* problem that ESLint identified just like any other. | |
*/ | |
try { | |
const parseResult = (typeof parser.parseForESLint === "function") | |
? parser.parseForESLint(textToParse, parserOptions) | |
: { ast: parser.parse(textToParse, parserOptions) }; | |
const ast = parseResult.ast; | |
const parserServices = parseResult.services || {}; | |
const visitorKeys = parseResult.visitorKeys || evk.KEYS; | |
const scopeManager = parseResult.scopeManager || analyzeScope(ast, languageOptions, visitorKeys); | |
return { | |
success: true, | |
/* | |
* Save all values that `parseForESLint()` returned. | |
* If a `SourceCode` object is given as the first parameter instead of source code text, | |
* linter skips the parsing process and reuses the source code object. | |
* In that case, linter needs all the values that `parseForESLint()` returned. | |
*/ | |
sourceCode: new SourceCode({ | |
text, | |
ast, | |
parserServices, | |
scopeManager, | |
visitorKeys | |
}) | |
}; | |
} catch (ex) { | |
// If the message includes a leading line number, strip it: | |
const message = `Parsing error: ${ex.message.replace(/^line \d+:/iu, "").trim()}`; | |
debug("%s\n%s", message, ex.stack); | |
return { | |
success: false, | |
error: { | |
ruleId: null, | |
fatal: true, | |
severity: 2, | |
message, | |
line: ex.lineNumber, | |
column: ex.column | |
} | |
}; | |
} | |
} | |
/** | |
* Gets the scope for the current node | |
* @param {ScopeManager} scopeManager The scope manager for this AST | |
* @param {ASTNode} currentNode The node to get the scope of | |
* @returns {eslint-scope.Scope} The scope information for this node | |
*/ | |
function getScope(scopeManager, currentNode) { | |
// On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope. | |
const inner = currentNode.type !== "Program"; | |
for (let node = currentNode; node; node = node.parent) { | |
const scope = scopeManager.acquire(node, inner); | |
if (scope) { | |
if (scope.type === "function-expression-name") { | |
return scope.childScopes[0]; | |
} | |
return scope; | |
} | |
} | |
return scopeManager.scopes[0]; | |
} | |
/** | |
* Marks a variable as used in the current scope | |
* @param {ScopeManager} scopeManager The scope manager for this AST. The scope may be mutated by this function. | |
* @param {ASTNode} currentNode The node currently being traversed | |
* @param {LanguageOptions} languageOptions The options used to parse this text | |
* @param {string} name The name of the variable that should be marked as used. | |
* @returns {boolean} True if the variable was found and marked as used, false if not. | |
*/ | |
function markVariableAsUsed(scopeManager, currentNode, languageOptions, name) { | |
const parserOptions = languageOptions.parserOptions; | |
const sourceType = languageOptions.sourceType; | |
const hasGlobalReturn = | |
(parserOptions.ecmaFeatures && parserOptions.ecmaFeatures.globalReturn) || | |
sourceType === "commonjs"; | |
const specialScope = hasGlobalReturn || sourceType === "module"; | |
const currentScope = getScope(scopeManager, currentNode); | |
// Special Node.js scope means we need to start one level deeper | |
const initialScope = currentScope.type === "global" && specialScope ? currentScope.childScopes[0] : currentScope; | |
for (let scope = initialScope; scope; scope = scope.upper) { | |
const variable = scope.variables.find(scopeVar => scopeVar.name === name); | |
if (variable) { | |
variable.eslintUsed = true; | |
return true; | |
} | |
} | |
return false; | |
} | |
/** | |
* Runs a rule, and gets its listeners | |
* @param {Rule} rule A normalized rule with a `create` method | |
* @param {Context} ruleContext The context that should be passed to the rule | |
* @throws {any} Any error during the rule's `create` | |
* @returns {Object} A map of selector listeners provided by the rule | |
*/ | |
function createRuleListeners(rule, ruleContext) { | |
try { | |
return rule.create(ruleContext); | |
} catch (ex) { | |
ex.message = `Error while loading rule '${ruleContext.id}': ${ex.message}`; | |
throw ex; | |
} | |
} | |
/** | |
* Gets all the ancestors of a given node | |
* @param {ASTNode} node The node | |
* @returns {ASTNode[]} All the ancestor nodes in the AST, not including the provided node, starting | |
* from the root node and going inwards to the parent node. | |
*/ | |
function getAncestors(node) { | |
const ancestorsStartingAtParent = []; | |
for (let ancestor = node.parent; ancestor; ancestor = ancestor.parent) { | |
ancestorsStartingAtParent.push(ancestor); | |
} | |
return ancestorsStartingAtParent.reverse(); | |
} | |
// methods that exist on SourceCode object | |
const DEPRECATED_SOURCECODE_PASSTHROUGHS = { | |
getSource: "getText", | |
getSourceLines: "getLines", | |
getAllComments: "getAllComments", | |
getNodeByRangeIndex: "getNodeByRangeIndex", | |
getComments: "getComments", | |
getCommentsBefore: "getCommentsBefore", | |
getCommentsAfter: "getCommentsAfter", | |
getCommentsInside: "getCommentsInside", | |
getJSDocComment: "getJSDocComment", | |
getFirstToken: "getFirstToken", | |
getFirstTokens: "getFirstTokens", | |
getLastToken: "getLastToken", | |
getLastTokens: "getLastTokens", | |
getTokenAfter: "getTokenAfter", | |
getTokenBefore: "getTokenBefore", | |
getTokenByRangeStart: "getTokenByRangeStart", | |
getTokens: "getTokens", | |
getTokensAfter: "getTokensAfter", | |
getTokensBefore: "getTokensBefore", | |
getTokensBetween: "getTokensBetween" | |
}; | |
const BASE_TRAVERSAL_CONTEXT = Object.freeze( | |
Object.keys(DEPRECATED_SOURCECODE_PASSTHROUGHS).reduce( | |
(contextInfo, methodName) => | |
Object.assign(contextInfo, { | |
[methodName](...args) { | |
return this.getSourceCode()[DEPRECATED_SOURCECODE_PASSTHROUGHS[methodName]](...args); | |
} | |
}), | |
{} | |
) | |
); | |
/** | |
* Runs the given rules on the given SourceCode object | |
* @param {SourceCode} sourceCode A SourceCode object for the given text | |
* @param {Object} configuredRules The rules configuration | |
* @param {function(string): Rule} ruleMapper A mapper function from rule names to rules | |
* @param {string | undefined} parserName The name of the parser in the config | |
* @param {LanguageOptions} languageOptions The options for parsing the code. | |
* @param {Object} settings The settings that were enabled in the config | |
* @param {string} filename The reported filename of the code | |
* @param {boolean} disableFixes If true, it doesn't make `fix` properties. | |
* @param {string | undefined} cwd cwd of the cli | |
* @param {string} physicalFilename The full path of the file on disk without any code block information | |
* @returns {Problem[]} An array of reported problems | |
*/ | |
function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageOptions, settings, filename, disableFixes, cwd, physicalFilename) { | |
const emitter = createEmitter(); | |
const nodeQueue = []; | |
let currentNode = sourceCode.ast; | |
Traverser.traverse(sourceCode.ast, { | |
enter(node, parent) { | |
node.parent = parent; | |
nodeQueue.push({ isEntering: true, node }); | |
}, | |
leave(node) { | |
nodeQueue.push({ isEntering: false, node }); | |
}, | |
visitorKeys: sourceCode.visitorKeys | |
}); | |
/* | |
* Create a frozen object with the ruleContext properties and methods that are shared by all rules. | |
* All rule contexts will inherit from this object. This avoids the performance penalty of copying all the | |
* properties once for each rule. | |
*/ | |
const sharedTraversalContext = Object.freeze( | |
Object.assign( | |
Object.create(BASE_TRAVERSAL_CONTEXT), | |
{ | |
getAncestors: () => getAncestors(currentNode), | |
getDeclaredVariables: sourceCode.scopeManager.getDeclaredVariables.bind(sourceCode.scopeManager), | |
getCwd: () => cwd, | |
getFilename: () => filename, | |
getPhysicalFilename: () => physicalFilename || filename, | |
getScope: () => getScope(sourceCode.scopeManager, currentNode), | |
getSourceCode: () => sourceCode, | |
markVariableAsUsed: name => markVariableAsUsed(sourceCode.scopeManager, currentNode, languageOptions, name), | |
parserOptions: { | |
...languageOptions.parserOptions | |
}, | |
parserPath: parserName, | |
languageOptions, | |
parserServices: sourceCode.parserServices, | |
settings | |
} | |
) | |
); | |
const lintingProblems = []; | |
Object.keys(configuredRules).forEach(ruleId => { | |
const severity = ConfigOps.getRuleSeverity(configuredRules[ruleId]); | |
// not load disabled rules | |
if (severity === 0) { | |
return; | |
} | |
const rule = ruleMapper(ruleId); | |
if (!rule) { | |
lintingProblems.push(createLintingProblem({ ruleId })); | |
return; | |
} | |
const messageIds = rule.meta && rule.meta.messages; | |
let reportTranslator = null; | |
const ruleContext = Object.freeze( | |
Object.assign( | |
Object.create(sharedTraversalContext), | |
{ | |
id: ruleId, | |
options: getRuleOptions(configuredRules[ruleId]), | |
report(...args) { | |
/* | |
* Create a report translator lazily. | |
* In a vast majority of cases, any given rule reports zero errors on a given | |
* piece of code. Creating a translator lazily avoids the performance cost of | |
* creating a new translator function for each rule that usually doesn't get | |
* called. | |
* | |
* Using lazy report translators improves end-to-end performance by about 3% | |
* with Node 8.4.0. | |
*/ | |
if (reportTranslator === null) { | |
reportTranslator = createReportTranslator({ | |
ruleId, | |
severity, | |
sourceCode, | |
messageIds, | |
disableFixes | |
}); | |
} | |
const problem = reportTranslator(...args); | |
if (problem.fix && !(rule.meta && rule.meta.fixable)) { | |
throw new Error("Fixable rules must set the `meta.fixable` property to \"code\" or \"whitespace\"."); | |
} | |
if (problem.suggestions && !(rule.meta && rule.meta.hasSuggestions === true)) { | |
if (rule.meta && rule.meta.docs && typeof rule.meta.docs.suggestion !== "undefined") { | |
// Encourage migration from the former property name. | |
throw new Error("Rules with suggestions must set the `meta.hasSuggestions` property to `true`. `meta.docs.suggestion` is ignored by ESLint."); | |
} | |
throw new Error("Rules with suggestions must set the `meta.hasSuggestions` property to `true`."); | |
} | |
lintingProblems.push(problem); | |
} | |
} | |
) | |
); | |
const ruleListeners = createRuleListeners(rule, ruleContext); | |
/** | |
* Include `ruleId` in error logs | |
* @param {Function} ruleListener A rule method that listens for a node. | |
* @returns {Function} ruleListener wrapped in error handler | |
*/ | |
function addRuleErrorHandler(ruleListener) { | |
return function ruleErrorHandler(...listenerArgs) { | |
try { | |
return ruleListener(...listenerArgs); | |
} catch (e) { | |
e.ruleId = ruleId; | |
throw e; | |
} | |
}; | |
} | |
// add all the selectors from the rule as listeners | |
Object.keys(ruleListeners).forEach(selector => { | |
const ruleListener = timing.enabled | |
? timing.time(ruleId, ruleListeners[selector]) | |
: ruleListeners[selector]; | |
emitter.on( | |
selector, | |
addRuleErrorHandler(ruleListener) | |
); | |
}); | |
}); | |
// only run code path analyzer if the top level node is "Program", skip otherwise | |
const eventGenerator = nodeQueue[0].node.type === "Program" | |
? new CodePathAnalyzer(new NodeEventGenerator(emitter, { visitorKeys: sourceCode.visitorKeys, fallback: Traverser.getKeys })) | |
: new NodeEventGenerator(emitter, { visitorKeys: sourceCode.visitorKeys, fallback: Traverser.getKeys }); | |
nodeQueue.forEach(traversalInfo => { | |
currentNode = traversalInfo.node; | |
try { | |
if (traversalInfo.isEntering) { | |
eventGenerator.enterNode(currentNode); | |
} else { | |
eventGenerator.leaveNode(currentNode); | |
} | |
} catch (err) { | |
err.currentNode = currentNode; | |
throw err; | |
} | |
}); | |
return lintingProblems; | |
} | |
/** | |
* Ensure the source code to be a string. | |
* @param {string|SourceCode} textOrSourceCode The text or source code object. | |
* @returns {string} The source code text. | |
*/ | |
function ensureText(textOrSourceCode) { | |
if (typeof textOrSourceCode === "object") { | |
const { hasBOM, text } = textOrSourceCode; | |
const bom = hasBOM ? "\uFEFF" : ""; | |
return bom + text; | |
} | |
return String(textOrSourceCode); | |
} | |
/** | |
* Get an environment. | |
* @param {LinterInternalSlots} slots The internal slots of Linter. | |
* @param {string} envId The environment ID to get. | |
* @returns {Environment|null} The environment. | |
*/ | |
function getEnv(slots, envId) { | |
return ( | |
(slots.lastConfigArray && slots.lastConfigArray.pluginEnvironments.get(envId)) || | |
BuiltInEnvironments.get(envId) || | |
null | |
); | |
} | |
/** | |
* Get a rule. | |
* @param {LinterInternalSlots} slots The internal slots of Linter. | |
* @param {string} ruleId The rule ID to get. | |
* @returns {Rule|null} The rule. | |
*/ | |
function getRule(slots, ruleId) { | |
return ( | |
(slots.lastConfigArray && slots.lastConfigArray.pluginRules.get(ruleId)) || | |
slots.ruleMap.get(ruleId) | |
); | |
} | |
/** | |
* Normalize the value of the cwd | |
* @param {string | undefined} cwd raw value of the cwd, path to a directory that should be considered as the current working directory, can be undefined. | |
* @returns {string | undefined} normalized cwd | |
*/ | |
function normalizeCwd(cwd) { | |
if (cwd) { | |
return cwd; | |
} | |
if (typeof process === "object") { | |
return process.cwd(); | |
} | |
// It's more explicit to assign the undefined | |
// eslint-disable-next-line no-undefined -- Consistently returning a value | |
return undefined; | |
} | |
/** | |
* The map to store private data. | |
* @type {WeakMap<Linter, LinterInternalSlots>} | |
*/ | |
const internalSlotsMap = new WeakMap(); | |
/** | |
* Throws an error when the given linter is in flat config mode. | |
* @param {Linter} linter The linter to check. | |
* @returns {void} | |
* @throws {Error} If the linter is in flat config mode. | |
*/ | |
function assertEslintrcConfig(linter) { | |
const { configType } = internalSlotsMap.get(linter); | |
if (configType === "flat") { | |
throw new Error("This method cannot be used with flat config. Add your entries directly into the config array."); | |
} | |
} | |
//------------------------------------------------------------------------------ | |
// Public Interface | |
//------------------------------------------------------------------------------ | |
/** | |
* Object that is responsible for verifying JavaScript text | |
* @name Linter | |
*/ | |
class Linter { | |
/** | |
* Initialize the Linter. | |
* @param {Object} [config] the config object | |
* @param {string} [config.cwd] path to a directory that should be considered as the current working directory, can be undefined. | |
* @param {"flat"|"eslintrc"} [config.configType="eslintrc"] the type of config used. | |
*/ | |
constructor({ cwd, configType } = {}) { | |
internalSlotsMap.set(this, { | |
cwd: normalizeCwd(cwd), | |
lastConfigArray: null, | |
lastSourceCode: null, | |
configType, // TODO: Remove after flat config conversion | |
parserMap: new Map([["espree", espree]]), | |
ruleMap: new Rules() | |
}); | |
this.version = pkg.version; | |
} | |
/** | |
* Getter for package version. | |
* @static | |
* @returns {string} The version from package.json. | |
*/ | |
static get version() { | |
return pkg.version; | |
} | |
/** | |
* Same as linter.verify, except without support for processors. | |
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object. | |
* @param {ConfigData} providedConfig An ESLintConfig instance to configure everything. | |
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked. | |
* @throws {Error} If during rule execution. | |
* @returns {LintMessage[]} The results as an array of messages or an empty array if no messages. | |
*/ | |
_verifyWithoutProcessors(textOrSourceCode, providedConfig, providedOptions) { | |
const slots = internalSlotsMap.get(this); | |
const config = providedConfig || {}; | |
const options = normalizeVerifyOptions(providedOptions, config); | |
let text; | |
// evaluate arguments | |
if (typeof textOrSourceCode === "string") { | |
slots.lastSourceCode = null; | |
text = textOrSourceCode; | |
} else { | |
slots.lastSourceCode = textOrSourceCode; | |
text = textOrSourceCode.text; | |
} | |
// Resolve parser. | |
let parserName = DEFAULT_PARSER_NAME; | |
let parser = espree; | |
if (typeof config.parser === "object" && config.parser !== null) { | |
parserName = config.parser.filePath; | |
parser = config.parser.definition; | |
} else if (typeof config.parser === "string") { | |
if (!slots.parserMap.has(config.parser)) { | |
return [{ | |
ruleId: null, | |
fatal: true, | |
severity: 2, | |
message: `Configured parser '${config.parser}' was not found.`, | |
line: 0, | |
column: 0 | |
}]; | |
} | |
parserName = config.parser; | |
parser = slots.parserMap.get(config.parser); | |
} | |
// search and apply "eslint-env *". | |
const envInFile = options.allowInlineConfig && !options.warnInlineConfig | |
? findEslintEnv(text) | |
: {}; | |
const resolvedEnvConfig = Object.assign({ builtin: true }, config.env, envInFile); | |
const enabledEnvs = Object.keys(resolvedEnvConfig) | |
.filter(envName => resolvedEnvConfig[envName]) | |
.map(envName => getEnv(slots, envName)) | |
.filter(env => env); | |
const parserOptions = resolveParserOptions(parser, config.parserOptions || {}, enabledEnvs); | |
const configuredGlobals = resolveGlobals(config.globals || {}, enabledEnvs); | |
const settings = config.settings || {}; | |
const languageOptions = createLanguageOptions({ | |
globals: config.globals, | |
parser, | |
parserOptions | |
}); | |
if (!slots.lastSourceCode) { | |
const parseResult = parse( | |
text, | |
languageOptions, | |
options.filename | |
); | |
if (!parseResult.success) { | |
return [parseResult.error]; | |
} | |
slots.lastSourceCode = parseResult.sourceCode; | |
} else { | |
/* | |
* If the given source code object as the first argument does not have scopeManager, analyze the scope. | |
* This is for backward compatibility (SourceCode is frozen so it cannot rebind). | |
*/ | |
if (!slots.lastSourceCode.scopeManager) { | |
slots.lastSourceCode = new SourceCode({ | |
text: slots.lastSourceCode.text, | |
ast: slots.lastSourceCode.ast, | |
parserServices: slots.lastSourceCode.parserServices, | |
visitorKeys: slots.lastSourceCode.visitorKeys, | |
scopeManager: analyzeScope(slots.lastSourceCode.ast, languageOptions) | |
}); | |
} | |
} | |
const sourceCode = slots.lastSourceCode; | |
const commentDirectives = options.allowInlineConfig | |
? getDirectiveComments(options.filename, sourceCode.ast, ruleId => getRule(slots, ruleId), options.warnInlineConfig) | |
: { configuredRules: {}, enabledGlobals: {}, exportedVariables: {}, problems: [], disableDirectives: [] }; | |
// augment global scope with declared global variables | |
addDeclaredGlobals( | |
sourceCode.scopeManager.scopes[0], | |
configuredGlobals, | |
{ exportedVariables: commentDirectives.exportedVariables, enabledGlobals: commentDirectives.enabledGlobals } | |
); | |
const configuredRules = Object.assign({}, config.rules, commentDirectives.configuredRules); | |
let lintingProblems; | |
try { | |
lintingProblems = runRules( | |
sourceCode, | |
configuredRules, | |
ruleId => getRule(slots, ruleId), | |
parserName, | |
languageOptions, | |
settings, | |
options.filename, | |
options.disableFixes, | |
slots.cwd, | |
providedOptions.physicalFilename | |
); | |
} catch (err) { | |
err.message += `\nOccurred while linting ${options.filename}`; | |
debug("An error occurred while traversing"); | |
debug("Filename:", options.filename); | |
if (err.currentNode) { | |
const { line } = err.currentNode.loc.start; | |
debug("Line:", line); | |
err.message += `:${line}`; | |
} | |
debug("Parser Options:", parserOptions); | |
debug("Parser Path:", parserName); | |
debug("Settings:", settings); | |
if (err.ruleId) { | |
err.message += `\nRule: "${err.ruleId}"`; | |
} | |
throw err; | |
} | |
return applyDisableDirectives({ | |
directives: commentDirectives.disableDirectives, | |
disableFixes: options.disableFixes, | |
problems: lintingProblems | |
.concat(commentDirectives.problems) | |
.sort((problemA, problemB) => problemA.line - problemB.line || problemA.column - problemB.column), | |
reportUnusedDisableDirectives: options.reportUnusedDisableDirectives | |
}); | |
} | |
/** | |
* Verifies the text against the rules specified by the second argument. | |
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object. | |
* @param {ConfigData|ConfigArray} config An ESLintConfig instance to configure everything. | |
* @param {(string|(VerifyOptions&ProcessorOptions))} [filenameOrOptions] The optional filename of the file being checked. | |
* If this is not set, the filename will default to '<input>' in the rule context. If | |
* an object, then it has "filename", "allowInlineConfig", and some properties. | |
* @returns {LintMessage[]} The results as an array of messages or an empty array if no messages. | |
*/ | |
verify(textOrSourceCode, config, filenameOrOptions) { | |
debug("Verify"); | |
const { configType } = internalSlotsMap.get(this); | |
const options = typeof filenameOrOptions === "string" | |
? { filename: filenameOrOptions } | |
: filenameOrOptions || {}; | |
if (config) { | |
if (configType === "flat") { | |
/* | |
* Because of how Webpack packages up the files, we can't | |
* compare directly to `FlatConfigArray` using `instanceof` | |
* because it's not the same `FlatConfigArray` as in the tests. | |
* So, we work around it by assuming an array is, in fact, a | |
* `FlatConfigArray` if it has a `getConfig()` method. | |
*/ | |
let configArray = config; | |
if (!Array.isArray(config) || typeof config.getConfig !== "function") { | |
configArray = new FlatConfigArray(config); | |
configArray.normalizeSync(); | |
} | |
return this._verifyWithFlatConfigArray(textOrSourceCode, configArray, options, true); | |
} | |
if (typeof config.extractConfig === "function") { | |
return this._verifyWithConfigArray(textOrSourceCode, config, options); | |
} | |
} | |
/* | |
* If we get to here, it means `config` is just an object rather | |
* than a config array so we can go right into linting. | |
*/ | |
/* | |
* `Linter` doesn't support `overrides` property in configuration. | |
* So we cannot apply multiple processors. | |
*/ | |
if (options.preprocess || options.postprocess) { | |
return this._verifyWithProcessor(textOrSourceCode, config, options); | |
} | |
return this._verifyWithoutProcessors(textOrSourceCode, config, options); | |
} | |
/** | |
* Verify with a processor. | |
* @param {string|SourceCode} textOrSourceCode The source code. | |
* @param {FlatConfig} config The config array. | |
* @param {VerifyOptions&ProcessorOptions} options The options. | |
* @param {FlatConfigArray} [configForRecursive] The `ConfigArray` object to apply multiple processors recursively. | |
* @returns {LintMessage[]} The found problems. | |
*/ | |
_verifyWithFlatConfigArrayAndProcessor(textOrSourceCode, config, options, configForRecursive) { | |
const filename = options.filename || "<input>"; | |
const filenameToExpose = normalizeFilename(filename); | |
const physicalFilename = options.physicalFilename || filenameToExpose; | |
const text = ensureText(textOrSourceCode); | |
const preprocess = options.preprocess || (rawText => [rawText]); | |
const postprocess = options.postprocess || (messagesList => messagesList.flat()); | |
const filterCodeBlock = | |
options.filterCodeBlock || | |
(blockFilename => blockFilename.endsWith(".js")); | |
const originalExtname = path.extname(filename); | |
const messageLists = preprocess(text, filenameToExpose).map((block, i) => { | |
debug("A code block was found: %o", block.filename || "(unnamed)"); | |
// Keep the legacy behavior. | |
if (typeof block === "string") { | |
return this._verifyWithFlatConfigArrayAndWithoutProcessors(block, config, options); | |
} | |
const blockText = block.text; | |
const blockName = path.join(filename, `${i}_${block.filename}`); | |
// Skip this block if filtered. | |
if (!filterCodeBlock(blockName, blockText)) { | |
debug("This code block was skipped."); | |
return []; | |
} | |
// Resolve configuration again if the file content or extension was changed. | |
if (configForRecursive && (text !== blockText || path.extname(blockName) !== originalExtname)) { | |
debug("Resolving configuration again because the file content or extension was changed."); | |
return this._verifyWithFlatConfigArray( | |
blockText, | |
configForRecursive, | |
{ ...options, filename: blockName, physicalFilename } | |
); | |
} | |
// Does lint. | |
return this._verifyWithFlatConfigArrayAndWithoutProcessors( | |
blockText, | |
config, | |
{ ...options, filename: blockName, physicalFilename } | |
); | |
}); | |
return postprocess(messageLists, filenameToExpose); | |
} | |
/** | |
* Same as linter.verify, except without support for processors. | |
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object. | |
* @param {FlatConfig} providedConfig An ESLintConfig instance to configure everything. | |
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked. | |
* @throws {Error} If during rule execution. | |
* @returns {LintMessage[]} The results as an array of messages or an empty array if no messages. | |
*/ | |
_verifyWithFlatConfigArrayAndWithoutProcessors(textOrSourceCode, providedConfig, providedOptions |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment