Skip to content

Commit

Permalink
fix(vercel#38743): config.runtime support template literal
Browse files Browse the repository at this point in the history
  • Loading branch information
SukkaW committed Jul 18, 2022
1 parent 653d5e7 commit 5bc2585
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 6 deletions.
32 changes: 32 additions & 0 deletions packages/next/build/analysis/extract-const-value.ts
Expand Up @@ -11,6 +11,7 @@ import type {
ObjectExpression,
RegExpLiteral,
StringLiteral,
TemplateLiteral,
VariableDeclaration,
} from '@swc/core'

Expand Down Expand Up @@ -124,6 +125,10 @@ function isRegExpLiteral(node: Node): node is RegExpLiteral {
return node.type === 'RegExpLiteral'
}

function isTemplateLiteral(node: Node): node is TemplateLiteral {
return node.type === 'TemplateLiteral'
}

class UnsupportedValueError extends Error {}
class NoSuchDeclarationError extends Error {}

Expand Down Expand Up @@ -191,6 +196,33 @@ function extractValue(node: Node): any {
}

return obj
} else if (isTemplateLiteral(node)) {
// e.g. `abc`
if (node.expressions.length !== 0) {
// TODO: should we add support for `${'e'}d${'g'}'e'`?
throw new UnsupportedValueError()
}

// When TemplateLiteral has 0 expressions, the length of quasis is always 1.
// Because when parsing TemplateLiteral, the parser yields the first quasi,
// then the first expression, then the next quasi, then the next expression, etc.,
// until the last quasi.
// Thus if there is no expression, the parser ends at the frst and also last quasis
const firstQuasis = node.quasis[0]

// A "cooked" interpretation where backslashes have special meaning, while a
// "raw" interpretation where backslashes do not have special meaning
// https://exploringjs.com/impatient-js/ch_template-literals.html#template-strings-cooked-vs-raw
const { cooked } = firstQuasis

// FIXME: The type definition of "cooked" and "raw" (from swc) are outdated.
// Both of them should be string | null | undefined, not StringLiteral.
// It is a temporary type guard to make TypeScript happy.
// https://github.com/swc-project/swc/issues/4501
if (cooked == null || typeof cooked === 'string') {
return cooked
}
return extractValue(cooked)
} else {
throw new UnsupportedValueError()
}
Expand Down
42 changes: 36 additions & 6 deletions test/e2e/switchable-runtime/index.test.ts
Expand Up @@ -115,11 +115,15 @@ describe('Switchable runtime', () => {
)
})

it('should build /api/hello as an api route with edge runtime', async () => {
const response = await fetchViaHTTP(context.appPort, '/api/hello')
const text = await response.text()
it('should build /api/hello and /api/edge as an api route with edge runtime', async () => {
let response = await fetchViaHTTP(context.appPort, '/api/hello')
let text = await response.text()
expect(text).toMatch(/Hello from .+\/api\/hello/)

response = await fetchViaHTTP(context.appPort, '/api/edge')
text = await response.text()
expect(text).toMatch(/Returned by Edge API Route .+\/api\/edge/)

if (!(global as any).isNextDeploy) {
const manifest = await readJson(
join(context.appDir, '.next/server/middleware-manifest.json')
Expand All @@ -137,6 +141,17 @@ describe('Switchable runtime', () => {
regexp: '^/api/hello$',
wasm: [],
},
'/api/edge': {
env: [],
files: [
'server/edge-runtime-webpack.js',
'server/pages/api/edge.js',
],
name: 'pages/api/hello',
page: '/api/edge',
regexp: '^/api/edge$',
wasm: [],
},
},
})
}
Expand Down Expand Up @@ -235,11 +250,15 @@ describe('Switchable runtime', () => {
})
})

it('should build /api/hello as an api route with edge runtime', async () => {
const response = await fetchViaHTTP(context.appPort, '/api/hello')
const text = await response.text()
it('should build /api/hello and /api/edge as an api route with edge runtime', async () => {
let response = await fetchViaHTTP(context.appPort, '/api/hello')
let text = await response.text()
expect(text).toMatch(/Hello from .+\/api\/hello/)

response = await fetchViaHTTP(context.appPort, '/api/edge')
text = await response.text()
expect(text).toMatch(/Returned by Edge API Route .+\/api\/edge/)

if (!(global as any).isNextDeploy) {
const manifest = await readJson(
join(context.appDir, '.next/server/middleware-manifest.json')
Expand All @@ -257,6 +276,17 @@ describe('Switchable runtime', () => {
regexp: '^/api/hello$',
wasm: [],
},
'/api/edge': {
env: [],
files: [
'server/edge-runtime-webpack.js',
'server/pages/api/edge.js',
],
name: 'pages/api/edge',
page: '/api/edge',
regexp: '^/api/edge$',
wasm: [],
},
},
})
}
Expand Down
7 changes: 7 additions & 0 deletions test/e2e/switchable-runtime/pages/api/edge.js
@@ -0,0 +1,7 @@
export default (req) => {
return new Response(`Returned by Edge API Route ${req.url}`)
}

export const config = {
runtime: `experimental-edge`,
}

0 comments on commit 5bc2585

Please sign in to comment.