Skip to content

Startup probe for new Function() gives false positive on Cloudflare Workers #179

@IGassmann

Description

@IGassmann

The startup probe in unpack.js that detects whether new Function() is available can give a false positive on Cloudflare Workers, causing silent decode failures at runtime.

The probe

var inlineObjectReadThreshold = 2;

try { new Function('') } catch(error) { inlineObjectReadThreshold = Infinity }

This assumes that if new Function() works at module initialization time, it will continue to work at runtime. That assumption doesn't hold on Cloudflare Workers.

Why it fails on CF Workers

CF Workers has an allow_eval_during_startup compat flag (default since compatibility_date >= 2025-06-01) that permits new Function() during module initialization but blocks it at runtime. So:

  1. Module loads → startup probe succeeds → inlineObjectReadThreshold stays at 2
  2. At runtime, after 4+ same-structure objects are decoded → readObject.count++ > 2new Function() is called → throws

Workarounds

The msgpackr/index-no-eval entry point works, as does passing { useRecords: false }. But both require the consumer to know about this issue upfront. The probe is meant to handle this automatically and doesn't.

Suggestions

  1. Document the CF Workers footgun — at minimum, note in the README that msgpackr/index-no-eval is required on CF Workers even when allow_eval_during_startup is enabled, since the startup probe can give a false positive.

  2. Wrap the actual JIT attempt in a try/catch with a fallback to the slow path, so the probe is resilient to environments where new Function() availability changes between initialization and runtime:

if (readObject.count++ > inlineObjectReadThreshold) {
  try {
    structure.read = (new Function('r', 'return function(){return {' + ... + '}}'))(read)
  } catch(e) {
    inlineObjectReadThreshold = Infinity // disable JIT globally on first failure
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions