@sveltejs/kit 1.0.11 → 1.0.13

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.
Files changed (45) hide show
  1. package/package.json +3 -3
  2. package/src/core/adapt/builder.js +1 -1
  3. package/src/core/{prerender → postbuild}/crawl.js +0 -0
  4. package/src/core/{prerender → postbuild}/entities.js +0 -0
  5. package/src/core/{prerender → postbuild}/fallback.js +10 -7
  6. package/src/core/postbuild/index.js +104 -0
  7. package/src/core/{prerender → postbuild}/prerender.js +32 -106
  8. package/src/core/{prerender → postbuild}/queue.js +0 -0
  9. package/src/core/sync/sync.js +10 -0
  10. package/src/core/sync/write_client_manifest.js +1 -1
  11. package/src/core/sync/write_server.js +89 -0
  12. package/src/core/utils.js +0 -9
  13. package/src/exports/vite/build/build_server.js +11 -163
  14. package/src/exports/vite/build/build_service_worker.js +3 -2
  15. package/src/exports/vite/build/utils.js +1 -0
  16. package/src/exports/vite/dev/index.js +72 -114
  17. package/src/exports/vite/index.js +26 -27
  18. package/src/exports/vite/preview/index.js +11 -12
  19. package/src/runtime/app/environment.js +1 -1
  20. package/src/runtime/app/paths.js +1 -1
  21. package/src/runtime/client/client.js +8 -2
  22. package/src/runtime/client/fetcher.js +12 -4
  23. package/src/runtime/client/start.js +1 -2
  24. package/src/runtime/client/types.d.ts +1 -1
  25. package/src/runtime/client/utils.js +1 -2
  26. package/src/runtime/control.js +23 -5
  27. package/src/runtime/server/ambient.d.ts +8 -0
  28. package/src/runtime/server/cookie.js +4 -5
  29. package/src/runtime/server/data/index.js +5 -2
  30. package/src/runtime/server/endpoint.js +5 -5
  31. package/src/runtime/server/fetch.js +11 -9
  32. package/src/runtime/server/index.js +54 -395
  33. package/src/runtime/server/page/csp.js +9 -11
  34. package/src/runtime/server/page/index.js +13 -8
  35. package/src/runtime/server/page/load_data.js +2 -3
  36. package/src/runtime/server/page/render.js +28 -25
  37. package/src/runtime/server/page/respond_with_error.js +20 -13
  38. package/src/runtime/server/page/types.d.ts +0 -1
  39. package/src/runtime/server/respond.js +419 -0
  40. package/src/runtime/server/utils.js +21 -4
  41. package/src/runtime/shared.js +28 -0
  42. package/types/index.d.ts +10 -5
  43. package/types/internal.d.ts +22 -39
  44. package/src/runtime/env.js +0 -12
  45. package/src/runtime/paths.js +0 -11
