How do their APIs compare?
How do their APIs compare?
About diasurgical/devilutionx · 2 messages · last activity 2 Oct 2026
These two projects have fundamentally different notions of "API," and the search results confirm that difference rather than surfacing a shared comparison point, so let me lay it out clearly.
diasurgical/devilutionx — an internal game engine, not a library API
DevilutionX is a standalone game application, not something meant to be embedded by third parties. Its "API surface" is really a set of internal, loosely-coupled C++ modules communicating through plain headers and free functions in the devilution namespace:
- Error/fatal handling: a small, consistent interface of
[[noreturn]]functions likeErrDlg,InsertCDDlg, andDirErrorDlgin [Source/appfat.h:L36-L62], implemented in [Source/appfat.cpp:L71-L107]. These aren't designed for external consumers — they're the engine's internal way of aborting with a dialog. - UI subsystems expose narrow, single-purpose headers, e.g.
Source/DiabloUI/selok.h:L1-L11with free functions likeUiSelOkDialog,selok_Free,selok_Select,selok_Esc— essentially a C-style callback interface wrapped in a namespace, not an object-oriented API. - Device/controller abstractions like
GameController[Source/controls/devices/game_controller.h:L1-L40] andJoystick[Source/controls/devices/joystick.h:L1-L40] use static factory methods (Add,Remove,Get,All) — a small, consistent static-registry pattern repeated across similar classes, but still internal engine plumbing, not a published API. - UI widget classes (
UiEdit,UiText,UiListItemin [Source/DiabloUI/ui_item.h:L246-L355]) form a lightweight in-house UI toolkit — constructors take raw buffers/callbacks rather than following strict encapsulation. - There's no stable versioned public header, no ABI contract, and no documented "embedding" API — consistent with it being a self-contained game port rather than a library.
v8/v8 — a deliberately engineered, versioned embedder API
V8 is designed from the ground up to be embedded (by Chromium, Node.js, etc.), so its API in src/api/api.cc and src/api/api.h is a much more formal contract:
- Validation-first design: public entry points like
FunctionTemplate::NewandFunctionTemplate::NewWithCFunctionOverloadsrun explicit contract checks viaUtils::ApiCheckbefore doing any work — e.g. rejecting fast API calls combined withConstructorBehavior::kThrow[src/api/api.cc:L1226-L1233, L1256-L1263], and validating instance-type ranges againsti::Internals::kFirstEmbedderJSApiObjectType/kLastEmbedderJSApiObjectType[src/api/api.cc:L1240-L1250, L1282-L1292]. This is the kind of defensive boundary-checking you'd expect at a public library surface, which devilutionx's internal headers don't need. - Type-mapping macros:
src/api/api.h:L176-L215definesOPEN_HANDLE_LIST-style macros (V(Int32Array, JSTypedArray),V(Promise, JSPromise), etc.) that formally map every publicv8::*handle type to its internali::*representation — a deliberate, enumerated translation layer between public and internal representations. DevilutionX has no analogous public/internal split since everything is internal. - Scope/lifetime guard classes:
EnterV8Scope,EnterV8NoScriptNoExceptionScope,EnterV8InternalScope[src/api/api-inl.h:L246-L285] enforce invariants (no re-entrant script execution, no live exceptions) around every API call via RAII, with explicitDCHECKs. This is infrastructure purpose-built to protect a stable ABI from misuse by external embedders. - GC-aware argument marshaling:
FunctionCallbackArguments::IterateInstanceandPropertyCallbackArguments::IterateInstance[src/api/api-arguments.cc:L11-L33] expose callback argument slots to the garbage collector — a concern that only exists because V8's API must interoperate safely with a moving GC while embedder code holds references.
Did this answer what you came for?
Want to ask your own question?
Open chat for diasurgical/devilutionxPublic Q&A. Generated by RepoPilot from the actual source of diasurgical/devilutionx. AI answers can be incomplete or stale — verify before relying on them.