mirror of https://github.com/webpack/webpack.git
Merge pull request #8418 from webpack/types/misc
Preliminary work before typing the parsers
This commit is contained in:
commit
5fb6c5ea18
|
|
@ -8,11 +8,14 @@
|
|||
const parseJson = require("json-parse-better-errors");
|
||||
const JsonExportsDependency = require("./dependencies/JsonExportsDependency");
|
||||
|
||||
class JsonParser {
|
||||
constructor(options) {
|
||||
this.options = options;
|
||||
}
|
||||
/** @typedef {import("./NormalModule").ParserState} ParserState */
|
||||
|
||||
class JsonParser {
|
||||
/**
|
||||
* @param {string} source the source to parse
|
||||
* @param {ParserState} state the parser state
|
||||
* @returns {ParserState} the parser state
|
||||
*/
|
||||
parse(source, state) {
|
||||
const data = parseJson(source[0] === "\ufeff" ? source.slice(1) : source);
|
||||
state.module.buildInfo.jsonData = data;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,14 @@ const makeSerializable = require("./util/makeSerializable");
|
|||
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
|
||||
/** @typedef {import("./util/createHash").Hash} Hash */
|
||||
|
||||
/**
|
||||
* @typedef {Object} ParserState
|
||||
* @property {NormalModule} current
|
||||
* @property {NormalModule} module
|
||||
* @property {Compilation} compilation
|
||||
* @property {TODO} options
|
||||
*/
|
||||
|
||||
const EARLY_RETURN_ERROR = new Error("flags early return is not an error");
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
"use strict";
|
||||
|
||||
const path = require("path");
|
||||
|
||||
const NORMALIZE_SLASH_DIRECTION_REGEXP = /\\/g;
|
||||
const PATH_CHARS_REGEXP = /[-[\]{}()*+?.,\\^$|#\s]/g;
|
||||
const SEPARATOR_REGEXP = /[/\\]$/;
|
||||
|
|
@ -13,18 +14,38 @@ const FRONT_OR_BACK_BANG_REGEXP = /^!|!$/g;
|
|||
const INDEX_JS_REGEXP = /\/index.js(!|\?|\(query\))/g;
|
||||
const MATCH_RESOURCE_REGEXP = /!=!/;
|
||||
|
||||
/**
|
||||
* @param {string} request the request
|
||||
* @returns {string} the normalized request
|
||||
*/
|
||||
const normalizeBackSlashDirection = request => {
|
||||
return request.replace(NORMALIZE_SLASH_DIRECTION_REGEXP, "/");
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} path the path to match
|
||||
* @returns {RegExp} the path matcher
|
||||
*/
|
||||
const createRegExpForPath = path => {
|
||||
const regexpTypePartial = path.replace(PATH_CHARS_REGEXP, "\\$&");
|
||||
return new RegExp(`(^|!)${regexpTypePartial}`, "g");
|
||||
};
|
||||
|
||||
class RequestShortener {
|
||||
constructor(directory) {
|
||||
directory = normalizeBackSlashDirection(directory);
|
||||
/**
|
||||
* @param {string} dir the directory
|
||||
*/
|
||||
constructor(dir) {
|
||||
/** @type {RegExp | null} */
|
||||
this.currentDirectoryRegExp = null;
|
||||
/** @type {RegExp | null} */
|
||||
this.parentDirectoryRegExp = null;
|
||||
/** @type {RegExp | null} */
|
||||
this.buildinsRegExp = null;
|
||||
/** @type {boolean} */
|
||||
this.buildinsAsModule = false;
|
||||
|
||||
let directory = normalizeBackSlashDirection(dir);
|
||||
if (SEPARATOR_REGEXP.test(directory)) {
|
||||
directory = directory.substr(0, directory.length - 1);
|
||||
}
|
||||
|
|
@ -38,6 +59,7 @@ class RequestShortener {
|
|||
const parentDirectory = endsWithSeparator
|
||||
? dirname.substr(0, dirname.length - 1)
|
||||
: dirname;
|
||||
|
||||
if (parentDirectory && parentDirectory !== directory) {
|
||||
this.parentDirectoryRegExp = createRegExpForPath(parentDirectory);
|
||||
}
|
||||
|
|
@ -51,11 +73,18 @@ class RequestShortener {
|
|||
this.buildinsRegExp = createRegExpForPath(buildins);
|
||||
}
|
||||
|
||||
/** @type {Map<string, string>} */
|
||||
this.cache = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | undefined | null} request the request to shorten
|
||||
* @returns {string | undefined | null} the shortened request
|
||||
*/
|
||||
shorten(request) {
|
||||
if (!request) return request;
|
||||
if (!request) {
|
||||
return request;
|
||||
}
|
||||
const cacheEntry = this.cache.get(request);
|
||||
if (cacheEntry !== undefined) {
|
||||
return cacheEntry;
|
||||
|
|
|
|||
|
|
@ -10,15 +10,23 @@ const { HookMap, SyncHook, SyncWaterfallHook } = require("tapable");
|
|||
|
||||
/** @typedef {import("enhanced-resolve/lib/Resolver")} Resolver */
|
||||
|
||||
/**
|
||||
* @typedef {Object} ResolverCache
|
||||
* @property {WeakMap<Object, Resolver>} direct
|
||||
* @property {Map<string, Resolver>} stringified
|
||||
*/
|
||||
|
||||
module.exports = class ResolverFactory {
|
||||
constructor() {
|
||||
this.hooks = Object.freeze({
|
||||
/** @type {HookMap<Object>} */
|
||||
resolveOptions: new HookMap(
|
||||
() => new SyncWaterfallHook(["resolveOptions"])
|
||||
),
|
||||
/** @type {HookMap<Resolver, Object>} */
|
||||
resolver: new HookMap(() => new SyncHook(["resolver", "resolveOptions"]))
|
||||
});
|
||||
/** @type {Map<string, { direct: WeakMap<Object, Resolver>, stringified: Map<string, Resolver> }>} */
|
||||
/** @type {Map<string, ResolverCache>} */
|
||||
this.cache = new Map();
|
||||
}
|
||||
|
||||
|
|
@ -37,7 +45,9 @@ module.exports = class ResolverFactory {
|
|||
this.cache.set(type, typedCaches);
|
||||
}
|
||||
const cachedResolver = typedCaches.direct.get(resolveOptions);
|
||||
if (cachedResolver) return cachedResolver;
|
||||
if (cachedResolver) {
|
||||
return cachedResolver;
|
||||
}
|
||||
const ident = JSON.stringify(resolveOptions);
|
||||
const resolver = typedCaches.stringified.get(ident);
|
||||
if (resolver) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ const NullDependency = require("./NullDependency");
|
|||
/** @typedef {import("../ModuleGraph")} ModuleGraph */
|
||||
|
||||
class JsonExportsDependency extends NullDependency {
|
||||
/**
|
||||
* @param {string[]} exports export names
|
||||
*/
|
||||
constructor(exports) {
|
||||
super();
|
||||
this.exports = exports;
|
||||
|
|
|
|||
|
|
@ -5,24 +5,72 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const TOMBSTONE = {};
|
||||
const UNDEFINED_MARKER = {};
|
||||
const TOMBSTONE = Symbol("tombstone");
|
||||
const UNDEFINED_MARKER = Symbol("undefined");
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {T | true | undefined} Cell<T>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {T | true | typeof TOMBSTONE | typeof UNDEFINED_MARKER} InternalCell<T>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template K
|
||||
* @template V
|
||||
* @param {[K, InternalCell<V>]} pair the internal cell
|
||||
* @returns {[K, Cell<V>]} its “safe” representation
|
||||
*/
|
||||
const extractPair = pair => {
|
||||
const key = pair[0];
|
||||
const val = pair[1];
|
||||
if (val === UNDEFINED_MARKER || val === TOMBSTONE) {
|
||||
return [key, undefined];
|
||||
} else {
|
||||
return /** @type {[K, Cell<V>]} */ (pair);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @template K
|
||||
* @template V
|
||||
*/
|
||||
class StackedSetMap {
|
||||
/**
|
||||
* @param {Map<K, V>[]=} parentStack an optional parent
|
||||
*/
|
||||
constructor(parentStack) {
|
||||
this.stack = parentStack === undefined ? [] : parentStack.slice();
|
||||
/** @type {Map<K, InternalCell<V>>} */
|
||||
this.map = new Map();
|
||||
/** @type {Map<K, InternalCell<V>>[]} */
|
||||
this.stack = parentStack === undefined ? [] : parentStack.slice();
|
||||
this.stack.push(this.map);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {K} item the item to add
|
||||
* @returns {void}
|
||||
*/
|
||||
add(item) {
|
||||
this.map.set(item, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {K} item the key of the element to add
|
||||
* @param {V} value the value of the element to add
|
||||
* @returns {void}
|
||||
*/
|
||||
set(item, value) {
|
||||
this.map.set(item, value === undefined ? UNDEFINED_MARKER : value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {K} item the item to delete
|
||||
* @returns {void}
|
||||
*/
|
||||
delete(item) {
|
||||
if (this.stack.length > 1) {
|
||||
this.map.set(item, TOMBSTONE);
|
||||
|
|
@ -31,11 +79,17 @@ class StackedSetMap {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {K} item the item to test
|
||||
* @returns {boolean} true if the item exists in this set
|
||||
*/
|
||||
has(item) {
|
||||
const topValue = this.map.get(item);
|
||||
if (topValue !== undefined) return topValue !== TOMBSTONE;
|
||||
if (topValue !== undefined) {
|
||||
return topValue !== TOMBSTONE;
|
||||
}
|
||||
if (this.stack.length > 1) {
|
||||
for (var i = this.stack.length - 2; i >= 0; i--) {
|
||||
for (let i = this.stack.length - 2; i >= 0; i--) {
|
||||
const value = this.stack[i].get(item);
|
||||
if (value !== undefined) {
|
||||
this.map.set(item, value);
|
||||
|
|
@ -47,6 +101,10 @@ class StackedSetMap {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {K} item the key of the element to return
|
||||
* @returns {Cell<V>} the value of the element
|
||||
*/
|
||||
get(item) {
|
||||
const topValue = this.map.get(item);
|
||||
if (topValue !== undefined) {
|
||||
|
|
@ -55,7 +113,7 @@ class StackedSetMap {
|
|||
: topValue;
|
||||
}
|
||||
if (this.stack.length > 1) {
|
||||
for (var i = this.stack.length - 2; i >= 0; i--) {
|
||||
for (let i = this.stack.length - 2; i >= 0; i--) {
|
||||
const value = this.stack[i].get(item);
|
||||
if (value !== undefined) {
|
||||
this.map.set(item, value);
|
||||
|
|
@ -86,22 +144,17 @@ class StackedSetMap {
|
|||
|
||||
asArray() {
|
||||
this._compress();
|
||||
return Array.from(this.map.entries(), pair => pair[0]);
|
||||
return Array.from(this.map.keys());
|
||||
}
|
||||
|
||||
asSet() {
|
||||
return new Set(this.asArray());
|
||||
this._compress();
|
||||
return new Set(this.map.keys());
|
||||
}
|
||||
|
||||
asPairArray() {
|
||||
this._compress();
|
||||
return Array.from(
|
||||
this.map.entries(),
|
||||
pair =>
|
||||
/** @type {[TODO, TODO]} */ (pair[1] === UNDEFINED_MARKER
|
||||
? [pair[0], undefined]
|
||||
: pair)
|
||||
);
|
||||
return Array.from(this.map.entries(), extractPair);
|
||||
}
|
||||
|
||||
asMap() {
|
||||
|
|
|
|||
|
|
@ -5,23 +5,50 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
module.exports = class TrackingSet {
|
||||
/**
|
||||
* @template T
|
||||
* @template U
|
||||
* @typedef {import("./StackedSetMap")<T,U>} StackedSetMap<T,U>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @template U
|
||||
*/
|
||||
class TrackingSet {
|
||||
/**
|
||||
* @param {StackedSetMap<T,U>} set the set to track
|
||||
*/
|
||||
constructor(set) {
|
||||
/** @type {StackedSetMap<T,U>} */
|
||||
this.set = set;
|
||||
/** @type {Set<T>} */
|
||||
this.set2 = new Set();
|
||||
this.stack = set.stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {T} item the item to add
|
||||
* @returns {void}
|
||||
*/
|
||||
add(item) {
|
||||
this.set2.add(item);
|
||||
return this.set.add(item);
|
||||
this.set.add(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {T} item the item to delete
|
||||
* @returns {void}
|
||||
*/
|
||||
delete(item) {
|
||||
this.set2.delete(item);
|
||||
return this.set.delete(item);
|
||||
this.set.delete(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {T} item the item to test
|
||||
* @returns {boolean} true if the item exists in this set
|
||||
*/
|
||||
has(item) {
|
||||
return this.set.has(item);
|
||||
}
|
||||
|
|
@ -33,4 +60,6 @@ module.exports = class TrackingSet {
|
|||
getAddedItems() {
|
||||
return this.set2;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = TrackingSet;
|
||||
|
|
|
|||
Loading…
Reference in New Issue