@@ -1,405 +1,64 @@
1
- import { DEV } from 'esm-env';
2
- import { is_endpoint_request, render_endpoint } from './endpoint.js';
3
- import { render_page } from './page/index.js';
4
- import { render_response } from './page/render.js';
5
- import { respond_with_error } from './page/respond_with_error.js';
6
- import { is_form_content_type } from '../../utils/http.js';
7
- import { GENERIC_ERROR, get_option, handle_fatal_error, redirect_response } from './utils.js';
8
- import {
9
- decode_pathname,
10
- decode_params,
11
- disable_search,
12
- has_data_suffix,
13
- normalize_path,
14
- strip_data_suffix
15
- } from '../../utils/url.js';
16
- import { exec } from '../../utils/routing.js';
17
- import { INVALIDATED_PARAM, redirect_json_response, render_data } from './data/index.js';
18
- import { add_cookies_to_headers, get_cookies } from './cookie.js';
19
- import { create_fetch } from './fetch.js';
20
- import { Redirect } from '../control.js';
21
- import {
22
- validate_common_exports,
23
- validate_page_server_exports,
24
- validate_server_exports
25
- } from '../../utils/exports.js';
26
- import { error, json } from '../../exports/index.js';
27
-
28
- /* global __SVELTEKIT_ADAPTER_NAME__ */
29
-
30
- /** @type {import('types').RequiredResolveOptions['transformPageChunk']} */
31
- const default_transform = ({ html }) => html;
32
-
33
- /** @type {import('types').RequiredResolveOptions['filterSerializedResponseHeaders']} */
34
- const default_filter = () => false;
35
-
36
- /** @type {import('types').RequiredResolveOptions['preload']} */
37
- const default_preload = ({ type }) => type === 'js' || type === 'css';
38
-
39
- /** @type {import('types').Respond} */
40
- export async function respond(request, options, state) {
41
- /** URL but stripped from the potential `/__data.json` suffix and its search param */
42
- let url = new URL(request.url);
43
-
44
- if (options.csrf.check_origin) {
45
- const forbidden =
46
- request.method === 'POST' &&
47
- request.headers.get('origin') !== url.origin &&
48
- is_form_content_type(request);
49
-
50
- if (forbidden) {
51
- const csrf_error = error(403, `Cross-site ${request.method} form submissions are forbidden`);
52
- if (request.headers.get('accept') === 'application/json') {
53
- return json(csrf_error.body, { status: csrf_error.status });
54
- }
55
- return new Response(csrf_error.body.message, { status: csrf_error.status });
56
- }
57
- }
58
-
59
- let decoded;
60
- try {
61
- decoded = decode_pathname(url.pathname);
62
- } catch {
63
- return new Response('Malformed URI', { status: 400 });
1
+ import { respond } from './respond.js';
2
+ import { set_private_env } from '../env-private.js';
3
+ import { set_public_env } from '../env-public.js';
4
+ import { options, get_hooks } from '__GENERATED__/server-internal.js';
5
+
6
+ export class Server {
7
+ /** @type {import('types').SSROptions} */
8
+ #options;
9
+
10
+ /** @type {import('types').SSRManifest} */
11
+ #manifest;
12
+
13
+ /** @param {import('types').SSRManifest} manifest */
14
+ constructor(manifest) {
15
+ /** @type {import('types').SSROptions} */
16
+ this.#options = options;
17
+ this.#manifest = manifest;
64
18
  }
65
19
 
66
- /** @type {import('types').SSRRoute | null} */
67
- let route = null;
68
-
69
- /** @type {Record<string, string>} */
70
- let params = {};
71
-
72
- if (options.paths.base && !state.prerendering?.fallback) {
73
- if (!decoded.startsWith(options.paths.base)) {
74
- return new Response('Not found', { status: 404 });
75
- }
76
- decoded = decoded.slice(options.paths.base.length) || '/';
77
- }
78
-
79
- const is_data_request = has_data_suffix(decoded);
80
- /** @type {boolean[] | undefined} */
81
- let invalidated_data_nodes;
82
- if (is_data_request) {
83
- decoded = strip_data_suffix(decoded) || '/';
84
- url.pathname = strip_data_suffix(url.pathname) || '/';
85
- invalidated_data_nodes = url.searchParams.get(INVALIDATED_PARAM)?.split('_').map(Boolean);
86
- url.searchParams.delete(INVALIDATED_PARAM);
87
- }
88
-
89
- if (!state.prerendering?.fallback) {
90
- // TODO this could theoretically break should probably be inside a try-catch
91
- const matchers = await options.manifest._.matchers();
92
-
93
- for (const candidate of options.manifest._.routes) {
94
- const match = candidate.pattern.exec(decoded);
95
- if (!match) continue;
96
-
97
- const matched = exec(match, candidate.params, matchers);
98
- if (matched) {
99
- route = candidate;
100
- params = decode_params(matched);
101
- break;
102
- }
103
- }
104
- }
105
-
106
- /** @type {import('types').TrailingSlash | void} */
107
- let trailing_slash = undefined;
108
-
109
- /** @type {Record<string, string>} */
110
- const headers = {};
111
-
112
- /** @type {import('types').RequestEvent} */
113
- const event = {
114
- // @ts-expect-error `cookies` and `fetch` need to be created after the `event` itself
115
- cookies: null,
116
- // @ts-expect-error
117
- fetch: null,
118
- getClientAddress:
119
- state.getClientAddress ||
120
- (() => {
121
- throw new Error(
122
- `${__SVELTEKIT_ADAPTER_NAME__} does not specify getClientAddress. Please raise an issue`
123
- );
124
- }),
125
- locals: {},
126
- params,
127
- platform: state.platform,
128
- request,
129
- route: { id: route?.id ?? null },
130
- setHeaders: (new_headers) => {
131
- for (const key in new_headers) {
132
- const lower = key.toLowerCase();
133
- const value = new_headers[key];
134
-
135
- if (lower === 'set-cookie') {
136
- throw new Error(
137
- `Use \`event.cookies.set(name, value, options)\` instead of \`event.setHeaders\` to set cookies`
138
- );
139
- } else if (lower in headers) {
140
- throw new Error(`"${key}" header is already set`);
141
- } else {
142
- headers[lower] = value;
143
-
144
- if (state.prerendering && lower === 'cache-control') {
145
- state.prerendering.cache = /** @type {string} */ (value);
146
- }
147
- }
148
- }
149
- },
150
- url,
151
- isDataRequest: is_data_request
152
- };
153
-
154
- /** @type {import('types').RequiredResolveOptions} */
155
- let resolve_opts = {
156
- transformPageChunk: default_transform,
157
- filterSerializedResponseHeaders: default_filter,
158
- preload: default_preload
159
- };
160
-
161
- try {
162
- // determine whether we need to redirect to add/remove a trailing slash
163
- if (route && !is_data_request) {
164
- if (route.page) {
165
- const nodes = await Promise.all([
166
- // we use == here rather than === because [undefined] serializes as "[null]"
167
- ...route.page.layouts.map((n) => (n == undefined ? n : options.manifest._.nodes[n]())),
168
- options.manifest._.nodes[route.page.leaf]()
169
- ]);
170
-
171
- if (DEV) {
172
- const layouts = nodes.slice(0, -1);
173
- const page = nodes.at(-1);
174
-
175
- for (const layout of layouts) {
176
- if (layout) {
177
- validate_common_exports(layout.server, /** @type {string} */ (layout.server_id));
178
- validate_common_exports(
179
- layout.universal,
180
- /** @type {string} */ (layout.universal_id)
181
- );
182
- }
183
- }
184
-
185
- if (page) {
186
- validate_page_server_exports(page.server, /** @type {string} */ (page.server_id));
187
- validate_common_exports(page.universal, /** @type {string} */ (page.universal_id));
188
- }
189
- }
190
-
191
- trailing_slash = get_option(nodes, 'trailingSlash');
192
- } else if (route.endpoint) {
193
- const node = await route.endpoint();
194
- trailing_slash = node.trailingSlash;
195
-
196
- if (DEV) {
197
- validate_server_exports(node, /** @type {string} */ (route.endpoint_id));
198
- }
199
- }
200
-
201
- const normalized = normalize_path(url.pathname, trailing_slash ?? 'never');
202
-
203
- if (normalized !== url.pathname && !state.prerendering?.fallback) {
204
- return new Response(undefined, {
205
- status: 301,
206
- headers: {
207
- 'x-sveltekit-normalize': '1',
208
- location:
209
- // ensure paths starting with '//' are not treated as protocol-relative
210
- (normalized.startsWith('//') ? url.origin + normalized : normalized) +
211
- (url.search === '?' ? '' : url.search)
212
- }
213
- });
214
- }
215
- }
216
-
217
- const { cookies, new_cookies, get_cookie_header } = get_cookies(
218
- request,
219
- url,
220
- options.dev,
221
- trailing_slash ?? 'never'
222
- );
223
-
224
- event.cookies = cookies;
225
- event.fetch = create_fetch({ event, options, state, get_cookie_header });
226
-
227
- if (state.prerendering && !state.prerendering.fallback) disable_search(url);
228
-
229
- const response = await options.hooks.handle({
230
- event,
231
- resolve: (event, opts) =>
232
- resolve(event, opts).then((response) => {
233
- // add headers/cookies here, rather than inside `resolve`, so that we
234
- // can do it once for all responses instead of once per `return`
235
- for (const key in headers) {
236
- const value = headers[key];
237
- response.headers.set(key, /** @type {string} */ (value));
238
- }
239
-
240
- add_cookies_to_headers(response.headers, Object.values(new_cookies));
241
-
242
- if (state.prerendering && event.route.id !== null) {
243
- response.headers.set('x-sveltekit-routeid', encodeURI(event.route.id));
244
- }
245
-
246
- return response;
247
- })
248
- });
249
-
250
- // respond with 304 if etag matches
251
- if (response.status === 200 && response.headers.has('etag')) {
252
- let if_none_match_value = request.headers.get('if-none-match');
253
-
254
- // ignore W/ prefix https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match#directives
255
- if (if_none_match_value?.startsWith('W/"')) {
256
- if_none_match_value = if_none_match_value.substring(2);
257
- }
258
-
259
- const etag = /** @type {string} */ (response.headers.get('etag'));
260
-
261
- if (if_none_match_value === etag) {
262
- const headers = new Headers({ etag });
263
-
264
- // https://datatracker.ietf.org/doc/html/rfc7232#section-4.1 + set-cookie
265
- for (const key of [
266
- 'cache-control',
267
- 'content-location',
268
- 'date',
269
- 'expires',
270
- 'vary',
271
- 'set-cookie'
272
- ]) {
273
- const value = response.headers.get(key);
274
- if (value) headers.set(key, value);
275
- }
276
-
277
- return new Response(undefined, {
278
- status: 304,
279
- headers
280
- });
281
- }
282
- }
283
-
284
- // Edge case: If user does `return Response(30x)` in handle hook while processing a data request,
285
- // we need to transform the redirect response to a corresponding JSON response.
286
- if (is_data_request && response.status >= 300 && response.status <= 308) {
287
- const location = response.headers.get('location');
288
- if (location) {
289
- return redirect_json_response(new Redirect(/** @type {any} */ (response.status), location));
290
- }
291
- }
292
-
293
- return response;
294
- } catch (error) {
295
- if (error instanceof Redirect) {
296
- if (is_data_request) {
297
- return redirect_json_response(error);
298
- } else {
299
- return redirect_response(error.status, error.location);
300
- }
20
+ /**
21
+ * @param {{
22
+ * env: Record<string, string>
23
+ * }} opts
24
+ */
25
+ async init({ env }) {
26
+ // Take care: Some adapters may have to call `Server.init` per-request to set env vars,
27
+ // so anything that shouldn't be rerun should be wrapped in an `if` block to make sure it hasn't
28
+ // been done already.
29
+ const entries = Object.entries(env);
30
+
31
+ const prefix = this.#options.env_public_prefix;
32
+ const prv = Object.fromEntries(entries.filter(([k]) => !k.startsWith(prefix)));
33
+ const pub = Object.fromEntries(entries.filter(([k]) => k.startsWith(prefix)));
34
+
35
+ set_private_env(prv);
36
+ set_public_env(pub);
37
+
38
+ if (!this.#options.hooks) {
39
+ const module = await get_hooks();
40
+
41
+ this.#options.hooks = {
42
+ handle: module.handle || (({ event, resolve }) => resolve(event)),
43
+ // @ts-expect-error
44
+ handleError: module.handleError || (({ error }) => console.error(error?.stack)),
45
+ handleFetch: module.handleFetch || (({ request, fetch }) => fetch(request))
46
+ };
301
47
  }
302
- return await handle_fatal_error(event, options, error);
303
48
  }
304
49
 
305
50
  /**
306
- *
307
- * @param {import('types').RequestEvent} event
308
- * @param {import('types').ResolveOptions} [opts]
51
+ * @param {Request} request
52
+ * @param {import('types').RequestOptions} options
309
53
  */
310
- async function resolve(event, opts) {
311
- try {
312
- if (opts) {
313
- if ('ssr' in opts) {
314
- throw new Error(
315
- 'ssr has been removed, set it in the appropriate +layout.js instead. See the PR for more information: https://github.com/sveltejs/kit/pull/6197'
316
- );
317
- }
318
-
319
- resolve_opts = {
320
- transformPageChunk: opts.transformPageChunk || default_transform,
321
- filterSerializedResponseHeaders: opts.filterSerializedResponseHeaders || default_filter,
322
- preload: opts.preload || default_preload
323
- };
324
- }
325
-
326
- if (state.prerendering?.fallback) {
327
- return await render_response({
328
- event,
329
- options,
330
- state,
331
- page_config: { ssr: false, csr: true },
332
- status: 200,
333
- error: null,
334
- branch: [],
335
- fetched: [],
336
- resolve_opts
337
- });
338
- }
339
-
340
- if (route) {
341
- /** @type {Response} */
342
- let response;
343
-
344
- if (is_data_request) {
345
- response = await render_data(
346
- event,
347
- route,
348
- options,
349
- state,
350
- invalidated_data_nodes,
351
- trailing_slash ?? 'never'
352
- );
353
- } else if (route.endpoint && (!route.page || is_endpoint_request(event))) {
354
- response = await render_endpoint(event, await route.endpoint(), state);
355
- } else if (route.page) {
356
- response = await render_page(event, route, route.page, options, state, resolve_opts);
357
- } else {
358
- // a route will always have a page or an endpoint, but TypeScript
359
- // doesn't know that
360
- throw new Error('This should never happen');
361
- }
362
-
363
- return response;
364
- }
365
-
366
- if (state.initiator === GENERIC_ERROR) {
367
- return new Response('Internal Server Error', {
368
- status: 500
369
- });
370
- }
371
-
372
- // if this request came direct from the user, rather than
373
- // via a `fetch` in a `load`, render a 404 page
374
- if (!state.initiator) {
375
- return await respond_with_error({
376
- event,
377
- options,
378
- state,
379
- status: 404,
380
- error: new Error(`Not found: ${event.url.pathname}`),
381
- resolve_opts
382
- });
383
- }
384
-
385
- if (state.prerendering) {
386
- return new Response('not found', { status: 404 });
387
- }
388
-
389
- // we can't load the endpoint from our own manifest,
390
- // so we need to make an actual HTTP request
391
- return await fetch(request);
392
- } catch (error) {
393
- // HttpError from endpoint can end up here - TODO should it be handled there instead?
394
- return await handle_fatal_error(event, options, error);
395
- } finally {
396
- event.cookies.set = () => {
397
- throw new Error('Cannot use `cookies.set(...)` after the response has been generated');
398
- };
399
-
400
- event.setHeaders = () => {
401
- throw new Error('Cannot use `setHeaders(...)` after the response has been generated');
402
- };
54
+ async respond(request, options) {
55
+ // TODO this should probably have been removed for 1.0 — i think we can get rid of it?
56
+ if (!(request instanceof Request)) {
57
+ throw new Error(
58
+ 'The first argument to server.respond must be a Request object. See https://github.com/sveltejs/kit/pull/3384 for details'
59
+ );
403
60
  }
61
+
62
+ return respond(request, this.#options, this.#manifest, options);
404
63
  }
405
64
  }
@@ -50,15 +50,14 @@ class BaseProvider {
50
50
  * @param {boolean} use_hashes
51
51
  * @param {import('types').CspDirectives} directives
52
52
  * @param {string} nonce
53
- * @param {boolean} dev
54
53
  */
55
- constructor(use_hashes, directives, nonce, dev) {
54
+ constructor(use_hashes, directives, nonce) {
56
55
  this.#use_hashes = use_hashes;
57
- this.#directives = dev ? { ...directives } : directives; // clone in dev so we can safely mutate
56
+ this.#directives = __SVELTEKIT_DEV__ ? { ...directives } : directives; // clone in dev so we can safely mutate
58
57
 
59
58
  const d = this.#directives;
60
59
 
61
- if (dev) {
60
+ if (__SVELTEKIT_DEV__) {
62
61
  // remove strict-dynamic in dev...
63
62
  // TODO reinstate this if we can figure out how to make strict-dynamic work
64
63
  // if (d['default-src']) {
@@ -90,7 +89,7 @@ class BaseProvider {
90
89
  effective_script_src.filter((value) => value !== 'unsafe-inline').length > 0;
91
90
 
92
91
  this.#style_needs_csp =
93
- !dev &&
92
+ !__SVELTEKIT_DEV__ &&
94
93
  !!effective_style_src &&
95
94
  effective_style_src.filter((value) => value !== 'unsafe-inline').length > 0;
96
95
 
@@ -189,10 +188,9 @@ class CspReportOnlyProvider extends BaseProvider {
189
188
  * @param {boolean} use_hashes
190
189
  * @param {import('types').CspDirectives} directives
191
190
  * @param {string} nonce
192
- * @param {boolean} dev
193
191
  */
194
- constructor(use_hashes, directives, nonce, dev) {
195
- super(use_hashes, directives, nonce, dev);
192
+ constructor(use_hashes, directives, nonce) {
193
+ super(use_hashes, directives, nonce);
196
194
 
197
195
  if (Object.values(directives).filter((v) => !!v).length > 0) {
198
196
  // If we're generating content-security-policy-report-only,
@@ -223,10 +221,10 @@ export class Csp {
223
221
  * @param {import('./types').CspConfig} config
224
222
  * @param {import('./types').CspOpts} opts
225
223
  */
226
- constructor({ mode, directives, reportOnly }, { prerender, dev }) {
224
+ constructor({ mode, directives, reportOnly }, { prerender }) {
227
225
  const use_hashes = mode === 'hash' || (mode === 'auto' && prerender);
228
- this.csp_provider = new CspProvider(use_hashes, directives, this.nonce, dev);
229
- this.report_only_provider = new CspReportOnlyProvider(use_hashes, reportOnly, this.nonce, dev);
226
+ this.csp_provider = new CspProvider(use_hashes, directives, this.nonce);
227
+ this.report_only_provider = new CspReportOnlyProvider(use_hashes, reportOnly, this.nonce);
230
228
  }
231
229
 
232
230
  get script_needs_nonce() {
@@ -24,11 +24,12 @@ import { respond_with_error } from './respond_with_error.js';
24
24
  * @param {import('types').SSRRoute} route
25
25
  * @param {import('types').PageNodeIndexes} page
26
26
  * @param {import('types').SSROptions} options
27
+ * @param {import('types').SSRManifest} manifest
27
28
  * @param {import('types').SSRState} state
28
29
  * @param {import('types').RequiredResolveOptions} resolve_opts
29
30
  * @returns {Promise<Response>}
30
31
  */
31
- export async function render_page(event, route, page, options, state, resolve_opts) {
32
+ export async function render_page(event, route, page, options, manifest, state, resolve_opts) {
32
33
  if (state.initiator === route) {
33
34
  // infinite request cycle detected
34
35
  return new Response(`Not found: ${event.url.pathname}`, {
@@ -39,15 +40,15 @@ export async function render_page(event, route, page, options, state, resolve_op
39
40
  state.initiator = route;
40
41
 
41
42
  if (is_action_json_request(event)) {
42
- const node = await options.manifest._.nodes[page.leaf]();
43
+ const node = await manifest._.nodes[page.leaf]();
43
44
  return handle_action_json_request(event, options, node?.server);
44
45
  }
45
46
 
46
47
  try {
47
48
  const nodes = await Promise.all([
48
49
  // we use == here rather than === because [undefined] serializes as "[null]"
49
- ...page.layouts.map((n) => (n == undefined ? n : options.manifest._.nodes[n]())),
50
- options.manifest._.nodes[page.leaf]()
50
+ ...page.layouts.map((n) => (n == undefined ? n : manifest._.nodes[n]())),
51
+ manifest._.nodes[page.leaf]()
51
52
  ]);
52
53
 
53
54
  const leaf_node = /** @type {import('types').SSRNode} */ (nodes.at(-1));
@@ -105,6 +106,7 @@ export async function render_page(event, route, page, options, state, resolve_op
105
106
  error: null,
106
107
  event,
107
108
  options,
109
+ manifest,
108
110
  state,
109
111
  resolve_opts
110
112
  });
@@ -135,6 +137,7 @@ export async function render_page(event, route, page, options, state, resolve_op
135
137
  error: null,
136
138
  event,
137
139
  options,
140
+ manifest,
138
141
  state,
139
142
  resolve_opts
140
143
  });
@@ -163,7 +166,6 @@ export async function render_page(event, route, page, options, state, resolve_op
163
166
 
164
167
  return await load_server_data({
165
168
  event,
166
- options,
167
169
  state,
168
170
  node,
169
171
  parent: async () => {
@@ -251,7 +253,7 @@ export async function render_page(event, route, page, options, state, resolve_op
251
253
  while (i--) {
252
254
  if (page.errors[i]) {
253
255
  const index = /** @type {number} */ (page.errors[i]);
254
- const node = await options.manifest._.nodes[index]();
256
+ const node = await manifest._.nodes[index]();
255
257
 
256
258
  let j = i;
257
259
  while (!branch[j]) j -= 1;
@@ -259,6 +261,7 @@ export async function render_page(event, route, page, options, state, resolve_op
259
261
  return await render_response({
260
262
  event,
261
263
  options,
264
+ manifest,
262
265
  state,
263
266
  resolve_opts,
264
267
  page_config: { ssr: true, csr: true },
@@ -299,6 +302,7 @@ export async function render_page(event, route, page, options, state, resolve_op
299
302
  return await render_response({
300
303
  event,
301
304
  options,
305
+ manifest,
302
306
  state,
303
307
  resolve_opts,
304
308
  page_config: {
@@ -311,15 +315,16 @@ export async function render_page(event, route, page, options, state, resolve_op
311
315
  action_result,
312
316
  fetched
313
317
  });
314
- } catch (error) {
318
+ } catch (e) {
315
319
  // if we end up here, it means the data loaded successfull
316
320
  // but the page failed to render, or that a prerendering error occurred
317
321
  return await respond_with_error({
318
322
  event,
319
323
  options,
324
+ manifest,
320
325
  state,
321
326
  status: 500,
322
- error,
327
+ error: e,
323
328
  resolve_opts
324
329
  });
325
330
  }
@@ -5,14 +5,13 @@ import { unwrap_promises } from '../../../utils/promises.js';
5
5
  * Calls the user's server `load` function.
6
6
  * @param {{
7
7
  * event: import('types').RequestEvent;
8
- * options: import('types').SSROptions;
9
8
  * state: import('types').SSRState;
10
9
  * node: import('types').SSRNode | undefined;
11
10
  * parent: () => Promise<Record<string, any>>;
12
11
  * }} opts
13
12
  * @returns {Promise<import('types').ServerDataNode | null>}
14
13
  */
15
- export async function load_server_data({ event, options, state, node, parent }) {
14
+ export async function load_server_data({ event, state, node, parent }) {
16
15
  if (!node?.server) return null;
17
16
 
18
17
  const uses = {
@@ -66,7 +65,7 @@ export async function load_server_data({ event, options, state, node, parent })
66
65
  });
67
66
 
68
67
  const data = result ? await unwrap_promises(result) : null;
69
- if (options.dev) {
68
+ if (__SVELTEKIT_DEV__) {
70
69
  validate_load_response(data, /** @type {string} */ (event.route.id));
71
70
  }
72
71