]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
Merge remote-tracking branch 'github/master' into changing_unwrap_ref
authorpikax <carlos@hypermob.co.uk>
Wed, 8 Apr 2020 20:21:04 +0000 (21:21 +0100)
committerpikax <carlos@hypermob.co.uk>
Wed, 8 Apr 2020 20:21:04 +0000 (21:21 +0100)
# Conflicts:
# packages/reactivity/src/ref.ts
# packages/runtime-core/__tests__/apiTemplateRef.spec.ts
# packages/runtime-core/src/apiWatch.ts

1  2 
packages/compiler-core/__tests__/transforms/vIf.spec.ts
packages/compiler-core/src/index.ts
packages/runtime-core/__tests__/apiTemplateRef.spec.ts
packages/runtime-dom/jsx.d.ts
packages/server-renderer/src/helpers/ssrRenderAttrs.ts

index 7e3470234578d6bd9782d9e25abba59abbbaa37b,0513ff4e33586f4b9ebbd055b7deaf6bc98afaa6..0ded2ac20671507c8ea4b117829a9a40c1fce7f9
@@@ -78,7 -78,23 +78,23 @@@ describe('compiler: v-if', () => 
        expect(node.branches[0].children[2].type).toBe(NodeTypes.ELEMENT)
        expect((node.branches[0].children[2] as ElementNode).tag).toBe(`p`)
      })
 -  
 +
