chore: keep the call context on the event view instead of cloning the request state - #16968
Nic-Polumeyv wants to merge 32 commits into
Conversation
|
Install the latest version of pnpm add https://pkg.svelte.dev/@sveltejs/kit/c/e0cadf43e453b5150f90fd9ddf3a7bd0ff52e5e5Open in |
🦋 Changeset detectedLatest commit: e0cadf4 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
727ebe8 to
57e9cc0
Compare
57e9cc0 to
d77baa8
Compare
1dd3e60 to
f131d52
Compare
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe change replaces transient remote and render state flags with derived Merge Risk: 🟡 Moderate · up to Direct remote forms that invoke requested-query operations will fail instead of executing. This breaks a supported form workflow and should be fixed before merge. Development also emits a spurious warning for valid Cache-Control configuration. 🚥 Pre-merge checks | ✅ 1 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (1 passed)
Full details: Backward Compatibility Impact DisclosureExplanation The pull request introduces breaking exported type changes. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…ss with init and respond
66bbaeb to
e1e2090
Compare
be2f7f2 to
e65743d
Compare
elliott-with-the-longest-name-on-github
left a comment
There was a problem hiding this comment.
This looks overall good, but I'm slightly concerned about the fact that we're putting the query restrictions on a prototype object, because prototypes aren't preserved through spreads.
The restrictions are applied through this:
const derived = Object.assign(Object.create(QUERY_PROTOTYPE), event, ...);...but in merge_tracing we spread the event:
export function merge_tracing(event_like, current) {
return {
...event_like,
tracing: {
...event_like.tracing,
current
}
};
}Object spread copies the enumerable properties, but does not preserve the prototype. Therefore:
const query_event = derive_event(event, 'query');
const traced_event = merge_tracing(query_event, span);...produces a normal object, where inside(traced_event, 'query') === true, but the protections for traced_event.url, .params, and .route are gone. I don't think we're actually doing this right now (so it's probably a latent bug). I'm not sure what exactly the best solution for that is... 🤔
|
Solid catch. v3 has the same hole (not 100% sure if you were alluding to already knowing that). But... the non-enumerable getters this replaces are skipped by that spread too, and either way it gives I'm thinking of just routing Edit: Actually, rather than patching const poison = (property) => {
const fail = () => {
throw new Error(`Cannot access event.${property} in a query. Pass the value as an argument to the query instead`);
};
return new Proxy(Object.freeze({}), { get: fail, has: fail, ownKeys: fail, set: fail });
};
const POISON = { url: poison('url'), params: poison('params'), route: poison('route') };Every copy mechanism carries data properties, and return {
...event,
...overrides,
...(entering & KINDS.remote ? restrictions(event, flags) : null),
...(flags & KINDS.query ? POISON : null),
[CONTEXT]: flags
};That also drops |
|
Hmm, I'm not sure I love that the error is moving from const url = getRequestEvent();
if (something) {
url.pathname // throws
}which just means there are more opportunities for you to write code that throws sometimes but not all the time. As much as I don't like the additional complexity it brings, I think using |
|
Ohh ok. I underweighted that. Going with my first option then |
b9d7d02 to
d21e7ce
Compare
… request state `RequestState` carries five `is_in_*` booleans that say what kind of code is on the stack, and the only way to flip one is to clone the whole state object and re-enter the store with the copy. The event is now a class. `event.clone(kind)` is the view for a kind of code, with the kinds as bit flags read through getters like `event.in_render`, and a subclass for what that kind may not do. A clone copies a fixed field list: 18 ns against 305 ns for the spread copy.
ecc1d6e to
1677ceb
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Note
Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.
🟡 Other comments (1)
packages/kit/src/exports/internal/server/validate-headers.js-8-8 (1)
8-8: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winAccept
must-understandinVALID_CACHE_CONTROL_DIRECTIVES.
validateHeaderscurrently warns for this IANA-registered Cache-Control directive in development. Add it besidemust-revalidate.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: QUIET
Plan: Advanced
Run ID: d69ea76a-c12a-443b-9ed9-781b21192a25
📒 Files selected for processing (29)
packages/kit/src/exports/hooks/sequence.spec.jspackages/kit/src/exports/internal/server/event.jspackages/kit/src/exports/internal/server/event.spec.jspackages/kit/src/exports/internal/server/index.jspackages/kit/src/exports/internal/server/validate-headers.jspackages/kit/src/exports/internal/server/validate-headers.spec.jspackages/kit/src/runtime/app/server/remote/command.jspackages/kit/src/runtime/app/server/remote/form.jspackages/kit/src/runtime/app/server/remote/prerender.jspackages/kit/src/runtime/app/server/remote/prerender.spec.jspackages/kit/src/runtime/app/server/remote/query.jspackages/kit/src/runtime/app/server/remote/requested.jspackages/kit/src/runtime/app/server/remote/shared.jspackages/kit/src/runtime/server/data/index.jspackages/kit/src/runtime/server/endpoint.jspackages/kit/src/runtime/server/errors.jspackages/kit/src/runtime/server/fetch.jspackages/kit/src/runtime/server/page/actions.jspackages/kit/src/runtime/server/page/data_serializer.jspackages/kit/src/runtime/server/page/index.jspackages/kit/src/runtime/server/page/load_data.jspackages/kit/src/runtime/server/page/render.jspackages/kit/src/runtime/server/page/respond_with_error.jspackages/kit/src/runtime/server/remote-functions.jspackages/kit/src/runtime/server/remote-functions.spec.jspackages/kit/src/runtime/server/respond.jspackages/kit/src/runtime/server/state.jspackages/kit/src/runtime/server/utils.jspackages/kit/src/types/internal.d.ts
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
sveltejs/vite-plugin-svelte(manual)vitejs/vite(manual)sveltejs/svelte(manual)
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
50b344b to
df4665a
Compare
elliott-with-the-longest-name-on-github
left a comment
There was a problem hiding this comment.
Just some thoughts... I need to think about this approach some more before I can decide if it's worth it. Will come back to it tomorrow
Co-authored-by: Elliott Johnson <hello@ell.iott.dev>
Co-authored-by: Elliott Johnson <hello@ell.iott.dev>
Co-authored-by: kdelay <90545043+kdelay@users.noreply.github.com>
# Conflicts: # packages/kit/src/runtime/server/respond.js
# Conflicts: # packages/kit/src/runtime/app/server/remote/shared.js
RequestStatecarries fiveis_in_*booleans that say what kind of code is on the stack. Flipping one means cloning the whole state and re-entering the store with the copy, and every other copy of the event (merge_tracing, theresolvewrapper,sequence) is a spread that carries whatever the source happens to enumerate.The event is now a class in
packages/kit/src/exports/internal/server/event.js, andevent.clone(kind)is the only way to copy it: a view for a kind of code with a fixed field list, the kinds on the stack as bit flags read through getters likeevent.in_query, and aQueryEventwhoseurl,paramsandroutethrow on access. In dev,with_request_storerefuses anything that is not aRequestEvent, so a stray spread fails at the store instead of silently losing its restrictions.Fixes #17035.
requested()reads the kind set by thecommand/formwrapper, so it works wherever the command is called from.