fix: strip BOM character from beginning of input (#13548)

Fixes #13519

---------

Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
pull/13559/head
Dominic Gannaway 3 months ago committed by GitHub
parent 531ff6243c
commit d220edd754
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: strip BOM character from input

@ -20,6 +20,7 @@ export { default as preprocess } from './preprocess/index.js';
* @returns {CompileResult} * @returns {CompileResult}
*/ */
export function compile(source, options) { export function compile(source, options) {
source = remove_bom(source);
state.reset_warning_filter(options.warningFilter); state.reset_warning_filter(options.warningFilter);
const validated = validate_component_options(options, ''); const validated = validate_component_options(options, '');
state.reset(source, validated); state.reset(source, validated);
@ -58,6 +59,7 @@ export function compile(source, options) {
* @returns {CompileResult} * @returns {CompileResult}
*/ */
export function compileModule(source, options) { export function compileModule(source, options) {
source = remove_bom(source);
state.reset_warning_filter(options.warningFilter); state.reset_warning_filter(options.warningFilter);
const validated = validate_module_options(options, ''); const validated = validate_module_options(options, '');
state.reset(source, validated); state.reset(source, validated);
@ -101,6 +103,7 @@ export function compileModule(source, options) {
* @returns {AST.Root | LegacyRoot} * @returns {AST.Root | LegacyRoot}
*/ */
export function parse(source, { filename, rootDir, modern } = {}) { export function parse(source, { filename, rootDir, modern } = {}) {
source = remove_bom(source);
state.reset_warning_filter(() => false); state.reset_warning_filter(() => false);
state.reset(source, { filename: filename ?? '(unknown)', rootDir }); state.reset(source, { filename: filename ?? '(unknown)', rootDir });
@ -140,6 +143,17 @@ function to_public_ast(source, ast, modern) {
return convert(source, ast); return convert(source, ast);
} }
/**
* Remove the byte order mark from a string if it's present since it would mess with our template generation logic
* @param {string} source
*/
function remove_bom(source) {
if (source.charCodeAt(0) === 0xfeff) {
return source.slice(1);
}
return source;
}
/** /**
* @deprecated Replace this with `import { walk } from 'estree-walker'` * @deprecated Replace this with `import { walk } from 'estree-walker'`
* @returns {never} * @returns {never}

@ -1,5 +1,5 @@
import * as fs from 'node:fs'; import * as fs from 'node:fs';
import { assert } from 'vitest'; import { assert, it } from 'vitest';
import { parse } from 'svelte/compiler'; import { parse } from 'svelte/compiler';
import { try_load_json } from '../helpers.js'; import { try_load_json } from '../helpers.js';
import { suite, type BaseTest } from '../suite.js'; import { suite, type BaseTest } from '../suite.js';
@ -34,3 +34,24 @@ const { test, run } = suite<ParserTest>(async (config, cwd) => {
export { test }; export { test };
await run(__dirname); await run(__dirname);
it('Strips BOM from the input', () => {
const input = '\uFEFF<div></div>';
const actual = parse(input, { modern: true });
assert.deepEqual(JSON.parse(JSON.stringify(actual.fragment)), {
type: 'Fragment',
nodes: [
{
attributes: [],
end: 11,
fragment: {
nodes: [],
type: 'Fragment'
},
name: 'div',
start: 0,
type: 'RegularElement'
}
]
});
});

Loading…
Cancel
Save