Skip to content

Commit

Permalink
fix missing slotted elements in AST (#6148)
Browse files Browse the repository at this point in the history
  • Loading branch information
Conduitry authored Mar 30, 2021
1 parent e84e356 commit 286c60d
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 47 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Export interfaces for transition parameters ([#5207](https://github.com/sveltejs/svelte/issues/5207))
* Export store's useful TypeScript definitions ([#5864](https://github.com/sveltejs/svelte/issues/5864))
* Fix previous breaking change to `svelte/preprocess` types location ([#6100](https://github.com/sveltejs/svelte/pull/6100))
* Fix missing slotted elements in AST ([#6066](https://github.com/sveltejs/svelte/issues/6066))

## 3.35.0

Expand Down
7 changes: 4 additions & 3 deletions src/compiler/compile/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { is_reserved_keyword } from './utils/reserved_keywords';
import { apply_preprocessor_sourcemap } from '../utils/mapped_code';
import Element from './nodes/Element';
import { DecodedSourceMap, RawSourceMap } from '@ampproject/remapping/dist/types/types';
import { clone } from '../utils/clone';

interface ComponentOptions {
namespace?: string;
Expand Down Expand Up @@ -116,12 +117,12 @@ export default class Component {

// the instance JS gets mutated, so we park
// a copy here for later. TODO this feels gross
this.original_ast = {
this.original_ast = clone({
html: ast.html,
css: ast.css,
instance: ast.instance && JSON.parse(JSON.stringify(ast.instance)),
instance: ast.instance,
module: ast.module
};
});

this.file =
compile_options.filename &&
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/compile/nodes/Binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { TemplateNode } from '../../interfaces';
import Element from './Element';
import InlineComponent from './InlineComponent';
import Window from './Window';
import { clone } from '../../utils/clone';

// TODO this should live in a specific binding
const read_only_media_attributes = new Set([
Expand Down Expand Up @@ -42,7 +43,7 @@ export default class Binding extends Node {

this.name = info.name;
this.expression = new Expression(component, this, scope, info.expression);
this.raw_expression = JSON.parse(JSON.stringify(info.expression));
this.raw_expression = clone(info.expression);

const { name } = get_object(this.expression.node);

Expand Down
3 changes: 2 additions & 1 deletion src/compiler/compile/nodes/shared/Context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { x } from 'code-red';
import { Node, Identifier, Expression } from 'estree';
import { walk } from 'estree-walker';
import is_reference from 'is-reference';
import { clone } from '../../../utils/clone';

export interface Context {
key: Identifier;
Expand Down Expand Up @@ -81,7 +82,7 @@ function update_reference(contexts: Context[], n: number, expression: Expression
}

// NOTE: avoid unnecessary deep clone?
expression = JSON.parse(JSON.stringify(expression)) as Expression;
expression = clone(expression) as Expression;
walk(expression, {
enter(node, parent: Node) {
if (is_reference(node, parent)) {
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/compile/nodes/shared/Expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { is_reserved_keyword } from '../../utils/reserved_keywords';
import replace_object from '../../utils/replace_object';
import is_contextual from './is_contextual';
import EachBlock from '../EachBlock';
import { clone } from '../../../utils/clone';

type Owner = INode;

Expand Down Expand Up @@ -195,7 +196,7 @@ export default class Expression {
const node = walk(this.node, {
enter(node: any, parent: any) {
if (node.type === 'Property' && node.shorthand) {
node.value = JSON.parse(JSON.stringify(node.value));
node.value = clone(node.value);
node.shorthand = false;
}

Expand Down
33 changes: 33 additions & 0 deletions src/compiler/utils/clone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// adapted from klona v2.0.4 - https://github.com/lukeed/klona
// (c) Luke Edwards, under MIT License

// The sole modification is to skip function values in objects when cloning, so we don't break tests.

export function clone(val) {
let k, out, tmp;

if (Array.isArray(val)) {
out = Array(k=val.length);
while (k--) out[k] = (tmp=val[k]) && typeof tmp === 'object' ? clone(tmp) : tmp;
return out;
}

if (Object.prototype.toString.call(val) === '[object Object]') {
out = {}; // null
for (k in val) {
if (k === '__proto__') {
Object.defineProperty(out, k, {
value: clone(val[k]),
configurable: true,
enumerable: true,
writable: true
});
} else if (typeof val[k] !== 'function') { // MODIFICATION: skip functions
out[k] = (tmp=val[k]) && typeof tmp === 'object' ? clone(tmp) : tmp;
}
}
return out;
}

return val;
}
1 change: 1 addition & 0 deletions test/parser/samples/slotted-element/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<Component><div slot='foo'></div></Component>
42 changes: 42 additions & 0 deletions test/parser/samples/slotted-element/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"html": {
"start": 0,
"end": 45,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 45,
"type": "InlineComponent",
"name": "Component",
"attributes": [],
"children": [
{
"start": 11,
"end": 33,
"type": "Element",
"name": "div",
"attributes": [
{
"start": 16,
"end": 26,
"type": "Attribute",
"name": "slot",
"value": [
{
"start": 22,
"end": 25,
"type": "Text",
"raw": "foo",
"data": "foo"
}
]
}
],
"children": []
}
]
}
]
}
}
76 changes: 35 additions & 41 deletions test/parser/samples/textarea-children/output.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,51 +9,45 @@
"end": 61,
"type": "Element",
"name": "textarea",
"attributes": [
"attributes": [],
"children": [
{
"type": "Attribute",
"name": "value",
"value": [
{
"start": 10,
"end": 41,
"type": "Text",
"raw": "\n\t<p>not actually an element. ",
"data": "\n\t<p>not actually an element. "
},
{
"start": 40,
"end": 45,
"type": "MustacheTag",
"expression": {
"type": "Identifier",
"start": 41,
"end": 44,
"loc": {
"start": {
"line": 2,
"column": 30
},
"end": {
"line": 2,
"column": 33
}
},
"name": "foo"
"start": 10,
"end": 41,
"type": "Text",
"raw": "\n\t<p>not actually an element. ",
"data": "\n\t<p>not actually an element. "
},
{
"start": 40,
"end": 45,
"type": "MustacheTag",
"expression": {
"type": "Identifier",
"start": 41,
"end": 44,
"loc": {
"start": {
"line": 2,
"column": 30
},
"end": {
"line": 2,
"column": 33
}
},
{
"start": 45,
"end": 50,
"type": "Text",
"raw": "</p>\n",
"data": "</p>\n"
}
]
"name": "foo"
}
},
{
"start": 45,
"end": 50,
"type": "Text",
"raw": "</p>\n",
"data": "</p>\n"
}
],
"children": []
]
}
]
}
}
}

0 comments on commit 286c60d

Please sign in to comment.