Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dependency: packages/data-context/package.json to reduce vulnerabilities #28063

Merged
merged 12 commits into from
Oct 16, 2023
8 changes: 8 additions & 0 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
<!-- See the ../guides/writing-the-cypress-changelog.md for details on writing the changelog. -->
## 13.3.2

_Released 10/25/2023 (PENDING)_

**Dependency Updates:**

- Upgraded [`@babel/core`](https://www.npmjs.com/package/@babel/core) from `7.22.9` to `7.23.2` to address the [SNYK-JS-SEMVER-3247795](https://snyk.io/vuln/SNYK-JS-SEMVER-3247795) security vulnerability. Upgraded [`@babel/traverse`](https://www.npmjs.com/package/@babel/traverse) from `7.22.8` to `7.23.2` to address the [SNYK-JS-BABELTRAVERSE-5962462](https://snyk.io/vuln/SNYK-JS-BABELTRAVERSE-5962462) security vulnerability. Upgraded [`react-docgen`](https://www.npmjs.com/package/react-docgen) from `6.0.0-alpha.3` to `6.0.4` to address the [SNYK-JS-BABELTRAVERSE-5962462](https://snyk.io/vuln/SNYK-JS-BABELTRAVERSE-5962462) security vulnerability. Addressed in [#28063](https://github.com/cypress-io/cypress/pull/28063).

## 13.3.1

_Released 10/11/2023_
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ export function createTransformPluginsFileBabelPlugin (ast: PluginsConfigAst): b
babelTypes.blockStatement(statementToInject as babelTypes.Statement[] | babelTypes.Statement[]),
)

path.get('body').pushContainer('body' as never, ifComponentMode as babel.Node)
path.get('body').pushContainer('body' as never, ifComponentMode as never)

