Skip to content

Commit

Permalink
Change "finalize" terminology to "drop", and other cleanup.
Browse files Browse the repository at this point in the history
  • Loading branch information
benjamn committed Apr 29, 2021
1 parent 25af660 commit 8948dae
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 53 deletions.
4 changes: 2 additions & 2 deletions src/cache/inmemory/__tests__/__snapshots__/policies.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ Object {
}
`;

exports[`type policies field policies custom finalize functions are called if merge function returns undefined 1`] = `
exports[`type policies field policies custom field policy drop functions are called if merge function returns undefined 1`] = `
Object {
"ROOT_QUERY": Object {
"__typename": "Query",
Expand Down Expand Up @@ -1243,7 +1243,7 @@ Object {
}
`;

exports[`type policies field policies custom finalize functions are called if merge function returns undefined 2`] = `
exports[`type policies field policies custom field policy drop functions are called if merge function returns undefined 2`] = `
Object {
"ROOT_QUERY": Object {
"__typename": "Query",
Expand Down
8 changes: 4 additions & 4 deletions src/cache/inmemory/__tests__/policies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1705,7 +1705,7 @@ describe("type policies", function () {
expect(cache.extract()).toMatchSnapshot();
});

describe("custom finalize functions", function () {
describe("custom field policy drop functions", function () {
const makeCache = (resolve: () => void) => new InMemoryCache({
typePolicies: {
Parent: {
Expand All @@ -1722,7 +1722,7 @@ describe("type policies", function () {
expect(incoming).toBe("initial value");
return storage.cached = "merged value";
},
finalize(existing, { storage }) {
drop(existing, { storage }) {
expect(existing).toBe("merged value");
expect(storage.cached).toBe(existing);
delete storage.cached;
Expand Down Expand Up @@ -1778,7 +1778,7 @@ describe("type policies", function () {

const evicted = cache.evict({
// Note that we're removing Query.parent, not directly removing
// Parent.deleteMe, but we still expect the Parent.deleteMe finalize
// Parent.deleteMe, but we still expect the Parent.deleteMe drop
// function to be called.
fieldName: "parent",
});
Expand Down Expand Up @@ -1842,7 +1842,7 @@ describe("type policies", function () {
] : incoming;
},

finalize(existing) {
drop(existing) {
expect(existing).toEqual([
{ __ref: 'Task:{"taskID":1}' },
{ __ref: 'Task:{"taskID":2}' },
Expand Down
75 changes: 38 additions & 37 deletions src/cache/inmemory/entityStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,48 +188,39 @@ export abstract class EntityStore implements NormalizedCache {
// that lead from the entity to the nested object within it.
this.group.assignPaths(dataId, merged);

// Run finalize functions for fields that are being removed. We consider
// only the fields of existing that are shared by incoming, since those
// are the only fields that could be changing.
if (existing) {
const context: ReadMergeModifyContext = { store: this };

const walk = (existing: StoreValue, incoming: StoreValue | undefined) => {
if (existing === incoming) return;

if (Array.isArray(existing)) {
(existing as StoreValue[]).forEach((child, i) => {
walk(
child,
incoming && Array.isArray(incoming)
? incoming[i]
: void 0,
);
// Collect objects and field names removed by this merge, so we can run
// drop functions configured for the fields that are about to removed
// (before we finally set this.data[dataId] = merged, below).
const drops: [StoreObject, string][] = [];

const walk = (exVal: StoreValue, inVal: StoreValue | undefined) => {
if (exVal === inVal) return;

if (Array.isArray(exVal)) {
(exVal as StoreValue[]).forEach((exChild, i) => {
const inChild = inVal && Array.isArray(inVal) ? inVal[i] : void 0;
walk(exChild, inChild);
});

} else if (storeValueIsStoreObject(existing)) {
Object.keys(existing).forEach(storeFieldName => {
const eChild = existing[storeFieldName];
const iChild = incoming && storeValueIsStoreObject(incoming)
? incoming[storeFieldName]
} else if (storeValueIsStoreObject(exVal)) {
Object.keys(exVal).forEach(storeFieldName => {
const exChild = exVal[storeFieldName];
const inChild = inVal && storeValueIsStoreObject(inVal)
? inVal[storeFieldName]
: void 0;

// Visit children before running finalizeField for eChild.
walk(eChild, iChild);
// Visit children before running dropField for eChild.
walk(exChild, inChild);

if (iChild === void 0) {
this.policies.finalizeField(
existing.__typename,
existing,
storeFieldName,
context,
);
if (inChild === void 0) {
drops.push([exVal, storeFieldName]);
}
});
}
};

// To detect field removals (in order to run finalize functions), we can
// To detect field removals (in order to run drop functions), we can
// restrict our attention to the incoming fields, since those are the
// top-level fields that might have changed.
Object.keys(incoming).forEach(storeFieldName => {
Expand All @@ -239,14 +230,22 @@ export abstract class EntityStore implements NormalizedCache {
walk(eChild, iChild);

if (iChild === void 0) {
this.policies.finalizeField(
existing.__typename,
existing,
drops.push([existing, storeFieldName]);
}
});

if (drops.length) {
const context: ReadMergeModifyContext = { store: this };

drops.forEach(([storeObject, storeFieldName]) => {
this.policies.dropField(
storeObject.__typename,
storeObject,
storeFieldName,
context,
);
}
});
});
}
}
}

Expand Down Expand Up @@ -670,11 +669,13 @@ class CacheGroup {
if (isReference(parentObjOrRef)) {
path.push(parentObjOrRef.__ref);
} else {
// See assignPathsAndFinalize to understand how this map is populated.
// See assignPaths to understand how this map is populated.
const assignedPath = this.paths.get(parentObjOrRef);
if (assignedPath) {
assignedPath.forEach(push);
} else {
// If we can't find a path for this object, use the object reference
// itself as a key.
path.push(parentObjOrRef);
}
}
Expand Down
20 changes: 10 additions & 10 deletions src/cache/inmemory/policies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export type FieldPolicy<
keyArgs?: KeySpecifier | KeyArgsFunction | false;
read?: FieldReadFunction<TExisting, TReadResult>;
merge?: FieldMergeFunction<TExisting, TIncoming> | boolean;
finalize?: FieldFinalizeFunction<TExisting>;
drop?: FieldDropFunction<TExisting>;
};

export type StorageType = Record<string, any>;
Expand Down Expand Up @@ -223,7 +223,7 @@ export type FieldMergeFunction<TExisting = any, TIncoming = TExisting> = (
options: FieldFunctionOptions,
) => SafeReadonly<TExisting>;

export type FieldFinalizeFunction<TExisting = any> = (
export type FieldDropFunction<TExisting = any> = (
existing: SafeReadonly<TExisting> | undefined,
options: FieldFunctionOptions,
) => void;
Expand Down Expand Up @@ -276,7 +276,7 @@ export class Policies {
keyFn?: KeyArgsFunction;
read?: FieldReadFunction<any>;
merge?: FieldMergeFunction<any>;
finalize?: FieldFinalizeFunction<any>;
drop?: FieldDropFunction<any>;
};
};
};
Expand Down Expand Up @@ -452,7 +452,7 @@ export class Policies {
if (typeof incoming === "function") {
existing.read = incoming;
} else {
const { keyArgs, read, merge, finalize } = incoming;
const { keyArgs, read, merge, drop } = incoming;

existing.keyFn =
// Pass false to disable argument-based differentiation of
Expand All @@ -472,8 +472,8 @@ export class Policies {

setMerge(existing, merge);

if (typeof finalize === "function") {
existing.finalize = finalize;
if (typeof drop === "function") {
existing.drop = drop;
}
}

Expand Down Expand Up @@ -779,17 +779,17 @@ export class Policies {
return existing;
}

public finalizeField(
public dropField(
typename: string | undefined,
objectOrReference: StoreObject | Reference,
storeFieldName: string,
context: ReadMergeModifyContext,
) {
const fieldName = fieldNameFromStoreName(storeFieldName);
const policy = this.getFieldPolicy(typename, fieldName, false);
const finalize = policy && policy.finalize;
if (finalize) {
finalize(
const drop = policy && policy.drop;
if (drop) {
drop(
context.store.getFieldValue(objectOrReference, storeFieldName),
// TODO Consolidate this code with similiar code in readField?
makeFieldFunctionOptions(
Expand Down

0 comments on commit 8948dae

Please sign in to comment.