Repository: gatsbyjs/gatsby
File: packages/gatsby-source-contentful/src/extend-node-type.js (JavaScript)

Code before:
      },
      references: {
        type: [`ContentfulReference`],
        async resolve(source, args, context, info) {
          const parent = await context.nodeModel.findRootNodeAncestor(source)

          const rawReferences = { Entry: new Set(), Asset: new Set() }

          // Locate all Contentful Links within the rich text data
          const traverse = obj => {
            for (let k in obj) {
              const value = obj[k]
              if (value && value.sys && value.sys.type === `Link`) {
                rawReferences[value.sys.linkType].add(value.sys.contentful_id)
              } else if (value && typeof value === `object`) {
                traverse(value)
              }
            }
          }

          traverse(JSON.parse(source.raw))

          if (!rawReferences.Entry.size && !rawReferences.Asset.size) {
            return []
          }

          const rawEntries = Array.from(rawReferences.Entry)
          const rawAssets = Array.from(rawReferences.Asset)

          // Query for referenced nodes
          const resultEntries = await context.nodeModel.runQuery({
            query: {
              filter: {
                contentful_id: { in: rawEntries },
              },
            },
            type: `ContentfulEntry`,
          })

          const resultAssets = await context.nodeModel.runQuery({
            query: {
              filter: {
                contentful_id: { in: rawAssets },
              },
            },
            type: `ContentfulAsset`,
          })

          // Localize results
          const nodeLocale = parent.node_locale


Review comment (suggestion):
This implies this `.raw` field can't have circular references. Is that correct? I've seen many Contentful models with circular references, I'm just not sure where/how they manifest, so this could be perfectly safe. (`JSON.parse` would never cause circular refs so the `traverse` call is safe here)

Code after:
        deprecationReason: `This field is deprecated, please use 'raw' instead. @todo add link to migration steps.`,
      },
      json: {
        type: GraphQLString,
        deprecationReason: `This field is deprecated, please use 'raw' instead. @todo add link to migration steps.`,
      },
      references: {
        type: [`ContentfulReference`],
        async resolve(source, args, context, info) {
          const parent = await context.nodeModel.findRootNodeAncestor(source)

          const rawReferences = { Entry: new Set(), Asset: new Set() }

          // Locate all Contentful Links within the rich text data
          const traverse = obj => {
            for (let k in obj) {
              const value = obj[k]
              if (value && value.sys && value.sys.type === `Link`) {
                rawReferences[value.sys.linkType].add(value.sys.contentful_id)
              } else if (value && typeof value === `object`) {
                traverse(value)
              }
            }
          }

          traverse(JSON.parse(source.raw))

          if (!rawReferences.Entry.size && !rawReferences.Asset.size) {
            return []
          }

          const rawEntries = Array.from(rawReferences.Entry)
          const rawAssets = Array.from(rawReferences.Asset)

          // Query for referenced nodes
          const resultEntries = await context.nodeModel.runQuery({
            query: {
              filter: {
                contentful_id: { in: rawEntries },
              },
            },
            type: `ContentfulEntry`,
          })

          const resultAssets = await context.nodeModel.runQuery({
            query: {
              filter: {
                contentful_id: { in: rawAssets },
              },
            },
            type: `ContentfulAsset`,