From 98356b753b18a676673441ca8933a242b6ff8312 Mon Sep 17 00:00:00 2001
From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com>
Date: Sun, 11 May 2025 14:56:02 -0700
Subject: [PATCH 01/15] fix: warn on bidirectional control characters
---
.changeset/rare-crews-collect.md | 5 +++
.../.generated/compile-warnings.md | 8 ++++
.../svelte/messages/compile-warnings/misc.md | 6 +++
.../src/compiler/phases/1-parse/index.js | 8 +++-
.../src/compiler/phases/2-analyze/index.js | 4 ++
.../phases/2-analyze/visitors/Literal.js | 14 +++++++
.../2-analyze/visitors/TemplateElement.js | 12 ++++++
.../svelte/src/compiler/phases/patterns.js | 1 +
packages/svelte/src/compiler/warnings.js | 9 ++++
.../_expected/client/index.svelte.js | 17 ++++++++
.../client/index.svelte.warnings.json | 42 +++++++++++++++++++
.../_expected/server/index.svelte.js | 7 ++++
.../server/index.svelte.warnings.json | 42 +++++++++++++++++++
.../bidirectional-control-chars/index.svelte | 5 +++
14 files changed, 179 insertions(+), 1 deletion(-)
create mode 100644 .changeset/rare-crews-collect.md
create mode 100644 packages/svelte/src/compiler/phases/2-analyze/visitors/Literal.js
create mode 100644 packages/svelte/src/compiler/phases/2-analyze/visitors/TemplateElement.js
create mode 100644 packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.js
create mode 100644 packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json
create mode 100644 packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.js
create mode 100644 packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json
create mode 100644 packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte
diff --git a/.changeset/rare-crews-collect.md b/.changeset/rare-crews-collect.md
new file mode 100644
index 000000000000..a4ffe09324f0
--- /dev/null
+++ b/.changeset/rare-crews-collect.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: warn on bidirectional control characters
diff --git a/documentation/docs/98-reference/.generated/compile-warnings.md b/documentation/docs/98-reference/.generated/compile-warnings.md
index 0e94cbadb2e8..eef57f439e11 100644
--- a/documentation/docs/98-reference/.generated/compile-warnings.md
+++ b/documentation/docs/98-reference/.generated/compile-warnings.md
@@ -586,6 +586,14 @@ Attributes should not contain ':' characters to prevent ambiguity with Svelte di
Quoted attributes on components and custom elements will be stringified in a future version of Svelte. If this isn't what you want, remove the quotes
```
+### bidirectional_control_characters_detected
+
+```
+A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences
+```
+
+Bidirectional control characters can alter the direction in which text appears to be in. For example, via control characters, you can make `defabc` look like `abcdef`. As a result, if you were to copy some code that has these control characters, they may alter the behavior of your code in ways you did not intend. For more information check out [this website](https://trojansource.codes).
+
### bind_invalid_each_rest
```
diff --git a/packages/svelte/messages/compile-warnings/misc.md b/packages/svelte/messages/compile-warnings/misc.md
index 3b977db1be57..362e83aafc20 100644
--- a/packages/svelte/messages/compile-warnings/misc.md
+++ b/packages/svelte/messages/compile-warnings/misc.md
@@ -1,3 +1,9 @@
+## bidirectional_control_characters_detected
+
+> A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences
+
+Bidirectional control characters can alter the direction in which text appears to be in. For example, via control characters, you can make `defabc` look like `abcdef`. As a result, if you were to unknowingly copy and paste some code that has these control characters, they may alter the behavior of your code in ways you did not intend. For more information check out [this website](https://trojansource.codes).
+
## legacy_code
> `%code%` is no longer valid — please use `%suggestion%` instead
diff --git a/packages/svelte/src/compiler/phases/1-parse/index.js b/packages/svelte/src/compiler/phases/1-parse/index.js
index 6cc5b58aa666..d1a72318550b 100644
--- a/packages/svelte/src/compiler/phases/1-parse/index.js
+++ b/packages/svelte/src/compiler/phases/1-parse/index.js
@@ -2,8 +2,9 @@
// @ts-expect-error acorn type definitions are borked in the release we use
import { isIdentifierStart, isIdentifierChar } from 'acorn';
import fragment from './state/fragment.js';
-import { regex_whitespace } from '../patterns.js';
+import { regex_bidirectional_control_characters, regex_whitespace } from '../patterns.js';
import * as e from '../../errors.js';
+import * as w from '../../warnings.js';
import { create_fragment } from './utils/create.js';
import read_options from './read/options.js';
import { is_reserved } from '../../../utils.js';
@@ -64,6 +65,11 @@ export class Parser {
throw new TypeError('Template must be a string');
}
+ const control_chars = regex_bidirectional_control_characters.exec(template);
+ if (control_chars) {
+ w.bidirectional_control_characters_detected({ start: template.indexOf(control_chars[0][0]) });
+ }
+
this.loose = loose;
this.template_untrimmed = template;
this.template = template.trimEnd();
diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js
index 2e36a896493f..766b317d06e2 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/index.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/index.js
@@ -43,6 +43,7 @@ import { ImportDeclaration } from './visitors/ImportDeclaration.js';
import { KeyBlock } from './visitors/KeyBlock.js';
import { LabeledStatement } from './visitors/LabeledStatement.js';
import { LetDirective } from './visitors/LetDirective.js';
+import { Literal } from './visitors/Literal.js';
import { MemberExpression } from './visitors/MemberExpression.js';
import { NewExpression } from './visitors/NewExpression.js';
import { OnDirective } from './visitors/OnDirective.js';
@@ -63,6 +64,7 @@ import { SvelteSelf } from './visitors/SvelteSelf.js';
import { SvelteWindow } from './visitors/SvelteWindow.js';
import { SvelteBoundary } from './visitors/SvelteBoundary.js';
import { TaggedTemplateExpression } from './visitors/TaggedTemplateExpression.js';
+import { TemplateElement } from './visitors/TemplateElement.js';
import { Text } from './visitors/Text.js';
import { TitleElement } from './visitors/TitleElement.js';
import { TransitionDirective } from './visitors/TransitionDirective.js';
@@ -156,6 +158,7 @@ const visitors = {
KeyBlock,
LabeledStatement,
LetDirective,
+ Literal,
MemberExpression,
NewExpression,
OnDirective,
@@ -176,6 +179,7 @@ const visitors = {
SvelteWindow,
SvelteBoundary,
TaggedTemplateExpression,
+ TemplateElement,
Text,
TransitionDirective,
TitleElement,
diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/Literal.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/Literal.js
new file mode 100644
index 000000000000..c371e9a22480
--- /dev/null
+++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/Literal.js
@@ -0,0 +1,14 @@
+/** @import { Literal } from 'estree' */
+import * as w from '../../../warnings.js';
+import { regex_bidirectional_control_characters } from '../../patterns.js';
+
+/**
+ * @param {Literal} node
+ */
+export function Literal(node) {
+ if (typeof node.value === 'string') {
+ if (regex_bidirectional_control_characters.test(node.value)) {
+ w.bidirectional_control_characters_detected(node);
+ }
+ }
+}
diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/TemplateElement.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/TemplateElement.js
new file mode 100644
index 000000000000..73950a097475
--- /dev/null
+++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/TemplateElement.js
@@ -0,0 +1,12 @@
+/** @import { TemplateElement } from 'estree' */
+import * as w from '../../../warnings.js';
+import { regex_bidirectional_control_characters } from '../../patterns.js';
+
+/**
+ * @param {TemplateElement} node
+ */
+export function TemplateElement(node) {
+ if (regex_bidirectional_control_characters.test(node.value.cooked ?? '')) {
+ w.bidirectional_control_characters_detected(node);
+ }
+}
diff --git a/packages/svelte/src/compiler/phases/patterns.js b/packages/svelte/src/compiler/phases/patterns.js
index bda299de9e18..a1379f758cae 100644
--- a/packages/svelte/src/compiler/phases/patterns.js
+++ b/packages/svelte/src/compiler/phases/patterns.js
@@ -21,3 +21,4 @@ export const regex_invalid_identifier_chars = /(^[^a-zA-Z_$]|[^a-zA-Z0-9_$])/g;
export const regex_starts_with_vowel = /^[aeiou]/;
export const regex_heading_tags = /^h[1-6]$/;
export const regex_illegal_attribute_character = /(^[0-9-.])|[\^$@%?!|()[\]{}^*+~;]/;
+export const regex_bidirectional_control_characters = /[\u202a\u202b\u202c\u202d\u202e\u2066\u2067\u2068\u2069]/;
\ No newline at end of file
diff --git a/packages/svelte/src/compiler/warnings.js b/packages/svelte/src/compiler/warnings.js
index e6fc8caba54f..805706eb2f11 100644
--- a/packages/svelte/src/compiler/warnings.js
+++ b/packages/svelte/src/compiler/warnings.js
@@ -86,6 +86,7 @@ export const codes = [
'a11y_role_supports_aria_props_implicit',
'a11y_unknown_aria_attribute',
'a11y_unknown_role',
+ 'bidirectional_control_characters_detected',
'legacy_code',
'unknown_code',
'options_deprecated_accessors',
@@ -506,6 +507,14 @@ export function a11y_unknown_role(node, role, suggestion) {
w(node, 'a11y_unknown_role', `${suggestion ? `Unknown role '${role}'. Did you mean '${suggestion}'?` : `Unknown role '${role}'`}\nhttps://svelte.dev/e/a11y_unknown_role`);
}
+/**
+ * A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences
+ * @param {null | NodeLike} node
+ */
+export function bidirectional_control_characters_detected(node) {
+ w(node, 'bidirectional_control_characters_detected', `A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected`);
+}
+
/**
* `%code%` is no longer valid — please use `%suggestion%` instead
* @param {null | NodeLike} node
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.js
new file mode 100644
index 000000000000..254ba018c034
--- /dev/null
+++ b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.js
@@ -0,0 +1,17 @@
+import 'svelte/internal/disclose-version';
+import 'svelte/internal/flags/legacy';
+import * as $ from 'svelte/internal/client';
+
+var root = $.template(`defabc
`, 1);
+
+export default function Bidirectional_control_chars($$anchor) {
+ let name = '\u2067\u2066rld\u2069\u2066wo\u2069\u2069';
+
+ $.next();
+
+ var fragment = root();
+ var h1 = $.sibling($.first_child(fragment));
+
+ h1.textContent = 'Hello, rldwo!';
+ $.append($$anchor, fragment);
+}
\ No newline at end of file
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json
new file mode 100644
index 000000000000..85f9f5c8a8a0
--- /dev/null
+++ b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json
@@ -0,0 +1,42 @@
+[
+ {
+ "code": "bidirectional_control_characters_detected",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected",
+ "filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
+ "start": {
+ "line": 4,
+ "column": 0,
+ "character": 79
+ },
+ "end": {
+ "line": 4,
+ "column": 0,
+ "character": 79
+ },
+ "position": [
+ 79,
+ 79
+ ],
+ "frame": "2: let name = '\\u2067\\u2066rld\\u2069\\u2066wo\\u2069\\u2069';\n3: \n4: defabc\n ^\n5: Hello, {name}!
"
+ },
+ {
+ "code": "bidirectional_control_characters_detected",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected",
+ "filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
+ "start": {
+ "line": 2,
+ "column": 15,
+ "character": 24
+ },
+ "end": {
+ "line": 2,
+ "column": 58,
+ "character": 67
+ },
+ "position": [
+ 24,
+ 67
+ ],
+ "frame": "1: \n4: defabc"
+ }
+]
\ No newline at end of file
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.js b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.js
new file mode 100644
index 000000000000..59d43b758eca
--- /dev/null
+++ b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.js
@@ -0,0 +1,7 @@
+import * as $ from 'svelte/internal/server';
+
+export default function Bidirectional_control_chars($$payload) {
+ let name = '\u2067\u2066rld\u2069\u2066wo\u2069\u2069';
+
+ $$payload.out += `defabc Hello, rldwo!
`;
+}
\ No newline at end of file
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json
new file mode 100644
index 000000000000..85f9f5c8a8a0
--- /dev/null
+++ b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json
@@ -0,0 +1,42 @@
+[
+ {
+ "code": "bidirectional_control_characters_detected",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected",
+ "filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
+ "start": {
+ "line": 4,
+ "column": 0,
+ "character": 79
+ },
+ "end": {
+ "line": 4,
+ "column": 0,
+ "character": 79
+ },
+ "position": [
+ 79,
+ 79
+ ],
+ "frame": "2: let name = '\\u2067\\u2066rld\\u2069\\u2066wo\\u2069\\u2069';\n3: \n4: defabc\n ^\n5: Hello, {name}!
"
+ },
+ {
+ "code": "bidirectional_control_characters_detected",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected",
+ "filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
+ "start": {
+ "line": 2,
+ "column": 15,
+ "character": 24
+ },
+ "end": {
+ "line": 2,
+ "column": 58,
+ "character": 67
+ },
+ "position": [
+ 24,
+ 67
+ ],
+ "frame": "1: \n4: defabc"
+ }
+]
\ No newline at end of file
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte
new file mode 100644
index 000000000000..e7c5f7c08f55
--- /dev/null
+++ b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte
@@ -0,0 +1,5 @@
+
+defabc
+Hello, {name}!
\ No newline at end of file
From 89dd5d83a0f6eb8acbe1c4212b512e7b5b56b591 Mon Sep 17 00:00:00 2001
From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com>
Date: Sun, 11 May 2025 15:48:47 -0700
Subject: [PATCH 02/15] check evaluated values as well, fix minor issue
---
.../3-transform/client/visitors/shared/utils.js | 16 +++++++++++++---
.../3-transform/server/visitors/shared/utils.js | 9 ++++++++-
packages/svelte/src/compiler/phases/scope.js | 4 ++--
3 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js
index bc79b760431c..c393da4bdf22 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js
@@ -4,8 +4,12 @@
import { walk } from 'zimmerframe';
import { object } from '../../../../../utils/ast.js';
import * as b from '#compiler/builders';
+import * as w from '../../../../../warnings.js';
import { sanitize_template_string } from '../../../../../utils/sanitize_template_string.js';
-import { regex_is_valid_identifier } from '../../../../patterns.js';
+import {
+ regex_is_valid_identifier,
+ regex_bidirectional_control_characters
+} from '../../../../patterns.js';
import is_reference from 'is-reference';
import { dev, is_ignored, locator } from '../../../../../state.js';
import { create_derived } from '../../utils.js';
@@ -77,7 +81,10 @@ export function build_template_chunk(
// If we have a single expression, then pass that in directly to possibly avoid doing
// extra work in the template_effect (instead we do the work in set_text).
if (evaluated.is_known) {
- value = b.literal(evaluated.value);
+ if (regex_bidirectional_control_characters.test((evaluated.value ?? '') + '')) {
+ w.bidirectional_control_characters_detected(node);
+ }
+ value = b.literal((evaluated.value ?? '') + '');
}
return { value, has_state };
@@ -96,7 +103,10 @@ export function build_template_chunk(
}
if (evaluated.is_known) {
- quasi.value.cooked += evaluated.value + '';
+ if (regex_bidirectional_control_characters.test((evaluated.value ?? '') + '')) {
+ w.bidirectional_control_characters_detected(node);
+ }
+ quasi.value.cooked += (evaluated.value ?? '') + '';
} else {
if (!evaluated.is_defined) {
// add `?? ''` where necessary
diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js
index 8fcf8efa68b6..403611272270 100644
--- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js
+++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js
@@ -9,8 +9,12 @@ import {
EMPTY_COMMENT
} from '../../../../../../internal/server/hydration.js';
import * as b from '#compiler/builders';
+import * as w from '../../../../../warnings.js';
import { sanitize_template_string } from '../../../../../utils/sanitize_template_string.js';
-import { regex_whitespaces_strict } from '../../../../patterns.js';
+import {
+ regex_bidirectional_control_characters,
+ regex_whitespaces_strict
+} from '../../../../patterns.js';
/** Opens an if/each block, so that we can remove nodes in the case of a mismatch */
export const block_open = b.literal(BLOCK_OPEN);
@@ -48,6 +52,9 @@ export function process_children(nodes, { visit, state }) {
const evaluated = state.scope.evaluate(node.expression);
if (evaluated.is_known) {
+ if (regex_bidirectional_control_characters.test((evaluated.value ?? '') + '')) {
+ w.bidirectional_control_characters_detected(node);
+ }
quasi.value.cooked += escape_html((evaluated.value ?? '') + '');
} else {
expressions.push(b.call('$.escape', /** @type {Expression} */ (visit(node.expression))));
diff --git a/packages/svelte/src/compiler/phases/scope.js b/packages/svelte/src/compiler/phases/scope.js
index 8297f174d3de..75a26d487b78 100644
--- a/packages/svelte/src/compiler/phases/scope.js
+++ b/packages/svelte/src/compiler/phases/scope.js
@@ -23,12 +23,12 @@ export const STRING = Symbol('string');
/** @type {Record} */
const globals = {
- BigInt: [NUMBER, BigInt],
+ BigInt: [NUMBER],
'Math.min': [NUMBER, Math.min],
'Math.max': [NUMBER, Math.max],
'Math.random': [NUMBER],
'Math.floor': [NUMBER, Math.floor],
- // @ts-expect-error
+ // @ts-ignore
'Math.f16round': [NUMBER, Math.f16round],
'Math.round': [NUMBER, Math.round],
'Math.abs': [NUMBER, Math.abs],
From b093ac7f1687c3c40411c04f06ea45cf4e91b35e Mon Sep 17 00:00:00 2001
From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com>
Date: Sun, 11 May 2025 15:57:18 -0700
Subject: [PATCH 03/15] fix failing tests
---
.../client/index.svelte.warnings.json | 20 +++++++++++++++++++
.../server/index.svelte.warnings.json | 20 +++++++++++++++++++
.../purity/_expected/client/index.svelte.js | 2 +-
3 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json
index 85f9f5c8a8a0..f6ee896926fe 100644
--- a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json
+++ b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json
@@ -38,5 +38,25 @@
67
],
"frame": "1: \n4: defabc"
+ },
+ {
+ "code": "bidirectional_control_characters_detected",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected",
+ "filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
+ "start": {
+ "line": 5,
+ "column": 11,
+ "character": 103
+ },
+ "end": {
+ "line": 5,
+ "column": 17,
+ "character": 109
+ },
+ "position": [
+ 103,
+ 109
+ ],
+ "frame": "3: \n4: defabc\n5: Hello, {name}!
\n ^"
}
]
\ No newline at end of file
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json
index 85f9f5c8a8a0..f6ee896926fe 100644
--- a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json
+++ b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json
@@ -38,5 +38,25 @@
67
],
"frame": "1: \n4: defabc"
+ },
+ {
+ "code": "bidirectional_control_characters_detected",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected",
+ "filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
+ "start": {
+ "line": 5,
+ "column": 11,
+ "character": 103
+ },
+ "end": {
+ "line": 5,
+ "column": 17,
+ "character": 109
+ },
+ "position": [
+ 103,
+ 109
+ ],
+ "frame": "3: \n4: defabc\n5: Hello, {name}!
\n ^"
}
]
\ No newline at end of file
diff --git a/packages/svelte/tests/snapshot/samples/purity/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/purity/_expected/client/index.svelte.js
index 5bc9766acfd4..f661dbc01d83 100644
--- a/packages/svelte/tests/snapshot/samples/purity/_expected/client/index.svelte.js
+++ b/packages/svelte/tests/snapshot/samples/purity/_expected/client/index.svelte.js
@@ -8,7 +8,7 @@ export default function Purity($$anchor) {
var fragment = root();
var p = $.first_child(fragment);
- p.textContent = 0;
+ p.textContent = '0';
var p_1 = $.sibling(p, 2);
From 5f7726e21a03e1b365a79ba4098be697202c4ce0 Mon Sep 17 00:00:00 2001
From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com>
Date: Sun, 11 May 2025 16:01:58 -0700
Subject: [PATCH 04/15] lint
---
packages/svelte/src/compiler/phases/patterns.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/svelte/src/compiler/phases/patterns.js b/packages/svelte/src/compiler/phases/patterns.js
index a1379f758cae..f0c88ee35161 100644
--- a/packages/svelte/src/compiler/phases/patterns.js
+++ b/packages/svelte/src/compiler/phases/patterns.js
@@ -21,4 +21,5 @@ export const regex_invalid_identifier_chars = /(^[^a-zA-Z_$]|[^a-zA-Z0-9_$])/g;
export const regex_starts_with_vowel = /^[aeiou]/;
export const regex_heading_tags = /^h[1-6]$/;
export const regex_illegal_attribute_character = /(^[0-9-.])|[\^$@%?!|()[\]{}^*+~;]/;
-export const regex_bidirectional_control_characters = /[\u202a\u202b\u202c\u202d\u202e\u2066\u2067\u2068\u2069]/;
\ No newline at end of file
+export const regex_bidirectional_control_characters =
+ /[\u202a\u202b\u202c\u202d\u202e\u2066\u2067\u2068\u2069]/;
From 2c280949d6032b5990fd9dec455355829daf95cb Mon Sep 17 00:00:00 2001
From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com>
Date: Sun, 11 May 2025 16:13:49 -0700
Subject: [PATCH 05/15] fix
---
documentation/docs/98-reference/.generated/compile-warnings.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/documentation/docs/98-reference/.generated/compile-warnings.md b/documentation/docs/98-reference/.generated/compile-warnings.md
index eef57f439e11..2c6770ebe65e 100644
--- a/documentation/docs/98-reference/.generated/compile-warnings.md
+++ b/documentation/docs/98-reference/.generated/compile-warnings.md
@@ -592,7 +592,7 @@ Quoted attributes on components and custom elements will be stringified in a fut
A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences
```
-Bidirectional control characters can alter the direction in which text appears to be in. For example, via control characters, you can make `defabc` look like `abcdef`. As a result, if you were to copy some code that has these control characters, they may alter the behavior of your code in ways you did not intend. For more information check out [this website](https://trojansource.codes).
+Bidirectional control characters can alter the direction in which text appears to be in. For example, via control characters, you can make `defabc` look like `abcdef`. As a result, if you were to unknowingly copy and paste some code that has these control characters, they may alter the behavior of your code in ways you did not intend. For more information check out [this website](https://trojansource.codes).
### bind_invalid_each_rest
From ef30da7167080155fc94f7322c219a1458a3b912 Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Mon, 12 May 2025 17:32:27 -0400
Subject: [PATCH 06/15] shrink warning code
---
.../98-reference/.generated/compile-warnings.md | 2 +-
packages/svelte/messages/compile-warnings/misc.md | 2 +-
.../svelte/src/compiler/phases/1-parse/index.js | 2 +-
.../compiler/phases/2-analyze/visitors/Literal.js | 2 +-
.../phases/2-analyze/visitors/TemplateElement.js | 2 +-
.../3-transform/client/visitors/shared/utils.js | 4 ++--
.../3-transform/server/visitors/shared/utils.js | 2 +-
packages/svelte/src/compiler/warnings.js | 8 ++++----
.../_expected/client/index.svelte.warnings.json | 14 +++++++-------
.../_expected/server/index.svelte.warnings.json | 14 +++++++-------
10 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/documentation/docs/98-reference/.generated/compile-warnings.md b/documentation/docs/98-reference/.generated/compile-warnings.md
index 2c6770ebe65e..9bfdb2b86ead 100644
--- a/documentation/docs/98-reference/.generated/compile-warnings.md
+++ b/documentation/docs/98-reference/.generated/compile-warnings.md
@@ -586,7 +586,7 @@ Attributes should not contain ':' characters to prevent ambiguity with Svelte di
Quoted attributes on components and custom elements will be stringified in a future version of Svelte. If this isn't what you want, remove the quotes
```
-### bidirectional_control_characters_detected
+### bidirectional_control_characters
```
A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences
diff --git a/packages/svelte/messages/compile-warnings/misc.md b/packages/svelte/messages/compile-warnings/misc.md
index 362e83aafc20..7422db5d08c7 100644
--- a/packages/svelte/messages/compile-warnings/misc.md
+++ b/packages/svelte/messages/compile-warnings/misc.md
@@ -1,4 +1,4 @@
-## bidirectional_control_characters_detected
+## bidirectional_control_characters
> A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences
diff --git a/packages/svelte/src/compiler/phases/1-parse/index.js b/packages/svelte/src/compiler/phases/1-parse/index.js
index d1a72318550b..d6dc4e01d376 100644
--- a/packages/svelte/src/compiler/phases/1-parse/index.js
+++ b/packages/svelte/src/compiler/phases/1-parse/index.js
@@ -67,7 +67,7 @@ export class Parser {
const control_chars = regex_bidirectional_control_characters.exec(template);
if (control_chars) {
- w.bidirectional_control_characters_detected({ start: template.indexOf(control_chars[0][0]) });
+ w.bidirectional_control_characters({ start: template.indexOf(control_chars[0][0]) });
}
this.loose = loose;
diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/Literal.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/Literal.js
index c371e9a22480..58684ba71ca0 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/visitors/Literal.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/Literal.js
@@ -8,7 +8,7 @@ import { regex_bidirectional_control_characters } from '../../patterns.js';
export function Literal(node) {
if (typeof node.value === 'string') {
if (regex_bidirectional_control_characters.test(node.value)) {
- w.bidirectional_control_characters_detected(node);
+ w.bidirectional_control_characters(node);
}
}
}
diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/TemplateElement.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/TemplateElement.js
index 73950a097475..978042bbc589 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/visitors/TemplateElement.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/TemplateElement.js
@@ -7,6 +7,6 @@ import { regex_bidirectional_control_characters } from '../../patterns.js';
*/
export function TemplateElement(node) {
if (regex_bidirectional_control_characters.test(node.value.cooked ?? '')) {
- w.bidirectional_control_characters_detected(node);
+ w.bidirectional_control_characters(node);
}
}
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js
index c393da4bdf22..59e57972f58a 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js
@@ -82,7 +82,7 @@ export function build_template_chunk(
// extra work in the template_effect (instead we do the work in set_text).
if (evaluated.is_known) {
if (regex_bidirectional_control_characters.test((evaluated.value ?? '') + '')) {
- w.bidirectional_control_characters_detected(node);
+ w.bidirectional_control_characters(node);
}
value = b.literal((evaluated.value ?? '') + '');
}
@@ -104,7 +104,7 @@ export function build_template_chunk(
if (evaluated.is_known) {
if (regex_bidirectional_control_characters.test((evaluated.value ?? '') + '')) {
- w.bidirectional_control_characters_detected(node);
+ w.bidirectional_control_characters(node);
}
quasi.value.cooked += (evaluated.value ?? '') + '';
} else {
diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js
index 403611272270..1dbde82aae46 100644
--- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js
+++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js
@@ -53,7 +53,7 @@ export function process_children(nodes, { visit, state }) {
if (evaluated.is_known) {
if (regex_bidirectional_control_characters.test((evaluated.value ?? '') + '')) {
- w.bidirectional_control_characters_detected(node);
+ w.bidirectional_control_characters(node);
}
quasi.value.cooked += escape_html((evaluated.value ?? '') + '');
} else {
diff --git a/packages/svelte/src/compiler/warnings.js b/packages/svelte/src/compiler/warnings.js
index 805706eb2f11..4c5471959423 100644
--- a/packages/svelte/src/compiler/warnings.js
+++ b/packages/svelte/src/compiler/warnings.js
@@ -86,7 +86,7 @@ export const codes = [
'a11y_role_supports_aria_props_implicit',
'a11y_unknown_aria_attribute',
'a11y_unknown_role',
- 'bidirectional_control_characters_detected',
+ 'bidirectional_control_characters',
'legacy_code',
'unknown_code',
'options_deprecated_accessors',
@@ -511,8 +511,8 @@ export function a11y_unknown_role(node, role, suggestion) {
* A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences
* @param {null | NodeLike} node
*/
-export function bidirectional_control_characters_detected(node) {
- w(node, 'bidirectional_control_characters_detected', `A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected`);
+export function bidirectional_control_characters(node) {
+ w(node, 'bidirectional_control_characters', `A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters`);
}
/**
@@ -821,4 +821,4 @@ export function svelte_element_invalid_this(node) {
*/
export function svelte_self_deprecated(node, name, basename) {
w(node, 'svelte_self_deprecated', `\`\` is deprecated — use self-imports (e.g. \`import ${name} from './${basename}'\`) instead\nhttps://svelte.dev/e/svelte_self_deprecated`);
-}
\ No newline at end of file
+}
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json
index f6ee896926fe..48e8ec58c940 100644
--- a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json
+++ b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json
@@ -1,7 +1,7 @@
[
{
- "code": "bidirectional_control_characters_detected",
- "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected",
+ "code": "bidirectional_control_characters",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters",
"filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
"start": {
"line": 4,
@@ -20,8 +20,8 @@
"frame": "2: let name = '\\u2067\\u2066rld\\u2069\\u2066wo\\u2069\\u2069';\n3: \n4: defabc\n ^\n5: Hello, {name}!
"
},
{
- "code": "bidirectional_control_characters_detected",
- "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected",
+ "code": "bidirectional_control_characters",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters",
"filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
"start": {
"line": 2,
@@ -40,8 +40,8 @@
"frame": "1: \n4: defabc"
},
{
- "code": "bidirectional_control_characters_detected",
- "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected",
+ "code": "bidirectional_control_characters",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters",
"filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
"start": {
"line": 5,
@@ -59,4 +59,4 @@
],
"frame": "3: \n4: defabc\n5: Hello, {name}!
\n ^"
}
-]
\ No newline at end of file
+]
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json
index f6ee896926fe..48e8ec58c940 100644
--- a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json
+++ b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json
@@ -1,7 +1,7 @@
[
{
- "code": "bidirectional_control_characters_detected",
- "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected",
+ "code": "bidirectional_control_characters",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters",
"filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
"start": {
"line": 4,
@@ -20,8 +20,8 @@
"frame": "2: let name = '\\u2067\\u2066rld\\u2069\\u2066wo\\u2069\\u2069';\n3: \n4: defabc\n ^\n5: Hello, {name}!
"
},
{
- "code": "bidirectional_control_characters_detected",
- "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected",
+ "code": "bidirectional_control_characters",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters",
"filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
"start": {
"line": 2,
@@ -40,8 +40,8 @@
"frame": "1: \n4: defabc"
},
{
- "code": "bidirectional_control_characters_detected",
- "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters_detected",
+ "code": "bidirectional_control_characters",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters",
"filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
"start": {
"line": 5,
@@ -59,4 +59,4 @@
],
"frame": "3: \n4: defabc\n5: Hello, {name}!
\n ^"
}
-]
\ No newline at end of file
+]
From 4294d5b1caf00007735e107b54b8c49739ed523e Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Mon, 12 May 2025 18:33:55 -0400
Subject: [PATCH 07/15] use validator test suite rather than snapshot (which
should be used sparingly as it creates more git noise)
---
.../_expected/client/index.svelte.js | 17 -----
.../client/index.svelte.warnings.json | 62 -------------------
.../_expected/server/index.svelte.js | 7 ---
.../server/index.svelte.warnings.json | 62 -------------------
.../input.svelte} | 2 +-
.../warnings.json | 26 ++++++++
6 files changed, 27 insertions(+), 149 deletions(-)
delete mode 100644 packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.js
delete mode 100644 packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json
delete mode 100644 packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.js
delete mode 100644 packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json
rename packages/svelte/tests/{snapshot/samples/bidirectional-control-chars/index.svelte => validator/samples/bidirectional-control-characters/input.svelte} (81%)
create mode 100644 packages/svelte/tests/validator/samples/bidirectional-control-characters/warnings.json
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.js
deleted file mode 100644
index 254ba018c034..000000000000
--- a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import 'svelte/internal/disclose-version';
-import 'svelte/internal/flags/legacy';
-import * as $ from 'svelte/internal/client';
-
-var root = $.template(`defabc `, 1);
-
-export default function Bidirectional_control_chars($$anchor) {
- let name = '\u2067\u2066rld\u2069\u2066wo\u2069\u2069';
-
- $.next();
-
- var fragment = root();
- var h1 = $.sibling($.first_child(fragment));
-
- h1.textContent = 'Hello, rldwo!';
- $.append($$anchor, fragment);
-}
\ No newline at end of file
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json
deleted file mode 100644
index 48e8ec58c940..000000000000
--- a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/client/index.svelte.warnings.json
+++ /dev/null
@@ -1,62 +0,0 @@
-[
- {
- "code": "bidirectional_control_characters",
- "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters",
- "filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
- "start": {
- "line": 4,
- "column": 0,
- "character": 79
- },
- "end": {
- "line": 4,
- "column": 0,
- "character": 79
- },
- "position": [
- 79,
- 79
- ],
- "frame": "2: let name = '\\u2067\\u2066rld\\u2069\\u2066wo\\u2069\\u2069';\n3: \n4: defabc\n ^\n5: Hello, {name}!
"
- },
- {
- "code": "bidirectional_control_characters",
- "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters",
- "filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
- "start": {
- "line": 2,
- "column": 15,
- "character": 24
- },
- "end": {
- "line": 2,
- "column": 58,
- "character": 67
- },
- "position": [
- 24,
- 67
- ],
- "frame": "1: \n4: defabc"
- },
- {
- "code": "bidirectional_control_characters",
- "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters",
- "filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
- "start": {
- "line": 5,
- "column": 11,
- "character": 103
- },
- "end": {
- "line": 5,
- "column": 17,
- "character": 109
- },
- "position": [
- 103,
- 109
- ],
- "frame": "3: \n4: defabc\n5: Hello, {name}!
\n ^"
- }
-]
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.js b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.js
deleted file mode 100644
index 59d43b758eca..000000000000
--- a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import * as $ from 'svelte/internal/server';
-
-export default function Bidirectional_control_chars($$payload) {
- let name = '\u2067\u2066rld\u2069\u2066wo\u2069\u2069';
-
- $$payload.out += `defabc Hello, rldwo!
`;
-}
\ No newline at end of file
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json b/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json
deleted file mode 100644
index 48e8ec58c940..000000000000
--- a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/_expected/server/index.svelte.warnings.json
+++ /dev/null
@@ -1,62 +0,0 @@
-[
- {
- "code": "bidirectional_control_characters",
- "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters",
- "filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
- "start": {
- "line": 4,
- "column": 0,
- "character": 79
- },
- "end": {
- "line": 4,
- "column": 0,
- "character": 79
- },
- "position": [
- 79,
- 79
- ],
- "frame": "2: let name = '\\u2067\\u2066rld\\u2069\\u2066wo\\u2069\\u2069';\n3: \n4: defabc\n ^\n5: Hello, {name}!
"
- },
- {
- "code": "bidirectional_control_characters",
- "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters",
- "filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
- "start": {
- "line": 2,
- "column": 15,
- "character": 24
- },
- "end": {
- "line": 2,
- "column": 58,
- "character": 67
- },
- "position": [
- 24,
- 67
- ],
- "frame": "1: \n4: defabc"
- },
- {
- "code": "bidirectional_control_characters",
- "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences\nhttps://svelte.dev/e/bidirectional_control_characters",
- "filename": "packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte",
- "start": {
- "line": 5,
- "column": 11,
- "character": 103
- },
- "end": {
- "line": 5,
- "column": 17,
- "character": 109
- },
- "position": [
- 103,
- 109
- ],
- "frame": "3: \n4: defabc\n5: Hello, {name}!
\n ^"
- }
-]
diff --git a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte b/packages/svelte/tests/validator/samples/bidirectional-control-characters/input.svelte
similarity index 81%
rename from packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte
rename to packages/svelte/tests/validator/samples/bidirectional-control-characters/input.svelte
index e7c5f7c08f55..276d92948fd1 100644
--- a/packages/svelte/tests/snapshot/samples/bidirectional-control-chars/index.svelte
+++ b/packages/svelte/tests/validator/samples/bidirectional-control-characters/input.svelte
@@ -2,4 +2,4 @@
let name = '\u2067\u2066rld\u2069\u2066wo\u2069\u2069';
defabc
-Hello, {name}!
\ No newline at end of file
+Hello, {name}!
diff --git a/packages/svelte/tests/validator/samples/bidirectional-control-characters/warnings.json b/packages/svelte/tests/validator/samples/bidirectional-control-characters/warnings.json
new file mode 100644
index 000000000000..f8ebcc905b6e
--- /dev/null
+++ b/packages/svelte/tests/validator/samples/bidirectional-control-characters/warnings.json
@@ -0,0 +1,26 @@
+[
+ {
+ "code": "bidirectional_control_characters",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences",
+ "start": {
+ "line": 4,
+ "column": 0
+ },
+ "end": {
+ "line": 4,
+ "column": 0
+ }
+ },
+ {
+ "code": "bidirectional_control_characters",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences",
+ "start": {
+ "line": 2,
+ "column": 15
+ },
+ "end": {
+ "line": 2,
+ "column": 58
+ }
+ }
+]
From 926b9eef94cded89e8f742d939a28258189ddbe1 Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Mon, 12 May 2025 18:46:14 -0400
Subject: [PATCH 08/15] show ranges during parsing, and warn on all occurrences
rather than just the first
---
.../src/compiler/phases/1-parse/index.js | 7 ++---
.../svelte/src/compiler/phases/patterns.js | 2 +-
.../warnings.json | 26 ++++++++++++++++++-
3 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/packages/svelte/src/compiler/phases/1-parse/index.js b/packages/svelte/src/compiler/phases/1-parse/index.js
index d6dc4e01d376..733cf834881c 100644
--- a/packages/svelte/src/compiler/phases/1-parse/index.js
+++ b/packages/svelte/src/compiler/phases/1-parse/index.js
@@ -65,9 +65,10 @@ export class Parser {
throw new TypeError('Template must be a string');
}
- const control_chars = regex_bidirectional_control_characters.exec(template);
- if (control_chars) {
- w.bidirectional_control_characters({ start: template.indexOf(control_chars[0][0]) });
+ regex_bidirectional_control_characters.lastIndex = 0;
+ for (const match of template.matchAll(regex_bidirectional_control_characters)) {
+ let start = match.index;
+ w.bidirectional_control_characters({ start, end: start + match[0].length });
}
this.loose = loose;
diff --git a/packages/svelte/src/compiler/phases/patterns.js b/packages/svelte/src/compiler/phases/patterns.js
index f0c88ee35161..2bee717131c7 100644
--- a/packages/svelte/src/compiler/phases/patterns.js
+++ b/packages/svelte/src/compiler/phases/patterns.js
@@ -22,4 +22,4 @@ export const regex_starts_with_vowel = /^[aeiou]/;
export const regex_heading_tags = /^h[1-6]$/;
export const regex_illegal_attribute_character = /(^[0-9-.])|[\^$@%?!|()[\]{}^*+~;]/;
export const regex_bidirectional_control_characters =
- /[\u202a\u202b\u202c\u202d\u202e\u2066\u2067\u2068\u2069]/;
+ /[\u202a\u202b\u202c\u202d\u202e\u2066\u2067\u2068\u2069]+/g;
diff --git a/packages/svelte/tests/validator/samples/bidirectional-control-characters/warnings.json b/packages/svelte/tests/validator/samples/bidirectional-control-characters/warnings.json
index f8ebcc905b6e..e1e48fbcf1dd 100644
--- a/packages/svelte/tests/validator/samples/bidirectional-control-characters/warnings.json
+++ b/packages/svelte/tests/validator/samples/bidirectional-control-characters/warnings.json
@@ -8,7 +8,31 @@
},
"end": {
"line": 4,
- "column": 0
+ "column": 2
+ }
+ },
+ {
+ "code": "bidirectional_control_characters",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences",
+ "start": {
+ "line": 4,
+ "column": 5
+ },
+ "end": {
+ "line": 4,
+ "column": 7
+ }
+ },
+ {
+ "code": "bidirectional_control_characters",
+ "message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences",
+ "start": {
+ "line": 4,
+ "column": 10
+ },
+ "end": {
+ "line": 4,
+ "column": 12
}
},
{
From e92ed93c3e3900509219de384eece8cf10686a08 Mon Sep 17 00:00:00 2001
From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com>
Date: Mon, 12 May 2025 15:49:18 -0700
Subject: [PATCH 09/15] fix lint
---
packages/svelte/src/compiler/warnings.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/svelte/src/compiler/warnings.js b/packages/svelte/src/compiler/warnings.js
index 4c5471959423..c281433213e8 100644
--- a/packages/svelte/src/compiler/warnings.js
+++ b/packages/svelte/src/compiler/warnings.js
@@ -821,4 +821,4 @@ export function svelte_element_invalid_this(node) {
*/
export function svelte_self_deprecated(node, name, basename) {
w(node, 'svelte_self_deprecated', `\`\` is deprecated — use self-imports (e.g. \`import ${name} from './${basename}'\`) instead\nhttps://svelte.dev/e/svelte_self_deprecated`);
-}
+}
\ No newline at end of file
From 65608c7174dee6fb9da44a190ca14b4782bf00e2 Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Mon, 12 May 2025 18:53:59 -0400
Subject: [PATCH 10/15] move check into Text visitor so it happens in expected
order
---
.../src/compiler/phases/1-parse/index.js | 9 +------
.../phases/2-analyze/visitors/Text.js | 13 +++++++++-
.../warnings.json | 24 +++++++++----------
3 files changed, 25 insertions(+), 21 deletions(-)
diff --git a/packages/svelte/src/compiler/phases/1-parse/index.js b/packages/svelte/src/compiler/phases/1-parse/index.js
index 733cf834881c..6cc5b58aa666 100644
--- a/packages/svelte/src/compiler/phases/1-parse/index.js
+++ b/packages/svelte/src/compiler/phases/1-parse/index.js
@@ -2,9 +2,8 @@
// @ts-expect-error acorn type definitions are borked in the release we use
import { isIdentifierStart, isIdentifierChar } from 'acorn';
import fragment from './state/fragment.js';
-import { regex_bidirectional_control_characters, regex_whitespace } from '../patterns.js';
+import { regex_whitespace } from '../patterns.js';
import * as e from '../../errors.js';
-import * as w from '../../warnings.js';
import { create_fragment } from './utils/create.js';
import read_options from './read/options.js';
import { is_reserved } from '../../../utils.js';
@@ -65,12 +64,6 @@ export class Parser {
throw new TypeError('Template must be a string');
}
- regex_bidirectional_control_characters.lastIndex = 0;
- for (const match of template.matchAll(regex_bidirectional_control_characters)) {
- let start = match.index;
- w.bidirectional_control_characters({ start, end: start + match[0].length });
- }
-
this.loose = loose;
this.template_untrimmed = template;
this.template = template.trimEnd();
diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/Text.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/Text.js
index 363a111b7dc6..6d97eb87c22e 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/visitors/Text.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/Text.js
@@ -1,8 +1,9 @@
/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */
import { is_tag_valid_with_parent } from '../../../../html-tree-validation.js';
-import { regex_not_whitespace } from '../../patterns.js';
+import { regex_bidirectional_control_characters, regex_not_whitespace } from '../../patterns.js';
import * as e from '../../../errors.js';
+import * as w from '../../../warnings.js';
/**
* @param {AST.Text} node
@@ -17,4 +18,14 @@ export function Text(node, context) {
e.node_invalid_placement(node, message);
}
}
+
+ regex_bidirectional_control_characters.lastIndex = 0;
+ for (const match of node.data.matchAll(regex_bidirectional_control_characters)) {
+ let start = match.index + node.start;
+ w.bidirectional_control_characters({ start, end: start + match[0].length });
+ }
+
+ // if (regex_bidirectional_control_characters.test(node.data)) {
+ // w.bidirectional_control_characters(node);
+ // }
}
diff --git a/packages/svelte/tests/validator/samples/bidirectional-control-characters/warnings.json b/packages/svelte/tests/validator/samples/bidirectional-control-characters/warnings.json
index e1e48fbcf1dd..6e70193c6c83 100644
--- a/packages/svelte/tests/validator/samples/bidirectional-control-characters/warnings.json
+++ b/packages/svelte/tests/validator/samples/bidirectional-control-characters/warnings.json
@@ -3,12 +3,12 @@
"code": "bidirectional_control_characters",
"message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences",
"start": {
- "line": 4,
- "column": 0
+ "line": 2,
+ "column": 15
},
"end": {
- "line": 4,
- "column": 2
+ "line": 2,
+ "column": 58
}
},
{
@@ -16,11 +16,11 @@
"message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences",
"start": {
"line": 4,
- "column": 5
+ "column": 0
},
"end": {
"line": 4,
- "column": 7
+ "column": 2
}
},
{
@@ -28,23 +28,23 @@
"message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences",
"start": {
"line": 4,
- "column": 10
+ "column": 5
},
"end": {
"line": 4,
- "column": 12
+ "column": 7
}
},
{
"code": "bidirectional_control_characters",
"message": "A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences",
"start": {
- "line": 2,
- "column": 15
+ "line": 4,
+ "column": 10
},
"end": {
- "line": 2,
- "column": 58
+ "line": 4,
+ "column": 12
}
}
]
From 214955008b1dda43a98fbce3b682304e0ba9ee75 Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Mon, 12 May 2025 18:55:34 -0400
Subject: [PATCH 11/15] unused
---
.../svelte/src/compiler/phases/2-analyze/visitors/Text.js | 4 ----
1 file changed, 4 deletions(-)
diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/Text.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/Text.js
index 6d97eb87c22e..51e570f6a03f 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/visitors/Text.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/Text.js
@@ -24,8 +24,4 @@ export function Text(node, context) {
let start = match.index + node.start;
w.bidirectional_control_characters({ start, end: start + match[0].length });
}
-
- // if (regex_bidirectional_control_characters.test(node.data)) {
- // w.bidirectional_control_characters(node);
- // }
}
From c8a828d3b4b7fbd13b63f404c56704f726c931d9 Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Mon, 12 May 2025 18:55:44 -0400
Subject: [PATCH 12/15] add svelte-ignore test
---
.../samples/bidirectional-control-characters/input.svelte | 3 +++
1 file changed, 3 insertions(+)
diff --git a/packages/svelte/tests/validator/samples/bidirectional-control-characters/input.svelte b/packages/svelte/tests/validator/samples/bidirectional-control-characters/input.svelte
index 276d92948fd1..78a72dd8f828 100644
--- a/packages/svelte/tests/validator/samples/bidirectional-control-characters/input.svelte
+++ b/packages/svelte/tests/validator/samples/bidirectional-control-characters/input.svelte
@@ -3,3 +3,6 @@
defabc
Hello, {name}!
+
+
+defabc
From 8fe2f0d8ceb0a03733dd8df1aa3a22a118665bd2 Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Mon, 12 May 2025 19:03:19 -0400
Subject: [PATCH 13/15] ignore control characters following a svelte-ignore
comment
---
.../phases/2-analyze/visitors/Text.js | 33 ++++++++++++++++---
.../input.svelte | 2 +-
2 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/Text.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/Text.js
index 51e570f6a03f..a03421e8dd26 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/visitors/Text.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/Text.js
@@ -4,15 +4,20 @@ import { is_tag_valid_with_parent } from '../../../../html-tree-validation.js';
import { regex_bidirectional_control_characters, regex_not_whitespace } from '../../patterns.js';
import * as e from '../../../errors.js';
import * as w from '../../../warnings.js';
+import { extract_svelte_ignore } from '../../../utils/extract_svelte_ignore.js';
/**
* @param {AST.Text} node
* @param {Context} context
*/
export function Text(node, context) {
- const in_template = context.path.at(-1)?.type === 'Fragment';
+ const parent = /** @type {AST.SvelteNode} */ (context.path.at(-1));
- if (in_template && context.state.parent_element && regex_not_whitespace.test(node.data)) {
+ if (
+ parent.type === 'Fragment' &&
+ context.state.parent_element &&
+ regex_not_whitespace.test(node.data)
+ ) {
const message = is_tag_valid_with_parent('#text', context.state.parent_element);
if (message) {
e.node_invalid_placement(node, message);
@@ -21,7 +26,27 @@ export function Text(node, context) {
regex_bidirectional_control_characters.lastIndex = 0;
for (const match of node.data.matchAll(regex_bidirectional_control_characters)) {
- let start = match.index + node.start;
- w.bidirectional_control_characters({ start, end: start + match[0].length });
+ let is_ignored = false;
+
+ // if we have a svelte-ignore comment earlier in the text, bail
+ // (otherwise we can only use svelte-ignore on parent elements/blocks)
+ if (parent.type === 'Fragment') {
+ for (const child of parent.nodes) {
+ if (child === node) break;
+
+ if (child.type === 'Comment') {
+ is_ignored ||= extract_svelte_ignore(
+ child.start + 4,
+ child.data,
+ context.state.analysis.runes
+ ).includes('bidirectional_control_characters');
+ }
+ }
+ }
+
+ if (!is_ignored) {
+ let start = match.index + node.start;
+ w.bidirectional_control_characters({ start, end: start + match[0].length });
+ }
}
}
diff --git a/packages/svelte/tests/validator/samples/bidirectional-control-characters/input.svelte b/packages/svelte/tests/validator/samples/bidirectional-control-characters/input.svelte
index 78a72dd8f828..21587e5f4fe8 100644
--- a/packages/svelte/tests/validator/samples/bidirectional-control-characters/input.svelte
+++ b/packages/svelte/tests/validator/samples/bidirectional-control-characters/input.svelte
@@ -5,4 +5,4 @@
Hello, {name}!
-defabc
+defabc
From 3f3aab0e8156aeab94ced05533aedfebd67bb80f Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Mon, 12 May 2025 19:06:55 -0400
Subject: [PATCH 14/15] tweak message
---
documentation/docs/98-reference/.generated/compile-warnings.md | 2 +-
packages/svelte/messages/compile-warnings/misc.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/documentation/docs/98-reference/.generated/compile-warnings.md b/documentation/docs/98-reference/.generated/compile-warnings.md
index 9bfdb2b86ead..7069f9020674 100644
--- a/documentation/docs/98-reference/.generated/compile-warnings.md
+++ b/documentation/docs/98-reference/.generated/compile-warnings.md
@@ -592,7 +592,7 @@ Quoted attributes on components and custom elements will be stringified in a fut
A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences
```
-Bidirectional control characters can alter the direction in which text appears to be in. For example, via control characters, you can make `defabc` look like `abcdef`. As a result, if you were to unknowingly copy and paste some code that has these control characters, they may alter the behavior of your code in ways you did not intend. For more information check out [this website](https://trojansource.codes).
+Bidirectional control characters can alter the direction in which text appears to be in. For example, via control characters, you can make `defabc` look like `abcdef`. As a result, if you were to unknowingly copy and paste some code that has these control characters, they may alter the behavior of your code in ways you did not intend. See [trojansource.codes](https://trojansource.codes/) for more information.
### bind_invalid_each_rest
diff --git a/packages/svelte/messages/compile-warnings/misc.md b/packages/svelte/messages/compile-warnings/misc.md
index 7422db5d08c7..29343dd28a33 100644
--- a/packages/svelte/messages/compile-warnings/misc.md
+++ b/packages/svelte/messages/compile-warnings/misc.md
@@ -2,7 +2,7 @@
> A bidirectional control character was detected in your code. These characters can be used to alter the visual direction of your code and could have unintended consequences
-Bidirectional control characters can alter the direction in which text appears to be in. For example, via control characters, you can make `defabc` look like `abcdef`. As a result, if you were to unknowingly copy and paste some code that has these control characters, they may alter the behavior of your code in ways you did not intend. For more information check out [this website](https://trojansource.codes).
+Bidirectional control characters can alter the direction in which text appears to be in. For example, via control characters, you can make `defabc` look like `abcdef`. As a result, if you were to unknowingly copy and paste some code that has these control characters, they may alter the behavior of your code in ways you did not intend. See [trojansource.codes](https://trojansource.codes/) for more information.
## legacy_code
From cc7c317263b5e457a40c871256938865d8f5c8be Mon Sep 17 00:00:00 2001
From: Rich Harris
Date: Mon, 12 May 2025 19:09:05 -0400
Subject: [PATCH 15/15] no need to test evaluations, since we are already
testing the literals that they are composed of
---
.../3-transform/client/visitors/shared/utils.js | 12 +-----------
.../3-transform/server/visitors/shared/utils.js | 9 +--------
2 files changed, 2 insertions(+), 19 deletions(-)
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js
index 59e57972f58a..fb3f8df74b1a 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js
@@ -4,12 +4,8 @@
import { walk } from 'zimmerframe';
import { object } from '../../../../../utils/ast.js';
import * as b from '#compiler/builders';
-import * as w from '../../../../../warnings.js';
import { sanitize_template_string } from '../../../../../utils/sanitize_template_string.js';
-import {
- regex_is_valid_identifier,
- regex_bidirectional_control_characters
-} from '../../../../patterns.js';
+import { regex_is_valid_identifier } from '../../../../patterns.js';
import is_reference from 'is-reference';
import { dev, is_ignored, locator } from '../../../../../state.js';
import { create_derived } from '../../utils.js';
@@ -81,9 +77,6 @@ export function build_template_chunk(
// If we have a single expression, then pass that in directly to possibly avoid doing
// extra work in the template_effect (instead we do the work in set_text).
if (evaluated.is_known) {
- if (regex_bidirectional_control_characters.test((evaluated.value ?? '') + '')) {
- w.bidirectional_control_characters(node);
- }
value = b.literal((evaluated.value ?? '') + '');
}
@@ -103,9 +96,6 @@ export function build_template_chunk(
}
if (evaluated.is_known) {
- if (regex_bidirectional_control_characters.test((evaluated.value ?? '') + '')) {
- w.bidirectional_control_characters(node);
- }
quasi.value.cooked += (evaluated.value ?? '') + '';
} else {
if (!evaluated.is_defined) {
diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js
index 1dbde82aae46..8fcf8efa68b6 100644
--- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js
+++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js
@@ -9,12 +9,8 @@ import {
EMPTY_COMMENT
} from '../../../../../../internal/server/hydration.js';
import * as b from '#compiler/builders';
-import * as w from '../../../../../warnings.js';
import { sanitize_template_string } from '../../../../../utils/sanitize_template_string.js';
-import {
- regex_bidirectional_control_characters,
- regex_whitespaces_strict
-} from '../../../../patterns.js';
+import { regex_whitespaces_strict } from '../../../../patterns.js';
/** Opens an if/each block, so that we can remove nodes in the case of a mismatch */
export const block_open = b.literal(BLOCK_OPEN);
@@ -52,9 +48,6 @@ export function process_children(nodes, { visit, state }) {
const evaluated = state.scope.evaluate(node.expression);
if (evaluated.is_known) {
- if (regex_bidirectional_control_characters.test((evaluated.value ?? '') + '')) {
- w.bidirectional_control_characters(node);
- }
quasi.value.cooked += escape_html((evaluated.value ?? '') + '');
} else {
expressions.push(b.call('$.escape', /** @type {Expression} */ (visit(node.expression))));