@thednp/dommatrix 3.1.0 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +10 -5
- package/CHANGELOG.md +19 -2
- package/README.md +15 -76
- package/dist/dommatrix.cjs +69 -33
- package/dist/dommatrix.cjs.map +1 -1
- package/dist/dommatrix.d.ts +10 -3
- package/dist/dommatrix.js +69 -33
- package/dist/dommatrix.js.map +1 -1
- package/dist/dommatrix.mjs +69 -33
- package/dist/dommatrix.mjs.map +1 -1
- package/package.json +2 -1
package/AGENTS.md
CHANGED
|
@@ -31,6 +31,7 @@ pnpm fix:ts # deno lint src --fix
|
|
|
31
31
|
pnpm format # deno fmt src
|
|
32
32
|
pnpm bench # vitest browser bench vs test/fixtures/index-3.0.x.ts (no coverage)
|
|
33
33
|
pnpm bench:native # vitest browser bench vs native DOMMatrix (no coverage)
|
|
34
|
+
pnpm bench:docs # run both bench suites (2x), write test/fixtures/bench-results.json, regenerate the BENCHMARK.md tables and the README ## Benchmarks summary
|
|
34
35
|
```
|
|
35
36
|
|
|
36
37
|
Always run `pnpm lint` and `pnpm test` after making changes.
|
|
@@ -44,8 +45,11 @@ Deno equivalents: `deno task test`, `deno task lint`, `deno task check`, `deno t
|
|
|
44
45
|
- `src/types.ts` — exported types (`JSONMatrix`, `Matrix`, `Matrix3d`, `PointTuple`)
|
|
45
46
|
- `test/dommatrix.test.ts` — the full test suite (Vitest, browser mode)
|
|
46
47
|
- `test/dommatrix.bench.test.ts` — benchmark vs the `test/fixtures/index-3.0.x.ts` snapshot: parity suite (every op must match the backup within `1e-9`, runs in `pnpm test` and gates CI) + interleaved perf suite (auto-skipped under coverage)
|
|
47
|
-
- `test/native.bench.test.ts` — benchmark vs native `DOMMatrix`: parity suite (
|
|
48
|
-
- `test/fixtures
|
|
48
|
+
- `test/native.bench.test.ts` — benchmark vs native `DOMMatrix`: parity suite (22 ops at `1e-9`, runs in `pnpm test`) + interleaved perf suite
|
|
49
|
+
- `test/fixtures/bench-results.json` — last measured results, written by `scripts/update-benchmark.js`; single source of truth for the `BENCHMARK.md` tables and the README `## Benchmarks` summary
|
|
50
|
+
- `scripts/update-benchmark.js` — runs both bench suites (2x, ~1 min), parses the `afterAll` tables from vitest stdout, writes the fixture, rewrites the two table blocks of `BENCHMARK.md` (between the `<!-- b1 -->`/`<!-- /b1 -->` and `<!-- b2 -->`/`<!-- /b2 -->` markers, plus the `<!-- b-updated -->` date stamp) and regenerates the README `## Benchmarks` summary
|
|
51
|
+
- `BENCHMARK.md` — the full benchmark report (static methodology intro, `<!-- b1 -->`/`<!-- b2 -->`-marked table blocks, static conclusion); only the marked blocks are regenerated by `pnpm bench:docs`
|
|
52
|
+
- `test/fixtures/` — test helpers, sample data, and the bench-results fixture
|
|
49
53
|
- `docs/` — GitHub Pages demo; `docs/dommatrix.js` is a build artifact copied from `dist/`
|
|
50
54
|
- `dist/` — build output, committed to the repo; regenerate with `pnpm build`, never edit by hand
|
|
51
55
|
- `experiments/` — archived Cypress experiments (not part of the build)
|
|
@@ -77,7 +81,7 @@ Deno equivalents: `deno task test`, `deno task lint`, `deno task check`, `deno t
|
|
|
77
81
|
1. Bump `version` in `package.json` **and** in `deno.json`
|
|
78
82
|
2. Add an entry to `CHANGELOG.md` (Keep a Changelog style, date-stamped)
|
|
79
83
|
3. Run `pnpm build && pnpm lint && pnpm test` and `deno publish --dry-run --allow-dirty`
|
|
80
|
-
4. Commit, then tag with the **bare version number** (no `v` prefix — existing tags are `1.0.0` ... `3.0
|
|
84
|
+
4. Commit, then tag with the **bare version number** (no `v` prefix — existing tags are `1.0.0` ... `3.1.0`)
|
|
81
85
|
|
|
82
86
|
The GitHub Actions `publish.yml` workflow publishes to both npm and JSR on GitHub Release (JSR via OIDC when enabled on the scope, otherwise the `JSR_TOKEN` secret).
|
|
83
87
|
|
|
@@ -88,9 +92,10 @@ Note: `prepublishOnly` runs `pnpm up --latest` (updates all deps), `pnpm format`
|
|
|
88
92
|
- The old `vite.config.ts` was replaced by `tsdown.config.mts` in 3.0.5 — `tsdown.config.mts` relies on: object-form `entry` for the chunk name (`dommatrix`), an `outputOptions` override for UMD (it must spread defaults, otherwise `sourcemap` is silently dropped), and `outExtensions` to keep the `.d.ts` filename. The `.mts` extension (not `.ts`) prevents Node's `MODULE_TYPELESS_PACKAGE_JSON` ESM-reparse warning — `package.json` deliberately has no `"type": "module"` because that would break Node `require()` of the UMD `dist/dommatrix.js`
|
|
89
93
|
- With `deno.json` present, `deno lint` enforces `verbatim-module-syntax` — type-only imports (like `import type CSSMatrix from "."` in `src/types.ts`) must use `import type`
|
|
90
94
|
- Vitest runs only in browser mode; any Node-only concern (globals, `require()`, `process`) needs the stubbed-global test pattern
|
|
91
|
-
- **Browser `console.table` is NOT forwarded to the terminal** — both bench suites accumulate rows on `globalThis` (`__CSSMATRIX_BENCH__`, `__CSSMATRIX_NATIVE_BENCH__`, inspectable in `pnpm test-ui` devtools) and print a pad-aligned `console.log` table in `afterAll`. `console.log` in `afterAll` does forward.
|
|
95
|
+
- **Browser `console.table` is NOT forwarded to the terminal** — both bench suites accumulate rows on `globalThis` (`__CSSMATRIX_BENCH__`, `__CSSMATRIX_NATIVE_BENCH__`, inspectable in `pnpm test-ui` devtools) and print a pad-aligned `console.log` table in `afterAll`. `console.log` in `afterAll` *does* forward (but only with the verbose reporter — see next bullet).
|
|
96
|
+
- **The `BENCHMARK.md` tables are generated** by `pnpm bench:docs` (`scripts/update-benchmark.js`) from `test/fixtures/bench-results.json` — do not hand-edit the blocks between the `<!-- b1 -->`/`<!-- /b1 -->` and `<!-- b2 -->`/`<!-- /b2 -->` markers (the tables and their interpretation only), nor the `<!-- b-updated -->`/`<!-- /b-updated -->` date stamp; the intro and the closing conclusion are otherwise static. The script also regenerates the short README `## Benchmarks` summary — a "X–Yx faster" report with a last-updated line, linking to `BENCHMARK.md` — by writing between the `<!-- b-summary -->`/`<!-- /b-summary -->` markers of the section bounded by the `## Benchmarks` and `## Demo` headings (the script fails if that boundary is not found). It spawns vitest with `--reporter=verbose` (the default reporter does not forward browser `console.log`), parses the two `afterAll` tables from stdout, runs each suite twice and reports medians. Grouping thresholds: vs-3.0.x buckets at 6x / 2x / 1.12x (ratio >= 6 “Large”, >= 2 “Moderate”, >= 1.12 “Mild”, else “At parity”); native is split three-way at ±5% (the measured noise floor).
|
|
92
97
|
- **Bench measurements must run without coverage**: istanbul instruments `src/index.ts` but not `test/fixtures/index-3.0.x.ts`, so under coverage the current file measures 30-60% slower than an identical backup. The suites skip timing at runtime when `typeof globalThis["__VITEST_COVERAGE__"] === "object"` (the key only appears after instrumented code executes) — parity assertions still run in `pnpm test`.
|
|
93
98
|
- **Interleaved sampling**: `bench(a, b, iterations)` warms up both implementations, then takes 2 alternating samples each and reports medians. Sequential per-implementation measurement biases toward the first implementation (~20-30%) because the second's allocations raise GC pressure. Identical files must measure ~0.92-1.09x.
|
|
94
|
-
- Native DOMMatrix quirks that shaped `test/native.bench.test.ts`: Chrome lacks `DOMMatrix.fromArray` (use `DOMMatrix.fromMatrix(values)`); native has no `skew()`/`skewSelf()` (only `skewX`/`skewY`); `rotateAxisAngle(x, y, z, angle)` takes the angle last; `DOMPoint` exposes `x/y/z/w` as prototype getters so `Object.keys()` is empty — extract values into a plain object before comparing; the bench test needs a long timeout (120s) because
|
|
99
|
+
- Native DOMMatrix quirks that shaped `test/native.bench.test.ts`: Chrome lacks `DOMMatrix.fromArray` (use `DOMMatrix.fromMatrix(values)`); native has no `skew()`/`skewSelf()` (only `skewX`/`skewY`); `rotateAxisAngle(x, y, z, angle)` takes the angle last; `DOMPoint` exposes `x/y/z/w` as prototype getters so `Object.keys()` is empty — extract values into a plain object before comparing; the bench test needs a long timeout (120s) because 23 interleaved cases take ~15s.
|
|
95
100
|
- `rotateAxisAngle`/`rotateAxisAngleSelf` throw only when any of the 4 values is non-finite; zero-length vector returns a copy (or `this` for the `Self` variant)
|
|
96
101
|
- `deno lint` runs on `src/` only — the `tsconfig.json` `include` is `["src/*"]`, `noEmit: true`
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.1.1] - 2026-08-05
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `pnpm bench:docs` (`scripts/update-benchmark.js`): runs both bench suites twice, parses the printed tables, writes `test/fixtures/bench-results.json`, and regenerates the `BENCHMARK.md` tables and the README `## Benchmarks` summary from it — no more hand-transcribing benchmark numbers.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- The full benchmark report moved out of the README into a dedicated `BENCHMARK.md` (static methodology intro and conclusion, with the two result tables wrapped in `<!-- b1 -->` / `<!-- /b1 -->` and `<!-- b2 -->` / `<!-- /b2 -->` markers). The README `## Benchmarks` section is now a short summary — a one-line "X–Yx faster than the previous release / than native" range plus a link to `BENCHMARK.md` — so it keeps the attention on the big picture instead of the per-operation numbers.
|
|
17
|
+
- `setMatrixValue()` now **mutates the matrix in place and returns `this`**, matching the native `DOMMatrix.setMatrixValue()` (previously it returned a new matrix and left the original untouched). The `fromArray()` / `fromMatrix()` value writers now accept an optional target instance, so the array / object paths of `setMatrixValue()` write straight into the existing instance instead of allocating a new one. Both benchmark suites gained `setMatrixValue()` operations to cover the new path: array and transform-list inputs against the 3.0.x snapshot, and a parity-checked transform-list case against native (the native parity suite now covers 22 operations).
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- The native benchmark's `transformPoint` case measured asymmetric work: the shim side constructed the matrix from a transform string on every iteration while the native side reused a pre-built `DOMMatrix`. Both sides now pre-build the matrix, and the corrected measurement is ~11x shim-faster on `transformPoint` (previously reported as ~0.36x native-faster, see the 3.1.0 entry above); `test/fixtures/bench-results.json`, the `BENCHMARK.md` tables and the README `## Benchmarks` summary were regenerated with `pnpm bench:docs`.
|
|
22
|
+
|
|
23
|
+
[3.1.1]: https://github.com/thednp/dommatrix/releases/tag/3.1.1
|
|
24
|
+
|
|
8
25
|
## [3.1.0] - 2026-08-04
|
|
9
26
|
|
|
10
27
|
### Added
|
|
@@ -22,8 +39,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
22
39
|
- `multiply()`/`multiplySelf()` share a new `multiplyInto()` kernel with a single 64-multiplication pass; `multiplySelf()` writes into `this` instead of allocating and spreading a result object.
|
|
23
40
|
- `translate()`, `translateSelf()`, `scale()`, `scaleSelf()`, `skew()`, `skewSelf()` (plus `skewX()`/`skewY()` delegating to `skew()`) use specialized pre-multiply math instead of general matrix multiplication.
|
|
24
41
|
- `toJSON()` builds the result object with explicit property writes instead of spreading `this`; `toFloat32Array()`/`toFloat64Array()` build typed arrays directly, skipping the intermediate `toArray()` allocation.
|
|
25
|
-
- Measured performance deltas (vs `3.0.
|
|
26
|
-
- vs native `DOMMatrix` (`pnpm bench:native`, Chromium): the shim is faster on construction and mutation-heavy operations (e.g. `multiplySelf` ~48x, `translateSelf` ~28x, `scaleSelf` ~36x, `multiply` ~4x — largely native's Web IDL per-property access and `toJSON()` overhead), while native wins the
|
|
42
|
+
- Measured performance deltas (vs the `3.0.x` snapshot, Chromium, `pnpm bench`; ops/s ratios are noise-floor-corrected via interleaved sampling): `multiplySelf` ~17–18x, `scale` ~13x, `skew` ~6–14x, `translate` ~6.5–13x, `multiply` ~7x, `fromMatrix` ~7–7.6x, `rotate` ~5–5.6x, `rotateAxisAngle` ~4.1–4.5x, `toJSON` ~9.7–10.1x, `new CSSMatrix(transform list)` ~1.9–2.4x; unchanged code paths (`new CSSMatrix()`, `fromArray`, `transformPoint`, `toString`, `is2D`/`isIdentity`) measure ~0.96–1.1x.
|
|
43
|
+
- vs native `DOMMatrix` (`pnpm bench:native`, Chromium): the shim is faster on construction and mutation-heavy operations (e.g. `multiplySelf` ~48x, `translateSelf` ~28x, `scaleSelf` ~36x, `multiply` ~4x — largely native's Web IDL per-property access and `toJSON()` overhead) and on point transforms (`transformPoint` ~11x), while native wins only the serialization case: `toString` ~0.84x (shim/native ratios); `toFloat32Array` is at parity.
|
|
27
44
|
|
|
28
45
|
### Fixed
|
|
29
46
|
|
package/README.md
CHANGED
|
@@ -12,12 +12,12 @@ A TypeScript sourced [DOMMatrix](https://developer.mozilla.org/en-US/docs/Web/AP
|
|
|
12
12
|
## Table of Contents
|
|
13
13
|
|
|
14
14
|
- [Features](#features)
|
|
15
|
+
- [Benchmarks](#benchmarks)
|
|
15
16
|
- [Demo](#demo)
|
|
16
17
|
- [Installation](#installation)
|
|
17
18
|
- [Quick Start](#quick-start)
|
|
18
19
|
- [API Reference](#api-reference)
|
|
19
20
|
- [CSSMatrix vs native DOMMatrix](#cssmatrix-vs-native-dommatrix)
|
|
20
|
-
- [Benchmarks](#benchmarks)
|
|
21
21
|
- [Alternatives](#alternatives)
|
|
22
22
|
- [History](#history)
|
|
23
23
|
- [Thanks](#thanks)
|
|
@@ -33,6 +33,18 @@ A TypeScript sourced [DOMMatrix](https://developer.mozilla.org/en-US/docs/Web/AP
|
|
|
33
33
|
- **TypeScript** — bundled type definitions, including the `Matrix`, `Matrix3d`, `JSONMatrix` and `PointTuple` types
|
|
34
34
|
- **Verified against native** — every method is tested side-by-side with the native `DOMMatrix` in real browsers, with **100% test coverage**
|
|
35
35
|
|
|
36
|
+
## Benchmarks
|
|
37
|
+
|
|
38
|
+
<!-- b-summary -->
|
|
39
|
+
|
|
40
|
+
`CSSMatrix` is **1.2x–91x faster** than the previous 3.0.x release series and **1.8x–162x faster** than the native `DOMMatrix` — except `toString()`, which native does ~1.2x faster.
|
|
41
|
+
|
|
42
|
+
Every operation's result matches the previous release series and the native `DOMMatrix` to within `1e-9` (output is indistinguishable at the 9th decimal place). Full methodology, per-operation results and interpretation: [BENCHMARK](BENCHMARK.md).
|
|
43
|
+
|
|
44
|
+
Last updated: **2026-08-05**.
|
|
45
|
+
|
|
46
|
+
<!-- /b-summary -->
|
|
47
|
+
|
|
36
48
|
## Demo
|
|
37
49
|
|
|
38
50
|
See DOMMatrix shim in action, [click me](https://thednp.github.io/dommatrix) and start transforming.
|
|
@@ -152,7 +164,7 @@ For the complete JavaScript API, check the [JavaScript API](https://github.com/t
|
|
|
152
164
|
|
|
153
165
|
| Method | Description |
|
|
154
166
|
| --- | --- |
|
|
155
|
-
| `setMatrixValue(init)` |
|
|
167
|
+
| `setMatrixValue(init)` | Replaces the matrix values from the given string / array / object, mutates in place and returns `this` |
|
|
156
168
|
| `translate(x, y?, z?)` / `translateSelf(x, y?, z?)` | Applies a translation (CSS `translate3d()`) |
|
|
157
169
|
| `rotate(rx?, ry?, rz?)` / `rotateSelf(rx?, ry?, rz?)` | Applies a rotation; a single value rotates about the z-axis (CSS `rotate()`) |
|
|
158
170
|
| `rotateAxisAngle(x, y, z, angle)` / `rotateAxisAngleSelf(...)` | Applies a rotation about a vector (CSS `rotate3d()`) |
|
|
@@ -188,86 +200,13 @@ The shim mirrors the native **DOMMatrix** API surface closely — the same `m11`
|
|
|
188
200
|
| `transformOrigin` argument | Not supported | Supported (`new DOMMatrix(init, transformOrigin)`) |
|
|
189
201
|
| `is2D` / `isIdentity` | Computed getters — always reflect the current values | `is2D` is a flag fixed at construction and can report stale results (e.g. after `rotateAxisAngle()`) |
|
|
190
202
|
| `transformPoint()` | Accepts a `DOMPoint` **or** a plain `{ x, y, z, w }` tuple; returns the same type it received | Accepts `DOMPointInit`, always returns a `DOMPoint` |
|
|
191
|
-
| `setMatrixValue()` |
|
|
203
|
+
| `setMatrixValue()` | Mutates in place and returns `this`; accepts any of the shim's input types (string, array / typed array, `DOMMatrix`, plain object) | Mutates in place and returns `this`; accepts `DOMMatrixInit` only |
|
|
192
204
|
| `toArray()` | Plain `Array` of 6/16 values, alongside `toFloat32Array()` / `toFloat64Array()` | `toFloat32Array()` / `toFloat64Array()` only |
|
|
193
205
|
| `toJSON()` | `{ a-f, m11-m44, is2D, isIdentity }` | Same shape |
|
|
194
206
|
| TypeScript | Ships bundled type definitions, zero runtime dependencies | WebIDL-generated typings |
|
|
195
207
|
|
|
196
208
|
Methods of the `DOMMatrixReadOnly` prototype that are not part of this shim: `flipX()`, `flipY()`, `inverse()` and `rotateFromVector()` (`transpose()` is not part of the native interface either). Everything else — `translate*`, `rotate*`, `rotateAxisAngle*`, `scale*`, `skew*`, `multiply*`, `toString()`, `toFloat(32/64)Array()`, `transformPoint()` — is implemented with behavior verified against the native interface by the test suite.
|
|
197
209
|
|
|
198
|
-
## Benchmarks
|
|
199
|
-
|
|
200
|
-
Two benchmark suites run headless Chromium via Vitest and gate CI with **parity assertions** (output must be identical within `1e-9`), while the timings are reported only:
|
|
201
|
-
|
|
202
|
-
- `pnpm bench` — `test/dommatrix.bench.test.ts`, current implementation vs a `test/fixtures/index-3.0.x.ts` snapshot of the previous release (22 operations)
|
|
203
|
-
- `pnpm bench:native` — `test/native.bench.test.ts`, current implementation vs the browser's native `DOMMatrix` (22 operations, 21 parity-checked)
|
|
204
|
-
|
|
205
|
-
Measurements are skipped under coverage (istanbul instrumentation distorts timings) and use interleaved sampling — both implementations are alternated per sample and medians are reported, so the ratios are noise-floor-corrected (identical files measure ~0.92–1.09x). Results are also stored on `globalThis.__CSSMATRIX_BENCH__` / `__CSSMATRIX_NATIVE_BENCH__` for inspection in `pnpm test-ui` devtools, since browser `console.table` output is not forwarded to the terminal.
|
|
206
|
-
|
|
207
|
-
The tables below report the median of two interleaved runs on headless Chromium (Playwright 1217), 2026-08-04. Ratios above 1 mean the shim is faster.
|
|
208
|
-
|
|
209
|
-
### vs 3.0.x (previous release)
|
|
210
|
-
|
|
211
|
-
Ratio = 3.1.x ops/s ÷ 3.0.x ops/s.
|
|
212
|
-
|
|
213
|
-
**Large wins (6.9–104x)** — the hot paths that were specialized:
|
|
214
|
-
|
|
215
|
-
| Operation | Ratio | Operation | Ratio |
|
|
216
|
-
| --- | --- | --- | --- |
|
|
217
|
-
| `skewSelf` | ~104x | `scaleSelf` | ~61x |
|
|
218
|
-
| `translateSelf` | ~49x | `multiplySelf` | ~18x |
|
|
219
|
-
| `scale` | ~14x | `skew` | ~13x |
|
|
220
|
-
| `translate` | ~13x | `toJSON` | ~9.7x |
|
|
221
|
-
| `fromMatrix` | ~7.3x | `multiply` | ~6.9x |
|
|
222
|
-
|
|
223
|
-
**Moderate wins (2.2–5.2x)**:
|
|
224
|
-
|
|
225
|
-
| Operation | Ratio | Operation | Ratio |
|
|
226
|
-
| --- | --- | --- | --- |
|
|
227
|
-
| `rotate` | ~5.2x | `rotateSelf` | ~4.7x |
|
|
228
|
-
| `rotateAxisAngle` | ~4.1x | `new CSSMatrix(transform list)` | ~2.2x |
|
|
229
|
-
|
|
230
|
-
**Mild wins (1.2–1.4x)**:
|
|
231
|
-
|
|
232
|
-
| Operation | Ratio |
|
|
233
|
-
| --- | --- |
|
|
234
|
-
| `new CSSMatrix(matrix 2D)` | ~1.3x |
|
|
235
|
-
| `new CSSMatrix(matrix3d)` | ~1.2x |
|
|
236
|
-
|
|
237
|
-
**At parity (~1.0x)** — unchanged code paths, no regression:
|
|
238
|
-
|
|
239
|
-
`new CSSMatrix()`, `fromArray`, `transformPoint`, `toString`, `toFloat32Array`, `is2D` + `isIdentity` (~1.0–1.1x).
|
|
240
|
-
|
|
241
|
-
### vs native `DOMMatrix`
|
|
242
|
-
|
|
243
|
-
Ratio = shim ops/s ÷ native ops/s.
|
|
244
|
-
|
|
245
|
-
**Shim faster** (1.8–150x):
|
|
246
|
-
|
|
247
|
-
| Operation | Ratio | Operation | Ratio |
|
|
248
|
-
| --- | --- | --- | --- |
|
|
249
|
-
| `new Matrix()` | ~150x¹ | `multiplySelf` | ~48x |
|
|
250
|
-
| `scaleSelf` | ~35x | `skewXSelf` | ~35x |
|
|
251
|
-
| `translateSelf` | ~31x | `rotateAxisAngle` | ~10x |
|
|
252
|
-
| `rotateSelf` | ~8.3x | static from values | ~7.0x |
|
|
253
|
-
| `multiply` | ~4.0x | `translate` | ~4.0x |
|
|
254
|
-
| `scale` | ~4.0x | `fromMatrix` | ~3.8x |
|
|
255
|
-
| `skewX` | ~3.7x | `rotate` | ~3.4x |
|
|
256
|
-
| `new Matrix(matrix 2D)` | ~2.7x | `toJSON` | ~2.0x |
|
|
257
|
-
| `new Matrix(matrix3d)` | ~1.95x | `new Matrix(transform list)` | ~1.9x |
|
|
258
|
-
| `is2D` + `isIdentity` | ~1.8x | `toFloat32Array` | ~1.0x |
|
|
259
|
-
|
|
260
|
-
¹ measured as construct + `toJSON()`; native's `toJSON()` is a slow JS↔C++ bridge that dominates this row.
|
|
261
|
-
|
|
262
|
-
**Native faster** (the pure-compute cases):
|
|
263
|
-
|
|
264
|
-
| Operation | Ratio |
|
|
265
|
-
| --- | --- |
|
|
266
|
-
| `transformPoint` | ~0.36x (native ~2.8x faster) |
|
|
267
|
-
| `toString` | ~0.82x (native ~1.2x faster) |
|
|
268
|
-
|
|
269
|
-
The shim wins construction and mutation-heavy operations because V8 fully optimizes the plain-JS hot paths, while native `DOMMatrix` pays a C++ call per property access. Native C++ wins where the operation itself is the whole cost: point transforms and serialization.
|
|
270
|
-
|
|
271
210
|
## Alternatives
|
|
272
211
|
|
|
273
212
|
DOMMatrix shim is meant to be a light pocket tool for many things like [svg-path-commander](http://thednp.github.io/svg-path-commander). For a complete polyfill that fills in the missing `DOMMatrixReadOnly` methods (`inverse()`, `flipX()`, `flipY()`, ...), you might want to also consider [geometry-interfaces](https://github.com/trusktr/geometry-interfaces) and [geometry-polyfill](https://github.com/jarek-foksa/geometry-polyfill).
|
package/dist/dommatrix.cjs
CHANGED
|
@@ -42,17 +42,68 @@ const isCompatibleObject = (object) => {
|
|
|
42
42
|
* the result is a 3D matrix. Otherwise, a TypeError exception is thrown.
|
|
43
43
|
*
|
|
44
44
|
* @param array an `Array` to feed values from.
|
|
45
|
+
* @param target an optional matrix instance to write the values into; when omitted
|
|
46
|
+
* a new matrix is returned. Used internally by `setMatrixValue` to mutate in place.
|
|
45
47
|
* @return the resulted matrix.
|
|
46
48
|
*/
|
|
47
|
-
const fromArray = (array) => {
|
|
49
|
+
const fromArray = (array, target) => {
|
|
48
50
|
if (!isCompatibleArray(array)) throw TypeError(`CSSMatrix: "${Array.from(array).join(",")}" must be an array with 6/16 numbers.`);
|
|
49
51
|
// istanbul ignore else @preserve
|
|
50
52
|
if (array.length === 16) {
|
|
51
53
|
const [m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44] = array;
|
|
52
|
-
return
|
|
54
|
+
return writeValues(target ?? new CSSMatrix(), m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
|
|
53
55
|
}
|
|
54
56
|
const [M11, M12, M21, M22, M41, M42] = array;
|
|
55
|
-
return
|
|
57
|
+
return writeValues(target ?? new CSSMatrix(), M11, M12, 0, 0, M21, M22, 0, 0, 0, 0, 1, 0, M41, M42, 0, 1);
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Internal helper that writes the 16 values of a matrix into a given `CSSMatrix`
|
|
61
|
+
* instance. This is the single place where all 22 aliases (`a`-`f` and `m11`-`m44`)
|
|
62
|
+
* are written, so every write path keeps the instance monomorphic.
|
|
63
|
+
*
|
|
64
|
+
* @param target the matrix instance to write the values into.
|
|
65
|
+
* @param m11 the `m11` value.
|
|
66
|
+
* @param m12 the `m12` value.
|
|
67
|
+
* @param m13 the `m13` value.
|
|
68
|
+
* @param m14 the `m14` value.
|
|
69
|
+
* @param m21 the `m21` value.
|
|
70
|
+
* @param m22 the `m22` value.
|
|
71
|
+
* @param m23 the `m23` value.
|
|
72
|
+
* @param m24 the `m24` value.
|
|
73
|
+
* @param m31 the `m31` value.
|
|
74
|
+
* @param m32 the `m32` value.
|
|
75
|
+
* @param m33 the `m33` value.
|
|
76
|
+
* @param m34 the `m34` value.
|
|
77
|
+
* @param m41 the `m41` value.
|
|
78
|
+
* @param m42 the `m42` value.
|
|
79
|
+
* @param m43 the `m43` value.
|
|
80
|
+
* @param m44 the `m44` value.
|
|
81
|
+
* @return the target matrix.
|
|
82
|
+
*/
|
|
83
|
+
const writeValues = (target, m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44) => {
|
|
84
|
+
target.m11 = m11;
|
|
85
|
+
target.a = m11;
|
|
86
|
+
target.m21 = m21;
|
|
87
|
+
target.c = m21;
|
|
88
|
+
target.m31 = m31;
|
|
89
|
+
target.m41 = m41;
|
|
90
|
+
target.e = m41;
|
|
91
|
+
target.m12 = m12;
|
|
92
|
+
target.b = m12;
|
|
93
|
+
target.m22 = m22;
|
|
94
|
+
target.d = m22;
|
|
95
|
+
target.m32 = m32;
|
|
96
|
+
target.m42 = m42;
|
|
97
|
+
target.f = m42;
|
|
98
|
+
target.m13 = m13;
|
|
99
|
+
target.m23 = m23;
|
|
100
|
+
target.m33 = m33;
|
|
101
|
+
target.m43 = m43;
|
|
102
|
+
target.m14 = m14;
|
|
103
|
+
target.m24 = m24;
|
|
104
|
+
target.m34 = m34;
|
|
105
|
+
target.m44 = m44;
|
|
106
|
+
return target;
|
|
56
107
|
};
|
|
57
108
|
/**
|
|
58
109
|
* Creates a new mutable `CSSMatrix` instance given the 16 values of the matrix.
|
|
@@ -78,40 +129,19 @@ const fromArray = (array) => {
|
|
|
78
129
|
* @return the resulted matrix.
|
|
79
130
|
*/
|
|
80
131
|
const fromValues = (m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44) => {
|
|
81
|
-
|
|
82
|
-
m.m11 = m11;
|
|
83
|
-
m.a = m11;
|
|
84
|
-
m.m21 = m21;
|
|
85
|
-
m.c = m21;
|
|
86
|
-
m.m31 = m31;
|
|
87
|
-
m.m41 = m41;
|
|
88
|
-
m.e = m41;
|
|
89
|
-
m.m12 = m12;
|
|
90
|
-
m.b = m12;
|
|
91
|
-
m.m22 = m22;
|
|
92
|
-
m.d = m22;
|
|
93
|
-
m.m32 = m32;
|
|
94
|
-
m.m42 = m42;
|
|
95
|
-
m.f = m42;
|
|
96
|
-
m.m13 = m13;
|
|
97
|
-
m.m23 = m23;
|
|
98
|
-
m.m33 = m33;
|
|
99
|
-
m.m43 = m43;
|
|
100
|
-
m.m14 = m14;
|
|
101
|
-
m.m24 = m24;
|
|
102
|
-
m.m34 = m34;
|
|
103
|
-
m.m44 = m44;
|
|
104
|
-
return m;
|
|
132
|
+
return writeValues(new CSSMatrix(), m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
|
|
105
133
|
};
|
|
106
134
|
/**
|
|
107
135
|
* Creates a new mutable `CSSMatrix` instance given an existing matrix or a
|
|
108
136
|
* `DOMMatrix` instance which provides the values for its properties.
|
|
109
137
|
*
|
|
110
138
|
* @param m the source matrix to feed values from.
|
|
139
|
+
* @param target an optional matrix instance to write the values into; when omitted
|
|
140
|
+
* a new matrix is returned. Used internally by `setMatrixValue` to mutate in place.
|
|
111
141
|
* @return the resulted matrix.
|
|
112
142
|
*/
|
|
113
|
-
const fromMatrix = (m) => {
|
|
114
|
-
if (isCompatibleObject(m)) return
|
|
143
|
+
const fromMatrix = (m, target) => {
|
|
144
|
+
if (isCompatibleObject(m)) return writeValues(target ?? new CSSMatrix(), m.m11, m.m12, m.m13, m.m14, m.m21, m.m22, m.m23, m.m24, m.m31, m.m32, m.m33, m.m34, m.m41, m.m42, m.m43, m.m44);
|
|
115
145
|
throw TypeError(`CSSMatrix: "${JSON.stringify(m)}" is not a DOMMatrix / CSSMatrix / JSON compatible object.`);
|
|
116
146
|
};
|
|
117
147
|
/**
|
|
@@ -576,13 +606,19 @@ var CSSMatrix = class {
|
|
|
576
606
|
* This method expects valid *matrix()* / *matrix3d()* string values, as well
|
|
577
607
|
* as other transform functions like *translateX(10px)*.
|
|
578
608
|
*
|
|
609
|
+
* The matrix is mutated in place (the same instance is returned), matching
|
|
610
|
+
* the behavior of the native `DOMMatrix.setMatrixValue()`.
|
|
611
|
+
*
|
|
579
612
|
* @param source
|
|
580
|
-
* @return the matrix instance
|
|
613
|
+
* @return the current matrix instance
|
|
581
614
|
*/
|
|
582
615
|
setMatrixValue(source) {
|
|
583
|
-
if (typeof source === "string" && source.length && source !== "none")
|
|
584
|
-
|
|
585
|
-
|
|
616
|
+
if (typeof source === "string" && source.length && source !== "none") {
|
|
617
|
+
const m = fromString(source);
|
|
618
|
+
return writeValues(this, m.m11, m.m12, m.m13, m.m14, m.m21, m.m22, m.m23, m.m24, m.m31, m.m32, m.m33, m.m34, m.m41, m.m42, m.m43, m.m44);
|
|
619
|
+
}
|
|
620
|
+
if (Array.isArray(source) || source instanceof Float64Array || source instanceof Float32Array) return fromArray(source, this);
|
|
621
|
+
if (typeof source === "object") return fromMatrix(source, this);
|
|
586
622
|
return this;
|
|
587
623
|
}
|
|
588
624
|
/**
|