diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3fceb5f2fc..459cf656c7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,9 @@
## Unreleased
+* Fix misaligned line numbers in source maps ([#3906](https://github.com/sveltejs/svelte/issues/3906))
* Fix reactivity with imported values that are then mutated ([#4555](https://github.com/sveltejs/svelte/issues/4555))
+* Display a11y warning for `href="javascript:..."` ([#4733](https://github.com/sveltejs/svelte/pull/4733))
## 3.21.0
diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts
index c2f7c20c68..f7f3cc55bc 100644
--- a/src/compiler/compile/nodes/Element.ts
+++ b/src/compiler/compile/nodes/Element.ts
@@ -430,7 +430,7 @@ export default class Element extends Node {
if (href_attribute) {
const href_value = href_attribute.get_static_value();
- if (href_value === '' || href_value === '#') {
+ if (href_value === '' || href_value === '#' || /^\W*javascript:/i.test(href_value)) {
component.warn(href_attribute, {
code: `a11y-invalid-attribute`,
message: `A11y: '${href_value}' is not a valid ${href_attribute.name} attribute`
diff --git a/src/compiler/parse/read/script.ts b/src/compiler/parse/read/script.ts
index 130c346ba1..8260894215 100644
--- a/src/compiler/parse/read/script.ts
+++ b/src/compiler/parse/read/script.ts
@@ -37,7 +37,8 @@ export default function read_script(parser: Parser, start: number, attributes: N
message: `
+
+{foo.bar.baz}
diff --git a/test/sourcemaps/samples/script-after-comment/test.js b/test/sourcemaps/samples/script-after-comment/test.js
new file mode 100644
index 0000000000..b473970112
--- /dev/null
+++ b/test/sourcemaps/samples/script-after-comment/test.js
@@ -0,0 +1,16 @@
+export function test({ assert, smc, locateInSource, locateInGenerated }) {
+ const expected = locateInSource( 'assertThisLine' );
+ const start = locateInGenerated( 'assertThisLine' );
+
+ const actual = smc.originalPositionFor({
+ line: start.line + 1,
+ column: start.column
+ });
+
+ assert.deepEqual( actual, {
+ source: 'input.svelte',
+ name: null,
+ line: expected.line + 1,
+ column: expected.column
+ });
+}
diff --git a/test/sourcemaps/samples/two-scripts/input.svelte b/test/sourcemaps/samples/two-scripts/input.svelte
new file mode 100644
index 0000000000..4c869827c0
--- /dev/null
+++ b/test/sourcemaps/samples/two-scripts/input.svelte
@@ -0,0 +1,9 @@
+
+
+
+
+{foo.bar.baz}
diff --git a/test/sourcemaps/samples/two-scripts/test.js b/test/sourcemaps/samples/two-scripts/test.js
new file mode 100644
index 0000000000..b473970112
--- /dev/null
+++ b/test/sourcemaps/samples/two-scripts/test.js
@@ -0,0 +1,16 @@
+export function test({ assert, smc, locateInSource, locateInGenerated }) {
+ const expected = locateInSource( 'assertThisLine' );
+ const start = locateInGenerated( 'assertThisLine' );
+
+ const actual = smc.originalPositionFor({
+ line: start.line + 1,
+ column: start.column
+ });
+
+ assert.deepEqual( actual, {
+ source: 'input.svelte',
+ name: null,
+ line: expected.line + 1,
+ column: expected.column
+ });
+}
diff --git a/test/validator/samples/a11y-anchor-is-valid/input.svelte b/test/validator/samples/a11y-anchor-is-valid/input.svelte
index 7b14a80c9f..6d0f77a308 100644
--- a/test/validator/samples/a11y-anchor-is-valid/input.svelte
+++ b/test/validator/samples/a11y-anchor-is-valid/input.svelte
@@ -1,3 +1,4 @@
not actually a link
invalid
-invalid
\ No newline at end of file
+invalid
+invalid
\ No newline at end of file
diff --git a/test/validator/samples/a11y-anchor-is-valid/warnings.json b/test/validator/samples/a11y-anchor-is-valid/warnings.json
index 532c44ad24..9438a74f5b 100644
--- a/test/validator/samples/a11y-anchor-is-valid/warnings.json
+++ b/test/validator/samples/a11y-anchor-is-valid/warnings.json
@@ -43,5 +43,20 @@
"character": 61
},
"pos": 53
+ },
+ {
+ "code": "a11y-invalid-attribute",
+ "message": "A11y: 'javascript:void(0)' is not a valid href attribute",
+ "start": {
+ "line": 4,
+ "column": 3,
+ "character": 77
+ },
+ "end": {
+ "line": 4,
+ "column": 28,
+ "character": 102
+ },
+ "pos": 77
}
]