Skip to content

Commit

Permalink
Implement getting nested dictionaries in Mixed.
Browse files Browse the repository at this point in the history
  • Loading branch information
elle-j committed Feb 1, 2024
1 parent 08facb4 commit 5005afe
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 14 deletions.
2 changes: 2 additions & 0 deletions packages/realm/bindgen/js_opt_in_spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ classes:
- make_ssl_verify_callback
- get_mixed_type
- get_mixed_element_type
- get_mixed_element_type_from_dict

LogCategoryRef:
methods:
Expand Down Expand Up @@ -317,6 +318,7 @@ classes:
- get_obj
- get_any
- get_list
- get_dictionary
- sort_by_names
- snapshot
- max
Expand Down
2 changes: 1 addition & 1 deletion packages/realm/bindgen/vendor/realm-core
18 changes: 14 additions & 4 deletions packages/realm/src/Dictionary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

import {
AssertionError,
Collection,
Expand All @@ -41,14 +42,23 @@ export type DictionaryChangeSet = {
};
export type DictionaryChangeCallback = (dictionary: Dictionary, changes: DictionaryChangeSet) => void;

/**
* Helpers for getting and setting dictionary entries, as well as
* converting the values to and from their binding representations.
* @internal
*/
export type DictionaryHelpers = TypeHelpers & {
get?(dictionary: binding.Dictionary, key: string): unknown;
};

const DEFAULT_PROPERTY_DESCRIPTOR: PropertyDescriptor = { configurable: true, enumerable: true };
const PROXY_HANDLER: ProxyHandler<Dictionary> = {
get(target, prop, receiver) {
const value = Reflect.get(target, prop, receiver);
if (typeof value === "undefined" && typeof prop === "string") {
const internal = target[INTERNAL];
const fromBinding = target[HELPERS].fromBinding;
return fromBinding(internal.tryGetAny(prop));
const { get: customGet, fromBinding } = target[HELPERS];
return fromBinding(customGet ? customGet(internal, prop) : internal.tryGetAny(prop));
} else {
return value;
}
Expand Down Expand Up @@ -111,7 +121,7 @@ export class Dictionary<T = unknown> extends Collection<string, T, [string, T],
* Create a `Results` wrapping a set of query `Results` from the binding.
* @internal
*/
constructor(realm: Realm, internal: binding.Dictionary, helpers: TypeHelpers) {
constructor(realm: Realm, internal: binding.Dictionary, helpers: DictionaryHelpers) {
if (arguments.length === 0 || !(internal instanceof binding.Dictionary)) {
throw new IllegalConstructorError("Dictionary");
}
Expand Down Expand Up @@ -182,7 +192,7 @@ export class Dictionary<T = unknown> extends Collection<string, T, [string, T],
private declare [INTERNAL]: binding.Dictionary;

/** @internal */
private declare [HELPERS]: TypeHelpers;
private declare [HELPERS]: DictionaryHelpers;

/** @ts-expect-error We're exposing methods in the end-users namespace of keys */
[key: string]: T;
Expand Down
6 changes: 5 additions & 1 deletion packages/realm/src/OrderedCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ export type CollectionChangeCallback<T = unknown, EntryType extends [unknown, un
changes: CollectionChangeSet,
) => void;

/** @internal */
/**
* Helpers for getting and setting ordered collection items, as well
* as converting the values to and from their binding representations.
* @internal
*/
export type OrderedCollectionHelpers = TypeHelpers & {
get(results: binding.Results, index: number): unknown;
};
Expand Down
31 changes: 23 additions & 8 deletions packages/realm/src/TypeHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
ClassHelpers,
Collection,
Dictionary,
DictionaryHelpers,
INTERNAL,
List,
ObjCreator,
Expand Down Expand Up @@ -168,19 +169,15 @@ function mixedFromBinding(options: TypeOptions, value: binding.MixedArg): unknow
const { wrapObject } = getClassHelpers(value.tableKey);
return wrapObject(linkedObj);
} else if (value instanceof binding.List) {
return new List(realm, value, getCollectionHelpersForMixed(realm, options));
return new List(realm, value, getListHelpersForMixed(realm, options));
} else if (value instanceof binding.Dictionary) {
const typeHelpers: TypeHelpers<Realm.Mixed> = {
toBinding: mixedToBinding.bind(null, realm.internal),
fromBinding: mixedFromBinding.bind(null, options),
};
return new Dictionary(realm, value, typeHelpers);
return new Dictionary(realm, value, getDictionaryHelpersForMixed(realm, options));
} else {
return value;
}
}

function getCollectionHelpersForMixed(realm: Realm, options: TypeOptions) {
function getListHelpersForMixed(realm: Realm, options: TypeOptions) {
const helpers: OrderedCollectionHelpers = {
toBinding: mixedToBinding.bind(null, realm.internal),
fromBinding: mixedFromBinding.bind(null, options),
Expand All @@ -190,14 +187,32 @@ function getCollectionHelpersForMixed(realm: Realm, options: TypeOptions) {
return new List(realm, results.getList(index), helpers);
}
if (elementType === binding.MixedDataType.Dictionary) {
// TODO
return new Dictionary(realm, results.getDictionary(index), getDictionaryHelpersForMixed(realm, options));
}
return results.getAny(index);
},
};
return helpers;
}

function getDictionaryHelpersForMixed(realm: Realm, options: TypeOptions) {
const helpers: DictionaryHelpers = {
toBinding: mixedToBinding.bind(null, realm.internal),
fromBinding: mixedFromBinding.bind(null, options),
get(dictionary: binding.Dictionary, key: string) {
const elementType = binding.Helpers.getMixedElementTypeFromDict(dictionary, key);
if (elementType === binding.MixedDataType.List) {
return new List(realm, dictionary.getList(key), getListHelpersForMixed(realm, options));
}
if (elementType === binding.MixedDataType.Dictionary) {
return new Dictionary(realm, dictionary.getDictionary(key), helpers);
}
return dictionary.tryGetAny(key);
},
};
return helpers;
}

function defaultToBinding(value: unknown): binding.MixedArg {
return value as binding.MixedArg;
}
Expand Down

0 comments on commit 5005afe

Please sign in to comment.