Skip to content

perry-codegen: Effect — (number).slice is not a function during Schema.ts__init (#680 follow-up, ~310th init) #684

Description

@proggeramlug

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

Refs #321, #671, #680.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regression

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions