sercrod

Runtime specification

This page defines the browser runtime contract for Sercrod. It is intended to be used as a stable reference for implementation, documentation, and tests.

This specification reflects the public runtime and documentation published as Sercrod v0.1.12.

The words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY describe normative behavior.

1. Scope

This specification covers the runtime behavior of Sercrod hosts in a browser: host discovery, data initialization, template capture, rendering, expression scope, directive evaluation order, events, input timing, network execution, cleanup, and public integration hooks.

This specification does not define authoring style, product positioning, marketing text, or tutorial order.

2. Host model

A Sercrod host is a custom element named <serc-rod>.

3. Initialization order

For each host, runtime initialization MUST behave as if it follows this order:

  1. Determine the host instance and attach Sercrod runtime state.
  2. Initialize host data from the data attribute or assigned host data.
  3. Capture the initial host children as the host template.
  4. Perform the initial render from the captured template and current data.
  5. Mark the host's JavaScript-only ready property and dispatch sercrod-ready once after the first completed update() cycle.
  6. Register event listeners, network triggers, and cleanup hooks created during rendering.

An implementation MAY interleave internal setup steps, but the observable result MUST be equivalent to the order above.

The initial host HTML MUST be the source template for later updates. Updates MUST render from the stored template and current scope, not from the latest already-rendered DOM as if it were the canonical template.

4. Data model

Each host renders against a scope object. The host data object is the primary scope for expressions, and the runtime MUST make host data available through normal data names and through $data.

When a data attribute is present, the runtime MUST attempt to parse it as JSON first. If JSON parsing fails, the runtime MAY evaluate the attribute value as a JavaScript expression. Expression-based data values MUST be treated as trusted template code.

<serc-rod data='{"count":0}'>
	<button @click="count++">%count%</button>
</serc-rod>

The runtime MAY allow host data assignment from JavaScript:

host.data = { count: 0 };

5. Template and render model

Sercrod uses a regeneration render model. On update, the runtime MUST rebuild the host subtree from the stored host template, current host data, and current local scope.

The runtime does not specify a virtual DOM diff contract. Implementations MAY optimize internally, but public behavior MUST remain equivalent to regeneration from the stored template.

Text interpolation MUST evaluate expressions between the configured delimiters. The default delimiter pair is % and %, so %name% evaluates name.

6. Expression scope

Sercrod expressions MUST be evaluated in the current Sercrod scope. Expressions MAY access:

Template authors SHOULD keep expressions small. Reusable or complex behavior SHOULD be moved into methods.

The runtime MUST treat expression execution as trusted template execution. This specification does not define a sandbox boundary for arbitrary untrusted expressions.

7. Directive prefixes and bindings

The runtime MUST evaluate directive and binding expressions in the current Sercrod expression scope.

8. Directive evaluation order

For each rendered node, the runtime MUST behave as if directives are evaluated in this order:

  1. Plain output for text nodes and *literal.
  2. Scope pre-processing, including *let and *global.
  3. Structure directives: *if, *elseif, *else, *switch, *case, *default, *each, and *for.
  4. Child Sercrod host boundary handling.
  5. Non-structure side-effect and IO directives: *apply, *restore, save/load action forms, *post, *fetch, and *api.
  6. Fallback element rendering: attribute bindings, output directives, template include behavior, event binding, and recursive child rendering.

Some directives are early-exit directives. When an early-exit directive handles a node, later directive families on that same node MUST NOT be assumed to run.

Structure directives MUST decide DOM shape before side-effect and IO directives on the same node are evaluated.

9. Events and update timing

An event handler attribute has this form:

@event="expression"

When the DOM event fires, the runtime MUST evaluate the expression in the current Sercrod scope. The runtime MUST provide the native event as $event and $e, and the declaring element as el and $el.

Modifier Required behavior
.prevent / .preventDefault Call event.preventDefault().
.stop Call event.stopPropagation().
.once Register the listener with once behavior.
.capture Register the listener in capture phase.
.passive Register the listener as passive.
.update Force an update after the handler runs.
.noupdate Suppress the automatic update after the handler runs.

The runtime SHOULD avoid automatic updates for configured non-mutating events. The .update modifier MUST force an update, and .noupdate MUST suppress the automatic update for that handler.

10. Input timing

*lazy MUST NOT mean that the value is ignored. *lazy MUST NOT be documented as blur-only behavior unless tests establish that as a public contract.

When both *lazy and *eager are present on the same element, behavior is currently unspecified and SHOULD NOT be relied on.

11. Network execution model

Network directives define a frontend/server contract through template attributes.

The public *fetch form is:

url[:prop]

When :prop is present, the runtime MUST store the parsed response at that data property.

For HTTP responses, the runtime MUST parse JSON responses as JSON when the response Content-Type indicates JSON. Non-JSON responses MAY be kept as text or Blob-like values depending on the directive and operation.

11.1 Trigger timing

*fetch and GET-style *api MUST be treated as initial loading when attached to non-clickable elements.

*fetch and *api MUST be treated as user-triggered actions when attached to clickable elements.

Clickable triggers include button, a without download, input[type=button], input[type=submit], and input[type=reset]. For *fetch, input[type=image] MUST also be treated as clickable.

12. Runtime events

Network and file operations MUST expose observable CustomEvent hooks for integration.

The exact event detail payloads SHOULD be covered by directive-specific tests before being treated as stable public contract.

13. Cleanup and resource lifetime

14. Configuration contract

Runtime configuration MUST be read from window.__Sercrod.config when defined before sercrod.js is loaded. Unspecified configuration fields MUST keep their defaults.

The public configuration surface includes:

The runtime MAY also read ambient preload hooks before initialization:

These hooks MUST be defined before loading sercrod.js if they should affect runtime initialization.

15. Security boundaries

Sercrod templates are executable trusted code.

16. Public contract versus internal behavior

Public runtime contract

Internal behavior unless documented elsewhere

17. Open questions

The following behaviors need implementation tests or explicit design decisions before being elevated to stable contract:

18. Minimum test matrix

Each normative section SHOULD have at least one test before the behavior is treated as hard public contract.