From 6bf5a59a11d6c5f3dd652b695ff5b03d7528beea Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Tue, 18 Aug 2020 15:25:16 +0800 Subject: [PATCH] fix: do not throw when api.render is called from an anonymous function Fixes #4774 --- packages/@vue/cli/__tests__/Generator.spec.js | 20 +++++++++++++++++++ packages/@vue/cli/lib/GeneratorAPI.js | 13 +++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/packages/@vue/cli/__tests__/Generator.spec.js b/packages/@vue/cli/__tests__/Generator.spec.js index 5a97a794d1..8e169b3e43 100644 --- a/packages/@vue/cli/__tests__/Generator.spec.js +++ b/packages/@vue/cli/__tests__/Generator.spec.js @@ -531,6 +531,26 @@ test('api: render fs directory', async () => { expect(fs.readFileSync('/.vscode/config.json', 'utf-8')).toMatch('{}') }) +// #4774 +test('api: call render inside an anonymous function', async () => { + const generator = new Generator('/', { plugins: [ + { + id: 'test1', + apply: api => { + (() => { + api.render('./template', { m: 2 }) + })() + }, + options: { + n: 1 + } + } + ] }) + + await generator.generate() + expect(fs.readFileSync('/foo.js', 'utf-8')).toMatch('foo(1)') +}) + test('api: render object', async () => { const generator = new Generator('/', { plugins: [ { diff --git a/packages/@vue/cli/lib/GeneratorAPI.js b/packages/@vue/cli/lib/GeneratorAPI.js index f7ea81b638..30aefa11fd 100644 --- a/packages/@vue/cli/lib/GeneratorAPI.js +++ b/packages/@vue/cli/lib/GeneratorAPI.js @@ -457,7 +457,18 @@ function extractCallDir () { const obj = {} Error.captureStackTrace(obj) const callSite = obj.stack.split('\n')[3] - const fileName = callSite.match(/\s\((.*):\d+:\d+\)$/)[1] + + // the regexp for the stack when called inside a named function + const namedStackRegExp = /\s\((.*):\d+:\d+\)$/ + // the regexp for the stack when called inside an anonymous + const anonymousStackRegExp = /at (.*):\d+:\d+$/ + + let matchResult = callSite.match(namedStackRegExp) + if (!matchResult) { + matchResult = callSite.match(anonymousStackRegExp) + } + + const fileName = matchResult[1] return path.dirname(fileName) }