+     test('component v-if', () => {
+       const { node } = parseWithIfTransform(`<Component v-if="ok"></Component>`)
+       expect(node.type).toBe(NodeTypes.IF)
+       expect(node.branches.length).toBe(1)
+       expect((node.branches[0].children[0] as ElementNode).tag).toBe(
+         `Component`
+       )
+       expect((node.branches[0].children[0] as ElementNode).tagType).toBe(
+         ElementTypes.COMPONENT
+       )
+       expect(
+         ((node.branches[0].children[0] as ElementNode)!
+           .codegenNode as VNodeCall)!.isBlock
+       ).toBe(false)
+     })
      test('v-if + v-else', () => {
        const { node } = parseWithIfTransform(`<div v-if="ok"/><p v-else/>`)
        expect(node.type).toBe(NodeTypes.IF)
index d5ce029779a27f221b50339fef15b4b213490df8,432492aa2a9856dc383fcd5f66d3d29817d30d25..ba2587fdd74588bd48614819f35b65942600c949
@@@ -96,19 -26,28 +26,32 @@@ export 
    CompilerError,
    createCompilerError
  } from './errors'
  export * from './ast'
  export * from './utils'
- export { registerRuntimeHelpers } from './runtimeHelpers'
+ export * from './runtimeHelpers'
  
- // expose transforms so higher-order compilers can import and extend them
+ export { getBaseTransformPreset, TransformPreset } from './compile'
  export { transformModel } from './transforms/vModel'
  export { transformOn } from './transforms/vOn'
- // utility, but need to rewrite typing to avoid dts relying on @vue/shared
- import { generateCodeFrame as _genCodeFrame } from '@vue/shared'
- const generateCodeFrame = _genCodeFrame as (
-   source: string,
-   start?: number,
-   end?: number
- ) => string
- export { generateCodeFrame }
+ export { transformBind } from './transforms/vBind'
+ export { noopDirectiveTransform } from './transforms/noopDirectiveTransform'
+ export { processIf } from './transforms/vIf'
+ export { processFor, createForLoopParams } from './transforms/vFor'
+ export {
+   transformExpression,
+   processExpression
+ } from './transforms/transformExpression'
+ export {
+   buildSlots,
+   SlotFnBuilder,
+   trackVForSlotScopes,
+   trackSlotScopes
+ } from './transforms/vSlot'
 -export { transformElement, resolveComponentType, buildProps } from './transforms/transformElement'
++export {
++  transformElement,
++  resolveComponentType,
++  buildProps
++} from './transforms/transformElement'
+ export { processSlotOutlet } from './transforms/transformSlotOutlet'
+ export { generateCodeFrame } from '@vue/shared'
index 05a8654676e976610e3cf60353fa65fb44fe1180,cdf6f409d227708d6412329ddc504912e4661980..8748c4f661f1e056776ca981b004a5cad50e9bea
@@@ -18,31 -12,288 +12,311 @@@ import { Ref, ComponentPublicInstance 
  //      Patricio Zavolinsky <https://github.com/pzavolinsky>
  //      Digiguru <https://github.com/digiguru>
  //      Eric Anderson <https://github.com/ericanderson>
- //      Albert Kurniawan <https://github.com/morcerf>
- //      Tanguy Krotoff <https://github.com/tkrotoff>
  //      Dovydas Navickas <https://github.com/DovydasNavickas>
- //      Stéphane Goetz <https://github.com/onigoetz>
+ //                 Josh Rutherford <https://github.com/theruther4d>
+ //                 Guilherme Hübner <https://github.com/guilhermehubner>
+ //                 Ferdy Budhidharma <https://github.com/ferdaber>
+ //                 Johann Rakotoharisoa <https://github.com/jrakotoharisoa>
+ //                 Olivier Pascal <https://github.com/pascaloliv>
+ //                 Martin Hochel <https://github.com/hotell>
+ //                 Frank Li <https://github.com/franklixuefei>
+ //                 Jessica Franco <https://github.com/Jessidhia>
+ //                 Saransh Kataria <https://github.com/saranshkataria>
+ //                 Kanitkorn Sujautra <https://github.com/lukyth>
+ //                 Sebastian Silbermann <https://github.com/eps1lon>
+ import * as CSS from 'csstype'
+ export interface CSSProperties extends CSS.Properties<string | number> {
+   /**
+    * The index signature was removed to enable closed typing for style
+    * using CSSType. You're able to use type assertion or module augmentation
+    * to add properties or an index signature of your own.
+    *
+    * For examples and more information, visit:
+    * https://github.com/frenic/csstype#what-should-i-do-when-i-get-type-errors
+    */
+ }
+ type Booleanish = boolean | 'true' | 'false'
+ // All the WAI-ARIA 1.1 attributes from https://www.w3.org/TR/wai-aria-1.1/
+ interface AriaAttributes {
+   /** Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application. */
+   'aria-activedescendant'?: string
+   /** Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute. */
+   'aria-atomic'?: boolean | 'false' | 'true'
+   /**
+    * Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be
+    * presented if they are made.
+    */
+   'aria-autocomplete'?: 'none' | 'inline' | 'list' | 'both'
+   /** Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user. */
+   'aria-busy'?: boolean | 'false' | 'true'
+   /**
+    * Indicates the current "checked" state of checkboxes, radio buttons, and other widgets.
+    * @see aria-pressed @see aria-selected.
+    */
+   'aria-checked'?: boolean | 'false' | 'mixed' | 'true'
+   /**
+    * Defines the total number of columns in a table, grid, or treegrid.
+    * @see aria-colindex.
+    */
+   'aria-colcount'?: number
+   /**
+    * Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid.
+    * @see aria-colcount @see aria-colspan.
+    */
+   'aria-colindex'?: number
+   /**
+    * Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid.
+    * @see aria-colindex @see aria-rowspan.
+    */
+   'aria-colspan'?: number
+   /**
+    * Identifies the element (or elements) whose contents or presence are controlled by the current element.
+    * @see aria-owns.
+    */
+   'aria-controls'?: string
+   /** Indicates the element that represents the current item within a container or set of related elements. */
 -  'aria-current'?: boolean | 'false' | 'true' | 'page' | 'step' | 'location' | 'date' | 'time'
++  'aria-current'?:
++    | boolean
++    | 'false'
++    | 'true'
++    | 'page'
++    | 'step'
++    | 'location'
++    | 'date'
++    | 'time'
+   /**
+    * Identifies the element (or elements) that describes the object.
+    * @see aria-labelledby
+    */
+   'aria-describedby'?: string
+   /**
+    * Identifies the element that provides a detailed, extended description for the object.
+    * @see aria-describedby.
+    */
+   'aria-details'?: string
+   /**
+    * Indicates that the element is perceivable but disabled, so it is not editable or otherwise operable.
+    * @see aria-hidden @see aria-readonly.
+    */
+   'aria-disabled'?: boolean | 'false' | 'true'
+   /**
+    * Indicates what functions can be performed when a dragged object is released on the drop target.
+    * @deprecated in ARIA 1.1
+    */
+   'aria-dropeffect'?: 'none' | 'copy' | 'execute' | 'link' | 'move' | 'popup'
+   /**
+    * Identifies the element that provides an error message for the object.
+    * @see aria-invalid @see aria-describedby.
+    */
+   'aria-errormessage'?: string
+   /** Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed. */
+   'aria-expanded'?: boolean | 'false' | 'true'
+   /**
+    * Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion,
+    * allows assistive technology to override the general default of reading in document source order.
+    */
+   'aria-flowto'?: string
+   /**
+    * Indicates an element's "grabbed" state in a drag-and-drop operation.
+    * @deprecated in ARIA 1.1
+    */
+   'aria-grabbed'?: boolean | 'false' | 'true'
+   /** Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element. */
 -  'aria-haspopup'?: boolean | 'false' | 'true' | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog'
++  'aria-haspopup'?:
++    | boolean
++    | 'false'
++    | 'true'
++    | 'menu'
++    | 'listbox'
++    | 'tree'
++    | 'grid'
++    | 'dialog'
+   /**
+    * Indicates whether the element is exposed to an accessibility API.
+    * @see aria-disabled.
+    */
+   'aria-hidden'?: boolean | 'false' | 'true'
+   /**
+    * Indicates the entered value does not conform to the format expected by the application.
+    * @see aria-errormessage.
+    */
+   'aria-invalid'?: boolean | 'false' | 'true' | 'grammar' | 'spelling'
+   /** Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element. */
+   'aria-keyshortcuts'?: string
+   /**
+    * Defines a string value that labels the current element.
+    * @see aria-labelledby.
+    */
+   'aria-label'?: string
+   /**
+    * Identifies the element (or elements) that labels the current element.
+    * @see aria-describedby.
+    */
+   'aria-labelledby'?: string
+   /** Defines the hierarchical level of an element within a structure. */
+   'aria-level'?: number
+   /** Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region. */
+   'aria-live'?: 'off' | 'assertive' | 'polite'
+   /** Indicates whether an element is modal when displayed. */
+   'aria-modal'?: boolean | 'false' | 'true'
+   /** Indicates whether a text box accepts multiple lines of input or only a single line. */
+   'aria-multiline'?: boolean | 'false' | 'true'
+   /** Indicates that the user may select more than one item from the current selectable descendants. */
+   'aria-multiselectable'?: boolean | 'false' | 'true'
+   /** Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous. */
+   'aria-orientation'?: 'horizontal' | 'vertical'
+   /**
+    * Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship
+    * between DOM elements where the DOM hierarchy cannot be used to represent the relationship.
+    * @see aria-controls.
+    */
+   'aria-owns'?: string
+   /**
+    * Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value.
+    * A hint could be a sample value or a brief description of the expected format.
+    */
+   'aria-placeholder'?: string
+   /**
+    * Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM.
+    * @see aria-setsize.
+    */
+   'aria-posinset'?: number
+   /**
+    * Indicates the current "pressed" state of toggle buttons.
+    * @see aria-checked @see aria-selected.
+    */
+   'aria-pressed'?: boolean | 'false' | 'mixed' | 'true'
+   /**
+    * Indicates that the element is not editable, but is otherwise operable.
+    * @see aria-disabled.
+    */
+   'aria-readonly'?: boolean | 'false' | 'true'
+   /**
+    * Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified.
+    * @see aria-atomic.
+    */
+   'aria-relevant'?: 'additions' | 'additions text' | 'all' | 'removals' | 'text'
+   /** Indicates that user input is required on the element before a form may be submitted. */
+   'aria-required'?: boolean | 'false' | 'true'
+   /** Defines a human-readable, author-localized description for the role of an element. */
+   'aria-roledescription'?: string
+   /**
+    * Defines the total number of rows in a table, grid, or treegrid.
+    * @see aria-rowindex.
+    */
+   'aria-rowcount'?: number
+   /**
+    * Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid.
+    * @see aria-rowcount @see aria-rowspan.
+    */
+   'aria-rowindex'?: number
+   /**
+    * Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid.
+    * @see aria-rowindex @see aria-colspan.
+    */
+   'aria-rowspan'?: number
+   /**
+    * Indicates the current "selected" state of various widgets.
+    * @see aria-checked @see aria-pressed.
+    */
+   'aria-selected'?: boolean | 'false' | 'true'
+   /**
+    * Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM.
+    * @see aria-posinset.
+    */
+   'aria-setsize'?: number
+   /** Indicates if items in a table or grid are sorted in ascending or descending order. */
+   'aria-sort'?: 'none' | 'ascending' | 'descending' | 'other'
+   /** Defines the maximum allowed value for a range widget. */
+   'aria-valuemax'?: number
+   /** Defines the minimum allowed value for a range widget. */
+   'aria-valuemin'?: number
+   /**
+    * Defines the current value for a range widget.
+    * @see aria-valuetext.
+    */
+   'aria-valuenow'?: number
+   /** Defines the human readable text alternative of aria-valuenow for a range widget. */
+   'aria-valuetext'?: string
+ }
 -export interface HTMLAttributes extends AriaAttributes{
 -
 -  domPropsInnerHTML?: string;
++export interface HTMLAttributes extends AriaAttributes {
++  domPropsInnerHTML?: string
  
- interface HTMLAttributes {
    class?: any
-   style?: string | Partial<CSSStyleDeclaration>
+   style?: string | CSSProperties
+   // Standard HTML Attributes
    accesskey?: string
-   contenteditable?: boolean
 -  contenteditable?: Booleanish | "inherit"
++  contenteditable?: Booleanish | 'inherit'
    contextmenu?: string
    dir?: string
-   disabled?: boolean
-   draggable?: boolean
+   draggable?: Booleanish
    hidden?: boolean
    id?: string
    lang?: string
-   spellcheck?: boolean
+   placeholder?: string
+   spellcheck?: Booleanish
    tabindex?: number
    title?: string
+   translate?: 'yes' | 'no'
+   // Unknown
+   radiogroup?: string // <command>, <menuitem>
  
+   // WAI-ARIA
    role?: string
 -  inputmode?: 'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search'
+   // RDFa Attributes
+   about?: string
+   datatype?: string
+   inlist?: any
+   prefix?: string
+   property?: string
+   resource?: string
+   typeof?: string
+   vocab?: string
+   // Non-standard Attributes
+   autocapitalize?: string
+   autocorrect?: string
+   autocave?: string
+   color?: string
+   itemprop?: string
+   itemscope?: boolean
+   itemtype?: string
+   itemid?: string
+   itemref?: string
+   results?: number
+   security?: string
+   unselectable?: 'on' | 'off'
+   // Living Standard
+   /**
+    * Hints at the type of data that might be entered by the user while editing the element or its contents
+    * @see https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-inputmode-attribute
+    */
++  inputmode?:
++    | 'none'
++    | 'text'
++    | 'tel'
++    | 'url'
++    | 'email'
++    | 'numeric'
++    | 'decimal'
++    | 'search'
+   /**
+    * Specify that a standard HTML element should behave like a defined custom built-in element
+    * @see https://html.spec.whatwg.org/multipage/custom-elements.html#attr-is
+    */
+   is?: string
  }
  
- interface AnchorHTMLAttributes extends HTMLAttributes {
export interface AnchorHTMLAttributes extends HTMLAttributes {
    download?: any
    href?: string
    hreflang?: string
@@@ -63,9 -317,10 +340,9 @@@ export interface AreaHTMLAttributes ext
    target?: string
  }
  
- interface AudioHTMLAttributes extends MediaHTMLAttributes {}
 -export interface AudioHTMLAttributes extends MediaHTMLAttributes {
 -}
++export interface AudioHTMLAttributes extends MediaHTMLAttributes {}
  
- interface BaseHTMLAttributes extends HTMLAttributes {
export interface BaseHTMLAttributes extends HTMLAttributes {
    href?: string
    target?: string
  }
@@@ -407,115 -688,286 +710,298 @@@ export interface VideoHTMLAttributes ex
    playsinline?: boolean
    poster?: string
    width?: number | string
+   disablePictureInPicture?: boolean
  }
  
- interface AllHTMLAttributes extends HTMLAttributes {
-   accept?: string
-   acceptcharset?: string
-   action?: boolean
+ export interface WebViewHTMLAttributes extends HTMLAttributes {
    allowfullscreen?: boolean
-   allowtransparency?: boolean
-   alt?: string
-   async?: boolean
-   autocomplete?: string
-   autofocus?: boolean
-   autoplay?: boolean
-   capture?: boolean // https://www.w3.org/tr/html-media-capture/#the-capture-attribute
-   cellpadding?: number | string
-   cellspacing?: number | string
-   challenge?: string
-   charset?: string
-   checked?: boolean
-   cite?: string
-   classid?: string
-   cols?: number
-   colspan?: number
-   content?: string
-   controls?: boolean
-   coord?: string
-   crossorigin?: string
-   data?: string
-   datetime?: string
-   default?: boolean
-   defer?: boolean
-   dirname?: string
-   disabled?: boolean
-   download?: any
-   enctype?: string
-   form?: string
-   formaction?: string
-   formenctype?: string
-   formmethod?: string
-   formnovalidate?: boolean
-   formtarget?: string
-   frameborder?: number | string
-   headers?: string
+   allowpopups?: boolean
+   autoFocus?: boolean
+   autosize?: boolean
+   blinkfeatures?: string
+   disableblinkfeatures?: string
+   disableguestresize?: boolean
+   disablewebsecurity?: boolean
+   guestinstance?: string
+   httpreferrer?: string
+   nodeintegration?: boolean
+   partition?: string
+   plugins?: boolean
+   preload?: string
+   src?: string
+   useragent?: string
+   webpreferences?: string
+ }
+ export interface SVGAttributes extends AriaAttributes {
 -
 -  domPropsInnerHTML?: string;
++  domPropsInnerHTML?: string
+   color?: string
    height?: number | string
-   high?: number
-   href?: string
-   hreflang?: string
-   htmlfor?: string
-   httpequiv?: string
-   integrity?: string
-   keyparams?: string
-   keytype?: string
-   kind?: string
-   label?: string
-   list?: string
-   loop?: boolean
-   low?: number
-   manifest?: string
-   marginheight?: number
-   marginwidth?: number
+   id?: string
+   lang?: string
    max?: number | string
-   maxlength?: number
    media?: string
-   mediagroup?: string
    method?: string
    min?: number | string
-   minlength?: number
-   multiple?: boolean
-   muted?: boolean
    name?: string
-   nonce?: string
-   novalidate?: boolean
-   open?: boolean
-   optimum?: number
-   pattern?: string
-   placeholder?: string
-   playsinline?: boolean
-   poster?: string
-   preload?: string
-   readonly?: boolean
-   rel?: string
-   required?: boolean
-   reversed?: boolean
-   rows?: number
-   rowspan?: number
-   sandbox?: string
-   scope?: string
-   scoped?: boolean
-   scrolling?: string
-   seamless?: boolean
-   selected?: boolean
-   shape?: string
-   size?: number
-   sizes?: string
-   span?: number
-   src?: string
-   srcdoc?: string
-   srclang?: string
-   srcset?: string
-   start?: number
-   step?: number | string
-   summary?: string
    target?: string
    type?: string
-   usemap?: string
-   value?: string | string[] | number
    width?: number | string
-   wmode?: string
-   wrap?: string
+   // Other HTML properties supported by SVG elements in browsers
+   role?: string
+   tabindex?: number
+   // SVG Specific attributes
+   'accent-height'?: number | string
+   accumulate?: 'none' | 'sum'
+   additive?: 'replace' | 'sum'
 -  'alignment-baseline'?: 'auto' | 'baseline' | 'before-edge' | 'text-before-edge' | 'middle' | 'central' | 'after-edge' | 'text-after-edge' | 'ideographic' | 'alphabetic' | 'hanging' | 'mathematical' | 'inherit'
++  'alignment-baseline'?:
++    | 'auto'
++    | 'baseline'
++    | 'before-edge'
++    | 'text-before-edge'
++    | 'middle'
++    | 'central'
++    | 'after-edge'
++    | 'text-after-edge'
++    | 'ideographic'
++    | 'alphabetic'
++    | 'hanging'
++    | 'mathematical'
++    | 'inherit'
+   allowReorder?: 'no' | 'yes'
+   alphabetic?: number | string
+   amplitude?: number | string
+   'arabic-form'?: 'initial' | 'medial' | 'terminal' | 'isolated'
+   ascent?: number | string
+   attributeName?: string
+   attributeType?: string
+   autoReverse?: number | string
+   azimuth?: number | string
+   baseFrequency?: number | string
+   'baseline-shift'?: number | string
+   baseProfile?: number | string
+   bbox?: number | string
+   begin?: number | string
+   bias?: number | string
+   by?: number | string
+   calcMode?: number | string
+   'cap-height'?: number | string
+   clip?: number | string
+   'clip-path'?: string
+   clipPathUnits?: number | string
+   'clip-rule'?: number | string
+   'color-interpolation'?: number | string
+   'color-interpolation-filters'?: 'auto' | 'sRGB' | 'linearRGB' | 'inherit'
+   'color-profile'?: number | string
+   'color-rendering'?: number | string
+   contentScriptType?: number | string
+   contentStyleType?: number | string
+   cursor?: number | string
+   cx?: number | string
+   cy?: number | string
+   d?: string
+   decelerate?: number | string
+   descent?: number | string
+   diffuseConstant?: number | string
+   direction?: number | string
+   display?: number | string
+   divisor?: number | string
+   'dominant-baseline'?: number | string
+   dur?: number | string
+   dx?: number | string
+   dy?: number | string
+   edgeMode?: number | string
+   elevation?: number | string
+   'enable-background'?: number | string
+   end?: number | string
+   exponent?: number | string
+   externalResourcesRequired?: number | string
+   fill?: string
+   'fill-opacity'?: number | string
+   'fill-rule'?: 'nonzero' | 'evenodd' | 'inherit'
+   filter?: string
+   filterRes?: number | string
+   filterUnits?: number | string
+   'flood-color'?: number | string
+   'flood-opacity'?: number | string
+   focusable?: number | string
+   'font-family'?: string
+   'font-size'?: number | string
+   'font-size-adjust'?: number | string
+   'font-stretch'?: number | string
+   'font-style'?: number | string
+   'font-variant'?: number | string
+   'font-weight'?: number | string
+   format?: number | string
+   from?: number | string
+   fx?: number | string
+   fy?: number | string
+   g1?: number | string
+   g2?: number | string
+   'glyph-name'?: number | string
+   'glyph-orientation-horizontal'?: number | string
+   'glyph-orientation-vertical'?: number | string
+   glyphRef?: number | string
+   gradientTransform?: string
+   gradientUnits?: string
+   hanging?: number | string
+   'horiz-adv-x'?: number | string
+   'horiz-origin-x'?: number | string
+   href?: string
+   ideographic?: number | string
+   'image-rendering'?: number | string
+   in2?: number | string
+   in?: string
+   intercept?: number | string
+   k1?: number | string
+   k2?: number | string
+   k3?: number | string
+   k4?: number | string
+   k?: number | string
+   kernelMatrix?: number | string
+   kernelUnitLength?: number | string
+   kerning?: number | string
+   keyPoints?: number | string
+   keySplines?: number | string
+   keyTimes?: number | string
+   lengthAdjust?: number | string
+   'letter-spacing'?: number | string
+   'lighting-color'?: number | string
+   limitingConeAngle?: number | string
+   local?: number | string
+   'marker-end'?: string
+   markerHeight?: number | string
+   'marker-mid'?: string
+   'marker-start'?: string
+   markerUnits?: number | string
+   markerWidth?: number | string
+   mask?: string
+   maskContentUnits?: number | string
+   maskUnits?: number | string
+   mathematical?: number | string
+   mode?: number | string
+   numOctaves?: number | string
+   offset?: number | string
+   opacity?: number | string
+   operator?: number | string
+   order?: number | string
+   orient?: number | string
+   orientation?: number | string
+   origin?: number | string
+   overflow?: number | string
+   'overline-position'?: number | string
+   'overline-thickness'?: number | string
+   'paint-order'?: number | string
+   'panose-1'?: number | string
+   pathLength?: number | string
+   patternContentUnits?: string
+   patternTransform?: number | string
+   patternUnits?: string
+   'pointer-events'?: number | string
+   points?: string
+   pointsAtX?: number | string
+   pointsAtY?: number | string
+   pointsAtZ?: number | string
+   preserveAlpha?: number | string
+   preserveAspectRatio?: string
+   primitiveUnits?: number | string
+   r?: number | string
+   radius?: number | string
+   refX?: number | string
+   refY?: number | string
+   renderingIntent?: number | string
+   repeatCount?: number | string
+   repeatDur?: number | string
+   requiredExtensions?: number | string
+   requiredFeatures?: number | string
+   restart?: number | string
+   result?: string
+   rotate?: number | string
+   rx?: number | string
+   ry?: number | string
+   scale?: number | string
+   seed?: number | string
+   'shape-rendering'?: number | string
+   slope?: number | string
+   spacing?: number | string
+   specularConstant?: number | string
+   specularExponent?: number | string
+   speed?: number | string
+   spreadMethod?: string
+   startOffset?: number | string
+   stdDeviation?: number | string
+   stemh?: number | string
+   stemv?: number | string
+   stitchTiles?: number | string
+   'stop-color'?: string
+   'stop-opacity'?: number | string
+   'strikethrough-position'?: number | string
+   'strikethrough-thickness'?: number | string
+   string?: number | string
+   stroke?: string
+   'stroke-dasharray'?: string | number
+   'stroke-dashoffset'?: string | number
+   'stroke-linecap'?: 'butt' | 'round' | 'square' | 'inherit'
+   'stroke-linejoin'?: 'miter' | 'round' | 'bevel' | 'inherit'
+   'stroke-miterlimit'?: number | string
+   'stroke-opacity'?: number | string
+   'stroke-width'?: number | string
+   surfaceScale?: number | string
+   systemLanguage?: number | string
+   tableValues?: number | string
+   targetX?: number | string
+   targetY?: number | string
+   'text-anchor'?: string
+   'text-decoration'?: number | string
+   textLength?: number | string
+   'text-rendering'?: number | string
+   to?: number | string
+   transform?: string
+   u1?: number | string
+   u2?: number | string
+   'underline-position'?: number | string
+   'underline-thickness'?: number | string
+   unicode?: number | string
+   'unicode-bidi'?: number | string
+   'unicode-range'?: number | string
+   'unitsPer-em'?: number | string
+   'v-alphabetic'?: number | string
+   values?: string
+   'vector-effect'?: number | string
+   version?: string
+   'vert-adv-y'?: number | string
+   'vert-origin-x'?: number | string
+   'vert-origin-y'?: number | string
+   'v-hanging'?: number | string
+   'v-ideographic'?: number | string
+   viewBox?: string
+   viewTarget?: number | string
+   visibility?: number | string
+   'v-mathematical'?: number | string
+   widths?: number | string
+   'word-spacing'?: number | string
+   'writing-mode'?: number | string
+   x1?: number | string
+   x2?: number | string
+   x?: number | string
+   xChannelSelector?: string
+   'x-height'?: number | string
 -  'xlinkActuate'?: string
 -  'xlinkArcrole'?: string
 -  'xlinkHref'?: string
 -  'xlinkRole'?: string
 -  'xlinkShow'?: string
 -  'xlinkTitle'?: string
 -  'xlinkType'?: string
++  xlinkActuate?: string
++  xlinkArcrole?: string
++  xlinkHref?: string
++  xlinkRole?: string
++  xlinkShow?: string
++  xlinkTitle?: string
++  xlinkType?: string
+   y1?: number | string
+   y2?: number | string
+   y?: number | string
+   yChannelSelector?: string
+   z?: number | string
+   zoomAndPan?: string
  }
  
  interface IntrinsicElementAttributes {
index 0000000000000000000000000000000000000000,d17c0dd11d63721d34e44858f6eb97bb48b63a86..958e470805c5fc7a6d19bda02a6b8901d3aa9095
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,97 +1,95 @@@
 -    return value === ''
 -      ? ` ${attrKey}`
 -      : ` ${attrKey}="${escapeHtml(value)}"`
+ import { escapeHtml, stringifyStyle } from '@vue/shared'
+ import {
+   normalizeClass,
+   normalizeStyle,
+   propsToAttrMap,
+   isString,
+   isOn,
+   isSSRSafeAttrName,
+   isBooleanAttr,
+   makeMap
+ } from '@vue/shared'
+ const shouldIgnoreProp = makeMap(`key,ref,innerHTML,textContent`)
+ export function ssrRenderAttrs(
+   props: Record<string, unknown>,
+   tag?: string
+ ): string {
+   let ret = ''
+   for (const key in props) {
+     if (
+       shouldIgnoreProp(key) ||
+       isOn(key) ||
+       (tag === 'textarea' && key === 'value')
+     ) {
+       continue
+     }
+     const value = props[key]
+     if (key === 'class') {
+       ret += ` class="${ssrRenderClass(value)}"`
+     } else if (key === 'style') {
+       ret += ` style="${ssrRenderStyle(value)}"`
+     } else {
+       ret += ssrRenderDynamicAttr(key, value, tag)
+     }
+   }
+   return ret
+ }
+ // render an attr with dynamic (unknown) key.
+ export function ssrRenderDynamicAttr(
+   key: string,
+   value: unknown,
+   tag?: string
+ ): string {
+   if (!isRenderableValue(value)) {
+     return ``
+   }
+   const attrKey =
+     tag && tag.indexOf('-') > 0
+       ? key // preserve raw name on custom elements
+       : propsToAttrMap[key] || key.toLowerCase()
+   if (isBooleanAttr(attrKey)) {
+     return value === false ? `` : ` ${attrKey}`
+   } else if (isSSRSafeAttrName(attrKey)) {
++    return value === '' ? ` ${attrKey}` : ` ${attrKey}="${escapeHtml(value)}"`
+   } else {
+     console.warn(
+       `[@vue/server-renderer] Skipped rendering unsafe attribute name: ${attrKey}`
+     )
+     return ``
+   }
+ }
+ // Render a v-bind attr with static key. The key is pre-processed at compile
+ // time and we only need to check and escape value.
+ export function ssrRenderAttr(key: string, value: unknown): string {
+   if (!isRenderableValue(value)) {
+     return ``
+   }
+   return ` ${key}="${escapeHtml(value)}"`
+ }
+ function isRenderableValue(value: unknown): boolean {
+   if (value == null) {
+     return false
+   }
+   const type = typeof value
+   return type === 'string' || type === 'number' || type === 'boolean'
+ }
+ export function ssrRenderClass(raw: unknown): string {
+   return escapeHtml(normalizeClass(raw))
+ }
+ export function ssrRenderStyle(raw: unknown): string {
+   if (!raw) {
+     return ''
+   }
+   if (isString(raw)) {
+     return escapeHtml(raw)
+   }
+   const styles = normalizeStyle(raw)
+   return escapeHtml(stringifyStyle(styles))
+ }