@@ -6,8 +6,93 @@ import { getLocator } from 'locate-character';
6
6
import { walk } from 'zimmerframe' ;
7
7
import { validate_component_options , validate_module_options } from './validate-options.js' ;
8
8
import { convert } from './legacy.js' ;
9
+ import { transform_warnings } from './utils/warnings.js' ;
9
10
export { default as preprocess } from './preprocess/index.js' ;
10
11
12
+ /**
13
+ * @param {string } source
14
+ * @param {string | undefined } filename
15
+ * @param {Function } fn
16
+ */
17
+ function handle_error ( source , filename , fn ) {
18
+ try {
19
+ return fn ( ) ;
20
+ } catch ( e ) {
21
+ if ( /** @type {any } */ ( e ) . name === 'CompileError' ) {
22
+ const error = /** @type {import('#compiler').CompileError } */ ( e ) ;
23
+
24
+ error . filename = filename ;
25
+
26
+ if ( error . position ) {
27
+ // TODO this is reused with warnings — DRY out
28
+ const locator = getLocator ( source , { offsetLine : 1 } ) ;
29
+ const start = locator ( error . position [ 0 ] ) ;
30
+ const end = locator ( error . position [ 1 ] ) ;
31
+
32
+ error . start = start ;
33
+ error . end = end ;
34
+ }
35
+ }
36
+
37
+ throw e ;
38
+ }
39
+ }
40
+
41
+ /**
42
+ * The parse function parses a component, returning only its abstract syntax tree.
43
+ *
44
+ * The `modern` option (`false` by default in Svelte 5) makes the parser return a modern AST instead of the legacy AST.
45
+ * `modern` will become `true` by default in Svelte 6, and the option will be removed in Svelte 7.
46
+ *
47
+ * https://svelte.dev/docs/svelte-compiler#svelte-parse
48
+ * @param {string } source
49
+ * @param {{ filename?: string; modern?: boolean } } [options]
50
+ * @returns {import('#compiler').SvelteNode | import('./types/legacy-nodes.js').LegacySvelteNode }
51
+ */
52
+ export function parse ( source , options = { } ) {
53
+ return handle_error ( source , undefined , ( ) => {
54
+ /** @type {import('#compiler').Root } */
55
+ const ast = _parse ( source ) ;
56
+
57
+ if ( options . modern ) {
58
+ // remove things that we don't want to treat as public API
59
+ return walk ( /** @type {import('#compiler').SvelteNode } */ ( ast ) , null , {
60
+ _ ( node , { next } ) {
61
+ // @ts -ignore
62
+ delete node . parent ;
63
+ // @ts -ignore
64
+ delete node . metadata ;
65
+ next ( ) ;
66
+ }
67
+ } ) ;
68
+ }
69
+
70
+ return convert ( source , ast ) ;
71
+ } ) ;
72
+ }
73
+
74
+ /**
75
+ * @param {string } source
76
+ * @param {TODO } options
77
+ */
78
+ export function analyze ( source , options = { } ) {
79
+ return handle_error ( source , options . filename , ( ) => {
80
+ const validated = validate_component_options ( options , '' ) ;
81
+ const parsed = _parse ( source ) ;
82
+
83
+ const combined_options = /** @type {import('#compiler').ValidatedCompileOptions } */ ( {
84
+ ...validated ,
85
+ ...parsed . options
86
+ } ) ;
87
+
88
+ const analysis = analyze_component ( parsed , combined_options ) ;
89
+
90
+ return {
91
+ warnings : transform_warnings ( source , options . filename , analysis . warnings )
92
+ } ;
93
+ } ) ;
94
+ }
95
+
11
96
/**
12
97
* `compile` converts your `.svelte` source code into a JavaScript module that exports a component
13
98
*
@@ -17,7 +102,7 @@ export { default as preprocess } from './preprocess/index.js';
17
102
* @returns {import('#compiler').CompileResult }
18
103
*/
19
104
export function compile ( source , options ) {
20
- try {
105
+ return handle_error ( source , options . filename , ( ) => {
21
106
const validated = validate_component_options ( options , '' ) ;
22
107
const parsed = _parse ( source ) ;
23
108
@@ -29,17 +114,7 @@ export function compile(source, options) {
29
114
const analysis = analyze_component ( parsed , combined_options ) ;
30
115
const result = transform_component ( analysis , source , combined_options ) ;
31
116
return result ;
32
- } catch ( e ) {
33
- if ( /** @type {any } */ ( e ) . name === 'CompileError' ) {
34
- handle_compile_error (
35
- /** @type {import('#compiler').CompileError } */ ( e ) ,
36
- options . filename ,
37
- source
38
- ) ;
39
- }
40
-
41
- throw e ;
42
- }
117
+ } ) ;
43
118
}
44
119
45
120
/**
@@ -51,86 +126,11 @@ export function compile(source, options) {
51
126
* @returns {import('#compiler').CompileResult }
52
127
*/
53
128
export function compileModule ( source , options ) {
54
- try {
129
+ return handle_error ( source , options . filename , ( ) => {
55
130
const validated = validate_module_options ( options , '' ) ;
56
131
const analysis = analyze_module ( parse_acorn ( source ) , validated ) ;
57
132
return transform_module ( analysis , source , validated ) ;
58
- } catch ( e ) {
59
- if ( /** @type {any } */ ( e ) . name === 'CompileError' ) {
60
- handle_compile_error (
61
- /** @type {import('#compiler').CompileError } */ ( e ) ,
62
- options . filename ,
63
- source
64
- ) ;
65
- }
66
-
67
- throw e ;
68
- }
69
- }
70
-
71
- /**
72
- * @param {import('#compiler').CompileError } error
73
- * @param {string | undefined } filename
74
- * @param {string } source
75
- */
76
- function handle_compile_error ( error , filename , source ) {
77
- error . filename = filename ;
78
-
79
- if ( error . position ) {
80
- // TODO this is reused with warnings — DRY out
81
- const locator = getLocator ( source , { offsetLine : 1 } ) ;
82
- const start = locator ( error . position [ 0 ] ) ;
83
- const end = locator ( error . position [ 1 ] ) ;
84
-
85
- error . start = start ;
86
- error . end = end ;
87
- }
88
-
89
- throw error ;
90
- }
91
-
92
- /**
93
- * The parse function parses a component, returning only its abstract syntax tree.
94
- *
95
- * The `modern` option (`false` by default in Svelte 5) makes the parser return a modern AST instead of the legacy AST.
96
- * `modern` will become `true` by default in Svelte 6, and the option will be removed in Svelte 7.
97
- *
98
- * https://svelte.dev/docs/svelte-compiler#svelte-parse
99
- * @param {string } source
100
- * @param {{ filename?: string; modern?: boolean } } [options]
101
- * @returns {import('#compiler').SvelteNode | import('./types/legacy-nodes.js').LegacySvelteNode }
102
- */
103
- export function parse ( source , options = { } ) {
104
- /** @type {import('#compiler').Root } */
105
- let ast ;
106
- try {
107
- ast = _parse ( source ) ;
108
- } catch ( e ) {
109
- if ( /** @type {any } */ ( e ) . name === 'CompileError' ) {
110
- handle_compile_error (
111
- /** @type {import('#compiler').CompileError } */ ( e ) ,
112
- options . filename ,
113
- source
114
- ) ;
115
- }
116
-
117
- throw e ;
118
- }
119
-
120
- if ( options . modern ) {
121
- // remove things that we don't want to treat as public API
122
- return walk ( /** @type {import('#compiler').SvelteNode } */ ( ast ) , null , {
123
- _ ( node , { next } ) {
124
- // @ts -ignore
125
- delete node . parent ;
126
- // @ts -ignore
127
- delete node . metadata ;
128
- next ( ) ;
129
- }
130
- } ) ;
131
- }
132
-
133
- return convert ( source , ast ) ;
133
+ } ) ;
134
134
}
135
135
136
136
/**
0 commit comments