Degrade gracefully when the JS AST source is unavailable #1

Merged
flufi merged 1 commit from Sophie/phosphorus.osl:fix/jsfunc-null-js-source into main 2026-07-09 09:27:14 +00:00
Contributor

jsFunc declared its parameter as string js, so it hard-failed the
moment import("./src/js/ast.js") returned anything else.

In a built bundle that is always. fpp only emits import switch cases
for .osl and .rwl files, so import("./src/js/ast.js") falls through
the switch and returns null. The typed parameter then rejects it and
Setup dies before the browser draws anything:

type: Initial value for "js" must be of type string
in: phosphorus.osl -> Setup -> jsFunc()

The JS AST generator is already optional -- jsVersion = canUseJs ? js.ast null
and every caller guards on rtr.ast.jsVersion == null before falling back
to the OSL tokeniser. jsFunc just wasn't allowed to report "unavailable".

Accept an untyped source, and return null when it is missing/empty or when
eval() yields nothing (e.g. the app has no javascript permission). js.ast
is then null, jsVersion is null, and the OSL AST generator takes over.

Verified in originOS: the committed build now boots to the chromeLike
layout with a working tab bar and url bar.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com


Two follow-ups this PR deliberately does not cover:

  1. fpp should inline non-.osl imports. The real reason import("./src/js/ast.js") returns null is that fpp only emits switch cases for .osl/.rwl. Until that is fixed the built bundles silently lose the JS AST fast path and fall back to the OSL tokeniser. This PR only makes that fallback survivable instead of fatal.

  2. A separate originOS/OSL runtime bug also crashed phosphorus, after this one. Promise.new(...) spawns a worker on its own Scratch target but hands it the same osl_clone[windowId] scope object as the main thread, and self (__self__) lives on that shared object. So the worker running shared.config.net.refresh() overwrote self while the RWL parser was mid-tokenise(), and self.tokens read back as null:

    Unknown: Method 'append()' is not available on the data type 'null'
          in: phosphorus.osl -> Setup -> init() -> init() -> anonymous() -> tokenise()
    

    That is fixed on the originOS side by giving each target its own self slot; no phosphorus change is needed for it.

`jsFunc` declared its parameter as `string js`, so it hard-failed the moment `import("./src/js/ast.js")` returned anything else. In a built bundle that is always. fpp only emits `import` switch cases for `.osl` and `.rwl` files, so `import("./src/js/ast.js")` falls through the switch and returns `null`. The typed parameter then rejects it and Setup dies before the browser draws anything: type: Initial value for "js" must be of type string in: phosphorus.osl -> Setup -> jsFunc() The JS AST generator is already optional -- `jsVersion = canUseJs ? js.ast null` and every caller guards on `rtr.ast.jsVersion == null` before falling back to the OSL tokeniser. jsFunc just wasn't allowed to report "unavailable". Accept an untyped source, and return null when it is missing/empty or when `eval()` yields nothing (e.g. the app has no javascript permission). `js.ast` is then null, `jsVersion` is null, and the OSL AST generator takes over. Verified in originOS: the committed build now boots to the chromeLike layout with a working tab bar and url bar. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --- Two follow-ups this PR deliberately does not cover: 1. **fpp should inline non-`.osl` imports.** The real reason `import("./src/js/ast.js")` returns null is that fpp only emits switch cases for `.osl`/`.rwl`. Until that is fixed the built bundles silently lose the JS AST fast path and fall back to the OSL tokeniser. This PR only makes that fallback survivable instead of fatal. 2. **A separate originOS/OSL runtime bug also crashed phosphorus**, after this one. `Promise.new(...)` spawns a worker on its own Scratch target but hands it the *same* `osl_clone[windowId]` scope object as the main thread, and `self` (`__self__`) lives on that shared object. So the worker running `shared.config.net.refresh()` overwrote `self` while the RWL parser was mid-`tokenise()`, and `self.tokens` read back as null: Unknown: Method 'append()' is not available on the data type 'null' in: phosphorus.osl -> Setup -> init() -> init() -> anonymous() -> tokenise() That is fixed on the originOS side by giving each target its own `self` slot; no phosphorus change is needed for it.
`jsFunc` declared its parameter as `string js`, so it hard-failed the
moment `import("./src/js/ast.js")` returned anything else.

In a built bundle that is always. fpp only emits `import` switch cases
for `.osl` and `.rwl` files, so `import("./src/js/ast.js")` falls through
the switch and returns `null`. The typed parameter then rejects it and
Setup dies before the browser draws anything:

    type: Initial value for "js" must be of type string
    in: phosphorus.osl -> Setup -> jsFunc()

The JS AST generator is already optional -- `jsVersion = canUseJs ? js.ast null`
and every caller guards on `rtr.ast.jsVersion == null` before falling back
to the OSL tokeniser. jsFunc just wasn't allowed to report "unavailable".

Accept an untyped source, and return null when it is missing/empty or when
`eval()` yields nothing (e.g. the app has no javascript permission). `js.ast`
is then null, `jsVersion` is null, and the OSL AST generator takes over.

Verified in originOS: the committed build now boots to the chromeLike
layout with a working tab bar and url bar.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
flufi approved these changes 2026-07-09 09:27:05 +00:00
flufi left a comment

seems fine, will have to check on 619 tho

seems fine, will have to check on 619 tho
flufi merged commit 70445cbdf0 into main 2026-07-09 09:27:14 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
flufi/phosphorus.osl!1
No description provided.