Skip to content

Commit

Permalink
feat(toolkit/util): support the coercion of Map's from other JavaScri…
Browse files Browse the repository at this point in the history
…pt realms
  • Loading branch information
danielwiehl authored and simoneggler committed Feb 10, 2021
1 parent 26c422b commit aea4aa8
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 6 deletions.
5 changes: 5 additions & 0 deletions projects/scion/toolkit/util/src/dictionaries.util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ describe('Dictionaries', () => {
expect(Dictionaries.coerce(dictionary)).toBe(dictionary);
});

it('should return tuples as dictionary', () => {
const tuples = [['key1', 'value1'], ['key2', 'value2']];
expect(Dictionaries.coerce(tuples)).toEqual({key1: 'value1', key2: 'value2'});
});

it('should return `null` for a `null` value', () => {
expect(Dictionaries.coerce(null, {coerceNullOrUndefined: false})).toBeNull();
});
Expand Down
33 changes: 27 additions & 6 deletions projects/scion/toolkit/util/src/dictionaries.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,22 @@ export class Dictionaries {
}

if (dictionaryLike instanceof Map) {
return Array
.from(dictionaryLike.entries())
.reduce(
(obj: Dictionary, [key, value]: [string, any]): Dictionary => ({...obj, [key]: value}),
{},
);
return createDictionaryFromMap(dictionaryLike);
}

// Data sent from one JavaScript realm to another is serialized with the structured clone algorithm.
// Altought the algorithm supports the `Map` data type, a deserialized map object cannot be checked to be instance of `Map`.
// This is most likely because the serialization takes place in a different realm.
// @see https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
// @see http://man.hubwiz.com/docset/JavaScript.docset/Contents/Resources/Documents/developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm.html
try {
const map = new Map(dictionaryLike as any);
return createDictionaryFromMap(map);
}
catch {
// noop
}

return dictionaryLike;
}
}
Expand All @@ -47,3 +56,15 @@ export class Dictionaries {
export interface Dictionary<T = any> {
[key: string]: T;
}

function createDictionaryFromMap(map: Map<any, any>): Dictionary {
return Array
.from(map.entries())
.reduce(
(dictionary: Dictionary, [key, value]: [string, any]): Dictionary => {
dictionary[key] = value;
return dictionary;
},
{},
);
}
5 changes: 5 additions & 0 deletions projects/scion/toolkit/util/src/maps.util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ describe('Maps', () => {
expect(Maps.coerce(new Map(map))).toEqual(map);
});

it('should return tuples as map', () => {
const tuples = [['key1', 'value1'], ['key2', 'value2']];
expect(Maps.coerce(tuples)).toEqual(new Map().set('key1', 'value1').set('key2', 'value2'));
});

it('should return `null` for a `null` value', () => {
expect(Maps.coerce(null, {coerceNullOrUndefined: false})).toBeNull();
});
Expand Down
12 changes: 12 additions & 0 deletions projects/scion/toolkit/util/src/maps.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ export class Maps {
return mapLike;
}

// Data sent from one JavaScript realm to another is serialized with the structured clone algorithm.
// Altought the algorithm supports the `Map` data type, a deserialized map object cannot be checked to be instance of `Map`.
// This is most likely because the serialization takes place in a different realm.
// @see https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
// @see http://man.hubwiz.com/docset/JavaScript.docset/Contents/Resources/Documents/developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm.html
try {
return new Map(mapLike as any);
}
catch {
// noop
}

return Object
.entries(mapLike)
.reduce(
Expand Down

0 comments on commit aea4aa8

Please sign in to comment.