aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-07-04 08:41:03 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-07-04 08:41:03 -0700
commitbbcc08dbb44dd28f7141e6f50a7cb5edfb8b4987 (patch)
tree7cd40a5fd5a0cb23cba1c171ba83398223cfdc55 /src
parent77b5999b73021d1b12fd9bcf2a8e8a261722ec2c (diff)
parent0f987a5601e3ec2f154607802b1e7da2ef03b770 (diff)
downloadbun-bbcc08dbb44dd28f7141e6f50a7cb5edfb8b4987.tar.gz
bun-bbcc08dbb44dd28f7141e6f50a7cb5edfb8b4987.tar.zst
bun-bbcc08dbb44dd28f7141e6f50a7cb5edfb8b4987.zip
Merge branch 'jarred/landing'
Diffstat (limited to 'src')
m---------src/bun.js/WebKit0
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.cpp48
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.h7
-rw-r--r--src/bun.js/event_loop.zig8
-rw-r--r--src/bun.js/fs.exports.js72
-rw-r--r--src/bun.js/javascript.zig5
-rw-r--r--src/bun.js/javascript_core_c_api.zig18
-rw-r--r--src/bun.js/webcore.zig36
m---------src/deps/uws0
-rw-r--r--src/feature_flags.zig2
-rw-r--r--src/js_printer.zig10
-rw-r--r--src/sourcemap/sourcemap.zig6
-rw-r--r--src/string_immutable.zig45
13 files changed, 190 insertions, 67 deletions
diff --git a/src/bun.js/WebKit b/src/bun.js/WebKit
-Subproject a06260772abc4a9e9a984cc3654f44e0b9872b1
+Subproject 7e7774dabf1c2d94fe3604defb3c54a4c989c3b
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp
index 1e73da3ed..138267cd6 100644
--- a/src/bun.js/bindings/ZigGlobalObject.cpp
+++ b/src/bun.js/bindings/ZigGlobalObject.cpp
@@ -1487,6 +1487,29 @@ JSC_DEFINE_HOST_FUNCTION(functionConcatTypedArrays, (JSGlobalObject * globalObje
return flattenArrayOfBuffersIntoArrayBuffer(globalObject, arrayValue);
}
+extern "C" uint64_t Bun__readOriginTimer(void*);
+
+JSC_DECLARE_HOST_FUNCTION(functionPerformanceNow);
+
+JSC_DEFINE_HOST_FUNCTION(functionPerformanceNow, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
+{
+ auto* global = reinterpret_cast<GlobalObject*>(globalObject);
+ // nanoseconds to seconds
+ uint64_t time = Bun__readOriginTimer(global->bunVM());
+ double result = time / 1000000000.0;
+ return JSValue::encode(jsNumber(time));
+}
+
+JSC_DECLARE_HOST_FUNCTION(functionBunNanoseconds);
+
+JSC_DEFINE_HOST_FUNCTION(functionBunNanoseconds, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
+{
+ auto* global = reinterpret_cast<GlobalObject*>(globalObject);
+ // nanoseconds to seconds
+ uint64_t time = Bun__readOriginTimer(global->bunVM());
+ return JSValue::encode(jsNumber(time));
+}
+
JSC_DECLARE_HOST_FUNCTION(functionConcatTypedArraysFromIterator);
JSC_DEFINE_HOST_FUNCTION(functionConcatTypedArraysFromIterator, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
@@ -1663,10 +1686,10 @@ void GlobalObject::finishCreation(VM& vm)
init.set(prototype);
});
- m_JSHTTPResponseControllerPrototype.initLater(
- [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::JSObject>::Initializer& init) {
- auto* prototype = createJSSinkControllerPrototype(init.vm, init.owner, WebCore::SinkID::HTTPResponseSink);
- init.set(prototype);
+ m_JSHTTPResponseController.initLater(
+ [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::Structure>::Initializer& init) {
+ auto* structure = createJSSinkControllerStructure(init.vm, init.owner, WebCore::SinkID::HTTPResponseSink);
+ init.set(structure);
});
m_JSHTTPSResponseControllerPrototype.initLater(
@@ -1675,6 +1698,13 @@ void GlobalObject::finishCreation(VM& vm)
init.set(prototype);
});
+ m_performanceObject.initLater(
+ [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::JSObject>::Initializer& init) {
+ JSC::JSObject* object = JSC::constructEmptyObject(init.owner, init.owner->objectPrototype(), 1);
+ object->putDirectNativeFunction(init.vm, init.owner, JSC::Identifier::fromString(init.vm, "now"_s), 1, functionPerformanceNow, NoIntrinsic, 0);
+ init.set(object);
+ });
+
m_processEnvObject.initLater(
[](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::JSObject>::Initializer& init) {
auto jsClass = reinterpret_cast<Zig::GlobalObject*>(init.owner)->m_dotEnvClassRef;
@@ -1878,6 +1908,9 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm)
putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "process"_s), JSC::CustomGetterSetter::create(vm, property_lazyProcessGetter, property_lazyProcessSetter),
JSC::PropertyAttribute::CustomAccessor | 0);
+ putDirect(vm, JSC::Identifier::fromString(vm, "performance"_s), this->performanceObject(),
+ 0);
+
putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "URL"_s), JSC::CustomGetterSetter::create(vm, JSDOMURL_getter, nullptr),
JSC::PropertyAttribute::DontDelete | 0);
@@ -2036,6 +2069,12 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count, JSC::VM& vm
}
{
+ JSC::Identifier identifier = JSC::Identifier::fromString(vm, "nanoseconds"_s);
+ object->putDirectNativeFunction(vm, this, identifier, 1, functionBunNanoseconds, NoIntrinsic,
+ JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
+ }
+
+ {
JSC::Identifier identifier = JSC::Identifier::fromString(vm, pathToFileURLString);
object->putDirectNativeFunction(vm, this, identifier, 1, functionPathToFileURL, NoIntrinsic,
@@ -2135,6 +2174,7 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor)
thisObject->m_requireMap.visit(visitor);
thisObject->m_processEnvObject.visit(visitor);
thisObject->m_processObject.visit(visitor);
+ thisObject->m_performanceObject.visit(visitor);
visitor.append(thisObject->m_readableStreamToArrayBufferResolve);
visitor.append(thisObject->m_readableStreamToText);
diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h
index 47449321b..3832eb9c2 100644
--- a/src/bun.js/bindings/ZigGlobalObject.h
+++ b/src/bun.js/bindings/ZigGlobalObject.h
@@ -179,7 +179,7 @@ public:
JSC::Structure* HTTPResponseSinkStructure() { return m_JSHTTPResponseSinkClassStructure.getInitializedOnMainThread(this); }
JSC::JSObject* HTTPResponseSink() { return m_JSHTTPResponseSinkClassStructure.constructorInitializedOnMainThread(this); }
JSC::JSValue HTTPResponseSinkPrototype() { return m_JSHTTPResponseSinkClassStructure.prototypeInitializedOnMainThread(this); }
- JSC::JSValue JSReadableHTTPResponseSinkControllerPrototype() { return m_JSHTTPResponseControllerPrototype.getInitializedOnMainThread(this); }
+ JSC::Structure* JSReadableHTTPResponseSinkController() { return m_JSHTTPResponseController.getInitializedOnMainThread(this); }
JSC::Structure* HTTPSResponseSinkStructure() { return m_JSHTTPSResponseSinkClassStructure.getInitializedOnMainThread(this); }
JSC::JSObject* HTTPSResponseSink() { return m_JSHTTPSResponseSinkClassStructure.constructorInitializedOnMainThread(this); }
@@ -189,6 +189,8 @@ public:
JSC::JSMap* readableStreamNativeMap() { return m_lazyReadableStreamPrototypeMap.getInitializedOnMainThread(this); }
JSC::JSMap* requireMap() { return m_requireMap.getInitializedOnMainThread(this); }
+ JSC::JSObject* performanceObject() { return m_performanceObject.getInitializedOnMainThread(this); }
+
JSC::JSObject* processObject()
{
return m_processObject.getInitializedOnMainThread(this);
@@ -228,11 +230,12 @@ private:
LazyProperty<JSGlobalObject, JSObject> m_JSArrayBufferControllerPrototype;
LazyProperty<JSGlobalObject, JSObject> m_JSHTTPSResponseControllerPrototype;
- LazyProperty<JSGlobalObject, JSObject> m_JSHTTPResponseControllerPrototype;
+ LazyProperty<JSGlobalObject, Structure> m_JSHTTPResponseController;
LazyProperty<JSGlobalObject, JSObject> m_processObject;
LazyProperty<JSGlobalObject, JSObject> m_processEnvObject;
LazyProperty<JSGlobalObject, JSMap> m_lazyReadableStreamPrototypeMap;
LazyProperty<JSGlobalObject, JSMap> m_requireMap;
+ LazyProperty<JSGlobalObject, JSObject> m_performanceObject;
// LazyProperty<JSGlobalObject, WebCore::JSEventTarget> m_eventTarget;
JSClassRef m_dotEnvClassRef;
diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig
index 95bf5456c..df6af2748 100644
--- a/src/bun.js/event_loop.zig
+++ b/src/bun.js/event_loop.zig
@@ -422,7 +422,13 @@ pub const EventLoop = struct {
if (this.tickWithCount() == 0) break;
}
- this.global.vm().releaseWeakRefs();
+ // This is JSC's event loop
+ // We don't actually use this.
+ // However, there are three uses of it in JavaScriptCore outside our control:
+ // 1. FinalizationRegistry callbacks
+ // 2. WebAssembly.instantiate
+ // 3. WebAssembly.instantiateStreaming
+ this.global.vm().doWork();
if (!ctx.disable_run_us_loop and ctx.us_loop_reference_count > 0 and !ctx.is_us_loop_entered) {
ctx.is_us_loop_entered = true;
diff --git a/src/bun.js/fs.exports.js b/src/bun.js/fs.exports.js
index 0680b3568..8eb043f69 100644
--- a/src/bun.js/fs.exports.js
+++ b/src/bun.js/fs.exports.js
@@ -119,6 +119,39 @@ function callbackify(fsFunction, args) {
});
}
+// note: this is not quite the same as how node does it
+// in some cases, node swaps around arguments or makes small tweaks to the return type
+// this is just better than nothing.
+function promisify(fsFunction) {
+ // TODO: remove variadic arguments
+ // we can use new Function() here instead
+ // based on fsFucntion.length
+ var obj = {
+ [fsFunction.name]: function (resolve, reject, args) {
+ var result;
+ try {
+ result = fsFunction.apply(fs, args);
+ args = undefined;
+ } catch (err) {
+ args = undefined;
+ reject(err);
+ return;
+ }
+
+ resolve(result);
+ },
+ };
+
+ var func = obj[fsFunction.name];
+
+ // TODO: consider @createPromiseCapabiilty intrinsic
+ return (...args) => {
+ return new Promise((resolve, reject) => {
+ func(resolve, reject, args);
+ });
+ };
+}
+
export var accessSync = fs.accessSync.bind(fs);
export var appendFileSync = fs.appendFileSync.bind(fs);
export var closeSync = fs.closeSync.bind(fs);
@@ -157,6 +190,44 @@ export var lutimesSync = fs.lutimesSync.bind(fs);
export var createReadStream = fs.createReadStream.bind(fs);
export var createWriteStream = fs.createWriteStream.bind(fs);
+export var promises = {
+ access: promisify(fs.accessSync),
+ appendFile: promisify(fs.appendFileSync),
+ close: promisify(fs.closeSync),
+ copyFile: promisify(fs.copyFileSync),
+ exists: promisify(fs.existsSync),
+ chown: promisify(fs.chownSync),
+ chmod: promisify(fs.chmodSync),
+ fchmod: promisify(fs.fchmodSync),
+ fchown: promisify(fs.fchownSync),
+ fstat: promisify(fs.fstatSync),
+ fsync: promisify(fs.fsyncSync),
+ ftruncate: promisify(fs.ftruncateSync),
+ futimes: promisify(fs.futimesSync),
+ lchmod: promisify(fs.lchmodSync),
+ lchown: promisify(fs.lchownSync),
+ link: promisify(fs.linkSync),
+ lstat: promisify(fs.lstatSync),
+ mkdir: promisify(fs.mkdirSync),
+ mkdtemp: promisify(fs.mkdtempSync),
+ open: promisify(fs.openSync),
+ read: promisify(fs.readSync),
+ write: promisify(fs.writeSync),
+ readdir: promisify(fs.readdirSync),
+ writeFile: promisify(fs.writeFileSync),
+ readlink: promisify(fs.readlinkSync),
+ realpath: promisify(fs.realpathSync),
+ rename: promisify(fs.renameSync),
+ stat: promisify(fs.statSync),
+ symlink: promisify(fs.symlinkSync),
+ truncate: promisify(fs.truncateSync),
+ unlink: promisify(fs.unlinkSync),
+ utimes: promisify(fs.utimesSync),
+ lutimes: promisify(fs.lutimesSync),
+};
+
+promises.readFile = promises.readfile = promisify(fs.readFileSync);
+
// lol
realpath.native = realpath;
realpathSync.native = realpathSync;
@@ -233,4 +304,5 @@ export default {
createReadStream,
createWriteStream,
constants,
+ promises,
};
diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig
index 9ed16caf0..5c4f2ae68 100644
--- a/src/bun.js/javascript.zig
+++ b/src/bun.js/javascript.zig
@@ -258,12 +258,17 @@ pub export fn Bun__drainMicrotasks() void {
JSC.VirtualMachine.vm.eventLoop().tick();
}
+export fn Bun__readOriginTimer(vm: *JSC.VirtualMachine) u64 {
+ return vm.origin_timer.read();
+}
+
comptime {
if (!JSC.is_bindgen) {
_ = Bun__getDefaultGlobal;
_ = Bun__getVM;
_ = Bun__drainMicrotasks;
_ = Bun__queueMicrotask;
+ _ = Bun__readOriginTimer;
}
}
diff --git a/src/bun.js/javascript_core_c_api.zig b/src/bun.js/javascript_core_c_api.zig
index aa9af2b7e..82145defc 100644
--- a/src/bun.js/javascript_core_c_api.zig
+++ b/src/bun.js/javascript_core_c_api.zig
@@ -102,15 +102,31 @@ pub extern fn JSValueToNumber(ctx: JSContextRef, value: JSValueRef, exception: E
pub extern fn JSValueToStringCopy(ctx: JSContextRef, value: JSValueRef, exception: ExceptionRef) JSStringRef;
pub extern fn JSValueToObject(ctx: JSContextRef, value: JSValueRef, exception: ExceptionRef) JSObjectRef;
+const log_protection = @import("../global.zig").Environment.allow_assert;
+pub inline fn JSValueUnprotect(ctx: JSContextRef, value: JSValueRef) void {
+ const Wrapped = struct {
+ pub extern fn JSValueUnprotect(ctx: JSContextRef, value: JSValueRef) void;
+ };
+ if (comptime log_protection) {
+ const Output = @import("../global.zig").Output;
+ Output.debug("[unprotect] {d}\n", .{@ptrToInt(value)});
+ }
+ // wrapper exists to make it easier to set a breakpoint
+ Wrapped.JSValueUnprotect(ctx, value);
+}
+
pub inline fn JSValueProtect(ctx: JSContextRef, value: JSValueRef) void {
const Wrapped = struct {
pub extern fn JSValueProtect(ctx: JSContextRef, value: JSValueRef) void;
};
+ if (comptime log_protection) {
+ const Output = @import("../global.zig").Output;
+ Output.debug("[protect] {d}\n", .{@ptrToInt(value)});
+ }
// wrapper exists to make it easier to set a breakpoint
Wrapped.JSValueProtect(ctx, value);
}
-pub extern fn JSValueUnprotect(ctx: JSContextRef, value: JSValueRef) void;
pub const JSPropertyAttributes = enum(c_uint) {
kJSPropertyAttributeNone = 0,
kJSPropertyAttributeReadOnly = 2,
diff --git a/src/bun.js/webcore.zig b/src/bun.js/webcore.zig
index 0433402fc..981e15c8f 100644
--- a/src/bun.js/webcore.zig
+++ b/src/bun.js/webcore.zig
@@ -92,39 +92,3 @@ pub const Crypto = struct {
return JSC.ZigString.init(str).toValueGC(ctx.ptr()).asObjectRef();
}
};
-
-pub const Performance = struct {
- pub const Class = JSC.NewClass(
- void,
- .{
- .name = "performance",
- .read_only = true,
- },
- .{
- .now = .{
- .rfn = Performance.now,
- },
- },
- .{},
- );
-
- pub fn now(
- _: void,
- ctx: JSC.C.JSContextRef,
- _: JSC.C.JSObjectRef,
- _: JSC.C.JSObjectRef,
- _: []const JSC.C.JSValueRef,
- _: JSC.C.ExceptionRef,
- ) JSC.C.JSValueRef {
- return JSC.C.JSValueMakeNumber(
- ctx,
- @floatCast(
- f64,
- @intToFloat(
- f128,
- JSC.VirtualMachine.vm.origin_timer.read(),
- ) / std.time.ns_per_ms,
- ),
- );
- }
-};
diff --git a/src/deps/uws b/src/deps/uws
-Subproject f0ea7574ab3c642bc1c0ee4991e771c1ee164f4
+Subproject 1b46cf9ace5f55f713d55bb8c086f5878d13245
diff --git a/src/feature_flags.zig b/src/feature_flags.zig
index 6fe6da892..dc77a47e6 100644
--- a/src/feature_flags.zig
+++ b/src/feature_flags.zig
@@ -95,4 +95,4 @@ pub const simd = true;
// This change didn't seem to make a meaningful difference in microbenchmarks
pub const latin1_is_now_ascii = false;
-pub const http_buffer_pooling = false;
+pub const http_buffer_pooling = true;
diff --git a/src/js_printer.zig b/src/js_printer.zig
index 1a68c6662..945e0a382 100644
--- a/src/js_printer.zig
+++ b/src/js_printer.zig
@@ -340,8 +340,14 @@ pub fn writeJSONString(text: []const u8, comptime Writer: type, writer: Writer,
test "quoteForJSON" {
var allocator = default_allocator;
- try std.testing.expectEqualStrings("\"I don't need any quotes.\"", try quoteForJSON("I don't need any quotes.", allocator, false));
- try std.testing.expectEqualStrings("\"I need a quote for \\\"this\\\".\"", try quoteForJSON("I need a quote for \"this\".", allocator, false));
+ try std.testing.expectEqualStrings(
+ "\"I don't need any quotes.\"",
+ (try quoteForJSON("I don't need any quotes.", MutableString.init(allocator, 0) catch unreachable, false)).list.items,
+ );
+ try std.testing.expectEqualStrings(
+ "\"I need a quote for \\\"this\\\".\"",
+ (try quoteForJSON("I need a quote for \"this\".", MutableString.init(allocator, 0) catch unreachable, false)).list.items,
+ );
}
pub const SourceMapHandler = struct {
diff --git a/src/sourcemap/sourcemap.zig b/src/sourcemap/sourcemap.zig
index 22a916940..92bd6189c 100644
--- a/src/sourcemap/sourcemap.zig
+++ b/src/sourcemap/sourcemap.zig
@@ -645,7 +645,11 @@ pub const LineOffsetTable = struct {
}
if (c > 0x7F and columns_for_non_ascii.items.len == 0) {
-
+ std.debug.assert(@ptrToInt(
+ remaining.ptr,
+ ) > @ptrToInt(
+ contents.ptr,
+ ));
// we have a non-ASCII character, so we need to keep track of the
// mapping from byte offsets to UTF-16 code unit counts
columns_for_non_ascii.appendAssumeCapacity(column);
diff --git a/src/string_immutable.zig b/src/string_immutable.zig
index d4dc7c6c1..5ee958b40 100644
--- a/src/string_immutable.zig
+++ b/src/string_immutable.zig
@@ -2624,19 +2624,24 @@ pub fn indexOfNewlineOrNonASCIICheckStart(slice_: []const u8, offset: u32, compt
const cmp = @bitCast(AsciiVectorU1, (vec > max_16_ascii)) | @bitCast(AsciiVectorU1, (vec < min_16_ascii)) |
@bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '\r'))) |
@bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '\n')));
- const bitmask = @ptrCast(*const AsciiVectorInt, &cmp).*;
- const first = @ctz(AsciiVectorInt, bitmask);
- if (first < ascii_vector_size) {
+
+ if (@reduce(.Max, cmp) > 0) {
+ const bitmask = @ptrCast(*const AsciiVectorInt, &cmp).*;
+ const first = @ctz(AsciiVectorInt, bitmask);
+
return @as(u32, first) + @intCast(u32, slice.len - remaining.len) + offset;
}
remaining = remaining[ascii_vector_size..];
}
+
+ assert(remaining.len < ascii_vector_size);
}
- for (remaining) |char, i| {
+ for (remaining) |*char_| {
+ const char = char_.*;
if (char > 127 or char < 0x20 or char == '\n' or char == '\r') {
- return @truncate(u32, i + (slice.len - remaining.len)) + offset;
+ return @truncate(u32, (@ptrToInt(char_) - @ptrToInt(slice.ptr))) + offset;
}
}
@@ -2658,19 +2663,22 @@ pub fn indexOfNeedsEscape(slice: []const u8) ?u32 {
const cmp = @bitCast(AsciiVectorU1, (vec > max_16_ascii)) | @bitCast(AsciiVectorU1, (vec < min_16_ascii)) |
@bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '\\'))) |
@bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '"')));
- const bitmask = @ptrCast(*const AsciiVectorInt, &cmp).*;
- const first = @ctz(AsciiVectorInt, bitmask);
- if (first < ascii_vector_size) {
- return @as(u32, first) + @intCast(u32, slice.len - remaining.len);
+
+ if (@reduce(.Max, cmp) > 0) {
+ const bitmask = @ptrCast(*const AsciiVectorInt, &cmp).*;
+ const first = @ctz(AsciiVectorInt, bitmask);
+
+ return @as(u32, first) + @truncate(u32, @ptrToInt(remaining.ptr) - @ptrToInt(slice.ptr));
}
remaining = remaining[ascii_vector_size..];
}
}
- for (remaining) |char, i| {
+ for (remaining) |*char_| {
+ const char = char_.*;
if (char > 127 or char < 0x20 or char == '\\' or char == '"') {
- return @truncate(u32, i + (slice.len - remaining.len));
+ return @truncate(u32, @ptrToInt(char_) - @ptrToInt(slice.ptr));
}
}
@@ -2762,10 +2770,10 @@ pub fn indexOfNotChar(slice: []const u8, char: u8) ?u32 {
if (comptime Environment.isAarch64 or Environment.isX64) {
while (remaining.len >= ascii_vector_size) {
const vec: AsciiVector = remaining[0..ascii_vector_size].*;
- const cmp = vec != @splat(ascii_vector_size, char);
- const bitmask = @ptrCast(*const AsciiVectorInt, &cmp).*;
- const first = @ctz(AsciiVectorInt, bitmask);
- if (first < ascii_vector_size) {
+ const cmp = @splat(ascii_vector_size, char) != vec;
+ if (@reduce(.Min, @bitCast(AsciiVectorU1, cmp)) > 0) {
+ const bitmask = @ptrCast(*const AsciiVectorInt, &cmp).*;
+ const first = @ctz(AsciiVectorInt, bitmask);
return @as(u32, first) + @intCast(u32, slice.len - remaining.len);
}
@@ -2773,11 +2781,10 @@ pub fn indexOfNotChar(slice: []const u8, char: u8) ?u32 {
}
}
- while (remaining.len > 0) {
- if (remaining[0] != char) {
- return @truncate(u32, (slice.len - remaining.len));
+ for (remaining) |*current| {
+ if (current.* != char) {
+ return @truncate(u32, @ptrToInt(current) - @ptrToInt(slice.ptr));
}
- remaining = remaining[1..];
}
return null;