Repository navigation
Description
Summary
After #680 (v0.5.807) fixed the type-only-cycle and namespace-collision blockers exposed by Effect's import {} from "effect", init advances from the 75th call (internal/tracer.ts__init) to the ~310th call (Schema.ts__init) where it throws:
TypeError: (number).slice is not a function
at <anonymous>
exit: 1
(number).slice means perry's call dispatch is invoking .slice(...) on a JSValue whose tag is INT32_TAG (or a f64 number). Schema.ts has no obvious .slice call at top level — this is likely a deeply-chained String.prototype.slice reaching a value perry tracked as a string but is actually a number.
Repro
mkdir effect-680-followup && cd effect-680-followup
cat > package.json <<JSON
{ "name": "effect-680-followup", "version": "0.0.0", "type": "module",
"perry": { "compilePackages": ["effect"] } }
JSON
bun add effect@3.21.2
cat > test_bare.ts <<TS
import {} from "effect";
console.log("ok");
TS
perry compile test_bare.ts -o /tmp/out
/tmp/out
# stderr: TypeError: (number).slice is not a function
# at <anonymous>Bisection
lldb on the stripped binary, frame mapping via --keep-intermediates-preserved entry .o:
* thread #1
frame #6: out`<unnamed Schema.ts__init+5024> <- bl deep inside Schema.ts__init
frame #7: out`<unnamed Schema.ts__init> <- Schema.ts__init at offset +5020
frame #8: out`__perry_user_main + 1252 <- bl in main returning to +1252 = +0x4e4
Mapping _main + 1252 -> bl @ _main + 1248 (offset 0x4e0) -> objdump -r test_bare_ts.o:
0x4e0 ARM64_RELOC_BRANCH26 _node_modules_effect_src_Schema_ts__init
Then within Schema.ts__init (function start 0x67e58 in its .o), the bl at frame 7's +5020 lands at .o offset 0x67e58 + 0x139c = 0x691f4:
0x691f4 ARM64_RELOC_BRANCH26 _js_native_call_method
So js_native_call_method(receiver, "slice", args) is being called with a non-string receiver. The receiver is what Schema.ts__init computed at that point — likely the result of a chained property access or method call.
Likely shape
Schema.ts has many chained imports and uses several namespace imports (array_, bigDecimal_, chunk_, etc.). The (number).slice likely happens inside a dual()-wrapped function or a top-level pipe() chain where the typing/dispatch lost track of the receiver's actual class. This may be another #680-class namespace collision that the per-namespace map didn't catch (e.g. for a property chain someNs.getter.slice(...) rather than a direct someNs.method(...)).
Status snapshot for #321
| Phase | Pre-#680 | Post-#680 (v0.5.807) |
|---|---|---|
| Init position reached | 75 (tracer.ts) | ~310 (Schema.ts) |
| Topology cycles | broken (tracer first) | sound (Context first) |
| Namespace member collisions | random.make -> tracer.make | resolved per-namespace |
| Throw class | value is not a function |
(number).slice is not a function |
Activity
fix(compile): #684 — type-only imports must not register exports into…
tests: #808 — ≥300-module init-scale harness (#823)
docs: #798 — refresh CLAUDE.md parity status section (#820)
fix(transform): anchor inliner and deforest max-LocalId scans on the …
fix(transform): anchor inliner + deforest max-LocalId scans on the ha…