Merge remote-tracking branch 'origin' into elliott/variadic-snippets

pull/10320/head
S. Elliott Johnson 3 years ago
commit 7c8564b873

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: transform textarea and contenteditable binding expressions

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: ensure unstate() only deeply applies to plain objects and arrays

@ -29,9 +29,8 @@ export interface ComponentClientTransformState extends ClientTransformState {
readonly hoisted: Array<Statement | ModuleDeclaration>;
readonly events: Set<string>;
/** Stuff that happens before the render effect */
/** Stuff that happens before the render effect(s) */
readonly init: Statement[];
/** Stuff that happens inside separate render effects (due to call expressions) */
readonly update_effects: Statement[];
/** Stuff that happens inside the render effect */
@ -42,7 +41,7 @@ export interface ComponentClientTransformState extends ClientTransformState {
/** Used if condition for singular prop is false (see comment above) */
grouped: Statement;
}[];
/** Stuff that happens after the render effect (bindings, actions) */
/** Stuff that happens after the render effect (control blocks, dynamic elements, bindings, actions, etc) */
readonly after_update: Statement[];
/** The HTML template string */
readonly template: string[];

@ -1802,11 +1802,11 @@ export const template_visitors = {
}
if (is_reactive) {
context.state.init.push(
context.state.after_update.push(
b.stmt(b.call('$.snippet_effect', b.thunk(snippet_function), ...args))
);
} else {
context.state.init.push(b.stmt(b.call(snippet_function, ...args)));
context.state.after_update.push(b.stmt(b.call(snippet_function, ...args)));
}
},
AnimateDirective(node, { state, visit }) {
@ -2604,16 +2604,14 @@ export const template_visitors = {
);
}
const getter = b.thunk(
/** @type {import('estree').Expression} */ (context.visit(node.expression))
);
const getter = b.thunk(/** @type {import('estree').Expression} */ (visit(node.expression)));
const assignment = b.assignment('=', node.expression, b.id('$$value'));
const setter = b.arrow(
[b.id('$$value')],
serialize_set_binding(
assignment,
context,
() => /** @type {import('estree').Expression} */ (context.visit(assignment)),
() => /** @type {import('estree').Expression} */ (visit(assignment)),
{
skip_proxy_and_freeze: true
}
@ -2776,9 +2774,7 @@ export const template_visitors = {
group_getter = b.thunk(
b.block([
b.stmt(serialize_attribute_value(value, context)[1]),
b.return(
/** @type {import('estree').Expression} */ (context.visit(node.expression))
)
b.return(/** @type {import('estree').Expression} */ (visit(node.expression)))
])
);
}
@ -2987,7 +2983,7 @@ export const template_visitors = {
: b.member(b.member(b.id('$$props'), b.id('$$slots')), name, true, true);
const slot = b.call('$.slot', context.state.node, expression, props_expression, fallback);
context.state.init.push(b.stmt(slot));
context.state.after_update.push(b.stmt(slot));
},
SvelteHead(node, context) {
// TODO attributes?

@ -1445,9 +1445,6 @@ const template_visitors = {
context.state.init.push(b.stmt(b.call('$.add_snippet_symbol', node.expression)));
}
},
BindDirective(node, context) {
// TODO
},
Component(node, context) {
const state = context.state;
const [dec, id] = serialize_anchor(state);
@ -1687,9 +1684,19 @@ function serialize_element_attributes(node, context) {
if (binding?.omit_in_ssr) continue;
if (ContentEditableBindings.includes(attribute.name)) {
content = { escape: false, expression: attribute.expression };
content = {
escape: false,
expression: /** @type {import('estree').Expression} */ (
context.visit(attribute.expression)
)
};
} else if (attribute.name === 'value' && node.name === 'textarea') {
content = { escape: true, expression: attribute.expression };
content = {
escape: true,
expression: /** @type {import('estree').Expression} */ (
context.visit(attribute.expression)
)
};
} else if (attribute.name === 'group') {
const value_attribute = /** @type {import('#compiler').Attribute | undefined} */ (
node.attributes.find((attr) => attr.type === 'Attribute' && attr.name === 'value')

@ -11,11 +11,15 @@ import {
batch_inspect
} from '../runtime.js';
import {
array_prototype,
define_property,
get_descriptor,
get_descriptors,
get_prototype_of,
is_array,
object_keys
is_frozen,
object_keys,
object_prototype
} from '../utils.js';
/** @typedef {{ s: Map<string | symbol, import('../types.js').SourceSignal<any>>; v: import('../types.js').SourceSignal<number>; a: boolean, i: boolean, p: StateObject }} Metadata */
@ -23,12 +27,6 @@ import {
export const STATE_SYMBOL = Symbol('$state');
export const READONLY_SYMBOL = Symbol('readonly');
const object_prototype = Object.prototype;
const array_prototype = Array.prototype;
const get_prototype_of = Object.getPrototypeOf;
const is_frozen = Object.isFrozen;
/**
* @template {StateObject} T
* @param {T} value

@ -1,7 +1,16 @@
import { DEV } from 'esm-env';
import { subscribe_to_store } from '../../store/utils.js';
import { EMPTY_FUNC, run_all } from '../common.js';
import { get_descriptor, get_descriptors, is_array, is_frozen, object_freeze } from './utils.js';
import {
array_prototype,
get_descriptor,
get_descriptors,
get_prototype_of,
is_array,
is_frozen,
object_freeze,
object_prototype
} from './utils.js';
import {
PROPS_IS_LAZY_INITIAL,
PROPS_IS_IMMUTABLE,
@ -1975,7 +1984,9 @@ function deep_unstate(value, visited = new Map()) {
visited.set(value, unstated);
return unstated;
}
const prototype = get_prototype_of(value);
// Only deeply unstate plain objects and arrays
if (prototype === object_prototype || prototype === array_prototype) {
let contains_unstated = false;
/** @type {any} */
const nested_unstated = Array.isArray(value) ? [] : {};
@ -1986,8 +1997,10 @@ function deep_unstate(value, visited = new Map()) {
contains_unstated = true;
}
}
visited.set(value, contains_unstated ? nested_unstated : value);
} else {
visited.set(value, value);
}
}
return visited.get(value) ?? value;

@ -10,6 +10,9 @@ export var object_freeze = Object.freeze;
export var define_property = Object.defineProperty;
export var get_descriptor = Object.getOwnPropertyDescriptor;
export var get_descriptors = Object.getOwnPropertyDescriptors;
export var object_prototype = Object.prototype;
export var array_prototype = Array.prototype;
export var get_prototype_of = Object.getPrototypeOf;
/**
* @param {any} thing

@ -4,11 +4,15 @@ export default test({
html: `
<input>
<p>hello world</p>
<textarea></textarea>
<div contenteditable="true">world</div>
`,
ssrHtml: `
<input value="world">
<p>hello world</p>
<textarea>world</textarea>
<div contenteditable="true">world</div>
`,
async test({ assert, component, target, window }) {
@ -34,6 +38,8 @@ export default test({
`
<input>
<p>hello everybody</p>
<textarea></textarea>
<div contenteditable="true">everybody</div>
`
);
@ -44,6 +50,8 @@ export default test({
`
<input>
<p>hello goodbye</p>
<textarea></textarea>
<div contenteditable="true">goodbye</div>
`
);

@ -7,3 +7,5 @@
<input bind:value={$name}>
<p>hello {$name}</p>
<textarea bind:value={$name} />
<div contenteditable="true" bind:innerHTML={$name}></div>

Loading…
Cancel
Save