From 69804ecaf82ad43fc43957a97a850ddddcc5cc02 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 20 Sep 2018 11:50:39 -0400 Subject: [PATCH] various --- src/compile/nodes/Fragment.ts | 25 ----- src/compile/nodes/MustacheTag.ts | 26 +---- src/compile/nodes/RawMustacheTag.ts | 95 +--------------- src/compile/nodes/Slot.ts | 9 -- src/compile/render-dom/Block.ts | 25 +++-- src/compile/render-dom/Renderer.ts | 3 +- .../render-dom/wrappers/Element/Attribute.ts | 18 +++- .../wrappers/Element/Binding/SelectBinding.ts | 56 ++++++++++ .../render-dom/wrappers/Element/index.ts | 12 ++- src/compile/render-dom/wrappers/Fragment.ts | 4 + .../wrappers/InlineComponent/index.ts | 2 +- .../render-dom/wrappers/MustacheTag.ts | 4 - .../render-dom/wrappers/RawMustacheTag.ts | 101 ++++++++++++++++++ .../render-dom/wrappers/shared/Wrapper.ts | 14 ++- 14 files changed, 216 insertions(+), 178 deletions(-) create mode 100644 src/compile/render-dom/wrappers/Element/Binding/SelectBinding.ts create mode 100644 src/compile/render-dom/wrappers/RawMustacheTag.ts diff --git a/src/compile/nodes/Fragment.ts b/src/compile/nodes/Fragment.ts index 78f0481862..37fc5a675b 100644 --- a/src/compile/nodes/Fragment.ts +++ b/src/compile/nodes/Fragment.ts @@ -16,29 +16,4 @@ export default class Fragment extends Node { this.scope = scope; this.children = mapChildren(component, this, scope, info.children); } - - init() { - this.block = new Block({ - component: this.component, - name: '@create_main_fragment', - key: null, - - bindings: new Map(), - - dependencies: new Set(), - }); - - this.component.target.blocks.push(this.block); - this.initChildren(this.block, true, null); - - this.block.hasUpdateMethod = true; - } - - build() { - this.init(); - - this.children.forEach(child => { - child.build(this.block, null, 'nodes'); - }); - } } \ No newline at end of file diff --git a/src/compile/nodes/MustacheTag.ts b/src/compile/nodes/MustacheTag.ts index 3fc92d323f..e668987a9c 100644 --- a/src/compile/nodes/MustacheTag.ts +++ b/src/compile/nodes/MustacheTag.ts @@ -1,27 +1,3 @@ -import Node from './shared/Node'; import Tag from './shared/Tag'; -import Block from '../render-dom/Block'; -export default class MustacheTag extends Tag { - build( - block: Block, - parentNode: string, - parentNodes: string - ) { - const { init } = this.renameThisMethod( - block, - value => `@setData(${this.var}, ${value});` - ); - - block.addElement( - this.var, - `@createText(${init})`, - parentNodes && `@claimText(${parentNodes}, ${init})`, - parentNode - ); - } - - remount(name: string) { - return `@append(${name}._slotted.default, ${this.var});`; - } -} \ No newline at end of file +export default class MustacheTag extends Tag {} \ No newline at end of file diff --git a/src/compile/nodes/RawMustacheTag.ts b/src/compile/nodes/RawMustacheTag.ts index a23cfe04ea..ada3123410 100644 --- a/src/compile/nodes/RawMustacheTag.ts +++ b/src/compile/nodes/RawMustacheTag.ts @@ -1,96 +1,3 @@ -import deindent from '../../utils/deindent'; -import Node from './shared/Node'; import Tag from './shared/Tag'; -import Block from '../render-dom/Block'; -export default class RawMustacheTag extends Tag { - build( - block: Block, - parentNode: string, - parentNodes: string - ) { - const name = this.var; - - const needsAnchorBefore = this.prev ? this.prev.type !== 'Element' : !parentNode; - const needsAnchorAfter = this.next ? this.next.type !== 'Element' : !parentNode; - - const anchorBefore = needsAnchorBefore - ? block.getUniqueName(`${name}_before`) - : (this.prev && this.prev.var) || 'null'; - - const anchorAfter = needsAnchorAfter - ? block.getUniqueName(`${name}_after`) - : (this.next && this.next.var) || 'null'; - - let detach: string; - let insert: (content: string) => string; - let useInnerHTML = false; - - if (anchorBefore === 'null' && anchorAfter === 'null') { - useInnerHTML = true; - detach = `${parentNode}.innerHTML = '';`; - insert = content => `${parentNode}.innerHTML = ${content};`; - } else if (anchorBefore === 'null') { - detach = `@detachBefore(${anchorAfter});`; - insert = content => `${anchorAfter}.insertAdjacentHTML("beforebegin", ${content});`; - } else if (anchorAfter === 'null') { - detach = `@detachAfter(${anchorBefore});`; - insert = content => `${anchorBefore}.insertAdjacentHTML("afterend", ${content});`; - } else { - detach = `@detachBetween(${anchorBefore}, ${anchorAfter});`; - insert = content => `${anchorBefore}.insertAdjacentHTML("afterend", ${content});`; - } - - const { init } = this.renameThisMethod( - block, - content => deindent` - ${!useInnerHTML && detach} - ${insert(content)} - ` - ); - - // we would have used comments here, but the `insertAdjacentHTML` api only - // exists for `Element`s. - if (needsAnchorBefore) { - block.addElement( - anchorBefore, - `@createElement('noscript')`, - parentNodes && `@createElement('noscript')`, - parentNode, - true - ); - } - - function addAnchorAfter() { - block.addElement( - anchorAfter, - `@createElement('noscript')`, - parentNodes && `@createElement('noscript')`, - parentNode - ); - } - - if (needsAnchorAfter && anchorBefore === 'null') { - // anchorAfter needs to be in the DOM before we - // insert the HTML... - addAnchorAfter(); - } - - block.builders.mount.addLine(insert(init)); - - if (!parentNode) { - block.builders.destroy.addConditional('detach', needsAnchorBefore - ? `${detach}\n@detachNode(${anchorBefore});` - : detach); - } - - if (needsAnchorAfter && anchorBefore !== 'null') { - // ...otherwise it should go afterwards - addAnchorAfter(); - } - } - - remount(name: string) { - return `@append(${name}._slotted.default, ${this.var});`; - } -} \ No newline at end of file +export default class RawMustacheTag extends Tag {} \ No newline at end of file diff --git a/src/compile/nodes/Slot.ts b/src/compile/nodes/Slot.ts index 40a340bd7b..028f42852b 100644 --- a/src/compile/nodes/Slot.ts +++ b/src/compile/nodes/Slot.ts @@ -1,15 +1,6 @@ -import deindent from '../../utils/deindent'; -import isValidIdentifier from '../../utils/isValidIdentifier'; -import reservedNames from '../../utils/reservedNames'; import Node from './shared/Node'; import Element from './Element'; import Attribute from './Attribute'; -import Block from '../render-dom/Block'; -import { quotePropIfNecessary } from '../../utils/quoteIfNecessary'; - -function sanitize(name) { - return name.replace(/[^a-zA-Z]+/g, '_').replace(/^_/, '').replace(/_$/, ''); -} export default class Slot extends Element { type: 'Element'; diff --git a/src/compile/render-dom/Block.ts b/src/compile/render-dom/Block.ts index 8e229ae298..8183d69340 100644 --- a/src/compile/render-dom/Block.ts +++ b/src/compile/render-dom/Block.ts @@ -1,12 +1,12 @@ import CodeBuilder from '../../utils/CodeBuilder'; import deindent from '../../utils/deindent'; import { escape } from '../../utils/stringify'; -import Component from '../Component'; +import Renderer from './Renderer'; export interface BlockOptions { parent?: Block; name: string; - component?: Component; + renderer?: Renderer; comment?: string; key?: string; bindings?: Map; @@ -15,7 +15,7 @@ export interface BlockOptions { export default class Block { parent?: Block; - component: Component; + renderer: Renderer; name: string; comment?: string; @@ -60,7 +60,7 @@ export default class Block { constructor(options: BlockOptions) { this.parent = options.parent; - this.component = options.component; + this.renderer = options.renderer; this.name = options.name; this.comment = options.comment; @@ -94,7 +94,7 @@ export default class Block { this.hasOutroMethod = false; this.outros = 0; - this.getUniqueName = this.component.getUniqueNameMaker(); + this.getUniqueName = this.renderer.component.getUniqueNameMaker(); this.variables = new Map(); this.aliases = new Map() @@ -110,6 +110,7 @@ export default class Block { const dupes = new Set(); this.wrappers.forEach(wrapper => { + if (!wrapper.var) return; if (wrapper.parent && wrapper.parent.canUseInnerHTML) return; if (seen.has(wrapper.var)) { @@ -122,6 +123,8 @@ export default class Block { const counts = new Map(); this.wrappers.forEach(wrapper => { + if (!wrapper.var) return; + if (dupes.has(wrapper.var)) { const i = counts.get(wrapper.var) || 0; wrapper.var = this.getUniqueName(wrapper.var + i); @@ -159,11 +162,11 @@ export default class Block { } addIntro() { - this.hasIntros = this.hasIntroMethod = this.component.target.hasIntroTransitions = true; + this.hasIntros = this.hasIntroMethod = this.renderer.hasIntroTransitions = true; } addOutro() { - this.hasOutros = this.hasOutroMethod = this.component.target.hasOutroTransitions = true; + this.hasOutros = this.hasOutroMethod = this.renderer.hasOutroTransitions = true; this.outros += 1; } @@ -198,7 +201,7 @@ export default class Block { } toString() { - const { dev } = this.component.options; + const { dev } = this.renderer.options; if (this.hasIntroMethod || this.hasOutroMethod) { this.addVariable('#current'); @@ -233,7 +236,7 @@ export default class Block { properties.addBlock(`c: @noop,`); } else { const hydrate = !this.builders.hydrate.isEmpty() && ( - this.component.options.hydratable + this.renderer.options.hydratable ? `this.h()` : this.builders.hydrate ); @@ -246,7 +249,7 @@ export default class Block { `); } - if (this.component.options.hydratable) { + if (this.renderer.options.hydratable) { if (this.builders.claim.isEmpty() && this.builders.hydrate.isEmpty()) { properties.addBlock(`l: @noop,`); } else { @@ -259,7 +262,7 @@ export default class Block { } } - if (this.component.options.hydratable && !this.builders.hydrate.isEmpty()) { + if (this.renderer.options.hydratable && !this.builders.hydrate.isEmpty()) { properties.addBlock(deindent` ${dev ? 'h: function hydrate' : 'h'}() { ${this.builders.hydrate} diff --git a/src/compile/render-dom/Renderer.ts b/src/compile/render-dom/Renderer.ts index 97c2696b01..e1b03c7ad0 100644 --- a/src/compile/render-dom/Renderer.ts +++ b/src/compile/render-dom/Renderer.ts @@ -26,6 +26,7 @@ export default class Renderer { constructor(component: Component, options: CompileOptions) { this.component = component; this.options = options; + this.locate = component.locate; // TODO messy this.readonly = new Set(); this.slots = new Set(); @@ -40,7 +41,7 @@ export default class Renderer { // main block this.block = new Block({ - component, + renderer: this, name: '@create_main_fragment', key: null, diff --git a/src/compile/render-dom/wrappers/Element/Attribute.ts b/src/compile/render-dom/wrappers/Element/Attribute.ts index e568a877b8..85f7ad71f4 100644 --- a/src/compile/render-dom/wrappers/Element/Attribute.ts +++ b/src/compile/render-dom/wrappers/Element/Attribute.ts @@ -1,8 +1,10 @@ import Attribute from '../../../nodes/Attribute'; import Block from '../../Block'; import fixAttributeCasing from '../../../../utils/fixAttributeCasing'; -import ElementWrapper from '.'; +import ElementWrapper from './index'; import { stringify } from '../../../../utils/stringify'; +import Wrapper from '../shared/wrapper'; +import deindent from '../../../../utils/deindent'; export default class AttributeWrapper { node: Attribute; @@ -14,6 +16,20 @@ export default class AttributeWrapper { if (node.dependencies.size > 0) { parent.cannotUseInnerHTML(); + + // special case —