-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make $capture_state capture local state #3822
Merged
+298
−43
Merged
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
cf3fe22
capture local variables in $capture_state
rixo 0239ff3
Merge remote-tracking branch 'upstream/master' into hmr-capture-state
rixo b32a022
Merge branch 'master' of github.com:sveltejs/svelte into hmr-capture-…
Rich-Harris a99cd8a
update tests
Rich-Harris 16398f9
Merge remote-tracking branch 'upstream/master' into hmr-capture-state
rixo 1f84174
shorter & less ambiguous param names
rixo d1f490b
fix TS warnings
rixo 1521c67
Merge branch 'hmr-capture-state' of github.com:rixo/svelte into hmr-c…
rixo 8cdcdc0
add test of $capture_state & $inject_state behaviour
rixo 00ef7bd
remove specific handling of props from $capture_state
rixo 002bed8
fix TS error
rixo eb4dcfc
capture store subscriptions in $capture_state
rixo 8989476
fix lint error
rixo 3b5a7df
add $$inject special prop, clean $capture_state & $inject_state
rixo 67bafea
Merge branch 'master' into pr/3822
Conduitry ae5d759
Merge master into pr/3822
rixo 1f6d759
Merge remote-tracking branch 'upstream/master' into hmr-capture-state
rixo bed3964
Merge remote-tracking branch 'upstream/master' into hmr-capture-state
rixo e478e1f
Merge remote-tracking branch 'upstream/master' into hmr-capture-state
rixo 7ba1d76
Merge branch 'master' into pr/3822
Conduitry 63a56ad
fix test
Conduitry 7e5578f
tidy
Conduitry dde2b21
tidy
Conduitry 1a38d04
simplify handling of noop $capture_state/$inject_state
Conduitry File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export default { | ||
options: { | ||
dev: true | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
/* generated by Svelte vX.Y.Z */ | ||
import { | ||
SvelteComponentDev, | ||
add_location, | ||
append_dev, | ||
detach_dev, | ||
dispatch_dev, | ||
element, | ||
init, | ||
insert_dev, | ||
noop, | ||
safe_not_equal, | ||
set_data_dev, | ||
space, | ||
subscribe, | ||
text, | ||
validate_store | ||
} from "svelte/internal"; | ||
|
||
const file = undefined; | ||
|
||
function create_fragment(ctx) { | ||
let p; | ||
let t0; | ||
let t1; | ||
let t2; | ||
let t3; | ||
let t4; | ||
let t5; | ||
let t6; | ||
let t7; | ||
let t8; | ||
let t9; | ||
let t10; | ||
|
||
const block = { | ||
c: function create() { | ||
p = element("p"); | ||
t0 = text(/*prop*/ ctx[0]); | ||
t1 = space(); | ||
t2 = text(/*realName*/ ctx[1]); | ||
t3 = space(); | ||
t4 = text(/*local*/ ctx[3]); | ||
t5 = space(); | ||
t6 = text(priv); | ||
t7 = space(); | ||
t8 = text(/*$prop*/ ctx[2]); | ||
t9 = space(); | ||
t10 = text(/*shadowedByModule*/ ctx[4]); | ||
add_location(p, file, 22, 0, 430); | ||
}, | ||
l: function claim(nodes) { | ||
throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option"); | ||
}, | ||
m: function mount(target, anchor) { | ||
insert_dev(target, p, anchor); | ||
append_dev(p, t0); | ||
append_dev(p, t1); | ||
append_dev(p, t2); | ||
append_dev(p, t3); | ||
append_dev(p, t4); | ||
append_dev(p, t5); | ||
append_dev(p, t6); | ||
append_dev(p, t7); | ||
append_dev(p, t8); | ||
append_dev(p, t9); | ||
append_dev(p, t10); | ||
}, | ||
p: function update(ctx, [dirty]) { | ||
if (dirty & /*prop*/ 1) set_data_dev(t0, /*prop*/ ctx[0]); | ||
if (dirty & /*realName*/ 2) set_data_dev(t2, /*realName*/ ctx[1]); | ||
if (dirty & /*$prop*/ 4) set_data_dev(t8, /*$prop*/ ctx[2]); | ||
}, | ||
i: noop, | ||
o: noop, | ||
d: function destroy(detaching) { | ||
if (detaching) detach_dev(p); | ||
} | ||
}; | ||
|
||
dispatch_dev("SvelteRegisterBlock", { | ||
block, | ||
id: create_fragment.name, | ||
type: "component", | ||
source: "", | ||
ctx | ||
}); | ||
|
||
return block; | ||
} | ||
|
||
let moduleLiveBinding; | ||
const moduleContantProps = 4; | ||
let moduleLet; | ||
const moduleConst = 2; | ||
let shadowedByModule; | ||
const priv = "priv"; | ||
|
||
function instance($$self, $$props, $$invalidate) { | ||
let $prop, | ||
$$unsubscribe_prop = noop, | ||
$$subscribe_prop = () => ($$unsubscribe_prop(), $$unsubscribe_prop = subscribe(prop, $$value => $$invalidate(2, $prop = $$value)), prop); | ||
|
||
$$self.$$.on_destroy.push(() => $$unsubscribe_prop()); | ||
let { prop } = $$props; | ||
validate_store(prop, "prop"); | ||
$$subscribe_prop(); | ||
let { alias: realName } = $$props; | ||
let local; | ||
let shadowedByModule; | ||
const writable_props = ["prop", "alias"]; | ||
|
||
Object.keys($$props).forEach(key => { | ||
if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Component> was created with unknown prop '${key}'`); | ||
}); | ||
|
||
$$self.$set = $$props => { | ||
if ("prop" in $$props) $$subscribe_prop($$invalidate(0, prop = $$props.prop)); | ||
if ("alias" in $$props) $$invalidate(1, realName = $$props.alias); | ||
}; | ||
|
||
$$self.$capture_state = () => ({ | ||
moduleLiveBinding, | ||
moduleContantProps, | ||
moduleLet, | ||
moduleConst, | ||
shadowedByModule, | ||
prop, | ||
realName, | ||
local, | ||
priv, | ||
shadowedByModule, | ||
computed, | ||
$prop | ||
}); | ||
|
||
$$self.$inject_state = $$props => { | ||
if ("prop" in $$props) $$subscribe_prop($$invalidate(0, prop = $$props.prop)); | ||
if ("realName" in $$props) $$invalidate(1, realName = $$props.realName); | ||
if ("local" in $$props) $$invalidate(3, local = $$props.local); | ||
if ("shadowedByModule" in $$props) $$invalidate(4, shadowedByModule = $$props.shadowedByModule); | ||
if ("computed" in $$props) computed = $$props.computed; | ||
}; | ||
|
||
let computed; | ||
|
||
if ($$props && "$$inject" in $$props) { | ||
$$self.$inject_state($$props.$$inject); | ||
} | ||
|
||
$: computed = local * 2; | ||
return [prop, realName, $prop, local, shadowedByModule]; | ||
} | ||
|
||
class Component extends SvelteComponentDev { | ||
constructor(options) { | ||
super(options); | ||
init(this, options, instance, create_fragment, safe_not_equal, { prop: 0, alias: 1 }); | ||
|
||
dispatch_dev("SvelteRegisterComponent", { | ||
component: this, | ||
tagName: "Component", | ||
options, | ||
id: create_fragment.name | ||
}); | ||
|
||
const { ctx } = this.$$; | ||
const props = options.props || {}; | ||
|
||
if (/*prop*/ ctx[0] === undefined && !("prop" in props)) { | ||
console.warn("<Component> was created without expected prop 'prop'"); | ||
} | ||
|
||
if (/*realName*/ ctx[1] === undefined && !("alias" in props)) { | ||
console.warn("<Component> was created without expected prop 'alias'"); | ||
} | ||
} | ||
|
||
get prop() { | ||
throw new Error("<Component>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'"); | ||
} | ||
|
||
set prop(value) { | ||
throw new Error("<Component>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'"); | ||
} | ||
|
||
get alias() { | ||
throw new Error("<Component>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'"); | ||
} | ||
|
||
set alias(value) { | ||
throw new Error("<Component>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'"); | ||
} | ||
} | ||
|
||
export default Component; | ||
export { moduleLiveBinding, moduleContantProps }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<script context="module"> | ||
export let moduleLiveBinding; | ||
export const moduleContantProps = 4; | ||
let moduleLet; | ||
const moduleConst = 2; | ||
let shadowedByModule; | ||
</script> | ||
<script> | ||
export let prop; | ||
|
||
let realName; | ||
export { realName as alias }; | ||
|
||
let local; | ||
|
||
const priv = 'priv'; | ||
|
||
$: computed = local * 2; | ||
|
||
let shadowedByModule; | ||
</script> | ||
<!-- NOTE $prop ensures store subscriptions are not part of captured state --> | ||
<p>{prop} {realName} {local} {priv} {$prop} {shadowedByModule}</p> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the intent here (and then again below) to check whether there's a non-noop capture_state/inject_state? Right now, won't this will be truthy whenever we're compiling in dev mode?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm when I made a change to this effect locally, what ended up happening was that in the
debug-no-dependencies
test, noinstance
function was generated at all, and so$$self.$capture_state
/$$self.$inject_state
weren't set, even tonoop
. So perhaps what's here now is correct.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative would be to make
$capture_state
and$inject_state
actually exist as instance methods onSvelteComponentDev
(as noops), and have them be overridden ininstance
when necessary - which I might actually like better. Thoughts?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, thanks :)
So yeah, it was always true in dev mode (before your change) but I just wanted to write out the real reason, that it was needed for
$capture_state
and$inject_state
.I agree that having them on
SvelteComponentDev
is far better. It also explicits these methods' contract by making it clear that they are always present for all components in dev mode. It's great.