# How Hyperframes Detects Non‑Deterministic JavaScript Code: A Deep Dive into Static Analysis

> Hyperframes detects non-deterministic JavaScript by static lint-checking script blocks for patterns like Math.random and Date.now ensuring deterministic video generation.

- Repository: [HeyGen/hyperframes](https://github.com/heygen-com/hyperframes)
- Tags: deep-dive
- Published: 2026-05-17

---

**Hyperframes detects non‑deterministic JavaScript by statically lint‑checking every inline `<script>` block for prohibited patterns like `Math.random()` and `Date.now()` before rendering, ensuring deterministic video generation without executing the code.**

The heygen-com/hyperframes framework guarantees that video renders are pixel‑perfect and reproducible by eliminating sources of runtime variability at the source code level. Rather than executing user scripts to observe behavior, the framework employs a static analysis pipeline that scans inline JavaScript for time‑based and randomness APIs. This article explains how the `hyperframes lint` command implements this detection through the core rule set.

## The Linting Pipeline: From HTML to Findings

The detection process begins when the CLI parses an HTML composition and extracts all inline `<script>` blocks. External scripts with `src` attributes are intentionally ignored, as their content cannot be statically verified. Each script’s raw text is stored in the `scripts` array of the `LintContext`, defined in [`packages/core/src/context.ts`](https://github.com/heygen-com/hyperframes/blob/main/packages/core/src/context.ts) and accessed by the rule set in [`packages/core/src/lint/rules/core.ts`](https://github.com/heygen-com/hyperframes/blob/main/packages/core/src/lint/rules/core.ts) (lines 74‑80).

### Normalizing Code by Stripping Comments

Before pattern matching, the linter normalizes each script by removing single‑line and block comments. This prevents false positives where prohibited API names appear inside documentation rather than executable code. The implementation uses two regular expressions applied sequentially in [`core.ts`](https://github.com/heygen-com/hyperframes/blob/main/core.ts) lines 306‑308:

```ts
const stripped = script.content
    .replace(/\/\/.*$/gm, "")
    .replace(/\/\*[\s\S]*?\*\//g, "");

```

### Pattern Matching Against Non‑Deterministic APIs

With comments removed, the linter checks the stripped content against a hard‑coded array of regular expressions defined in [`core.ts`](https://github.com/heygen-com/hyperframes/blob/main/core.ts) lines 777‑803. The current prohibited patterns include:

- `/Math\.random\s*\(/` – Flags `Math.random()` calls
- `/Date\.now\s*\(/` – Flags `Date.now()` calls
- `/new\s+Date\s*\(/` – Flags `new Date()` constructor calls
- `/performance\.now\s*\(/` – Flags `performance.now()` calls
- `/crypto\.getRandomValues\s*\(/` – Flags `crypto.getRandomValues()` calls

Each pattern includes a descriptive label and a specific fix hint, such as recommending a seeded PRNG like mulberry32 to replace `Math.random()`.

## Core Implementation: The `non_deterministic_code` Rule

The actual detection logic resides in the `non_deterministic_code` rule within the exported `coreRules` array. For each script in the `LintContext`, the rule iterates over the pattern list and tests the stripped content (lines 311‑319). When a match is found, the rule generates a finding with:

- **Code**: `non_deterministic_code`
- **Severity**: `error`
- **Message**: Description of the prohibited API detected
- **Hint**: Actionable guidance (e.g., "Use a seeded PRNG")
- **Snippet**: Context from the offending script

This approach guarantees that non‑deterministic code is caught **without executing the user script**, eliminating the possibility of runtime side effects during analysis.

## Running the Linter in Practice

To verify a composition before rendering, run the CLI command:

```bash
npx hyperframes lint my-composition.html

```

Consider the following HTML that would trigger violations:

```html
<script>
  const seed = Math.random();   // ❌ non‑deterministic
  const now = Date.now();       // ❌ non‑deterministic
</script>

```

The linter produces output similar to:

```

✖ non_deterministic_code (error)
  Script contains `Math.random()` which produces non‑deterministic output.
  Hint: Use a seeded PRNG (e.g. a simple mulberry32) so renders are deterministic.

```

Developers must replace these APIs with deterministic alternatives—such as using GSAP timeline positions instead of `Date.now()`—before the composition can be safely rendered.

## Key Files and Architecture

The static analysis pipeline spans several packages:

- **[`packages/core/src/lint/rules/core.ts`](https://github.com/heygen-com/hyperframes/blob/main/packages/core/src/lint/rules/core.ts)**: Implements the `non_deterministic_code` rule, comment stripping (lines 306‑308), pattern definitions (lines 777‑803), and matching logic (lines 311‑319).
- **[`packages/core/src/context.ts`](https://github.com/heygen-com/hyperframes/blob/main/packages/core/src/context.ts)**: Defines `LintContext` and manages the `scripts` array populated from parsed HTML.
- **[`packages/cli/src/commands/lint.ts`](https://github.com/heygen-com/hyperframes/blob/main/packages/cli/src/commands/lint.ts)**: Invokes `coreRules` on the composition and formats findings for terminal or JSON output.
- **[`packages/producer/src/services/fileServer.ts`](https://github.com/heygen-com/hyperframes/blob/main/packages/producer/src/services/fileServer.ts)**: Contains optional runtime shims that replace `Math.random` with seeded PRNGs during actual rendering, providing a secondary defense layer.

## Summary

- Hyperframes uses **static analysis**, not execution, to detect non‑deterministic JavaScript.
- The linter extracts inline scripts, strips comments, and matches against regex patterns for APIs like `Math.random()` and `Date.now()`.
- Violations are reported with specific error codes, severity levels, and fix hints before rendering begins.
- The core logic lives in [`packages/core/src/lint/rules/core.ts`](https://github.com/heygen-com/hyperframes/blob/main/packages/core/src/lint/rules/core.ts) within the `coreRules` array.
- Developers must use deterministic alternatives such as seeded PRNGs or timeline‑based positioning to pass validation.

## Frequently Asked Questions

### Does Hyperframes execute my JavaScript to detect non‑deterministic code?

No. Hyperframes performs **static linting** only. The `hyperframes lint` command parses your HTML composition and scans the raw text of inline `<script>` blocks using regular expressions. It never evaluates or runs the JavaScript, ensuring no side effects occur during analysis.

### What specific JavaScript APIs does Hyperframes flag as non‑deterministic?

According to the source code in [`packages/core/src/lint/rules/core.ts`](https://github.com/heygen-com/hyperframes/blob/main/packages/core/src/lint/rules/core.ts) (lines 777‑803), the linter flags `Math.random()`, `Date.now()`, `new Date()`, `performance.now()`, and `crypto.getRandomValues()`. Each of these APIs introduces variability based on system time or hardware randomness, which breaks deterministic video rendering.

### How do I fix non‑deterministic code errors in Hyperframes?

Replace flagged APIs with deterministic alternatives. For `Math.random()`, implement a seeded PRNG such as mulberry32. For `Date.now()` or `new Date()`, use GSAP timeline positions or other frame‑based timing references. The linter provides specific hints for each violation type to guide the replacement.

### Does Hyperframes check external script files?

No. The linter specifically ignores external scripts referenced via `<script src="...">` attributes and only analyzes inline scripts within the HTML composition. This limitation is noted in the `LintContext` implementation where only inline script content is extracted into the `scripts` array.