@carbonenginejs/runtime-utils 0.1.1 → 0.1.3
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/LICENSE +21 -21
- package/NOTICE +23 -23
- package/README.md +69 -69
- package/THIRD-PARTY-NOTICES.md +64 -64
- package/docs/README.md +74 -73
- package/docs/architecture.md +101 -101
- package/docs/concepts/foundation-consolidation.md +85 -85
- package/docs/concepts/model-lifecycle.md +111 -0
- package/docs/const-kb.md +85 -87
- package/docs/core-types/DECORATOR-TODOS.md +25 -25
- package/docs/core-types/README.md +229 -168
- package/docs/reference/api.md +105 -102
- package/docs/reference/classes/README.md +135 -135
- package/package.json +139 -139
- package/src/arrays.js +5 -5
- package/src/audio/audioFormats.js +34 -34
- package/src/audio/index.js +1 -1
- package/src/box3.js +331 -331
- package/src/bytes.js +56 -56
- package/src/compression.js +56 -56
- package/src/constants/index.js +7 -7
- package/src/constants/trinity.js +13 -13
- package/src/constants.js +15 -15
- package/src/curve.js +79 -79
- package/src/d3d/dxgiFormats.js +46 -46
- package/src/d3d/index.js +2 -2
- package/src/d3d/primitiveTopology.js +11 -11
- package/src/document/CjsCarbonDocument.js +212 -212
- package/src/document/CjsClassRegistry.js +373 -373
- package/src/document/CjsDocumentDehydrator.js +142 -142
- package/src/document/CjsDocumentHydrator.js +156 -156
- package/src/document/CjsStructRegistry.js +348 -348
- package/src/document/hydrationAdapter.js +129 -129
- package/src/document/index.js +6 -6
- package/src/errors/CjsError.js +286 -286
- package/src/errors/index.js +5 -5
- package/src/geometry/box.js +22 -22
- package/src/geometry/cylinder.js +22 -22
- package/src/geometry/helpers/earcut.js +1 -1
- package/src/geometry/helpers/misc.js +3 -3
- package/src/geometry/index.js +8 -8
- package/src/geometry/json.js +67 -67
- package/src/geometry/lathe.js +44 -44
- package/src/geometry/plane.js +14 -14
- package/src/geometry/shape.js +4 -4
- package/src/geometry/sphere.js +24 -24
- package/src/geometry/torus.js +14 -14
- package/src/graphics/colorSpaces.js +22 -22
- package/src/graphics/index.js +4 -4
- package/src/graphics/pixelFormats.js +158 -158
- package/src/graphics/textureDimensions.js +22 -22
- package/src/graphics/trinityEnums.js +87 -87
- package/src/index.js +62 -62
- package/src/is.js +108 -46
- package/src/json.js +23 -23
- package/src/lifecycle/CjsLifecycleState.js +77 -77
- package/src/lifecycle/index.js +1 -1
- package/src/lne3.js +70 -70
- package/src/lookup.js +48 -48
- package/src/mat3.js +51 -51
- package/src/mat4.js +699 -699
- package/src/math/index.js +25 -25
- package/src/math/scalar.js +63 -63
- package/src/media/index.js +1 -1
- package/src/media/mediaTypes.js +50 -50
- package/src/mesh.js +424 -424
- package/src/model/CjsEventEmitter.js +333 -333
- package/src/model/CjsModel.js +1589 -1544
- package/src/model/CjsModelState.js +72 -72
- package/src/model/index.js +4 -4
- package/src/model/sourceRecordUtils.js +54 -54
- package/src/noise.js +310 -310
- package/src/num.js +827 -827
- package/src/object.js +39 -39
- package/src/path.js +53 -53
- package/src/pln.js +125 -125
- package/src/pool.js +9 -9
- package/src/quat.js +144 -144
- package/src/ray3.js +188 -188
- package/src/renderContext/formats.js +145 -145
- package/src/renderContext/index.js +5 -5
- package/src/renderContext/presentation.js +125 -125
- package/src/renderContext/resources.js +27 -27
- package/src/renderContext/upscaling.js +22 -22
- package/src/renderContext/window.js +20 -20
- package/src/runtime/CjsRuntimeState.js +50 -50
- package/src/schema/CjsSchema.js +555 -318
- package/src/schema/index.js +4 -4
- package/src/shader/index.js +1 -1
- package/src/shader/shaderStages.js +37 -37
- package/src/sph3.js +181 -181
- package/src/tangent.js +288 -288
- package/src/text.js +40 -40
- package/src/tri3.js +98 -98
- package/src/types/carbonTypes.js +635 -635
- package/src/types/index.js +2 -2
- package/src/utils.js +58 -58
- package/src/validation.js +46 -46
- package/src/vec2.js +229 -229
- package/src/vec3.js +1188 -1172
- package/src/vec4.js +347 -347
- package/src/vertex.js +108 -108
- package/src/webgpu/index.js +1 -1
- package/src/webgpu/textureFormats.js +121 -121
package/src/errors/CjsError.js
CHANGED
|
@@ -1,286 +1,286 @@
|
|
|
1
|
-
import { isPlainObject } from "../is.js";
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
ERROR_CODE_PATTERN = /^CJS_[A-Z][A-Z0-9]*(?:_[A-Z][A-Z0-9]*)*$/u,
|
|
5
|
-
DEFAULT_CANCELLATION_MESSAGE = "The operation was cancelled.";
|
|
6
|
-
|
|
7
|
-
export const CJS_OPERATION_CANCELLED = "CJS_OPERATION_CANCELLED";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Represents one structured operational failure with a stable CarbonEngineJS code.
|
|
11
|
-
*
|
|
12
|
-
* Programmer-contract violations should continue to use native error classes
|
|
13
|
-
* such as `TypeError`, `RangeError`, and `SyntaxError`.
|
|
14
|
-
*/
|
|
15
|
-
export class CjsError extends Error
|
|
16
|
-
{
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Creates an operational error.
|
|
20
|
-
*
|
|
21
|
-
* Details are detached and deeply frozen JSON-safe data. Cause identity is
|
|
22
|
-
* preserved through the native `Error` cause property when supplied.
|
|
23
|
-
*
|
|
24
|
-
* @param {string} code Stable uppercase `CJS_*` machine-readable code.
|
|
25
|
-
* @param {string} message Human-readable failure description.
|
|
26
|
-
* @param {{cause?: *, details?: object|null}} [options]
|
|
27
|
-
*/
|
|
28
|
-
constructor(code, message, options = {})
|
|
29
|
-
{
|
|
30
|
-
const
|
|
31
|
-
normalizedCode = CjsError.#NormalizeCode(code),
|
|
32
|
-
normalizedMessage = CjsError.#NormalizeMessage(message),
|
|
33
|
-
normalizedOptions = CjsError.#NormalizeOptions(options),
|
|
34
|
-
errorOptions = Object.hasOwn(normalizedOptions, "cause")
|
|
35
|
-
? { cause: normalizedOptions.cause }
|
|
36
|
-
: undefined;
|
|
37
|
-
|
|
38
|
-
super(normalizedMessage, errorOptions);
|
|
39
|
-
|
|
40
|
-
this.name = new.target.name;
|
|
41
|
-
|
|
42
|
-
Object.defineProperties(this, {
|
|
43
|
-
code: {
|
|
44
|
-
value: normalizedCode,
|
|
45
|
-
enumerable: true,
|
|
46
|
-
configurable: false,
|
|
47
|
-
writable: false
|
|
48
|
-
},
|
|
49
|
-
details: {
|
|
50
|
-
value: CjsError.#NormalizeDetails(normalizedOptions.details),
|
|
51
|
-
enumerable: true,
|
|
52
|
-
configurable: false,
|
|
53
|
-
writable: false
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Checks a structured or legacy error for an exact stable code.
|
|
60
|
-
*
|
|
61
|
-
* Invalid candidate codes and inaccessible error properties return false
|
|
62
|
-
* so this helper remains safe inside failure handling.
|
|
63
|
-
*/
|
|
64
|
-
static hasCode(error, code)
|
|
65
|
-
{
|
|
66
|
-
if (!CjsError.#IsCode(code) || error === null || error === undefined)
|
|
67
|
-
{
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
try
|
|
72
|
-
{
|
|
73
|
-
return error.code === code;
|
|
74
|
-
}
|
|
75
|
-
catch
|
|
76
|
-
{
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/** Reports whether a value is one valid stable error code. */
|
|
82
|
-
static #IsCode(value)
|
|
83
|
-
{
|
|
84
|
-
return typeof value === "string" && ERROR_CODE_PATTERN.test(value);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/** Validates and returns one stable error code. */
|
|
88
|
-
static #NormalizeCode(value)
|
|
89
|
-
{
|
|
90
|
-
if (!CjsError.#IsCode(value))
|
|
91
|
-
{
|
|
92
|
-
throw new TypeError("code must be an uppercase CJS_* identifier.");
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return value;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/** Validates and returns one non-empty error message. */
|
|
99
|
-
static #NormalizeMessage(value)
|
|
100
|
-
{
|
|
101
|
-
if (typeof value !== "string" || value.trim() === "")
|
|
102
|
-
{
|
|
103
|
-
throw new TypeError("message must be a non-empty string.");
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return value;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/** Validates and returns one plain constructor-options record. */
|
|
110
|
-
static #NormalizeOptions(value)
|
|
111
|
-
{
|
|
112
|
-
if (!isPlainObject(value))
|
|
113
|
-
{
|
|
114
|
-
throw new TypeError("options must be a plain object.");
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return value;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/** Converts optional details into detached deeply frozen data. */
|
|
121
|
-
static #NormalizeDetails(value)
|
|
122
|
-
{
|
|
123
|
-
if (value === undefined || value === null)
|
|
124
|
-
{
|
|
125
|
-
return null;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (!isPlainObject(value))
|
|
129
|
-
{
|
|
130
|
-
throw new TypeError("details must be a JSON-safe plain object or null.");
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return CjsError.#CloneDetailsValue(value, "details", new Set());
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/** Clones one JSON-safe details value while detecting active cycles. */
|
|
137
|
-
static #CloneDetailsValue(value, path, active)
|
|
138
|
-
{
|
|
139
|
-
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
140
|
-
{
|
|
141
|
-
return value;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (typeof value === "number")
|
|
145
|
-
{
|
|
146
|
-
if (!Number.isFinite(value))
|
|
147
|
-
{
|
|
148
|
-
throw new TypeError(`${path} must contain only finite numbers.`);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return value;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (!Array.isArray(value) && !isPlainObject(value))
|
|
155
|
-
{
|
|
156
|
-
throw new TypeError(`${path} must contain only JSON-safe values.`);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (active.has(value))
|
|
160
|
-
{
|
|
161
|
-
throw new TypeError(`${path} must not contain a circular reference.`);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
active.add(value);
|
|
165
|
-
|
|
166
|
-
const clone = Array.isArray(value)
|
|
167
|
-
? CjsError.#CloneDetailsArray(value, path, active)
|
|
168
|
-
: CjsError.#CloneDetailsRecord(value, path, active);
|
|
169
|
-
|
|
170
|
-
active.delete(value);
|
|
171
|
-
return Object.freeze(clone);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/** Clones one dense JSON-safe details array. */
|
|
175
|
-
static #CloneDetailsArray(value, path, active)
|
|
176
|
-
{
|
|
177
|
-
const clone = [];
|
|
178
|
-
|
|
179
|
-
for (const key of Reflect.ownKeys(value))
|
|
180
|
-
{
|
|
181
|
-
if (key === "length")
|
|
182
|
-
{
|
|
183
|
-
continue;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (typeof key !== "string"
|
|
187
|
-
|| !/^(?:0|[1-9]\d*)$/u.test(key)
|
|
188
|
-
|| Number(key) >= value.length)
|
|
189
|
-
{
|
|
190
|
-
throw new TypeError(`${path} arrays must contain only indexed values.`);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
for (let i = 0; i < value.length; i++)
|
|
195
|
-
{
|
|
196
|
-
const descriptor = Object.getOwnPropertyDescriptor(value, String(i));
|
|
197
|
-
|
|
198
|
-
if (!descriptor?.enumerable || !Object.hasOwn(descriptor, "value"))
|
|
199
|
-
{
|
|
200
|
-
throw new TypeError(`${path} arrays must contain dense data properties.`);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
clone.push(CjsError.#CloneDetailsValue(
|
|
204
|
-
descriptor.value,
|
|
205
|
-
`${path}[${i}]`,
|
|
206
|
-
active
|
|
207
|
-
));
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return clone;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/** Clones one plain JSON-safe details record. */
|
|
214
|
-
static #CloneDetailsRecord(value, path, active)
|
|
215
|
-
{
|
|
216
|
-
const clone = {};
|
|
217
|
-
|
|
218
|
-
for (const key of Reflect.ownKeys(value))
|
|
219
|
-
{
|
|
220
|
-
if (typeof key !== "string")
|
|
221
|
-
{
|
|
222
|
-
throw new TypeError(`${path} must not contain symbol keys.`);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
226
|
-
|
|
227
|
-
if (!descriptor?.enumerable || !Object.hasOwn(descriptor, "value"))
|
|
228
|
-
{
|
|
229
|
-
throw new TypeError(`${path} must contain only enumerable data properties.`);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
Object.defineProperty(clone, key, {
|
|
233
|
-
value: CjsError.#CloneDetailsValue(
|
|
234
|
-
descriptor.value,
|
|
235
|
-
`${path}[${JSON.stringify(key)}]`,
|
|
236
|
-
active
|
|
237
|
-
),
|
|
238
|
-
enumerable: true,
|
|
239
|
-
configurable: false,
|
|
240
|
-
writable: false
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
return clone;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/** Represents one cancelled operation using Web-compatible abort identity. */
|
|
250
|
-
export class CjsCancellationError extends CjsError
|
|
251
|
-
{
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Creates a cancellation error with stable code `CJS_OPERATION_CANCELLED`.
|
|
255
|
-
*
|
|
256
|
-
* @param {string} [message]
|
|
257
|
-
* @param {{cause?: *, details?: object|null}} [options]
|
|
258
|
-
*/
|
|
259
|
-
constructor(message = DEFAULT_CANCELLATION_MESSAGE, options = {})
|
|
260
|
-
{
|
|
261
|
-
super(CJS_OPERATION_CANCELLED, message, options);
|
|
262
|
-
this.name = "AbortError";
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Checks for this cancellation type, its stable code, or a platform
|
|
267
|
-
* `AbortError` name.
|
|
268
|
-
*/
|
|
269
|
-
static is(error)
|
|
270
|
-
{
|
|
271
|
-
if (CjsError.hasCode(error, CJS_OPERATION_CANCELLED))
|
|
272
|
-
{
|
|
273
|
-
return true;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
try
|
|
277
|
-
{
|
|
278
|
-
return error?.name === "AbortError";
|
|
279
|
-
}
|
|
280
|
-
catch
|
|
281
|
-
{
|
|
282
|
-
return false;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
}
|
|
1
|
+
import { isPlainObject } from "../is.js";
|
|
2
|
+
|
|
3
|
+
const
|
|
4
|
+
ERROR_CODE_PATTERN = /^CJS_[A-Z][A-Z0-9]*(?:_[A-Z][A-Z0-9]*)*$/u,
|
|
5
|
+
DEFAULT_CANCELLATION_MESSAGE = "The operation was cancelled.";
|
|
6
|
+
|
|
7
|
+
export const CJS_OPERATION_CANCELLED = "CJS_OPERATION_CANCELLED";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Represents one structured operational failure with a stable CarbonEngineJS code.
|
|
11
|
+
*
|
|
12
|
+
* Programmer-contract violations should continue to use native error classes
|
|
13
|
+
* such as `TypeError`, `RangeError`, and `SyntaxError`.
|
|
14
|
+
*/
|
|
15
|
+
export class CjsError extends Error
|
|
16
|
+
{
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates an operational error.
|
|
20
|
+
*
|
|
21
|
+
* Details are detached and deeply frozen JSON-safe data. Cause identity is
|
|
22
|
+
* preserved through the native `Error` cause property when supplied.
|
|
23
|
+
*
|
|
24
|
+
* @param {string} code Stable uppercase `CJS_*` machine-readable code.
|
|
25
|
+
* @param {string} message Human-readable failure description.
|
|
26
|
+
* @param {{cause?: *, details?: object|null}} [options]
|
|
27
|
+
*/
|
|
28
|
+
constructor(code, message, options = {})
|
|
29
|
+
{
|
|
30
|
+
const
|
|
31
|
+
normalizedCode = CjsError.#NormalizeCode(code),
|
|
32
|
+
normalizedMessage = CjsError.#NormalizeMessage(message),
|
|
33
|
+
normalizedOptions = CjsError.#NormalizeOptions(options),
|
|
34
|
+
errorOptions = Object.hasOwn(normalizedOptions, "cause")
|
|
35
|
+
? { cause: normalizedOptions.cause }
|
|
36
|
+
: undefined;
|
|
37
|
+
|
|
38
|
+
super(normalizedMessage, errorOptions);
|
|
39
|
+
|
|
40
|
+
this.name = new.target.name;
|
|
41
|
+
|
|
42
|
+
Object.defineProperties(this, {
|
|
43
|
+
code: {
|
|
44
|
+
value: normalizedCode,
|
|
45
|
+
enumerable: true,
|
|
46
|
+
configurable: false,
|
|
47
|
+
writable: false
|
|
48
|
+
},
|
|
49
|
+
details: {
|
|
50
|
+
value: CjsError.#NormalizeDetails(normalizedOptions.details),
|
|
51
|
+
enumerable: true,
|
|
52
|
+
configurable: false,
|
|
53
|
+
writable: false
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Checks a structured or legacy error for an exact stable code.
|
|
60
|
+
*
|
|
61
|
+
* Invalid candidate codes and inaccessible error properties return false
|
|
62
|
+
* so this helper remains safe inside failure handling.
|
|
63
|
+
*/
|
|
64
|
+
static hasCode(error, code)
|
|
65
|
+
{
|
|
66
|
+
if (!CjsError.#IsCode(code) || error === null || error === undefined)
|
|
67
|
+
{
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
try
|
|
72
|
+
{
|
|
73
|
+
return error.code === code;
|
|
74
|
+
}
|
|
75
|
+
catch
|
|
76
|
+
{
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Reports whether a value is one valid stable error code. */
|
|
82
|
+
static #IsCode(value)
|
|
83
|
+
{
|
|
84
|
+
return typeof value === "string" && ERROR_CODE_PATTERN.test(value);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Validates and returns one stable error code. */
|
|
88
|
+
static #NormalizeCode(value)
|
|
89
|
+
{
|
|
90
|
+
if (!CjsError.#IsCode(value))
|
|
91
|
+
{
|
|
92
|
+
throw new TypeError("code must be an uppercase CJS_* identifier.");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Validates and returns one non-empty error message. */
|
|
99
|
+
static #NormalizeMessage(value)
|
|
100
|
+
{
|
|
101
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
102
|
+
{
|
|
103
|
+
throw new TypeError("message must be a non-empty string.");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return value;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Validates and returns one plain constructor-options record. */
|
|
110
|
+
static #NormalizeOptions(value)
|
|
111
|
+
{
|
|
112
|
+
if (!isPlainObject(value))
|
|
113
|
+
{
|
|
114
|
+
throw new TypeError("options must be a plain object.");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return value;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Converts optional details into detached deeply frozen data. */
|
|
121
|
+
static #NormalizeDetails(value)
|
|
122
|
+
{
|
|
123
|
+
if (value === undefined || value === null)
|
|
124
|
+
{
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!isPlainObject(value))
|
|
129
|
+
{
|
|
130
|
+
throw new TypeError("details must be a JSON-safe plain object or null.");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return CjsError.#CloneDetailsValue(value, "details", new Set());
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Clones one JSON-safe details value while detecting active cycles. */
|
|
137
|
+
static #CloneDetailsValue(value, path, active)
|
|
138
|
+
{
|
|
139
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
140
|
+
{
|
|
141
|
+
return value;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (typeof value === "number")
|
|
145
|
+
{
|
|
146
|
+
if (!Number.isFinite(value))
|
|
147
|
+
{
|
|
148
|
+
throw new TypeError(`${path} must contain only finite numbers.`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return value;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (!Array.isArray(value) && !isPlainObject(value))
|
|
155
|
+
{
|
|
156
|
+
throw new TypeError(`${path} must contain only JSON-safe values.`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (active.has(value))
|
|
160
|
+
{
|
|
161
|
+
throw new TypeError(`${path} must not contain a circular reference.`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
active.add(value);
|
|
165
|
+
|
|
166
|
+
const clone = Array.isArray(value)
|
|
167
|
+
? CjsError.#CloneDetailsArray(value, path, active)
|
|
168
|
+
: CjsError.#CloneDetailsRecord(value, path, active);
|
|
169
|
+
|
|
170
|
+
active.delete(value);
|
|
171
|
+
return Object.freeze(clone);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Clones one dense JSON-safe details array. */
|
|
175
|
+
static #CloneDetailsArray(value, path, active)
|
|
176
|
+
{
|
|
177
|
+
const clone = [];
|
|
178
|
+
|
|
179
|
+
for (const key of Reflect.ownKeys(value))
|
|
180
|
+
{
|
|
181
|
+
if (key === "length")
|
|
182
|
+
{
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (typeof key !== "string"
|
|
187
|
+
|| !/^(?:0|[1-9]\d*)$/u.test(key)
|
|
188
|
+
|| Number(key) >= value.length)
|
|
189
|
+
{
|
|
190
|
+
throw new TypeError(`${path} arrays must contain only indexed values.`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
for (let i = 0; i < value.length; i++)
|
|
195
|
+
{
|
|
196
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(i));
|
|
197
|
+
|
|
198
|
+
if (!descriptor?.enumerable || !Object.hasOwn(descriptor, "value"))
|
|
199
|
+
{
|
|
200
|
+
throw new TypeError(`${path} arrays must contain dense data properties.`);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
clone.push(CjsError.#CloneDetailsValue(
|
|
204
|
+
descriptor.value,
|
|
205
|
+
`${path}[${i}]`,
|
|
206
|
+
active
|
|
207
|
+
));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return clone;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Clones one plain JSON-safe details record. */
|
|
214
|
+
static #CloneDetailsRecord(value, path, active)
|
|
215
|
+
{
|
|
216
|
+
const clone = {};
|
|
217
|
+
|
|
218
|
+
for (const key of Reflect.ownKeys(value))
|
|
219
|
+
{
|
|
220
|
+
if (typeof key !== "string")
|
|
221
|
+
{
|
|
222
|
+
throw new TypeError(`${path} must not contain symbol keys.`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
226
|
+
|
|
227
|
+
if (!descriptor?.enumerable || !Object.hasOwn(descriptor, "value"))
|
|
228
|
+
{
|
|
229
|
+
throw new TypeError(`${path} must contain only enumerable data properties.`);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
Object.defineProperty(clone, key, {
|
|
233
|
+
value: CjsError.#CloneDetailsValue(
|
|
234
|
+
descriptor.value,
|
|
235
|
+
`${path}[${JSON.stringify(key)}]`,
|
|
236
|
+
active
|
|
237
|
+
),
|
|
238
|
+
enumerable: true,
|
|
239
|
+
configurable: false,
|
|
240
|
+
writable: false
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return clone;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** Represents one cancelled operation using Web-compatible abort identity. */
|
|
250
|
+
export class CjsCancellationError extends CjsError
|
|
251
|
+
{
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Creates a cancellation error with stable code `CJS_OPERATION_CANCELLED`.
|
|
255
|
+
*
|
|
256
|
+
* @param {string} [message]
|
|
257
|
+
* @param {{cause?: *, details?: object|null}} [options]
|
|
258
|
+
*/
|
|
259
|
+
constructor(message = DEFAULT_CANCELLATION_MESSAGE, options = {})
|
|
260
|
+
{
|
|
261
|
+
super(CJS_OPERATION_CANCELLED, message, options);
|
|
262
|
+
this.name = "AbortError";
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Checks for this cancellation type, its stable code, or a platform
|
|
267
|
+
* `AbortError` name.
|
|
268
|
+
*/
|
|
269
|
+
static is(error)
|
|
270
|
+
{
|
|
271
|
+
if (CjsError.hasCode(error, CJS_OPERATION_CANCELLED))
|
|
272
|
+
{
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
try
|
|
277
|
+
{
|
|
278
|
+
return error?.name === "AbortError";
|
|
279
|
+
}
|
|
280
|
+
catch
|
|
281
|
+
{
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
}
|
package/src/errors/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
CJS_OPERATION_CANCELLED,
|
|
3
|
-
CjsCancellationError,
|
|
4
|
-
CjsError
|
|
5
|
-
} from "./CjsError.js";
|
|
1
|
+
export {
|
|
2
|
+
CJS_OPERATION_CANCELLED,
|
|
3
|
+
CjsCancellationError,
|
|
4
|
+
CjsError
|
|
5
|
+
} from "./CjsError.js";
|
package/src/geometry/box.js
CHANGED
|
@@ -23,17 +23,17 @@ export function createBox(options = {})
|
|
|
23
23
|
widthSegments = 1,
|
|
24
24
|
heightSegments = 1,
|
|
25
25
|
depthSegments = 1
|
|
26
|
-
} = options;
|
|
27
|
-
|
|
28
|
-
if (![ width, height, depth ].every(Number.isFinite) ||
|
|
29
|
-
width === 0 || height === 0 || depth === 0)
|
|
30
|
-
{
|
|
31
|
-
throw new Error("Box dimensions must be finite and non-zero");
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
widthSegments = Math.max(1, Math.floor(Number.isFinite(widthSegments) ? widthSegments : 1));
|
|
35
|
-
heightSegments = Math.max(1, Math.floor(Number.isFinite(heightSegments) ? heightSegments : 1));
|
|
36
|
-
depthSegments = Math.max(1, Math.floor(Number.isFinite(depthSegments) ? depthSegments : 1));
|
|
26
|
+
} = options;
|
|
27
|
+
|
|
28
|
+
if (![ width, height, depth ].every(Number.isFinite) ||
|
|
29
|
+
width === 0 || height === 0 || depth === 0)
|
|
30
|
+
{
|
|
31
|
+
throw new Error("Box dimensions must be finite and non-zero");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
widthSegments = Math.max(1, Math.floor(Number.isFinite(widthSegments) ? widthSegments : 1));
|
|
35
|
+
heightSegments = Math.max(1, Math.floor(Number.isFinite(heightSegments) ? heightSegments : 1));
|
|
36
|
+
depthSegments = Math.max(1, Math.floor(Number.isFinite(depthSegments) ? depthSegments : 1));
|
|
37
37
|
|
|
38
38
|
const
|
|
39
39
|
indices = [],
|
|
@@ -121,17 +121,17 @@ export function createBox(options = {})
|
|
|
121
121
|
|
|
122
122
|
// Normalize
|
|
123
123
|
const result = toJSON(indices, positions, uvs, normals);
|
|
124
|
-
result.factory = createBox;
|
|
125
|
-
result.options = {
|
|
126
|
-
width,
|
|
127
|
-
height,
|
|
128
|
-
depth,
|
|
129
|
-
widthSegments,
|
|
130
|
-
heightSegments,
|
|
131
|
-
depthSegments
|
|
132
|
-
};
|
|
133
|
-
result.shape = { factory: result.factory, options: result.options };
|
|
134
|
-
return result;
|
|
124
|
+
result.factory = createBox;
|
|
125
|
+
result.options = {
|
|
126
|
+
width,
|
|
127
|
+
height,
|
|
128
|
+
depth,
|
|
129
|
+
widthSegments,
|
|
130
|
+
heightSegments,
|
|
131
|
+
depthSegments
|
|
132
|
+
};
|
|
133
|
+
result.shape = { factory: result.factory, options: result.options };
|
|
134
|
+
return result;
|
|
135
135
|
|
|
136
136
|
}
|
|
137
137
|
|