Compare commits

...

3 Commits

Author SHA1 Message Date
Don Isaac
c8fa6bcc57 Update src/js/internal/util/inspect.js
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2024-12-20 21:03:41 -08:00
Don Isaac
c2a5dd56c5 perf 2024-12-19 20:11:06 -08:00
Don Isaac
7738d66420 perf(node/util): use string.split 2024-12-19 17:56:50 -08:00
2 changed files with 17 additions and 109 deletions

View File

@@ -106,91 +106,3 @@ pub fn internalErrorName(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFr
var fmtstring = bun.String.createFormat("Unknown system error {d}", .{err_int}) catch bun.outOfMemory();
return fmtstring.transferToJS(globalThis);
}
/// `extractedSplitNewLines` for ASCII/Latin1 strings. Panics if passed a non-string.
/// Returns `undefined` if param is utf8 or utf16 and not fully ascii.
///
/// ```js
/// // util.js
/// const extractedNewLineRe = new RegExp("(?<=\\n)");
/// extractedSplitNewLines = value => RegExpPrototypeSymbolSplit(extractedNewLineRe, value);
/// ```
pub fn extractedSplitNewLinesFastPathStringsOnly(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue {
bun.assert(callframe.argumentsCount() == 1);
const value = callframe.argument(0);
bun.assert(value.isString());
const str = try value.toBunString2(globalThis);
defer str.deref();
return switch (str.encoding()) {
inline .utf16, .latin1 => |encoding| split(encoding, globalThis, bun.default_allocator, &str),
.utf8 => if (bun.strings.isAllASCII(str.byteSlice()))
return split(.utf8, globalThis, bun.default_allocator, &str)
else
return JSC.JSValue.jsUndefined(),
};
}
fn split(
comptime encoding: bun.strings.EncodingNonAscii,
globalThis: *JSC.JSGlobalObject,
allocator: Allocator,
str: *const bun.String,
) bun.JSError!JSC.JSValue {
var fallback = std.heap.stackFallback(1024, allocator);
const alloc = fallback.get();
const Char = switch (encoding) {
.utf8, .latin1 => u8,
.utf16 => u16,
};
var lines: std.ArrayListUnmanaged(bun.String) = .{};
defer {
for (lines.items) |out| {
out.deref();
}
lines.deinit(alloc);
}
const buffer: []const Char = if (encoding == .utf16)
str.utf16()
else
str.byteSlice();
var it: SplitNewlineIterator(Char) = .{ .buffer = buffer, .index = 0 };
while (it.next()) |line| {
const encoded_line = switch (encoding) {
inline .utf8 => bun.String.fromUTF8(line),
inline .latin1 => bun.String.createLatin1(line),
inline .utf16 => bun.String.fromUTF16(line),
};
errdefer encoded_line.deref();
try lines.append(alloc, encoded_line);
}
return bun.String.toJSArray(globalThis, lines.items);
}
pub fn SplitNewlineIterator(comptime T: type) type {
return struct {
buffer: []const T,
index: ?usize,
const Self = @This();
/// Returns a slice of the next field, or null if splitting is complete.
pub fn next(self: *Self) ?[]const T {
const start = self.index orelse return null;
if (std.mem.indexOfScalarPos(T, self.buffer, start, '\n')) |delim_start| {
const end = delim_start + 1;
const slice = self.buffer[start..end];
self.index = end;
return slice;
} else {
self.index = null;
return self.buffer[start..];
}
}
};
}

View File

@@ -141,21 +141,6 @@ const kRejected = Symbol("kRejected"); // state ID 2
const ALL_PROPERTIES = 0;
const ONLY_ENUMERABLE = 2;
/**
* Fast path for {@link extractedSplitNewLines} for ASCII/Latin1 strings.
* @returns `value` split on newlines (newline included at end), or `undefined`
* if non-ascii UTF8/UTF16.
*
* Passing this a non-string will cause a panic.
*
* @type {(value: string) => string[] | undefined}
*/
const extractedSplitNewLinesFastPathStringsOnly = $newZigFunction(
"node_util_binding.zig",
"extractedSplitNewLinesFastPathStringsOnly",
1,
);
const isAsyncFunction = v =>
typeof v === "function" && StringPrototypeStartsWith(FunctionPrototypeToString(v), "async");
const isGeneratorFunction = v =>
@@ -430,8 +415,6 @@ try {
"[\\x00-\\x1f\\x5c\\x7f-\\x9f]|[\\ud800-\\udbff](?![\\udc00-\\udfff])|(?<![\\ud800-\\udbff])[\\udc00-\\udfff]",
"g",
);
const extractedNewLineRe = new RegExp("(?<=\\n)");
extractedSplitNewLinesSlow = value => RegExpPrototypeSymbolSplit(extractedNewLineRe, value);
// CI doesn't run in an elderly runtime
} catch {
// These are from a previous version of node,
@@ -453,11 +436,24 @@ try {
}
const extractedSplitNewLines = value => {
if (typeof value === "string") {
return extractedSplitNewLinesFastPathStringsOnly(value) || extractedSplitNewLinesSlow(value);
const lines = StringPrototypeSplit(value, "\n");
let i = 0;
for (let j = 0, length = lines.length; j < length; j++) {
const line = lines[j];
if (line !== "")
lines[i++] = line + "\n";
}
return extractedSplitNewLinesSlow(value);
}
lines.length = i;
return lines;
for (let i = 0; i < lines.length; i++) {
if (i !== lines.length - 1) {
lines[i] += "\n";
continue;
}
if (lines[i] === "") lines.pop();
}
return lines;
};
const keyStrRegExp = /^[a-zA-Z_][a-zA-Z_0-9]*$/;
const numberRegExp = /^(0|[1-9][0-9]*)$/;