Design the browser playground behavior

Archived MVP specification. For ASPL 0.6.0, see the current reference and native HTTP guide.

Type: prototype Status: resolved Blocked by: 03, 06, 08, 11, 12, 13 Parent: Find the ASPL MVP specification

Question

How should the browser-local playground edit, compile, run, stop, and diagnose Arabic or English ASPL programs, including the required conversion of Arabic-Indic and Extended Arabic-Indic digit input to ASCII outside strings and comments, while making its lack of Linux shared-library calls and ELF execution obvious, and what resource limits keep the page responsive?

Comments

Answer

Use the outcome-led worker console shown as variant C in the browser playground behavior prototype. The playground owns one in-memory source buffer and one dedicated worker. It checks after a short editing pause, reruns the complete check before every execution, executes one immutable source snapshot, and replaces the worker whenever work must stop.

The playground is an evaluation environment. It has no account, saved project, browser persistence, file manager, package workflow, server execution, or multi-file editing.

Page structure

The Arabic interface is the default. An explicit English control changes interface copy and diagnostic rendering. Source vocabulary, identifier script, browser locale, and text direction never select the interface language.

On desktop, the chosen layout has:

  1. a top status and action band containing the current worker state, Run, Stop, and the browser capability notice;
  2. the source editor as the main area; and
  3. a narrow inline-end rail containing program output, the worker log, current diagnostics, the last run outcome, and measurements.

The rail therefore appears on the left in the Arabic interface and on the right in the English interface. On narrow screens, the status and actions remain above the editor and the rail moves below it. Run, Stop, example selection, language selection, direction selection, diagnostics, and overwrite confirmation must all work from the keyboard. Ctrl+Enter or Command+Enter invokes Run when an editor input method is not consuming that chord.

A permanent compact notice beside Run says the equivalent of Bytecode only · No Linux libraries · No ELF execution. The page header also states that source and execution stay in the browser. These notices remain visible for every example and outcome.

Source buffer and examples

A new session loads a runnable Arabic example and selects RTL atom order. The example menu contains at least one Arabic program, one equivalent English program, one deliberately mixed-vocabulary program, an infinite-loop limit case, a browser-rejected foreign-import case, and a file-like case containing unconverted Arabic-form digits. Reset restores the selected example. Reloading the page restores the Arabic default rather than previous edits.

Changing examples or resetting when the buffer differs from its loaded example requires an inline confirmation. The confirmation names that the only in-memory edits will be replaced and offers explicit replace and keep-editing actions. It is not a modal. An unchanged buffer is replaced immediately.

The implementation editor stores logical source text and meets the token-aware source display contract from Design the bilingual source notation. The raw textarea in the prototype is only an input driver. It is not a conforming editor implementation. Numeric atoms always display LTR, comments choose their content direction, and all other lexical atoms use the selected RTL or LTR atom order. Changing display direction never changes stored source bytes.

Digit input

Typing and pasting use one editor transaction. When the current lossless lexical classification proves an inserted Arabic-Indic or Extended Arabic-Indic digit is in executable source, the editor converts it to the corresponding ASCII digit before committing the transaction. A paste is scanned through strings and comments, so one paste may convert some digits and preserve others. The transaction remains undoable as one edit, and a short nonblocking message reports the number converted.

Digits inside strings and comments remain exact. If malformed surrounding text prevents reliable classification, the editor leaves the input unchanged. The next check then emits one non-ascii-digit diagnostic for each maximal convertible span with the complete ASCII replacement. Other Unicode decimal digits receive no guessed conversion.

Automatic checking

An edit marks the buffer dirty and schedules a check 350 milliseconds after the last edit. A check captures the current source revision and runs strict UTF-8 validation, lexing, parsing, checking, browser host-policy validation, lowering, canonical serialization, and canonical bytecode validation. Warnings do not block Run. Errors and browser policy rejection do.

Only one worker job exists at a time. Every request carries a monotonically increasing job identifier and source revision. If an edit makes an active check obsolete, the page terminates that worker, discards its partial result, creates a clean worker, and schedules the latest revision. Messages whose job identifier or source revision is no longer current are ignored. Superseded checks do not add a user-visible cancellation result.

The worker log records worker loading, check start, successful check, blocking check result, run start, explicit Stop, configured limit stop, and final run outcome. It shows the newest event first. It does not record keystrokes, every compiler stage, token counts, or program output.

Running and source revisions

Run is explicit. It captures the current buffer, performs the complete check again even when the same revision passed automatic checking, and begins execution only from the resulting validated VmProgram. Run clears the previous run result when this new attempt begins. A source error or policy rejection ends the attempt without entering main.

The source editor remains usable while a program runs. Execution continues against its immutable source snapshot. When the buffer changes, the status says that the active run uses an older snapshot and that the edits are not part of it. Automatic checking of the newer source waits until the run finishes or stops because the single worker is busy.

