diff --git a/CHANGELOG.md b/CHANGELOG.md index 995184c017..1a2216284b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,37 @@ # Svelte changelog +## 1.54.1 + +* Hoist destructured references ([#1139](https://github.com/sveltejs/svelte/issues/1139)) +* Add `bind:volume` for media elements ([#1143](https://github.com/sveltejs/svelte/issues/1143)) + +## 1.54.0 + +* Run `oncreate` hooks depth-first, top-to-bottom ([#1135](https://github.com/sveltejs/svelte/issues/1135)) +* Render boolean attributes correctly in SSR mode ([#1109](https://github.com/sveltejs/svelte/issues/1109)) +* Add `feed` aria role to expected roles when doing a11y checks ([#1124](https://github.com/sveltejs/svelte/pull/1124)) +* More complete fix for case sensitive attributes ([#1062](https://github.com/sveltejs/svelte/issues/1062)) +* Handle CLRF line endings in await block comments ([#1132](https://github.com/sveltejs/svelte/issues/1132)) + +## 1.53.0 + +* Base scoping selectors on `' + ); + parser.read(/<\/style>/); + element.end = parser.index; } else { parser.stack.push(element); } diff --git a/src/shared/index.js b/src/shared/index.js index 3adae010c2..ef160ebf07 100644 --- a/src/shared/index.js +++ b/src/shared/index.js @@ -177,7 +177,7 @@ export function setDev(newState) { } export function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } export function _mount(target, anchor) { diff --git a/src/utils/annotateWithScopes.ts b/src/utils/annotateWithScopes.ts index 9b5c9d5e88..41e734b6e9 100644 --- a/src/utils/annotateWithScopes.ts +++ b/src/utils/annotateWithScopes.ts @@ -1,11 +1,13 @@ import { walk } from 'estree-walker'; +import isReference from 'is-reference'; import { Node } from '../interfaces'; export default function annotateWithScopes(expression: Node) { + const globals = new Set(); let scope = new Scope(null, false); walk(expression, { - enter(node: Node) { + enter(node: Node, parent: Node) { if (/Function/.test(node.type)) { if (node.type === 'FunctionDeclaration') { scope.declarations.add(node.id.name); @@ -25,6 +27,10 @@ export default function annotateWithScopes(expression: Node) { node._scope = scope = new Scope(scope, true); } else if (/(Function|Class|Variable)Declaration/.test(node.type)) { scope.addDeclaration(node); + } else if (isReference(node, parent)) { + if (!scope.has(node.name)) { + globals.add(node.name); + } } }, @@ -35,7 +41,7 @@ export default function annotateWithScopes(expression: Node) { }, }); - return scope; + return { scope, globals }; } export class Scope { diff --git a/src/utils/createDebuggingComment.ts b/src/utils/createDebuggingComment.ts index bb9dffd0f4..65a3270ebb 100644 --- a/src/utils/createDebuggingComment.ts +++ b/src/utils/createDebuggingComment.ts @@ -17,5 +17,5 @@ export default function createDebuggingComment(node: Node, generator: DomGenerat const start = locate(c); const loc = `(${start.line + 1}:${start.column})`; - return `${loc} ${source.slice(c, d)}`.replace(/\n/g, ' '); -} \ No newline at end of file + return `${loc} ${source.slice(c, d)}`.replace(/\s/g, ' '); +} diff --git a/src/utils/fixAttributeCasing.ts b/src/utils/fixAttributeCasing.ts new file mode 100644 index 0000000000..bcd7f50edd --- /dev/null +++ b/src/utils/fixAttributeCasing.ts @@ -0,0 +1,12 @@ +const svgAttributes = 'accent-height accumulate additive alignment-baseline allowReorder alphabetic amplitude arabic-form ascent attributeName attributeType autoReverse azimuth baseFrequency baseline-shift baseProfile bbox begin bias by calcMode cap-height class clip clipPathUnits clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering contentScriptType contentStyleType cursor cx cy d decelerate descent diffuseConstant direction display divisor dominant-baseline dur dx dy edgeMode elevation enable-background end exponent externalResourcesRequired fill fill-opacity fill-rule filter filterRes filterUnits flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format from fr fx fy g1 g2 glyph-name glyph-orientation-horizontal glyph-orientation-vertical glyphRef gradientTransform gradientUnits hanging height href horiz-adv-x horiz-origin-x id ideographic image-rendering in in2 intercept k k1 k2 k3 k4 kernelMatrix kernelUnitLength kerning keyPoints keySplines keyTimes lang lengthAdjust letter-spacing lighting-color limitingConeAngle local marker-end marker-mid marker-start markerHeight markerUnits markerWidth mask maskContentUnits maskUnits mathematical max media method min mode name numOctaves offset onabort onactivate onbegin onclick onend onerror onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup onrepeat onresize onscroll onunload opacity operator order orient orientation origin overflow overline-position overline-thickness panose-1 paint-order pathLength patternContentUnits patternTransform patternUnits pointer-events points pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits r radius refX refY rendering-intent repeatCount repeatDur requiredExtensions requiredFeatures restart result rotate rx ry scale seed shape-rendering slope spacing specularConstant specularExponent speed spreadMethod startOffset stdDeviation stemh stemv stitchTiles stop-color stop-opacity strikethrough-position strikethrough-thickness string stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale systemLanguage tabindex tableValues target targetX targetY text-anchor text-decoration text-rendering textLength to transform type u1 u2 underline-position underline-thickness unicode unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical values version vert-adv-y vert-origin-x vert-origin-y viewBox viewTarget visibility width widths word-spacing writing-mode x x-height x1 x2 xChannelSelector xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y y1 y2 yChannelSelector z zoomAndPan'.split(' '); + +const svgAttributeLookup = new Map(); + +svgAttributes.forEach(name => { + svgAttributeLookup.set(name.toLowerCase(), name); +}); + +export default function fixAttributeCasing(name) { + name = name.toLowerCase(); + return svgAttributeLookup.get(name) || name; +} diff --git a/src/utils/fullCharCodeAt.ts b/src/utils/fullCharCodeAt.ts new file mode 100644 index 0000000000..034da9258b --- /dev/null +++ b/src/utils/fullCharCodeAt.ts @@ -0,0 +1,10 @@ +// Adapted from https://github.com/acornjs/acorn/blob/6584815dca7440e00de841d1dad152302fdd7ca5/src/tokenize.js +// Reproduced under MIT License https://github.com/acornjs/acorn/blob/master/LICENSE + +export default function fullCharCodeAt(str: string, i: number): number { + let code = str.charCodeAt(i) + if (code <= 0xd7ff || code >= 0xe000) return code; + + let next = str.charCodeAt(i + 1); + return (code << 10) + next - 0x35fdc00; +} \ No newline at end of file diff --git a/src/parse/utils/hash.ts b/src/utils/hash.ts similarity index 100% rename from src/parse/utils/hash.ts rename to src/utils/hash.ts diff --git a/src/utils/isValidIdentifier.ts b/src/utils/isValidIdentifier.ts new file mode 100644 index 0000000000..20ceeb4bbf --- /dev/null +++ b/src/utils/isValidIdentifier.ts @@ -0,0 +1,15 @@ +import { isIdentifierStart, isIdentifierChar } from 'acorn'; +import fullCharCodeAt from './fullCharCodeAt'; + +export default function isValidIdentifier(str: string): boolean { + let i = 0; + + while (i < str.length) { + const code = fullCharCodeAt(str, i); + if (!(i === 0 ? isIdentifierStart : isIdentifierChar)(code, true)) return false; + + i += code <= 0xffff ? 1 : 2; + } + + return true; +} \ No newline at end of file diff --git a/src/validate/html/a11y.ts b/src/validate/html/a11y.ts index 4dbf249fff..1e07c0b4d4 100644 --- a/src/validate/html/a11y.ts +++ b/src/validate/html/a11y.ts @@ -8,7 +8,7 @@ import { Node } from '../../interfaces'; const ariaAttributes = 'activedescendant atomic autocomplete busy checked controls current describedby disabled dropeffect expanded flowto grabbed haspopup hidden invalid label labelledby level live multiline multiselectable orientation owns posinset pressed readonly relevant required selected setsize sort valuemax valuemin valuenow valuetext'.split(' '); const ariaAttributeSet = new Set(ariaAttributes); -const ariaRoles = 'alert alertdialog application article banner button checkbox columnheader combobox command complementary composite contentinfo definition dialog directory document form grid gridcell group heading img input landmark link list listbox listitem log main marquee math menu menubar menuitem menuitemcheckbox menuitemradio navigation note option presentation progressbar radio radiogroup range region roletype row rowgroup rowheader scrollbar search section sectionhead select separator slider spinbutton status structure tab tablist tabpanel textbox timer toolbar tooltip tree treegrid treeitem widget window'.split(' '); +const ariaRoles = 'alert alertdialog application article banner button checkbox columnheader combobox command complementary composite contentinfo definition dialog directory document feed form grid gridcell group heading img input landmark link list listbox listitem log main marquee math menu menubar menuitem menuitemcheckbox menuitemradio navigation note option presentation progressbar radio radiogroup range region roletype row rowgroup rowheader scrollbar search section sectionhead select separator slider spinbutton status structure tab tablist tabpanel textbox timer toolbar tooltip tree treegrid treeitem widget window'.split(' '); const ariaRoleSet = new Set(ariaRoles); const invisibleElements = new Set(['meta', 'html', 'script', 'style']); diff --git a/src/validate/html/index.ts b/src/validate/html/index.ts index bf94b63c52..b2a190696f 100644 --- a/src/validate/html/index.ts +++ b/src/validate/html/index.ts @@ -19,14 +19,29 @@ export default function validateHtml(validator: Validator, html: Node) { const elementStack: Node[] = []; function visit(node: Node) { - a11y(validator, node, elementStack); - if (node.type === 'Element') { if (meta.has(node.name)) { return meta.get(node.name)(validator, node, refs, refCallees); } - validateElement(validator, node, refs, refCallees, stack, elementStack); + const isComponent = + node.name === ':Self' || + node.name === ':Component' || + validator.components.has(node.name); + + validateElement( + validator, + node, + refs, + refCallees, + stack, + elementStack, + isComponent + ); + + if (!isComponent) { + a11y(validator, node, elementStack); + } } else if (node.type === 'EachBlock') { if (validator.helpers.has(node.context)) { let c = node.expression.end; @@ -54,6 +69,12 @@ export default function validateHtml(validator: Validator, html: Node) { if (node.else) { visit(node.else); } + + if (node.type === 'AwaitBlock') { + visit(node.pending); + visit(node.then); + visit(node.catch); + } } html.children.forEach(visit); diff --git a/src/validate/html/validateElement.ts b/src/validate/html/validateElement.ts index 2572fd29d4..550f8d2ae7 100644 --- a/src/validate/html/validateElement.ts +++ b/src/validate/html/validateElement.ts @@ -11,11 +11,9 @@ export default function validateElement( refs: Map, refCallees: Node[], stack: Node[], - elementStack: Node[] + elementStack: Node[], + isComponent: Boolean ) { - const isComponent = - node.name === ':Self' || node.name === ':Component' || validator.components.has(node.name); - if (isComponent) { validator.used.components.add(node.name); } @@ -141,7 +139,8 @@ export default function validateElement( name === 'paused' || name === 'buffered' || name === 'seekable' || - name === 'played' + name === 'played' || + name === 'volume' ) { if (node.name !== 'audio' && node.name !== 'video') { validator.error( diff --git a/src/validate/html/validateHead.ts b/src/validate/html/validateHead.ts index 73d100a450..bac56474b2 100644 --- a/src/validate/html/validateHead.ts +++ b/src/validate/html/validateHead.ts @@ -11,6 +11,6 @@ export default function validateHead(validator: Validator, node: Node, refs: Map node.children.forEach(node => { if (node.type !== 'Element') return; // TODO handle {{#if}} and friends? - validateElement(validator, node, refs, refCallees, [], []); + validateElement(validator, node, refs, refCallees, [], [], false); }); } diff --git a/src/validate/js/propValidators/computed.ts b/src/validate/js/propValidators/computed.ts index 644043ddb1..94a7212881 100644 --- a/src/validate/js/propValidators/computed.ts +++ b/src/validate/js/propValidators/computed.ts @@ -1,5 +1,8 @@ import checkForDupes from '../utils/checkForDupes'; import checkForComputedKeys from '../utils/checkForComputedKeys'; +import getName from '../../../utils/getName'; +import isValidIdentifier from '../../../utils/isValidIdentifier'; +import reservedNames from '../../../utils/reservedNames'; import { Validator } from '../../'; import { Node } from '../../../interfaces'; import walkThroughTopFunctionScope from '../../../utils/walkThroughTopFunctionScope'; @@ -22,6 +25,23 @@ export default function computed(validator: Validator, prop: Node) { checkForComputedKeys(validator, prop.value.properties); prop.value.properties.forEach((computation: Node) => { + const name = getName(computation.key); + + if (!isValidIdentifier(name)) { + const suggestion = name.replace(/[^_$a-z0-9]/ig, '_').replace(/^\d/, '_$&'); + validator.error( + `Computed property name '${name}' is invalid — must be a valid identifier such as ${suggestion}`, + computation.start + ); + } + + if (reservedNames.has(name)) { + validator.error( + `Computed property name '${name}' is invalid — cannot be a JavaScript reserved word`, + computation.start + ); + } + if (!isFunctionExpression.has(computation.value.type)) { validator.error( `Computed properties can be function expressions or arrow function expressions`, diff --git a/test/css/index.js b/test/css/index.js index 1e91e770c8..b2e989d571 100644 --- a/test/css/index.js +++ b/test/css/index.js @@ -117,6 +117,8 @@ describe('css', () => { normalizeHtml(window, html.replace(/svelte-\d+/g, 'svelte-xyz')), normalizeHtml(window, expected.html) ); + + window.document.head.innerHTML = ''; // remove added styles } catch (err) { console.log(dom.code); throw err; diff --git a/test/js/samples/collapses-text-around-comments/expected-bundle.js b/test/js/samples/collapses-text-around-comments/expected-bundle.js index 487665fe9d..59cd2de125 100644 --- a/test/js/samples/collapses-text-around-comments/expected-bundle.js +++ b/test/js/samples/collapses-text-around-comments/expected-bundle.js @@ -167,7 +167,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { @@ -198,13 +198,13 @@ function data() { } function encapsulateStyles(node) { - setAttribute(node, "svelte-3590263702", ""); + setAttribute(node, "svelte-2794052100", ""); } function add_css() { var style = createElement("style"); - style.id = 'svelte-3590263702-style'; - style.textContent = "p[svelte-3590263702],[svelte-3590263702] p{color:red}"; + style.id = 'svelte-2794052100-style'; + style.textContent = "p[svelte-2794052100],[svelte-2794052100] p{color:red}"; appendNode(style, document.head); } @@ -245,7 +245,7 @@ function SvelteComponent(options) { init(this, options); this._state = assign(data(), options.data); - if (!document.getElementById("svelte-3590263702-style")) add_css(); + if (!document.getElementById("svelte-2794052100-style")) add_css(); this._fragment = create_main_fragment(this._state, this); diff --git a/test/js/samples/collapses-text-around-comments/expected.js b/test/js/samples/collapses-text-around-comments/expected.js index 0ad2ccd29e..aea4721e36 100644 --- a/test/js/samples/collapses-text-around-comments/expected.js +++ b/test/js/samples/collapses-text-around-comments/expected.js @@ -6,13 +6,13 @@ function data() { }; function encapsulateStyles(node) { - setAttribute(node, "svelte-3590263702", ""); + setAttribute(node, "svelte-2794052100", ""); } function add_css() { var style = createElement("style"); - style.id = 'svelte-3590263702-style'; - style.textContent = "p[svelte-3590263702],[svelte-3590263702] p{color:red}"; + style.id = 'svelte-2794052100-style'; + style.textContent = "p[svelte-2794052100],[svelte-2794052100] p{color:red}"; appendNode(style, document.head); } @@ -53,7 +53,7 @@ function SvelteComponent(options) { init(this, options); this._state = assign(data(), options.data); - if (!document.getElementById("svelte-3590263702-style")) add_css(); + if (!document.getElementById("svelte-2794052100-style")) add_css(); this._fragment = create_main_fragment(this._state, this); diff --git a/test/js/samples/component-static/expected-bundle.js b/test/js/samples/component-static/expected-bundle.js index d304821c98..708ef5be95 100644 --- a/test/js/samples/component-static/expected-bundle.js +++ b/test/js/samples/component-static/expected-bundle.js @@ -143,7 +143,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/computed-collapsed-if/expected-bundle.js b/test/js/samples/computed-collapsed-if/expected-bundle.js index 1732dcf323..b39f95a77b 100644 --- a/test/js/samples/computed-collapsed-if/expected-bundle.js +++ b/test/js/samples/computed-collapsed-if/expected-bundle.js @@ -143,7 +143,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/css-media-query/expected-bundle.js b/test/js/samples/css-media-query/expected-bundle.js index 0d653764f2..91662053a4 100644 --- a/test/js/samples/css-media-query/expected-bundle.js +++ b/test/js/samples/css-media-query/expected-bundle.js @@ -163,7 +163,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { @@ -190,13 +190,13 @@ var proto = { /* generated by Svelte vX.Y.Z */ function encapsulateStyles(node) { - setAttribute(node, "svelte-2363328337", ""); + setAttribute(node, "svelte-3905933315", ""); } function add_css() { var style = createElement("style"); - style.id = 'svelte-2363328337-style'; - style.textContent = "@media(min-width: 1px){div[svelte-2363328337],[svelte-2363328337] div{color:red}}"; + style.id = 'svelte-3905933315-style'; + style.textContent = "@media(min-width: 1px){div[svelte-3905933315],[svelte-3905933315] div{color:red}}"; appendNode(style, document.head); } @@ -231,7 +231,7 @@ function SvelteComponent(options) { init(this, options); this._state = assign({}, options.data); - if (!document.getElementById("svelte-2363328337-style")) add_css(); + if (!document.getElementById("svelte-3905933315-style")) add_css(); this._fragment = create_main_fragment(this._state, this); diff --git a/test/js/samples/css-media-query/expected.js b/test/js/samples/css-media-query/expected.js index 3c36f9c6ce..37afa6b42a 100644 --- a/test/js/samples/css-media-query/expected.js +++ b/test/js/samples/css-media-query/expected.js @@ -2,13 +2,13 @@ import { appendNode, assign, createElement, detachNode, init, insertNode, noop, proto, setAttribute } from "svelte/shared.js"; function encapsulateStyles(node) { - setAttribute(node, "svelte-2363328337", ""); + setAttribute(node, "svelte-3905933315", ""); } function add_css() { var style = createElement("style"); - style.id = 'svelte-2363328337-style'; - style.textContent = "@media(min-width: 1px){div[svelte-2363328337],[svelte-2363328337] div{color:red}}"; + style.id = 'svelte-3905933315-style'; + style.textContent = "@media(min-width: 1px){div[svelte-3905933315],[svelte-3905933315] div{color:red}}"; appendNode(style, document.head); } @@ -43,7 +43,7 @@ function SvelteComponent(options) { init(this, options); this._state = assign({}, options.data); - if (!document.getElementById("svelte-2363328337-style")) add_css(); + if (!document.getElementById("svelte-3905933315-style")) add_css(); this._fragment = create_main_fragment(this._state, this); diff --git a/test/js/samples/css-shadow-dom-keyframes/expected-bundle.js b/test/js/samples/css-shadow-dom-keyframes/expected-bundle.js index 3edee605c1..03e5cef1e2 100644 --- a/test/js/samples/css-shadow-dom-keyframes/expected-bundle.js +++ b/test/js/samples/css-shadow-dom-keyframes/expected-bundle.js @@ -155,7 +155,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/deconflict-globals/expected-bundle.js b/test/js/samples/deconflict-globals/expected-bundle.js new file mode 100644 index 0000000000..ba22542c4b --- /dev/null +++ b/test/js/samples/deconflict-globals/expected-bundle.js @@ -0,0 +1,221 @@ +function noop() {} + +function assign(target) { + var k, + source, + i = 1, + len = arguments.length; + for (; i < len; i++) { + source = arguments[i]; + for (k in source) target[k] = source[k]; + } + + return target; +} + +function blankObject() { + return Object.create(null); +} + +function destroy(detach) { + this.destroy = noop; + this.fire('destroy'); + this.set = this.get = noop; + + if (detach !== false) this._fragment.u(); + this._fragment.d(); + this._fragment = this._state = null; +} + +function differs(a, b) { + return a !== b || ((a && typeof a === 'object') || typeof a === 'function'); +} + +function dispatchObservers(component, group, changed, newState, oldState) { + for (var key in group) { + if (!changed[key]) continue; + + var newValue = newState[key]; + var oldValue = oldState[key]; + + var callbacks = group[key]; + if (!callbacks) continue; + + for (var i = 0; i < callbacks.length; i += 1) { + var callback = callbacks[i]; + if (callback.__calling) continue; + + callback.__calling = true; + callback.call(component, newValue, oldValue); + callback.__calling = false; + } + } +} + +function fire(eventName, data) { + var handlers = + eventName in this._handlers && this._handlers[eventName].slice(); + if (!handlers) return; + + for (var i = 0; i < handlers.length; i += 1) { + handlers[i].call(this, data); + } +} + +function get(key) { + return key ? this._state[key] : this._state; +} + +function init(component, options) { + component._observers = { pre: blankObject(), post: blankObject() }; + component._handlers = blankObject(); + component._bind = options._bind; + + component.options = options; + component.root = options.root || component; + component.store = component.root.store || options.store; +} + +function observe(key, callback, options) { + var group = options && options.defer + ? this._observers.post + : this._observers.pre; + + (group[key] || (group[key] = [])).push(callback); + + if (!options || options.init !== false) { + callback.__calling = true; + callback.call(this, this._state[key]); + callback.__calling = false; + } + + return { + cancel: function() { + var index = group[key].indexOf(callback); + if (~index) group[key].splice(index, 1); + } + }; +} + +function on(eventName, handler) { + if (eventName === 'teardown') return this.on('destroy', handler); + + var handlers = this._handlers[eventName] || (this._handlers[eventName] = []); + handlers.push(handler); + + return { + cancel: function() { + var index = handlers.indexOf(handler); + if (~index) handlers.splice(index, 1); + } + }; +} + +function set(newState) { + this._set(assign({}, newState)); + if (this.root._lock) return; + this.root._lock = true; + callAll(this.root._beforecreate); + callAll(this.root._oncreate); + callAll(this.root._aftercreate); + this.root._lock = false; +} + +function _set(newState) { + var oldState = this._state, + changed = {}, + dirty = false; + + for (var key in newState) { + if (differs(newState[key], oldState[key])) changed[key] = dirty = true; + } + if (!dirty) return; + + this._state = assign({}, oldState, newState); + this._recompute(changed, this._state); + if (this._bind) this._bind(changed, this._state); + + if (this._fragment) { + dispatchObservers(this, this._observers.pre, changed, this._state, oldState); + this._fragment.p(changed, this._state); + dispatchObservers(this, this._observers.post, changed, this._state, oldState); + } +} + +function callAll(fns) { + while (fns && fns.length) fns.shift()(); +} + +function _mount(target, anchor) { + this._fragment.m(target, anchor); +} + +function _unmount() { + if (this._fragment) this._fragment.u(); +} + +var proto = { + destroy: destroy, + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + teardown: destroy, + _recompute: noop, + _set: _set, + _mount: _mount, + _unmount: _unmount +}; + +/* generated by Svelte vX.Y.Z */ +function data_1() { + return { + foo: 'bar' +}; +} + +function oncreate() { + alert(JSON.stringify(data())); +} + +function create_main_fragment(state, component) { + + return { + c: noop, + + m: noop, + + p: noop, + + u: noop, + + d: noop + }; +} + +function SvelteComponent(options) { + init(this, options); + this._state = assign(data_1(), options.data); + + var _oncreate = oncreate.bind(this); + + if (!options.root) { + this._oncreate = []; + } + + this._fragment = create_main_fragment(this._state, this); + + this.root._oncreate.push(_oncreate); + + if (options.target) { + this._fragment.c(); + this._fragment.m(options.target, options.anchor || null); + + callAll(this._oncreate); + } +} + +assign(SvelteComponent.prototype, proto); + +export default SvelteComponent; diff --git a/test/js/samples/deconflict-globals/expected.js b/test/js/samples/deconflict-globals/expected.js new file mode 100644 index 0000000000..8730f4e3c3 --- /dev/null +++ b/test/js/samples/deconflict-globals/expected.js @@ -0,0 +1,52 @@ +/* generated by Svelte vX.Y.Z */ +import { assign, callAll, init, noop, proto } from "svelte/shared.js"; + +function data_1() { + return { + foo: 'bar' +}; +} + +function oncreate() { + alert(JSON.stringify(data())); +}; + +function create_main_fragment(state, component) { + + return { + c: noop, + + m: noop, + + p: noop, + + u: noop, + + d: noop + }; +} + +function SvelteComponent(options) { + init(this, options); + this._state = assign(data_1(), options.data); + + var _oncreate = oncreate.bind(this); + + if (!options.root) { + this._oncreate = []; + } + + this._fragment = create_main_fragment(this._state, this); + + this.root._oncreate.push(_oncreate); + + if (options.target) { + this._fragment.c(); + this._fragment.m(options.target, options.anchor || null); + + callAll(this._oncreate); + } +} + +assign(SvelteComponent.prototype, proto); +export default SvelteComponent; \ No newline at end of file diff --git a/test/js/samples/deconflict-globals/input.html b/test/js/samples/deconflict-globals/input.html new file mode 100644 index 0000000000..6c3dc88e87 --- /dev/null +++ b/test/js/samples/deconflict-globals/input.html @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/test/js/samples/do-use-dataset/expected-bundle.js b/test/js/samples/do-use-dataset/expected-bundle.js index b768840f2e..2079e6607c 100644 --- a/test/js/samples/do-use-dataset/expected-bundle.js +++ b/test/js/samples/do-use-dataset/expected-bundle.js @@ -159,7 +159,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/dont-use-dataset-in-legacy/expected-bundle.js b/test/js/samples/dont-use-dataset-in-legacy/expected-bundle.js index da13568e97..efcfcc8f30 100644 --- a/test/js/samples/dont-use-dataset-in-legacy/expected-bundle.js +++ b/test/js/samples/dont-use-dataset-in-legacy/expected-bundle.js @@ -163,7 +163,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/dont-use-dataset-in-svg/expected-bundle.js b/test/js/samples/dont-use-dataset-in-svg/expected-bundle.js index ad53e6a274..cf43bbd130 100644 --- a/test/js/samples/dont-use-dataset-in-svg/expected-bundle.js +++ b/test/js/samples/dont-use-dataset-in-svg/expected-bundle.js @@ -163,7 +163,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/each-block-changed-check/expected-bundle.js b/test/js/samples/each-block-changed-check/expected-bundle.js index 90f3eeadef..e35826e354 100644 --- a/test/js/samples/each-block-changed-check/expected-bundle.js +++ b/test/js/samples/each-block-changed-check/expected-bundle.js @@ -175,7 +175,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/event-handlers-custom/expected-bundle.js b/test/js/samples/event-handlers-custom/expected-bundle.js index 17943516aa..43db3035a3 100644 --- a/test/js/samples/event-handlers-custom/expected-bundle.js +++ b/test/js/samples/event-handlers-custom/expected-bundle.js @@ -155,7 +155,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/head-no-whitespace/expected-bundle.js b/test/js/samples/head-no-whitespace/expected-bundle.js index f6e4968c9e..91f894bc30 100644 --- a/test/js/samples/head-no-whitespace/expected-bundle.js +++ b/test/js/samples/head-no-whitespace/expected-bundle.js @@ -155,7 +155,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/if-block-no-update/expected-bundle.js b/test/js/samples/if-block-no-update/expected-bundle.js index 966081e9ed..b309a25e96 100644 --- a/test/js/samples/if-block-no-update/expected-bundle.js +++ b/test/js/samples/if-block-no-update/expected-bundle.js @@ -159,7 +159,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/if-block-simple/expected-bundle.js b/test/js/samples/if-block-simple/expected-bundle.js index 63fed6f4cf..5084639f4b 100644 --- a/test/js/samples/if-block-simple/expected-bundle.js +++ b/test/js/samples/if-block-simple/expected-bundle.js @@ -159,7 +159,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/inline-style-optimized-multiple/expected-bundle.js b/test/js/samples/inline-style-optimized-multiple/expected-bundle.js index 53526770d7..753d61db71 100644 --- a/test/js/samples/inline-style-optimized-multiple/expected-bundle.js +++ b/test/js/samples/inline-style-optimized-multiple/expected-bundle.js @@ -159,7 +159,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/inline-style-optimized-url/expected-bundle.js b/test/js/samples/inline-style-optimized-url/expected-bundle.js index 45848aad35..cf360881b1 100644 --- a/test/js/samples/inline-style-optimized-url/expected-bundle.js +++ b/test/js/samples/inline-style-optimized-url/expected-bundle.js @@ -159,7 +159,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/inline-style-optimized/expected-bundle.js b/test/js/samples/inline-style-optimized/expected-bundle.js index 84e4f81567..38024df4ff 100644 --- a/test/js/samples/inline-style-optimized/expected-bundle.js +++ b/test/js/samples/inline-style-optimized/expected-bundle.js @@ -159,7 +159,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/inline-style-unoptimized/expected-bundle.js b/test/js/samples/inline-style-unoptimized/expected-bundle.js index 5d04406716..320c733a43 100644 --- a/test/js/samples/inline-style-unoptimized/expected-bundle.js +++ b/test/js/samples/inline-style-unoptimized/expected-bundle.js @@ -159,7 +159,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/input-without-blowback-guard/expected-bundle.js b/test/js/samples/input-without-blowback-guard/expected-bundle.js index 22778e66cf..eacaca85a6 100644 --- a/test/js/samples/input-without-blowback-guard/expected-bundle.js +++ b/test/js/samples/input-without-blowback-guard/expected-bundle.js @@ -163,7 +163,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/legacy-input-type/expected-bundle.js b/test/js/samples/legacy-input-type/expected-bundle.js index 802dbfc100..7b730f08d9 100644 --- a/test/js/samples/legacy-input-type/expected-bundle.js +++ b/test/js/samples/legacy-input-type/expected-bundle.js @@ -161,7 +161,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/legacy-quote-class/expected-bundle.js b/test/js/samples/legacy-quote-class/expected-bundle.js index 09b00d11ea..499a82c46e 100644 --- a/test/js/samples/legacy-quote-class/expected-bundle.js +++ b/test/js/samples/legacy-quote-class/expected-bundle.js @@ -178,7 +178,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { diff --git a/test/js/samples/media-bindings/expected-bundle.js b/test/js/samples/media-bindings/expected-bundle.js index 9394167dca..bbd56d8123 100644 --- a/test/js/samples/media-bindings/expected-bundle.js +++ b/test/js/samples/media-bindings/expected-bundle.js @@ -171,7 +171,7 @@ function _set(newState) { } function callAll(fns) { - while (fns && fns.length) fns.pop()(); + while (fns && fns.length) fns.shift()(); } function _mount(target, anchor) { @@ -226,6 +226,12 @@ function create_main_fragment(state, component) { component.set({ buffered: timeRangesToArray(audio.buffered), seekable: timeRangesToArray(audio.seekable) }); } + function audio_volumechange_handler() { + audio_updating = true; + component.set({ volume: audio.volume }); + audio_updating = false; + } + return { c: function create() { audio = createElement("audio"); @@ -243,15 +249,19 @@ function create_main_fragment(state, component) { if (!('buffered' in state)) component.root._beforecreate.push(audio_progress_handler); addListener(audio, "loadedmetadata", audio_loadedmetadata_handler); if (!('buffered' in state && 'seekable' in state)) component.root._beforecreate.push(audio_loadedmetadata_handler); + addListener(audio, "volumechange", audio_volumechange_handler); }, m: function mount(target, anchor) { insertNode(audio, target, anchor); + + audio.volume = state.volume; }, p: function update(changed, state) { if (!audio_updating && !isNaN(state.currentTime )) audio.currentTime = state.currentTime ; - if (!audio_updating && audio_is_paused !== (audio_is_paused = state.paused)) audio[audio_is_paused ? "pause" : "play"](); + if (!audio_updating && audio_is_paused !== (audio_is_paused = state.paused )) audio[audio_is_paused ? "pause" : "play"](); + if (!audio_updating && !isNaN(state.volume)) audio.volume = state.volume; }, u: function unmount() { @@ -265,6 +275,7 @@ function create_main_fragment(state, component) { removeListener(audio, "pause", audio_play_pause_handler); removeListener(audio, "progress", audio_progress_handler); removeListener(audio, "loadedmetadata", audio_loadedmetadata_handler); + removeListener(audio, "volumechange", audio_volumechange_handler); } }; } diff --git a/test/js/samples/media-bindings/expected.js b/test/js/samples/media-bindings/expected.js index c1dd10c238..ae80f288f6 100644 --- a/test/js/samples/media-bindings/expected.js +++ b/test/js/samples/media-bindings/expected.js @@ -30,6 +30,12 @@ function create_main_fragment(state, component) { component.set({ buffered: timeRangesToArray(audio.buffered), seekable: timeRangesToArray(audio.seekable) }); } + function audio_volumechange_handler() { + audio_updating = true; + component.set({ volume: audio.volume }); + audio_updating = false; + } + return { c: function create() { audio = createElement("audio"); @@ -47,15 +53,19 @@ function create_main_fragment(state, component) { if (!('buffered' in state)) component.root._beforecreate.push(audio_progress_handler); addListener(audio, "loadedmetadata", audio_loadedmetadata_handler); if (!('buffered' in state && 'seekable' in state)) component.root._beforecreate.push(audio_loadedmetadata_handler); + addListener(audio, "volumechange", audio_volumechange_handler); }, m: function mount(target, anchor) { insertNode(audio, target, anchor); + + audio.volume = state.volume; }, p: function update(changed, state) { if (!audio_updating && !isNaN(state.currentTime )) audio.currentTime = state.currentTime ; - if (!audio_updating && audio_is_paused !== (audio_is_paused = state.paused)) audio[audio_is_paused ? "pause" : "play"](); + if (!audio_updating && audio_is_paused !== (audio_is_paused = state.paused )) audio[audio_is_paused ? "pause" : "play"](); + if (!audio_updating && !isNaN(state.volume)) audio.volume = state.volume; }, u: function unmount() { @@ -69,6 +79,7 @@ function create_main_fragment(state, component) { removeListener(audio, "pause", audio_play_pause_handler); removeListener(audio, "progress", audio_progress_handler); removeListener(audio, "loadedmetadata", audio_loadedmetadata_handler); + removeListener(audio, "volumechange", audio_volumechange_handler); } }; } diff --git a/test/js/samples/media-bindings/input.html b/test/js/samples/media-bindings/input.html index 07a5cc1bc1..e7fe359341 100644 --- a/test/js/samples/media-bindings/input.html +++ b/test/js/samples/media-bindings/input.html @@ -1 +1 @@ -