Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions bend2/comp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2862,7 +2862,7 @@ function c_ids(src: string, m = ""): string {
|| q in FL.book.tlds || FL.ids.has(p + "_" + q))
?? die(`${p}(${k}) names no constructor or def`);
return FL.js ? JSON.stringify(p === "CID" && q in FL.book.ctrs
? js_tag(q) : Bend.name_key(q)) : name_id(p + "_", q);
? js_tag(q) : q) : name_id(p + "_", q);
});
}

Expand Down Expand Up @@ -3085,7 +3085,8 @@ function js_tag(k: Name): string {
}

function js_key(n: Name): string {
return (n === "__proto__" ? `["${n}"]` : `"${n}"`) + ": ";
const key = JSON.stringify(n);
return (n === "__proto__" ? `[${key}]` : key) + ": ";
}

function js_expr(sc: Scope, tm: HTerm, ty0: HTerm | null = null): string {
Expand Down Expand Up @@ -3250,7 +3251,7 @@ function js_def(sc: Scope, k: Name, def: Bend.Def): void {
block(sc, `function ${name_id("$", k)}(${params.join(", ")}) {`, () => {
if (def_foreign(def)) {
const K = ty_wnf(tele_unbind(def.T).doms.at(-1)![2]);
return file_push(sc, `return { $: ${JSON.stringify(Bend.name_key(k))
return file_push(sc, `return { $: ${JSON.stringify(k)
}, args: [${live.map(([, , A], i) => host(A, params[i], 1))
}], kont: (x) => ${params.at(-1)}(${host(K?.$ === "All" ? K.A : null,
"x")}) };`);
Expand Down Expand Up @@ -3287,7 +3288,7 @@ function host(A: HTerm | null, x: string, out = 0): string {
}

// A module (for the .bend loader and -o <out>.mjs) roots and exports each
// def a host can call.
// callable def by its book name: "lib:value" differs from a root "lib.value".
export function js_lib(book: Bend.Book, mod = false): string {
FL = file_new(book, true);
const outs = !mod ? null : [...new Set(FL.book.order)].filter((k) => {
Expand All @@ -3307,7 +3308,7 @@ export function js_lib(book: Bend.Book, mod = false): string {
const { live, lays } = fun_of(k);
const ps = live.map((_, i) => "a" + i);
const xs = live.map(([, , A], i) => host(A, ps[i]));
return ` ${js_key(Bend.name_key(k))}run_lib((${ps}) => ${host(tele_unbind(
return ` ${js_key(k)}run_lib((${ps}) => ${host(tele_unbind(
FL.book.tlds[k].T).ret, `run_loop(${name_id("$", k)}(${xs}))`, 1)
}, ${lays.length}),`;
}).join("\n")}\n};\n`;
Expand Down
16 changes: 16 additions & 0 deletions tests/io/effect_namespace_collision.bend
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# An imported effect and a dotted root effect must register independently.
import Base
import ./effect_namespace_lib.bend as L

def effect_namespace_lib.value() -> IO(U32):
import "./effect_namespace_collision.js"

def main() -> IO(Unit):
do IO<Unit>:
imported : U32 <- L.value()
root : U32 <- effect_namespace_lib.value()
Unit <- IO.print(U32.show(imported))
IO.print(U32.show(root))

#|1
#|2
1 change: 1 addition & 0 deletions tests/io/effect_namespace_collision.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io_eff(CID(effect_namespace_lib.value), () => 2);
9 changes: 9 additions & 0 deletions tests/io/effect_namespace_lib.bend
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Base

def value() -> IO(U32):
import "./effect_namespace_lib.js"

#|SOME PROOFS FAIL
#|Error: 1 def relies on unsafe or foreign code:
#|defs that depend on foreign effects: value
#|exit 1
1 change: 1 addition & 0 deletions tests/io/effect_namespace_lib.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io_eff(CID(value), () => 1);
4 changes: 2 additions & 2 deletions tests/io/module_export_keys.bend
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# A pure __proto__ def is an own, enumerable JS module export, without
# changing the export object's prototype.
# JS exports keep own __proto__ keys and distinguish imported dep:value
# from a root dep.value, including when the export object is spread.
import Base

def Module.export_keys() -> IO(U32):
Expand Down
16 changes: 13 additions & 3 deletions tests/io/module_export_keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ function module_export_keys() {
try {
const input = path.join(dir, "lib.bend");
const output = path.join(dir, "lib.mjs");
fs.writeFileSync(path.join(dir, "dep.bend"), `import Base
def value(x: U32) -> U32:
U32.add(x, 10)
`);
fs.writeFileSync(input, `import Base
import ./dep.bend as D

def __proto__(x: U32) -> U32:
U32.add(x, 1)
Expand All @@ -19,6 +24,9 @@ def toString(x: U32) -> U32:

def ordinary(x: U32) -> U32:
U32.add(x, 4)

def dep.value(x: U32) -> U32:
U32.add(x, 20)
`);
const built = child.spawnSync(process.execPath,
[path.resolve("bend2/main.ts"), input, "-o", output], {
Expand All @@ -29,7 +37,9 @@ def ordinary(x: U32) -> U32:
return 1;
}
const lib = require(output).default;
const keys = ["__proto__", "constructor", "toString", "ordinary"];
const values = { "dep:value": 15, ["__proto__"]: 6, constructor: 7,
toString: 8, ordinary: 9, "dep.value": 25 };
const keys = Object.keys(values);
if (keys.some((k) => !Object.hasOwn(lib, k))) {
return 2;
}
Expand All @@ -40,8 +50,8 @@ def ordinary(x: U32) -> U32:
return 4;
}
const copy = { ...lib };
return keys.every((k, i) => Object.hasOwn(copy, k)
&& lib[k](5) === i + 6 && copy[k](5) === i + 6) ? 0 : 5;
return keys.every((k) => Object.hasOwn(copy, k)
&& lib[k](5) === values[k] && copy[k](5) === values[k]) ? 0 : 5;
} finally {
fs.rmSync(dir, { recursive: true, force: true });
}
Expand Down