Skip to content

Commit 4c40c09

Browse files
hyperpolymathclaude
andcommitted
fix(codegen/deno-esm): add endsWith / stripSuffix / numToFixed2 lowering (closes #470)
Three `pub extern fn` decls in stdlib/Deno.affine had no matching entry in codegen_deno.ml's `deno_builtins` table. The codegen emitted bare calls to undefined JS symbols at runtime (ReferenceError). Adds direct lowerings (per the option-1 path in the issue): endsWith(s, x) -> String(s).endsWith(x) stripSuffix(s, x) -> ((__s,__x) => __s.endsWith(__x) ? __s.slice(0,-__x.length) : __s)(s, x) numToFixed2(n) -> Number(n).toFixed(2) Adds `tests/codegen-deno/deno_string_fmt.{affine,harness.mjs}` covering the three names plus stripSuffix passthrough on suffix-miss. The general extern->stdlib-body linkage question (option-2 in #470) stays open as follow-up — option-1 is the small, ship-now fix. 374/374 dune tests + all codegen-deno harnesses green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com>
1 parent 3ee4a21 commit 4c40c09

3 files changed

Lines changed: 49 additions & 0 deletions

File tree

lib/codegen_deno.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,12 @@ let () =
648648
(* Kilobyte display string: `(n/1024).toFixed(2)` — runtime number
649649
formatting is an honest host primitive in every language. *)
650650
b "kbString" (fun a -> Printf.sprintf "(Number(%s) / 1024).toFixed(2)" (arg 0 a));
651+
(* String suffix predicates + numeric formatter (#470). Originally
652+
intended to ride on stdlib bodies; without extern->stdlib linkage
653+
they need explicit lowering entries. *)
654+
b "endsWith" (fun a -> Printf.sprintf "String(%s).endsWith(%s)" (arg 0 a) (arg 1 a));
655+
b "stripSuffix" (fun a -> Printf.sprintf "((__s, __x) => __s.endsWith(__x) ? __s.slice(0, -__x.length) : __s)(%s, %s)" (arg 0 a) (arg 1 a));
656+
b "numToFixed2" (fun a -> Printf.sprintf "Number(%s).toFixed(2)" (arg 0 a));
651657
(* ---- misc host ---- *)
652658
b "dateNow" (fun _ -> "Date.now()");
653659
(* `new Date().toISOString()` — UTC ISO-8601 timestamp string. Distinct
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// SPDX-License-Identifier: MPL-2.0
2+
// #470 — Deno externs `endsWith` / `stripSuffix` / `numToFixed2` needed
3+
// explicit lowering entries in codegen_deno.ml. Before the fix all three
4+
// emitted a bare call to an undefined symbol -> runtime ReferenceError.
5+
6+
use Deno::{ endsWith, stripSuffix, numToFixed2 };
7+
8+
pub fn is_ts(p: String) -> Bool = endsWith(p, ".ts");
9+
10+
pub fn drop_ts_suffix(p: String) -> String = stripSuffix(p, ".ts");
11+
12+
pub fn drop_missing_suffix(p: String) -> String = stripSuffix(p, ".rs");
13+
14+
pub fn fmt_pct(x: Int) -> String = numToFixed2(x);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// SPDX-License-Identifier: MPL-2.0
2+
// #470 — verify the three previously-missing Deno externs now resolve.
3+
4+
import assert from "node:assert/strict";
5+
6+
const {
7+
is_ts,
8+
drop_ts_suffix,
9+
drop_missing_suffix,
10+
fmt_pct,
11+
} = await import("./deno_string_fmt.deno.js");
12+
13+
// endsWith
14+
assert.equal(is_ts("foo.ts"), true, "endsWith hit");
15+
assert.equal(is_ts("foo.tsx"), false, "endsWith miss");
16+
assert.equal(is_ts(""), false, "endsWith empty");
17+
18+
// stripSuffix — present
19+
assert.equal(drop_ts_suffix("foo.ts"), "foo", "stripSuffix removes matching suffix");
20+
assert.equal(drop_ts_suffix(".ts"), "", "stripSuffix down to empty");
21+
22+
// stripSuffix — absent (must return input unchanged, not throw)
23+
assert.equal(drop_missing_suffix("foo.ts"), "foo.ts", "stripSuffix passthrough when suffix absent");
24+
25+
// numToFixed2
26+
assert.equal(fmt_pct(0), "0.00", "numToFixed2 of 0");
27+
assert.equal(fmt_pct(42), "42.00", "numToFixed2 of int");
28+
29+
console.log("deno_string_fmt.harness.mjs OK");

0 commit comments

Comments
 (0)