fix package bug, improve stack trace

This commit is contained in:
2026-02-17 00:28:10 -06:00
parent 8a19cffe9f
commit 0ac575db85
6 changed files with 50 additions and 103 deletions

View File

@@ -2,8 +2,8 @@
## Building
Recompile after changes: `make`
Bootstrap from scratch (first time): `make bootstrap`
Build (or rebuild after changes): `make`
Install to system: `make install`
Run `cell --help` to see all CLI flags.
## Code Style

View File

@@ -1,83 +1,30 @@
# Development build: creates libcell_runtime.dylib + thin main wrapper
# This is the default target for working on cell itself
#
# If cell doesn't exist yet, use 'make bootstrap' first (requires meson)
# or manually build with meson once.
#
# The cell shop is at ~/.cell and core scripts are installed to ~/.cell/core
BUILD = build
INSTALL_BIN = /opt/homebrew/bin
INSTALL_LIB = /opt/homebrew/lib
INSTALL_INC = /opt/homebrew/include
CELL_SHOP = $(HOME)/.cell
CELL_SHOP = $(HOME)/.cell
CELL_CORE_PACKAGE = $(CELL_SHOP)/packages/core
all: $(BUILD)/build.ninja
meson compile -C $(BUILD)
cp $(BUILD)/libcell_runtime.dylib .
cp $(BUILD)/cell .
doit: bootstrap
$(BUILD)/build.ninja:
meson setup $(BUILD) -Dbuildtype=debugoptimized
maker: install
install: all $(CELL_SHOP)
cp cell $(INSTALL_BIN)/cell
cp libcell_runtime.dylib $(INSTALL_LIB)/
cp source/cell.h source/quickjs.h source/wota.h $(INSTALL_INC)/
rm -rf $(CELL_SHOP)/packages/core
ln -s $(CURDIR) $(CELL_SHOP)/packages/core
@echo "Installed cell to $(INSTALL_BIN) and $(INSTALL_LIB)"
makecell:
cell pack core -o cell
cp cell /opt/homebrew/bin/
# Install core: symlink this directory to ~/.cell/core
install: cell $(CELL_SHOP)
@echo "Linking cell core to $(CELL_CORE_PACKAGE)"
rm -rf $(CELL_CORE_PACKAGE)
ln -s $(PWD) $(CELL_CORE_PACKAGE)
cp cell /opt/homebrew/bin/
cp libcell_runtime.dylib /opt/homebrew/lib/
@echo "Core installed."
cell: libcell_runtime.dylib cell_main
cp cell_main cell
chmod +x cell
cp cell /opt/homebrew/bin/cell
cp libcell_runtime.dylib /opt/homebrew/lib/
# Build the shared runtime library (everything except main.c)
# Uses existing cell to run build -d
libcell_runtime.dylib: $(CELL_SHOP)/build/dynamic
cell build -d
cp $(CELL_SHOP)/build/dynamic/libcell_runtime.dylib .
# Build the thin main wrapper that links to libcell_runtime
cell_main: source/main.c libcell_runtime.dylib
cc -o cell_main source/main.c -L. -lcell_runtime -Wl,-rpath,@loader_path -Wl,-rpath,/opt/homebrew/lib
# Create the cell shop directories
$(CELL_SHOP):
mkdir -p $(CELL_SHOP)
mkdir -p $(CELL_SHOP)/packages
mkdir -p $(CELL_SHOP)/cache
mkdir -p $(CELL_SHOP)/build
mkdir -p $(CELL_SHOP)/packages $(CELL_SHOP)/cache $(CELL_SHOP)/build
$(CELL_CORE):
ln -s $(PWD) $(CELL_CORE)
# Static build: creates a fully static cell binary (for distribution)
static:
cell build
cp $(CELL_SHOP)/build/static/cell .
# Bootstrap: build cell from scratch using meson (only needed once)
# Also installs core scripts to ~/.cell/core
bootstrap:
meson setup build_bootstrap -Dbuildtype=debugoptimized
meson compile -C build_bootstrap
cp build_bootstrap/cell .
cp build_bootstrap/libcell_runtime.dylib .
@echo "Bootstrap complete. Run cell like ./cell --dev to use a local shop at .cell."
# Clean build artifacts
clean:
rm -rf $(CELL_SHOP)/build build_bootstrap
rm -f cell cell_main libcell_runtime.dylib
rm -rf $(BUILD)
rm -f cell libcell_runtime.dylib
# Ensure dynamic build directory exists
$(CELL_SHOP)/build/dynamic: $(CELL_SHOP)
mkdir -p $(CELL_SHOP)/build/dynamic
# Legacy meson target
meson:
meson setup build_dbg -Dbuildtype=debugoptimized
meson install -C build_dbg
.PHONY: cell static bootstrap clean meson install
.PHONY: all install clean

View File

