Skip to content

feat(util): add createSeededRandom() - #3586

Merged
MartinKanera merged 3 commits into
clientIO:devfrom
kumilingus:feat/g-seeded-generator
Nov 3, 2026
Merged

MartinKanera merged 3 commits into
clientIO:devfrom
kumilingus:feat/g-seeded-generator

Conversation

@kumilingus

@kumilingus kumilingus commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Description

Adds util.createSeededRandom(seed). It returns a random function that gives the same sequence for the same seed:

const random = joint.util.createSeededRandom(42);
random();        // 0.6011037519201636 - a number from [0, 1), like Math.random()
random(10);      // an integer from [0, 10]
random(0, 100);  // an integer from [0, 100]; the bounds can be in either order
new g.Point(random(0, 100), random(0, 100));
  • random() is a drop-in for Math.random(), and random(max) / random(min, max) replace g.random(max) / g.random(min, max). Code that generates random data needs one random function, with nothing passed into other APIs.
  • The implementation is mulberry32.
    • The seed is converted to an unsigned 32-bit integer: 1.5 acts as 1, -1 as 4294967295, and NaN, Infinity or a non-numeric value as 0.
    • The sequence for a seed stays the same within a major version.
    • It is not cryptographically secure.
  • The geometry module (g.random(), g.Point.random()) is unchanged.
  • The mulberry32 copy in the alg.rightAnglePath tests is replaced by util.createSeededRandom(). It produces the same sequence, so the test cases are unchanged.

Refs #3558

Motivation and Context

Demos, examples and tests that generate random positions, sizes or graphs use Math.random() or g.random(), which can't be seeded. They look different on every run, so they can't be compared against reference screenshots, reproduced from a bug report, or tested deterministically.

Tests

  • test/jointjs/core/util.js (util.createSeededRandom()):
    • the pinned sequence for seed 42;
    • the same seed gives the same sequence across all three forms, and different seeds give different sequences;
    • random() stays within [0, 1);
    • random(max) and random(min, max) cover the whole integer range, including swapped bounds;
    • seed conversion, including NaN and Infinity.
  • Verified that the tests fail without the seed conversion, with a broken one-argument form, without swapping reversed bounds, and with an exclusive upper bound.
  • yarn dist builds.
  • karma geometry 359/359, vectorizer 462/462 and joint 2245/2245 pass.
  • yarn test-server, yarn lint, yarn test-ts and yarn test-coverage pass.

@kumilingus kumilingus self-assigned this Nov 2, 2026
@kumilingus kumilingus changed the title feat(g): add seededGenerator() and a generator argument to random() feat(util): add createSeededRandom() Nov 2, 2026
@MartinKanera
MartinKanera requested a lite review from Copilot November 3, 2026 11:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain, with the change accompanied by documented types and comprehensive coverage for determinism, ranges, swapped bounds, and seed conversion.

No open issues 🎉

What changed in this PR

Adds util.createSeededRandom(seed) to @joint/core, providing deterministic Mulberry32-based pseudo-random sequences with floating-point and inclusive integer-range forms.

Changes:

  • Added the seeded random utility with documented seed normalization and overloads.
  • Added comprehensive tests for determinism, ranges, swapped bounds, and seed conversion.
  • Replaced the duplicated generator in right-angle path tests.
  • Added the @joint/core minor-release changeset.
File Description
packages/​joint-core/​types/​util.d.ts Declares and documents the seeded random factory and callable overloads.
packages/​joint-core/​test/​jointjs/​core/​util.js Tests deterministic sequences, ranges, swapped bounds, and seed conversion.
packages/​joint-core/​test/​jointjs/​alg.rightAnglePath.js Reuses the shared seeded random utility in deterministic tests.
packages/​joint-core/​src/​util/​util.mjs Implements the Mulberry32-based seeded random generator.
.changeset/​util-create-seeded-random.md Records the minor @joint/core release change.

Review effort: Lite

@MartinKanera
MartinKanera merged commit 97595fa into clientIO:dev Nov 3, 2026
3 checks passed
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.

3 participants