miaoda-game-devkit 0.10.0 → 0.10.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/dist/lint/setup.mjs
CHANGED
|
@@ -1,8 +1,92 @@
|
|
|
1
1
|
// src/lint/setup.ts
|
|
2
2
|
import { afterEach } from "vitest";
|
|
3
3
|
|
|
4
|
-
// src/testing/jsdom-
|
|
4
|
+
// src/testing/jsdom-webgl.ts
|
|
5
|
+
var CONSTANT_NAME = /^[A-Z][A-Z0-9_]*$/;
|
|
6
|
+
var TEXTURE_UNIT_LIMIT = 32;
|
|
7
|
+
var TEXTURE_SIZE_LIMIT = 4096;
|
|
8
|
+
var VIEWPORT_LIMIT = 4096;
|
|
9
|
+
function parameterValue(name) {
|
|
10
|
+
if (name === "VERSION") return "WebGL 2.0 (miaoda-game-devkit stub)";
|
|
11
|
+
if (name === "SHADING_LANGUAGE_VERSION") return "WebGL GLSL ES 3.00 (stub)";
|
|
12
|
+
if (name === "VENDOR" || name === "RENDERER") return "miaoda-game-devkit";
|
|
13
|
+
if (name === "MAX_VIEWPORT_DIMS") {
|
|
14
|
+
return new Int32Array([VIEWPORT_LIMIT, VIEWPORT_LIMIT]);
|
|
15
|
+
}
|
|
16
|
+
if (name === "VIEWPORT" || name === "SCISSOR_BOX") {
|
|
17
|
+
return new Int32Array([0, 0, VIEWPORT_LIMIT, VIEWPORT_LIMIT]);
|
|
18
|
+
}
|
|
19
|
+
if (name.includes("MAX_") && name.includes("SIZE")) return TEXTURE_SIZE_LIMIT;
|
|
20
|
+
if (name.startsWith("MAX_")) return TEXTURE_UNIT_LIMIT;
|
|
21
|
+
if (name.endsWith("_BITS")) return 8;
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
function createWebGLContext(canvas, attributes) {
|
|
25
|
+
const constants = /* @__PURE__ */ new Map();
|
|
26
|
+
const constantNames = /* @__PURE__ */ new Map();
|
|
27
|
+
const state = {
|
|
28
|
+
canvas,
|
|
29
|
+
drawingBufferWidth: canvas.width,
|
|
30
|
+
drawingBufferHeight: canvas.height
|
|
31
|
+
};
|
|
32
|
+
const method = (name) => {
|
|
33
|
+
if (name === "getContextAttributes") return () => attributes;
|
|
34
|
+
if (name === "getExtension") return () => null;
|
|
35
|
+
if (name === "getSupportedExtensions") return () => [];
|
|
36
|
+
if (name === "getParameter") {
|
|
37
|
+
return (pname) => parameterValue(constantNames.get(pname) ?? "UNKNOWN");
|
|
38
|
+
}
|
|
39
|
+
if (name === "getShaderPrecisionFormat") {
|
|
40
|
+
return () => ({ rangeMin: 127, rangeMax: 127, precision: 23 });
|
|
41
|
+
}
|
|
42
|
+
if (name === "getShaderInfoLog" || name === "getProgramInfoLog") return () => "";
|
|
43
|
+
if (name === "getError") return () => 0;
|
|
44
|
+
if (name === "isContextLost") return () => false;
|
|
45
|
+
if (name.startsWith("get") && name.endsWith("Parameter")) return () => true;
|
|
46
|
+
if (name.startsWith("get")) return () => null;
|
|
47
|
+
if (name.startsWith("create") || name.startsWith("getUniformLocation")) {
|
|
48
|
+
return () => ({});
|
|
49
|
+
}
|
|
50
|
+
return () => void 0;
|
|
51
|
+
};
|
|
52
|
+
return new Proxy(state, {
|
|
53
|
+
get(target, property) {
|
|
54
|
+
if (property in target) return target[property];
|
|
55
|
+
if (typeof property !== "string") return void 0;
|
|
56
|
+
if (CONSTANT_NAME.test(property)) {
|
|
57
|
+
const existing = constants.get(property);
|
|
58
|
+
if (existing !== void 0) return existing;
|
|
59
|
+
const value = constants.size + 1;
|
|
60
|
+
constants.set(property, value);
|
|
61
|
+
constantNames.set(value, property);
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
const implementation = method(property);
|
|
65
|
+
target[property] = implementation;
|
|
66
|
+
return implementation;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
5
70
|
var contexts = /* @__PURE__ */ new WeakMap();
|
|
71
|
+
function getJSDOMWebGLContext(canvas, options) {
|
|
72
|
+
const existing = contexts.get(canvas);
|
|
73
|
+
if (existing) return existing;
|
|
74
|
+
const attributes = {
|
|
75
|
+
alpha: true,
|
|
76
|
+
antialias: false,
|
|
77
|
+
depth: true,
|
|
78
|
+
premultipliedAlpha: true,
|
|
79
|
+
preserveDrawingBuffer: false,
|
|
80
|
+
stencil: false,
|
|
81
|
+
...typeof options === "object" && options !== null ? options : {}
|
|
82
|
+
};
|
|
83
|
+
const context = createWebGLContext(canvas, attributes);
|
|
84
|
+
contexts.set(canvas, context);
|
|
85
|
+
return context;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/testing/jsdom-canvas.ts
|
|
89
|
+
var contexts2 = /* @__PURE__ */ new WeakMap();
|
|
6
90
|
function createCanvasContext(canvas) {
|
|
7
91
|
const imageData = (width = 1, height = 1) => ({
|
|
8
92
|
data: new Uint8ClampedArray(width * height * 4),
|
|
@@ -49,12 +133,15 @@ function createCanvasContext(canvas) {
|
|
|
49
133
|
return context;
|
|
50
134
|
}
|
|
51
135
|
function installJSDOMCanvasContext() {
|
|
52
|
-
HTMLCanvasElement.prototype.getContext = function getContext(contextId) {
|
|
136
|
+
HTMLCanvasElement.prototype.getContext = function getContext(contextId, options) {
|
|
137
|
+
if (contextId === "webgl" || contextId === "webgl2") {
|
|
138
|
+
return getJSDOMWebGLContext(this, options);
|
|
139
|
+
}
|
|
53
140
|
if (contextId !== "2d") return null;
|
|
54
|
-
const existing =
|
|
141
|
+
const existing = contexts2.get(this);
|
|
55
142
|
if (existing) return existing;
|
|
56
143
|
const context = createCanvasContext(this);
|
|
57
|
-
|
|
144
|
+
contexts2.set(this, context);
|
|
58
145
|
return context;
|
|
59
146
|
};
|
|
60
147
|
}
|
|
@@ -1452,7 +1452,36 @@ function resolvePhaser3BrowserEntry(projectRoot) {
|
|
|
1452
1452
|
return void 0;
|
|
1453
1453
|
}
|
|
1454
1454
|
}
|
|
1455
|
+
var COVERAGE_INCLUDE = [
|
|
1456
|
+
"src/game/core/**/*.{ts,tsx}",
|
|
1457
|
+
"src/game/runtime/**/*.{ts,tsx}"
|
|
1458
|
+
];
|
|
1459
|
+
var COVERAGE_EXCLUDE = [
|
|
1460
|
+
"src/game/{core,runtime}/**/*.d.ts",
|
|
1461
|
+
"src/game/{core,runtime}/**/*.{spec,test}.{ts,tsx}"
|
|
1462
|
+
];
|
|
1463
|
+
var GATE_SCAN_EXCLUDE = [
|
|
1464
|
+
"src/**/*.d.ts",
|
|
1465
|
+
"src/**/*.{spec,test}.{ts,tsx}",
|
|
1466
|
+
"src/game/example/**"
|
|
1467
|
+
];
|
|
1468
|
+
function assertCoverageScopeIsPopulated(projectRoot) {
|
|
1469
|
+
const scan = (pattern) => (0, import_node_fs3.globSync)(pattern, { cwd: projectRoot, exclude: GATE_SCAN_EXCLUDE });
|
|
1470
|
+
if (COVERAGE_INCLUDE.flatMap(scan).length > 0) return;
|
|
1471
|
+
const misplaced = scan("src/**/{core,runtime}/**/*.{ts,tsx}");
|
|
1472
|
+
if (misplaced.length === 0) return;
|
|
1473
|
+
throw new Error(
|
|
1474
|
+
[
|
|
1475
|
+
"The coverage gate matched no source file, so it proves nothing.",
|
|
1476
|
+
"Deterministic rules belong in src/game/core/; the loop, scheduling,",
|
|
1477
|
+
"Controller, and Telemetry belong in src/game/runtime/.",
|
|
1478
|
+
"Move these files under those two directories:",
|
|
1479
|
+
...misplaced.slice(0, 10).map((file) => ` ${file}`)
|
|
1480
|
+
].join("\n")
|
|
1481
|
+
);
|
|
1482
|
+
}
|
|
1455
1483
|
function defineReactGameVitestConfig(options) {
|
|
1484
|
+
assertCoverageScopeIsPopulated(options.projectRoot);
|
|
1456
1485
|
const phaser3BrowserEntry = resolvePhaser3BrowserEntry(options.projectRoot);
|
|
1457
1486
|
return (0, import_config.defineConfig)({
|
|
1458
1487
|
// Keep discovery and dependency resolution anchored to the generated app even
|
|
@@ -1495,14 +1524,8 @@ function defineReactGameVitestConfig(options) {
|
|
|
1495
1524
|
clearMocks: true,
|
|
1496
1525
|
coverage: {
|
|
1497
1526
|
provider: "v8",
|
|
1498
|
-
include:
|
|
1499
|
-
|
|
1500
|
-
"src/game/runtime/**/*.{ts,tsx}"
|
|
1501
|
-
],
|
|
1502
|
-
exclude: [
|
|
1503
|
-
"src/game/{core,runtime}/**/*.d.ts",
|
|
1504
|
-
"src/game/{core,runtime}/**/*.{spec,test}.{ts,tsx}"
|
|
1505
|
-
],
|
|
1527
|
+
include: COVERAGE_INCLUDE,
|
|
1528
|
+
exclude: COVERAGE_EXCLUDE,
|
|
1506
1529
|
reporter: ["text-summary"],
|
|
1507
1530
|
thresholds: {
|
|
1508
1531
|
perFile: true,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/react-vitest-config.ts
|
|
2
|
-
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
2
|
+
import { existsSync as existsSync3, globSync, readFileSync as readFileSync2 } from "fs";
|
|
3
3
|
import { dirname as dirname2, resolve as resolve3 } from "path";
|
|
4
4
|
import { defineConfig } from "vitest/config";
|
|
5
5
|
|
|
@@ -1418,7 +1418,36 @@ function resolvePhaser3BrowserEntry(projectRoot) {
|
|
|
1418
1418
|
return void 0;
|
|
1419
1419
|
}
|
|
1420
1420
|
}
|
|
1421
|
+
var COVERAGE_INCLUDE = [
|
|
1422
|
+
"src/game/core/**/*.{ts,tsx}",
|
|
1423
|
+
"src/game/runtime/**/*.{ts,tsx}"
|
|
1424
|
+
];
|
|
1425
|
+
var COVERAGE_EXCLUDE = [
|
|
1426
|
+
"src/game/{core,runtime}/**/*.d.ts",
|
|
1427
|
+
"src/game/{core,runtime}/**/*.{spec,test}.{ts,tsx}"
|
|
1428
|
+
];
|
|
1429
|
+
var GATE_SCAN_EXCLUDE = [
|
|
1430
|
+
"src/**/*.d.ts",
|
|
1431
|
+
"src/**/*.{spec,test}.{ts,tsx}",
|
|
1432
|
+
"src/game/example/**"
|
|
1433
|
+
];
|
|
1434
|
+
function assertCoverageScopeIsPopulated(projectRoot) {
|
|
1435
|
+
const scan = (pattern) => globSync(pattern, { cwd: projectRoot, exclude: GATE_SCAN_EXCLUDE });
|
|
1436
|
+
if (COVERAGE_INCLUDE.flatMap(scan).length > 0) return;
|
|
1437
|
+
const misplaced = scan("src/**/{core,runtime}/**/*.{ts,tsx}");
|
|
1438
|
+
if (misplaced.length === 0) return;
|
|
1439
|
+
throw new Error(
|
|
1440
|
+
[
|
|
1441
|
+
"The coverage gate matched no source file, so it proves nothing.",
|
|
1442
|
+
"Deterministic rules belong in src/game/core/; the loop, scheduling,",
|
|
1443
|
+
"Controller, and Telemetry belong in src/game/runtime/.",
|
|
1444
|
+
"Move these files under those two directories:",
|
|
1445
|
+
...misplaced.slice(0, 10).map((file) => ` ${file}`)
|
|
1446
|
+
].join("\n")
|
|
1447
|
+
);
|
|
1448
|
+
}
|
|
1421
1449
|
function defineReactGameVitestConfig(options) {
|
|
1450
|
+
assertCoverageScopeIsPopulated(options.projectRoot);
|
|
1422
1451
|
const phaser3BrowserEntry = resolvePhaser3BrowserEntry(options.projectRoot);
|
|
1423
1452
|
return defineConfig({
|
|
1424
1453
|
// Keep discovery and dependency resolution anchored to the generated app even
|
|
@@ -1461,14 +1490,8 @@ function defineReactGameVitestConfig(options) {
|
|
|
1461
1490
|
clearMocks: true,
|
|
1462
1491
|
coverage: {
|
|
1463
1492
|
provider: "v8",
|
|
1464
|
-
include:
|
|
1465
|
-
|
|
1466
|
-
"src/game/runtime/**/*.{ts,tsx}"
|
|
1467
|
-
],
|
|
1468
|
-
exclude: [
|
|
1469
|
-
"src/game/{core,runtime}/**/*.d.ts",
|
|
1470
|
-
"src/game/{core,runtime}/**/*.{spec,test}.{ts,tsx}"
|
|
1471
|
-
],
|
|
1493
|
+
include: COVERAGE_INCLUDE,
|
|
1494
|
+
exclude: COVERAGE_EXCLUDE,
|
|
1472
1495
|
reporter: ["text-summary"],
|
|
1473
1496
|
thresholds: {
|
|
1474
1497
|
perFile: true,
|
|
@@ -184,8 +184,92 @@ function runtimeFailureError(code, value) {
|
|
|
184
184
|
return error;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
// src/testing/jsdom-
|
|
187
|
+
// src/testing/jsdom-webgl.ts
|
|
188
|
+
var CONSTANT_NAME = /^[A-Z][A-Z0-9_]*$/;
|
|
189
|
+
var TEXTURE_UNIT_LIMIT = 32;
|
|
190
|
+
var TEXTURE_SIZE_LIMIT = 4096;
|
|
191
|
+
var VIEWPORT_LIMIT = 4096;
|
|
192
|
+
function parameterValue(name) {
|
|
193
|
+
if (name === "VERSION") return "WebGL 2.0 (miaoda-game-devkit stub)";
|
|
194
|
+
if (name === "SHADING_LANGUAGE_VERSION") return "WebGL GLSL ES 3.00 (stub)";
|
|
195
|
+
if (name === "VENDOR" || name === "RENDERER") return "miaoda-game-devkit";
|
|
196
|
+
if (name === "MAX_VIEWPORT_DIMS") {
|
|
197
|
+
return new Int32Array([VIEWPORT_LIMIT, VIEWPORT_LIMIT]);
|
|
198
|
+
}
|
|
199
|
+
if (name === "VIEWPORT" || name === "SCISSOR_BOX") {
|
|
200
|
+
return new Int32Array([0, 0, VIEWPORT_LIMIT, VIEWPORT_LIMIT]);
|
|
201
|
+
}
|
|
202
|
+
if (name.includes("MAX_") && name.includes("SIZE")) return TEXTURE_SIZE_LIMIT;
|
|
203
|
+
if (name.startsWith("MAX_")) return TEXTURE_UNIT_LIMIT;
|
|
204
|
+
if (name.endsWith("_BITS")) return 8;
|
|
205
|
+
return 0;
|
|
206
|
+
}
|
|
207
|
+
function createWebGLContext(canvas, attributes) {
|
|
208
|
+
const constants = /* @__PURE__ */ new Map();
|
|
209
|
+
const constantNames = /* @__PURE__ */ new Map();
|
|
210
|
+
const state = {
|
|
211
|
+
canvas,
|
|
212
|
+
drawingBufferWidth: canvas.width,
|
|
213
|
+
drawingBufferHeight: canvas.height
|
|
214
|
+
};
|
|
215
|
+
const method = (name) => {
|
|
216
|
+
if (name === "getContextAttributes") return () => attributes;
|
|
217
|
+
if (name === "getExtension") return () => null;
|
|
218
|
+
if (name === "getSupportedExtensions") return () => [];
|
|
219
|
+
if (name === "getParameter") {
|
|
220
|
+
return (pname) => parameterValue(constantNames.get(pname) ?? "UNKNOWN");
|
|
221
|
+
}
|
|
222
|
+
if (name === "getShaderPrecisionFormat") {
|
|
223
|
+
return () => ({ rangeMin: 127, rangeMax: 127, precision: 23 });
|
|
224
|
+
}
|
|
225
|
+
if (name === "getShaderInfoLog" || name === "getProgramInfoLog") return () => "";
|
|
226
|
+
if (name === "getError") return () => 0;
|
|
227
|
+
if (name === "isContextLost") return () => false;
|
|
228
|
+
if (name.startsWith("get") && name.endsWith("Parameter")) return () => true;
|
|
229
|
+
if (name.startsWith("get")) return () => null;
|
|
230
|
+
if (name.startsWith("create") || name.startsWith("getUniformLocation")) {
|
|
231
|
+
return () => ({});
|
|
232
|
+
}
|
|
233
|
+
return () => void 0;
|
|
234
|
+
};
|
|
235
|
+
return new Proxy(state, {
|
|
236
|
+
get(target, property) {
|
|
237
|
+
if (property in target) return target[property];
|
|
238
|
+
if (typeof property !== "string") return void 0;
|
|
239
|
+
if (CONSTANT_NAME.test(property)) {
|
|
240
|
+
const existing = constants.get(property);
|
|
241
|
+
if (existing !== void 0) return existing;
|
|
242
|
+
const value = constants.size + 1;
|
|
243
|
+
constants.set(property, value);
|
|
244
|
+
constantNames.set(value, property);
|
|
245
|
+
return value;
|
|
246
|
+
}
|
|
247
|
+
const implementation = method(property);
|
|
248
|
+
target[property] = implementation;
|
|
249
|
+
return implementation;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
}
|
|
188
253
|
var contexts = /* @__PURE__ */ new WeakMap();
|
|
254
|
+
function getJSDOMWebGLContext(canvas, options) {
|
|
255
|
+
const existing = contexts.get(canvas);
|
|
256
|
+
if (existing) return existing;
|
|
257
|
+
const attributes = {
|
|
258
|
+
alpha: true,
|
|
259
|
+
antialias: false,
|
|
260
|
+
depth: true,
|
|
261
|
+
premultipliedAlpha: true,
|
|
262
|
+
preserveDrawingBuffer: false,
|
|
263
|
+
stencil: false,
|
|
264
|
+
...typeof options === "object" && options !== null ? options : {}
|
|
265
|
+
};
|
|
266
|
+
const context = createWebGLContext(canvas, attributes);
|
|
267
|
+
contexts.set(canvas, context);
|
|
268
|
+
return context;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// src/testing/jsdom-canvas.ts
|
|
272
|
+
var contexts2 = /* @__PURE__ */ new WeakMap();
|
|
189
273
|
function createCanvasContext(canvas) {
|
|
190
274
|
const imageData = (width = 1, height = 1) => ({
|
|
191
275
|
data: new Uint8ClampedArray(width * height * 4),
|
|
@@ -232,12 +316,15 @@ function createCanvasContext(canvas) {
|
|
|
232
316
|
return context;
|
|
233
317
|
}
|
|
234
318
|
function installJSDOMCanvasContext() {
|
|
235
|
-
HTMLCanvasElement.prototype.getContext = function getContext(contextId) {
|
|
319
|
+
HTMLCanvasElement.prototype.getContext = function getContext(contextId, options) {
|
|
320
|
+
if (contextId === "webgl" || contextId === "webgl2") {
|
|
321
|
+
return getJSDOMWebGLContext(this, options);
|
|
322
|
+
}
|
|
236
323
|
if (contextId !== "2d") return null;
|
|
237
|
-
const existing =
|
|
324
|
+
const existing = contexts2.get(this);
|
|
238
325
|
if (existing) return existing;
|
|
239
326
|
const context = createCanvasContext(this);
|
|
240
|
-
|
|
327
|
+
contexts2.set(this, context);
|
|
241
328
|
return context;
|
|
242
329
|
};
|
|
243
330
|
}
|
|
@@ -182,8 +182,92 @@ function runtimeFailureError(code, value) {
|
|
|
182
182
|
return error;
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
// src/testing/jsdom-
|
|
185
|
+
// src/testing/jsdom-webgl.ts
|
|
186
|
+
var CONSTANT_NAME = /^[A-Z][A-Z0-9_]*$/;
|
|
187
|
+
var TEXTURE_UNIT_LIMIT = 32;
|
|
188
|
+
var TEXTURE_SIZE_LIMIT = 4096;
|
|
189
|
+
var VIEWPORT_LIMIT = 4096;
|
|
190
|
+
function parameterValue(name) {
|
|
191
|
+
if (name === "VERSION") return "WebGL 2.0 (miaoda-game-devkit stub)";
|
|
192
|
+
if (name === "SHADING_LANGUAGE_VERSION") return "WebGL GLSL ES 3.00 (stub)";
|
|
193
|
+
if (name === "VENDOR" || name === "RENDERER") return "miaoda-game-devkit";
|
|
194
|
+
if (name === "MAX_VIEWPORT_DIMS") {
|
|
195
|
+
return new Int32Array([VIEWPORT_LIMIT, VIEWPORT_LIMIT]);
|
|
196
|
+
}
|
|
197
|
+
if (name === "VIEWPORT" || name === "SCISSOR_BOX") {
|
|
198
|
+
return new Int32Array([0, 0, VIEWPORT_LIMIT, VIEWPORT_LIMIT]);
|
|
199
|
+
}
|
|
200
|
+
if (name.includes("MAX_") && name.includes("SIZE")) return TEXTURE_SIZE_LIMIT;
|
|
201
|
+
if (name.startsWith("MAX_")) return TEXTURE_UNIT_LIMIT;
|
|
202
|
+
if (name.endsWith("_BITS")) return 8;
|
|
203
|
+
return 0;
|
|
204
|
+
}
|
|
205
|
+
function createWebGLContext(canvas, attributes) {
|
|
206
|
+
const constants = /* @__PURE__ */ new Map();
|
|
207
|
+
const constantNames = /* @__PURE__ */ new Map();
|
|
208
|
+
const state = {
|
|
209
|
+
canvas,
|
|
210
|
+
drawingBufferWidth: canvas.width,
|
|
211
|
+
drawingBufferHeight: canvas.height
|
|
212
|
+
};
|
|
213
|
+
const method = (name) => {
|
|
214
|
+
if (name === "getContextAttributes") return () => attributes;
|
|
215
|
+
if (name === "getExtension") return () => null;
|
|
216
|
+
if (name === "getSupportedExtensions") return () => [];
|
|
217
|
+
if (name === "getParameter") {
|
|
218
|
+
return (pname) => parameterValue(constantNames.get(pname) ?? "UNKNOWN");
|
|
219
|
+
}
|
|
220
|
+
if (name === "getShaderPrecisionFormat") {
|
|
221
|
+
return () => ({ rangeMin: 127, rangeMax: 127, precision: 23 });
|
|
222
|
+
}
|
|
223
|
+
if (name === "getShaderInfoLog" || name === "getProgramInfoLog") return () => "";
|
|
224
|
+
if (name === "getError") return () => 0;
|
|
225
|
+
if (name === "isContextLost") return () => false;
|
|
226
|
+
if (name.startsWith("get") && name.endsWith("Parameter")) return () => true;
|
|
227
|
+
if (name.startsWith("get")) return () => null;
|
|
228
|
+
if (name.startsWith("create") || name.startsWith("getUniformLocation")) {
|
|
229
|
+
return () => ({});
|
|
230
|
+
}
|
|
231
|
+
return () => void 0;
|
|
232
|
+
};
|
|
233
|
+
return new Proxy(state, {
|
|
234
|
+
get(target, property) {
|
|
235
|
+
if (property in target) return target[property];
|
|
236
|
+
if (typeof property !== "string") return void 0;
|
|
237
|
+
if (CONSTANT_NAME.test(property)) {
|
|
238
|
+
const existing = constants.get(property);
|
|
239
|
+
if (existing !== void 0) return existing;
|
|
240
|
+
const value = constants.size + 1;
|
|
241
|
+
constants.set(property, value);
|
|
242
|
+
constantNames.set(value, property);
|
|
243
|
+
return value;
|
|
244
|
+
}
|
|
245
|
+
const implementation = method(property);
|
|
246
|
+
target[property] = implementation;
|
|
247
|
+
return implementation;
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
186
251
|
var contexts = /* @__PURE__ */ new WeakMap();
|
|
252
|
+
function getJSDOMWebGLContext(canvas, options) {
|
|
253
|
+
const existing = contexts.get(canvas);
|
|
254
|
+
if (existing) return existing;
|
|
255
|
+
const attributes = {
|
|
256
|
+
alpha: true,
|
|
257
|
+
antialias: false,
|
|
258
|
+
depth: true,
|
|
259
|
+
premultipliedAlpha: true,
|
|
260
|
+
preserveDrawingBuffer: false,
|
|
261
|
+
stencil: false,
|
|
262
|
+
...typeof options === "object" && options !== null ? options : {}
|
|
263
|
+
};
|
|
264
|
+
const context = createWebGLContext(canvas, attributes);
|
|
265
|
+
contexts.set(canvas, context);
|
|
266
|
+
return context;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/testing/jsdom-canvas.ts
|
|
270
|
+
var contexts2 = /* @__PURE__ */ new WeakMap();
|
|
187
271
|
function createCanvasContext(canvas) {
|
|
188
272
|
const imageData = (width = 1, height = 1) => ({
|
|
189
273
|
data: new Uint8ClampedArray(width * height * 4),
|
|
@@ -230,12 +314,15 @@ function createCanvasContext(canvas) {
|
|
|
230
314
|
return context;
|
|
231
315
|
}
|
|
232
316
|
function installJSDOMCanvasContext() {
|
|
233
|
-
HTMLCanvasElement.prototype.getContext = function getContext(contextId) {
|
|
317
|
+
HTMLCanvasElement.prototype.getContext = function getContext(contextId, options) {
|
|
318
|
+
if (contextId === "webgl" || contextId === "webgl2") {
|
|
319
|
+
return getJSDOMWebGLContext(this, options);
|
|
320
|
+
}
|
|
234
321
|
if (contextId !== "2d") return null;
|
|
235
|
-
const existing =
|
|
322
|
+
const existing = contexts2.get(this);
|
|
236
323
|
if (existing) return existing;
|
|
237
324
|
const context = createCanvasContext(this);
|
|
238
|
-
|
|
325
|
+
contexts2.set(this, context);
|
|
239
326
|
return context;
|
|
240
327
|
};
|
|
241
328
|
}
|