| [9af201e] | 1 | /*
|
|---|
| 2 | MIT License http://www.opensource.org/licenses/mit-license.php
|
|---|
| 3 | Author Tobias Koppers @sokra
|
|---|
| 4 | */
|
|---|
| 5 |
|
|---|
| 6 | "use strict";
|
|---|
| 7 |
|
|---|
| 8 | const util = require("util");
|
|---|
| 9 |
|
|---|
| 10 | /** @type {Map<string, () => void>} */
|
|---|
| 11 | const deprecationCache = new Map();
|
|---|
| 12 |
|
|---|
| 13 | /**
|
|---|
| 14 | * Defines the fake hook marker type used by this module.
|
|---|
| 15 | * @typedef {object} FakeHookMarker
|
|---|
| 16 | * @property {true} _fakeHook it's a fake hook
|
|---|
| 17 | */
|
|---|
| 18 |
|
|---|
| 19 | /**
|
|---|
| 20 | * Defines the shared type used by this module.
|
|---|
| 21 | * @template T
|
|---|
| 22 | * @typedef {T & FakeHookMarker} FakeHook<T>
|
|---|
| 23 | */
|
|---|
| 24 |
|
|---|
| 25 | /**
|
|---|
| 26 | * Creates a deprecation.
|
|---|
| 27 | * @param {string} message deprecation message
|
|---|
| 28 | * @param {string} code deprecation code
|
|---|
| 29 | * @returns {() => void} function to trigger deprecation
|
|---|
| 30 | */
|
|---|
| 31 | const createDeprecation = (message, code) => {
|
|---|
| 32 | const cached = deprecationCache.get(message);
|
|---|
| 33 | if (cached !== undefined) return cached;
|
|---|
| 34 | const fn = util.deprecate(
|
|---|
| 35 | () => {},
|
|---|
| 36 | message,
|
|---|
| 37 | `DEP_WEBPACK_DEPRECATION_${code}`
|
|---|
| 38 | );
|
|---|
| 39 | deprecationCache.set(message, fn);
|
|---|
| 40 | return fn;
|
|---|
| 41 | };
|
|---|
| 42 |
|
|---|
| 43 | /** @typedef {"concat" | "entry" | "filter" | "find" | "findIndex" | "includes" | "indexOf" | "join" | "lastIndexOf" | "map" | "reduce" | "reduceRight" | "slice" | "some"} COPY_METHODS_NAMES */
|
|---|
| 44 |
|
|---|
| 45 | /** @type {COPY_METHODS_NAMES[]} */
|
|---|
| 46 | const COPY_METHODS = [
|
|---|
| 47 | "concat",
|
|---|
| 48 | "entry",
|
|---|
| 49 | "filter",
|
|---|
| 50 | "find",
|
|---|
| 51 | "findIndex",
|
|---|
| 52 | "includes",
|
|---|
| 53 | "indexOf",
|
|---|
| 54 | "join",
|
|---|
| 55 | "lastIndexOf",
|
|---|
| 56 | "map",
|
|---|
| 57 | "reduce",
|
|---|
| 58 | "reduceRight",
|
|---|
| 59 | "slice",
|
|---|
| 60 | "some"
|
|---|
| 61 | ];
|
|---|
| 62 |
|
|---|
| 63 | /** @typedef {"copyWithin" | "entries" | "fill" | "keys" | "pop" | "reverse" | "shift" | "splice" | "sort" | "unshift"} DISABLED_METHODS_NAMES */
|
|---|
| 64 |
|
|---|
| 65 | /** @type {DISABLED_METHODS_NAMES[]} */
|
|---|
| 66 | const DISABLED_METHODS = [
|
|---|
| 67 | "copyWithin",
|
|---|
| 68 | "entries",
|
|---|
| 69 | "fill",
|
|---|
| 70 | "keys",
|
|---|
| 71 | "pop",
|
|---|
| 72 | "reverse",
|
|---|
| 73 | "shift",
|
|---|
| 74 | "splice",
|
|---|
| 75 | "sort",
|
|---|
| 76 | "unshift"
|
|---|
| 77 | ];
|
|---|
| 78 |
|
|---|
| 79 | /**
|
|---|
| 80 | * Defines the set with deprecated array methods type used by this module.
|
|---|
| 81 | * @template T
|
|---|
| 82 | * @typedef {Set<T> & { [Symbol.isConcatSpreadable]: boolean } & { push: (...items: T[]) => void, length?: number } & { [P in DISABLED_METHODS_NAMES]: () => void } & { [P in COPY_METHODS_NAMES]: P extends keyof Array<T> ? () => Pick<Array<T>, P> : never }} SetWithDeprecatedArrayMethods
|
|---|
| 83 | */
|
|---|
| 84 |
|
|---|
| 85 | /**
|
|---|
| 86 | * Processes the provided set.
|
|---|
| 87 | * @template T
|
|---|
| 88 | * @param {Set<T>} set new set
|
|---|
| 89 | * @param {string} name property name
|
|---|
| 90 | * @returns {void}
|
|---|
| 91 | */
|
|---|
| 92 | module.exports.arrayToSetDeprecation = (set, name) => {
|
|---|
| 93 | for (const method of COPY_METHODS) {
|
|---|
| 94 | if (/** @type {SetWithDeprecatedArrayMethods<T>} */ (set)[method]) continue;
|
|---|
| 95 | const d = createDeprecation(
|
|---|
| 96 | `${name} was changed from Array to Set (using Array method '${method}' is deprecated)`,
|
|---|
| 97 | "ARRAY_TO_SET"
|
|---|
| 98 | );
|
|---|
| 99 | /** @type {EXPECTED_ANY} */
|
|---|
| 100 | (set)[method] =
|
|---|
| 101 | // eslint-disable-next-line func-names
|
|---|
| 102 | function () {
|
|---|
| 103 | d();
|
|---|
| 104 | // eslint-disable-next-line unicorn/prefer-spread
|
|---|
| 105 | const array = Array.from(this);
|
|---|
| 106 | return Array.prototype[
|
|---|
| 107 | /** @type {keyof COPY_METHODS} */ (method)
|
|---|
| 108 | ].apply(
|
|---|
| 109 | array,
|
|---|
| 110 | // eslint-disable-next-line prefer-rest-params
|
|---|
| 111 | arguments
|
|---|
| 112 | );
|
|---|
| 113 | };
|
|---|
| 114 | }
|
|---|
| 115 | const dPush = createDeprecation(
|
|---|
| 116 | `${name} was changed from Array to Set (using Array method 'push' is deprecated)`,
|
|---|
| 117 | "ARRAY_TO_SET_PUSH"
|
|---|
| 118 | );
|
|---|
| 119 | const dLength = createDeprecation(
|
|---|
| 120 | `${name} was changed from Array to Set (using Array property 'length' is deprecated)`,
|
|---|
| 121 | "ARRAY_TO_SET_LENGTH"
|
|---|
| 122 | );
|
|---|
| 123 | const dIndexer = createDeprecation(
|
|---|
| 124 | `${name} was changed from Array to Set (indexing Array is deprecated)`,
|
|---|
| 125 | "ARRAY_TO_SET_INDEXER"
|
|---|
| 126 | );
|
|---|
| 127 | /** @type {SetWithDeprecatedArrayMethods<T>} */
|
|---|
| 128 | (set).push = function push() {
|
|---|
| 129 | dPush();
|
|---|
| 130 | // eslint-disable-next-line prefer-rest-params, unicorn/prefer-spread
|
|---|
| 131 | for (const item of Array.from(arguments)) {
|
|---|
| 132 | this.add(item);
|
|---|
| 133 | }
|
|---|
| 134 | return this.size;
|
|---|
| 135 | };
|
|---|
| 136 | for (const method of DISABLED_METHODS) {
|
|---|
| 137 | if (/** @type {SetWithDeprecatedArrayMethods<T>} */ (set)[method]) continue;
|
|---|
| 138 |
|
|---|
| 139 | /** @type {SetWithDeprecatedArrayMethods<T>} */
|
|---|
| 140 | (set)[method] = () => {
|
|---|
| 141 | throw new Error(
|
|---|
| 142 | `${name} was changed from Array to Set (using Array method '${method}' is not possible)`
|
|---|
| 143 | );
|
|---|
| 144 | };
|
|---|
| 145 | }
|
|---|
| 146 | /**
|
|---|
| 147 | * Creates an index getter.
|
|---|
| 148 | * @param {number} index index
|
|---|
| 149 | * @returns {() => T | undefined} value
|
|---|
| 150 | */
|
|---|
| 151 | const createIndexGetter = (index) => {
|
|---|
| 152 | /**
|
|---|
| 153 | * Returns the value at this location.
|
|---|
| 154 | * @this {Set<T>} a Set
|
|---|
| 155 | * @returns {T | undefined} the value at this location
|
|---|
| 156 | */
|
|---|
| 157 | // eslint-disable-next-line func-style
|
|---|
| 158 | const fn = function () {
|
|---|
| 159 | dIndexer();
|
|---|
| 160 | let i = 0;
|
|---|
| 161 | for (const item of this) {
|
|---|
| 162 | if (i++ === index) return item;
|
|---|
| 163 | }
|
|---|
| 164 | };
|
|---|
| 165 | return fn;
|
|---|
| 166 | };
|
|---|
| 167 | /**
|
|---|
| 168 | * Define index getter.
|
|---|
| 169 | * @param {number} index index
|
|---|
| 170 | */
|
|---|
| 171 | const defineIndexGetter = (index) => {
|
|---|
| 172 | Object.defineProperty(set, index, {
|
|---|
| 173 | get: createIndexGetter(index),
|
|---|
| 174 | set(value) {
|
|---|
| 175 | throw new Error(
|
|---|
| 176 | `${name} was changed from Array to Set (indexing Array with write is not possible)`
|
|---|
| 177 | );
|
|---|
| 178 | }
|
|---|
| 179 | });
|
|---|
| 180 | };
|
|---|
| 181 | defineIndexGetter(0);
|
|---|
| 182 | let indexerDefined = 1;
|
|---|
| 183 | Object.defineProperty(set, "length", {
|
|---|
| 184 | get() {
|
|---|
| 185 | dLength();
|
|---|
| 186 | const length = this.size;
|
|---|
| 187 | for (indexerDefined; indexerDefined < length + 1; indexerDefined++) {
|
|---|
| 188 | defineIndexGetter(indexerDefined);
|
|---|
| 189 | }
|
|---|
| 190 | return length;
|
|---|
| 191 | },
|
|---|
| 192 | set(value) {
|
|---|
| 193 | throw new Error(
|
|---|
| 194 | `${name} was changed from Array to Set (writing to Array property 'length' is not possible)`
|
|---|
| 195 | );
|
|---|
| 196 | }
|
|---|
| 197 | });
|
|---|
| 198 | /** @type {SetWithDeprecatedArrayMethods<T>} */
|
|---|
| 199 | (set)[Symbol.isConcatSpreadable] = true;
|
|---|
| 200 | };
|
|---|
| 201 |
|
|---|
| 202 | /**
|
|---|
| 203 | * Returns } SetDeprecatedArray.
|
|---|
| 204 | * @template T
|
|---|
| 205 | * @param {string} name name
|
|---|
| 206 | * @returns {{ new <T = EXPECTED_ANY>(values?: ReadonlyArray<T> | null): SetDeprecatedArray<T> }} SetDeprecatedArray
|
|---|
| 207 | */
|
|---|
| 208 | module.exports.createArrayToSetDeprecationSet = (name) => {
|
|---|
| 209 | let initialized = false;
|
|---|
| 210 |
|
|---|
| 211 | /**
|
|---|
| 212 | * Represents SetDeprecatedArray.
|
|---|
| 213 | * @template T
|
|---|
| 214 | */
|
|---|
| 215 | class SetDeprecatedArray extends Set {
|
|---|
| 216 | /**
|
|---|
| 217 | * Creates an instance of SetDeprecatedArray.
|
|---|
| 218 | * @param {ReadonlyArray<T> | null=} items items
|
|---|
| 219 | */
|
|---|
| 220 | constructor(items) {
|
|---|
| 221 | super(items);
|
|---|
| 222 | if (!initialized) {
|
|---|
| 223 | initialized = true;
|
|---|
| 224 | module.exports.arrayToSetDeprecation(
|
|---|
| 225 | /** @type {SetWithDeprecatedArrayMethods<T>} */
|
|---|
| 226 | (SetDeprecatedArray.prototype),
|
|---|
| 227 | name
|
|---|
| 228 | );
|
|---|
| 229 | }
|
|---|
| 230 | }
|
|---|
| 231 | }
|
|---|
| 232 | return SetDeprecatedArray;
|
|---|
| 233 | };
|
|---|
| 234 |
|
|---|
| 235 | /**
|
|---|
| 236 | * Returns fake hook which redirects.
|
|---|
| 237 | * @template {object} T
|
|---|
| 238 | * @param {T} fakeHook fake hook implementation
|
|---|
| 239 | * @param {string=} message deprecation message (not deprecated when unset)
|
|---|
| 240 | * @param {string=} code deprecation code (not deprecated when unset)
|
|---|
| 241 | * @returns {FakeHook<T>} fake hook which redirects
|
|---|
| 242 | */
|
|---|
| 243 | module.exports.createFakeHook = (fakeHook, message, code) => {
|
|---|
| 244 | if (message && code) {
|
|---|
| 245 | fakeHook = deprecateAllProperties(fakeHook, message, code);
|
|---|
| 246 | }
|
|---|
| 247 | return Object.freeze(
|
|---|
| 248 | Object.assign(fakeHook, { _fakeHook: /** @type {true} */ (true) })
|
|---|
| 249 | );
|
|---|
| 250 | };
|
|---|
| 251 |
|
|---|
| 252 | /**
|
|---|
| 253 | * Deprecate all properties.
|
|---|
| 254 | * @template T
|
|---|
| 255 | * @param {T} obj object
|
|---|
| 256 | * @param {string} message deprecation message
|
|---|
| 257 | * @param {string} code deprecation code
|
|---|
| 258 | * @returns {T} object with property access deprecated
|
|---|
| 259 | */
|
|---|
| 260 | const deprecateAllProperties = (obj, message, code) => {
|
|---|
| 261 | const newObj = {};
|
|---|
| 262 | const descriptors = Object.getOwnPropertyDescriptors(obj);
|
|---|
| 263 | for (const name of Object.keys(descriptors)) {
|
|---|
| 264 | const descriptor = descriptors[name];
|
|---|
| 265 | if (typeof descriptor.value === "function") {
|
|---|
| 266 | Object.defineProperty(newObj, name, {
|
|---|
| 267 | ...descriptor,
|
|---|
| 268 | value: util.deprecate(descriptor.value, message, code)
|
|---|
| 269 | });
|
|---|
| 270 | } else if (descriptor.get || descriptor.set) {
|
|---|
| 271 | Object.defineProperty(newObj, name, {
|
|---|
| 272 | ...descriptor,
|
|---|
| 273 | get: descriptor.get && util.deprecate(descriptor.get, message, code),
|
|---|
| 274 | set: descriptor.set && util.deprecate(descriptor.set, message, code)
|
|---|
| 275 | });
|
|---|
| 276 | } else {
|
|---|
| 277 | let value = descriptor.value;
|
|---|
| 278 | Object.defineProperty(newObj, name, {
|
|---|
| 279 | configurable: descriptor.configurable,
|
|---|
| 280 | enumerable: descriptor.enumerable,
|
|---|
| 281 | get: util.deprecate(() => value, message, code),
|
|---|
| 282 | set: descriptor.writable
|
|---|
| 283 | ? util.deprecate(
|
|---|
| 284 | /**
|
|---|
| 285 | * Handles the callback logic for this hook.
|
|---|
| 286 | * @template T
|
|---|
| 287 | * @param {T} v value
|
|---|
| 288 | * @returns {T} result
|
|---|
| 289 | */
|
|---|
| 290 | (v) => (value = v),
|
|---|
| 291 | message,
|
|---|
| 292 | code
|
|---|
| 293 | )
|
|---|
| 294 | : undefined
|
|---|
| 295 | });
|
|---|
| 296 | }
|
|---|
| 297 | }
|
|---|
| 298 | return /** @type {T} */ (newObj);
|
|---|
| 299 | };
|
|---|
| 300 |
|
|---|
| 301 | module.exports.deprecateAllProperties = deprecateAllProperties;
|
|---|
| 302 |
|
|---|
| 303 | /**
|
|---|
| 304 | * Returns frozen object with deprecation when modifying.
|
|---|
| 305 | * @template {object} T
|
|---|
| 306 | * @param {T} obj object
|
|---|
| 307 | * @param {string} name property name
|
|---|
| 308 | * @param {string} code deprecation code
|
|---|
| 309 | * @param {string} note additional note
|
|---|
| 310 | * @returns {T} frozen object with deprecation when modifying
|
|---|
| 311 | */
|
|---|
| 312 | module.exports.soonFrozenObjectDeprecation = (obj, name, code, note = "") => {
|
|---|
| 313 | const message = `${name} will be frozen in future, all modifications are deprecated.${
|
|---|
| 314 | note && `\n${note}`
|
|---|
| 315 | }`;
|
|---|
| 316 | return /** @type {T} */ (
|
|---|
| 317 | new Proxy(obj, {
|
|---|
| 318 | set: util.deprecate(
|
|---|
| 319 | /**
|
|---|
| 320 | * Handles the callback logic for this hook.
|
|---|
| 321 | * @param {object} target target
|
|---|
| 322 | * @param {string | symbol} property property
|
|---|
| 323 | * @param {EXPECTED_ANY} value value
|
|---|
| 324 | * @param {EXPECTED_ANY} receiver receiver
|
|---|
| 325 | * @returns {boolean} result
|
|---|
| 326 | */
|
|---|
| 327 | (target, property, value, receiver) =>
|
|---|
| 328 | Reflect.set(target, property, value, receiver),
|
|---|
| 329 | message,
|
|---|
| 330 | code
|
|---|
| 331 | ),
|
|---|
| 332 | defineProperty: util.deprecate(
|
|---|
| 333 | /**
|
|---|
| 334 | * Handles the define property callback for this hook.
|
|---|
| 335 | * @param {object} target target
|
|---|
| 336 | * @param {string | symbol} property property
|
|---|
| 337 | * @param {PropertyDescriptor} descriptor descriptor
|
|---|
| 338 | * @returns {boolean} result
|
|---|
| 339 | */
|
|---|
| 340 | (target, property, descriptor) =>
|
|---|
| 341 | Reflect.defineProperty(target, property, descriptor),
|
|---|
| 342 | message,
|
|---|
| 343 | code
|
|---|
| 344 | ),
|
|---|
| 345 | deleteProperty: util.deprecate(
|
|---|
| 346 | /**
|
|---|
| 347 | * Handles the delete property callback for this hook.
|
|---|
| 348 | * @param {object} target target
|
|---|
| 349 | * @param {string | symbol} property property
|
|---|
| 350 | * @returns {boolean} result
|
|---|
| 351 | */
|
|---|
| 352 | (target, property) => Reflect.deleteProperty(target, property),
|
|---|
| 353 | message,
|
|---|
| 354 | code
|
|---|
| 355 | ),
|
|---|
| 356 | setPrototypeOf: util.deprecate(
|
|---|
| 357 | /**
|
|---|
| 358 | * Updates prototype of using the provided target.
|
|---|
| 359 | * @param {object} target target
|
|---|
| 360 | * @param {EXPECTED_OBJECT | null} proto proto
|
|---|
| 361 | * @returns {boolean} result
|
|---|
| 362 | */
|
|---|
| 363 | (target, proto) => Reflect.setPrototypeOf(target, proto),
|
|---|
| 364 | message,
|
|---|
| 365 | code
|
|---|
| 366 | )
|
|---|
| 367 | })
|
|---|
| 368 | );
|
|---|
| 369 | };
|
|---|