@@ -1,13 +1,6 @@
[dependencies]
cell-steam = "/Users/johnalanbrook/work/cell-steam"
cell-sdl3 = "/Users/johnalanbrook/work/cell-sdl3"
[compilation]
CFLAGS = "-Isource -Wno-incompatible-pointer-types -Wno-missing-braces -Wno-strict-prototypes -Wno-unused-function -Wno-int-conversion"
LDFLAGS = "-lstdc++ -lm"
[compilation.macos_arm64]
CFLAGS = "-x objective-c"
LDFLAGS = "-framework CoreFoundation -framework CFNetwork"
[compilation.playdate]
CFLAGS = "-DMINIZ_NO_TIME -DTARGET_EXTENSION -DTARGET_PLAYDATE -I$LOCAL/PlaydateSDK/C_API"
[compilation.windows]
LDFLAGS = "-lws2_32 -lwinmm -liphlpapi -lbcrypt -lwinhttp -static-libgcc -static-libstdc++"
CFLAGS = "-DMINIZ_NO_TIME -DTARGET_EXTENSION -DTARGET_PLAYDATE -I$LOCAL/PlaydateSDK/C_API"

View File

@@ -56,6 +56,7 @@
"vscode-languageserver-protocol": "^3.17.0"
},
"devDependencies": {
"@types/node": "^20.19.33",
"@types/vscode": "^1.75.0",
"typescript": "^5.0.0"
}

View File

@@ -75,7 +75,7 @@ package.load_config = function(name)
package.save_config = function(name, config)
{
var config_path = get_path(name) + '/cell.toml'
fd.slurpwrite(config_path, utf8.encode(toml.encode(config)))
fd.slurpwrite(config_path, stone(blob(toml.encode(config))))
}
package.dependencies = function(name)

View File

@@ -2113,7 +2113,9 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
/* Search frame chain for a disruption handler.
Use frame_pc to track each frame's execution point:
- For the faulting frame, it's the current pc.
- For unwound caller frames, read from frame->address. */
- For unwound caller frames, read from frame->address.
Keep frame_ref.val at the faulting frame and preserve caller
links so the trace walk can show the full call chain. */
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); /* re-chase after GC */
{
uint32_t frame_pc = pc;
@@ -2125,28 +2127,34 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
env = fn->u.reg.env_record;
pc = code->disruption_pc;
ctx->disruption_reported = FALSE;
frame_ref.val = JS_MKPTR(frame); /* root handler frame for GC */
break;
}
if (JS_IsNull(frame->caller)) {
if (!ctx->disruption_reported) {
const char *fn_name = code->name_cstr ? code->name_cstr : "<anonymous>";
const char *file = code->filename_cstr ? code->filename_cstr : "<unknown>";
/* Use faulting frame (frame_ref.val) for the header */
JSFrameRegister *fault = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
JSFunction *fault_fn = JS_VALUE_GET_FUNCTION(fault->function);
JSCodeRegister *fault_code = fault_fn->u.reg.code;
const char *fn_name = fault_code->name_cstr ? fault_code->name_cstr : "<anonymous>";
const char *file = fault_code->filename_cstr ? fault_code->filename_cstr : "<unknown>";
uint16_t line = 0, col = 0;
if (code->line_table && frame_pc > 0 && frame_pc - 1 < code->instr_count) {
line = code->line_table[frame_pc - 1].line;
col = code->line_table[frame_pc - 1].col;
uint32_t fpc = pc > 0 ? pc - 1 : 0;
if (fault_code->line_table && fpc < fault_code->instr_count) {
line = fault_code->line_table[fpc].line;
col = fault_code->line_table[fpc].col;
}
fprintf(stderr, "unhandled disruption in %s (%s:%u:%u)\n", fn_name, file, line, col);
/* Walk and print the frame chain as a stack trace */
/* Walk intact caller chain for stack trace */
{
JSFrameRegister *trace_frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
JSFrameRegister *trace_frame = fault;
int first = 1;
while (trace_frame) {
if (!mist_is_function(trace_frame->function)) break;
JSFunction *trace_fn = JS_VALUE_GET_FUNCTION(trace_frame->function);
if (trace_fn->kind == JS_FUNC_KIND_REGISTER && trace_fn->u.reg.code) {
JSCodeRegister *tc = trace_fn->u.reg.code;
uint32_t tpc = first ? (frame_pc > 0 ? frame_pc - 1 : 0)
uint32_t tpc = first ? fpc
: (uint32_t)(JS_VALUE_GET_INT(trace_frame->address) >> 16);
uint16_t tl = 0, tcol = 0;
if (tc->line_table && tpc < tc->instr_count) {
@@ -2164,15 +2172,13 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
}
ctx->disruption_reported = TRUE;
}
frame_ref.val = JS_MKPTR(frame); /* update root for GC / done */
result = JS_Throw(ctx, JS_NULL);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
goto done;
}
/* Unwind one frame — read caller's saved pc from its address field */
JSFrameRegister *caller = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->caller);
frame->caller = JS_NULL;
frame = caller;
frame_ref.val = JS_MKPTR(frame);
/* Advance to caller — keep chain intact (no nulling caller links) */
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->caller);
frame_pc = (uint32_t)(JS_VALUE_GET_INT(frame->address) >> 16);
}
}