if (ast.requiresReturnConfig) {
path.get('body').pushContainer('body' as never, returnConfigAst)
path.get('body').pushContainer('body' as never, returnConfigAst as never)
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion packages/data-context/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"prettier": "2.5.1",
"randexp": "0.5.3",
"randomstring": "1.1.5",
"react-docgen": "6.0.0-alpha.3",
"react-docgen": "6.0.4",
"semver": "7.3.2",
"simple-git": "3.16.0",
"stringify-object": "^3.0.0",
Expand Down
32 changes: 25 additions & 7 deletions packages/data-context/src/actions/CodegenActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import type { DataContext } from '..'
import { SpecOptions, codeGenerator } from '../codegen'
import templates from '../codegen/templates'
import type { CodeGenType } from '../gen/graphcache-config.gen'
import { parse as parseReactComponent, resolver as reactDocgenResolvers } from 'react-docgen'
import { visit } from 'ast-types'

export interface ReactComponentDescriptor {
Expand All @@ -16,12 +15,29 @@ export interface ReactComponentDescriptor {
export class CodegenActions {
constructor (private ctx: DataContext) {}

async getReactComponentsFromFile (filePath: string): Promise<{components: ReactComponentDescriptor[], errored?: boolean }> {
async getReactComponentsFromFile (filePath: string, reactDocgen?: typeof import('react-docgen')): Promise<{components: ReactComponentDescriptor[], errored?: boolean }> {
try {
// this dance to get react-docgen is for now because react-docgen is a module and our typescript settings are set up to transpile to commonjs
// which will require the module, which will fail because it's an es module. This is a temporary workaround.
let actualReactDocgen = reactDocgen

if (!actualReactDocgen) {
actualReactDocgen = await import('react-docgen')
}

const { parse: parseReactComponent, builtinResolvers: reactDocgenResolvers } = actualReactDocgen

const src = await this.ctx.fs.readFile(filePath, 'utf8')

const exportResolver: ExportResolver = new Map()
let result = parseReactComponent(src, findAllWithLink(exportResolver), undefined, { parserOptions: { plugins: ['typescript', 'jsx'] } })
let result = parseReactComponent(src, {
resolver: findAllWithLink(exportResolver, reactDocgenResolvers),
babelOptions: {
parserOpts: {
plugins: ['typescript', 'jsx'],
},
},
})

// types appear to be incorrect in react-docgen@6.0.0-alpha.3
// TODO: update when 6.0.0 stable is out for fixed types.
Expand Down Expand Up @@ -166,9 +182,9 @@ export class CodegenActions {

type ExportResolver = Map<string, ReactComponentDescriptor>

function findAllWithLink (exportResolver: ExportResolver) {
return (ast: any, parser: any, importer: any) => {
visit(ast, {
function findAllWithLink (exportResolver: ExportResolver, reactDocgenResolvers: typeof import('react-docgen').builtinResolvers) {
return (fileState: any) => {
visit(fileState.ast, {
// export const Foo, export { Foo, Bar }, export function FooBar () { ... }
visitExportNamedDeclaration: (path) => {
const declaration = path.node.declaration as any
Expand Down Expand Up @@ -228,6 +244,8 @@ function findAllWithLink (exportResolver: ExportResolver) {
},
})

return reactDocgenResolvers.findAllExportedComponentDefinitions(ast, parser, importer)
const exportedDefinitionsResolver = new reactDocgenResolvers.FindExportedDefinitionsResolver()

return exportedDefinitionsResolver.resolve(fileState)
}
}
35 changes: 19 additions & 16 deletions packages/data-context/test/unit/actions/CodegenActions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,39 @@ import path from 'path'
describe('CodegenActions', () => {
let ctx: DataContext
let actions: CodegenActions
let reactDocgen: typeof import('react-docgen')

beforeEach(() => {
beforeEach(async () => {
sinon.restore()

ctx = createTestDataContext('open')

reactDocgen = await eval('import("react-docgen")')

actions = new CodegenActions(ctx)
})

context('getReactComponentsFromFile', () => {
const absolutePathPrefix = path.resolve('./test/unit/actions/project')

it('returns React components from file with class component', async () => {
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-class.jsx`)
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-class.jsx`, reactDocgen)

expect(components).to.have.length(1)
expect(components[0].exportName).to.equal('Counter')
expect(components[0].isDefault).to.equal(false)
})

it('returns React components from file with functional component', async () => {
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-functional.jsx`)
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-functional.jsx`, reactDocgen)

expect(components).to.have.length(1)
expect(components[0].exportName).to.equal('Counter')
expect(components[0].isDefault).to.equal(false)
})

it('returns only exported React components from file with functional components', async () => {
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-multiple-components.jsx`)
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-multiple-components.jsx`, reactDocgen)

expect(components).to.have.length(2)
expect(components[0].exportName).to.equal('CounterContainer')
Expand All @@ -48,51 +51,51 @@ describe('CodegenActions', () => {
})

it('returns React components from a tsx file', async () => {
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter.tsx`)
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter.tsx`, reactDocgen)

expect(components).to.have.length(1)
expect(components[0].exportName).to.equal('Counter')
expect(components[0].isDefault).to.equal(false)
})

it('returns React components that are exported by default', async () => {
let reactComponents = await (await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-default.tsx`)).components
let reactComponents = await (await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-default.tsx`, reactDocgen)).components

expect(reactComponents).to.have.length(1)
expect(reactComponents[0].exportName).to.equal('CounterDefault')
expect(reactComponents[0].isDefault).to.equal(true)

reactComponents = await (await actions.getReactComponentsFromFile(`${absolutePathPrefix}/default-anonymous.jsx`)).components
reactComponents = await (await actions.getReactComponentsFromFile(`${absolutePathPrefix}/default-anonymous.jsx`, reactDocgen)).components
expect(reactComponents).to.have.length(1)
expect(reactComponents[0].exportName).to.equal('Component')
expect(reactComponents[0].isDefault).to.equal(true)

reactComponents = await (await actions.getReactComponentsFromFile(`${absolutePathPrefix}/default-function.jsx`)).components
reactComponents = await (await actions.getReactComponentsFromFile(`${absolutePathPrefix}/default-function.jsx`, reactDocgen)).components
expect(reactComponents).to.have.length(1)
expect(reactComponents[0].exportName).to.equal('HelloWorld')
expect(reactComponents[0].isDefault).to.equal(true)

reactComponents = await (await actions.getReactComponentsFromFile(`${absolutePathPrefix}/default-class.jsx`)).components
reactComponents = await (await actions.getReactComponentsFromFile(`${absolutePathPrefix}/default-class.jsx`, reactDocgen)).components
expect(reactComponents).to.have.length(1)
expect(reactComponents[0].exportName).to.equal('HelloWorld')
expect(reactComponents[0].isDefault).to.equal(true)

reactComponents = await (await actions.getReactComponentsFromFile(`${absolutePathPrefix}/default-specifier.jsx`)).components
reactComponents = await (await actions.getReactComponentsFromFile(`${absolutePathPrefix}/default-specifier.jsx`, reactDocgen)).components
expect(reactComponents).to.have.length(1)
expect(reactComponents[0].exportName).to.equal('HelloWorld')
expect(reactComponents[0].isDefault).to.equal(true)
})

it('returns React components defined with arrow functions', async () => {
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-arrow-function.jsx`)
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-arrow-function.jsx`, reactDocgen)

expect(components).to.have.length(1)
expect(components[0].exportName).to.equal('Counter')
expect(components[0].isDefault).to.equal(false)
})

it('returns React components from a file with multiple separate export statements', async () => {
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-separate-exports.jsx`)
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-separate-exports.jsx`, reactDocgen)

expect(components).to.have.length(2)
expect(components[0].exportName).to.equal('CounterView')
Expand All @@ -102,7 +105,7 @@ describe('CodegenActions', () => {
})

it('returns React components that are exported and aliased', async () => {
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/export-alias.jsx`)
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/export-alias.jsx`, reactDocgen)

expect(components).to.have.length(1)
expect(components[0].exportName).to.equal('HelloWorld')
Expand All @@ -111,23 +114,23 @@ describe('CodegenActions', () => {

// TODO: "react-docgen" will resolve HOCs but our export detection does not. Can fall back to displayName here
it.skip('handles higher-order-components', async () => {
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-hoc.jsx`)
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/counter-hoc.jsx`, reactDocgen)

expect(components).to.have.length(1)
expect(components[0].exportName).to.equal('Counter')
expect(components[0].isDefault).to.equal(true)
})

it('correctly parses typescript files', async () => {
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/LoginForm.tsx`)
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/LoginForm.tsx`, reactDocgen)

expect(components).to.have.length(1)
expect(components[0].exportName).to.equal('LoginForm')
expect(components[0].isDefault).to.equal(true)
})

it('does not throw while parsing empty file', async () => {
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/empty.jsx`)
const { components } = await actions.getReactComponentsFromFile(`${absolutePathPrefix}/empty.jsx`, reactDocgen)

expect(components).to.have.length(0)
})
Expand Down
4 changes: 2 additions & 2 deletions packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"lint": "eslint --ext .js,.jsx,.ts,.tsx,.json, ."
},
"dependencies": {
"@babel/parser": "7.22.7",
"@babel/parser": "7.23.0",
"@benmalka/foxdriver": "0.4.1",
"@cypress/commit-info": "2.2.0",
"@cypress/get-windows-proxy": "1.6.2",
Expand Down Expand Up @@ -134,7 +134,7 @@
"widest-line": "3.1.0"
},
"devDependencies": {
"@babel/core": "7.22.9",
"@babel/core": "7.23.2",
"@babel/preset-env": "7.22.9",
"@cypress/debugging-proxy": "2.0.1",
"@cypress/sinon-chai": "2.9.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/web-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@packages/web-config",
"version": "0.0.0-development",
"devDependencies": {
"@babel/core": "7.22.9",
"@babel/core": "7.23.2",
"@babel/helper-define-map": "7.18.6",
"@babel/plugin-proposal-decorators": "7.22.7",
"@babel/plugin-transform-class-properties": "7.22.5",
Expand Down
2 changes: 1 addition & 1 deletion system-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"update:snapshots": "SNAPSHOT_UPDATE=1 npm run test"
},
"devDependencies": {
"@babel/core": "7.22.9",
"@babel/core": "7.23.2",
"@babel/preset-env": "7.22.9",
"@cypress/commit-info": "2.2.0",
"@cypress/debugging-proxy": "2.0.1",
Expand Down
Loading