@sveltejs/kit 3.0.0-next.10 → 3.0.0-next.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/constants.js +2 -0
- package/src/core/adapt/builder.js +3 -6
- package/src/core/config/index.js +6 -1
- package/src/core/config/options.js +11 -69
- package/src/core/postbuild/fallback.js +2 -1
- package/src/core/postbuild/prerender.js +75 -28
- package/src/core/postbuild/queue.js +2 -1
- package/src/core/sync/write_server.js +2 -2
- package/src/core/utils.js +28 -3
- package/src/exports/env/index.js +68 -3
- package/src/exports/internal/env.js +6 -3
- package/src/exports/params.js +9 -4
- package/src/exports/public.d.ts +41 -20
- package/src/exports/vite/dev/index.js +50 -6
- package/src/exports/vite/index.js +130 -125
- package/src/exports/vite/module_ids.js +0 -2
- package/src/exports/vite/preview/index.js +3 -2
- package/src/exports/vite/utils.js +20 -0
- package/src/runtime/app/paths/server.js +1 -1
- package/src/runtime/app/server/index.js +1 -1
- package/src/runtime/app/server/remote/query.js +1 -1
- package/src/runtime/client/ndjson.js +1 -1
- package/src/runtime/client/stream.js +3 -2
- package/src/runtime/server/data/index.js +1 -1
- package/src/runtime/server/errors.js +135 -0
- package/src/runtime/server/fetch.js +1 -1
- package/src/runtime/server/index.js +20 -10
- package/src/runtime/server/internal.js +25 -0
- package/src/runtime/server/page/actions.js +2 -1
- package/src/runtime/server/page/data_serializer.js +10 -10
- package/src/runtime/server/page/index.js +3 -2
- package/src/runtime/server/page/load_data.js +1 -1
- package/src/runtime/server/page/render.js +3 -7
- package/src/runtime/server/page/respond_with_error.js +6 -5
- package/src/runtime/server/{remote.js → remote-functions.js} +1 -1
- package/src/runtime/server/respond.js +3 -7
- package/src/runtime/server/sourcemaps.js +183 -0
- package/src/runtime/server/utils.js +2 -157
- package/src/types/ambient-private.d.ts +2 -0
- package/src/types/global-private.d.ts +0 -5
- package/src/types/internal.d.ts +6 -6
- package/src/types/private.d.ts +8 -0
- package/src/utils/escape.js +9 -25
- package/src/utils/features.js +1 -1
- package/src/utils/fork.js +7 -2
- package/src/utils/page_nodes.js +3 -5
- package/src/version.js +1 -1
- package/types/index.d.ts +72 -22
- package/types/index.d.ts.map +3 -1
- package/src/runtime/shared-server.js +0 -7
|
@@ -2,10 +2,10 @@ import { noop } from '../../utils/functions.js';
|
|
|
2
2
|
import { IN_WEBCONTAINER } from './constants.js';
|
|
3
3
|
import { respond } from './respond.js';
|
|
4
4
|
import { options, get_hooks } from '__SERVER__/internal.js';
|
|
5
|
-
import {
|
|
6
|
-
import { set_read_implementation, set_manifest } from '__sveltekit/server';
|
|
5
|
+
import { set_read_implementation, set_manifest } from './internal.js';
|
|
7
6
|
import { set_env } from '__sveltekit/env';
|
|
8
7
|
import { set_app } from './app.js';
|
|
8
|
+
import { SvelteKitError } from '@sveltejs/kit/internal';
|
|
9
9
|
|
|
10
10
|
/** @type {Promise<any>} */
|
|
11
11
|
let init_promise;
|
|
@@ -107,13 +107,23 @@ export class Server {
|
|
|
107
107
|
handle: module.handle || (({ event, resolve }) => resolve(event)),
|
|
108
108
|
handleError:
|
|
109
109
|
module.handleError ||
|
|
110
|
-
(({
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
(({ error }) => {
|
|
111
|
+
if (error instanceof SvelteKitError) {
|
|
112
|
+
// don't log stack traces for 404s etc, it's all internal gubbins
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let e = error;
|
|
117
|
+
while (e instanceof Error) {
|
|
118
|
+
if (e.stack) {
|
|
119
|
+
console.error(e.stack);
|
|
120
|
+
}
|
|
121
|
+
e = e.cause;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (e) {
|
|
125
|
+
console.error(String(e));
|
|
126
|
+
}
|
|
117
127
|
}),
|
|
118
128
|
handleFetch: module.handleFetch || (({ request, fetch }) => fetch(request)),
|
|
119
129
|
handleValidationError:
|
|
@@ -164,7 +174,7 @@ export class Server {
|
|
|
164
174
|
* @param {Request} request
|
|
165
175
|
* @param {import('types').RequestOptions} options
|
|
166
176
|
*/
|
|
167
|
-
|
|
177
|
+
respond(request, options) {
|
|
168
178
|
return respond(request, this.#options, this.#manifest, {
|
|
169
179
|
...options,
|
|
170
180
|
error: false,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** @import { SSRManifest } from '@sveltejs/kit'; */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @type {((path: string) => ReadableStream<any>) | null}
|
|
5
|
+
*/
|
|
6
|
+
export let read_implementation = null;
|
|
7
|
+
|
|
8
|
+
export let manifest = /** @type {SSRManifest} */ (/** @type {unknown} */ (null));
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {(path: string) => ReadableStream<any>} fn
|
|
12
|
+
*/
|
|
13
|
+
export function set_read_implementation(fn) {
|
|
14
|
+
read_implementation = fn;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
* @param {SSRManifest} value
|
|
20
|
+
*/
|
|
21
|
+
export function set_manifest(value) {
|
|
22
|
+
manifest = value;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { fix_stack_trace, set_fix_stack_trace } from './sourcemaps.js';
|
|
@@ -7,7 +7,8 @@ import { HttpError, Redirect, ActionFailure, SvelteKitError } from '@sveltejs/ki
|
|
|
7
7
|
import { with_request_store, merge_tracing } from '@sveltejs/kit/internal/server';
|
|
8
8
|
import { normalize_error } from '../../../utils/error.js';
|
|
9
9
|
import { is_form_content_type, negotiate } from '../../../utils/http.js';
|
|
10
|
-
import { create_replacer
|
|
10
|
+
import { create_replacer } from '../utils.js';
|
|
11
|
+
import { handle_error_and_jsonify } from '../errors.js';
|
|
11
12
|
import { record_span } from '../../telemetry/record_span.js';
|
|
12
13
|
|
|
13
14
|
/** @param {RequestEvent} event */
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import * as devalue from 'devalue';
|
|
2
2
|
import { compact } from '../../../utils/array.js';
|
|
3
3
|
import { create_async_iterator } from '../../../utils/streaming.js';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
get_global_name,
|
|
7
|
-
handle_error_and_jsonify,
|
|
8
|
-
serialize_uses
|
|
9
|
-
} from '../utils.js';
|
|
4
|
+
import { clarify_devalue_error, get_global_name, serialize_uses } from '../utils.js';
|
|
5
|
+
import { handle_error_and_jsonify } from '../errors.js';
|
|
10
6
|
|
|
11
7
|
/**
|
|
12
8
|
* If the serialized data contains promises, `chunks` will be an
|
|
@@ -45,12 +41,14 @@ export function server_data_serializer(event, event_state, options) {
|
|
|
45
41
|
let str;
|
|
46
42
|
try {
|
|
47
43
|
str = devalue.uneval(error ? [, error] : [data], replacer);
|
|
48
|
-
} catch {
|
|
44
|
+
} catch (e) {
|
|
49
45
|
error = await handle_error_and_jsonify(
|
|
50
46
|
event,
|
|
51
47
|
event_state,
|
|
52
48
|
options,
|
|
53
|
-
new Error(`Failed to serialize promise while rendering ${event.route.id}
|
|
49
|
+
new Error(`Failed to serialize promise while rendering ${event.route.id}`, {
|
|
50
|
+
cause: e
|
|
51
|
+
})
|
|
54
52
|
);
|
|
55
53
|
str = devalue.uneval([, error], replacer);
|
|
56
54
|
}
|
|
@@ -164,12 +162,14 @@ export function server_data_serializer_json(event, event_state, options) {
|
|
|
164
162
|
let str;
|
|
165
163
|
try {
|
|
166
164
|
str = devalue.stringify(value, reducers);
|
|
167
|
-
} catch {
|
|
165
|
+
} catch (e) {
|
|
168
166
|
const error = await handle_error_and_jsonify(
|
|
169
167
|
event,
|
|
170
168
|
event_state,
|
|
171
169
|
options,
|
|
172
|
-
new Error(`Failed to serialize promise while rendering ${event.route.id}
|
|
170
|
+
new Error(`Failed to serialize promise while rendering ${event.route.id}`, {
|
|
171
|
+
cause: e
|
|
172
|
+
})
|
|
173
173
|
);
|
|
174
174
|
|
|
175
175
|
key = 'error';
|
|
@@ -7,7 +7,8 @@ import { compact } from '../../../utils/array.js';
|
|
|
7
7
|
import { get_status, normalize_error } from '../../../utils/error.js';
|
|
8
8
|
import { noop } from '../../../utils/functions.js';
|
|
9
9
|
import { add_data_suffix } from '../../pathname.js';
|
|
10
|
-
import { redirect_response
|
|
10
|
+
import { redirect_response } from '../utils.js';
|
|
11
|
+
import { static_error_page, handle_error_and_jsonify } from '../errors.js';
|
|
11
12
|
import {
|
|
12
13
|
handle_action_json_request,
|
|
13
14
|
handle_action_request,
|
|
@@ -19,7 +20,7 @@ import { load_data, load_server_data } from './load_data.js';
|
|
|
19
20
|
import { render_response } from './render.js';
|
|
20
21
|
import { respond_with_error } from './respond_with_error.js';
|
|
21
22
|
import { DEV } from 'esm-env';
|
|
22
|
-
import { get_remote_action, handle_remote_form_post } from '../remote.js';
|
|
23
|
+
import { get_remote_action, handle_remote_form_post } from '../remote-functions.js';
|
|
23
24
|
import { PageNodes } from '../../../utils/page_nodes.js';
|
|
24
25
|
|
|
25
26
|
/**
|
|
@@ -465,7 +465,7 @@ export function create_universal_fetch(event, state, fetched, csr, resolve_opts)
|
|
|
465
465
|
const included = resolve_opts.filterSerializedResponseHeaders(lower, value);
|
|
466
466
|
if (!included) {
|
|
467
467
|
throw new Error(
|
|
468
|
-
`Failed to get response header "${lower}" — it must be included by the \`filterSerializedResponseHeaders\` option: https://svelte.dev/docs/kit/hooks#
|
|
468
|
+
`Failed to get response header "${lower}" — it must be included by the \`filterSerializedResponseHeaders\` option: https://svelte.dev/docs/kit/hooks#handle (at ${event.route.id})`
|
|
469
469
|
);
|
|
470
470
|
}
|
|
471
471
|
}
|
|
@@ -14,14 +14,10 @@ import { create_server_routing_response, generate_route_object } from './server_
|
|
|
14
14
|
import { add_data_suffix, add_resolution_suffix } from '../../pathname.js';
|
|
15
15
|
import { try_get_request_store, with_request_store } from '@sveltejs/kit/internal/server';
|
|
16
16
|
import { text_encoder } from '../../utils.js';
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
create_replacer,
|
|
20
|
-
get_global_name,
|
|
21
|
-
handle_error_and_jsonify
|
|
22
|
-
} from '../utils.js';
|
|
17
|
+
import { count_non_ssi_comments, create_replacer, get_global_name } from '../utils.js';
|
|
18
|
+
import { handle_error_and_jsonify } from '../errors.js';
|
|
23
19
|
import * as env from '__sveltekit/env';
|
|
24
|
-
import { collect_remote_data } from '../remote.js';
|
|
20
|
+
import { collect_remote_data } from '../remote-functions.js';
|
|
25
21
|
import Root from '../../components/root.svelte';
|
|
26
22
|
import { render } from 'svelte/server';
|
|
27
23
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Redirect } from '@sveltejs/kit/internal';
|
|
2
2
|
import { render_response } from './render.js';
|
|
3
3
|
import { load_data, load_server_data } from './load_data.js';
|
|
4
|
-
import {
|
|
4
|
+
import { redirect_response } from '../utils.js';
|
|
5
|
+
import { handle_error_and_jsonify, static_error_page } from '../errors.js';
|
|
5
6
|
import { PageNodes } from '../../../utils/page_nodes.js';
|
|
6
7
|
import { server_data_serializer } from './data_serializer.js';
|
|
7
8
|
|
|
@@ -33,12 +34,12 @@ export async function respond_with_error({
|
|
|
33
34
|
}) {
|
|
34
35
|
// reroute to the fallback page to prevent an infinite chain of requests.
|
|
35
36
|
if (event.request.headers.get('x-sveltekit-error')) {
|
|
36
|
-
|
|
37
|
+
const transformed = await handle_error_and_jsonify(event, event_state, options, error);
|
|
38
|
+
return static_error_page(options, status, transformed.message);
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
/** @type {import('./types.js').Fetched[]} */
|
|
40
42
|
const fetched = [];
|
|
41
|
-
|
|
42
43
|
try {
|
|
43
44
|
const branch = [];
|
|
44
45
|
const default_layout = await manifest._.nodes[0](); // 0 is always the root layout
|
|
@@ -46,6 +47,8 @@ export async function respond_with_error({
|
|
|
46
47
|
const ssr = nodes.ssr();
|
|
47
48
|
const csr = nodes.csr();
|
|
48
49
|
const data_serializer = server_data_serializer(event, event_state, options);
|
|
50
|
+
// Do this here first in case the awaits below before rendering themselves error
|
|
51
|
+
const transformed = await handle_error_and_jsonify(event, event_state, options, error);
|
|
49
52
|
|
|
50
53
|
if (ssr) {
|
|
51
54
|
state.error = true;
|
|
@@ -89,8 +92,6 @@ export async function respond_with_error({
|
|
|
89
92
|
);
|
|
90
93
|
}
|
|
91
94
|
|
|
92
|
-
const transformed = await handle_error_and_jsonify(event, event_state, options, error);
|
|
93
|
-
|
|
94
95
|
return await render_response({
|
|
95
96
|
options,
|
|
96
97
|
manifest,
|
|
@@ -7,7 +7,7 @@ import { with_request_store, merge_tracing } from '@sveltejs/kit/internal/server
|
|
|
7
7
|
import { app_dir, base } from '$app/paths/internal/server';
|
|
8
8
|
import { is_form_content_type } from '../../utils/http.js';
|
|
9
9
|
import { create_remote_key, parse_remote_arg, split_remote_key, stringify } from '../shared.js';
|
|
10
|
-
import { handle_error_and_jsonify } from './
|
|
10
|
+
import { handle_error_and_jsonify } from './errors.js';
|
|
11
11
|
import { normalize_error } from '../../utils/error.js';
|
|
12
12
|
import { check_incorrect_fail_use } from './page/actions.js';
|
|
13
13
|
import { DEV } from 'esm-env';
|
|
@@ -9,12 +9,8 @@ import { render_page } from './page/index.js';
|
|
|
9
9
|
import { render_response } from './page/render.js';
|
|
10
10
|
import { respond_with_error } from './page/respond_with_error.js';
|
|
11
11
|
import { get_self_origin, is_csrf_forbidden, is_remote_forbidden } from './csrf.js';
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
has_prerendered_path,
|
|
15
|
-
method_not_allowed,
|
|
16
|
-
redirect_response
|
|
17
|
-
} from './utils.js';
|
|
12
|
+
import { has_prerendered_path, method_not_allowed, redirect_response } from './utils.js';
|
|
13
|
+
import { handle_fatal_error } from './errors.js';
|
|
18
14
|
import { decode_pathname, disable_search, normalize_path } from '../../utils/url.js';
|
|
19
15
|
import { find_route } from '../../utils/routing.js';
|
|
20
16
|
import { redirect_json_response, render_data } from './data/index.js';
|
|
@@ -36,7 +32,7 @@ import {
|
|
|
36
32
|
strip_resolution_suffix
|
|
37
33
|
} from '../pathname.js';
|
|
38
34
|
import { server_data_serializer } from './page/data_serializer.js';
|
|
39
|
-
import { get_remote_id, handle_remote_call } from './remote.js';
|
|
35
|
+
import { get_remote_id, handle_remote_call } from './remote-functions.js';
|
|
40
36
|
import { record_span } from '../telemetry/record_span.js';
|
|
41
37
|
import { otel } from '../telemetry/otel.js';
|
|
42
38
|
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/* eslint-disable n/prefer-global/process */
|
|
2
|
+
|
|
3
|
+
// using `getBuiltinModule` rather than `import` makes this safe to run in non-Node-compatible environments
|
|
4
|
+
const fs = globalThis.process?.getBuiltinModule?.('node:fs');
|
|
5
|
+
const url = globalThis.process?.getBuiltinModule?.('node:url');
|
|
6
|
+
const path = globalThis.process?.getBuiltinModule?.('node:path');
|
|
7
|
+
const module = globalThis.process?.getBuiltinModule?.('node:module');
|
|
8
|
+
|
|
9
|
+
const cwd = globalThis.process?.cwd?.();
|
|
10
|
+
|
|
11
|
+
/** @type {(file: string) => string} */
|
|
12
|
+
const relative = cwd ? (file) => path.relative(cwd, file) : (file) => file;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Applies sourcemaps, makes paths relative to the cwd, and truncates
|
|
16
|
+
* non-user code from the bottom of the stack
|
|
17
|
+
* @param {Error} error
|
|
18
|
+
* @returns void
|
|
19
|
+
*/
|
|
20
|
+
export let fix_stack_trace = (error) => {
|
|
21
|
+
if (!error.stack || !fs) return;
|
|
22
|
+
|
|
23
|
+
let end = 0;
|
|
24
|
+
|
|
25
|
+
error.stack = error.stack
|
|
26
|
+
.split('\n')
|
|
27
|
+
.map((line, i) => {
|
|
28
|
+
const match = line.match(/^ {4}at.+(file:\/\/\/.*):(\d+):(\d+)(\)?)$/);
|
|
29
|
+
|
|
30
|
+
if (!match) {
|
|
31
|
+
if (!line.includes('node:internal/')) {
|
|
32
|
+
end = i + 1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return line;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const file = url.fileURLToPath(match[1]);
|
|
39
|
+
const traced = trace(file, Number(match[2]) - 1, Number(match[3]) - 1);
|
|
40
|
+
|
|
41
|
+
// truncate non-user code from the bottom of the stack (but leave it in otherwise)
|
|
42
|
+
if (!/[\\/]node_modules[\\/]/.test(traced?.file ?? file)) {
|
|
43
|
+
end = i + 1;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (traced?.line) {
|
|
47
|
+
const location = `${match[1]}:${match[2]}:${match[3]}`;
|
|
48
|
+
const original = `${relative(traced.file)}:${traced.line}:${traced.column}`;
|
|
49
|
+
|
|
50
|
+
return line.replace(location, original);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (traced) {
|
|
54
|
+
return `${line.replace(match[1], relative(file))} [${traced.file}]`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return line;
|
|
58
|
+
})
|
|
59
|
+
.slice(0, end)
|
|
60
|
+
.join('\n');
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Override the implementation of fix_stack_trace (for using during dev)
|
|
65
|
+
* @param {(error: Error) => void} fn
|
|
66
|
+
*/
|
|
67
|
+
export function set_fix_stack_trace(fn) {
|
|
68
|
+
fix_stack_trace = fn;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** @type {Map<string, { map: import('node:module').SourceMap; directory: string } | null>} */
|
|
72
|
+
const source_maps = new Map();
|
|
73
|
+
|
|
74
|
+
/** @type {Map<string, Array<string | undefined>>} */
|
|
75
|
+
const source_regions = new Map();
|
|
76
|
+
|
|
77
|
+
/** @param {string} file */
|
|
78
|
+
function get_source_map(file) {
|
|
79
|
+
if (source_maps.has(file)) {
|
|
80
|
+
return source_maps.get(file);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
let source;
|
|
85
|
+
let directory = path.dirname(file);
|
|
86
|
+
|
|
87
|
+
const code = fs.readFileSync(file, 'utf8');
|
|
88
|
+
const matches = Array.from(code.matchAll(/\/\/[#@]\s*sourceMappingURL=(\S+)/g));
|
|
89
|
+
const url = matches.at(-1)?.[1];
|
|
90
|
+
|
|
91
|
+
if (url?.startsWith('data:')) {
|
|
92
|
+
const comma = url.indexOf(',');
|
|
93
|
+
const metadata = url.slice(5, comma);
|
|
94
|
+
const data = url.slice(comma + 1);
|
|
95
|
+
source = metadata.endsWith(';base64')
|
|
96
|
+
? Buffer.from(data, 'base64').toString()
|
|
97
|
+
: decodeURIComponent(data);
|
|
98
|
+
} else {
|
|
99
|
+
const map_file = url
|
|
100
|
+
? path.resolve(path.dirname(file), decodeURIComponent(url))
|
|
101
|
+
: `${file}.map`;
|
|
102
|
+
if (fs.existsSync(map_file)) {
|
|
103
|
+
directory = path.dirname(map_file);
|
|
104
|
+
source = fs.readFileSync(map_file, 'utf8');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (source) {
|
|
109
|
+
const source_map = { map: new module.SourceMap(JSON.parse(source)), directory };
|
|
110
|
+
source_maps.set(file, source_map);
|
|
111
|
+
|
|
112
|
+
return source_map;
|
|
113
|
+
}
|
|
114
|
+
} catch {
|
|
115
|
+
// failure could be for any reason and this is best-effort, ignore
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
source_maps.set(file, null);
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
*
|
|
124
|
+
* @param {string} file
|
|
125
|
+
* @param {number} line
|
|
126
|
+
* @param {number} column
|
|
127
|
+
* @returns {null | { file: string, line?: number, column?: number }}
|
|
128
|
+
*/
|
|
129
|
+
function trace(file, line, column) {
|
|
130
|
+
const source_map = get_source_map(file);
|
|
131
|
+
if (!source_map) return null;
|
|
132
|
+
|
|
133
|
+
const entry = source_map.map.findEntry(line, column);
|
|
134
|
+
|
|
135
|
+
if (
|
|
136
|
+
entry &&
|
|
137
|
+
'originalSource' in entry &&
|
|
138
|
+
entry.originalSource &&
|
|
139
|
+
typeof entry.originalLine === 'number' &&
|
|
140
|
+
typeof entry.originalColumn === 'number'
|
|
141
|
+
) {
|
|
142
|
+
const source = entry.originalSource.startsWith('file:')
|
|
143
|
+
? url.fileURLToPath(entry.originalSource)
|
|
144
|
+
: path.resolve(source_map.directory, entry.originalSource);
|
|
145
|
+
|
|
146
|
+
const traced = {
|
|
147
|
+
file: source,
|
|
148
|
+
line: entry.originalLine + 1,
|
|
149
|
+
column: entry.originalColumn + 1
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// keep going, in case we are running code that was bundled a second time by an adapter
|
|
153
|
+
return trace(traced.file, traced.line - 1, traced.column - 1) ?? traced;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
let regions = source_regions.get(file);
|
|
157
|
+
if (!regions) {
|
|
158
|
+
/** @type {string | undefined} */
|
|
159
|
+
let source;
|
|
160
|
+
regions = fs
|
|
161
|
+
.readFileSync(file, 'utf8')
|
|
162
|
+
.split('\n')
|
|
163
|
+
.map((line) => {
|
|
164
|
+
// Vite will merge multiple files into one but add region markers
|
|
165
|
+
// with the original file names, which we try to extract here.
|
|
166
|
+
const start = line.match(/^\/\/#region (.+)$/);
|
|
167
|
+
if (start) source = start[1];
|
|
168
|
+
if (line === '//#endregion') source = undefined;
|
|
169
|
+
return source;
|
|
170
|
+
});
|
|
171
|
+
source_regions.set(file, regions);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const source = regions[line];
|
|
175
|
+
|
|
176
|
+
if (source) {
|
|
177
|
+
return {
|
|
178
|
+
file: source
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
/** @import { ServerHooks } from 'types' */
|
|
2
2
|
import * as devalue from 'devalue';
|
|
3
|
-
import {
|
|
4
|
-
import { json, text } from '@sveltejs/kit';
|
|
5
|
-
import { HttpError } from '@sveltejs/kit/internal';
|
|
6
|
-
import { with_request_store } from '@sveltejs/kit/internal/server';
|
|
7
|
-
import { coalesce_to_error, get_message, get_status } from '../../utils/error.js';
|
|
8
|
-
import { negotiate } from '../../utils/http.js';
|
|
9
|
-
import { fix_stack_trace } from '../shared-server.js';
|
|
3
|
+
import { text } from '@sveltejs/kit';
|
|
10
4
|
import { ENDPOINT_METHODS } from '../../constants.js';
|
|
11
|
-
import { escape_html } from '../../utils/escape.js';
|
|
12
|
-
import * as path from '../../utils/path.js';
|
|
13
5
|
|
|
14
6
|
/**
|
|
15
7
|
* @param {Partial<Record<import('types').HttpMethod, any>>} mod
|
|
@@ -46,103 +38,6 @@ export function get_global_name(options) {
|
|
|
46
38
|
return __SVELTEKIT_DEV__ ? '__sveltekit_dev' : `__sveltekit_${options.version_hash}`;
|
|
47
39
|
}
|
|
48
40
|
|
|
49
|
-
/**
|
|
50
|
-
* Return as a response that renders the error.html
|
|
51
|
-
*
|
|
52
|
-
* @param {import('types').SSROptions} options
|
|
53
|
-
* @param {number} status
|
|
54
|
-
* @param {string} message
|
|
55
|
-
*/
|
|
56
|
-
export function static_error_page(options, status, message) {
|
|
57
|
-
let page = options.templates.error({ status, message: escape_html(message) });
|
|
58
|
-
|
|
59
|
-
if (__SVELTEKIT_DEV__) {
|
|
60
|
-
// inject Vite HMR client, for easier debugging
|
|
61
|
-
page = page.replace('</head>', '<script type="module" src="/@vite/client"></script></head>');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return text(page, {
|
|
65
|
-
headers: { 'content-type': 'text/html; charset=utf-8' },
|
|
66
|
-
status
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
72
|
-
* @param {import('types').RequestState} state
|
|
73
|
-
* @param {import('types').SSROptions} options
|
|
74
|
-
* @param {unknown} error
|
|
75
|
-
*/
|
|
76
|
-
export async function handle_fatal_error(event, state, options, error) {
|
|
77
|
-
error = error instanceof HttpError ? error : coalesce_to_error(error);
|
|
78
|
-
const body = await handle_error_and_jsonify(event, state, options, error);
|
|
79
|
-
const status = body.status;
|
|
80
|
-
|
|
81
|
-
// ideally we'd use sec-fetch-dest instead, but Safari — quelle surprise — doesn't support it
|
|
82
|
-
const type = negotiate(event.request.headers.get('accept') || 'text/html', [
|
|
83
|
-
'application/json',
|
|
84
|
-
'text/html'
|
|
85
|
-
]);
|
|
86
|
-
|
|
87
|
-
if (event.isDataRequest || type === 'application/json') {
|
|
88
|
-
return json(body, {
|
|
89
|
-
status
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return static_error_page(options, status, body.message);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
98
|
-
* @param {import('types').RequestState} state
|
|
99
|
-
* @param {import('types').SSROptions} options
|
|
100
|
-
* @param {any} error
|
|
101
|
-
* @returns {App.Error | Promise<App.Error>}
|
|
102
|
-
*/
|
|
103
|
-
export function handle_error_and_jsonify(event, state, options, error) {
|
|
104
|
-
if (error instanceof HttpError) {
|
|
105
|
-
// @ts-expect-error custom user errors may not have a message field if App.Error is overwritten
|
|
106
|
-
return { message: 'Unknown Error', ...error.body };
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (__SVELTEKIT_DEV__ && typeof error == 'object') {
|
|
110
|
-
fix_stack_trace(error);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const status = get_status(error);
|
|
114
|
-
const message = get_message(error);
|
|
115
|
-
|
|
116
|
-
// TODO 4.0 await this, rather than handling the non-Promise case
|
|
117
|
-
const result = with_request_store({ event, state }, () =>
|
|
118
|
-
options.hooks.handleError({ error, event, status, message })
|
|
119
|
-
) ?? { status, message };
|
|
120
|
-
|
|
121
|
-
if (result instanceof Promise) {
|
|
122
|
-
if (!__SVELTEKIT_SUPPORTS_ASYNC__ && state.is_in_render) {
|
|
123
|
-
console.warn(
|
|
124
|
-
`To use an async \`handleError\` hook to handle errors that occur during rendering, you must enable \`compilerOptions.experimental.async\` in the SvelteKit plugin of your Vite config. The returned error has been replaced with a generic object`
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
// we're discarding the result, but we still need to prevent an unhandled
|
|
128
|
-
// rejection if the user's async `handleError` hook rejects
|
|
129
|
-
result.catch(() => {});
|
|
130
|
-
|
|
131
|
-
return {
|
|
132
|
-
status,
|
|
133
|
-
message: 'Internal Error'
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return result.then((body) => {
|
|
138
|
-
body ??= { status, message };
|
|
139
|
-
return { ...body, status: get_status(body, error) };
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return { ...result, status: get_status(result, error) };
|
|
144
|
-
}
|
|
145
|
-
|
|
146
41
|
/**
|
|
147
42
|
* @param {number} status
|
|
148
43
|
* @param {string} location
|
|
@@ -163,7 +58,7 @@ export function clarify_devalue_error(event, error) {
|
|
|
163
58
|
if (error.path) {
|
|
164
59
|
return (
|
|
165
60
|
`Data returned from \`load\` while rendering ${event.route.id} is not serializable: ${error.message} (${error.path}). ` +
|
|
166
|
-
`If you need to serialize/deserialize custom types, use transport hooks: https://svelte.dev/docs/kit/hooks#
|
|
61
|
+
`If you need to serialize/deserialize custom types, use transport hooks: https://svelte.dev/docs/kit/hooks#transport.`
|
|
167
62
|
);
|
|
168
63
|
}
|
|
169
64
|
|
|
@@ -212,56 +107,6 @@ export function has_prerendered_path(manifest, pathname) {
|
|
|
212
107
|
);
|
|
213
108
|
}
|
|
214
109
|
|
|
215
|
-
/**
|
|
216
|
-
* Formats the error into a nice message with sanitized stack trace
|
|
217
|
-
* @param {number} status
|
|
218
|
-
* @param {Error} error
|
|
219
|
-
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
220
|
-
*/
|
|
221
|
-
export function format_server_error(status, error, event) {
|
|
222
|
-
const formatted_text = `\n\x1b[1;31m[${status}] ${event.request.method} ${event.url.pathname}\x1b[0m`;
|
|
223
|
-
|
|
224
|
-
if (status === 404) {
|
|
225
|
-
return formatted_text;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
return `${formatted_text}\n${DEV ? clean_up_stack_trace(error) : error.stack}`;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* In dev, tidy up stack traces by making paths relative to the current project directory
|
|
233
|
-
* @param {string} file
|
|
234
|
-
*/
|
|
235
|
-
let relative = (file) => file;
|
|
236
|
-
|
|
237
|
-
if (DEV) {
|
|
238
|
-
try {
|
|
239
|
-
relative = (file) => path.relative(__SVELTEKIT_ROOT__, file);
|
|
240
|
-
} catch {
|
|
241
|
-
// do nothing
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Provides a refined stack trace by excluding lines following the last occurrence of a line containing +page. +layout. or +server.
|
|
247
|
-
* @param {Error} error
|
|
248
|
-
*/
|
|
249
|
-
export function clean_up_stack_trace(error) {
|
|
250
|
-
const stack_trace = (error.stack?.split('\n') ?? []).map((line) => {
|
|
251
|
-
return line.replace(/\((.+)(:\d+:\d+)\)$/, (_, file, loc) => `(${relative(file)}${loc})`);
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
// progressive enhancement for people who haven't configured files.src to something else
|
|
255
|
-
const last_line_from_src_code = stack_trace.findLastIndex((line) => /\(src[\\/]/.test(line));
|
|
256
|
-
|
|
257
|
-
if (last_line_from_src_code === -1) {
|
|
258
|
-
// default to the whole stack trace
|
|
259
|
-
return error.stack;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return stack_trace.slice(0, last_line_from_src_code + 1).join('\n');
|
|
263
|
-
}
|
|
264
|
-
|
|
265
110
|
/**
|
|
266
111
|
* Returns the filename without the extension. e.g., `+page.server`, `+page`, etc.
|
|
267
112
|
* @param {string | undefined} node_id
|
|
@@ -13,8 +13,10 @@ declare module '__sveltekit/paths' {
|
|
|
13
13
|
declare module '__sveltekit/server' {
|
|
14
14
|
import { SSRManifest } from '@sveltejs/kit';
|
|
15
15
|
|
|
16
|
+
export let fix_stack_trace: (error: Error) => string;
|
|
16
17
|
export let manifest: SSRManifest;
|
|
17
18
|
export function read_implementation(path: string): ReadableStream;
|
|
19
|
+
export function set_fix_stack_trace(fn: (error: Error) => string): void;
|
|
18
20
|
export function set_manifest(manifest: SSRManifest): void;
|
|
19
21
|
export function set_read_implementation(fn: (path: string) => ReadableStream): void;
|
|
20
22
|
}
|
|
@@ -38,11 +38,6 @@ declare global {
|
|
|
38
38
|
* Should only be used when bundleStrategy !== 'inline' to avoid SvelteKit runtime changing on every build, preventing cacheability.
|
|
39
39
|
*/
|
|
40
40
|
const __SVELTEKIT_PAYLOAD__: SvelteKitPayload;
|
|
41
|
-
/**
|
|
42
|
-
* The Vite `root` setting used to construct paths to nodes and components
|
|
43
|
-
* for the SSR manifest during development
|
|
44
|
-
*/
|
|
45
|
-
const __SVELTEKIT_ROOT__: string;
|
|
46
41
|
/**
|
|
47
42
|
* Whether the `experimental.async` flag is applied
|
|
48
43
|
*/
|