Skip to content

Viewer: Script Lab foundation (julc WebAssembly engine) - #206

Open
satran004 wants to merge 1 commit into
viewer/redesignfrom
viewer/julc-foundation
Open

satran004 wants to merge 1 commit into
viewer/redesignfrom
viewer/julc-foundation

Conversation

@satran004

@satran004 satran004 commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Stacked on #204 (Yaci Viewer redesign). Part of #207. This is PR 1 of the Script Lab series, which uses the julc WebAssembly engine to inspect, re-run and debug Plutus scripts in the browser.

What users get

A script page now has a Code panel with two tabs, UPLC and CBOR. "Decode script" runs julc in the browser and shows:

  • language, Plutus Core version, size, term count and parameters applied
  • hash verification: julc recomputes the hash from the code and compares it with the store's
  • the builtins used; clicking one finds it in the code
  • readable UPLC with syntax highlighting, search with next/previous match, line wrap, copy and download (.uplc)

Options:

  • "Always decode scripts automatically" is remembered per browser.
  • ?view=cbor links straight to the raw CBOR.

There is no decompiled-Java view on purpose: julc's decompiler output isn't idiomatic Java.

How julc is included (never built here)

  • julc.lock.json pins the release (v0.1.0-pre18, julc-wasm full engine) and its SHA-256.
  • scripts/fetch-julc.mjs runs before dev and build:
    • it downloads the release archive from GitHub and checks the SHA-256;
    • it unpacks only top-level plain files into static/julc/ (git-ignored), with no path traversal, links or .d.ts files.
  • Prod build: fails if the engine can't be installed. JULC_SKIP=1 builds without Script Lab (the panel says it isn't installed). JULC_ARCHIVE=<file> installs from a local copy, still checked.
  • Dev: carries on with a warning.
  • Coverage: Docker, Earthly and the npm release all go through npm run build. I checked the Docker build: it downloads the engine and serves it compressed with brotli.

Runtime

  • Loading: the browser downloads nothing until someone decodes. Then about 5.5 MB (brotli; 21.8 MB raw) loads once and is cached. A warm decode takes under 1 s.
  • Worker: one shared worker. If it times out or dies, it is restarted on the next use.
  • Browser support: julc is a GraalVM Web Image, so it needs WasmGC and exnref. Both are checked with tiny modules before any download, and unsupported browsers get a message. Chrome 128, which is Playwright 1.46's bundled Chromium, lacks exnref; current Chrome, Edge, Firefox and Safari work.
  • Remote hosting: PUBLIC_JULC_BASE_URL can point at an engine hosted elsewhere. A cross-origin worker is handled with a tiny shim.
  • Code view: virtualised, so only the lines on screen are rendered and highlighted. Scripts tens of thousands of UPLC lines long stay smooth.

Tests

  • npm run check: 0 errors, 0 warnings. vitest: 32 passing (new: tar safety, UPLC highlighting).
  • New tests/script-lab.spec.ts: decode, hash verified, builtins, search and next match, virtualisation, CBOR tab. Run with SCRIPT_LAB_HASH=<hash> PW_CHANNEL=chrome npx playwright test script-lab.
    • Passing against the Mainnet playground store.
    • It skips without SCRIPT_LAB_HASH, because devnets usually have no Plutus scripts.
  • Smoke tests: 19 passing on a local devnet.
  • Engine install: fresh install, cached rerun, JULC_SKIP, missing archive (--optional continues), and a wrong archive rejected on checksum.

Size note

build/ grows by about 36 MB, because adapter-node also writes .br and .gz copies of the engine, and the npm package includes it. The browser only downloads the brotli copy.

Next PRs in the series: re-running transaction scripts, the debugger, and fork-a-transaction. Upstream asks: bloxbean/julc#244.

🤖 Generated with Claude Code

Script pages can now decode Plutus scripts in the browser: searchable, highlighted UPLC, the builtins
used (click to find them), size, term count, parameters applied and a hash check.

- julc is not built here: scripts/fetch-julc.mjs downloads the release pinned in julc.lock.json,
  checks its SHA-256 and unpacks plain files into static/julc/ (git-ignored). It runs before dev
  (optional) and build (required unless JULC_SKIP=1; JULC_ARCHIVE installs from a local copy), so
  Docker, Earthly and npm builds all include it.
- $lib/julc/engine: lazy, shared worker client. Nothing loads until the user decodes (or opts in to
  always decoding); WasmGC and exnref are checked first, so older browsers get a message instead of
  a 5.5 MB download that can't run.
- CodeView: virtualised, so 20k-line scripts stay fast; search with match navigation, wrap, copy,
  download.
- Tests: untar safety and highlighting (vitest); tests/script-lab.spec.ts (needs SCRIPT_LAB_HASH and
  PW_CHANNEL=chrome, as Playwright's bundled Chromium lacks exnref).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copy link
Copy Markdown

Initial automated review · Aster

Hi @satran004, thanks for the PR! 🙏 This is an automatic first check by an AI reviewer. It does not replace maintainer review and may be wrong.

Reviewed commit: a89c5494dcdbb8bdd9769220e8581156084f8754

Issues found:

  • applications/viewer/src/routes/scripts/[hash]/+page.svelte:87 — Navigating from one Plutus script to another through search reuses ScriptCode, leaving the first script's decoded UPLC on the second page with a false hash mismatch and no Decode button. Please key the component by data.hash, or reset its state when the script changes.
  • applications/viewer/scripts/fetch-julc.mjs:71 — After an earlier dev/build run installs the engine, JULC_SKIP=1 npm run build leaves static/julc intact, so the build still bundles and enables Script Lab. Please remove or exclude previously installed assets when skipping.
  • applications/viewer/src/lib/julc/ScriptCode.svelte:97 — Enabling automatic decoding immediately hides its checkbox, and subsequent visits also hide it as decoding starts, leaving no usable control to turn the saved preference off. Please keep the toggle available after decoding.

Not tested: Build, unit tests and browser flows were not run; GitHub reported no CI checks or status results for this commit.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants