feat(code-runtime): own portable-identifier exclusions at the seam

Move the reserved-word, reserved-global, reserved-error-member, and
dunder exclusion sets from the worker backend up to the code-runtime
seam package, and narrow the portable identifier subset to drop the
JS-only `$`. Every backend now imports one contract so a binding
namespace list valid on one backend is valid on all.

Delivers only the seam extension and the worker's adoption; the Python
backend, py-types renderer, and Code Mode language dispatch are later
PRs in the stack that depend on these exports.
This commit is contained in:
Chinesezjc
2026-08-07 11:20:05 +08:00
parent 70937db8a0
commit 5d4cea9dc1
8 changed files with 256 additions and 19 deletions
@@ -787,6 +787,9 @@ describe('WorkerCodeRuntime — seam misuse and lifecycle', () => {
const cases: [string, RegExp][] = [
['not valid!', /not a usable identifier/],
['await', /not a usable identifier/],
// `$tools` is legal JS but outside the seam's language-portable subset:
// the same namespace list must work against every backend's language.
['$tools', /not a usable identifier/],
['console', /duplicate binding global/],
]
for (const [global, message] of cases) {
@@ -822,6 +825,14 @@ describe('WorkerCodeRuntime — seam misuse and lifecycle', () => {
])).rejects.toThrow(/duplicate injected global/)
await expect(run([namespace('tools', 'CallError', '')])).rejects.toThrow(/member property.*not usable/)
await expect(run([namespace('tools', 'CallError', 'message')])).rejects.toThrow(/member property.*not usable/)
// The shared exclusion set covers Python's exception-protocol members and
// dunders too, so the same errorClass is valid (or not) on every backend.
await expect(run([namespace('tools', 'CallError', 'args')])).rejects.toThrow(/member property.*not usable/)
await expect(run([namespace('tools', 'CallError', '__dict__')])).rejects.toThrow(/member property.*not usable/)
// The Python bootstrap's owned globals are refused here too (shared
// RESERVED_BINDING_GLOBALS), keeping namespace lists backend-portable.
await expect(runtime.run({ program: 'return 1', bindings: [{ global: '__dsh_main__', functions: {} }] }))
.rejects.toThrow(/duplicate binding global/)
})
it('rejects config values that are not positive numbers', async () => {