A completed outcome remains visible after later edits, marked Previous source snapshot. Diagnostics always identify the current checked source revision, so a stale run result cannot appear to describe current source. The next Run clears the stale outcome and uses the latest revision.

Normal completion shows the exact main status from 0 through 255. Traps, configured-limit stops, cancellation, policy rejection, load failure, host failure, and internal failure retain the classes and stable reasons from Define diagnostics and the safety boundary. The run outcome is separate from the worker log.

The اطبع or print builtin emits exact UTF-8 bytes into the bounded program-output region through the worker host callback fixed by Choose the MVP builtin environment. It creates no foreign import and adds no filesystem, network, or server bridge.

Accepted output appears as the running snapshot emits it. A new Run clears the previous output. Normal completion keeps it beside the exact main status. Stop, trap, limit stop, or host failure keeps accepted bytes and marks them partial. Later edits retain that output under the existing Previous source snapshot label until the next Run.

The region retains exact bytes for accounting but renders a safe view. Line feeds and tabs keep their layout. NUL, carriage return, bidi controls, and other non-printing controls appear as visible escapes with their Unicode code point and name. The region uses directional isolation so program text cannot reorder surrounding Arabic or English interface content.

Stop and worker failure

Stop is available during checking and execution. It calls Worker.terminate() immediately, invalidates the current job identifier, discards partial compiler or VM state, reports an explicit cancelled outcome for a user-requested stop, creates a clean worker, and automatically checks the latest buffer after the module reloads. It does not wait for cooperative cancellation because a synchronous WebAssembly call cannot process an ordinary worker message while it is stuck.

Initial WebAssembly loading does not count against a check or run clock. While loading, source editing remains available and Run remains disabled. Failure to start the worker or instantiate the module is host-failure with reason host-operation-failed and operation start-browser-worker. The UI offers Retry. An unexpected worker exit after loading uses the same class and reason with operation browser-worker. Explicit Stop, supersession, and a host-enforced deadline are not reported as unexpected worker exits.

Diagnostics and source mapping

The result rail renders the structured diagnostic records directly. Arabic is the default catalog and English is explicit. Reason keys, identifiers, source spellings, paths, library names, symbols, and numeric values remain exact and directionally isolated. The page does not infer language from Arabic or English source aliases.

Each diagnostic shows severity, stable reason, localized message, and exact line and scalar column. Selecting it focuses the editor and selects or highlights the mapped primary span through the token-aware source-to-display mapping. Secondary spans, machine-applicable edits, the independent 20-error and 20-warning caps, truncation notices, mapped traps, and bounded call traces follow the diagnostics decision. Raw directional controls and other unsafe characters are visible rather than emitted invisibly in diagnostic copy.

A foreign declaration completes host-neutral static checking and then produces policy-rejection/foreign-imports-not-supported at the first declaration with the total import count. Run never lowers or executes that source under browser policy. The diagnostic repeats that Linux shared libraries and ELF execution require the Linux tool. Externally supplied bytecode with any import fails loading under the same zero-import browser policy, although the MVP page does not expose a bytecode upload control.

Browser resource ceilings

One MiB is 1,048,576 bytes. These are fixed MVP browser ceilings, not WebAssembly platform maxima.

Resource Ceiling
Source bytes 1 MiB
Lexical items 131,072
Syntax nodes 131,072
Syntactic nesting 128
Compiler working memory 128 MiB
Check wall time after the loaded worker accepts the job 2 seconds
Bytecode bytes 8 MiB
Functions 4,096
Foreign imports 0
i64 constants 131,072
f64 constants 131,072
String references 131,072
String bytes 2 MiB
Bytecode instructions 524,288
Registers per function 8,192
Executed instructions 10,000,000
Runtime frames 512
Runtime value slots 131,072
VM-owned execution memory 64 MiB
Captured program output 256 KiB
Run wall time after execution begins 3 seconds
WebAssembly linear memory maximum 256 MiB
Concurrent worker jobs 1

The browser build may grow linear memory but must set its WebAssembly maximum to 256 MiB. Compiler and VM sublimits still apply inside that shared memory. A system allocation failure below a configured sublimit remains host-failure/allocation-failed.

The main thread measures wall time with a monotonic clock. The 2-second check clock starts when an already loaded worker accepts the compile job. The 3-second run clock starts when it accepts the execution job after successful checking. Initial module download, compilation, and instantiation belong to loading and count against neither clock. At a deadline, the page invalidates the job, terminates the worker, and reports limit-stop/time-limit with phase compile or execute. Instruction and wall clocks race; the first observed ceiling supplies the outcome.

The VM checks its instruction ceiling before dispatch as already specified. Output counts UTF-8 bytes accepted by the builtin callback. The callback refuses the complete write that would cross 256 KiB and returns limit-stop/output-limit; already accepted output remains visible and is marked partial.

Conformance evidence

Browser playground tests must cover: