@sveltejs/kit 2.30.0 → 2.31.0
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 +12 -1
- package/src/core/adapt/builder.js +122 -13
- package/src/core/config/options.js +6 -0
- package/src/core/sync/sync.js +3 -2
- package/src/core/sync/write_non_ambient.js +78 -2
- package/src/core/sync/write_types/index.js +0 -72
- package/src/exports/hooks/sequence.js +53 -31
- package/src/{runtime/app/server → exports/internal}/event.js +24 -9
- package/src/exports/internal/server.js +22 -0
- package/src/exports/public.d.ts +117 -6
- package/src/exports/vite/dev/index.js +8 -0
- package/src/exports/vite/index.js +30 -3
- package/src/exports/vite/utils.js +44 -0
- package/src/runtime/app/paths/index.js +3 -1
- package/src/runtime/app/paths/types.d.ts +0 -1
- package/src/runtime/app/server/index.js +1 -1
- package/src/runtime/app/server/remote/command.js +4 -5
- package/src/runtime/app/server/remote/form.js +5 -7
- package/src/runtime/app/server/remote/prerender.js +5 -7
- package/src/runtime/app/server/remote/query.js +6 -8
- package/src/runtime/app/server/remote/shared.js +9 -13
- package/src/runtime/client/client.js +9 -14
- package/src/runtime/server/data/index.js +10 -5
- package/src/runtime/server/endpoint.js +4 -3
- package/src/runtime/server/page/actions.js +55 -24
- package/src/runtime/server/page/index.js +22 -5
- package/src/runtime/server/page/load_data.js +131 -121
- package/src/runtime/server/page/render.js +15 -7
- package/src/runtime/server/page/respond_with_error.js +7 -2
- package/src/runtime/server/remote.js +59 -13
- package/src/runtime/server/respond.js +110 -34
- package/src/runtime/server/utils.js +20 -5
- package/src/runtime/shared.js +20 -0
- package/src/runtime/telemetry/noop.js +81 -0
- package/src/runtime/telemetry/otel.js +21 -0
- package/src/runtime/telemetry/record_span.js +65 -0
- package/src/types/ambient.d.ts +54 -0
- package/src/types/global-private.d.ts +2 -0
- package/src/types/internal.d.ts +28 -0
- package/src/types/synthetic/$env+dynamic+private.md +1 -1
- package/src/version.js +1 -1
- package/types/index.d.ts +171 -4
- package/types/index.d.ts.map +2 -2
- package/src/runtime/server/event-state.js +0 -40
|
@@ -11,6 +11,7 @@ import { text_encoder } from '../../utils.js';
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
14
|
+
* @param {import('types').RequestState} event_state
|
|
14
15
|
* @param {import('types').SSRRoute} route
|
|
15
16
|
* @param {import('types').SSROptions} options
|
|
16
17
|
* @param {import('@sveltejs/kit').SSRManifest} manifest
|
|
@@ -21,6 +22,7 @@ import { text_encoder } from '../../utils.js';
|
|
|
21
22
|
*/
|
|
22
23
|
export async function render_data(
|
|
23
24
|
event,
|
|
25
|
+
event_state,
|
|
24
26
|
route,
|
|
25
27
|
options,
|
|
26
28
|
manifest,
|
|
@@ -60,6 +62,7 @@ export async function render_data(
|
|
|
60
62
|
// load this. for the child, return as is. for the final result, stream things
|
|
61
63
|
return load_server_data({
|
|
62
64
|
event: new_event,
|
|
65
|
+
event_state,
|
|
63
66
|
state,
|
|
64
67
|
node,
|
|
65
68
|
parent: async () => {
|
|
@@ -107,7 +110,7 @@ export async function render_data(
|
|
|
107
110
|
|
|
108
111
|
return /** @type {import('types').ServerErrorNode} */ ({
|
|
109
112
|
type: 'error',
|
|
110
|
-
error: await handle_error_and_jsonify(event, options, error),
|
|
113
|
+
error: await handle_error_and_jsonify(event, event_state, options, error),
|
|
111
114
|
status:
|
|
112
115
|
error instanceof HttpError || error instanceof SvelteKitError
|
|
113
116
|
? error.status
|
|
@@ -117,7 +120,7 @@ export async function render_data(
|
|
|
117
120
|
)
|
|
118
121
|
);
|
|
119
122
|
|
|
120
|
-
const { data, chunks } = get_data_json(event, options, nodes);
|
|
123
|
+
const { data, chunks } = get_data_json(event, event_state, options, nodes);
|
|
121
124
|
|
|
122
125
|
if (!chunks) {
|
|
123
126
|
// use a normal JSON response where possible, so we get `content-length`
|
|
@@ -152,7 +155,7 @@ export async function render_data(
|
|
|
152
155
|
if (error instanceof Redirect) {
|
|
153
156
|
return redirect_json_response(error);
|
|
154
157
|
} else {
|
|
155
|
-
return json_response(await handle_error_and_jsonify(event, options, error), 500);
|
|
158
|
+
return json_response(await handle_error_and_jsonify(event, event_state, options, error), 500);
|
|
156
159
|
}
|
|
157
160
|
}
|
|
158
161
|
}
|
|
@@ -187,11 +190,12 @@ export function redirect_json_response(redirect) {
|
|
|
187
190
|
* If the serialized data contains promises, `chunks` will be an
|
|
188
191
|
* async iterable containing their resolutions
|
|
189
192
|
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
193
|
+
* @param {import('types').RequestState} event_state
|
|
190
194
|
* @param {import('types').SSROptions} options
|
|
191
195
|
* @param {Array<import('types').ServerDataSkippedNode | import('types').ServerDataNode | import('types').ServerErrorNode | null | undefined>} nodes
|
|
192
196
|
* @returns {{ data: string, chunks: AsyncIterable<string> | null }}
|
|
193
197
|
*/
|
|
194
|
-
export function get_data_json(event, options, nodes) {
|
|
198
|
+
export function get_data_json(event, event_state, options, nodes) {
|
|
195
199
|
let promise_id = 1;
|
|
196
200
|
let count = 0;
|
|
197
201
|
|
|
@@ -214,7 +218,7 @@ export function get_data_json(event, options, nodes) {
|
|
|
214
218
|
.catch(
|
|
215
219
|
/** @param {any} e */ async (e) => {
|
|
216
220
|
key = 'error';
|
|
217
|
-
return handle_error_and_jsonify(event, options, /** @type {any} */ (e));
|
|
221
|
+
return handle_error_and_jsonify(event, event_state, options, /** @type {any} */ (e));
|
|
218
222
|
}
|
|
219
223
|
)
|
|
220
224
|
.then(
|
|
@@ -226,6 +230,7 @@ export function get_data_json(event, options, nodes) {
|
|
|
226
230
|
} catch {
|
|
227
231
|
const error = await handle_error_and_jsonify(
|
|
228
232
|
event,
|
|
233
|
+
event_state,
|
|
229
234
|
options,
|
|
230
235
|
new Error(`Failed to serialize promise while rendering ${event.route.id}`)
|
|
231
236
|
);
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { Redirect } from '@sveltejs/kit/internal';
|
|
2
|
+
import { with_request_store } from '@sveltejs/kit/internal/server';
|
|
2
3
|
import { ENDPOINT_METHODS, PAGE_METHODS } from '../../constants.js';
|
|
3
4
|
import { negotiate } from '../../utils/http.js';
|
|
4
|
-
import { with_event } from '../app/server/event.js';
|
|
5
5
|
import { method_not_allowed } from './utils.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
9
|
+
* @param {import('types').RequestState} event_state
|
|
9
10
|
* @param {import('types').SSREndpoint} mod
|
|
10
11
|
* @param {import('types').SSRState} state
|
|
11
12
|
* @returns {Promise<Response>}
|
|
12
13
|
*/
|
|
13
|
-
export async function render_endpoint(event, mod, state) {
|
|
14
|
+
export async function render_endpoint(event, event_state, mod, state) {
|
|
14
15
|
const method = /** @type {import('types').HttpMethod} */ (event.request.method);
|
|
15
16
|
|
|
16
17
|
let handler = mod[method] || mod.fallback;
|
|
@@ -41,7 +42,7 @@ export async function render_endpoint(event, mod, state) {
|
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
try {
|
|
44
|
-
const response = await
|
|
45
|
+
const response = await with_request_store({ event, state: event_state }, () =>
|
|
45
46
|
handler(/** @type {import('@sveltejs/kit').RequestEvent<Record<string, any>>} */ (event))
|
|
46
47
|
);
|
|
47
48
|
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
/** @import { RequestEvent, ActionResult, Actions } from '@sveltejs/kit' */
|
|
2
|
+
/** @import { SSROptions, SSRNode, ServerNode, ServerHooks } from 'types' */
|
|
1
3
|
import * as devalue from 'devalue';
|
|
2
4
|
import { DEV } from 'esm-env';
|
|
3
5
|
import { json } from '@sveltejs/kit';
|
|
4
6
|
import { HttpError, Redirect, ActionFailure, SvelteKitError } from '@sveltejs/kit/internal';
|
|
7
|
+
import { with_request_store, merge_tracing } from '@sveltejs/kit/internal/server';
|
|
5
8
|
import { get_status, normalize_error } from '../../../utils/error.js';
|
|
6
9
|
import { is_form_content_type, negotiate } from '../../../utils/http.js';
|
|
7
10
|
import { handle_error_and_jsonify } from '../utils.js';
|
|
8
|
-
import {
|
|
11
|
+
import { record_span } from '../../telemetry/record_span.js';
|
|
9
12
|
|
|
10
|
-
/** @param {
|
|
13
|
+
/** @param {RequestEvent} event */
|
|
11
14
|
export function is_action_json_request(event) {
|
|
12
15
|
const accept = negotiate(event.request.headers.get('accept') ?? '*/*', [
|
|
13
16
|
'application/json',
|
|
@@ -18,11 +21,12 @@ export function is_action_json_request(event) {
|
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
/**
|
|
21
|
-
* @param {
|
|
22
|
-
* @param {import('types').
|
|
23
|
-
* @param {
|
|
24
|
+
* @param {RequestEvent} event
|
|
25
|
+
* @param {import('types').RequestState} event_state
|
|
26
|
+
* @param {SSROptions} options
|
|
27
|
+
* @param {SSRNode['server'] | undefined} server
|
|
24
28
|
*/
|
|
25
|
-
export async function handle_action_json_request(event, options, server) {
|
|
29
|
+
export async function handle_action_json_request(event, event_state, options, server) {
|
|
26
30
|
const actions = server?.actions;
|
|
27
31
|
|
|
28
32
|
if (!actions) {
|
|
@@ -35,7 +39,7 @@ export async function handle_action_json_request(event, options, server) {
|
|
|
35
39
|
return action_json(
|
|
36
40
|
{
|
|
37
41
|
type: 'error',
|
|
38
|
-
error: await handle_error_and_jsonify(event, options, no_actions_error)
|
|
42
|
+
error: await handle_error_and_jsonify(event, event_state, options, no_actions_error)
|
|
39
43
|
},
|
|
40
44
|
{
|
|
41
45
|
status: no_actions_error.status,
|
|
@@ -51,7 +55,7 @@ export async function handle_action_json_request(event, options, server) {
|
|
|
51
55
|
check_named_default_separate(actions);
|
|
52
56
|
|
|
53
57
|
try {
|
|
54
|
-
const data = await call_action(event, actions);
|
|
58
|
+
const data = await call_action(event, event_state, actions);
|
|
55
59
|
|
|
56
60
|
if (__SVELTEKIT_DEV__) {
|
|
57
61
|
validate_action_return(data);
|
|
@@ -92,7 +96,12 @@ export async function handle_action_json_request(event, options, server) {
|
|
|
92
96
|
return action_json(
|
|
93
97
|
{
|
|
94
98
|
type: 'error',
|
|
95
|
-
error: await handle_error_and_jsonify(
|
|
99
|
+
error: await handle_error_and_jsonify(
|
|
100
|
+
event,
|
|
101
|
+
event_state,
|
|
102
|
+
options,
|
|
103
|
+
check_incorrect_fail_use(err)
|
|
104
|
+
)
|
|
96
105
|
},
|
|
97
106
|
{
|
|
98
107
|
status: get_status(err)
|
|
@@ -111,7 +120,7 @@ export function check_incorrect_fail_use(error) {
|
|
|
111
120
|
}
|
|
112
121
|
|
|
113
122
|
/**
|
|
114
|
-
* @param {
|
|
123
|
+
* @param {Redirect} redirect
|
|
115
124
|
*/
|
|
116
125
|
export function action_json_redirect(redirect) {
|
|
117
126
|
return action_json({
|
|
@@ -122,7 +131,7 @@ export function action_json_redirect(redirect) {
|
|
|
122
131
|
}
|
|
123
132
|
|
|
124
133
|
/**
|
|
125
|
-
* @param {
|
|
134
|
+
* @param {ActionResult} data
|
|
126
135
|
* @param {ResponseInit} [init]
|
|
127
136
|
*/
|
|
128
137
|
function action_json(data, init) {
|
|
@@ -130,18 +139,19 @@ function action_json(data, init) {
|
|
|
130
139
|
}
|
|
131
140
|
|
|
132
141
|
/**
|
|
133
|
-
* @param {
|
|
142
|
+
* @param {RequestEvent} event
|
|
134
143
|
*/
|
|
135
144
|
export function is_action_request(event) {
|
|
136
145
|
return event.request.method === 'POST';
|
|
137
146
|
}
|
|
138
147
|
|
|
139
148
|
/**
|
|
140
|
-
* @param {
|
|
141
|
-
* @param {import('types').
|
|
142
|
-
* @
|
|
149
|
+
* @param {RequestEvent} event
|
|
150
|
+
* @param {import('types').RequestState} event_state
|
|
151
|
+
* @param {SSRNode['server'] | undefined} server
|
|
152
|
+
* @returns {Promise<ActionResult>}
|
|
143
153
|
*/
|
|
144
|
-
export async function handle_action_request(event, server) {
|
|
154
|
+
export async function handle_action_request(event, event_state, server) {
|
|
145
155
|
const actions = server?.actions;
|
|
146
156
|
|
|
147
157
|
if (!actions) {
|
|
@@ -164,7 +174,7 @@ export async function handle_action_request(event, server) {
|
|
|
164
174
|
check_named_default_separate(actions);
|
|
165
175
|
|
|
166
176
|
try {
|
|
167
|
-
const data = await call_action(event, actions);
|
|
177
|
+
const data = await call_action(event, event_state, actions);
|
|
168
178
|
|
|
169
179
|
if (__SVELTEKIT_DEV__) {
|
|
170
180
|
validate_action_return(data);
|
|
@@ -203,7 +213,7 @@ export async function handle_action_request(event, server) {
|
|
|
203
213
|
}
|
|
204
214
|
|
|
205
215
|
/**
|
|
206
|
-
* @param {
|
|
216
|
+
* @param {Actions} actions
|
|
207
217
|
*/
|
|
208
218
|
function check_named_default_separate(actions) {
|
|
209
219
|
if (actions.default && Object.keys(actions).length > 1) {
|
|
@@ -214,11 +224,12 @@ function check_named_default_separate(actions) {
|
|
|
214
224
|
}
|
|
215
225
|
|
|
216
226
|
/**
|
|
217
|
-
* @param {
|
|
218
|
-
* @param {
|
|
227
|
+
* @param {RequestEvent} event
|
|
228
|
+
* @param {import('types').RequestState} event_state
|
|
229
|
+
* @param {NonNullable<ServerNode['actions']>} actions
|
|
219
230
|
* @throws {Redirect | HttpError | SvelteKitError | Error}
|
|
220
231
|
*/
|
|
221
|
-
async function call_action(event, actions) {
|
|
232
|
+
async function call_action(event, event_state, actions) {
|
|
222
233
|
const url = new URL(event.request.url);
|
|
223
234
|
|
|
224
235
|
let name = 'default';
|
|
@@ -247,7 +258,27 @@ async function call_action(event, actions) {
|
|
|
247
258
|
);
|
|
248
259
|
}
|
|
249
260
|
|
|
250
|
-
return
|
|
261
|
+
return record_span({
|
|
262
|
+
name: 'sveltekit.form_action',
|
|
263
|
+
attributes: {
|
|
264
|
+
'sveltekit.form_action.name': name,
|
|
265
|
+
'http.route': event.route.id || 'unknown'
|
|
266
|
+
},
|
|
267
|
+
fn: async (current) => {
|
|
268
|
+
const traced_event = merge_tracing(event, current);
|
|
269
|
+
const result = await with_request_store({ event: traced_event, state: event_state }, () =>
|
|
270
|
+
action(traced_event)
|
|
271
|
+
);
|
|
272
|
+
if (result instanceof ActionFailure) {
|
|
273
|
+
current.setAttributes({
|
|
274
|
+
'sveltekit.form_action.result.type': 'failure',
|
|
275
|
+
'sveltekit.form_action.result.status': result.status
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return result;
|
|
280
|
+
}
|
|
281
|
+
});
|
|
251
282
|
}
|
|
252
283
|
|
|
253
284
|
/** @param {any} data */
|
|
@@ -265,7 +296,7 @@ function validate_action_return(data) {
|
|
|
265
296
|
* Try to `devalue.uneval` the data object, and if it fails, return a proper Error with context
|
|
266
297
|
* @param {any} data
|
|
267
298
|
* @param {string} route_id
|
|
268
|
-
* @param {
|
|
299
|
+
* @param {ServerHooks['transport']} transport
|
|
269
300
|
*/
|
|
270
301
|
export function uneval_action_response(data, route_id, transport) {
|
|
271
302
|
const replacer = (/** @type {any} */ thing) => {
|
|
@@ -284,7 +315,7 @@ export function uneval_action_response(data, route_id, transport) {
|
|
|
284
315
|
* Try to `devalue.stringify` the data object, and if it fails, return a proper Error with context
|
|
285
316
|
* @param {any} data
|
|
286
317
|
* @param {string} route_id
|
|
287
|
-
* @param {
|
|
318
|
+
* @param {ServerHooks['transport']} transport
|
|
288
319
|
*/
|
|
289
320
|
function stringify_action_response(data, route_id, transport) {
|
|
290
321
|
const encoders = Object.fromEntries(
|
|
@@ -25,6 +25,7 @@ const MAX_DEPTH = 10;
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
28
|
+
* @param {import('types').RequestState} event_state
|
|
28
29
|
* @param {import('types').PageNodeIndexes} page
|
|
29
30
|
* @param {import('types').SSROptions} options
|
|
30
31
|
* @param {import('@sveltejs/kit').SSRManifest} manifest
|
|
@@ -33,7 +34,16 @@ const MAX_DEPTH = 10;
|
|
|
33
34
|
* @param {import('types').RequiredResolveOptions} resolve_opts
|
|
34
35
|
* @returns {Promise<Response>}
|
|
35
36
|
*/
|
|
36
|
-
export async function render_page(
|
|
37
|
+
export async function render_page(
|
|
38
|
+
event,
|
|
39
|
+
event_state,
|
|
40
|
+
page,
|
|
41
|
+
options,
|
|
42
|
+
manifest,
|
|
43
|
+
state,
|
|
44
|
+
nodes,
|
|
45
|
+
resolve_opts
|
|
46
|
+
) {
|
|
37
47
|
if (state.depth > MAX_DEPTH) {
|
|
38
48
|
// infinite request cycle detected
|
|
39
49
|
return text(`Not found: ${event.url.pathname}`, {
|
|
@@ -43,7 +53,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
|
|
|
43
53
|
|
|
44
54
|
if (is_action_json_request(event)) {
|
|
45
55
|
const node = await manifest._.nodes[page.leaf]();
|
|
46
|
-
return handle_action_json_request(event, options, node?.server);
|
|
56
|
+
return handle_action_json_request(event, event_state, options, node?.server);
|
|
47
57
|
}
|
|
48
58
|
|
|
49
59
|
try {
|
|
@@ -57,11 +67,11 @@ export async function render_page(event, page, options, manifest, state, nodes,
|
|
|
57
67
|
if (is_action_request(event)) {
|
|
58
68
|
const remote_id = get_remote_action(event.url);
|
|
59
69
|
if (remote_id) {
|
|
60
|
-
action_result = await handle_remote_form_post(event, manifest, remote_id);
|
|
70
|
+
action_result = await handle_remote_form_post(event, event_state, manifest, remote_id);
|
|
61
71
|
} else {
|
|
62
72
|
// for action requests, first call handler in +page.server.js
|
|
63
73
|
// (this also determines status code)
|
|
64
|
-
action_result = await handle_action_request(event, leaf_node.server);
|
|
74
|
+
action_result = await handle_action_request(event, event_state, leaf_node.server);
|
|
65
75
|
}
|
|
66
76
|
|
|
67
77
|
if (action_result?.type === 'redirect') {
|
|
@@ -133,6 +143,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
|
|
|
133
143
|
status,
|
|
134
144
|
error: null,
|
|
135
145
|
event,
|
|
146
|
+
event_state,
|
|
136
147
|
options,
|
|
137
148
|
manifest,
|
|
138
149
|
state,
|
|
@@ -163,6 +174,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
|
|
|
163
174
|
|
|
164
175
|
return await load_server_data({
|
|
165
176
|
event,
|
|
177
|
+
event_state,
|
|
166
178
|
state,
|
|
167
179
|
node,
|
|
168
180
|
parent: async () => {
|
|
@@ -189,6 +201,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
|
|
|
189
201
|
try {
|
|
190
202
|
return await load_data({
|
|
191
203
|
event,
|
|
204
|
+
event_state,
|
|
192
205
|
fetched,
|
|
193
206
|
node,
|
|
194
207
|
parent: async () => {
|
|
@@ -243,7 +256,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
|
|
|
243
256
|
}
|
|
244
257
|
|
|
245
258
|
const status = get_status(err);
|
|
246
|
-
const error = await handle_error_and_jsonify(event, options, err);
|
|
259
|
+
const error = await handle_error_and_jsonify(event, event_state, options, err);
|
|
247
260
|
|
|
248
261
|
while (i--) {
|
|
249
262
|
if (page.errors[i]) {
|
|
@@ -258,6 +271,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
|
|
|
258
271
|
|
|
259
272
|
return await render_response({
|
|
260
273
|
event,
|
|
274
|
+
event_state,
|
|
261
275
|
options,
|
|
262
276
|
manifest,
|
|
263
277
|
state,
|
|
@@ -293,6 +307,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
|
|
|
293
307
|
// ndjson format
|
|
294
308
|
let { data, chunks } = get_data_json(
|
|
295
309
|
event,
|
|
310
|
+
event_state,
|
|
296
311
|
options,
|
|
297
312
|
branch.map((node) => node?.server_data)
|
|
298
313
|
);
|
|
@@ -311,6 +326,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
|
|
|
311
326
|
|
|
312
327
|
return await render_response({
|
|
313
328
|
event,
|
|
329
|
+
event_state,
|
|
314
330
|
options,
|
|
315
331
|
manifest,
|
|
316
332
|
state,
|
|
@@ -330,6 +346,7 @@ export async function render_page(event, page, options, manifest, state, nodes,
|
|
|
330
346
|
// but the page failed to render, or that a prerendering error occurred
|
|
331
347
|
return await respond_with_error({
|
|
332
348
|
event,
|
|
349
|
+
event_state,
|
|
333
350
|
options,
|
|
334
351
|
manifest,
|
|
335
352
|
state,
|