Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitecf3de1

Browse files
prevent merging into supertype field policies (#12750)
Co-authored-by: Jerel Miller <jerelmiller@gmail.com>Co-authored-by: jerelmiller <565661+jerelmiller@users.noreply.github.com>
1 parent0bcd2f4 commitecf3de1

File tree

4 files changed

+119
-29
lines changed

4 files changed

+119
-29
lines changed

‎.changeset/great-suns-cover.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@apollo/client":patch
3+
---
4+
5+
Prevent field policies from overwriting/merging into supertype field policies.

‎.size-limits.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"dist/apollo-client.min.cjs":42661,
3-
"import { ApolloClient, InMemoryCache, HttpLink } from\"@apollo/client\" (production)":34714
2+
"dist/apollo-client.min.cjs":42669,
3+
"import { ApolloClient, InMemoryCache, HttpLink } from\"@apollo/client\" (production)":34723
44
}

‎src/cache/inmemory/__tests__/policies.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,81 @@ describe("type policies", function () {
661661
).toBe('DeathAdder:{"tagId":"LethalAbacus666"}');
662662
});
663663

664+
it("specific field policies will not override supertype policies",()=>{
665+
constcache=newInMemoryCache({
666+
typePolicies:{
667+
Named:{
668+
fields:Object.freeze({
669+
name:Object.freeze({
670+
read(existing:any){
671+
returnexisting+" (Named)";
672+
},
673+
}),
674+
}),
675+
},
676+
Person:{
677+
fields:{
678+
name:{
679+
read(existing){
680+
returnexisting+" (Person)";
681+
},
682+
},
683+
},
684+
},
685+
},
686+
possibleTypes:{
687+
Named:["Person","Pet"],
688+
},
689+
});
690+
constquery=gql`
691+
{
692+
me {
693+
__typename
694+
id
695+
name
696+
pets {
697+
__typename
698+
id
699+
name
700+
}
701+
}
702+
}
703+
`;
704+
cache.writeQuery({
705+
query,
706+
data:{
707+
me:{
708+
__typename:"Person",
709+
id:23,
710+
name:"John Doe",
711+
pets:[
712+
{
713+
__typename:"Pet",
714+
id:1,
715+
name:"Fido",
716+
},
717+
{
718+
__typename:"Pet",
719+
id:2,
720+
name:"Whiskers",
721+
},
722+
],
723+
},
724+
},
725+
});
726+
expect(cache.readQuery({ query})).toEqual({
727+
me:{
728+
__typename:"Person",
729+
id:23,
730+
name:"John Doe (Person)",
731+
pets:[
732+
{__typename:"Pet",id:1,name:"Fido (Named)"},
733+
{__typename:"Pet",id:2,name:"Whiskers (Named)"},
734+
],
735+
},
736+
});
737+
});
738+
664739
it("typePolicies can be inherited from supertypes with fuzzy possibleTypes",()=>{
665740
constcache=newInMemoryCache({
666741
possibleTypes:{

‎src/cache/inmemory/policies.ts

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -281,17 +281,20 @@ export type PossibleTypesMap = {
281281
[supertype:string]:string[];
282282
};
283283

284+
typeInternalFieldPolicy={
285+
typename:string;
286+
keyFn?:KeyArgsFunction;
287+
read?:FieldReadFunction<any>;
288+
merge?:FieldMergeFunction<any>;
289+
};
290+
284291
exportclassPolicies{
285292
privatetypePolicies:{
286293
[__typename:string]:{
287294
keyFn?:KeyFieldsFunction;
288295
merge?:FieldMergeFunction<any>;
289296
fields:{
290-
[fieldName:string]:{
291-
keyFn?:KeyArgsFunction;
292-
read?:FieldReadFunction<any>;
293-
merge?:FieldMergeFunction<any>;
294-
};
297+
[fieldName:string]:InternalFieldPolicy;
295298
};
296299
};
297300
}=Object.create(null);
@@ -440,7 +443,11 @@ export class Policies {
440443
});
441444
}
442445

443-
privateupdateTypePolicy(typename:string,incoming:TypePolicy){
446+
privateupdateTypePolicy(
447+
typename:string,
448+
incoming:TypePolicy,
449+
existingFieldPolicies:Record<string,InternalFieldPolicy>
450+
){
444451
constexisting=this.getTypePolicy(typename);
445452
const{ keyFields, fields}=incoming;
446453

@@ -476,7 +483,17 @@ export class Policies {
476483

477484
if(fields){
478485
Object.keys(fields).forEach((fieldName)=>{
479-
constexisting=this.getFieldPolicy(typename,fieldName,true)!;
486+
letexisting=existingFieldPolicies[fieldName]as
487+
|InternalFieldPolicy
488+
|undefined;
489+
// Field policy inheritance is atomic/shallow: you can't inherit a
490+
// field policy and then override just its read function, since read
491+
// and merge functions often need to cooperate, so changing only one
492+
// of them would be a recipe for inconsistency.
493+
// So here we avoid merging an inherited field policy with an updated one.
494+
if(!existing||existing?.typename!==typename){
495+
existing=existingFieldPolicies[fieldName]={ typename};
496+
}
480497
constincoming=fields[fieldName];
481498

482499
if(typeofincoming==="function"){
@@ -623,7 +640,11 @@ export class Policies {
623640
// Merge the pending policies into this.typePolicies, in the order they
624641
// were originally passed to addTypePolicy.
625642
inbox.splice(0).forEach((policy)=>{
626-
this.updateTypePolicy(typename,policy);
643+
this.updateTypePolicy(
644+
typename,
645+
policy,
646+
this.typePolicies[typename].fields
647+
);
627648
});
628649
}
629650

@@ -632,21 +653,10 @@ export class Policies {
632653

633654
privategetFieldPolicy(
634655
typename:string|undefined,
635-
fieldName:string,
636-
createIfMissing:boolean
637-
):
638-
|{
639-
keyFn?:KeyArgsFunction;
640-
read?:FieldReadFunction<any>;
641-
merge?:FieldMergeFunction<any>;
642-
}
643-
|undefined{
656+
fieldName:string
657+
):InternalFieldPolicy|undefined{
644658
if(typename){
645-
constfieldPolicies=this.getTypePolicy(typename).fields;
646-
return(
647-
fieldPolicies[fieldName]||
648-
(createIfMissing&&(fieldPolicies[fieldName]=Object.create(null)))
649-
);
659+
returnthis.getTypePolicy(typename).fields[fieldName];
650660
}
651661
}
652662

@@ -760,13 +770,13 @@ export class Policies {
760770
}
761771

762772
publichasKeyArgs(typename:string|undefined,fieldName:string){
763-
constpolicy=this.getFieldPolicy(typename,fieldName,false);
773+
constpolicy=this.getFieldPolicy(typename,fieldName);
764774
return!!(policy&&policy.keyFn);
765775
}
766776

767777
publicgetStoreFieldName(fieldSpec:FieldSpecifier):string{
768778
const{ typename, fieldName}=fieldSpec;
769-
constpolicy=this.getFieldPolicy(typename,fieldName,false);
779+
constpolicy=this.getFieldPolicy(typename,fieldName);
770780
letstoreFieldName:Exclude<ReturnType<KeyArgsFunction>,KeySpecifier>;
771781

772782
letkeyFn=policy&&policy.keyFn;
@@ -835,7 +845,7 @@ export class Policies {
835845
objectOrReference,
836846
storeFieldName
837847
);
838-
constpolicy=this.getFieldPolicy(options.typename,fieldName,false);
848+
constpolicy=this.getFieldPolicy(options.typename,fieldName);
839849
constread=policy&&policy.read;
840850

841851
if(read){
@@ -866,7 +876,7 @@ export class Policies {
866876
typename:string|undefined,
867877
fieldName:string
868878
):FieldReadFunction|undefined{
869-
constpolicy=this.getFieldPolicy(typename,fieldName,false);
879+
constpolicy=this.getFieldPolicy(typename,fieldName);
870880
returnpolicy&&policy.read;
871881
}
872882

@@ -878,7 +888,7 @@ export class Policies {
878888
letpolicy:
879889
|Policies["typePolicies"][string]
880890
|Policies["typePolicies"][string]["fields"][string]
881-
|undefined=this.getFieldPolicy(parentTypename,fieldName,false);
891+
|undefined=this.getFieldPolicy(parentTypename,fieldName);
882892
letmerge=policy&&policy.merge;
883893
if(!merge&&childTypename){
884894
policy=this.getTypePolicy(childTypename);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp