From 3959dd8826c5c2b17d48222a907a2d40910d1287 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Sat, 5 Nov 2022 00:08:08 +0100 Subject: [PATCH 1/2] error if the use client directive is not on the top --- packages/next/server/next-typescript.ts | 40 ++++++++++++++++++++----- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/packages/next/server/next-typescript.ts b/packages/next/server/next-typescript.ts index 3daf55ab116ca4e..c30ac7f3912466c 100644 --- a/packages/next/server/next-typescript.ts +++ b/packages/next/server/next-typescript.ts @@ -187,19 +187,33 @@ export function createTSPlugin(modules: { ) } - function getIsClientEntry(fileName: string) { + function getIsClientEntry( + fileName: string, + throwOnInvalidDirective?: boolean + ) { const source = info.languageService.getProgram()?.getSourceFile(fileName) if (source) { let isClientEntry = false let isDirective = true ts.forEachChild(source!, (node) => { - if (isClientEntry || !isDirective) return - - if (isDirective && ts.isExpressionStatement(node)) { - if (ts.isStringLiteral(node.expression)) { - if (node.expression.text === 'use client') { + if ( + ts.isExpressionStatement(node) && + ts.isStringLiteral(node.expression) + ) { + if (node.expression.text === 'use client') { + if (isDirective) { isClientEntry = true + } else { + if (throwOnInvalidDirective) { + throw { + messageText: + 'The `"use client"` directive must be put at the top of the file.', + start: node.expression.getStart(), + length: + node.expression.getEnd() - node.expression.getStart(), + } + } } } } else { @@ -473,7 +487,19 @@ export function createTSPlugin(modules: { const source = info.languageService.getProgram()?.getSourceFile(fileName) if (source) { - const isClientEntry = getIsClientEntry(fileName) + let isClientEntry = false + + try { + isClientEntry = getIsClientEntry(fileName, true) + } catch (e: any) { + prior.push({ + file: source, + category: ts.DiagnosticCategory.Error, + code: 71004, + ...e, + }) + isClientEntry = false + } ts.forEachChild(source!, (node) => { if (ts.isImportDeclaration(node)) { From 36ba7ba58c9ed69b76561e323481d50286a87fa1 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Sat, 5 Nov 2022 20:30:27 +0100 Subject: [PATCH 2/2] fix linter --- packages/next/server/next-typescript.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/next/server/next-typescript.ts b/packages/next/server/next-typescript.ts index c30ac7f3912466c..7625bc3b60bc212 100644 --- a/packages/next/server/next-typescript.ts +++ b/packages/next/server/next-typescript.ts @@ -206,13 +206,14 @@ export function createTSPlugin(modules: { isClientEntry = true } else { if (throwOnInvalidDirective) { - throw { + const e = { messageText: 'The `"use client"` directive must be put at the top of the file.', start: node.expression.getStart(), length: node.expression.getEnd() - node.expression.getStart(), } + throw e } } }