mirror of
https://github.com/oven-sh/bun
synced 2026-02-18 06:41:50 +00:00
Merge branch 'jarred/process-change' of github.com:oven-sh/bun into jarred/process-change
This commit is contained in:
@@ -157,7 +157,7 @@ pub const IO = struct {
|
||||
std: struct { captured: ?*bun.ByteList = null },
|
||||
/// Write/Read to/from file descriptor
|
||||
fd: bun.FileDescriptor,
|
||||
/// Buffers the output
|
||||
/// Buffers the output (handled in Cmd.BufferedIoClosed.close())
|
||||
pipe,
|
||||
/// Discards output
|
||||
ignore,
|
||||
@@ -856,7 +856,7 @@ pub const Interpreter = struct {
|
||||
jsobjs.items[0..],
|
||||
)) {
|
||||
.result => |i| i,
|
||||
.err => |e| {
|
||||
.err => |*e| {
|
||||
arena.deinit();
|
||||
throwShellErr(e, .{ .js = globalThis.bunVM().event_loop });
|
||||
return null;
|
||||
@@ -1026,7 +1026,7 @@ pub const Interpreter = struct {
|
||||
const script_heap = try arena.allocator().create(ast.Script);
|
||||
script_heap.* = script;
|
||||
var interp = switch (ThisInterpreter.init(.{ .mini = mini }, bun.default_allocator, &arena, script_heap, jsobjs)) {
|
||||
.err => |e| {
|
||||
.err => |*e| {
|
||||
throwShellErr(e, .{ .mini = mini });
|
||||
return;
|
||||
},
|
||||
@@ -1072,7 +1072,7 @@ pub const Interpreter = struct {
|
||||
const script_heap = try arena.allocator().create(ast.Script);
|
||||
script_heap.* = script;
|
||||
var interp = switch (ThisInterpreter.init(mini, bun.default_allocator, &arena, script_heap, jsobjs)) {
|
||||
.err => |e| {
|
||||
.err => |*e| {
|
||||
throwShellErr(e, .{ .mini = mini });
|
||||
return;
|
||||
},
|
||||
@@ -1610,7 +1610,7 @@ pub const Interpreter = struct {
|
||||
const shell_state = switch (this.base.shell.dupeForSubshell(this.base.interpreter.allocator, io, .cmd_subst)) {
|
||||
.result => |s| s,
|
||||
.err => |e| {
|
||||
throwShellErr(bun.shell.ShellErr.newSys(e), this.base.eventLoop());
|
||||
this.base.throw(&bun.shell.ShellErr.newSys(e));
|
||||
return false;
|
||||
},
|
||||
};
|
||||
@@ -1637,7 +1637,7 @@ pub const Interpreter = struct {
|
||||
const shell_state = switch (this.base.shell.dupeForSubshell(this.base.interpreter.allocator, io, .cmd_subst)) {
|
||||
.result => |s| s,
|
||||
.err => |e| {
|
||||
throwShellErr(bun.shell.ShellErr.newSys(e), this.base.eventLoop());
|
||||
this.base.throw(&bun.shell.ShellErr.newSys(e));
|
||||
return false;
|
||||
},
|
||||
};
|
||||
@@ -1790,15 +1790,15 @@ pub const Interpreter = struct {
|
||||
std.debug.assert(this.child_state == .glob);
|
||||
}
|
||||
|
||||
if (task.err != null) {
|
||||
switch (task.err.?) {
|
||||
if (task.err) |*err| {
|
||||
switch (err.*) {
|
||||
.syscall => {
|
||||
throwShellErr(bun.shell.ShellErr.newSys(task.err.?.syscall), this.base.eventLoop());
|
||||
this.base.throw(&bun.shell.ShellErr.newSys(task.err.?.syscall));
|
||||
},
|
||||
.unknown => |errtag| {
|
||||
throwShellErr(.{
|
||||
this.base.throw(&.{
|
||||
.custom = bun.default_allocator.dupe(u8, @errorName(errtag)) catch bun.outOfMemory(),
|
||||
}, this.base.eventLoop());
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -2010,6 +2010,10 @@ pub const Interpreter = struct {
|
||||
.expansion = expansion,
|
||||
.result = std.ArrayList([:0]const u8).init(allocator),
|
||||
};
|
||||
if (bun.Environment.isWindows) {
|
||||
// event loop here is js event loop
|
||||
@panic("TODO SHELL WINDOWS!");
|
||||
}
|
||||
// this.ref.ref(this.event_loop.virtual_machine);
|
||||
this.ref.ref(this.event_loop);
|
||||
|
||||
@@ -2050,6 +2054,10 @@ pub const Interpreter = struct {
|
||||
|
||||
pub fn runFromMainThread(this: *This) void {
|
||||
print("runFromJS", .{});
|
||||
if (bun.Environment.isWindows) {
|
||||
// event loop here is js event loop
|
||||
@panic("TODO SHELL WINDOWS!");
|
||||
}
|
||||
this.expansion.onGlobWalkDone(this);
|
||||
// this.ref.unref(this.event_loop.virtual_machine);
|
||||
this.ref.unref(this.event_loop);
|
||||
@@ -2086,9 +2094,13 @@ pub const Interpreter = struct {
|
||||
interpreter: *ThisInterpreter,
|
||||
shell: *ShellState,
|
||||
|
||||
pub inline fn eventLoop(this: *State) JSC.EventLoopHandle {
|
||||
pub inline fn eventLoop(this: *const State) JSC.EventLoopHandle {
|
||||
return this.interpreter.event_loop;
|
||||
}
|
||||
|
||||
pub fn throw(this: *const State, err: *const bun.shell.ShellErr) void {
|
||||
throwShellErr(err, this.eventLoop());
|
||||
}
|
||||
};
|
||||
|
||||
pub const Script = struct {
|
||||
@@ -2766,7 +2778,7 @@ pub const Interpreter = struct {
|
||||
}
|
||||
|
||||
if (err) |e| {
|
||||
throwShellErr(shell.ShellErr.newSys(e), this.base.eventLoop());
|
||||
this.base.throw(&shell.ShellErr.newSys(e));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3202,7 +3214,7 @@ pub const Interpreter = struct {
|
||||
|
||||
pub fn onBufferedWriterDone(this: *Cmd, e: ?Syscall.Error) void {
|
||||
if (e) |err| {
|
||||
throwShellErr(bun.shell.ShellErr.newSys(err), this.base.eventLoop());
|
||||
this.base.throw(&bun.shell.ShellErr.newSys(err));
|
||||
return;
|
||||
}
|
||||
std.debug.assert(this.state == .waiting_write_err);
|
||||
@@ -3461,8 +3473,8 @@ pub const Interpreter = struct {
|
||||
} };
|
||||
const subproc = switch (Subprocess.spawnAsync(this.base.eventLoop(), spawn_args, &this.exec.subproc.child)) {
|
||||
.result => this.exec.subproc.child,
|
||||
.err => |e| {
|
||||
throwShellErr(e, this.base.eventLoop());
|
||||
.err => |*e| {
|
||||
this.base.throw(e);
|
||||
return;
|
||||
},
|
||||
};
|
||||
@@ -3975,8 +3987,8 @@ pub const Interpreter = struct {
|
||||
const path = cmd.redirection_file.items[0..cmd.redirection_file.items.len -| 1 :0];
|
||||
log("EXPANDED REDIRECT: {s}\n", .{cmd.redirection_file.items[0..]});
|
||||
const perm = 0o666;
|
||||
const extra: bun.Mode = if (node.redirect.append) std.os.O.APPEND else std.os.O.TRUNC;
|
||||
const redirfd = switch (Syscall.openat(cmd.base.shell.cwd_fd, path, std.os.O.WRONLY | std.os.O.CREAT | extra, perm)) {
|
||||
const flags = node.redirect.toFlags();
|
||||
const redirfd = switch (Syscall.openat(cmd.base.shell.cwd_fd, path, flags, perm)) {
|
||||
.err => |e| {
|
||||
const buf = std.fmt.allocPrint(arena.allocator(), "bun: {s}: {s}", .{ e.toSystemError().message, path }) catch bun.outOfMemory();
|
||||
cmd.writeFailingError(buf, 1);
|
||||
@@ -3996,12 +4008,11 @@ pub const Interpreter = struct {
|
||||
}
|
||||
},
|
||||
.jsbuf => |val| {
|
||||
if (cmd.base.eventLoop() == .mini) @panic("This should never happened");
|
||||
const global = cmd.base.eventLoop().js.global;
|
||||
if (interpreter.jsobjs[file.jsbuf.idx].asArrayBuffer(global)) |buf| {
|
||||
const globalObject = interpreter.event_loop.js.global;
|
||||
if (interpreter.jsobjs[file.jsbuf.idx].asArrayBuffer(globalObject)) |buf| {
|
||||
const builtinio: Builtin.BuiltinIO = .{ .arraybuf = .{ .buf = JSC.ArrayBuffer.Strong{
|
||||
.array_buffer = buf,
|
||||
.held = JSC.Strong.create(buf.value, global),
|
||||
.held = JSC.Strong.create(buf.value, globalObject),
|
||||
}, .i = 0 } };
|
||||
|
||||
if (node.redirect.stdin) {
|
||||
@@ -4031,21 +4042,38 @@ pub const Interpreter = struct {
|
||||
}
|
||||
} else {
|
||||
const jsval = cmd.base.interpreter.jsobjs[val.idx];
|
||||
global.throw("Unknown JS value used in shell: {}", .{jsval.fmtString(global)});
|
||||
cmd.base.interpreter.event_loop.js.global.throw("Unknown JS value used in shell: {}", .{jsval.fmtString(globalObject)});
|
||||
return .yield;
|
||||
}
|
||||
},
|
||||
}
|
||||
} else if (node.redirect.duplicate_out) {
|
||||
if (node.redirect.stdout) {
|
||||
cmd.exec.bltn.stderr = cmd.exec.bltn.stdout;
|
||||
}
|
||||
|
||||
if (node.redirect.stderr) {
|
||||
cmd.exec.bltn.stdout = cmd.exec.bltn.stderr;
|
||||
}
|
||||
}
|
||||
|
||||
return .cont;
|
||||
}
|
||||
|
||||
pub inline fn eventLoop(this: *Builtin) JSC.EventLoopHandle {
|
||||
pub inline fn eventLoop(this: *const Builtin) JSC.EventLoopHandle {
|
||||
return this.parentCmd().base.eventLoop();
|
||||
}
|
||||
|
||||
pub inline fn parentCmd(this: *Builtin) *Cmd {
|
||||
pub inline fn throw(this: *const Builtin, err: *const bun.shell.ShellErr) void {
|
||||
this.parentCmd().base.throw(err);
|
||||
}
|
||||
|
||||
pub inline fn parentCmd(this: *const Builtin) *const Cmd {
|
||||
const union_ptr = @fieldParentPtr(Cmd.Exec, "bltn", this);
|
||||
return @fieldParentPtr(Cmd, "exec", union_ptr);
|
||||
}
|
||||
|
||||
pub inline fn parentCmdMut(this: *Builtin) *Cmd {
|
||||
const union_ptr = @fieldParentPtr(Cmd.Exec, "bltn", this);
|
||||
return @fieldParentPtr(Cmd, "exec", union_ptr);
|
||||
}
|
||||
@@ -4056,7 +4084,7 @@ pub const Interpreter = struct {
|
||||
// }
|
||||
this.exit_code = exit_code;
|
||||
|
||||
var cmd = this.parentCmd();
|
||||
var cmd = this.parentCmdMut();
|
||||
log("builtin done ({s}: exit={d}) cmd to free: ({x})", .{ @tagName(this.kind), exit_code, @intFromPtr(cmd) });
|
||||
cmd.exit_code = this.exit_code.?;
|
||||
|
||||
@@ -4913,11 +4941,11 @@ pub const Interpreter = struct {
|
||||
if (paths) |p| {
|
||||
for (p) |path_raw| {
|
||||
const path = path_raw[0..std.mem.len(path_raw) :0];
|
||||
var task = ShellLsTask.create(this, this.opts, &this.state.exec.task_count, cwd, path, this.bltn.parentCmd().base.eventLoop());
|
||||
var task = ShellLsTask.create(this, this.opts, &this.state.exec.task_count, cwd, path, this.bltn.eventLoop());
|
||||
task.schedule();
|
||||
}
|
||||
} else {
|
||||
var task = ShellLsTask.create(this, this.opts, &this.state.exec.task_count, cwd, ".", this.bltn.parentCmd().base.eventLoop());
|
||||
var task = ShellLsTask.create(this, this.opts, &this.state.exec.task_count, cwd, ".", this.bltn.eventLoop());
|
||||
task.schedule();
|
||||
}
|
||||
},
|
||||
@@ -5027,7 +5055,7 @@ pub const Interpreter = struct {
|
||||
// if (!need_to_write_to_stdout_with_io) return; // yield execution
|
||||
} else {
|
||||
if (this.bltn.writeNoIO(.stderr, error_string).asErr()) |theerr| {
|
||||
throwShellErr(bun.shell.ShellErr.newSys(theerr), this.bltn.eventLoop());
|
||||
this.bltn.throw(&bun.shell.ShellErr.newSys(theerr));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5058,7 +5086,7 @@ pub const Interpreter = struct {
|
||||
defer output.deinit();
|
||||
|
||||
if (this.bltn.writeNoIO(.stdout, output.items[0..]).asErr()) |e| {
|
||||
throwShellErr(bun.shell.ShellErr.newSys(e), this.bltn.eventLoop());
|
||||
this.bltn.throw(&bun.shell.ShellErr.newSys(e));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6711,7 +6739,7 @@ pub const Interpreter = struct {
|
||||
const error_string = this.bltn.taskErrorToString(.rm, err);
|
||||
if (!this.bltn.stderr.needsIO()) {
|
||||
if (this.bltn.writeNoIO(.stderr, error_string).asErr()) |e| {
|
||||
throwShellErr(bun.shell.ShellErr.newSys(e), this.bltn.parentCmd().base.eventLoop());
|
||||
this.bltn.throw(&bun.shell.ShellErr.newSys(e));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -6747,7 +6775,7 @@ pub const Interpreter = struct {
|
||||
fn writeVerbose(this: *Rm, verbose: *ShellRmTask.DirTask) void {
|
||||
if (!this.bltn.stdout.needsIO()) {
|
||||
if (this.bltn.writeNoIO(.stdout, verbose.deleted_entries.items[0..]).asErr()) |err| {
|
||||
throwShellErr(bun.shell.ShellErr.newSys(err), this.bltn.parentCmd().base.eventLoop());
|
||||
this.bltn.parentCmd().base.throw(&bun.shell.ShellErr.newSys(err));
|
||||
return;
|
||||
}
|
||||
// _ = this.state.exec.output_done.fetchAdd(1, .SeqCst);
|
||||
@@ -7377,8 +7405,7 @@ pub const Interpreter = struct {
|
||||
/// it. IT DOES NOT CLOSE FILE DESCRIPTORS
|
||||
pub const BufferedWriter =
|
||||
struct {
|
||||
pseudoref_count: u32 = 1,
|
||||
writer: Writer = .{
|
||||
writer: Writer = if (bun.Environment.isWindows) .{} else .{
|
||||
.close_fd = false,
|
||||
},
|
||||
fd: bun.FileDescriptor = bun.invalid_fd,
|
||||
@@ -7613,7 +7640,7 @@ pub fn MaybeChild(comptime T: type) type {
|
||||
pub fn closefd(fd: bun.FileDescriptor) void {
|
||||
if (Syscall.close2(fd)) |err| {
|
||||
_ = err;
|
||||
log("ERR closefd: {d}\n", .{fd});
|
||||
log("ERR closefd: {}\n", .{fd});
|
||||
// stderr_mutex.lock();
|
||||
// defer stderr_mutex.unlock();
|
||||
// const stderr = std.io.getStdErr().writer();
|
||||
@@ -7696,6 +7723,11 @@ pub fn ShellTask(
|
||||
|
||||
pub fn schedule(this: *@This()) void {
|
||||
print("schedule", .{});
|
||||
|
||||
if (bun.Environment.isWindows) {
|
||||
// event loop here is js event loop
|
||||
@panic("TODO SHELL WINDOWS!");
|
||||
}
|
||||
this.ref.ref(this.event_loop);
|
||||
WorkPool.schedule(&this.task);
|
||||
}
|
||||
@@ -7742,7 +7774,7 @@ inline fn fastMod(val: anytype, comptime rhs: comptime_int) @TypeOf(val) {
|
||||
return val & (rhs - 1);
|
||||
}
|
||||
|
||||
fn throwShellErr(e: bun.shell.ShellErr, event_loop: JSC.EventLoopHandle) void {
|
||||
fn throwShellErr(e: *const bun.shell.ShellErr, event_loop: JSC.EventLoopHandle) void {
|
||||
switch (event_loop) {
|
||||
.mini => e.throwMini(),
|
||||
.js => e.throwJS(event_loop.js.global),
|
||||
|
||||
@@ -67,8 +67,8 @@ pub const ShellErr = union(enum) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn throwJS(this: @This(), globalThis: *JSC.JSGlobalObject) void {
|
||||
switch (this) {
|
||||
pub fn throwJS(this: *const @This(), globalThis: *JSC.JSGlobalObject) void {
|
||||
switch (this.*) {
|
||||
.sys => {
|
||||
const err = this.sys.toErrorInstance(globalThis);
|
||||
globalThis.throwValue(err);
|
||||
@@ -77,7 +77,7 @@ pub const ShellErr = union(enum) {
|
||||
var str = JSC.ZigString.init(this.custom);
|
||||
str.markUTF8();
|
||||
const err_value = str.toErrorInstance(globalThis);
|
||||
globalThis.vm().throwError(globalThis, err_value);
|
||||
globalThis.throwValue(err_value);
|
||||
// this.bunVM().allocator.free(JSC.ZigString.untagged(str._unsafe_ptr_do_not_use)[0..str.len]);
|
||||
},
|
||||
.invalid_arguments => {
|
||||
@@ -441,7 +441,33 @@ pub const AST = struct {
|
||||
stdout: bool = false,
|
||||
stderr: bool = false,
|
||||
append: bool = false,
|
||||
__unused: u4 = 0,
|
||||
/// 1>&2 === stdout=true and duplicate_out=true
|
||||
/// 2>&1 === stderr=true and duplicate_out=true
|
||||
duplicate_out: bool = false,
|
||||
__unused: u3 = 0,
|
||||
|
||||
pub fn redirectsElsewhere(this: RedirectFlags, io_kind: enum { stdin, stdout, stderr }) bool {
|
||||
return switch (io_kind) {
|
||||
.stdin => this.stdin,
|
||||
.stdout => if (this.duplicate_out) !this.stdout else this.stdout,
|
||||
.stderr => if (this.duplicate_out) !this.stderr else this.stderr,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn @"2>&1"() RedirectFlags {
|
||||
return .{ .stderr = true, .duplicate = true };
|
||||
}
|
||||
|
||||
pub fn @"1>&2"() RedirectFlags {
|
||||
return .{ .stdout = true, .duplicate = true };
|
||||
}
|
||||
|
||||
pub fn toFlags(this: RedirectFlags) bun.Mode {
|
||||
const read_write_flags: bun.Mode = if (this.stdin) std.os.O.RDONLY else std.os.O.WRONLY | std.os.O.CREAT;
|
||||
const extra: bun.Mode = if (this.append) std.os.O.APPEND else std.os.O.TRUNC;
|
||||
const final_flags: bun.Mode = if (this.stdin) read_write_flags else extra | read_write_flags;
|
||||
return final_flags;
|
||||
}
|
||||
|
||||
pub fn @"<"() RedirectFlags {
|
||||
return .{ .stdin = true };
|
||||
@@ -784,6 +810,7 @@ pub const Parser = struct {
|
||||
}
|
||||
|
||||
const redirect_file = try self.parse_atom() orelse {
|
||||
if (redirect.duplicate_out) break :redirect_file null;
|
||||
try self.add_error("Redirection with no file", .{});
|
||||
return ParseError.Expected;
|
||||
};
|
||||
@@ -801,6 +828,8 @@ pub const Parser = struct {
|
||||
} };
|
||||
}
|
||||
|
||||
const ParsedRedirect = struct { flags: AST.Cmd.RedirectFlags, redirect: AST.Cmd.Redirect };
|
||||
|
||||
/// Try to parse an assignment. If no assignment could be parsed then return
|
||||
/// null and backtrack the parser state
|
||||
fn parse_assign(self: *Parser) !?AST.Assign {
|
||||
@@ -1804,9 +1833,67 @@ pub fn NewLexer(comptime encoding: StringEncoding) type {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO Arbitrary file descriptor redirect
|
||||
fn eat_redirect(self: *@This(), first: InputChar) ?AST.Cmd.RedirectFlags {
|
||||
var flags: AST.Cmd.RedirectFlags = .{};
|
||||
switch (first.char) {
|
||||
'0' => flags.stdin = true,
|
||||
'1' => flags.stdout = true,
|
||||
'2' => flags.stderr = true,
|
||||
// Just allow the std file descriptors for now
|
||||
else => return null,
|
||||
}
|
||||
var dir: RedirectDirection = .out;
|
||||
if (self.peek()) |input| {
|
||||
if (input.escaped) return null;
|
||||
switch (input.char) {
|
||||
'>' => {
|
||||
_ = self.eat();
|
||||
dir = .out;
|
||||
const is_double = self.eat_simple_redirect_operator(dir);
|
||||
if (is_double) flags.append = true;
|
||||
if (self.peek()) |peeked| {
|
||||
if (!peeked.escaped and peeked.char == '&') {
|
||||
_ = self.eat();
|
||||
if (self.peek()) |peeked2| {
|
||||
switch (peeked2.char) {
|
||||
'1' => {
|
||||
_ = self.eat();
|
||||
if (!flags.stdout and flags.stderr) {
|
||||
flags.duplicate_out = true;
|
||||
flags.stdout = true;
|
||||
flags.stderr = false;
|
||||
} else return null;
|
||||
},
|
||||
'2' => {
|
||||
_ = self.eat();
|
||||
if (!flags.stderr and flags.stdout) {
|
||||
flags.duplicate_out = true;
|
||||
flags.stderr = true;
|
||||
flags.stdout = false;
|
||||
} else return null;
|
||||
},
|
||||
else => return null,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
},
|
||||
'<' => {
|
||||
dir = .in;
|
||||
const is_double = self.eat_simple_redirect_operator(dir);
|
||||
if (is_double) flags.append = true;
|
||||
return flags;
|
||||
},
|
||||
else => return null,
|
||||
}
|
||||
} else return null;
|
||||
}
|
||||
|
||||
fn eat_redirect_old(self: *@This(), first: InputChar) ?AST.Cmd.RedirectFlags {
|
||||
var flags: AST.Cmd.RedirectFlags = .{};
|
||||
if (self.matchesAsciiLiteral("2>&1")) {} else if (self.matchesAsciiLiteral("1>&2")) {} else switch (first.char) {
|
||||
'0'...'9' => {
|
||||
// Codepoint int casts are safe here because the digits are in the ASCII range
|
||||
var count: usize = 1;
|
||||
@@ -1952,13 +2039,25 @@ pub fn NewLexer(comptime encoding: StringEncoding) type {
|
||||
|
||||
fn appendStringToStrPool(self: *@This(), bunstr: bun.String) !void {
|
||||
const start = self.strpool.items.len;
|
||||
if (bunstr.is8Bit() or bunstr.isUTF8()) {
|
||||
try self.strpool.appendSlice(bunstr.byteSlice());
|
||||
} else {
|
||||
if (bunstr.isUTF16()) {
|
||||
const utf16 = bunstr.utf16();
|
||||
const additional = bun.simdutf.simdutf__utf8_length_from_utf16le(utf16.ptr, utf16.len);
|
||||
try self.strpool.ensureUnusedCapacity(additional);
|
||||
try bun.strings.convertUTF16ToUTF8Append(&self.strpool, bunstr.utf16());
|
||||
} else if (bunstr.isUTF8()) {
|
||||
try self.strpool.appendSlice(bunstr.byteSlice());
|
||||
} else if (bunstr.is8Bit()) {
|
||||
if (isAllAscii(bunstr.byteSlice())) {
|
||||
try self.strpool.appendSlice(bunstr.byteSlice());
|
||||
} else {
|
||||
const bytes = bunstr.byteSlice();
|
||||
const non_ascii_idx = bun.strings.firstNonASCII(bytes) orelse 0;
|
||||
|
||||
if (non_ascii_idx > 0) {
|
||||
try self.strpool.appendSlice(bytes[0..non_ascii_idx]);
|
||||
}
|
||||
self.strpool = try bun.strings.allocateLatin1IntoUTF8WithList(self.strpool, self.strpool.items.len, []const u8, bytes[non_ascii_idx..]);
|
||||
}
|
||||
}
|
||||
const end = self.strpool.items.len;
|
||||
self.j += @intCast(end - start);
|
||||
@@ -1980,10 +2079,33 @@ pub fn NewLexer(comptime encoding: StringEncoding) type {
|
||||
return std.mem.eql(u8, bytes[0 .. LEX_JS_STRING_PREFIX.len - 1], LEX_JS_STRING_PREFIX[1..]);
|
||||
}
|
||||
|
||||
fn eatJSSubstitutionIdx(self: *@This(), comptime literal: []const u8, comptime name: []const u8, comptime validate: *const fn (*@This(), usize) bool) ?usize {
|
||||
fn bumpCursorAscii(self: *@This(), new_idx: usize, prev_ascii_char: ?u7, cur_ascii_char: u7) void {
|
||||
if (comptime encoding == .ascii) {
|
||||
self.chars.src.i = new_idx;
|
||||
if (prev_ascii_char) |pc| self.chars.prev = .{ .char = pc };
|
||||
self.chars.current = .{ .char = cur_ascii_char };
|
||||
return;
|
||||
}
|
||||
self.chars.src.cursor = CodepointIterator.Cursor{
|
||||
.i = @intCast(new_idx),
|
||||
.c = cur_ascii_char,
|
||||
.width = 1,
|
||||
};
|
||||
self.chars.src.next_cursor = self.chars.src.cursor;
|
||||
SrcUnicode.nextCursor(&self.chars.src.iter, &self.chars.src.next_cursor);
|
||||
if (prev_ascii_char) |pc| self.chars.prev = .{ .char = pc };
|
||||
self.chars.current = .{ .char = cur_ascii_char };
|
||||
}
|
||||
|
||||
fn matchesAsciiLiteral(self: *@This(), literal: []const u8) bool {
|
||||
const bytes = self.chars.srcBytesAtCursor();
|
||||
if (literal.len - 1 >= bytes.len) return null;
|
||||
if (std.mem.eql(u8, bytes[0 .. literal.len - 1], literal[1..])) {
|
||||
if (literal.len >= bytes.len) return false;
|
||||
return std.mem.eql(u8, bytes[0..literal.len], literal[0..]);
|
||||
}
|
||||
|
||||
fn eatJSSubstitutionIdx(self: *@This(), comptime literal: []const u8, comptime name: []const u8, comptime validate: *const fn (*@This(), usize) bool) ?usize {
|
||||
if (self.matchesAsciiLiteral(literal[1..literal.len])) {
|
||||
const bytes = self.chars.srcBytesAtCursor();
|
||||
var i: usize = 0;
|
||||
var digit_buf: [32]u8 = undefined;
|
||||
var digit_buf_count: u8 = 0;
|
||||
@@ -2024,26 +2146,10 @@ pub fn NewLexer(comptime encoding: StringEncoding) type {
|
||||
// }
|
||||
|
||||
// Bump the cursor
|
||||
brk: {
|
||||
const new_idx = self.chars.cursorPos() + i;
|
||||
const prev_ascii_char: ?u7 = if (digit_buf_count == 1) null else @truncate(digit_buf[digit_buf_count - 2]);
|
||||
const cur_ascii_char: u7 = @truncate(digit_buf[digit_buf_count - 1]);
|
||||
if (comptime encoding == .ascii) {
|
||||
self.chars.src.i = new_idx;
|
||||
if (prev_ascii_char) |pc| self.chars.prev = .{ .char = pc };
|
||||
self.chars.current = .{ .char = cur_ascii_char };
|
||||
break :brk;
|
||||
}
|
||||
self.chars.src.cursor = CodepointIterator.Cursor{
|
||||
.i = @intCast(new_idx),
|
||||
.c = cur_ascii_char,
|
||||
.width = 1,
|
||||
};
|
||||
self.chars.src.next_cursor = self.chars.src.cursor;
|
||||
SrcUnicode.nextCursor(&self.chars.src.iter, &self.chars.src.next_cursor);
|
||||
if (prev_ascii_char) |pc| self.chars.prev = .{ .char = pc };
|
||||
self.chars.current = .{ .char = cur_ascii_char };
|
||||
}
|
||||
const new_idx = self.chars.cursorPos() + i;
|
||||
const prev_ascii_char: ?u7 = if (digit_buf_count == 1) null else @truncate(digit_buf[digit_buf_count - 2]);
|
||||
const cur_ascii_char: u7 = @truncate(digit_buf[digit_buf_count - 1]);
|
||||
self.bumpCursorAscii(new_idx, prev_ascii_char, cur_ascii_char);
|
||||
|
||||
// return self.string_refs[idx];
|
||||
return idx;
|
||||
@@ -2891,16 +2997,15 @@ const SPECIAL_CHARS = [_]u8{ '$', '>', '&', '|', '=', ';', '\n', '{', '}', ',',
|
||||
const BACKSLASHABLE_CHARS = [_]u8{ '$', '`', '"', '\\' };
|
||||
|
||||
pub fn escapeBunStr(bunstr: bun.String, outbuf: *std.ArrayList(u8), comptime add_quotes: bool) !bool {
|
||||
// latin-1 or ascii
|
||||
if (bunstr.is8Bit()) {
|
||||
try escape8Bit(bunstr.byteSlice(), outbuf, add_quotes);
|
||||
return true;
|
||||
}
|
||||
if (bunstr.isUTF16()) {
|
||||
return try escapeUtf16(bunstr.utf16(), outbuf, add_quotes);
|
||||
}
|
||||
// Otherwise is utf-8
|
||||
try escapeWTF8(bunstr.byteSlice(), outbuf, add_quotes);
|
||||
if (bunstr.isUTF8()) {
|
||||
try escapeWTF8(bunstr.byteSlice(), outbuf, add_quotes);
|
||||
return true;
|
||||
}
|
||||
// otherwise should be latin-1 or ascii
|
||||
try escape8Bit(bunstr.byteSlice(), outbuf, add_quotes);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -520,9 +520,9 @@ pub const ShellSubprocess = struct {
|
||||
|
||||
var spawn_options = bun.spawn.SpawnOptions{
|
||||
.cwd = spawn_args.cwd,
|
||||
.stdin = spawn_args.stdio[0].toPosix(),
|
||||
.stdout = spawn_args.stdio[1].toPosix(),
|
||||
.stderr = spawn_args.stdio[2].toPosix(),
|
||||
.stdin = spawn_args.stdio[0].asSpawnOption(),
|
||||
.stdout = spawn_args.stdio[1].asSpawnOption(),
|
||||
.stderr = spawn_args.stdio[2].asSpawnOption(),
|
||||
};
|
||||
|
||||
spawn_args.argv.append(allocator, null) catch {
|
||||
|
||||
@@ -14,7 +14,16 @@ const Output = @import("root").bun.Output;
|
||||
const PosixSpawn = @import("../bun.js/api/bun/spawn.zig").PosixSpawn;
|
||||
const os = std.os;
|
||||
|
||||
pub const OutKind = enum { stdout, stderr };
|
||||
pub const OutKind = enum {
|
||||
stdout,
|
||||
stderr,
|
||||
pub fn toFd(this: OutKind) bun.FileDescriptor {
|
||||
return switch (this) {
|
||||
.stdout => bun.STDOUT_FD,
|
||||
.stderr => bun.STDERR_FD,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const Stdio = bun.spawn.Stdio;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user