Skip to content

Commit

Permalink
fix: allow member access on directives (#9462)
Browse files Browse the repository at this point in the history
fixes #9445
  • Loading branch information
paoloricciuti committed Nov 15, 2023
1 parent 9eb969d commit 6f3dc04
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/itchy-lions-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"svelte": patch
---

fix: allow member access on directives
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,22 @@ function serialize_style_directives(style_directives, element_id, context, is_at
}
}

/**
* goes from nested.access to nested['access']
* @param {string} expression
*/
function member_expression_id_to_literal(expression) {
// this allow for accessing members of an object
const splitted_expression = expression.split('.');

let new_expression = splitted_expression.shift() ?? '';

for (let new_piece of splitted_expression) {
new_expression += `['${new_piece}']`;
}
return new_expression;
}

/**
* Serializes each class directive into something like `$.class_toogle(element, class_name, value)`
* and adds it either to init or update, depending on whether or not the value or the attributes are dynamic.
Expand Down Expand Up @@ -1676,7 +1692,16 @@ export const template_visitors = {
? b.literal(null)
: b.thunk(/** @type {import('estree').Expression} */ (visit(node.expression)));

state.init.push(b.stmt(b.call('$.animate', state.node, b.id(node.name), expression)));
state.init.push(
b.stmt(
b.call(
'$.animate',
state.node,
b.id(member_expression_id_to_literal(node.name)),
expression
)
)
);
},
ClassDirective(node, { state, next }) {
error(node, 'INTERNAL', 'Node should have been handled elsewhere');
Expand All @@ -1696,7 +1721,7 @@ export const template_visitors = {
b.call(
type,
state.node,
b.id(node.name),
b.id(member_expression_id_to_literal(node.name)),
expression,
node.modifiers.includes('global') ? b.true : b.false
)
Expand Down Expand Up @@ -2417,7 +2442,13 @@ export const template_visitors = {
/** @type {import('estree').Expression[]} */
const args = [
state.node,
b.arrow(params, b.call(serialize_get_binding(b.id(node.name), state), ...params))
b.arrow(
params,
b.call(
serialize_get_binding(b.id(member_expression_id_to_literal(node.name)), state),
...params
)
)
];

if (node.expression) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { test } from '../../test';

export default test({
skip_if_ssr: true
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// index.svelte (Svelte VERSION)
// Note: compiler output will change before 5.0 is released!
import "svelte/internal/disclose-version";
import * as $ from "svelte/internal";

var frag = $.template(`<div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div>`, true);

export default function Directives_with_member_access($$anchor, $$props) {
$.push($$props, false);

const one = () => {};
const nested = { one, "with-string": one };
const evenmore = { nested };

/* Init */
var fragment = $.open_frag($$anchor, true, frag);
var div = $.child_frag(fragment);
var div_1 = $.sibling($.sibling(div));
var div_2 = $.sibling($.sibling(div_1));
var div_3 = $.sibling($.sibling(div_2));

$.transition(div_3, one, null, false);

var div_4 = $.sibling($.sibling(div_3));

$.transition(div_4, nested['one'], null, false);

var div_5 = $.sibling($.sibling(div_4));

$.transition(div_5, evenmore['nested']['one'], null, false);

var div_6 = $.sibling($.sibling(div_5));

$.animate(div_6, one, null);

var div_7 = $.sibling($.sibling(div_6));

$.animate(div_7, nested['one'], null);

var div_8 = $.sibling($.sibling(div_7));

$.animate(div_8, evenmore['nested']['one'], null);

var div_9 = $.sibling($.sibling(div_8));

$.in(div_9, one, null, false);

var div_10 = $.sibling($.sibling(div_9));

$.in(div_10, nested['one'], null, false);

var div_11 = $.sibling($.sibling(div_10));

$.in(div_11, evenmore['nested']['one'], null, false);

var div_12 = $.sibling($.sibling(div_11));

$.out(div_12, one, null, false);

var div_13 = $.sibling($.sibling(div_12));

$.out(div_13, nested['one'], null, false);

var div_14 = $.sibling($.sibling(div_13));

$.out(div_14, evenmore['nested']['one'], null, false);

var div_15 = $.sibling($.sibling(div_14));
var div_16 = $.sibling($.sibling(div_15));
var div_17 = $.sibling($.sibling(div_16));

$.transition(div_17, nested['with-string'], null, false);

var div_18 = $.sibling($.sibling(div_17));

$.transition(div_18, evenmore['nested']['with-string'], null, false);

var div_19 = $.sibling($.sibling(div_18));

$.animate(div_19, nested['with-string'], null);

var div_20 = $.sibling($.sibling(div_19));

$.animate(div_20, evenmore['nested']['with-string'], null);

var div_21 = $.sibling($.sibling(div_20));

$.in(div_21, nested['with-string'], null, false);

var div_22 = $.sibling($.sibling(div_21));

$.in(div_22, evenmore['nested']['with-string'], null, false);

var div_23 = $.sibling($.sibling(div_22));

$.out(div_23, nested['with-string'], null, false);

var div_24 = $.sibling($.sibling(div_23));

$.out(div_24, evenmore['nested']['with-string'], null, false);
$.action(div, $$node => one($$node));
$.action(div_1, $$node => nested['one']($$node));
$.action(div_2, $$node => evenmore['nested']['one']($$node));
$.action(div_15, $$node => nested['with-string']($$node));
$.action(div_16, $$node => evenmore['nested']['with-string']($$node));
$.close_frag($$anchor, fragment);
$.pop();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<script>
const one = ()=>{};
const nested = {one, "with-string": one};
const evenmore = {nested};
</script>

<div use:one />
<div use:nested.one />
<div use:evenmore.nested.one />

<div transition:one />
<div transition:nested.one />
<div transition:evenmore.nested.one />

<div animate:one />
<div animate:nested.one />
<div animate:evenmore.nested.one />

<div in:one />
<div in:nested.one />
<div in:evenmore.nested.one />

<div out:one />
<div out:nested.one />
<div out:evenmore.nested.one />

<div use:nested.with-string />
<div use:evenmore.nested.with-string />

<div transition:nested.with-string />
<div transition:evenmore.nested.with-string />

<div animate:nested.with-string />
<div animate:evenmore.nested.with-string />

<div in:nested.with-string />
<div in:evenmore.nested.with-string />

<div out:nested.with-string />
<div out:evenmore.nested.with-string />
5 changes: 4 additions & 1 deletion packages/svelte/tests/snapshot/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import { VERSION } from 'svelte/compiler';

interface SnapshotTest extends BaseTest {
compileOptions?: Partial<import('#compiler').CompileOptions>;
skip_if_ssr?: boolean;
}

const { test, run } = suite<SnapshotTest>(async (config, cwd) => {
compile_directory(cwd, 'client', config.compileOptions);
compile_directory(cwd, 'server', config.compileOptions);
if (!config.skip_if_ssr) {
compile_directory(cwd, 'server', config.compileOptions);
}

// run `UPDATE_SNAPSHOTS=true pnpm test snapshot` to update snapshot tests
if (process.env.UPDATE_SNAPSHOTS) {
Expand Down

1 comment on commit 6f3dc04

@vercel
Copy link

@vercel vercel bot commented on 6f3dc04 Nov 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

svelte-5-preview – ./sites/svelte-5-preview

svelte-octane.vercel.app
svelte-5-preview-svelte.vercel.app
svelte-5-preview.vercel.app
svelte-5-preview-git-main-svelte.vercel.app

Please sign in to comment.