diff --git a/packages/rspack/etc/api.md b/packages/rspack/etc/api.md index a9d6cca3b3a..f3d16cd6ce0 100644 --- a/packages/rspack/etc/api.md +++ b/packages/rspack/etc/api.md @@ -14,13 +14,12 @@ import CacheFacade = require('./lib/CacheFacade'); import type { Callback } from '@rspack/lite-tapable'; import { cleanupGlobalTrace } from '@rspack/binding'; import { Compiler as Compiler_2 } from '../Compiler'; +import { default as default_2 } from './util/hash'; import { RawEvalDevToolModulePluginOptions as EvalDevToolModulePluginOptions } from '@rspack/binding'; import { EventEmitter } from 'events'; import { ExternalObject } from '@rspack/binding'; import fs from 'graceful-fs'; import { fs as fs_2 } from 'fs'; -import Hash_2 = require('./util/hash'); -import Hash_3 = require('../util/hash'); import { HookMap } from '@rspack/lite-tapable'; import type { JsAssetInfo } from '@rspack/binding'; import { JsChunk } from '@rspack/binding'; @@ -1118,7 +1117,7 @@ export class Compilation { // @public (undocumented) type CompilationHooks = { - chunkHash: liteTapable.SyncHook<[Chunk, Hash_3]>; + chunkHash: liteTapable.SyncHook<[Chunk, Hash_2]>; }; // @public (undocumented) @@ -3952,6 +3951,12 @@ class Hash { update(data: string | Buffer, inputEncoding?: string): Hash; } +// @public (undocumented) +class Hash_2 { + digest(encoding?: string): string | Buffer; + update(data: string | Buffer, inputEncoding?: string): this; +} + // @public (undocumented) export type HashDigest = z.infer; @@ -4924,7 +4929,7 @@ export interface LoaderContext { utils: { absolutify: (context: string, request: string) => string; contextify: (context: string, request: string) => string; - createHash: (algorithm?: string) => Hash_3; + createHash: (algorithm?: string) => Hash_2; }; // (undocumented) version: 2; @@ -13818,8 +13823,8 @@ const uniqueName: z.ZodString; // @public (undocumented) export const util: { - createHash: (algorithm: any) => any; - cleverMerge: (first: T, second: O) => T | O | (T & O); + createHash: (algorithm: "debug" | "md4" | "xxhash64" | (string & {}) | "native-md4" | (new () => default_2)) => default_2; + cleverMerge: (first: First, second: Second) => First | Second | (First & Second); }; // @public (undocumented) diff --git a/packages/rspack/src/Compilation.ts b/packages/rspack/src/Compilation.ts index 074a680f765..240add93cce 100644 --- a/packages/rspack/src/Compilation.ts +++ b/packages/rspack/src/Compilation.ts @@ -28,6 +28,7 @@ import { cutOffLoaderExecution } from "./ErrorHelpers"; import { type CodeGenerationResult, Module } from "./Module"; import type { NormalModuleFactory } from "./NormalModuleFactory"; import type { ResolverFactory } from "./ResolverFactory"; +import { JsDiagnostic, type RspackError } from "./RspackError"; import { Stats, type StatsAsset, @@ -48,10 +49,9 @@ import { StatsPrinter } from "./stats/StatsPrinter"; import { type AssetInfo, JsAssetInfo } from "./util/AssetInfo"; import MergeCaller from "./util/MergeCaller"; import { createFakeCompilationDependencies } from "./util/fake"; +import type Hash from "./util/hash"; import { memoizeValue } from "./util/memoize"; import { JsSource } from "./util/source"; -import Hash = require("./util/hash"); -import { JsDiagnostic, type RspackError } from "./RspackError"; export { type AssetInfo } from "./util/AssetInfo"; export type Assets = Record; diff --git a/packages/rspack/src/Compiler.ts b/packages/rspack/src/Compiler.ts index d51fc26012e..3001994cf62 100644 --- a/packages/rspack/src/Compiler.ts +++ b/packages/rspack/src/Compiler.ts @@ -976,6 +976,9 @@ class Compiler { binding.RegisterJsTapKind.CompilationChunkHash, () => this.#compilation!.hooks.chunkHash, queried => (chunk: binding.JsChunk) => { + if (!this.options.output.hashFunction) { + throw new Error("'output.hashFunction' cannot be undefined"); + } const hash = createHash(this.options.output.hashFunction); queried.call(Chunk.__from_binding(chunk, this.#compilation!), hash); const digestResult = hash.digest(this.options.output.hashDigest); @@ -1175,6 +1178,9 @@ class Compiler { JavascriptModulesPlugin.getCompilationHooks(this.#compilation!) .chunkHash, queried => (chunk: binding.JsChunk) => { + if (!this.options.output.hashFunction) { + throw new Error("'output.hashFunction' cannot be undefined"); + } const hash = createHash(this.options.output.hashFunction); queried.call(Chunk.__from_binding(chunk, this.#compilation!), hash); const digestResult = hash.digest(this.options.output.hashDigest); diff --git a/packages/rspack/src/ModuleTypeConstants.js b/packages/rspack/src/ModuleTypeConstants.js deleted file mode 100644 index b62eda91d59..00000000000 --- a/packages/rspack/src/ModuleTypeConstants.js +++ /dev/null @@ -1,169 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Sean Larkin @TheLarkInn -*/ - -"use strict"; - -/** - * @type {Readonly<"javascript/auto">} - */ -const JAVASCRIPT_MODULE_TYPE_AUTO = "javascript/auto"; - -/** - * @type {Readonly<"javascript/dynamic">} - */ -const JAVASCRIPT_MODULE_TYPE_DYNAMIC = "javascript/dynamic"; - -/** - * @type {Readonly<"javascript/esm">} - * This is the module type used for _strict_ ES Module syntax. This means that all legacy formats - * that webpack supports (CommonJS, AMD, SystemJS) are not supported. - */ -const JAVASCRIPT_MODULE_TYPE_ESM = "javascript/esm"; - -/** - * @type {Readonly<"json">} - * This is the module type used for JSON files. JSON files are always parsed as ES Module. - */ -const JSON_MODULE_TYPE = "json"; - -/** - * @type {Readonly<"webassembly/async">} - * This is the module type used for WebAssembly modules. In webpack 5 they are always treated as async modules. - * - */ -const WEBASSEMBLY_MODULE_TYPE_ASYNC = "webassembly/async"; - -/** - * @type {Readonly<"webassembly/sync">} - * This is the module type used for WebAssembly modules. In webpack 4 they are always treated as sync modules. - * There is a legacy option to support this usage in webpack 5 and up. - */ -const WEBASSEMBLY_MODULE_TYPE_SYNC = "webassembly/sync"; - -/** - * @type {Readonly<"css">} - * This is the module type used for CSS files. - */ -const CSS_MODULE_TYPE = "css"; - -/** - * @type {Readonly<"css/global">} - * This is the module type used for CSS modules files where you need to use `:local` in selector list to hash classes. - */ -const CSS_MODULE_TYPE_GLOBAL = "css/global"; - -/** - * @type {Readonly<"css/module">} - * This is the module type used for CSS modules files, by default all classes are hashed. - */ -const CSS_MODULE_TYPE_MODULE = "css/module"; - -/** - * @type {Readonly<"css/auto">} - * This is the module type used for CSS files, the module will be parsed as CSS modules if it's filename contains `.module.` or `.modules.`. - */ -const CSS_MODULE_TYPE_AUTO = "css/auto"; - -/** - * @type {Readonly<"asset">} - * This is the module type used for automatically choosing between `asset/inline`, `asset/resource` based on asset size limit (8096). - */ -const ASSET_MODULE_TYPE = "asset"; - -/** - * @type {Readonly<"asset/inline">} - * This is the module type used for assets that are inlined as a data URI. This is the equivalent of `url-loader`. - */ -const ASSET_MODULE_TYPE_INLINE = "asset/inline"; - -/** - * @type {Readonly<"asset/resource">} - * This is the module type used for assets that are copied to the output directory. This is the equivalent of `file-loader`. - */ -const ASSET_MODULE_TYPE_RESOURCE = "asset/resource"; - -/** - * @type {Readonly<"asset/source">} - * This is the module type used for assets that are imported as source code. This is the equivalent of `raw-loader`. - */ -const ASSET_MODULE_TYPE_SOURCE = "asset/source"; - -/** - * @type {Readonly<"asset/raw-data-url">} - * TODO: Document what this asset type is for. See css-loader tests for its usage. - */ -const ASSET_MODULE_TYPE_RAW_DATA_URL = "asset/raw-data-url"; - -/** - * @type {Readonly<"runtime">} - * This is the module type used for the webpack runtime abstractions. - */ -const WEBPACK_MODULE_TYPE_RUNTIME = "runtime"; - -/** - * @type {Readonly<"fallback-module">} - * This is the module type used for the ModuleFederation feature's FallbackModule class. - * TODO: Document this better. - */ -const WEBPACK_MODULE_TYPE_FALLBACK = "fallback-module"; - -/** - * @type {Readonly<"remote-module">} - * This is the module type used for the ModuleFederation feature's RemoteModule class. - * TODO: Document this better. - */ -const WEBPACK_MODULE_TYPE_REMOTE = "remote-module"; - -/** - * @type {Readonly<"provide-module">} - * This is the module type used for the ModuleFederation feature's ProvideModule class. - * TODO: Document this better. - */ -const WEBPACK_MODULE_TYPE_PROVIDE = "provide-module"; - -/** - * @type {Readonly<"consume-shared-module">} - * This is the module type used for the ModuleFederation feature's ConsumeSharedModule class. - */ -const WEBPACK_MODULE_TYPE_CONSUME_SHARED_MODULE = "consume-shared-module"; - -/** - * @type {Readonly<"lazy-compilation-proxy">} - * Module type used for `experiments.lazyCompilation` feature. See `LazyCompilationPlugin` for more information. - */ -const WEBPACK_MODULE_TYPE_LAZY_COMPILATION_PROXY = "lazy-compilation-proxy"; - -/** @typedef {"javascript/auto" | "javascript/dynamic" | "javascript/esm"} JavaScriptModuleTypes */ -/** @typedef {"json"} JSONModuleType */ -/** @typedef {"webassembly/async" | "webassembly/sync"} WebAssemblyModuleTypes */ -/** @typedef {"css" | "css/global" | "css/module"} CSSModuleTypes */ -/** @typedef {"asset" | "asset/inline" | "asset/resource" | "asset/source" | "asset/raw-data-url"} AssetModuleTypes */ -/** @typedef {"runtime" | "fallback-module" | "remote-module" | "provide-module" | "consume-shared-module" | "lazy-compilation-proxy"} WebpackModuleTypes */ -/** @typedef {string} UnknownModuleTypes */ -/** @typedef {JavaScriptModuleTypes | JSONModuleType | WebAssemblyModuleTypes | CSSModuleTypes | AssetModuleTypes | WebpackModuleTypes | UnknownModuleTypes} ModuleTypes */ - -exports.ASSET_MODULE_TYPE = ASSET_MODULE_TYPE; -exports.ASSET_MODULE_TYPE_RAW_DATA_URL = ASSET_MODULE_TYPE_RAW_DATA_URL; -exports.ASSET_MODULE_TYPE_SOURCE = ASSET_MODULE_TYPE_SOURCE; -exports.ASSET_MODULE_TYPE_RESOURCE = ASSET_MODULE_TYPE_RESOURCE; -exports.ASSET_MODULE_TYPE_INLINE = ASSET_MODULE_TYPE_INLINE; -exports.JAVASCRIPT_MODULE_TYPE_AUTO = JAVASCRIPT_MODULE_TYPE_AUTO; -exports.JAVASCRIPT_MODULE_TYPE_DYNAMIC = JAVASCRIPT_MODULE_TYPE_DYNAMIC; -exports.JAVASCRIPT_MODULE_TYPE_ESM = JAVASCRIPT_MODULE_TYPE_ESM; -exports.JSON_MODULE_TYPE = JSON_MODULE_TYPE; -exports.WEBASSEMBLY_MODULE_TYPE_ASYNC = WEBASSEMBLY_MODULE_TYPE_ASYNC; -exports.WEBASSEMBLY_MODULE_TYPE_SYNC = WEBASSEMBLY_MODULE_TYPE_SYNC; -exports.CSS_MODULE_TYPE = CSS_MODULE_TYPE; -exports.CSS_MODULE_TYPE_GLOBAL = CSS_MODULE_TYPE_GLOBAL; -exports.CSS_MODULE_TYPE_MODULE = CSS_MODULE_TYPE_MODULE; -exports.CSS_MODULE_TYPE_AUTO = CSS_MODULE_TYPE_AUTO; -exports.WEBPACK_MODULE_TYPE_RUNTIME = WEBPACK_MODULE_TYPE_RUNTIME; -exports.WEBPACK_MODULE_TYPE_FALLBACK = WEBPACK_MODULE_TYPE_FALLBACK; -exports.WEBPACK_MODULE_TYPE_REMOTE = WEBPACK_MODULE_TYPE_REMOTE; -exports.WEBPACK_MODULE_TYPE_PROVIDE = WEBPACK_MODULE_TYPE_PROVIDE; -exports.WEBPACK_MODULE_TYPE_CONSUME_SHARED_MODULE = - WEBPACK_MODULE_TYPE_CONSUME_SHARED_MODULE; -exports.WEBPACK_MODULE_TYPE_LAZY_COMPILATION_PROXY = - WEBPACK_MODULE_TYPE_LAZY_COMPILATION_PROXY; diff --git a/packages/rspack/src/ModuleTypeConstants.ts b/packages/rspack/src/ModuleTypeConstants.ts new file mode 100644 index 00000000000..b90c715b1a4 --- /dev/null +++ b/packages/rspack/src/ModuleTypeConstants.ts @@ -0,0 +1,149 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Sean Larkin @TheLarkInn +*/ + +export const JAVASCRIPT_MODULE_TYPE_AUTO = "javascript/auto"; + +export const JAVASCRIPT_MODULE_TYPE_DYNAMIC = "javascript/dynamic"; + +/** + * This is the module type used for _strict_ ES Module syntax. This means that all legacy formats + * that webpack supports (CommonJS, AMD, SystemJS) are not supported. + */ +export const JAVASCRIPT_MODULE_TYPE_ESM = "javascript/esm"; + +/** + * This is the module type used for JSON files. JSON files are always parsed as ES Module. + */ +export const JSON_MODULE_TYPE = "json"; + +/** + * This is the module type used for WebAssembly modules. In webpack 5 they are always treated as async modules. + * + */ +export const WEBASSEMBLY_MODULE_TYPE_ASYNC = "webassembly/async"; + +/** + * This is the module type used for WebAssembly modules. In webpack 4 they are always treated as sync modules. + * There is a legacy option to support this usage in webpack 5 and up. + */ +export const WEBASSEMBLY_MODULE_TYPE_SYNC = "webassembly/sync"; + +/** + * This is the module type used for CSS files. + */ +export const CSS_MODULE_TYPE = "css"; + +/** + * This is the module type used for CSS modules files where you need to use `:local` in selector list to hash classes. + */ +export const CSS_MODULE_TYPE_GLOBAL = "css/global"; + +/** + * This is the module type used for CSS modules files, by default all classes are hashed. + */ +export const CSS_MODULE_TYPE_MODULE = "css/module"; + +/** + * This is the module type used for CSS files, the module will be parsed as CSS modules if it's filename contains `.module.` or `.modules.`. + */ +export const CSS_MODULE_TYPE_AUTO = "css/auto"; + +/** + * This is the module type used for automatically choosing between `asset/inline`, `asset/resource` based on asset size limit (8096). + */ +export const ASSET_MODULE_TYPE = "asset"; + +/** + * This is the module type used for assets that are inlined as a data URI. This is the equivalent of `url-loader`. + */ +export const ASSET_MODULE_TYPE_INLINE = "asset/inline"; + +/** + * This is the module type used for assets that are copied to the output directory. This is the equivalent of `file-loader`. + */ +export const ASSET_MODULE_TYPE_RESOURCE = "asset/resource"; + +/** + * @type {Readonly<"asset/source">} + * This is the module type used for assets that are imported as source code. This is the equivalent of `raw-loader`. + */ +export const ASSET_MODULE_TYPE_SOURCE = "asset/source"; + +/** + * TODO: Document what this asset type is for. See css-loader tests for its usage. + */ +export const ASSET_MODULE_TYPE_RAW_DATA_URL = "asset/raw-data-url"; + +/** + * This is the module type used for the webpack runtime abstractions. + */ +export const WEBPACK_MODULE_TYPE_RUNTIME = "runtime"; + +/** + * This is the module type used for the ModuleFederation feature's FallbackModule class. + * TODO: Document this better. + */ +export const WEBPACK_MODULE_TYPE_FALLBACK = "fallback-module"; + +/** + * This is the module type used for the ModuleFederation feature's RemoteModule class. + * TODO: Document this better. + */ +export const WEBPACK_MODULE_TYPE_REMOTE = "remote-module"; + +/** + * This is the module type used for the ModuleFederation feature's ProvideModule class. + * TODO: Document this better. + */ +export const WEBPACK_MODULE_TYPE_PROVIDE = "provide-module"; + +/** + * This is the module type used for the ModuleFederation feature's ConsumeSharedModule class. + */ +export const WEBPACK_MODULE_TYPE_CONSUME_SHARED_MODULE = + "consume-shared-module"; + +/** + * Module type used for `experiments.lazyCompilation` feature. See `LazyCompilationPlugin` for more information. + */ +export const WEBPACK_MODULE_TYPE_LAZY_COMPILATION_PROXY = + "lazy-compilation-proxy"; + +export type JavaScriptModuleTypes = + | "javascript/auto" + | "javascript/dynamic" + | "javascript/esm"; + +export type JSONModuleType = "json"; + +export type WebAssemblyModuleTypes = "webassembly/async" | "webassembly/sync"; + +export type CSSModuleTypes = "css" | "css/global" | "css/module"; + +export type AssetModuleTypes = + | "asset" + | "asset/inline" + | "asset/resource" + | "asset/source" + | "asset/raw-data-url"; + +export type WebpackModuleTypes = + | "runtime" + | "fallback-module" + | "remote-module" + | "provide-module" + | "consume-shared-module" + | "lazy-compilation-proxy"; + +export type UnknownModuleTypes = string; + +export type ModuleTypes = + | JavaScriptModuleTypes + | JSONModuleType + | WebAssemblyModuleTypes + | CSSModuleTypes + | AssetModuleTypes + | WebpackModuleTypes + | UnknownModuleTypes; diff --git a/packages/rspack/src/builtin-plugin/JavascriptModulesPlugin.ts b/packages/rspack/src/builtin-plugin/JavascriptModulesPlugin.ts index 949aa8981de..bb102969a85 100644 --- a/packages/rspack/src/builtin-plugin/JavascriptModulesPlugin.ts +++ b/packages/rspack/src/builtin-plugin/JavascriptModulesPlugin.ts @@ -1,10 +1,10 @@ import { type BuiltinPlugin, BuiltinPluginName } from "@rspack/binding"; import * as liteTapable from "@rspack/lite-tapable"; +import type { Chunk } from "../Chunk"; import { Compilation } from "../Compilation"; +import type Hash from "../util/hash"; import { RspackBuiltinPlugin, createBuiltinPlugin } from "./base"; -import Hash = require("../util/hash"); -import type { Chunk } from "../Chunk"; export type CompilationHooks = { chunkHash: liteTapable.SyncHook<[Chunk, Hash]>; diff --git a/packages/rspack/src/config/adapterRuleUse.ts b/packages/rspack/src/config/adapterRuleUse.ts index 321c626b2f8..1969569b823 100644 --- a/packages/rspack/src/config/adapterRuleUse.ts +++ b/packages/rspack/src/config/adapterRuleUse.ts @@ -5,14 +5,14 @@ import type { } from "@rspack/binding"; import type { ResolveRequest } from "enhanced-resolve"; -import type { Compiler } from "../Compiler"; -import type { Logger } from "../logging/Logger"; -import Hash = require("../util/hash"); import type { Compilation } from "../Compilation"; +import type { Compiler } from "../Compiler"; import type { Module } from "../Module"; import { resolvePluginImport } from "../builtin-loader"; import { type LoaderObject, parsePathQueryFragment } from "../loader-runner"; +import type { Logger } from "../logging/Logger"; import { isNil } from "../util"; +import type Hash from "../util/hash"; import type { Mode, PublicPath, diff --git a/packages/rspack/src/loader-runner/index.ts b/packages/rspack/src/loader-runner/index.ts index e1783757c16..442020830b1 100644 --- a/packages/rspack/src/loader-runner/index.ts +++ b/packages/rspack/src/loader-runner/index.ts @@ -712,7 +712,7 @@ export async function runLoaders( }, createHash: type => { return createHash( - type || compiler._lastCompilation!.outputOptions.hashFunction + type || compiler._lastCompilation!.outputOptions.hashFunction! ); } }; diff --git a/packages/rspack/src/util/cleverMerge.js b/packages/rspack/src/util/cleverMerge.ts similarity index 71% rename from packages/rspack/src/util/cleverMerge.js rename to packages/rspack/src/util/cleverMerge.ts index 15751397ce6..fd414e7cd36 100644 --- a/packages/rspack/src/util/cleverMerge.js +++ b/packages/rspack/src/util/cleverMerge.ts @@ -7,20 +7,55 @@ * Copyright (c) JS Foundation and other contributors * https://github.com/webpack/webpack/blob/main/LICENSE */ +type Obj = Record; -"use strict"; +type Info = Map; -/** @type {WeakMap>} */ -const mergeCache = new WeakMap(); -/** @type {WeakMap>>} */ -const setPropertyCache = new WeakMap(); -const DELETE = Symbol("DELETE"); +type FunctionWithDynamicInfo = ((...args: any[]) => any) & { + [DYNAMIC_INFO]?: [FunctionWithDynamicInfo, Obj]; +}; + +type DynamicInfo = { + byProperty: string; + fn: FunctionWithDynamicInfo; +}; + +type ParsedObject = { + /** + * static properties (key is property name) + */ + static: Map; + /** + * dynamic part + */ + dynamic: DynamicInfo | undefined; +}; + +type ObjectParsedPropertyEntry = { + /** + * base value + */ + base: any; + /** + * the name of the selector property + */ + byProperty: string | undefined; + /** + * value depending on selector property, merged with base + */ + byValues: Map; +}; + +const mergeCache = new WeakMap>(); +const setPropertyCache = new WeakMap< + Obj, + Map> +>(); +export const DELETE = Symbol("DELETE"); const DYNAMIC_INFO = Symbol("cleverMerge dynamic info"); /** * Merges two given objects and caches the result to avoid computation if same objects passed as arguments again. - * @template T - * @template O * @example * // performs cleverMerge(first, second), stores the result in WeakMap and returns result * cachedCleverMerge({a: 1}, {a: 2}) @@ -28,11 +63,14 @@ const DYNAMIC_INFO = Symbol("cleverMerge dynamic info"); * // when same arguments passed, gets the result from WeakMap and returns it. * cachedCleverMerge({a: 1}, {a: 2}) * {a: 2} - * @param {T} first first object - * @param {O} second second object - * @returns {T & O | T | O} merged object of first and second object + * @param first first object + * @param second second object + * @returns merged object of first and second object */ -const cachedCleverMerge = (first, second) => { +export const cachedCleverMerge = ( + first: First, + second: Second +): First | Second | (First & Second) => { if (second === undefined) return first; if (first === undefined) return second; if (typeof second !== "object" || second === null) return second; @@ -44,22 +82,24 @@ const cachedCleverMerge = (first, second) => { mergeCache.set(first, innerCache); } const prevMerge = innerCache.get(second); - // @ts-expect-error + if (prevMerge !== undefined) return prevMerge; const newMerge = _cleverMerge(first, second, true); innerCache.set(second, newMerge); - // @ts-expect-error return newMerge; }; /** - * @template T - * @param {Partial} obj object - * @param {string} property property - * @param {string|number|boolean} value assignment value - * @returns {T} new object + * @param obj object + * @param property property + * @param value assignment value + * @returns new object */ -const cachedSetProperty = (obj, property, value) => { +export const cachedSetProperty = ( + obj: Obj, + property: string, + value: string | number | boolean +) => { let mapByProperty = setPropertyCache.get(obj); if (mapByProperty === undefined) { @@ -76,7 +116,6 @@ const cachedSetProperty = (obj, property, value) => { let result = mapByValue.get(value); - // @ts-expect-error if (result) return result; result = { @@ -85,31 +124,16 @@ const cachedSetProperty = (obj, property, value) => { }; mapByValue.set(value, result); - // @ts-expect-error return result; }; -/** - * @typedef {Object} ObjectParsedPropertyEntry - * @property {any | undefined} base base value - * @property {string | undefined} byProperty the name of the selector property - * @property {Map} byValues value depending on selector property, merged with base - */ +const parseCache = new WeakMap(); /** - * @typedef {Object} ParsedObject - * @property {Map} static static properties (key is property name) - * @property {{ byProperty: string, fn: Function } | undefined} dynamic dynamic part + * @param obj the object + * @returns parsed object */ - -/** @type {WeakMap} */ -const parseCache = new WeakMap(); - -/** - * @param {object} obj the object - * @returns {ParsedObject} parsed object - */ -const cachedParseObject = obj => { +const cachedParseObject = (obj: Obj) => { const entry = parseCache.get(obj); if (entry !== undefined) return entry; const result = parseObject(obj); @@ -121,17 +145,16 @@ const cachedParseObject = obj => { * @param {object} obj the object * @returns {ParsedObject} parsed object */ -const parseObject = obj => { - const info = new Map(); - let dynamicInfo; - // @ts-expect-error - const getInfo = p => { +const parseObject = (obj: Obj): ParsedObject => { + const info: Info = new Map(); + let dynamicInfo: DynamicInfo | undefined; + const getInfo = (p: any) => { const entry = info.get(p); if (entry !== undefined) return entry; const newEntry = { base: undefined, byProperty: undefined, - byValues: undefined + byValues: new Map() }; info.set(p, newEntry); return newEntry; @@ -139,7 +162,6 @@ const parseObject = obj => { for (const key of Object.keys(obj)) { if (key.startsWith("by")) { const byProperty = key; - // @ts-expect-error const byObj = obj[byProperty]; if (typeof byObj === "object") { for (const byValue of Object.keys(byObj)) { @@ -148,7 +170,6 @@ const parseObject = obj => { const entry = getInfo(key); if (entry.byProperty === undefined) { entry.byProperty = byProperty; - entry.byValues = new Map(); } else if (entry.byProperty !== byProperty) { throw new Error( `${byProperty} and ${entry.byProperty} for a single property is not supported` @@ -176,12 +197,10 @@ const parseObject = obj => { } } else { const entry = getInfo(key); - // @ts-expect-error entry.base = obj[key]; } } else { const entry = getInfo(key); - // @ts-expect-error entry.base = obj[key]; } } @@ -192,16 +211,15 @@ const parseObject = obj => { }; /** - * @param {Map} info static properties (key is property name) - * @param {{ byProperty: string, fn: Function } | undefined} dynamicInfo dynamic part - * @returns {object} the object + * @param info static properties (key is property name) + * @param dynamicInfo dynamic part + * @returns the object */ -const serializeObject = (info, dynamicInfo) => { - const obj = {}; +const serializeObject = (info: Info, dynamicInfo: DynamicInfo | undefined) => { + const obj: Obj = {}; // Setup byProperty structure for (const entry of info.values()) { if (entry.byProperty !== undefined) { - // @ts-expect-error const byObj = (obj[entry.byProperty] = obj[entry.byProperty] || {}); for (const byValue of entry.byValues.keys()) { byObj[byValue] = byObj[byValue] || {}; @@ -210,12 +228,10 @@ const serializeObject = (info, dynamicInfo) => { } for (const [key, entry] of info) { if (entry.base !== undefined) { - // @ts-expect-error obj[key] = entry.base; } // Fill byProperty structure if (entry.byProperty !== undefined) { - // @ts-expect-error const byObj = (obj[entry.byProperty] = obj[entry.byProperty] || {}); for (const byValue of Object.keys(byObj)) { const value = getFromByValues(entry.byValues, byValue); @@ -224,7 +240,6 @@ const serializeObject = (info, dynamicInfo) => { } } if (dynamicInfo !== undefined) { - // @ts-expect-error obj[dynamicInfo.byProperty] = dynamicInfo.fn; } return obj; @@ -237,10 +252,10 @@ const VALUE_TYPE_OBJECT = 3; const VALUE_TYPE_DELETE = 4; /** - * @param {any} value a single value + * @param value a single value * @returns {VALUE_TYPE_UNDEFINED | VALUE_TYPE_ATOM | VALUE_TYPE_ARRAY_EXTEND | VALUE_TYPE_OBJECT | VALUE_TYPE_DELETE} value type */ -const getValueType = value => { +const getValueType = (value: any) => { if (value === undefined) { return VALUE_TYPE_UNDEFINED; } else if (value === DELETE) { @@ -262,30 +277,34 @@ const getValueType = value => { * Merges two objects. Objects are deeply clever merged. * Arrays might reference the old value with "...". * Non-object values take preference over object values. - * @template T - * @template O - * @param {T} first first object - * @param {O} second second object - * @returns {T & O | T | O} merged object of first and second object + * @param first first object + * @param second second object + * @returns merged object of first and second object */ -const cleverMerge = (first, second) => { +export const cleverMerge = ( + first: First, + second: Second +): First | Second | (First & Second) => { if (second === undefined) return first; if (first === undefined) return second; if (typeof second !== "object" || second === null) return second; if (typeof first !== "object" || first === null) return first; - // @ts-expect-error return _cleverMerge(first, second, false); }; /** * Merges two objects. Objects are deeply clever merged. - * @param {object} first first object - * @param {object} second second object - * @param {boolean} internalCaching should parsing of objects and nested merges be cached - * @returns {object} merged object of first and second object + * @param first first object + * @param second second object + * @param internalCaching should parsing of objects and nested merges be cached + * @returns merged object of first and second object */ -const _cleverMerge = (first, second, internalCaching = false) => { +const _cleverMerge = ( + first: First, + second: Second, + internalCaching = false +): First & Second => { const firstObject = internalCaching ? cachedParseObject(first) : parseObject(first); @@ -294,7 +313,6 @@ const _cleverMerge = (first, second, internalCaching = false) => { // If the first argument has a dynamic part we modify the dynamic part to merge the second argument if (firstDynamicInfo !== undefined) { let { byProperty, fn } = firstDynamicInfo; - // @ts-expect-error const fnInfo = fn[DYNAMIC_INFO]; if (fnInfo) { second = internalCaching @@ -302,14 +320,14 @@ const _cleverMerge = (first, second, internalCaching = false) => { : cleverMerge(fnInfo[1], second); fn = fnInfo[0]; } - // @ts-expect-error - const newFn = (...args) => { + + const newFn: FunctionWithDynamicInfo = (...args: any[]) => { const fnResult = fn(...args); return internalCaching ? cachedCleverMerge(fnResult, second) : cleverMerge(fnResult, second); }; - // @ts-expect-error + newFn[DYNAMIC_INFO] = [fn, second]; return serializeObject(firstObject.static, { byProperty, fn: newFn }); } @@ -319,8 +337,7 @@ const _cleverMerge = (first, second, internalCaching = false) => { ? cachedParseObject(second) : parseObject(second); const { static: secondInfo, dynamic: secondDynamicInfo } = secondObject; - /** @type {Map} */ - const resultInfo = new Map(); + const resultInfo = new Map(); for (const [key, firstEntry] of firstInfo) { const secondEntry = secondInfo.get(key); const entry = @@ -338,12 +355,16 @@ const _cleverMerge = (first, second, internalCaching = false) => { }; /** - * @param {ObjectParsedPropertyEntry} firstEntry a - * @param {ObjectParsedPropertyEntry} secondEntry b - * @param {boolean} internalCaching should parsing of objects and nested merges be cached - * @returns {ObjectParsedPropertyEntry} new entry + * @param firstEntry a + * @param secondEntry b + * @param internalCaching should parsing of objects and nested merges be cached + * @returns new entry */ -const mergeEntries = (firstEntry, secondEntry, internalCaching) => { +const mergeEntries = ( + firstEntry: ObjectParsedPropertyEntry, + secondEntry: ObjectParsedPropertyEntry, + internalCaching: boolean +): ObjectParsedPropertyEntry => { switch (getValueType(secondEntry.base)) { case VALUE_TYPE_ATOM: case VALUE_TYPE_DELETE: @@ -450,11 +471,11 @@ const mergeEntries = (firstEntry, secondEntry, internalCaching) => { }; /** - * @param {Map} byValues all values - * @param {string} key value of the selector - * @returns {any | undefined} value + * @param byValues all values + * @param key value of the selector + * @returns value */ -const getFromByValues = (byValues, key) => { +const getFromByValues = (byValues: Obj, key: string) => { if (key !== "default" && byValues.has(key)) { return byValues.get(key); } @@ -462,12 +483,12 @@ const getFromByValues = (byValues, key) => { }; /** - * @param {any} a value - * @param {any} b value - * @param {boolean} internalCaching should parsing of objects and nested merges be cached - * @returns {any} value + * @param a value + * @param b value + * @param internalCaching should parsing of objects and nested merges be cached + * @returns value */ -const mergeSingleValue = (a, b, internalCaching) => { +const mergeSingleValue = (a: any, b: any, internalCaching: boolean) => { const bType = getValueType(b); const aType = getValueType(a); switch (bType) { @@ -494,8 +515,7 @@ const mergeSingleValue = (a, b, internalCaching) => { case VALUE_TYPE_UNDEFINED: return b; case VALUE_TYPE_DELETE: - // @ts-expect-error - return b.filter(item => item !== "..."); + return b.filter((item: string) => item !== "..."); case VALUE_TYPE_ARRAY_EXTEND: { const newArray = []; for (const item of b) { @@ -510,8 +530,7 @@ const mergeSingleValue = (a, b, internalCaching) => { return newArray; } case VALUE_TYPE_OBJECT: - // @ts-expect-error - return b.map(item => (item === "..." ? a : item)); + return b.map((item: string) => (item === "..." ? a : item)); default: throw new Error("Not implemented"); } @@ -521,15 +540,12 @@ const mergeSingleValue = (a, b, internalCaching) => { }; /** - * @template T - * @param {T} obj the object - * @returns {T} the object without operations like "..." or DELETE + * @param obj the object + * @returns the object without operations like "..." or DELETE */ -const removeOperations = obj => { - const newObj = /** @type {T} */ ({}); - // @ts-expect-error +export const removeOperations = (obj: O): O => { + const newObj: Obj = {}; for (const key of Object.keys(obj)) { - // @ts-expect-error const value = obj[key]; const type = getValueType(value); switch (type) { @@ -537,15 +553,12 @@ const removeOperations = obj => { case VALUE_TYPE_DELETE: break; case VALUE_TYPE_OBJECT: - // @ts-expect-error newObj[key] = removeOperations(value); break; case VALUE_TYPE_ARRAY_EXTEND: - // @ts-expect-error - newObj[key] = value.filter(i => i !== "..."); + newObj[key] = (value as string[]).filter(i => i !== "..."); break; default: - // @ts-expect-error newObj[key] = value; break; } @@ -554,30 +567,30 @@ const removeOperations = obj => { }; /** - * @template T - * @template {string} P - * @param {T} obj the object - * @param {P} byProperty the by description - * @param {...any} values values - * @returns {Omit|undefined} object with merged byProperty + * @param obj the object + * @param byProperty the by description + * @param values values + * @returns object with merged byProperty */ -const resolveByProperty = (obj, byProperty, ...values) => { - if (typeof obj !== "object" || obj === null || !(byProperty in obj)) { +export const resolveByProperty = ( + obj: O, + byProperty: P, + ...values: any[] +): Omit | undefined => { + if (!isPropertyInObject(obj, byProperty)) { return obj; } - const { [byProperty]: _byValue, ..._remaining } = /** @type {object} */ (obj); - const remaining = /** @type {T} */ (_remaining); - const byValue = /** @type {Record | function(...any[]): T} */ ( - _byValue - ); + const { [byProperty]: _byValue, ..._remaining } = obj; + const remaining = _remaining; + const byValue = _byValue; if (typeof byValue === "object") { - const key = values[0]; + const key = values[0] as PropertyKey; if (key in byValue) { - return cachedCleverMerge(remaining, byValue[key]); + return cachedCleverMerge(remaining, byValue[key as keyof typeof byValue]); } else if ("default" in byValue) { return cachedCleverMerge(remaining, byValue.default); } else { - return /** @type {T} */ (remaining); + return remaining; } } else if (typeof byValue === "function") { const result = byValue.apply(null, values); @@ -588,9 +601,9 @@ const resolveByProperty = (obj, byProperty, ...values) => { } }; -exports.cachedSetProperty = cachedSetProperty; -exports.cachedCleverMerge = cachedCleverMerge; -exports.cleverMerge = cleverMerge; -exports.resolveByProperty = resolveByProperty; -exports.removeOperations = removeOperations; -exports.DELETE = DELETE; +function isPropertyInObject< + O extends Obj | undefined | null, + P extends PropertyKey +>(obj: O, property: P): obj is NonNullable & Record { + return typeof obj === "object" && obj !== null && property in obj; +} diff --git a/packages/rspack/src/util/createHash.ts b/packages/rspack/src/util/createHash.ts index 42b218434b6..0559b360112 100644 --- a/packages/rspack/src/util/createHash.ts +++ b/packages/rspack/src/util/createHash.ts @@ -7,22 +7,30 @@ * Copyright (c) JS Foundation and other contributors * https://github.com/webpack/webpack/blob/main/LICENSE */ -//@ts-nocheck -const Hash = require("./hash"); +import crypto from "node:crypto"; +import Hash from "./hash"; +import BatchedHash from "./hash/BatchedHash"; +import createMd4 from "./hash/md4"; +import createXXHash64 from "./hash/xxhash64"; const BULK_SIZE = 2000; // We are using an object instead of a Map as this will stay static during the runtime // so access to it can be optimized by v8 -const digestCaches = {}; +const digestCaches: Record> = {}; class BulkUpdateDecorator extends Hash { + hash: Hash | undefined; + hashFactory: (() => Hash) | undefined; + hashKey: string | undefined; + buffer: string; + /** - * @param {Hash | function(): Hash} hashOrFactory function to create a hash - * @param {string=} hashKey key for caching + * @param hashOrFactory function to create a hash + * @param hashKey key for caching */ - constructor(hashOrFactory, hashKey) { + constructor(hashOrFactory: Hash | (() => Hash), hashKey?: string) { super(); this.hashKey = hashKey; if (typeof hashOrFactory === "function") { @@ -37,17 +45,17 @@ class BulkUpdateDecorator extends Hash { /** * Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding} - * @param {string|Buffer} data data - * @param {string=} inputEncoding data encoding - * @returns {this} updated hash + * @param data data + * @param inputEncoding data encoding + * @returns updated hash */ - update(data, inputEncoding) { + update(data: string | Buffer, inputEncoding?: string): this { if ( inputEncoding !== undefined || typeof data !== "string" || data.length > BULK_SIZE ) { - if (this.hash === undefined) this.hash = this.hashFactory(); + if (this.hash === undefined) this.hash = this.hashFactory!(); if (this.buffer.length > 0) { this.hash.update(this.buffer); this.buffer = ""; @@ -56,7 +64,7 @@ class BulkUpdateDecorator extends Hash { } else { this.buffer += data; if (this.buffer.length > BULK_SIZE) { - if (this.hash === undefined) this.hash = this.hashFactory(); + if (this.hash === undefined) this.hash = this.hashFactory!(); this.hash.update(this.buffer); this.buffer = ""; } @@ -66,11 +74,11 @@ class BulkUpdateDecorator extends Hash { /** * Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding} - * @param {string=} encoding encoding of the return value - * @returns {string|Buffer} digest + * @param encoding encoding of the return value + * @returns digest */ - digest(encoding) { - let digestCache; + digest(encoding?: string): string | Buffer { + let digestCache: Map | undefined; const buffer = this.buffer; if (this.hash === undefined) { // short data for hash, we can use caching @@ -81,7 +89,7 @@ class BulkUpdateDecorator extends Hash { } const cacheEntry = digestCache.get(buffer); if (cacheEntry !== undefined) return cacheEntry; - this.hash = this.hashFactory(); + this.hash = this.hashFactory!(); } if (buffer.length > 0) { this.hash.update(buffer); @@ -98,6 +106,8 @@ class BulkUpdateDecorator extends Hash { /* istanbul ignore next */ class DebugHash extends Hash { + string: string; + constructor() { super(); this.string = ""; @@ -105,42 +115,45 @@ class DebugHash extends Hash { /** * Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding} - * @param {string|Buffer} data data - * @param {string=} inputEncoding data encoding - * @returns {this} updated hash + * @param data data + * @param _inputEncoding data encoding + * @returns updated hash */ - update(data, inputEncoding) { + update(data: string | Buffer, _inputEncoding?: string): this { if (typeof data !== "string") data = data.toString("utf-8"); if (data.startsWith("debug-digest-")) { data = Buffer.from(data.slice("debug-digest-".length), "hex").toString(); } - this.string += `[${data}](${new Error().stack.split("\n", 3)[2]})\n`; + this.string += `[${data}](${new Error().stack?.split("\n", 3)[2]})\n`; return this; } /** * Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding} - * @param {string=} encoding encoding of the return value - * @returns {string|Buffer} digest + * @param encoding encoding of the return value + * @returns digest */ - digest(encoding) { + digest(encoding?: BufferEncoding) { return ( "debug-digest-" + Buffer.from(this.string).toString(encoding || "hex") ); } } -let crypto = undefined; -let createXXHash64 = undefined; -let createMd4 = undefined; -let BatchedHash = undefined; - /** * Creates a hash by name or function - * @param {string | typeof Hash} algorithm the algorithm name or a constructor creating a hash - * @returns {Hash} the hash + * @param algorithm the algorithm name or a constructor creating a hash + * @returns the hash */ -export const createHash = algorithm => { +export const createHash = ( + algorithm: + | "debug" + | "xxhash64" + | "md4" + | "native-md4" + | (string & {}) + | (new () => Hash) +): Hash => { if (typeof algorithm === "function") { return new BulkUpdateDecorator(() => new algorithm()); } @@ -149,26 +162,12 @@ export const createHash = algorithm => { case "debug": return new DebugHash(); case "xxhash64": - if (createXXHash64 === undefined) { - createXXHash64 = require("./hash/xxhash64"); - if (BatchedHash === undefined) { - BatchedHash = require("./hash/BatchedHash"); - } - } return new BatchedHash(createXXHash64()); case "md4": - if (createMd4 === undefined) { - createMd4 = require("./hash/md4"); - if (BatchedHash === undefined) { - BatchedHash = require("./hash/BatchedHash"); - } - } return new BatchedHash(createMd4()); case "native-md4": - if (crypto === undefined) crypto = require("node:crypto"); return new BulkUpdateDecorator(() => crypto.createHash("md4"), "md4"); default: - if (crypto === undefined) crypto = require("node:crypto"); return new BulkUpdateDecorator( () => crypto.createHash(algorithm), algorithm diff --git a/packages/rspack/src/util/hash/BatchedHash.js b/packages/rspack/src/util/hash/BatchedHash.ts similarity index 74% rename from packages/rspack/src/util/hash/BatchedHash.js rename to packages/rspack/src/util/hash/BatchedHash.ts index 7ac14b726ad..92d00ebe4ff 100644 --- a/packages/rspack/src/util/hash/BatchedHash.js +++ b/packages/rspack/src/util/hash/BatchedHash.ts @@ -7,15 +7,15 @@ * Copyright (c) JS Foundation and other contributors * https://github.com/webpack/webpack/blob/main/LICENSE */ +import Hash from "."; +import { MAX_SHORT_STRING } from "./wasm-hash"; -"use strict"; +export default class BatchedHash extends Hash { + string: string | undefined; + encoding: string | undefined; + hash: Hash; -const Hash = require("."); -const MAX_SHORT_STRING = require("./wasm-hash").MAX_SHORT_STRING; - -class BatchedHash extends Hash { - // @ts-expect-error - constructor(hash) { + constructor(hash: Hash) { super(); this.string = undefined; this.encoding = undefined; @@ -24,11 +24,11 @@ class BatchedHash extends Hash { /** * Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding} - * @param {string|Buffer} data data - * @param {string=} inputEncoding data encoding - * @returns {this} updated hash + * @param data data + * @param inputEncoding data encoding + * @returns updated hash */ - update(data, inputEncoding) { + update(data: string | Buffer, inputEncoding?: string) { if (this.string !== undefined) { if ( typeof data === "string" && @@ -60,15 +60,13 @@ class BatchedHash extends Hash { /** * Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding} - * @param {string=} encoding encoding of the return value - * @returns {string|Buffer} digest + * @param encoding encoding of the return value + * @returns digest */ - digest(encoding) { + digest(encoding?: string): string | Buffer { if (this.string !== undefined) { this.hash.update(this.string, this.encoding); } return this.hash.digest(encoding); } } - -module.exports = BatchedHash; diff --git a/packages/rspack/src/util/hash/index.js b/packages/rspack/src/util/hash/index.ts similarity index 60% rename from packages/rspack/src/util/hash/index.js rename to packages/rspack/src/util/hash/index.ts index 08c103aa184..aa25875c129 100644 --- a/packages/rspack/src/util/hash/index.js +++ b/packages/rspack/src/util/hash/index.ts @@ -7,19 +7,18 @@ * Copyright (c) JS Foundation and other contributors * https://github.com/webpack/webpack/blob/main/LICENSE */ -"use strict"; +import AbstractMethodError from "../../lib/AbstractMethodError"; -class Hash { +export default class Hash { /* istanbul ignore next */ /** * Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding} * @abstract - * @param {string|Buffer} data data - * @param {string=} inputEncoding data encoding - * @returns {this} updated hash + * @param data data + * @param inputEncoding data encoding + * @returns updated hash */ - update(data, inputEncoding) { - const AbstractMethodError = require("../../lib/AbstractMethodError"); + update(data: string | Buffer, inputEncoding?: string): this { throw new AbstractMethodError(); } @@ -27,13 +26,10 @@ class Hash { /** * Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding} * @abstract - * @param {string=} encoding encoding of the return value - * @returns {string|Buffer} digest + * @param encoding encoding of the return value + * @returns digest */ - digest(encoding) { - const AbstractMethodError = require("../../lib/AbstractMethodError"); + digest(encoding?: string): string | Buffer { throw new AbstractMethodError(); } } - -module.exports = Hash; diff --git a/packages/rspack/src/util/hash/md4.js b/packages/rspack/src/util/hash/md4.ts similarity index 96% rename from packages/rspack/src/util/hash/md4.js rename to packages/rspack/src/util/hash/md4.ts index f0a265acd5e..9ec854f46e5 100644 --- a/packages/rspack/src/util/hash/md4.js +++ b/packages/rspack/src/util/hash/md4.ts @@ -8,9 +8,7 @@ * https://github.com/webpack/webpack/blob/main/LICENSE */ -"use strict"; - -const create = require("./wasm-hash"); +import create from "./wasm-hash"; //#region wasm code: md4 (../../../assembly/hash/md4.asm.ts) --initialMemory 1 const md4 = new WebAssembly.Module( @@ -22,4 +20,4 @@ const md4 = new WebAssembly.Module( ); //#endregion -module.exports = create.bind(null, md4, [], 64, 32); +export default create.bind(null, md4, [], 64, 32); diff --git a/packages/rspack/src/util/hash/wasm-hash.js b/packages/rspack/src/util/hash/wasm-hash.ts similarity index 75% rename from packages/rspack/src/util/hash/wasm-hash.js rename to packages/rspack/src/util/hash/wasm-hash.ts index 7afc966db3c..a62f454fb29 100644 --- a/packages/rspack/src/util/hash/wasm-hash.js +++ b/packages/rspack/src/util/hash/wasm-hash.ts @@ -8,24 +8,42 @@ * https://github.com/webpack/webpack/blob/main/LICENSE */ -"use strict"; - // 65536 is the size of a wasm memory page // 64 is the maximum chunk size for every possible wasm hash implementation // 4 is the maximum number of bytes per char for string encoding (max is utf-8) // ~3 makes sure that it's always a block of 4 chars, so avoid partially encoded bytes for base64 -const MAX_SHORT_STRING = Math.floor((65536 - 64) / 4) & ~3; +export const MAX_SHORT_STRING = Math.floor((65536 - 64) / 4) & ~3; + +type Exports = WebAssembly.Instance["exports"] & { + init: () => void; + update: (b: number) => void; + memory: WebAssembly.Memory; + final: (b: number) => void; +}; class WasmHash { + exports: Exports; + instancesPool: WebAssembly.Instance[]; + buffered: number; + mem: Buffer; + chunkSize: number; + digestSize: number; + /** - * @param {WebAssembly.Instance} instance wasm instance - * @param {WebAssembly.Instance[]} instancesPool pool of instances - * @param {number} chunkSize size of data chunks passed to wasm - * @param {number} digestSize size of digest returned by wasm + * @param instance wasm instance + * @param instancesPool pool of instances + * @param chunkSize size of data chunks passed to wasm + * @param digestSize size of digest returned by wasm */ - constructor(instance, instancesPool, chunkSize, digestSize) { - const exports = /** @type {any} */ (instance.exports); + constructor( + instance: WebAssembly.Instance, + instancesPool: WebAssembly.Instance[], + chunkSize: number, + digestSize: number + ) { + const exports = instance.exports as Exports; exports.init(); + this.exports = exports; this.mem = Buffer.from(exports.memory.buffer, 0, 65536); this.buffered = 0; @@ -40,11 +58,11 @@ class WasmHash { } /** - * @param {Buffer | string} data data - * @param {BufferEncoding=} encoding encoding - * @returns {this} itself + * @param data data + * @param encoding encoding + * @returns itself */ - update(data, encoding) { + update(data: Buffer | string, encoding?: BufferEncoding): this { if (typeof data === "string") { while (data.length > MAX_SHORT_STRING) { this._updateWithShortString(data.slice(0, MAX_SHORT_STRING), encoding); @@ -62,7 +80,7 @@ class WasmHash { * @param {BufferEncoding=} encoding encoding * @returns {void} */ - _updateWithShortString(data, encoding) { + _updateWithShortString(data: string, encoding?: BufferEncoding): void { const { exports, buffered, mem, chunkSize } = this; let endPos; if (data.length < 70) { @@ -105,10 +123,10 @@ class WasmHash { } /** - * @param {Buffer} data data - * @returns {void} + * @param data data + * @returns */ - _updateWithBuffer(data) { + _updateWithBuffer(data: Buffer): void { const { exports, buffered, mem } = this; const length = data.length; if (buffered + length < this.chunkSize) { @@ -138,8 +156,7 @@ class WasmHash { } } - // @ts-expect-error - digest(type) { + digest(type: BufferEncoding) { const { exports, buffered, mem, digestSize } = this; exports.final(buffered); this.instancesPool.push(this); @@ -150,10 +167,14 @@ class WasmHash { } } -// @ts-expect-error -const create = (wasmModule, instancesPool, chunkSize, digestSize) => { +const create = ( + wasmModule: WebAssembly.Module, + instancesPool: WasmHash[], + chunkSize: number, + digestSize: number +): WasmHash => { if (instancesPool.length > 0) { - const old = instancesPool.pop(); + const old = instancesPool.pop() as WasmHash; old.reset(); return old; } else { @@ -166,5 +187,4 @@ const create = (wasmModule, instancesPool, chunkSize, digestSize) => { } }; -module.exports = create; -module.exports.MAX_SHORT_STRING = MAX_SHORT_STRING; +export default create; diff --git a/packages/rspack/src/util/hash/xxhash64.js b/packages/rspack/src/util/hash/xxhash64.ts similarity index 94% rename from packages/rspack/src/util/hash/xxhash64.js rename to packages/rspack/src/util/hash/xxhash64.ts index 2ad7913b361..eaf5a548530 100644 --- a/packages/rspack/src/util/hash/xxhash64.js +++ b/packages/rspack/src/util/hash/xxhash64.ts @@ -8,9 +8,7 @@ * https://github.com/webpack/webpack/blob/main/LICENSE */ -"use strict"; - -const create = require("./wasm-hash"); +import create from "./wasm-hash"; //#region wasm code: xxhash64 (../../../assembly/hash/xxhash64.asm.ts) --initialMemory 1 const xxhash64 = new WebAssembly.Module( @@ -22,4 +20,4 @@ const xxhash64 = new WebAssembly.Module( ); //#endregion -module.exports = create.bind(null, xxhash64, [], 32, 16); +export default create.bind(null, xxhash64, [], 32, 16);