Skip to content

Add C-API helpers for embedders: property accessors, exception, promise#1475

Open
andreasrosdal wants to merge 1 commit into
quickjs-ng:masterfrom
nordstjernen-web:claude/improve-javascript-support-xlOCa
Open

Add C-API helpers for embedders: property accessors, exception, promise#1475
andreasrosdal wants to merge 1 commit into
quickjs-ng:masterfrom
nordstjernen-web:claude/improve-javascript-support-xlOCa

Conversation

@andreasrosdal
Copy link
Copy Markdown
Contributor

Summary

Adds eight header-only inline helpers to quickjs.h that collapse
patterns repeated dozens of times in real embedders. Motivated by an
audit of the Nordstjernen browser's QuickJS binding (src/js.c,
~10k lines), where the same five-to-twelve-line dances appear at
hundreds of call sites.

I am making a web browser here:
https://github.com/nordstjernen-web/nordstjernen

This PR was created using Claude.

New helpers:

Helper Replaces
JS_FreeCStringSafe if (s) JS_FreeCString(ctx, s);
JS_GetPropertyStrInt32 get + null/undef check + JS_ToInt32 + free
JS_GetPropertyStrInt64 "
JS_GetPropertyStrFloat64 "
JS_GetPropertyStrBool get + null/undef check + JS_ToBool + free
JS_GetExceptionAsString JS_GetException + JS_ToCString + "stack" fetch + format
JS_ResolvePromise call resolvers[0] + free value + free both resolvers
JS_RejectPromise call resolvers[1] + free reason + free both resolvers

Each helper:

  • Takes ownership uniformly so callers can't leak a JSValue.
  • Silently clears any pending exception raised by an internal
    conversion (so embedders don't accidentally propagate a coercion
    error from a getter).
  • Returns a sensible fallback for missing / null / undefined
    properties.

Why

JS_GetException + JS_ToCString + JS_GetPropertyStr("stack") is
the single most-repeated pattern in the Nordstjernen binding —
appearing in every timer, every microtask drain, every event
dispatch, every fetch callback. It's also where refcount bugs hurt
most, because it runs on the error path. Folding it into one call
makes that path both shorter and safer.

The typed property accessors target options-bag reads (timer
options, fetch() init, event init, IntersectionObserver options,
etc.), which embedders implement by hand today.

Compatibility

  • All additions are static inline in quickjs.h.
  • No new exported symbols.
  • No changes to quickjs.c.
  • ABI unchanged; existing builds keep working without recompile.

Out of scope (follow-ups identified in the audit)

  • Per-call interrupt-deadline scoping (JS_SetContextDeadline).
  • Atom interning for hot DOM property names.
  • A callback-style JS_ObjectForEach for own-property iteration.
  • Moving polyfill text-encoding helpers (TextEncoder/Decoder)
    into C.

Each touches more of the engine and warrants a separate PR.

…e convenience)

Adds header-only inline helpers to quickjs.h, motivated by patterns
repeated throughout the Nordstjernen browser's QuickJS binding:

  JS_FreeCStringSafe         no-op on a NULL pointer
  JS_GetPropertyStrInt32     fetch+convert+free in one call
  JS_GetPropertyStrInt64     "
  JS_GetPropertyStrFloat64   "
  JS_GetPropertyStrBool      "
  JS_GetExceptionAsString    consume pending exception, format as
                             "<msg>" or "<msg>\n<stack>"
  JS_ResolvePromise          settle a JS_NewPromiseCapability pair
  JS_RejectPromise           "

Each helper consolidates a multi-line dance (get + null/undefined
check + convert + handle conversion error + free intermediate) into
one expression, and silently clears any pending exception raised by
the conversion so callers don't accidentally propagate it.

All additions are static inline; no ABI change, no quickjs.c changes.
api-test.c gains coverage for the new helpers.
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