Skip to content

Oroya JS 1.2 β€” capability and acceptance matrix

The repository targets 1.2.0. Publication is a separate gate: a successful build does not mean that the npm release or physical device acceptance has occurred.

AreaSupported contractLimitsEvidence
CoreAcyclic graph, unique IDs, owned components, mandatory Transform, copying settersDirect public array/map mutation bypasses graph methods; direct transform writes require invalidationNode, Stability, RuntimeRegression tests
FramesDefault rendering advances the scene; advanceScene: false only synchronizes and drawsThe caller advances a shared scene once; rendering is not pure by defaultCanvas2D Parity, SVG AnimatorParity, Three Lifecycle
Three.js3D primitives, Buffer/CSG, PBR material data, cameras, lights, interaction, skinning, instancing, particles, audio and postprocessingNo Path2D/Text translator; browser audio rules apply; plugins own their resourcesLifecycle unit tests; runtime browser fixture
SVGVector primitives, Box/Sphere 2D representations, gradients, filters, text, paths, orthographic viewBox, DOM interaction and SVG animationNo 3D meshes, PBR, physics drawing, skins or GPU effects; string output has no live interactionrenderSVG, AnimatorParity, browser SVG interaction
Canvas2DBox/Plane rectangles, Sphere/Circle circles, paths, text, fill/stroke, gradients, opacity and transformsNo picking, SVG filters/masks, mesh buffers or PBRParity tests; real pixel browser assertion
PersistenceExisting JSON shape and legacy omitted Transform, typed buffers, declarative component data, validation before constructionScripts, InstancedMesh runtime state and unknown components require adapters; external assets, callbacks, live playback/physics state are not bundledSerializationRoundtrip, RuntimeRegression, Stability
glTF/GLBLocal/URL loading, hierarchy, mesh buffers, PBR scalar fields, transform clips and skin metadataTextures require an asset adapter; morph targets, multimaterial preservation and decoder extensions are not promisedLoading tests with self-contained glTF/GLB; real WebGL skin fixture
AssetsDeduplicated acquisitions, reference counts, cancellation, recovery after failureget() does not acquire a reference; callers pair load() with release()AssetManager, Recovery
InputKeyboard/mouse/gamepad actions and down/up transitions, blur/disconnect cleanupGamepad state requires update() polling; device mapping uses the standard layoutInputManager, Gamepad
PhysicsFixed timestep, root-child bodies, contacts, constraints, raycasts, retirement and disposeRoot translation/rotation work; scaled roots and nested bodies are diagnosed and excluded; collider dimensions are explicit physics unitsPhysicsSystem, Lifecycle, Vehicle
InspectorRepeated attach/detach, scene replacement, frame metrics and stale-selection cleanupHost calls update(); overlay is optionalFrameMetrics, Lifecycle
React/VuePublic 1.2 bindings, committed React props, callbacks, explicit cameras, resize and cleanupWebGL bindings; imperative core APIs cover components outside the provided wrappersReact 18/19 StrictMode, Vue Bindings; real browser mounts
PluginsPublic registry and Three.js lifecycle; latest handler wins; removal restores earlier handler; disposal is idempotentBackend objects/resources remain owned by the plugin; a registry key alone does not add a core ComponentTypePlugin and Three Lifecycle tests
EditorGroups/primitives, selection, names, hierarchy, numeric/Euler transforms, materials, W/E/R gizmos, viewport camera, duplicate/delete, undo/redo, Save/LoadBasic desktop authoring; no timeline, bundled project assets or automatic animation-reference remapping on duplicationEditorController tests; editor browser workflow

Frame ownership

Advance the shared scene with one renderer, then draw other views without advancing it again:

threeRenderer.render(dt);
renderToSVG(scene, { width: 800, height: 600, dt, advanceScene: false });
renderToCanvas(scene, canvas, { width: 800, height: 600, dt, advanceScene: false });

Transform.setPosition, setRotation and setScale copy values and invalidate local matrices. Direct writes remain supported, but must be followed by updateLocalMatrix() or isDirty = true.

Camera projection remains authored by default. Set CameraDef.autoAspect: true or renderer adjustCameraToViewport: true to opt into resize fitting. Automatic React/Vue cameras opt in; active: true gives explicit cameras priority. Application-owned viewport cameras and overlays do not change authored scene cameras.

Diagnostics and persistence

Use validateSceneJSON(json) for { valid, diagnostics }. deserialize() validates before creating objects and throws SceneValidationError on errors. Diagnostics contain code, severity, message, and, where applicable, nodeId and path. Incomplete triangles and unresolved bone references are warnings to preserve valid legacy data/fragments; out-of-range buffer indices, malformed definitions, duplicate IDs and nonfinite values are errors.

serialize(scene, { onDiagnostic }) reports omitted runtime data. deserialize(json, { onDiagnostic }) reports warnings and errors. Unknown components do not silently gain unsupported runtime behavior. Exported threeCapabilities, svgCapabilities, canvas2DCapabilities and core diagnoseScene() allow preflight checks; per-render callbacks report backend limitations.

Plugins run after the scene update and before world-matrix synchronization; handler updates see zero delta when advancement is disabled. Handlers returning null use the built-in translator. Registry conflict resolution is last-registration-wins, and unregister restores the previous registered handler. Object dispose runs before plugin unregister/dispose; neither operation transfers resource ownership to the renderer.

Reproducible acceptance

Use Node 24 and pnpm 9.1.0. Libraries retain Node 18/20 support. Run pnpm install --frozen-lockfile, pnpm build, pnpm lint, pnpm typecheck, pnpm test, pnpm architecture:check, pnpm api:check:strict, pnpm api:compat, pnpm docs:check, pnpm docs:validate, pnpm build:apps, pnpm test:browser and pnpm verify:packages.

Browser tests run Chromium, Firefox and WebKit, plus Chromium/WebKit mobile profiles. Emulation is separate from the pending physical iOS/Android checks in validation/physical-devices.json.

pnpm perf:record explicitly establishes the corrected reference on the measurement machine. pnpm perf:check compares the same CPU, browser, viewport, Node major and DPR, rejecting CPU/frame median regressions above 10%. Scenarios use 1,000 nodes, 10,000 instances, 100 physics bodies and a skinned scene. The transfer count belongs to the development acceptance harness and measures decompressed JavaScript; it is not production gzip size. Publishing consumes the matching measured artifact evidence rather than comparing unrelated hosted-runner hardware.

pnpm test:endurance runs 30 minutes after 100 real mount cycles, checks that frames progress and resource counts stay bounded, and verifies zero owned geometry/texture/node allocations after disposal. JSON reports contain the SHA-256 digest of the compiled library ESM artifacts; stale evidence blocks release. Re-record evidence whenever those artifacts change.

pnpm release:check --candidate validates package, performance and endurance evidence. Stable pnpm release:check additionally requires device/browser versions, tested package version and an evidence location for Safari/iOS and Chrome/Android, bound to the same artifact digest. CI runs Windows/Linux and libraries on Node 18/20/24; physical devices are a separate release requirement.