Skip to content

Commit

Permalink
perf(core): replace neo-async with a minimal helper
Browse files Browse the repository at this point in the history
  • Loading branch information
chenjiahan committed Oct 31, 2024
1 parent affb4d3 commit 023e130
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 6 deletions.
2 changes: 0 additions & 2 deletions packages/rspack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,13 @@
"@swc/core": "1.4.0",
"@swc/types": "0.1.12",
"@types/graceful-fs": "4.1.9",
"@types/neo-async": "^2.6.6",
"@types/watchpack": "^2.4.0",
"@types/webpack-sources": "3.2.3",
"browserslist": "^4.21.3",
"cross-env": "^7.0.3",
"enhanced-resolve": "5.12.0",
"graceful-fs": "4.2.10",
"json-parse-even-better-errors": "^3.0.0",
"neo-async": "2.6.2",
"prebundle": "^1.1.0",
"tsc-alias": "^1.8.8",
"tsup": "^8.3.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/rspack/src/MultiCompiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
*/

import * as liteTapable from "@rspack/lite-tapable";
import asyncLib from "neo-async";
import type { Compiler, RspackOptions, Stats } from ".";
import MultiStats from "./MultiStats";
import MultiWatching from "./MultiWatching";
import type { WatchOptions } from "./config";
import ConcurrentCompilationError from "./error/ConcurrentCompilationError";
import ArrayQueue from "./util/ArrayQueue";
import asyncLib from "./util/asyncLib";
import type { InputFileSystem, WatchFileSystem } from "./util/fs";

interface Node<T> {
Expand Down
4 changes: 2 additions & 2 deletions packages/rspack/src/MultiWatching.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* https://github.com/webpack/webpack/blob/main/LICENSE
*/

import asyncLib from "neo-async";
import asyncLib from "./util/asyncLib";

import type { Callback } from "@rspack/lite-tapable";
import type { MultiCompiler } from "./MultiCompiler";
Expand Down Expand Up @@ -43,7 +43,7 @@ class MultiWatching {
}

close(callback: Callback<Error, void>) {
asyncLib.forEach(
asyncLib.each(
this.watchings,
(watching, finishedCallback) => {
watching.close(finishedCallback);
Expand Down
2 changes: 1 addition & 1 deletion packages/rspack/src/lib/CacheFacade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* https://github.com/webpack/webpack/blob/main/LICENSE
*/

import asyncLib from "neo-async";
import asyncLib from "../util/asyncLib";
import { getter as getLazyHashedEtag } from "./cache/getLazyHashedEtag.js";
import { mergeEtags } from "./cache/mergeEtags.js";

Expand Down
116 changes: 116 additions & 0 deletions packages/rspack/src/util/asyncLib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/**
* The following code is modified based on
* https://github.com/suguru03/neo-async/blob/master/lib/async.js
*
* MIT Licensed
* Author Suguru Motegi
* Copyright (c) 2014-2018 Suguru Motegi
* https://github.com/suguru03/neo-async/blob/master/LICENSE
*/
export interface Dictionary<T> {
[key: string]: T;
}
export type IterableCollection<T> = T[] | IterableIterator<T> | Dictionary<T>;
export type ErrorCallback<E = Error> = (err?: E | null) => void;
export type AsyncIterator<T, E = Error> = (
item: T,
callback: ErrorCallback<E>
) => void;

function throwError() {
throw new Error("Callback was already called.");
}

function noop() {}

function onlyOnce<E = Error>(func: ErrorCallback<E>): ErrorCallback<E> {
return (err?: E | null) => {
const fn = func;
// biome-ignore lint/style/noParameterAssign:
func = throwError;
fn(err);
};
}

function once<E = Error>(func: ErrorCallback<E>): ErrorCallback<E> {
return (err?: E | null) => {
const fn = func;
// biome-ignore lint/style/noParameterAssign:
func = noop;
fn(err);
};
}

function arrayEach<T, E = Error>(
array: T[],
iterator: (item: T, callback: ErrorCallback<E>) => void,
callback: ErrorCallback<E>
): void {
let index = -1;
while (++index < array.length) {
iterator(array[index], onlyOnce(callback));
}
}

/**
* @example
*
* // array
* var order = [];
* var array = [1, 3, 2];
* var iterator = function(num, done) {
* setTimeout(function() {
* order.push(num);
* done();
* }, num * 10);
* };
* asyncLib.each(array, iterator, function(err, res) {
* console.log(res); // undefined
* console.log(order); // [1, 2, 3]
* });
*
* @example
*
* // break
* var order = [];
* var array = [1, 3, 2];
* var iterator = function(num, done) {
* setTimeout(function() {
* order.push(num);
* done(null, num !== 2);
* }, num * 10);
* };
* asyncLib.each(array, iterator, function(err, res) {
* console.log(res); // undefined
* console.log(order); // [1, 2]
* });
*
*/
function each<T, E = Error>(
collection: IterableCollection<T>,
iterator: AsyncIterator<T, E>,
originalCallback: ErrorCallback<E>
) {
let callback = once(originalCallback);
let size = 0;
let completed = 0;

const done: ErrorCallback<E> = err => {
if (err) {
callback = once(callback);
callback(err);
} else if (++completed === size) {
callback(null);
}
};

if (Array.isArray(collection)) {
size = collection.length;
arrayEach(collection, iterator, done);
}
if (!size) {
callback(null);
}
}

export default { each };

0 comments on commit 023e130

Please sign in to comment.