From 1ffc0107e81d9196284a42dd450b8ff9d038b245 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Sat, 7 May 2022 13:30:08 +0800 Subject: [PATCH] fix: use `strip-literal` to strip string lterals (#8054) --- packages/vite/LICENSE.md | 29 ++++ packages/vite/package.json | 1 + .../src/node/__tests__/cleanString.spec.ts | Bin 4756 -> 0 bytes packages/vite/src/node/cleanString.ts | 145 ------------------ .../src/node/plugins/assetImportMetaUrl.ts | 4 +- packages/vite/src/node/plugins/css.ts | 2 +- packages/vite/src/node/plugins/html.ts | 4 +- .../src/node/plugins/workerImportMetaUrl.ts | 4 +- packages/vite/src/node/utils.ts | 4 + pnpm-lock.yaml | 8 + 10 files changed, 49 insertions(+), 152 deletions(-) delete mode 100644 packages/vite/src/node/__tests__/cleanString.spec.ts delete mode 100644 packages/vite/src/node/cleanString.ts diff --git a/packages/vite/LICENSE.md b/packages/vite/LICENSE.md index 30803708e30a76..80feb7f95c6941 100644 --- a/packages/vite/LICENSE.md +++ b/packages/vite/LICENSE.md @@ -3465,6 +3465,35 @@ Repository: chalk/strip-ansi --------------------------------------- +## strip-literal +License: MIT +By: Anthony Fu +Repository: git+https://github.com/antfu/strip-literal.git + +> MIT License +> +> Copyright (c) 2022 Anthony Fu +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. + +--------------------------------------- + ## to-regex-range License: MIT By: Jon Schlinkert, Rouven Weßling diff --git a/packages/vite/package.json b/packages/vite/package.json index 55c86878622111..b508842619033e 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -112,6 +112,7 @@ "source-map-js": "^1.0.2", "source-map-support": "^0.5.21", "strip-ansi": "^6.0.1", + "strip-literal": "^0.2.0", "terser": "^5.13.1", "tsconfck": "^1.2.2", "tslib": "^2.4.0", diff --git a/packages/vite/src/node/__tests__/cleanString.spec.ts b/packages/vite/src/node/__tests__/cleanString.spec.ts deleted file mode 100644 index 99ecbcaad444023d10ed467f6cd9b2794fa935bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4756 zcmc&&TW{h<6z(&>;>e0LHbgjVyDwE)sqNEBttvID`Vc4bULVgdHr(Vhw5>j>q99dtRn_6|U?$ zQ-ic-GV6`~a&OBt@6aXe3caIwaIOz zZov;=`T@2Ba4bIdu-|I-W1a~^a9k5;`>&T|JS0+-{|<(so8bl=CoX->6U}mGq2=jM z9@YxqK*%adC%hK{aWF>U)_#DBuv`3Ke5HcHE~qi67}q`oNs(6;7+07c2Z8MudX2P7 z<45tN*wS@h$Yx09&G6$nGH%Ypq}hZ6KBGw4d7qsi$A8u~S@~Ya)aXwBlt zDA?wj-s|CKszh%LBr9F&#G0}fOTv8^NHvKfH4(f#?0XXdMf&|Q(sd_rSkvM>3*vR8 z!GBp&6Y7)Py2Y+&Qy%JS`!wi`c<9ESLRGac#e>d>)?_t)i(+2b26-gxhFxivh&brQ z0`v1M%t9r}gaRdiJQ)ji=UL%`zfNh$@mMhPo;fZqSk)<)8)u%zly$M* z#_hWfHQU_AsEavDC$AfGZIGU5j5^C0M|~}0qWCOpYVu2&vv)sevdGLhE0%IH;D8T< z>u4QH6dcqF7>CViGefwD{wk&@IL{QJzltfi(dXIX7)~^%Ep&@CpGz$RNqbmidI@O` zrT&D?+YekgtBs~f z75jD>H84WYV*Ea&kO)vCQ(RRyA&d^5Z;-(6Sg&a+hTF|HK?8lt=k4rUnCt=^&UgO| zphU<~_6wnl`2d_8HJB%u-NpU{a>_Z5OQ(x0Z}30W(^uPeDjVs(KQ$Jo_0m*f zR_HlCzw36qOc!|m%L{$HHdc?H%PbhLO0(ES9_Y+YmHI#hQrw6eJh!}8*8~} z({BlwK;4@@p0%9{!u#8nGKRFhWc>MD;7<#Dsh|hWNf!!!3Zc$0ie|V2QB;lm-;44O zQ@-5etJ2J65a7ZvihOE(M~9o$omCG{>T#rAyoV?6apb*3@xxOTKaQf9nQw_!_AH8c z*Ra8T6A?iWE^)v9{nh1To~60D&-JES71sS;B6lQ8dnwzEvtRwUA9*7J-!<{-h&%Q- DgfAcj diff --git a/packages/vite/src/node/cleanString.ts b/packages/vite/src/node/cleanString.ts deleted file mode 100644 index d990ab75f15d7c..00000000000000 --- a/packages/vite/src/node/cleanString.ts +++ /dev/null @@ -1,145 +0,0 @@ -import type { RollupError } from 'rollup' -import { multilineCommentsRE, singlelineCommentsRE } from './utils' - -// bank on the non-overlapping nature of regex matches and combine all filters into one giant regex -// /`([^`\$\{\}]|\$\{(`|\g<1>)*\})*`/g can match nested string template -// but js not support match expression(\g<0>). so clean string template(`...`) in other ways. -const stringsRE = /"([^"\r\n]|(?<=\\)")*"|'([^'\r\n]|(?<=\\)')*'/g -const regexRE = /\/.*?(? ' '.repeat(s.length) -const stringBlankReplacer = (s: string) => - `${s[0]}${'\0'.repeat(s.length - 2)}${s[0]}` - -export function emptyString(raw: string): string { - let res = raw - .replace(cleanerRE, (s: string) => - s[0] === '/' ? blankReplacer(s) : stringBlankReplacer(s) - ) - .replace(regexRE, (s) => stringBlankReplacer(s)) - - let lastEnd = 0 - let start = 0 - while ((start = res.indexOf('`', lastEnd)) >= 0) { - let clean - ;[clean, lastEnd] = lexStringTemplateExpression(res, start) - res = replaceAt(res, start, lastEnd, clean) - } - - return res -} - -export function emptyCssComments(raw: string) { - return raw.replace(multilineCommentsRE, blankReplacer) -} - -const enum LexerState { - // template string - inTemplateString, - inInterpolationExpression, - inObjectExpression, - // strings - inSingleQuoteString, - inDoubleQuoteString, - // comments - inMultilineCommentsRE, - inSinglelineCommentsRE -} - -function replaceAt( - string: string, - start: number, - end: number, - replacement: string -): string { - return string.slice(0, start) + replacement + string.slice(end) -} - -/** - * lex string template and clean it. - */ -function lexStringTemplateExpression( - code: string, - start: number -): [string, number] { - let state = LexerState.inTemplateString as LexerState - let clean = '`' - const opStack: LexerState[] = [state] - - function pushStack(newState: LexerState) { - state = newState - opStack.push(state) - } - - function popStack() { - opStack.pop() - state = opStack[opStack.length - 1] - } - - let i = start + 1 - outer: for (; i < code.length; i++) { - const char = code.charAt(i) - switch (state) { - case LexerState.inTemplateString: - if (char === '$' && code.charAt(i + 1) === '{') { - pushStack(LexerState.inInterpolationExpression) - clean += '${' - i++ // jump next - } else if (char === '`') { - popStack() - clean += char - if (opStack.length === 0) { - break outer - } - } else { - clean += '\0' - } - break - case LexerState.inInterpolationExpression: - if (char === '{') { - pushStack(LexerState.inObjectExpression) - clean += char - } else if (char === '}') { - popStack() - clean += char - } else if (char === '`') { - pushStack(LexerState.inTemplateString) - clean += char - } else { - clean += char - } - break - case LexerState.inObjectExpression: - if (char === '}') { - popStack() - clean += char - } else if (char === '`') { - pushStack(LexerState.inTemplateString) - clean += char - } else { - clean += char - } - break - default: - throw new Error('unknown string template lexer state') - } - } - - if (opStack.length !== 0) { - error(start) - } - - return [clean, i + 1] -} - -function error(pos: number) { - const err = new Error( - `can not match string template expression.` - ) as RollupError - err.pos = pos - throw err -} diff --git a/packages/vite/src/node/plugins/assetImportMetaUrl.ts b/packages/vite/src/node/plugins/assetImportMetaUrl.ts index b8c16f76d2b93f..217b0d3fee1564 100644 --- a/packages/vite/src/node/plugins/assetImportMetaUrl.ts +++ b/packages/vite/src/node/plugins/assetImportMetaUrl.ts @@ -3,7 +3,7 @@ import MagicString from 'magic-string' import path from 'path' import { fileToUrl } from './asset' import type { ResolvedConfig } from '../config' -import { emptyString } from '../cleanString' +import { stripLiteral } from 'strip-literal' /** * Convert `new URL('./foo.png', import.meta.url)` to its resolved built URL @@ -27,7 +27,7 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin { let s: MagicString | undefined const assetImportMetaUrlRE = /\bnew\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*,?\s*\)/g - const cleanString = emptyString(code) + const cleanString = stripLiteral(code) let match: RegExpExecArray | null while ((match = assetImportMetaUrlRE.exec(cleanString))) { diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index c61e059867080b..22dfc33f67a509 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -49,7 +49,7 @@ import { transform, formatMessages } from 'esbuild' import { addToHTMLProxyTransformResult } from './html' import { injectSourcesContent, getCodeWithSourcemap } from '../server/sourcemap' import type { RawSourceMap } from '@ampproject/remapping' -import { emptyCssComments } from '../cleanString' +import { emptyCssComments } from '../utils' // const debug = createDebugger('vite:css') diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts index 0223c351af6071..6d793c416ce60a 100644 --- a/packages/vite/src/node/plugins/html.ts +++ b/packages/vite/src/node/plugins/html.ts @@ -36,7 +36,7 @@ import type { TextNode } from '@vue/compiler-dom' import { NodeTypes } from '@vue/compiler-dom' -import { emptyString } from '../cleanString' +import { stripLiteral } from 'strip-literal' interface ScriptAssetsUrl { start: number @@ -308,7 +308,7 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { } } else if (node.children.length) { const scriptNode = node.children.pop()! as TextNode - const cleanCode = emptyString(scriptNode.content) + const cleanCode = stripLiteral(scriptNode.content) let match: RegExpExecArray | null while ((match = inlineImportRE.exec(cleanCode))) { diff --git a/packages/vite/src/node/plugins/workerImportMetaUrl.ts b/packages/vite/src/node/plugins/workerImportMetaUrl.ts index 3d8970b746349c..bfd8c22dcad372 100644 --- a/packages/vite/src/node/plugins/workerImportMetaUrl.ts +++ b/packages/vite/src/node/plugins/workerImportMetaUrl.ts @@ -10,7 +10,7 @@ import { ENV_ENTRY, ENV_PUBLIC_PATH } from '../constants' import MagicString from 'magic-string' import type { ViteDevServer } from '..' import type { RollupError } from 'rollup' -import { emptyString } from '../cleanString' +import { stripLiteral } from 'strip-literal' type WorkerType = 'classic' | 'module' | 'ignore' const ignoreFlagRE = /\/\*\s*@vite-ignore\s*\*\// @@ -110,7 +110,7 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin { code.includes('new URL') && code.includes(`import.meta.url`) ) { - const cleanString = emptyString(code) + const cleanString = stripLiteral(code) const workerImportMetaUrlRE = /\bnew\s+(Worker|SharedWorker)\s*\(\s*(new\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*\))/g diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 29741989ea2326..ddcaced9832bc1 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -785,3 +785,7 @@ function gracefulRename( if (cb) cb(er) }) } + +export function emptyCssComments(raw: string) { + return raw.replace(multilineCommentsRE, (s) => ' '.repeat(s.length)) +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3f15dbb27aae88..a20eb4e3bb7d1f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -893,6 +893,7 @@ importers: source-map-js: ^1.0.2 source-map-support: ^0.5.21 strip-ansi: ^6.0.1 + strip-literal: ^0.2.0 terser: ^5.13.1 tsconfck: ^1.2.2 tslib: ^2.4.0 @@ -966,6 +967,7 @@ importers: source-map-js: 1.0.2 source-map-support: 0.5.21 strip-ansi: 6.0.1 + strip-literal: 0.2.0 terser: 5.13.1 tsconfck: 1.2.2_typescript@4.5.4 tslib: 2.4.0 @@ -9016,6 +9018,12 @@ packages: engines: {node: '>=8'} dev: true + /strip-literal/0.2.0: + resolution: {integrity: sha512-pqhiiFRDifA2CRVH0Gmv6MDbd2b27MS0oIqqy7JCqfL5m2sh68223lmEK2eoBXp4vNaq8G1Wzwd9dfQcWszUlg==} + dependencies: + acorn: 8.7.1 + dev: true + /stylis/4.0.13: resolution: {integrity: sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==}