@woosh/meep-engine 2.33.47 → 2.33.51
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/core/model/object/compareValues.js +67 -0
- package/core/model/object/invokeObjectClone.js +8 -0
- package/core/model/{ObjectUtils.spec.js → object/objectDeepEquals.spec.js} +1 -1
- package/core/model/object/objectShallowCopyByOwnKeys.js +17 -0
- package/core/model/object/read_property.d.ts +1 -0
- package/core/model/object/read_property.js +37 -0
- package/core/model/object/validatedObjectValueByKey.js +21 -0
- package/core/model/object/write_property.d.ts +1 -0
- package/core/model/object/write_property.js +52 -0
- package/engine/ecs/EntityComponentDataset.js +3 -3
- package/engine/ecs/EntityManager.js +1 -1
- package/engine/ecs/binding/ComponentPropertyBinding.js +14 -3
- package/engine/ecs/binding/EntityProxyScope.js +3 -26
- package/engine/graphics/particles/ParticleEmitterLibrary.js +21 -0
- package/engine/graphics/particles/ecs/ParticleEmitterSystem.d.ts +7 -0
- package/engine/graphics/particles/ecs/ParticleEmitterSystem.js +1 -10
- package/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts +2 -0
- package/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.d.ts +2 -0
- package/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.js +4 -0
- package/engine/graphics/texture/atlas/TextureAtlas.js +1 -1
- package/package.json +1 -1
- package/core/model/ObjectUtils.js +0 -122
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { compareStrings } from "../../primitives/strings/compareStrings.js";
|
|
2
|
+
import { compareNumbers } from "../../primitives/numbers/compareNumbers.js";
|
|
3
|
+
import { compareBooleans } from "../../primitives/boolean/compareBooleans.js";
|
|
4
|
+
import { extractFunctionBody } from "../../function/extractFunctionBody.js";
|
|
5
|
+
import { compareArrays } from "../../primitives/array/compareArrays.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @param {*} a
|
|
10
|
+
* @param {*} b
|
|
11
|
+
* @returns {number}
|
|
12
|
+
*/
|
|
13
|
+
export function compareValues(a, b) {
|
|
14
|
+
if (a === b) {
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const aType = typeof a;
|
|
19
|
+
const bType = typeof b;
|
|
20
|
+
|
|
21
|
+
if (aType !== bType) {
|
|
22
|
+
return compareStrings(aType, bType);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (aType === "string") {
|
|
26
|
+
return compareStrings(a, b);
|
|
27
|
+
} else if (aType === "number") {
|
|
28
|
+
return compareNumbers(a, b);
|
|
29
|
+
} else if (aType === "boolean") {
|
|
30
|
+
return compareBooleans(a, b);
|
|
31
|
+
} else if (aType === "function") {
|
|
32
|
+
return compareStrings(extractFunctionBody(a), extractFunctionBody(b));
|
|
33
|
+
} else if (aType === "object") {
|
|
34
|
+
if (a === null) {
|
|
35
|
+
if (b !== null) {
|
|
36
|
+
return -1;
|
|
37
|
+
} else {
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
} else if (b === null) {
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
45
|
+
return compareArrays(a, b, compareValues);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const aKeys = Object.keys(a);
|
|
49
|
+
const bKeys = Object.keys(b);
|
|
50
|
+
|
|
51
|
+
const dKeys = compareArrays(aKeys, bKeys, compareStrings);
|
|
52
|
+
|
|
53
|
+
if (dKeys !== 0) {
|
|
54
|
+
return dKeys;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for (let p in a) {
|
|
58
|
+
const d = compareValues(a[p], b[p]);
|
|
59
|
+
|
|
60
|
+
if (d !== 0) {
|
|
61
|
+
return d;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template S,R
|
|
3
|
+
* @param {S} source
|
|
4
|
+
* @return {R}
|
|
5
|
+
*/
|
|
6
|
+
export function objectShallowCopyByOwnKeys(source) {
|
|
7
|
+
const keys = Reflect.ownKeys(source);
|
|
8
|
+
|
|
9
|
+
const result = {};
|
|
10
|
+
const n = keys.length;
|
|
11
|
+
for (let i = 0; i < n; i++) {
|
|
12
|
+
const key = keys[i];
|
|
13
|
+
result[key] = source[key];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function read_property<T>(root: Object, parts: string[], part_offset: number, part_count: number): T | undefined
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { capitalize } from "../../primitives/strings/StringUtils.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @template T
|
|
5
|
+
* @param {Object} root
|
|
6
|
+
* @param {string[]} parts
|
|
7
|
+
* @param {number} part_offset
|
|
8
|
+
* @param {number} part_count
|
|
9
|
+
* @returns {undefined|T}
|
|
10
|
+
*/
|
|
11
|
+
export function read_property(root, parts, part_offset, part_count) {
|
|
12
|
+
|
|
13
|
+
let thing = root;
|
|
14
|
+
|
|
15
|
+
for (let i = 0; i < part_count; i++) {
|
|
16
|
+
|
|
17
|
+
const part = parts[i + part_offset];
|
|
18
|
+
|
|
19
|
+
if (thing.hasOwnProperty(part)) {
|
|
20
|
+
thing = thing[part];
|
|
21
|
+
} else {
|
|
22
|
+
const getter_name = `get${capitalize(part)}`;
|
|
23
|
+
const getter = thing[getter_name];
|
|
24
|
+
|
|
25
|
+
if (typeof getter === "function") {
|
|
26
|
+
// resolve via getter
|
|
27
|
+
thing = getter.call(thing);
|
|
28
|
+
} else {
|
|
29
|
+
// no getter
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return thing;
|
|
37
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { assert } from "../../assert.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @template V
|
|
5
|
+
* @param {Object<V>} object
|
|
6
|
+
* @param {string} key
|
|
7
|
+
* @returns {V}
|
|
8
|
+
* @throws {Error} if such key does not exist
|
|
9
|
+
*/
|
|
10
|
+
export function validatedObjectValueByKey(object, key) {
|
|
11
|
+
|
|
12
|
+
assert.typeOf(key, 'string', 'key');
|
|
13
|
+
|
|
14
|
+
const value = object[key];
|
|
15
|
+
|
|
16
|
+
if (value === undefined) {
|
|
17
|
+
throw new Error(`Unknown key '${key}', valid keys: [${Object.keys(object).join(', ')}]`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function write_property<T>(root: Object, parts: string[], part_offset: number, part_count: number, value: T): void
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { capitalize } from "../../primitives/strings/StringUtils.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @template T
|
|
5
|
+
* @param {Object} root
|
|
6
|
+
* @param {string[]} parts
|
|
7
|
+
* @param {number} part_offset
|
|
8
|
+
* @param {number} part_count
|
|
9
|
+
* @param {T} value
|
|
10
|
+
*/
|
|
11
|
+
export function write_property(root, parts, part_offset, part_count, value) {
|
|
12
|
+
let thing = root;
|
|
13
|
+
|
|
14
|
+
const last_index = part_offset + part_count - 1;
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < last_index; i++) {
|
|
17
|
+
|
|
18
|
+
const part = parts[i + part_offset];
|
|
19
|
+
|
|
20
|
+
if (thing.hasOwnProperty(part)) {
|
|
21
|
+
thing = thing[part];
|
|
22
|
+
} else {
|
|
23
|
+
|
|
24
|
+
const getter_name = `get${capitalize(part)}`;
|
|
25
|
+
const getter = thing[getter_name];
|
|
26
|
+
|
|
27
|
+
if (typeof getter === "function") {
|
|
28
|
+
// resolve via getter
|
|
29
|
+
thing = getter.call(thing);
|
|
30
|
+
} else {
|
|
31
|
+
// no getter
|
|
32
|
+
throw new Error(`No no property or getter found for '${part}' on [${i}]'${parts.slice(part_offset, part_offset + part_count).join('/')}'`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const last_part = parts[last_index];
|
|
38
|
+
|
|
39
|
+
const setter_name = `set${capitalize(last_part)}`;
|
|
40
|
+
const setter = thing[setter_name];
|
|
41
|
+
|
|
42
|
+
if (typeof setter === "function") {
|
|
43
|
+
// resolve via setter
|
|
44
|
+
setter.call(thing, value);
|
|
45
|
+
} else if (thing.hasOwnProperty(last_part)) {
|
|
46
|
+
thing[last_part] = value;
|
|
47
|
+
} else {
|
|
48
|
+
// no setter
|
|
49
|
+
throw new Error(`No no property or getter found for '${last_part}' on [${part_count - 1}]'${parts.slice(part_offset, part_offset + part_count).join('/')}'`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
@@ -1007,10 +1007,10 @@ export class EntityComponentDataset {
|
|
|
1007
1007
|
}
|
|
1008
1008
|
|
|
1009
1009
|
/**
|
|
1010
|
-
* @template
|
|
1010
|
+
* @template T
|
|
1011
1011
|
* @param {number} entityIndex
|
|
1012
|
-
* @param {Class<
|
|
1013
|
-
* @returns {
|
|
1012
|
+
* @param {Class<T>} klass
|
|
1013
|
+
* @returns {T|undefined}
|
|
1014
1014
|
*/
|
|
1015
1015
|
getComponent(entityIndex, klass) {
|
|
1016
1016
|
if (!ENV_PRODUCTION) {
|
|
@@ -715,7 +715,7 @@ EntityManager.prototype.startup = function (readyCallback, errorCallback) {
|
|
|
715
715
|
let firstFailure = true;
|
|
716
716
|
|
|
717
717
|
function systemError(system, error) {
|
|
718
|
-
console.error("Failed to start system", system);
|
|
718
|
+
console.error("Failed to start system", system, 'Error:', error);
|
|
719
719
|
|
|
720
720
|
if (firstFailure) {
|
|
721
721
|
firstFailure = false;
|
|
@@ -15,12 +15,12 @@ export class ComponentPropertyBinding {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* @template T
|
|
19
19
|
* @param {EntityComponentDataset} ecd
|
|
20
20
|
* @param {number} entity
|
|
21
|
+
* @returns {T}
|
|
21
22
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
__resolve_component(ecd, entity) {
|
|
24
24
|
const className = this.path.component;
|
|
25
25
|
const ComponentClass = ecd.getComponentClassByName(className);
|
|
26
26
|
|
|
@@ -34,6 +34,17 @@ export class ComponentPropertyBinding {
|
|
|
34
34
|
throw new Error(`Component '${className}' is not found on entity '${entity}'`);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
return component;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
* @param {EntityComponentDataset} ecd
|
|
43
|
+
* @param {number} entity
|
|
44
|
+
*/
|
|
45
|
+
resolve(ecd, entity) {
|
|
46
|
+
const component = this.__resolve_component(ecd, entity);
|
|
47
|
+
|
|
37
48
|
const value = resolvePath(component, this.path.path);
|
|
38
49
|
|
|
39
50
|
if (value === undefined) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { read_property } from "../../../core/model/object/read_property.js";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
*
|
|
3
5
|
* @param {number} entity
|
|
4
6
|
* @param {EntityComponentDataset} ecd
|
|
5
7
|
* @param {string} path
|
|
6
8
|
*/
|
|
7
|
-
import { capitalize } from "../../../core/primitives/strings/StringUtils.js";
|
|
8
|
-
|
|
9
9
|
function resolvePath(entity, ecd, path) {
|
|
10
10
|
if (!ecd.entityExists(entity)) {
|
|
11
11
|
// entity doesn't exist
|
|
@@ -37,30 +37,7 @@ function resolvePath(entity, ecd, path) {
|
|
|
37
37
|
return undefined;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
for (let i = 1; i < part_count; i++) {
|
|
43
|
-
|
|
44
|
-
const part = parts[i];
|
|
45
|
-
|
|
46
|
-
if (thing.hasOwnProperty(part)) {
|
|
47
|
-
thing = thing[part];
|
|
48
|
-
} else {
|
|
49
|
-
const getter_name = `get${capitalize(part)}`;
|
|
50
|
-
const getter = thing[getter_name];
|
|
51
|
-
|
|
52
|
-
if (typeof getter === "function") {
|
|
53
|
-
// resolve via getter
|
|
54
|
-
thing = getter.call(thing);
|
|
55
|
-
} else {
|
|
56
|
-
// no getter
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return thing;
|
|
40
|
+
return read_property(component, parts, 1, part_count - 1);
|
|
64
41
|
}
|
|
65
42
|
|
|
66
43
|
export class EntityProxyScope {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ParticleEmitter } from "./particular/engine/emitter/ParticleEmitter.js";
|
|
2
2
|
import { GameAssetType } from "../../asset/GameAssetType.js";
|
|
3
3
|
import { assert } from "../../../core/assert.js";
|
|
4
|
+
import { JsonAssetLoader } from "../../asset/loaders/JsonAssetLoader.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @deprecated Use "Effect" API to achieve the same results
|
|
@@ -20,6 +21,26 @@ export class ParticleEmitterLibrary {
|
|
|
20
21
|
this.data = {};
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param {string} path
|
|
27
|
+
* @returns {Promise<void>}
|
|
28
|
+
*/
|
|
29
|
+
async load_from_registry_file(path) {
|
|
30
|
+
|
|
31
|
+
const am = this.assetManager;
|
|
32
|
+
|
|
33
|
+
if (am.getLoaderByType(GameAssetType.JSON) === undefined) {
|
|
34
|
+
// add missing loader
|
|
35
|
+
await am.registerLoader(GameAssetType.JSON, new JsonAssetLoader());
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const asset = await am.promise(path, GameAssetType.JSON)
|
|
39
|
+
const particleSet = asset.create();
|
|
40
|
+
|
|
41
|
+
await this.load(particleSet);
|
|
42
|
+
}
|
|
43
|
+
|
|
23
44
|
/**
|
|
24
45
|
* @param {Object} listing
|
|
25
46
|
* @returns {Promise}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import {System} from "../../../ecs/System";
|
|
2
|
+
import Engine from "../../../Engine";
|
|
3
|
+
import {ParticleEmitter} from "../particular/engine/emitter/ParticleEmitter";
|
|
4
|
+
|
|
5
|
+
export class ParticleEmitterSystem extends System<ParticleEmitter> {
|
|
6
|
+
constructor(engine: Engine)
|
|
7
|
+
}
|
|
@@ -5,7 +5,6 @@ import { Transform } from "../../../ecs/transform/Transform.js";
|
|
|
5
5
|
import { ParticleEmitterFlag } from "../particular/engine/emitter/ParticleEmitterFlag.js";
|
|
6
6
|
import { RenderPassType } from "../../render/RenderPassType.js";
|
|
7
7
|
import { ParticleEmitterLibrary } from "../ParticleEmitterLibrary.js";
|
|
8
|
-
import { GameAssetType } from "../../../asset/GameAssetType.js";
|
|
9
8
|
import { ImageRGBADataLoader } from "../../../asset/loaders/image/ImageRGBADataLoader.js";
|
|
10
9
|
import { StandardFrameBuffers } from "../../StandardFrameBuffers.js";
|
|
11
10
|
import { assert } from "../../../../core/assert.js";
|
|
@@ -209,15 +208,7 @@ export class ParticleEmitterSystem extends System {
|
|
|
209
208
|
|
|
210
209
|
graphicsEngine.on.preRender.add(preRenderHook);
|
|
211
210
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
am.promise('data/database/particles/data.json', GameAssetType.JSON)
|
|
215
|
-
.then(asset => {
|
|
216
|
-
const particleSet = asset.create();
|
|
217
|
-
|
|
218
|
-
return library.load(particleSet);
|
|
219
|
-
})
|
|
220
|
-
.then(readyCallback, errorCallback);
|
|
211
|
+
this.library.load_from_registry_file('data/database/particles/data.json').then(readyCallback, errorCallback);
|
|
221
212
|
}
|
|
222
213
|
|
|
223
214
|
shutdown(entityManager, readyCallback, errorCallback) {
|
|
@@ -10,8 +10,8 @@ import Signal from "../../../../core/events/signal/Signal.js";
|
|
|
10
10
|
import { assert } from "../../../../core/assert.js";
|
|
11
11
|
import { DataType } from "../../../../core/collection/table/DataType.js";
|
|
12
12
|
import { DataType2TypedArrayConstructorMapping } from "../../../../core/collection/table/DataType2TypedArrayConstructorMapping.js";
|
|
13
|
-
import { invokeObjectClone } from "../../../../core/model/ObjectUtils.js";
|
|
14
13
|
import { AbstractTextureAtlas } from "./AbstractTextureAtlas.js";
|
|
14
|
+
import { invokeObjectClone } from "../../../../core/model/object/invokeObjectClone.js";
|
|
15
15
|
|
|
16
16
|
export class TextureAtlas extends AbstractTextureAtlas {
|
|
17
17
|
/**
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"productName": "Meep",
|
|
6
6
|
"description": "production-ready JavaScript game engine based on Entity Component System Architecture",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.33.
|
|
8
|
+
"version": "2.33.51",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @template V
|
|
3
|
-
* @param {Object<V>} object
|
|
4
|
-
* @param {V} value
|
|
5
|
-
* @returns {string}
|
|
6
|
-
*/
|
|
7
|
-
import { assert } from "../assert.js";
|
|
8
|
-
import { extractFunctionBody } from "../function/extractFunctionBody.js";
|
|
9
|
-
import { compareArrays } from "../primitives/array/compareArrays.js";
|
|
10
|
-
import { compareBooleans } from "../primitives/boolean/compareBooleans.js";
|
|
11
|
-
import { compareNumbers } from "../primitives/numbers/compareNumbers.js";
|
|
12
|
-
import { compareStrings } from "../primitives/strings/compareStrings.js";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
*
|
|
16
|
-
* @param {*} a
|
|
17
|
-
* @param {*} b
|
|
18
|
-
* @returns {number}
|
|
19
|
-
*/
|
|
20
|
-
export function compareValues(a, b) {
|
|
21
|
-
if (a === b) {
|
|
22
|
-
return 0;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const aType = typeof a;
|
|
26
|
-
const bType = typeof b;
|
|
27
|
-
|
|
28
|
-
if (aType !== bType) {
|
|
29
|
-
return compareStrings(aType, bType);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (aType === "string") {
|
|
33
|
-
return compareStrings(a, b);
|
|
34
|
-
} else if (aType === "number") {
|
|
35
|
-
return compareNumbers(a, b);
|
|
36
|
-
} else if (aType === "boolean") {
|
|
37
|
-
return compareBooleans(a, b);
|
|
38
|
-
} else if (aType === "function") {
|
|
39
|
-
return compareStrings(extractFunctionBody(a), extractFunctionBody(b));
|
|
40
|
-
} else if (aType === "object") {
|
|
41
|
-
if (a === null) {
|
|
42
|
-
if (b !== null) {
|
|
43
|
-
return -1;
|
|
44
|
-
} else {
|
|
45
|
-
return 0;
|
|
46
|
-
}
|
|
47
|
-
} else if (b === null) {
|
|
48
|
-
return 1;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
52
|
-
return compareArrays(a, b, compareValues);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const aKeys = Object.keys(a);
|
|
56
|
-
const bKeys = Object.keys(b);
|
|
57
|
-
|
|
58
|
-
const dKeys = compareArrays(aKeys, bKeys, compareStrings);
|
|
59
|
-
|
|
60
|
-
if (dKeys !== 0) {
|
|
61
|
-
return dKeys;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
for (let p in a) {
|
|
65
|
-
const d = compareValues(a[p], b[p]);
|
|
66
|
-
|
|
67
|
-
if (d !== 0) {
|
|
68
|
-
return d;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return 0;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* @template V
|
|
78
|
-
* @param {Object<V>} object
|
|
79
|
-
* @param {string} key
|
|
80
|
-
* @returns {V}
|
|
81
|
-
* @throws {Error} if such key does not exist
|
|
82
|
-
*/
|
|
83
|
-
export function validatedObjectValueByKey(object, key) {
|
|
84
|
-
|
|
85
|
-
assert.typeOf(key, 'string', 'key');
|
|
86
|
-
|
|
87
|
-
const value = object[key];
|
|
88
|
-
|
|
89
|
-
if (value === undefined) {
|
|
90
|
-
throw new Error(`Unknown key '${key}', valid keys: [${Object.keys(object).join(', ')}]`);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return value;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* @template T
|
|
98
|
-
* @param {T} object
|
|
99
|
-
* @return {T}
|
|
100
|
-
*/
|
|
101
|
-
export function invokeObjectClone(object) {
|
|
102
|
-
return object.clone();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* @template S,R
|
|
108
|
-
* @param {S} source
|
|
109
|
-
* @return {R}
|
|
110
|
-
*/
|
|
111
|
-
export function objectShallowCopyByOwnKeys(source) {
|
|
112
|
-
const keys = Reflect.ownKeys(source);
|
|
113
|
-
|
|
114
|
-
const result = {};
|
|
115
|
-
const n = keys.length;
|
|
116
|
-
for (let i = 0; i < n; i++) {
|
|
117
|
-
const key = keys[i];
|
|
118
|
-
result[key] = source[key];
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return result;
|
|
122
|
-
}
|