From f1da831be922362521607a579c4d2b5eeeaeb56a Mon Sep 17 00:00:00 2001 From: Jon Wong Date: Wed, 7 Dec 2016 14:54:01 -0800 Subject: [PATCH] Strip duplicate fragments from AST MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While duplicate fragments will result in “warnings”, generating a document with duplicate fragments results in an invalid GraphQL document. This was recently introduced when fragment interpolation became the defacto way to insert fragments. See upstream issue [here](https://github.com/apollostack/graphql-tag/issues/27). This is not intended to go upstream (yet). --- index.js | 13 ++++++++++--- test.js | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 8a6e6293..889cc102 100644 --- a/index.js +++ b/index.js @@ -26,8 +26,8 @@ function resetCaches() { // check all fragment definitions, checking for name->source uniqueness var printFragmentWarnings = true; function checkFragments(ast) { - for (var i = 0; i < ast.definitions.length; i++) { - var fragmentDefinition = ast.definitions[i]; + const astFragmentMap = {}; + ast.definitions = ast.definitions.filter(fragmentDefinition => { if (fragmentDefinition.kind === 'FragmentDefinition') { var fragmentName = fragmentDefinition.name.value; var sourceKey = cacheKeyFromLoc(fragmentDefinition.loc); @@ -51,7 +51,14 @@ function checkFragments(ast) { fragmentSourceMap[fragmentName][sourceKey] = true; } } - } + + if (!astFragmentMap[sourceKey]) { + astFragmentMap[sourceKey] = true; + return true; + } else { + return false; + } + }); } function disableFragmentWarnings() { diff --git a/test.js b/test.js index 458dd64a..ad3eea20 100644 --- a/test.js +++ b/test.js @@ -282,6 +282,20 @@ const assert = require('chai').assert; }); }); + describe('fragment de-duplication', () => { + beforeEach(() => { + gqlRequire.resetCaches(); + }); + + it('strips duplicate fragments from the document', () => { + const frag1 = gql`fragment TestDuplicate on Bar { field }`; + const query1 = gql`{ bar { fieldOne ...TestDuplicate } } ${frag1} ${frag1}`; + + assert.equal(query1.definitions.length, 2); + assert.equal(query1.definitions[1].kind, 'FragmentDefinition') + }); + }); + // How to make this work? // it.only('can reference a fragment passed as a document via shorthand', () => { // const ast = gql`