Skip to content

Commit

Permalink
chore(feature-detector): renames findDependencies into findGlobals
Browse files Browse the repository at this point in the history
  • Loading branch information
feugy committed Jan 16, 2023
1 parent 3a4e146 commit b699a76
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 59 deletions.
7 changes: 2 additions & 5 deletions docs/pages/packages/feature-detector.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ In the code snippet bellow, we're checking:
2. globals used, that are not provided by the Edge Runtime

```ts
import {
hasEdgeSignature,
findDependencies,
} from '@edge-runtime/feature-detector'
import { hasEdgeSignature, findGlobals } from '@edge-runtime/feature-detector'

const sourceFilePath = './test.js' // could be TypeScript as well. Must be in current working directory

Expand All @@ -59,7 +56,7 @@ if (hasEdgeSignature(sourceFilePath)) {
console.log(`${sourcefilePath} can run on the edge`)
}
// 2
console.log(findDependencies(sourceFilePath).globals)
console.log(findGlobals(sourceFilePath))
```

## API
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
import { Project, ts } from 'ts-morph'
import { dirname, resolve } from 'path'
import { Project, SourceFile, ts } from 'ts-morph'
import { buildProject } from './utils/project'

/**
* Find the list of globals used by source files in the provided project.
* Analyzed source files can be filtered by provided a list of glob patterns (default to all TypeScript and JavaScript files, excluding type definitions)
*/
export function findDependencies(
export function findGlobals(
sourcePath: string,
project: Project = buildProject()
): {
globals: string[]
} {
): string[] {
const globals = new Set<string>()
const sourceFile = project.addSourceFileAtPath(sourcePath)
const program = project.getProgram().compilerObject
const sourceFile = project.getSourceFileOrThrow(sourcePath)
addFileGlobals(sourceFile, globals)
for (const imported of sourceFile.getImportDeclarations()) {
console.log(imported.getModuleSpecifierSourceFileOrThrow())
const importedFile = project.getSourceFile(
resolve(
dirname(sourceFile.getFilePath()),
imported.getModuleSpecifierValue()
)
)
if (importedFile) {
addFileGlobals(importedFile, globals)
}
}
return [...globals]
}

function addFileGlobals(sourceFile: SourceFile, globals: Set<string>) {
const program = sourceFile.getProject().getProgram().compilerObject
const diagnostics = program.getSemanticDiagnostics(sourceFile.compilerNode)
for (const { code, messageText } of diagnostics) {
if (
Expand All @@ -33,5 +49,4 @@ export function findDependencies(
}
}
}
return { globals: [...globals] }
}
2 changes: 1 addition & 1 deletion packages/feature-detector/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './find-dependencies'
export * from './find-globals'
export * from './has-edge-signature'
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { readFile } from 'fs/promises'
import { join } from 'path'
import { Project, ScriptKind, SourceFile, SyntaxKind } from 'ts-morph'
import { findDependencies } from '../src'
import { Project, SourceFile } from 'ts-morph'
import { findGlobals } from '../src'
import { buildProject } from '../src/utils/project'

const fixtureFolder = join(__dirname, 'fixtures')

describe.each([
{ title: 'for JavaScript' },
{ title: 'for TypeScript', isTS: true },
])('findDependencies() $title', ({ isTS }) => {
])('findGlobals() $title', ({ isTS }) => {
let project: Project
let file: SourceFile

Expand All @@ -23,9 +22,10 @@ describe.each([
__filename
process.env['TEST']
`)
expect(findDependencies(file.getFilePath(), project)).toEqual({
globals: ['__filename', 'process'],
})
expect(findGlobals(file.getFilePath(), project)).toEqual([
'__filename',
'process',
])
})

it('returns globals variable with typeof', () => {
Expand All @@ -34,18 +34,14 @@ describe.each([
console.log('in node')
}
`)
expect(findDependencies(file.getFilePath(), project)).toEqual({
globals: ['process'],
})
expect(findGlobals(file.getFilePath(), project)).toEqual(['process'])
})

it('returns globals variables used as parameters', () => {
file.replaceWithText(`
console.log('in node', __dirname)
`)
expect(findDependencies(file.getFilePath(), project)).toEqual({
globals: ['__dirname'],
})
expect(findGlobals(file.getFilePath(), project)).toEqual(['__dirname'])
})

it('returns globals variables in instructions', () => {
Expand All @@ -54,9 +50,10 @@ describe.each([
for (const key in exports) {}
}
`)
expect(findDependencies(file.getFilePath(), project)).toEqual({
globals: ['__dirname', 'exports'],
})
expect(findGlobals(file.getFilePath(), project)).toEqual([
'__dirname',
'exports',
])
})

it('returns globals used with static methods', () => {
Expand All @@ -65,23 +62,17 @@ describe.each([
return Response.redirect(Buffer.from('ok'))
}
`)
expect(findDependencies(file.getFilePath(), project)).toEqual({
globals: ['Buffer'],
})
expect(findGlobals(file.getFilePath(), project)).toEqual(['Buffer'])
})

it('returns globals used with new operator', () => {
file.replaceWithText(`new Buffer(['o', 'k'])`)
expect(findDependencies(file.getFilePath(), project)).toEqual({
globals: ['Buffer'],
})
expect(findGlobals(file.getFilePath(), project)).toEqual(['Buffer'])
})

it('returns globals used as properties', () => {
file.replaceWithText(`Buffer.poolSize`)
expect(findDependencies(file.getFilePath(), project)).toEqual({
globals: ['Buffer'],
})
expect(findGlobals(file.getFilePath(), project)).toEqual(['Buffer'])
})

it('returns globals used as functions', () => {
Expand All @@ -90,19 +81,19 @@ describe.each([
$('.do-you[remember="the time"]')
})
`)
expect(findDependencies(file.getFilePath(), project)).toEqual({
globals: ['setImmediate', '$'],
})
expect(findGlobals(file.getFilePath(), project)).toEqual([
'setImmediate',
'$',
])
})

it('ignores known DOM globals', () => {
file.replaceWithText(`
console.log(JSON.stringify({ msg: btoa('hi') }))
const controller = new AbortController()
`)
expect(findDependencies(file.getFilePath(), project)).toEqual({
globals: [], // no console, JSON, btoa, AbortController
})
// no console, JSON, btoa, AbortController
expect(findGlobals(file.getFilePath(), project)).toEqual([])
})

it('dedupes identified globals', () => {
Expand All @@ -115,24 +106,20 @@ describe.each([
}
}
`)
expect(findDependencies(file.getFilePath(), project)).toEqual({
globals: ['Buffer'],
})
expect(findGlobals(file.getFilePath(), project)).toEqual(['Buffer'])
})

it('find globals from 3rd party code', async () => {
it('finds globals from 3rd party code', async () => {
const file = project.addSourceFileAtPath(
join(fixtureFolder, 'with-axios.out.js')
)
expect(findDependencies(file.getFilePath(), project)).toEqual({
globals: [
'navigator',
'window',
'document',
'Buffer',
'XMLHttpRequest',
'process',
],
})
expect(findGlobals(file.getFilePath(), project)).toEqual([
'navigator',
'window',
'document',
'Buffer',
'XMLHttpRequest',
'process',
])
})
})

0 comments on commit b699a76

Please sign in to comment.