diff --git a/1.Vue/flow/compiler.js b/1.Vue/flow/compiler.js deleted file mode 100644 index ad09a2e..0000000 --- a/1.Vue/flow/compiler.js +++ /dev/null @@ -1,227 +0,0 @@ -declare type CompilerOptions = { - warn?: Function; // allow customizing warning in different environments; e.g. node - modules?: Array; // platform specific modules; e.g. style; class - directives?: { [key: string]: Function }; // platform specific directives - staticKeys?: string; // a list of AST properties to be considered static; for optimization - isUnaryTag?: (tag: string) => ?boolean; // check if a tag is unary for the platform - canBeLeftOpenTag?: (tag: string) => ?boolean; // check if a tag can be left opened - isReservedTag?: (tag: string) => ?boolean; // check if a tag is a native for the platform - preserveWhitespace?: boolean; // preserve whitespace between elements? (Deprecated) - whitespace?: 'preserve' | 'condense'; // whitespace handling strategy - optimize?: boolean; // optimize static content? - - // web specific - mustUseProp?: (tag: string, type: ?string, name: string) => boolean; // check if an attribute should be bound as a property - isPreTag?: (attr: string) => ?boolean; // check if a tag needs to preserve whitespace - getTagNamespace?: (tag: string) => ?string; // check the namespace for a tag - expectHTML?: boolean; // only false for non-web builds - isFromDOM?: boolean; - shouldDecodeTags?: boolean; - shouldDecodeNewlines?: boolean; - shouldDecodeNewlinesForHref?: boolean; - outputSourceRange?: boolean; - - // runtime user-configurable - delimiters?: [string, string]; // template delimiters - comments?: boolean; // preserve comments in template - - // for ssr optimization compiler - scopeId?: string; -}; - -declare type WarningMessage = { - msg: string; - start?: number; - end?: number; -}; - -declare type CompiledResult = { - ast: ?ASTElement; - render: string; - staticRenderFns: Array; - stringRenderFns?: Array; - errors?: Array; - tips?: Array; -}; - -declare type ModuleOptions = { - // transform an AST node before any attributes are processed - // returning an ASTElement from pre/transforms replaces the element - preTransformNode: (el: ASTElement) => ?ASTElement; - // transform an AST node after built-ins like v-if, v-for are processed - transformNode: (el: ASTElement) => ?ASTElement; - // transform an AST node after its children have been processed - // cannot return replacement in postTransform because tree is already finalized - postTransformNode: (el: ASTElement) => void; - genData: (el: ASTElement) => string; // generate extra data string for an element - transformCode?: (el: ASTElement, code: string) => string; // further transform generated code for an element - staticKeys?: Array; // AST properties to be considered static -}; - -declare type ASTModifiers = { [key: string]: boolean }; -declare type ASTIfCondition = { exp: ?string; block: ASTElement }; -declare type ASTIfConditions = Array; - -declare type ASTAttr = { - name: string; - value: any; - dynamic?: boolean; - start?: number; - end?: number -}; - -declare type ASTElementHandler = { - value: string; - params?: Array; - modifiers: ?ASTModifiers; - dynamic?: boolean; - start?: number; - end?: number; -}; - -declare type ASTElementHandlers = { - [key: string]: ASTElementHandler | Array; -}; - -declare type ASTDirective = { - name: string; - rawName: string; - value: string; - arg: ?string; - isDynamicArg: boolean; - modifiers: ?ASTModifiers; - start?: number; - end?: number; -}; - -declare type ASTNode = ASTElement | ASTText | ASTExpression; - -declare type ASTElement = { - type: 1; - tag: string; - attrsList: Array; - attrsMap: { [key: string]: any }; - rawAttrsMap: { [key: string]: ASTAttr }; - parent: ASTElement | void; - children: Array; - - start?: number; - end?: number; - - processed?: true; - - static?: boolean; - staticRoot?: boolean; - staticInFor?: boolean; - staticProcessed?: boolean; - hasBindings?: boolean; - - text?: string; - attrs?: Array; - dynamicAttrs?: Array; - props?: Array; - plain?: boolean; - pre?: true; - ns?: string; - - component?: string; - inlineTemplate?: true; - transitionMode?: string | null; - slotName?: ?string; - slotTarget?: ?string; - slotTargetDynamic?: boolean; - slotScope?: ?string; - scopedSlots?: { [name: string]: ASTElement }; - - ref?: string; - refInFor?: boolean; - - if?: string; - ifProcessed?: boolean; - elseif?: string; - else?: true; - ifConditions?: ASTIfConditions; - - for?: string; - forProcessed?: boolean; - key?: string; - alias?: string; - iterator1?: string; - iterator2?: string; - - staticClass?: string; - classBinding?: string; - staticStyle?: string; - styleBinding?: string; - events?: ASTElementHandlers; - nativeEvents?: ASTElementHandlers; - - transition?: string | true; - transitionOnAppear?: boolean; - - model?: { - value: string; - callback: string; - expression: string; - }; - - directives?: Array; - - forbidden?: true; - once?: true; - onceProcessed?: boolean; - wrapData?: (code: string) => string; - wrapListeners?: (code: string) => string; - - // 2.4 ssr optimization - ssrOptimizability?: number; - - // weex specific - appendAsTree?: boolean; -}; - -declare type ASTExpression = { - type: 2; - expression: string; - text: string; - tokens: Array; - static?: boolean; - // 2.4 ssr optimization - ssrOptimizability?: number; - start?: number; - end?: number; -}; - -declare type ASTText = { - type: 3; - text: string; - static?: boolean; - isComment?: boolean; - // 2.4 ssr optimization - ssrOptimizability?: number; - start?: number; - end?: number; -}; - -// SFC-parser related declarations - -// an object format describing a single-file component -declare type SFCDescriptor = { - template: ?SFCBlock; - script: ?SFCBlock; - styles: Array; - customBlocks: Array; - errors: Array; -} - -declare type SFCBlock = { - type: string; - content: string; - attrs: {[attribute:string]: string}; - start?: number; - end?: number; - lang?: string; - src?: string; - scoped?: boolean; - module?: string | boolean; -}; diff --git a/1.Vue/flow/component.js b/1.Vue/flow/component.js deleted file mode 100644 index 0dc67a4..0000000 --- a/1.Vue/flow/component.js +++ /dev/null @@ -1,148 +0,0 @@ -import type { Config } from '../src/core/config' -import type VNode from '../src/core/vdom/vnode' -import type Watcher from '../src/core/observer/watcher' - -declare interface Component { - // constructor information - static cid: number; - static options: Object; - // extend - static extend: (options: Object) => Function; - static superOptions: Object; - static extendOptions: Object; - static sealedOptions: Object; - static super: Class; - // assets - static directive: (id: string, def?: Function | Object) => Function | Object | void; - static component: (id: string, def?: Class | Object) => Class; - static filter: (id: string, def?: Function) => Function | void; - // functional context constructor - static FunctionalRenderContext: Function; - - // public properties - $el: any; // so that we can attach __vue__ to it - $data: Object; - $props: Object; - $options: ComponentOptions; - $parent: Component | void; - $root: Component; - $children: Array; - $refs: { [key: string]: Component | Element | Array | void }; - $slots: { [key: string]: Array }; - $scopedSlots: { [key: string]: () => VNodeChildren }; - $vnode: VNode; // the placeholder node for the component in parent's render tree - $attrs: { [key: string] : string }; - $listeners: { [key: string]: Function | Array }; - $isServer: boolean; - - // public methods - $mount: (el?: Element | string, hydrating?: boolean) => Component; - $forceUpdate: () => void; - $destroy: () => void; - $set: (target: Object | Array, key: string | number, val: T) => T; - $delete: (target: Object | Array, key: string | number) => void; - $watch: (expOrFn: string | Function, cb: Function, options?: Object) => Function; - $on: (event: string | Array, fn: Function) => Component; - $once: (event: string, fn: Function) => Component; - $off: (event?: string | Array, fn?: Function) => Component; - $emit: (event: string, ...args: Array) => Component; - $nextTick: (fn: Function) => void | Promise<*>; - $createElement: (tag?: string | Component, data?: Object, children?: VNodeChildren) => VNode; - - // private properties - _uid: number | string; - _name: string; // this only exists in dev mode - _isVue: true; - _self: Component; - _renderProxy: Component; - _renderContext: ?Component; - _watcher: Watcher; - _watchers: Array; - _computedWatchers: { [key: string]: Watcher }; - _data: Object; - _props: Object; - _events: Object; - _inactive: boolean | null; - _directInactive: boolean; - _isMounted: boolean; - _isDestroyed: boolean; - _isBeingDestroyed: boolean; - _vnode: ?VNode; // self root node - _staticTrees: ?Array; // v-once cached trees - _hasHookEvent: boolean; - _provided: ?Object; - // _virtualComponents?: { [key: string]: Component }; - - // private methods - - // lifecycle - _init: Function; - _mount: (el?: Element | void, hydrating?: boolean) => Component; - _update: (vnode: VNode, hydrating?: boolean) => void; - - // rendering - _render: () => VNode; - - __patch__: ( - a: Element | VNode | void, - b: VNode, - hydrating?: boolean, - removeOnly?: boolean, - parentElm?: any, - refElm?: any - ) => any; - - // createElement - - // _c is internal that accepts `normalizationType` optimization hint - _c: ( - vnode?: VNode, - data?: VNodeData, - children?: VNodeChildren, - normalizationType?: number - ) => VNode | void; - - // renderStatic - _m: (index: number, isInFor?: boolean) => VNode | VNodeChildren; - // markOnce - _o: (vnode: VNode | Array, index: number, key: string) => VNode | VNodeChildren; - // toString - _s: (value: mixed) => string; - // text to VNode - _v: (value: string | number) => VNode; - // toNumber - _n: (value: string) => number | string; - // empty vnode - _e: () => VNode; - // loose equal - _q: (a: mixed, b: mixed) => boolean; - // loose indexOf - _i: (arr: Array, val: mixed) => number; - // resolveFilter - _f: (id: string) => Function; - // renderList - _l: (val: mixed, render: Function) => ?Array; - // renderSlot - _t: (name: string, fallback: ?Array, props: ?Object) => ?Array; - // apply v-bind object - _b: (data: any, tag: string, value: any, asProp: boolean, isSync?: boolean) => VNodeData; - // apply v-on object - _g: (data: any, value: any) => VNodeData; - // check custom keyCode - _k: (eventKeyCode: number, key: string, builtInAlias?: number | Array, eventKeyName?: string) => ?boolean; - // resolve scoped slots - _u: (scopedSlots: ScopedSlotsData, res?: Object) => { [key: string]: Function }; - - // SSR specific - _ssrNode: Function; - _ssrList: Function; - _ssrEscape: Function; - _ssrAttr: Function; - _ssrAttrs: Function; - _ssrDOMProps: Function; - _ssrClass: Function; - _ssrStyle: Function; - - // allow dynamic method registration - [key: string]: any -}; diff --git a/1.Vue/flow/global-api.js b/1.Vue/flow/global-api.js deleted file mode 100644 index 0ce54fd..0000000 --- a/1.Vue/flow/global-api.js +++ /dev/null @@ -1,23 +0,0 @@ -declare interface GlobalAPI { - cid: number; - options: Object; - config: Config; - util: Object; - - extend: (options: Object) => Function; - set: (target: Object | Array, key: string | number, value: T) => T; - delete: (target: Object| Array, key: string | number) => void; - nextTick: (fn: Function, context?: Object) => void | Promise<*>; - use: (plugin: Function | Object) => GlobalAPI; - mixin: (mixin: Object) => GlobalAPI; - compile: (template: string) => { render: Function, staticRenderFns: Array }; - - directive: (id: string, def?: Function | Object) => Function | Object | void; - component: (id: string, def?: Class | Object) => Class; - filter: (id: string, def?: Function) => Function | void; - - observable: (value: T) => T; - - // allow dynamic method registration - [key: string]: any -}; diff --git a/1.Vue/flow/modules.js b/1.Vue/flow/modules.js deleted file mode 100644 index a660e9c..0000000 --- a/1.Vue/flow/modules.js +++ /dev/null @@ -1,44 +0,0 @@ -declare module 'he' { - declare function escape(html: string): string; - declare function decode(html: string): string; -} - -declare module 'source-map' { - declare class SourceMapGenerator { - setSourceContent(filename: string, content: string): void; - addMapping(mapping: Object): void; - toString(): string; - } - declare class SourceMapConsumer { - constructor (map: Object): void; - originalPositionFor(position: { line: number; column: number; }): { - source: ?string; - line: ?number; - column: ?number; - }; - } -} - -declare module 'lru-cache' { - declare var exports: { - (): any - } -} - -declare module 'de-indent' { - declare var exports: { - (input: string): string - } -} - -declare module 'serialize-javascript' { - declare var exports: { - (input: string, options: { isJSON: boolean }): string - } -} - -declare module 'lodash.template' { - declare var exports: { - (input: string, options: { interpolate: RegExp, escape: RegExp }): Function - } -} diff --git a/1.Vue/flow/options.js b/1.Vue/flow/options.js deleted file mode 100644 index 09bd93f..0000000 --- a/1.Vue/flow/options.js +++ /dev/null @@ -1,90 +0,0 @@ -declare type InternalComponentOptions = { - _isComponent: true; - parent: Component; - _parentVnode: VNode; - render?: Function; - staticRenderFns?: Array -}; - -type InjectKey = string | Symbol; - -declare type ComponentOptions = { - componentId?: string; - - // data - data: Object | Function | void; - props?: { [key: string]: PropOptions }; - propsData?: ?Object; - computed?: { - [key: string]: Function | { - get?: Function; - set?: Function; - cache?: boolean - } - }; - methods?: { [key: string]: Function }; - watch?: { [key: string]: Function | string }; - - // DOM - el?: string | Element; - template?: string; - render: (h: () => VNode) => VNode; - renderError?: (h: () => VNode, err: Error) => VNode; - staticRenderFns?: Array<() => VNode>; - - // lifecycle - beforeCreate?: Function; - created?: Function; - beforeMount?: Function; - mounted?: Function; - beforeUpdate?: Function; - updated?: Function; - activated?: Function; - deactivated?: Function; - beforeDestroy?: Function; - destroyed?: Function; - errorCaptured?: () => boolean | void; - serverPrefetch?: Function; - - // assets - directives?: { [key: string]: Object }; - components?: { [key: string]: Class }; - transitions?: { [key: string]: Object }; - filters?: { [key: string]: Function }; - - // context - provide?: { [key: string | Symbol]: any } | () => { [key: string | Symbol]: any }; - inject?: { [key: string]: InjectKey | { from?: InjectKey, default?: any }} | Array; - - // component v-model customization - model?: { - prop?: string; - event?: string; - }; - - // misc - parent?: Component; - mixins?: Array; - name?: string; - extends?: Class | Object; - delimiters?: [string, string]; - comments?: boolean; - inheritAttrs?: boolean; - - // private - _isComponent?: true; - _propKeys?: Array; - _parentVnode?: VNode; - _parentListeners?: ?Object; - _renderChildren?: ?Array; - _componentTag: ?string; - _scopeId: ?string; - _base: Class; -}; - -declare type PropOptions = { - type: Function | Array | null; - default: any; - required: ?boolean; - validator: ?Function; -} diff --git a/1.Vue/flow/ssr.js b/1.Vue/flow/ssr.js deleted file mode 100644 index d6a9459..0000000 --- a/1.Vue/flow/ssr.js +++ /dev/null @@ -1,21 +0,0 @@ -declare type ComponentWithCacheContext = { - type: 'ComponentWithCache'; - bufferIndex: number; - buffer: Array; - key: string; -}; - -declare type ElementContext = { - type: 'Element'; - children: Array; - rendered: number; - endTag: string; - total: number; -}; - -declare type ComponentContext = { - type: 'Component'; - prevActive: Component; -}; - -declare type RenderState = ComponentContext | ComponentWithCacheContext | ElementContext; diff --git a/1.Vue/flow/vnode.js b/1.Vue/flow/vnode.js deleted file mode 100644 index c9f3b38..0000000 --- a/1.Vue/flow/vnode.js +++ /dev/null @@ -1,79 +0,0 @@ -declare type VNodeChildren = Array | string; - -declare type VNodeComponentOptions = { - Ctor: Class; - propsData: ?Object; - listeners: ?Object; - children: ?Array; - tag?: string; -}; - -declare type MountedComponentVNode = { - context: Component; - componentOptions: VNodeComponentOptions; - componentInstance: Component; - parent: VNode; - data: VNodeData; -}; - -// interface for vnodes in update modules -declare type VNodeWithData = { - tag: string; - data: VNodeData; - children: ?Array; - text: void; - elm: any; - ns: string | void; - context: Component; - key: string | number | void; - parent?: VNodeWithData; - componentOptions?: VNodeComponentOptions; - componentInstance?: Component; - isRootInsert: boolean; -}; - -declare interface VNodeData { - key?: string | number; - slot?: string; - ref?: string; - is?: string; - pre?: boolean; - tag?: string; - staticClass?: string; - class?: any; - staticStyle?: { [key: string]: any }; - style?: string | Array | Object; - normalizedStyle?: Object; - props?: { [key: string]: any }; - attrs?: { [key: string]: string }; - domProps?: { [key: string]: any }; - hook?: { [key: string]: Function }; - on?: ?{ [key: string]: Function | Array }; - nativeOn?: { [key: string]: Function | Array }; - transition?: Object; - show?: boolean; // marker for v-show - inlineTemplate?: { - render: Function; - staticRenderFns: Array; - }; - directives?: Array; - keepAlive?: boolean; - scopedSlots?: { [key: string]: Function }; - model?: { - value: any; - callback: Function; - }; -}; - -declare type VNodeDirective = { - name: string; - rawName: string; - value?: any; - oldValue?: any; - arg?: string; - oldArg?: string; - modifiers?: ASTModifiers; - def?: Object; -}; - -declare type ScopedSlotsData = Array<{ key: string, fn: Function } | ScopedSlotsData>; diff --git a/1.Vue/flow/weex.js b/1.Vue/flow/weex.js deleted file mode 100644 index 2834313..0000000 --- a/1.Vue/flow/weex.js +++ /dev/null @@ -1,122 +0,0 @@ -// global flag to be compiled away -declare var __WEEX__: boolean; - -// global object in Weex -declare var WXEnvironment: WeexEnvironment; - -declare type Weex = { - config: WeexConfigAPI; - document: WeexDocument; - requireModule: (name: string) => Object | void; - supports: (condition: string) => boolean | void; - isRegisteredModule: (name: string, method?: string) => boolean; - isRegisteredComponent: (name: string) => boolean; -}; - -declare type WeexConfigAPI = { - bundleUrl: string; // === weex.document.URL - bundleType: string; - env: WeexEnvironment; // === WXEnvironment -}; - -declare type WeexEnvironment = { - platform: string; // could be "Web", "iOS", "Android" - weexVersion: string; // the version of WeexSDK - - osName: string; // could be "iOS", "Android" or others - osVersion: string; - appName: string; // mobile app name or browser name - appVersion: string; - - // informations of current running device - deviceModel: string; // phone device model - deviceWidth: number; - deviceHeight: number; - scale: number; - - // only available on the web - userAgent?: string; - dpr?: number; - rem?: number; -}; - -declare interface WeexDocument { - id: string; - URL: string; - taskCenter: WeexTaskCenter; - - open: () => void; - close: () => void; - createElement: (tagName: string, props?: Object) => WeexElement; - createComment: (text: string) => Object; - fireEvent: (type: string) => void; - destroy: () => void; -}; - -declare interface WeexTaskCenter { - instanceId: string; - callbackManager: Object; - send: (type: string, params: Object, args: Array, options?: Object) => void; - registerHook: (componentId: string, type: string, hook: string, fn: Function) => void; - updateData: (componentId: string, data: Object | void, callback?: Function) => void; -}; - -declare interface WeexElement { - nodeType: number; - nodeId: string; - type: string; - ref: string; - text?: string; - - parentNode: WeexElement | void; - children: Array; - previousSibling: WeexElement | void; - nextSibling: WeexElement | void; - - appendChild: (node: WeexElement) => void; - removeChild: (node: WeexElement, preserved?: boolean) => void; - insertBefore: (node: WeexElement, before: WeexElement) => void; - insertAfter: (node: WeexElement, after: WeexElement) => void; - setAttr: (key: string, value: any, silent?: boolean) => void; - setAttrs: (attrs: Object, silent?: boolean) => void; - setStyle: (key: string, value: any, silent?: boolean) => void; - setStyles: (attrs: Object, silent?: boolean) => void; - addEvent: (type: string, handler: Function, args?: Array) => void; - removeEvent: (type: string) => void; - fireEvent: (type: string) => void; - destroy: () => void; -}; - -declare type WeexInstanceOption = { - instanceId: string; - config: WeexConfigAPI; - document: WeexDocument; - Vue?: GlobalAPI; - app?: Component; - data?: Object; -}; - -declare type WeexRuntimeContext = { - weex: Weex; - service: Object; - BroadcastChannel?: Function; -}; - -declare type WeexInstanceContext = { - Vue: GlobalAPI; - - // DEPRECATED - setTimeout?: Function; - clearTimeout?: Function; - setInterval?: Function; - clearInterval?: Function; -}; - -declare type WeexCompilerOptions = CompilerOptions & { - // whether to compile special template for - recyclable?: boolean; -}; - -declare type WeexCompiledResult = CompiledResult & { - '@render'?: string; -}; diff --git a/1.Vue/src/compiler/codeframe.js b/1.Vue/src/compiler/codeframe.js deleted file mode 100644 index 513d318..0000000 --- a/1.Vue/src/compiler/codeframe.js +++ /dev/null @@ -1,50 +0,0 @@ -/* @flow */ - -const range = 2 - -export function generateCodeFrame ( - source: string, - start: number = 0, - end: number = source.length -): string { - const lines = source.split(/\r?\n/) - let count = 0 - const res = [] - for (let i = 0; i < lines.length; i++) { - count += lines[i].length + 1 - if (count >= start) { - for (let j = i - range; j <= i + range || end > count; j++) { - if (j < 0 || j >= lines.length) continue - res.push(`${j + 1}${repeat(` `, 3 - String(j + 1).length)}| ${lines[j]}`) - const lineLength = lines[j].length - if (j === i) { - // push underline - const pad = start - (count - lineLength) + 1 - const length = end > count ? lineLength - pad : end - start - res.push(` | ` + repeat(` `, pad) + repeat(`^`, length)) - } else if (j > i) { - if (end > count) { - const length = Math.min(end - count, lineLength) - res.push(` | ` + repeat(`^`, length)) - } - count += lineLength + 1 - } - } - break - } - } - return res.join('\n') -} - -function repeat (str, n) { - let result = '' - if (n > 0) { - while (true) { // eslint-disable-line - if (n & 1) result += str - n >>>= 1 - if (n <= 0) break - str += str - } - } - return result -} diff --git a/1.Vue/src/compiler/codegen/events.js b/1.Vue/src/compiler/codegen/events.js deleted file mode 100644 index 44657e3..0000000 --- a/1.Vue/src/compiler/codegen/events.js +++ /dev/null @@ -1,190 +0,0 @@ -/* @flow */ - -const fnExpRE = /^([\w$_]+|\([^)]*?\))\s*=>|^function\s*(?:[\w$]+)?\s*\(/ -const fnInvokeRE = /\([^)]*?\);*$/ -const simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/ - -// KeyboardEvent.keyCode aliases -const keyCodes: { [key: string]: number | Array } = { - esc: 27, - tab: 9, - enter: 13, - space: 32, - up: 38, - left: 37, - right: 39, - down: 40, - 'delete': [8, 46] -} - -// KeyboardEvent.key aliases -const keyNames: { [key: string]: string | Array } = { - // #7880: IE11 and Edge use `Esc` for Escape key name. - esc: ['Esc', 'Escape'], - tab: 'Tab', - enter: 'Enter', - // #9112: IE11 uses `Spacebar` for Space key name. - space: [' ', 'Spacebar'], - // #7806: IE11 uses key names without `Arrow` prefix for arrow keys. - up: ['Up', 'ArrowUp'], - left: ['Left', 'ArrowLeft'], - right: ['Right', 'ArrowRight'], - down: ['Down', 'ArrowDown'], - // #9112: IE11 uses `Del` for Delete key name. - 'delete': ['Backspace', 'Delete', 'Del'] -} - -// #4868: modifiers that prevent the execution of the listener -// need to explicitly return null so that we can determine whether to remove -// the listener for .once -const genGuard = condition => `if(${condition})return null;` - -const modifierCode: { [key: string]: string } = { - stop: '$event.stopPropagation();', - prevent: '$event.preventDefault();', - self: genGuard(`$event.target !== $event.currentTarget`), - ctrl: genGuard(`!$event.ctrlKey`), - shift: genGuard(`!$event.shiftKey`), - alt: genGuard(`!$event.altKey`), - meta: genGuard(`!$event.metaKey`), - left: genGuard(`'button' in $event && $event.button !== 0`), - middle: genGuard(`'button' in $event && $event.button !== 1`), - right: genGuard(`'button' in $event && $event.button !== 2`) -} - -export function genHandlers ( - events: ASTElementHandlers, - isNative: boolean -): string { - const prefix = isNative ? 'nativeOn:' : 'on:' - let staticHandlers = `` - let dynamicHandlers = `` - for (const name in events) { - const handlerCode = genHandler(events[name]) - if (events[name] && events[name].dynamic) { - dynamicHandlers += `${name},${handlerCode},` - } else { - staticHandlers += `"${name}":${handlerCode},` - } - } - staticHandlers = `{${staticHandlers.slice(0, -1)}}` - if (dynamicHandlers) { - return prefix + `_d(${staticHandlers},[${dynamicHandlers.slice(0, -1)}])` - } else { - return prefix + staticHandlers - } -} - -// Generate handler code with binding params on Weex -/* istanbul ignore next */ -function genWeexHandler (params: Array, handlerCode: string) { - let innerHandlerCode = handlerCode - const exps = params.filter(exp => simplePathRE.test(exp) && exp !== '$event') - const bindings = exps.map(exp => ({ '@binding': exp })) - const args = exps.map((exp, i) => { - const key = `$_${i + 1}` - innerHandlerCode = innerHandlerCode.replace(exp, key) - return key - }) - args.push('$event') - return '{\n' + - `handler:function(${args.join(',')}){${innerHandlerCode}},\n` + - `params:${JSON.stringify(bindings)}\n` + - '}' -} - -function genHandler (handler: ASTElementHandler | Array): string { - if (!handler) { - return 'function(){}' - } - - if (Array.isArray(handler)) { - return `[${handler.map(handler => genHandler(handler)).join(',')}]` - } - - const isMethodPath = simplePathRE.test(handler.value) - const isFunctionExpression = fnExpRE.test(handler.value) - const isFunctionInvocation = simplePathRE.test(handler.value.replace(fnInvokeRE, '')) - - if (!handler.modifiers) { - if (isMethodPath || isFunctionExpression) { - return handler.value - } - /* istanbul ignore if */ - if (__WEEX__ && handler.params) { - return genWeexHandler(handler.params, handler.value) - } - return `function($event){${ - isFunctionInvocation ? `return ${handler.value}` : handler.value - }}` // inline statement - } else { - let code = '' - let genModifierCode = '' - const keys = [] - for (const key in handler.modifiers) { - if (modifierCode[key]) { - genModifierCode += modifierCode[key] - // left/right - if (keyCodes[key]) { - keys.push(key) - } - } else if (key === 'exact') { - const modifiers: ASTModifiers = (handler.modifiers: any) - genModifierCode += genGuard( - ['ctrl', 'shift', 'alt', 'meta'] - .filter(keyModifier => !modifiers[keyModifier]) - .map(keyModifier => `$event.${keyModifier}Key`) - .join('||') - ) - } else { - keys.push(key) - } - } - if (keys.length) { - code += genKeyFilter(keys) - } - // Make sure modifiers like prevent and stop get executed after key filtering - if (genModifierCode) { - code += genModifierCode - } - const handlerCode = isMethodPath - ? `return ${handler.value}($event)` - : isFunctionExpression - ? `return (${handler.value})($event)` - : isFunctionInvocation - ? `return ${handler.value}` - : handler.value - /* istanbul ignore if */ - if (__WEEX__ && handler.params) { - return genWeexHandler(handler.params, code + handlerCode) - } - return `function($event){${code}${handlerCode}}` - } -} - -function genKeyFilter (keys: Array): string { - return ( - // make sure the key filters only apply to KeyboardEvents - // #9441: can't use 'keyCode' in $event because Chrome autofill fires fake - // key events that do not have keyCode property... - `if(!$event.type.indexOf('key')&&` + - `${keys.map(genFilterCode).join('&&')})return null;` - ) -} - -function genFilterCode (key: string): string { - const keyVal = parseInt(key, 10) - if (keyVal) { - return `$event.keyCode!==${keyVal}` - } - const keyCode = keyCodes[key] - const keyName = keyNames[key] - return ( - `_k($event.keyCode,` + - `${JSON.stringify(key)},` + - `${JSON.stringify(keyCode)},` + - `$event.key,` + - `${JSON.stringify(keyName)}` + - `)` - ) -} diff --git a/1.Vue/src/compiler/codegen/index.js b/1.Vue/src/compiler/codegen/index.js deleted file mode 100644 index c96b3a3..0000000 --- a/1.Vue/src/compiler/codegen/index.js +++ /dev/null @@ -1,618 +0,0 @@ -/* @flow */ - -import { genHandlers } from './events' -import baseDirectives from '../directives/index' -import { camelize, no, extend } from 'shared/util' -import { baseWarn, pluckModuleFunction } from '../helpers' -import { emptySlotScopeToken } from '../parser/index' - -type TransformFunction = (el: ASTElement, code: string) => string; -type DataGenFunction = (el: ASTElement) => string; -type DirectiveFunction = (el: ASTElement, dir: ASTDirective, warn: Function) => boolean; - -export class CodegenState { - options: CompilerOptions; - warn: Function; - transforms: Array; - dataGenFns: Array; - directives: { [key: string]: DirectiveFunction }; - maybeComponent: (el: ASTElement) => boolean; - onceId: number; - staticRenderFns: Array; - pre: boolean; - - constructor (options: CompilerOptions) { - this.options = options - this.warn = options.warn || baseWarn - this.transforms = pluckModuleFunction(options.modules, 'transformCode') - this.dataGenFns = pluckModuleFunction(options.modules, 'genData') - this.directives = extend(extend({}, baseDirectives), options.directives) - const isReservedTag = options.isReservedTag || no - this.maybeComponent = (el: ASTElement) => !!el.component || !isReservedTag(el.tag) - this.onceId = 0 - this.staticRenderFns = [] - this.pre = false - } -} - -export type CodegenResult = { - render: string, - staticRenderFns: Array -}; - -export function generate ( - ast: ASTElement | void, - options: CompilerOptions -): CodegenResult { - const state = new CodegenState(options) - const code = ast ? genElement(ast, state) : '_c("div")' - return { - render: `with(this){return ${code}}`, - staticRenderFns: state.staticRenderFns - } -} - -export function genElement (el: ASTElement, state: CodegenState): string { - if (el.parent) { - el.pre = el.pre || el.parent.pre - } - - if (el.staticRoot && !el.staticProcessed) { - return genStatic(el, state) - } else if (el.once && !el.onceProcessed) { - return genOnce(el, state) - } else if (el.for && !el.forProcessed) { - return genFor(el, state) - } else if (el.if && !el.ifProcessed) { - return genIf(el, state) - } else if (el.tag === 'template' && !el.slotTarget && !state.pre) { - return genChildren(el, state) || 'void 0' - } else if (el.tag === 'slot') { - return genSlot(el, state) - } else { - // component or element - let code - if (el.component) { - code = genComponent(el.component, el, state) - } else { - let data - if (!el.plain || (el.pre && state.maybeComponent(el))) { - data = genData(el, state) - } - - const children = el.inlineTemplate ? null : genChildren(el, state, true) - code = `_c('${el.tag}'${ - data ? `,${data}` : '' // data - }${ - children ? `,${children}` : '' // children - })` - } - // module transforms - for (let i = 0; i < state.transforms.length; i++) { - code = state.transforms[i](el, code) - } - return code - } -} - -// hoist static sub-trees out -function genStatic (el: ASTElement, state: CodegenState): string { - el.staticProcessed = true - // Some elements (templates) need to behave differently inside of a v-pre - // node. All pre nodes are static roots, so we can use this as a location to - // wrap a state change and reset it upon exiting the pre node. - const originalPreState = state.pre - if (el.pre) { - state.pre = el.pre - } - state.staticRenderFns.push(`with(this){return ${genElement(el, state)}}`) - state.pre = originalPreState - return `_m(${ - state.staticRenderFns.length - 1 - }${ - el.staticInFor ? ',true' : '' - })` -} - -// v-once -function genOnce (el: ASTElement, state: CodegenState): string { - el.onceProcessed = true - if (el.if && !el.ifProcessed) { - return genIf(el, state) - } else if (el.staticInFor) { - let key = '' - let parent = el.parent - while (parent) { - if (parent.for) { - key = parent.key - break - } - parent = parent.parent - } - if (!key) { - process.env.NODE_ENV !== 'production' && state.warn( - `v-once can only be used inside v-for that is keyed. `, - el.rawAttrsMap['v-once'] - ) - return genElement(el, state) - } - return `_o(${genElement(el, state)},${state.onceId++},${key})` - } else { - return genStatic(el, state) - } -} - -export function genIf ( - el: any, - state: CodegenState, - altGen?: Function, - altEmpty?: string -): string { - el.ifProcessed = true // avoid recursion - return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty) -} - -function genIfConditions ( - conditions: ASTIfConditions, - state: CodegenState, - altGen?: Function, - altEmpty?: string -): string { - if (!conditions.length) { - return altEmpty || '_e()' - } - - const condition = conditions.shift() - if (condition.exp) { - return `(${condition.exp})?${ - genTernaryExp(condition.block) - }:${ - genIfConditions(conditions, state, altGen, altEmpty) - }` - } else { - return `${genTernaryExp(condition.block)}` - } - - // v-if with v-once should generate code like (a)?_m(0):_m(1) - function genTernaryExp (el) { - return altGen - ? altGen(el, state) - : el.once - ? genOnce(el, state) - : genElement(el, state) - } -} - -export function genFor ( - el: any, - state: CodegenState, - altGen?: Function, - altHelper?: string -): string { - const exp = el.for - const alias = el.alias - const iterator1 = el.iterator1 ? `,${el.iterator1}` : '' - const iterator2 = el.iterator2 ? `,${el.iterator2}` : '' - - if (process.env.NODE_ENV !== 'production' && - state.maybeComponent(el) && - el.tag !== 'slot' && - el.tag !== 'template' && - !el.key - ) { - state.warn( - `<${el.tag} v-for="${alias} in ${exp}">: component lists rendered with ` + - `v-for should have explicit keys. ` + - `See https://vuejs.org/guide/list.html#key for more info.`, - el.rawAttrsMap['v-for'], - true /* tip */ - ) - } - - el.forProcessed = true // avoid recursion - return `${altHelper || '_l'}((${exp}),` + - `function(${alias}${iterator1}${iterator2}){` + - `return ${(altGen || genElement)(el, state)}` + - '})' -} - -export function genData (el: ASTElement, state: CodegenState): string { - let data = '{' - - // directives first. - // directives may mutate the el's other properties before they are generated. - const dirs = genDirectives(el, state) - if (dirs) data += dirs + ',' - - // key - if (el.key) { - data += `key:${el.key},` - } - // ref - if (el.ref) { - data += `ref:${el.ref},` - } - if (el.refInFor) { - data += `refInFor:true,` - } - // pre - if (el.pre) { - data += `pre:true,` - } - // record original tag name for components using "is" attribute - if (el.component) { - data += `tag:"${el.tag}",` - } - // module data generation functions - for (let i = 0; i < state.dataGenFns.length; i++) { - data += state.dataGenFns[i](el) - } - // attributes - if (el.attrs) { - data += `attrs:${genProps(el.attrs)},` - } - // DOM props - if (el.props) { - data += `domProps:${genProps(el.props)},` - } - // event handlers - if (el.events) { - data += `${genHandlers(el.events, false)},` - } - if (el.nativeEvents) { - data += `${genHandlers(el.nativeEvents, true)},` - } - // slot target - // only for non-scoped slots - if (el.slotTarget && !el.slotScope) { - data += `slot:${el.slotTarget},` - } - // scoped slots - if (el.scopedSlots) { - data += `${genScopedSlots(el, el.scopedSlots, state)},` - } - // component v-model - if (el.model) { - data += `model:{value:${ - el.model.value - },callback:${ - el.model.callback - },expression:${ - el.model.expression - }},` - } - // inline-template - if (el.inlineTemplate) { - const inlineTemplate = genInlineTemplate(el, state) - if (inlineTemplate) { - data += `${inlineTemplate},` - } - } - data = data.replace(/,$/, '') + '}' - // v-bind dynamic argument wrap - // v-bind with dynamic arguments must be applied using the same v-bind object - // merge helper so that class/style/mustUseProp attrs are handled correctly. - if (el.dynamicAttrs) { - data = `_b(${data},"${el.tag}",${genProps(el.dynamicAttrs)})` - } - // v-bind data wrap - if (el.wrapData) { - data = el.wrapData(data) - } - // v-on data wrap - if (el.wrapListeners) { - data = el.wrapListeners(data) - } - return data -} - -function genDirectives (el: ASTElement, state: CodegenState): string | void { - const dirs = el.directives - if (!dirs) return - let res = 'directives:[' - let hasRuntime = false - let i, l, dir, needRuntime - for (i = 0, l = dirs.length; i < l; i++) { - dir = dirs[i] - needRuntime = true - const gen: DirectiveFunction = state.directives[dir.name] - if (gen) { - // compile-time directive that manipulates AST. - // returns true if it also needs a runtime counterpart. - needRuntime = !!gen(el, dir, state.warn) - } - if (needRuntime) { - hasRuntime = true - res += `{name:"${dir.name}",rawName:"${dir.rawName}"${ - dir.value ? `,value:(${dir.value}),expression:${JSON.stringify(dir.value)}` : '' - }${ - dir.arg ? `,arg:${dir.isDynamicArg ? dir.arg : `"${dir.arg}"`}` : '' - }${ - dir.modifiers ? `,modifiers:${JSON.stringify(dir.modifiers)}` : '' - }},` - } - } - if (hasRuntime) { - return res.slice(0, -1) + ']' - } -} - -function genInlineTemplate (el: ASTElement, state: CodegenState): ?string { - const ast = el.children[0] - if (process.env.NODE_ENV !== 'production' && ( - el.children.length !== 1 || ast.type !== 1 - )) { - state.warn( - 'Inline-template components must have exactly one child element.', - { start: el.start } - ) - } - if (ast && ast.type === 1) { - const inlineRenderFns = generate(ast, state.options) - return `inlineTemplate:{render:function(){${ - inlineRenderFns.render - }},staticRenderFns:[${ - inlineRenderFns.staticRenderFns.map(code => `function(){${code}}`).join(',') - }]}` - } -} - -function genScopedSlots ( - el: ASTElement, - slots: { [key: string]: ASTElement }, - state: CodegenState -): string { - // by default scoped slots are considered "stable", this allows child - // components with only scoped slots to skip forced updates from parent. - // but in some cases we have to bail-out of this optimization - // for example if the slot contains dynamic names, has v-if or v-for on them... - let needsForceUpdate = el.for || Object.keys(slots).some(key => { - const slot = slots[key] - return ( - slot.slotTargetDynamic || - slot.if || - slot.for || - containsSlotChild(slot) // is passing down slot from parent which may be dynamic - ) - }) - - // #9534: if a component with scoped slots is inside a conditional branch, - // it's possible for the same component to be reused but with different - // compiled slot content. To avoid that, we generate a unique key based on - // the generated code of all the slot contents. - let needsKey = !!el.if - - // OR when it is inside another scoped slot or v-for (the reactivity may be - // disconnected due to the intermediate scope variable) - // #9438, #9506 - // TODO: this can be further optimized by properly analyzing in-scope bindings - // and skip force updating ones that do not actually use scope variables. - if (!needsForceUpdate) { - let parent = el.parent - while (parent) { - if ( - (parent.slotScope && parent.slotScope !== emptySlotScopeToken) || - parent.for - ) { - needsForceUpdate = true - break - } - if (parent.if) { - needsKey = true - } - parent = parent.parent - } - } - - const generatedSlots = Object.keys(slots) - .map(key => genScopedSlot(slots[key], state)) - .join(',') - - return `scopedSlots:_u([${generatedSlots}]${ - needsForceUpdate ? `,null,true` : `` - }${ - !needsForceUpdate && needsKey ? `,null,false,${hash(generatedSlots)}` : `` - })` -} - -function hash(str) { - let hash = 5381 - let i = str.length - while(i) { - hash = (hash * 33) ^ str.charCodeAt(--i) - } - return hash >>> 0 -} - -function containsSlotChild (el: ASTNode): boolean { - if (el.type === 1) { - if (el.tag === 'slot') { - return true - } - return el.children.some(containsSlotChild) - } - return false -} - -function genScopedSlot ( - el: ASTElement, - state: CodegenState -): string { - const isLegacySyntax = el.attrsMap['slot-scope'] - if (el.if && !el.ifProcessed && !isLegacySyntax) { - return genIf(el, state, genScopedSlot, `null`) - } - if (el.for && !el.forProcessed) { - return genFor(el, state, genScopedSlot) - } - const slotScope = el.slotScope === emptySlotScopeToken - ? `` - : String(el.slotScope) - const fn = `function(${slotScope}){` + - `return ${el.tag === 'template' - ? el.if && isLegacySyntax - ? `(${el.if})?${genChildren(el, state) || 'undefined'}:undefined` - : genChildren(el, state) || 'undefined' - : genElement(el, state) - }}` - // reverse proxy v-slot without scope on this.$slots - const reverseProxy = slotScope ? `` : `,proxy:true` - return `{key:${el.slotTarget || `"default"`},fn:${fn}${reverseProxy}}` -} - -export function genChildren ( - el: ASTElement, - state: CodegenState, - checkSkip?: boolean, - altGenElement?: Function, - altGenNode?: Function -): string | void { - const children = el.children - if (children.length) { - const el: any = children[0] - // optimize single v-for - if (children.length === 1 && - el.for && - el.tag !== 'template' && - el.tag !== 'slot' - ) { - const normalizationType = checkSkip - ? state.maybeComponent(el) ? `,1` : `,0` - : `` - return `${(altGenElement || genElement)(el, state)}${normalizationType}` - } - const normalizationType = checkSkip - ? getNormalizationType(children, state.maybeComponent) - : 0 - const gen = altGenNode || genNode - return `[${children.map(c => gen(c, state)).join(',')}]${ - normalizationType ? `,${normalizationType}` : '' - }` - } -} - -// determine the normalization needed for the children array. -// 0: no normalization needed -// 1: simple normalization needed (possible 1-level deep nested array) -// 2: full normalization needed -function getNormalizationType ( - children: Array, - maybeComponent: (el: ASTElement) => boolean -): number { - let res = 0 - for (let i = 0; i < children.length; i++) { - const el: ASTNode = children[i] - if (el.type !== 1) { - continue - } - if (needsNormalization(el) || - (el.ifConditions && el.ifConditions.some(c => needsNormalization(c.block)))) { - res = 2 - break - } - if (maybeComponent(el) || - (el.ifConditions && el.ifConditions.some(c => maybeComponent(c.block)))) { - res = 1 - } - } - return res -} - -function needsNormalization (el: ASTElement): boolean { - return el.for !== undefined || el.tag === 'template' || el.tag === 'slot' -} - -function genNode (node: ASTNode, state: CodegenState): string { - if (node.type === 1) { - return genElement(node, state) - } else if (node.type === 3 && node.isComment) { - return genComment(node) - } else { - return genText(node) - } -} - -export function genText (text: ASTText | ASTExpression): string { - return `_v(${text.type === 2 - ? text.expression // no need for () because already wrapped in _s() - : transformSpecialNewlines(JSON.stringify(text.text)) - })` -} - -export function genComment (comment: ASTText): string { - return `_e(${JSON.stringify(comment.text)})` -} - -function genSlot (el: ASTElement, state: CodegenState): string { - const slotName = el.slotName || '"default"' - const children = genChildren(el, state) - let res = `_t(${slotName}${children ? `,${children}` : ''}` - const attrs = el.attrs || el.dynamicAttrs - ? genProps((el.attrs || []).concat(el.dynamicAttrs || []).map(attr => ({ - // slot props are camelized - name: camelize(attr.name), - value: attr.value, - dynamic: attr.dynamic - }))) - : null - const bind = el.attrsMap['v-bind'] - if ((attrs || bind) && !children) { - res += `,null` - } - if (attrs) { - res += `,${attrs}` - } - if (bind) { - res += `${attrs ? '' : ',null'},${bind}` - } - return res + ')' -} - -// componentName is el.component, take it as argument to shun flow's pessimistic refinement -function genComponent ( - componentName: string, - el: ASTElement, - state: CodegenState -): string { - const children = el.inlineTemplate ? null : genChildren(el, state, true) - return `_c(${componentName},${genData(el, state)}${ - children ? `,${children}` : '' - })` -} - -function genProps (props: Array): string { - let staticProps = `` - let dynamicProps = `` - for (let i = 0; i < props.length; i++) { - const prop = props[i] - const value = __WEEX__ - ? generateValue(prop.value) - : transformSpecialNewlines(prop.value) - if (prop.dynamic) { - dynamicProps += `${prop.name},${value},` - } else { - staticProps += `"${prop.name}":${value},` - } - } - staticProps = `{${staticProps.slice(0, -1)}}` - if (dynamicProps) { - return `_d(${staticProps},[${dynamicProps.slice(0, -1)}])` - } else { - return staticProps - } -} - -/* istanbul ignore next */ -function generateValue (value) { - if (typeof value === 'string') { - return transformSpecialNewlines(value) - } - return JSON.stringify(value) -} - -// #3895, #4268 -function transformSpecialNewlines (text: string): string { - return text - .replace(/\u2028/g, '\\u2028') - .replace(/\u2029/g, '\\u2029') -} diff --git a/1.Vue/src/compiler/create-compiler.js b/1.Vue/src/compiler/create-compiler.js deleted file mode 100644 index 67d2057..0000000 --- a/1.Vue/src/compiler/create-compiler.js +++ /dev/null @@ -1,75 +0,0 @@ -/* @flow */ - -import { extend } from 'shared/util' -import { detectErrors } from './error-detector' -import { createCompileToFunctionFn } from './to-function' - -export function createCompilerCreator (baseCompile: Function): Function { - return function createCompiler (baseOptions: CompilerOptions) { - function compile ( - template: string, - options?: CompilerOptions - ): CompiledResult { - const finalOptions = Object.create(baseOptions) - const errors = [] - const tips = [] - - let warn = (msg, range, tip) => { - (tip ? tips : errors).push(msg) - } - - if (options) { - if (process.env.NODE_ENV !== 'production' && options.outputSourceRange) { - // $flow-disable-line - const leadingSpaceLength = template.match(/^\s*/)[0].length - - warn = (msg, range, tip) => { - const data: WarningMessage = { msg } - if (range) { - if (range.start != null) { - data.start = range.start + leadingSpaceLength - } - if (range.end != null) { - data.end = range.end + leadingSpaceLength - } - } - (tip ? tips : errors).push(data) - } - } - // merge custom modules - if (options.modules) { - finalOptions.modules = - (baseOptions.modules || []).concat(options.modules) - } - // merge custom directives - if (options.directives) { - finalOptions.directives = extend( - Object.create(baseOptions.directives || null), - options.directives - ) - } - // copy other options - for (const key in options) { - if (key !== 'modules' && key !== 'directives') { - finalOptions[key] = options[key] - } - } - } - - finalOptions.warn = warn - - const compiled = baseCompile(template.trim(), finalOptions) - if (process.env.NODE_ENV !== 'production') { - detectErrors(compiled.ast, warn) - } - compiled.errors = errors - compiled.tips = tips - return compiled - } - - return { - compile, - compileToFunctions: createCompileToFunctionFn(compile) - } - } -} diff --git a/1.Vue/src/compiler/directives/bind.js b/1.Vue/src/compiler/directives/bind.js deleted file mode 100644 index e103572..0000000 --- a/1.Vue/src/compiler/directives/bind.js +++ /dev/null @@ -1,11 +0,0 @@ -/* @flow */ - -export default function bind (el: ASTElement, dir: ASTDirective) { - el.wrapData = (code: string) => { - return `_b(${code},'${el.tag}',${dir.value},${ - dir.modifiers && dir.modifiers.prop ? 'true' : 'false' - }${ - dir.modifiers && dir.modifiers.sync ? ',true' : '' - })` - } -} diff --git a/1.Vue/src/compiler/directives/index.js b/1.Vue/src/compiler/directives/index.js deleted file mode 100644 index 8f4342c..0000000 --- a/1.Vue/src/compiler/directives/index.js +++ /dev/null @@ -1,11 +0,0 @@ -/* @flow */ - -import on from './on' -import bind from './bind' -import { noop } from 'shared/util' - -export default { - on, - bind, - cloak: noop -} diff --git a/1.Vue/src/compiler/directives/model.js b/1.Vue/src/compiler/directives/model.js deleted file mode 100644 index c7a4c09..0000000 --- a/1.Vue/src/compiler/directives/model.js +++ /dev/null @@ -1,148 +0,0 @@ -/* @flow */ - -/** - * Cross-platform code generation for component v-model - */ -export function genComponentModel ( - el: ASTElement, - value: string, - modifiers: ?ASTModifiers -): ?boolean { - const { number, trim } = modifiers || {} - - const baseValueExpression = '$$v' - let valueExpression = baseValueExpression - if (trim) { - valueExpression = - `(typeof ${baseValueExpression} === 'string'` + - `? ${baseValueExpression}.trim()` + - `: ${baseValueExpression})` - } - if (number) { - valueExpression = `_n(${valueExpression})` - } - const assignment = genAssignmentCode(value, valueExpression) - - el.model = { - value: `(${value})`, - expression: JSON.stringify(value), - callback: `function (${baseValueExpression}) {${assignment}}` - } -} - -/** - * Cross-platform codegen helper for generating v-model value assignment code. - */ -export function genAssignmentCode ( - value: string, - assignment: string -): string { - const res = parseModel(value) - if (res.key === null) { - return `${value}=${assignment}` - } else { - return `$set(${res.exp}, ${res.key}, ${assignment})` - } -} - -/** - * Parse a v-model expression into a base path and a final key segment. - * Handles both dot-path and possible square brackets. - * - * Possible cases: - * - * - test - * - test[key] - * - test[test1[key]] - * - test["a"][key] - * - xxx.test[a[a].test1[key]] - * - test.xxx.a["asa"][test1[key]] - * - */ - -let len, str, chr, index, expressionPos, expressionEndPos - -type ModelParseResult = { - exp: string, - key: string | null -} - -export function parseModel (val: string): ModelParseResult { - // Fix https://github.com/vuejs/vue/pull/7730 - // allow v-model="obj.val " (trailing whitespace) - val = val.trim() - len = val.length - - if (val.indexOf('[') < 0 || val.lastIndexOf(']') < len - 1) { - index = val.lastIndexOf('.') - if (index > -1) { - return { - exp: val.slice(0, index), - key: '"' + val.slice(index + 1) + '"' - } - } else { - return { - exp: val, - key: null - } - } - } - - str = val - index = expressionPos = expressionEndPos = 0 - - while (!eof()) { - chr = next() - /* istanbul ignore if */ - if (isStringStart(chr)) { - parseString(chr) - } else if (chr === 0x5B) { - parseBracket(chr) - } - } - - return { - exp: val.slice(0, expressionPos), - key: val.slice(expressionPos + 1, expressionEndPos) - } -} - -function next (): number { - return str.charCodeAt(++index) -} - -function eof (): boolean { - return index >= len -} - -function isStringStart (chr: number): boolean { - return chr === 0x22 || chr === 0x27 -} - -function parseBracket (chr: number): void { - let inBracket = 1 - expressionPos = index - while (!eof()) { - chr = next() - if (isStringStart(chr)) { - parseString(chr) - continue - } - if (chr === 0x5B) inBracket++ - if (chr === 0x5D) inBracket-- - if (inBracket === 0) { - expressionEndPos = index - break - } - } -} - -function parseString (chr: number): void { - const stringQuote = chr - while (!eof()) { - chr = next() - if (chr === stringQuote) { - break - } - } -} diff --git a/1.Vue/src/compiler/directives/on.js b/1.Vue/src/compiler/directives/on.js deleted file mode 100644 index 893a678..0000000 --- a/1.Vue/src/compiler/directives/on.js +++ /dev/null @@ -1,10 +0,0 @@ -/* @flow */ - -import { warn } from 'core/util/index' - -export default function on (el: ASTElement, dir: ASTDirective) { - if (process.env.NODE_ENV !== 'production' && dir.modifiers) { - warn(`v-on without argument does not support modifiers.`) - } - el.wrapListeners = (code: string) => `_g(${code},${dir.value})` -} diff --git a/1.Vue/src/compiler/error-detector.js b/1.Vue/src/compiler/error-detector.js deleted file mode 100644 index 22c3b75..0000000 --- a/1.Vue/src/compiler/error-detector.js +++ /dev/null @@ -1,113 +0,0 @@ -/* @flow */ - -import { dirRE, onRE } from './parser/index' - -type Range = { start?: number, end?: number }; - -// these keywords should not appear inside expressions, but operators like -// typeof, instanceof and in are allowed -const prohibitedKeywordRE = new RegExp('\\b' + ( - 'do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' + - 'super,throw,while,yield,delete,export,import,return,switch,default,' + - 'extends,finally,continue,debugger,function,arguments' -).split(',').join('\\b|\\b') + '\\b') - -// these unary operators should not be used as property/method names -const unaryOperatorsRE = new RegExp('\\b' + ( - 'delete,typeof,void' -).split(',').join('\\s*\\([^\\)]*\\)|\\b') + '\\s*\\([^\\)]*\\)') - -// strip strings in expressions -const stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g - -// detect problematic expressions in a template -export function detectErrors (ast: ?ASTNode, warn: Function) { - if (ast) { - checkNode(ast, warn) - } -} - -function checkNode (node: ASTNode, warn: Function) { - if (node.type === 1) { - for (const name in node.attrsMap) { - if (dirRE.test(name)) { - const value = node.attrsMap[name] - if (value) { - const range = node.rawAttrsMap[name] - if (name === 'v-for') { - checkFor(node, `v-for="${value}"`, warn, range) - } else if (onRE.test(name)) { - checkEvent(value, `${name}="${value}"`, warn, range) - } else { - checkExpression(value, `${name}="${value}"`, warn, range) - } - } - } - } - if (node.children) { - for (let i = 0; i < node.children.length; i++) { - checkNode(node.children[i], warn) - } - } - } else if (node.type === 2) { - checkExpression(node.expression, node.text, warn, node) - } -} - -function checkEvent (exp: string, text: string, warn: Function, range?: Range) { - const stipped = exp.replace(stripStringRE, '') - const keywordMatch: any = stipped.match(unaryOperatorsRE) - if (keywordMatch && stipped.charAt(keywordMatch.index - 1) !== '$') { - warn( - `avoid using JavaScript unary operator as property name: ` + - `"${keywordMatch[0]}" in expression ${text.trim()}`, - range - ) - } - checkExpression(exp, text, warn, range) -} - -function checkFor (node: ASTElement, text: string, warn: Function, range?: Range) { - checkExpression(node.for || '', text, warn, range) - checkIdentifier(node.alias, 'v-for alias', text, warn, range) - checkIdentifier(node.iterator1, 'v-for iterator', text, warn, range) - checkIdentifier(node.iterator2, 'v-for iterator', text, warn, range) -} - -function checkIdentifier ( - ident: ?string, - type: string, - text: string, - warn: Function, - range?: Range -) { - if (typeof ident === 'string') { - try { - new Function(`var ${ident}=_`) - } catch (e) { - warn(`invalid ${type} "${ident}" in expression: ${text.trim()}`, range) - } - } -} - -function checkExpression (exp: string, text: string, warn: Function, range?: Range) { - try { - new Function(`return ${exp}`) - } catch (e) { - const keywordMatch = exp.replace(stripStringRE, '').match(prohibitedKeywordRE) - if (keywordMatch) { - warn( - `avoid using JavaScript keyword as property name: ` + - `"${keywordMatch[0]}"\n Raw expression: ${text.trim()}`, - range - ) - } else { - warn( - `invalid expression: ${e.message} in\n\n` + - ` ${exp}\n\n` + - ` Raw expression: ${text.trim()}\n`, - range - ) - } - } -} diff --git a/1.Vue/src/compiler/helpers.js b/1.Vue/src/compiler/helpers.js deleted file mode 100644 index 7231d68..0000000 --- a/1.Vue/src/compiler/helpers.js +++ /dev/null @@ -1,231 +0,0 @@ -/* @flow */ - -import { emptyObject } from 'shared/util' -import { parseFilters } from './parser/filter-parser' - -type Range = { start?: number, end?: number }; - -/* eslint-disable no-unused-vars */ -export function baseWarn (msg: string, range?: Range) { - console.error(`[Vue compiler]: ${msg}`) -} -/* eslint-enable no-unused-vars */ - -export function pluckModuleFunction ( - modules: ?Array, - key: string -): Array { - return modules - ? modules.map(m => m[key]).filter(_ => _) - : [] -} - -export function addProp (el: ASTElement, name: string, value: string, range?: Range, dynamic?: boolean) { - (el.props || (el.props = [])).push(rangeSetItem({ name, value, dynamic }, range)) - el.plain = false -} - -export function addAttr (el: ASTElement, name: string, value: any, range?: Range, dynamic?: boolean) { - const attrs = dynamic - ? (el.dynamicAttrs || (el.dynamicAttrs = [])) - : (el.attrs || (el.attrs = [])) - attrs.push(rangeSetItem({ name, value, dynamic }, range)) - el.plain = false -} - -// add a raw attr (use this in preTransforms) -export function addRawAttr (el: ASTElement, name: string, value: any, range?: Range) { - el.attrsMap[name] = value - el.attrsList.push(rangeSetItem({ name, value }, range)) -} - -export function addDirective ( - el: ASTElement, - name: string, - rawName: string, - value: string, - arg: ?string, - isDynamicArg: boolean, - modifiers: ?ASTModifiers, - range?: Range -) { - (el.directives || (el.directives = [])).push(rangeSetItem({ - name, - rawName, - value, - arg, - isDynamicArg, - modifiers - }, range)) - el.plain = false -} - -function prependModifierMarker (symbol: string, name: string, dynamic?: boolean): string { - return dynamic - ? `_p(${name},"${symbol}")` - : symbol + name // mark the event as captured -} - -export function addHandler ( - el: ASTElement, - name: string, - value: string, - modifiers: ?ASTModifiers, - important?: boolean, - warn?: ?Function, - range?: Range, - dynamic?: boolean -) { - modifiers = modifiers || emptyObject - // warn prevent and passive modifier - /* istanbul ignore if */ - if ( - process.env.NODE_ENV !== 'production' && warn && - modifiers.prevent && modifiers.passive - ) { - warn( - 'passive and prevent can\'t be used together. ' + - 'Passive handler can\'t prevent default event.', - range - ) - } - - // normalize click.right and click.middle since they don't actually fire - // this is technically browser-specific, but at least for now browsers are - // the only target envs that have right/middle clicks. - if (modifiers.right) { - if (dynamic) { - name = `(${name})==='click'?'contextmenu':(${name})` - } else if (name === 'click') { - name = 'contextmenu' - delete modifiers.right - } - } else if (modifiers.middle) { - if (dynamic) { - name = `(${name})==='click'?'mouseup':(${name})` - } else if (name === 'click') { - name = 'mouseup' - } - } - - // check capture modifier - if (modifiers.capture) { - delete modifiers.capture - name = prependModifierMarker('!', name, dynamic) - } - if (modifiers.once) { - delete modifiers.once - name = prependModifierMarker('~', name, dynamic) - } - /* istanbul ignore if */ - if (modifiers.passive) { - delete modifiers.passive - name = prependModifierMarker('&', name, dynamic) - } - - let events - if (modifiers.native) { - delete modifiers.native - events = el.nativeEvents || (el.nativeEvents = {}) - } else { - events = el.events || (el.events = {}) - } - - const newHandler: any = rangeSetItem({ value: value.trim(), dynamic }, range) - if (modifiers !== emptyObject) { - newHandler.modifiers = modifiers - } - - const handlers = events[name] - /* istanbul ignore if */ - if (Array.isArray(handlers)) { - important ? handlers.unshift(newHandler) : handlers.push(newHandler) - } else if (handlers) { - events[name] = important ? [newHandler, handlers] : [handlers, newHandler] - } else { - events[name] = newHandler - } - - el.plain = false -} - -export function getRawBindingAttr ( - el: ASTElement, - name: string -) { - return el.rawAttrsMap[':' + name] || - el.rawAttrsMap['v-bind:' + name] || - el.rawAttrsMap[name] -} - -export function getBindingAttr ( - el: ASTElement, - name: string, - getStatic?: boolean -): ?string { - const dynamicValue = - getAndRemoveAttr(el, ':' + name) || - getAndRemoveAttr(el, 'v-bind:' + name) - if (dynamicValue != null) { - return parseFilters(dynamicValue) - } else if (getStatic !== false) { - const staticValue = getAndRemoveAttr(el, name) - if (staticValue != null) { - return JSON.stringify(staticValue) - } - } -} - -// note: this only removes the attr from the Array (attrsList) so that it -// doesn't get processed by processAttrs. -// By default it does NOT remove it from the map (attrsMap) because the map is -// needed during codegen. -export function getAndRemoveAttr ( - el: ASTElement, - name: string, - removeFromMap?: boolean -): ?string { - let val - if ((val = el.attrsMap[name]) != null) { - const list = el.attrsList - for (let i = 0, l = list.length; i < l; i++) { - if (list[i].name === name) { - list.splice(i, 1) - break - } - } - } - if (removeFromMap) { - delete el.attrsMap[name] - } - return val -} - -export function getAndRemoveAttrByRegex ( - el: ASTElement, - name: RegExp -) { - const list = el.attrsList - for (let i = 0, l = list.length; i < l; i++) { - const attr = list[i] - if (name.test(attr.name)) { - list.splice(i, 1) - return attr - } - } -} - -function rangeSetItem ( - item: any, - range?: { start?: number, end?: number } -) { - if (range) { - if (range.start != null) { - item.start = range.start - } - if (range.end != null) { - item.end = range.end - } - } - return item -} diff --git a/1.Vue/src/compiler/index.js b/1.Vue/src/compiler/index.js deleted file mode 100644 index 56b54fd..0000000 --- a/1.Vue/src/compiler/index.js +++ /dev/null @@ -1,25 +0,0 @@ -/* @flow */ - -import { parse } from './parser/index' -import { optimize } from './optimizer' -import { generate } from './codegen/index' -import { createCompilerCreator } from './create-compiler' - -// `createCompilerCreator` allows creating compilers that use alternative -// parser/optimizer/codegen, e.g the SSR optimizing compiler. -// Here we just export a default compiler using the default parts. -export const createCompiler = createCompilerCreator(function baseCompile ( - template: string, - options: CompilerOptions -): CompiledResult { - const ast = parse(template.trim(), options) - if (options.optimize !== false) { - optimize(ast, options) - } - const code = generate(ast, options) - return { - ast, - render: code.render, - staticRenderFns: code.staticRenderFns - } -}) diff --git a/1.Vue/src/compiler/optimizer.js b/1.Vue/src/compiler/optimizer.js deleted file mode 100644 index 5f56e74..0000000 --- a/1.Vue/src/compiler/optimizer.js +++ /dev/null @@ -1,128 +0,0 @@ -/* @flow */ - -import { makeMap, isBuiltInTag, cached, no } from 'shared/util' - -let isStaticKey -let isPlatformReservedTag - -const genStaticKeysCached = cached(genStaticKeys) - -/** - * Goal of the optimizer: walk the generated template AST tree - * and detect sub-trees that are purely static, i.e. parts of - * the DOM that never needs to change. - * - * Once we detect these sub-trees, we can: - * - * 1. Hoist them into constants, so that we no longer need to - * create fresh nodes for them on each re-render; - * 2. Completely skip them in the patching process. - */ -export function optimize (root: ?ASTElement, options: CompilerOptions) { - if (!root) return - isStaticKey = genStaticKeysCached(options.staticKeys || '') - isPlatformReservedTag = options.isReservedTag || no - // first pass: mark all non-static nodes. - markStatic(root) - // second pass: mark static roots. - markStaticRoots(root, false) -} - -function genStaticKeys (keys: string): Function { - return makeMap( - 'type,tag,attrsList,attrsMap,plain,parent,children,attrs,start,end,rawAttrsMap' + - (keys ? ',' + keys : '') - ) -} - -function markStatic (node: ASTNode) { - node.static = isStatic(node) - if (node.type === 1) { - // do not make component slot content static. this avoids - // 1. components not able to mutate slot nodes - // 2. static slot content fails for hot-reloading - if ( - !isPlatformReservedTag(node.tag) && - node.tag !== 'slot' && - node.attrsMap['inline-template'] == null - ) { - return - } - for (let i = 0, l = node.children.length; i < l; i++) { - const child = node.children[i] - markStatic(child) - if (!child.static) { - node.static = false - } - } - if (node.ifConditions) { - for (let i = 1, l = node.ifConditions.length; i < l; i++) { - const block = node.ifConditions[i].block - markStatic(block) - if (!block.static) { - node.static = false - } - } - } - } -} - -function markStaticRoots (node: ASTNode, isInFor: boolean) { - if (node.type === 1) { - if (node.static || node.once) { - node.staticInFor = isInFor - } - // For a node to qualify as a static root, it should have children that - // are not just static text. Otherwise the cost of hoisting out will - // outweigh the benefits and it's better off to just always render it fresh. - if (node.static && node.children.length && !( - node.children.length === 1 && - node.children[0].type === 3 - )) { - node.staticRoot = true - return - } else { - node.staticRoot = false - } - if (node.children) { - for (let i = 0, l = node.children.length; i < l; i++) { - markStaticRoots(node.children[i], isInFor || !!node.for) - } - } - if (node.ifConditions) { - for (let i = 1, l = node.ifConditions.length; i < l; i++) { - markStaticRoots(node.ifConditions[i].block, isInFor) - } - } - } -} - -function isStatic (node: ASTNode): boolean { - if (node.type === 2) { // expression - return false - } - if (node.type === 3) { // text - return true - } - return !!(node.pre || ( - !node.hasBindings && // no dynamic bindings - !node.if && !node.for && // not v-if or v-for or v-else - !isBuiltInTag(node.tag) && // not a built-in - isPlatformReservedTag(node.tag) && // not a component - !isDirectChildOfTemplateFor(node) && - Object.keys(node).every(isStaticKey) - )) -} - -function isDirectChildOfTemplateFor (node: ASTElement): boolean { - while (node.parent) { - node = node.parent - if (node.tag !== 'template') { - return false - } - if (node.for) { - return true - } - } - return false -} diff --git a/1.Vue/src/compiler/parser/entity-decoder.js b/1.Vue/src/compiler/parser/entity-decoder.js deleted file mode 100644 index 2836294..0000000 --- a/1.Vue/src/compiler/parser/entity-decoder.js +++ /dev/null @@ -1,11 +0,0 @@ -/* @flow */ - -let decoder - -export default { - decode (html: string): string { - decoder = decoder || document.createElement('div') - decoder.innerHTML = html - return decoder.textContent - } -} diff --git a/1.Vue/src/compiler/parser/filter-parser.js b/1.Vue/src/compiler/parser/filter-parser.js deleted file mode 100644 index 10939d3..0000000 --- a/1.Vue/src/compiler/parser/filter-parser.js +++ /dev/null @@ -1,97 +0,0 @@ -/* @flow */ - -const validDivisionCharRE = /[\w).+\-_$\]]/ - -export function parseFilters (exp: string): string { - let inSingle = false - let inDouble = false - let inTemplateString = false - let inRegex = false - let curly = 0 - let square = 0 - let paren = 0 - let lastFilterIndex = 0 - let c, prev, i, expression, filters - - for (i = 0; i < exp.length; i++) { - prev = c - c = exp.charCodeAt(i) - if (inSingle) { - if (c === 0x27 && prev !== 0x5C) inSingle = false - } else if (inDouble) { - if (c === 0x22 && prev !== 0x5C) inDouble = false - } else if (inTemplateString) { - if (c === 0x60 && prev !== 0x5C) inTemplateString = false - } else if (inRegex) { - if (c === 0x2f && prev !== 0x5C) inRegex = false - } else if ( - c === 0x7C && // pipe - exp.charCodeAt(i + 1) !== 0x7C && - exp.charCodeAt(i - 1) !== 0x7C && - !curly && !square && !paren - ) { - if (expression === undefined) { - // first filter, end of expression - lastFilterIndex = i + 1 - expression = exp.slice(0, i).trim() - } else { - pushFilter() - } - } else { - switch (c) { - case 0x22: inDouble = true; break // " - case 0x27: inSingle = true; break // ' - case 0x60: inTemplateString = true; break // ` - case 0x28: paren++; break // ( - case 0x29: paren--; break // ) - case 0x5B: square++; break // [ - case 0x5D: square--; break // ] - case 0x7B: curly++; break // { - case 0x7D: curly--; break // } - } - if (c === 0x2f) { // / - let j = i - 1 - let p - // find first non-whitespace prev char - for (; j >= 0; j--) { - p = exp.charAt(j) - if (p !== ' ') break - } - if (!p || !validDivisionCharRE.test(p)) { - inRegex = true - } - } - } - } - - if (expression === undefined) { - expression = exp.slice(0, i).trim() - } else if (lastFilterIndex !== 0) { - pushFilter() - } - - function pushFilter () { - (filters || (filters = [])).push(exp.slice(lastFilterIndex, i).trim()) - lastFilterIndex = i + 1 - } - - if (filters) { - for (i = 0; i < filters.length; i++) { - expression = wrapFilter(expression, filters[i]) - } - } - - return expression -} - -function wrapFilter (exp: string, filter: string): string { - const i = filter.indexOf('(') - if (i < 0) { - // _f: resolveFilter - return `_f("${filter}")(${exp})` - } else { - const name = filter.slice(0, i) - const args = filter.slice(i + 1) - return `_f("${name}")(${exp}${args !== ')' ? ',' + args : args}` - } -} diff --git a/1.Vue/src/compiler/parser/html-parser.js b/1.Vue/src/compiler/parser/html-parser.js deleted file mode 100644 index f93c098..0000000 --- a/1.Vue/src/compiler/parser/html-parser.js +++ /dev/null @@ -1,306 +0,0 @@ -/** - * Not type-checking this file because it's mostly vendor code. - */ - -/*! - * HTML Parser By John Resig (ejohn.org) - * Modified by Juriy "kangax" Zaytsev - * Original code by Erik Arvidsson, Mozilla Public License - * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js - */ - -import { makeMap, no } from 'shared/util' -import { isNonPhrasingTag } from 'web/compiler/util' -import { unicodeRegExp } from 'core/util/lang' - -// Regular Expressions for parsing tags and attributes -const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/ -const dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/ -const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z${unicodeRegExp.source}]*` -const qnameCapture = `((?:${ncname}\\:)?${ncname})` -const startTagOpen = new RegExp(`^<${qnameCapture}`) -const startTagClose = /^\s*(\/?)>/ -const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`) -const doctype = /^]+>/i -// #7298: escape - to avoid being pased as HTML comment when inlined in page -const comment = /^', - '"': '"', - '&': '&', - ' ': '\n', - ' ': '\t', - ''': "'" -} -const encodedAttr = /&(?:lt|gt|quot|amp|#39);/g -const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#39|#10|#9);/g - -// #5992 -const isIgnoreNewlineTag = makeMap('pre,textarea', true) -const shouldIgnoreFirstNewline = (tag, html) => tag && isIgnoreNewlineTag(tag) && html[0] === '\n' - -function decodeAttr (value, shouldDecodeNewlines) { - const re = shouldDecodeNewlines ? encodedAttrWithNewLines : encodedAttr - return value.replace(re, match => decodingMap[match]) -} - -export function parseHTML (html, options) { - const stack = [] - const expectHTML = options.expectHTML - const isUnaryTag = options.isUnaryTag || no - const canBeLeftOpenTag = options.canBeLeftOpenTag || no - let index = 0 - let last, lastTag - while (html) { - last = html - // Make sure we're not in a plaintext content element like script/style - if (!lastTag || !isPlainTextElement(lastTag)) { - let textEnd = html.indexOf('<') - if (textEnd === 0) { - // Comment: - if (comment.test(html)) { - const commentEnd = html.indexOf('-->') - - if (commentEnd >= 0) { - if (options.shouldKeepComment) { - options.comment(html.substring(4, commentEnd), index, index + commentEnd + 3) - } - advance(commentEnd + 3) - continue - } - } - - // http://en.wikipedia.org/wiki/Conditional_comment#Downlevel-revealed_conditional_comment - if (conditionalComment.test(html)) { - const conditionalEnd = html.indexOf(']>') - - if (conditionalEnd >= 0) { - advance(conditionalEnd + 2) - continue - } - } - - // Doctype: - const doctypeMatch = html.match(doctype) - if (doctypeMatch) { - advance(doctypeMatch[0].length) - continue - } - - // End tag: - const endTagMatch = html.match(endTag) - if (endTagMatch) { - const curIndex = index - advance(endTagMatch[0].length) - parseEndTag(endTagMatch[1], curIndex, index) - continue - } - - // Start tag: - const startTagMatch = parseStartTag() - if (startTagMatch) { - handleStartTag(startTagMatch) - if (shouldIgnoreFirstNewline(startTagMatch.tagName, html)) { - advance(1) - } - continue - } - } - - let text, rest, next - if (textEnd >= 0) { - rest = html.slice(textEnd) - while ( - !endTag.test(rest) && - !startTagOpen.test(rest) && - !comment.test(rest) && - !conditionalComment.test(rest) - ) { - // < in plain text, be forgiving and treat it as text - next = rest.indexOf('<', 1) - if (next < 0) break - textEnd += next - rest = html.slice(textEnd) - } - text = html.substring(0, textEnd) - } - - if (textEnd < 0) { - text = html - } - - if (text) { - advance(text.length) - } - - if (options.chars && text) { - options.chars(text, index - text.length, index) - } - } else { - let endTagLength = 0 - const stackedTag = lastTag.toLowerCase() - const reStackedTag = reCache[stackedTag] || (reCache[stackedTag] = new RegExp('([\\s\\S]*?)(]*>)', 'i')) - const rest = html.replace(reStackedTag, function (all, text, endTag) { - endTagLength = endTag.length - if (!isPlainTextElement(stackedTag) && stackedTag !== 'noscript') { - text = text - .replace(//g, '$1') // #7298 - .replace(//g, '$1') - } - if (shouldIgnoreFirstNewline(stackedTag, text)) { - text = text.slice(1) - } - if (options.chars) { - options.chars(text) - } - return '' - }) - index += html.length - rest.length - html = rest - parseEndTag(stackedTag, index - endTagLength, index) - } - - if (html === last) { - options.chars && options.chars(html) - if (process.env.NODE_ENV !== 'production' && !stack.length && options.warn) { - options.warn(`Mal-formatted tag at end of template: "${html}"`, { start: index + html.length }) - } - break - } - } - - // Clean up any remaining tags - parseEndTag() - - function advance (n) { - index += n - html = html.substring(n) - } - - function parseStartTag () { - const start = html.match(startTagOpen) - if (start) { - const match = { - tagName: start[1], - attrs: [], - start: index - } - advance(start[0].length) - let end, attr - while (!(end = html.match(startTagClose)) && (attr = html.match(dynamicArgAttribute) || html.match(attribute))) { - attr.start = index - advance(attr[0].length) - attr.end = index - match.attrs.push(attr) - } - if (end) { - match.unarySlash = end[1] - advance(end[0].length) - match.end = index - return match - } - } - } - - function handleStartTag (match) { - const tagName = match.tagName - const unarySlash = match.unarySlash - - if (expectHTML) { - if (lastTag === 'p' && isNonPhrasingTag(tagName)) { - parseEndTag(lastTag) - } - if (canBeLeftOpenTag(tagName) && lastTag === tagName) { - parseEndTag(tagName) - } - } - - const unary = isUnaryTag(tagName) || !!unarySlash - - const l = match.attrs.length - const attrs = new Array(l) - for (let i = 0; i < l; i++) { - const args = match.attrs[i] - const value = args[3] || args[4] || args[5] || '' - const shouldDecodeNewlines = tagName === 'a' && args[1] === 'href' - ? options.shouldDecodeNewlinesForHref - : options.shouldDecodeNewlines - attrs[i] = { - name: args[1], - value: decodeAttr(value, shouldDecodeNewlines) - } - if (process.env.NODE_ENV !== 'production' && options.outputSourceRange) { - attrs[i].start = args.start + args[0].match(/^\s*/).length - attrs[i].end = args.end - } - } - - if (!unary) { - stack.push({ tag: tagName, lowerCasedTag: tagName.toLowerCase(), attrs: attrs, start: match.start, end: match.end }) - lastTag = tagName - } - - if (options.start) { - options.start(tagName, attrs, unary, match.start, match.end) - } - } - - function parseEndTag (tagName, start, end) { - let pos, lowerCasedTagName - if (start == null) start = index - if (end == null) end = index - - // Find the closest opened tag of the same type - if (tagName) { - lowerCasedTagName = tagName.toLowerCase() - for (pos = stack.length - 1; pos >= 0; pos--) { - if (stack[pos].lowerCasedTag === lowerCasedTagName) { - break - } - } - } else { - // If no tag name is provided, clean shop - pos = 0 - } - - if (pos >= 0) { - // Close all the open elements, up the stack - for (let i = stack.length - 1; i >= pos; i--) { - if (process.env.NODE_ENV !== 'production' && - (i > pos || !tagName) && - options.warn - ) { - options.warn( - `tag <${stack[i].tag}> has no matching end tag.`, - { start: stack[i].start, end: stack[i].end } - ) - } - if (options.end) { - options.end(stack[i].tag, start, end) - } - } - - // Remove the open elements from the stack - stack.length = pos - lastTag = pos && stack[pos - 1].tag - } else if (lowerCasedTagName === 'br') { - if (options.start) { - options.start(tagName, [], true, start, end) - } - } else if (lowerCasedTagName === 'p') { - if (options.start) { - options.start(tagName, [], false, start, end) - } - if (options.end) { - options.end(tagName, start, end) - } - } - } -} diff --git a/1.Vue/src/compiler/parser/index.js b/1.Vue/src/compiler/parser/index.js deleted file mode 100644 index fb25875..0000000 --- a/1.Vue/src/compiler/parser/index.js +++ /dev/null @@ -1,975 +0,0 @@ -/* @flow */ - -import he from 'he' -import { parseHTML } from './html-parser' -import { parseText } from './text-parser' -import { parseFilters } from './filter-parser' -import { genAssignmentCode } from '../directives/model' -import { extend, cached, no, camelize, hyphenate } from 'shared/util' -import { isIE, isEdge, isServerRendering } from 'core/util/env' - -import { - addProp, - addAttr, - baseWarn, - addHandler, - addDirective, - getBindingAttr, - getAndRemoveAttr, - getRawBindingAttr, - pluckModuleFunction, - getAndRemoveAttrByRegex -} from '../helpers' - -export const onRE = /^@|^v-on:/ -export const dirRE = process.env.VBIND_PROP_SHORTHAND - ? /^v-|^@|^:|^\./ - : /^v-|^@|^:/ -export const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/ -export const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/ -const stripParensRE = /^\(|\)$/g -const dynamicArgRE = /^\[.*\]$/ - -const argRE = /:(.*)$/ -export const bindRE = /^:|^\.|^v-bind:/ -const propBindRE = /^\./ -const modifierRE = /\.[^.\]]+(?=[^\]]*$)/g - -const slotRE = /^v-slot(:|$)|^#/ - -const lineBreakRE = /[\r\n]/ -const whitespaceRE = /\s+/g - -const invalidAttributeRE = /[\s"'<>\/=]/ - -const decodeHTMLCached = cached(he.decode) - -export const emptySlotScopeToken = `_empty_` - -// configurable state -export let warn: any -let delimiters -let transforms -let preTransforms -let postTransforms -let platformIsPreTag -let platformMustUseProp -let platformGetTagNamespace -let maybeComponent - -export function createASTElement ( - tag: string, - attrs: Array, - parent: ASTElement | void -): ASTElement { - return { - type: 1, - tag, - attrsList: attrs, - attrsMap: makeAttrsMap(attrs), - rawAttrsMap: {}, - parent, - children: [] - } -} - -/** - * Convert HTML string to AST. - */ -export function parse ( - template: string, - options: CompilerOptions -): ASTElement | void { - warn = options.warn || baseWarn - - platformIsPreTag = options.isPreTag || no - platformMustUseProp = options.mustUseProp || no - platformGetTagNamespace = options.getTagNamespace || no - const isReservedTag = options.isReservedTag || no - maybeComponent = (el: ASTElement) => !!el.component || !isReservedTag(el.tag) - - transforms = pluckModuleFunction(options.modules, 'transformNode') - preTransforms = pluckModuleFunction(options.modules, 'preTransformNode') - postTransforms = pluckModuleFunction(options.modules, 'postTransformNode') - - delimiters = options.delimiters - - const stack = [] - const preserveWhitespace = options.preserveWhitespace !== false - const whitespaceOption = options.whitespace - let root - let currentParent - let inVPre = false - let inPre = false - let warned = false - - function warnOnce (msg, range) { - if (!warned) { - warned = true - warn(msg, range) - } - } - - function closeElement (element) { - trimEndingWhitespace(element) - if (!inVPre && !element.processed) { - element = processElement(element, options) - } - // tree management - if (!stack.length && element !== root) { - // allow root elements with v-if, v-else-if and v-else - if (root.if && (element.elseif || element.else)) { - if (process.env.NODE_ENV !== 'production') { - checkRootConstraints(element) - } - addIfCondition(root, { - exp: element.elseif, - block: element - }) - } else if (process.env.NODE_ENV !== 'production') { - warnOnce( - `Component template should contain exactly one root element. ` + - `If you are using v-if on multiple elements, ` + - `use v-else-if to chain them instead.`, - { start: element.start } - ) - } - } - if (currentParent && !element.forbidden) { - if (element.elseif || element.else) { - processIfConditions(element, currentParent) - } else { - if (element.slotScope) { - // scoped slot - // keep it in the children list so that v-else(-if) conditions can - // find it as the prev node. - const name = element.slotTarget || '"default"' - ;(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element - } - currentParent.children.push(element) - element.parent = currentParent - } - } - - // final children cleanup - // filter out scoped slots - element.children = element.children.filter(c => !(c: any).slotScope) - // remove trailing whitespace node again - trimEndingWhitespace(element) - - // check pre state - if (element.pre) { - inVPre = false - } - if (platformIsPreTag(element.tag)) { - inPre = false - } - // apply post-transforms - for (let i = 0; i < postTransforms.length; i++) { - postTransforms[i](element, options) - } - } - - function trimEndingWhitespace (el) { - // remove trailing whitespace node - if (!inPre) { - let lastNode - while ( - (lastNode = el.children[el.children.length - 1]) && - lastNode.type === 3 && - lastNode.text === ' ' - ) { - el.children.pop() - } - } - } - - function checkRootConstraints (el) { - if (el.tag === 'slot' || el.tag === 'template') { - warnOnce( - `Cannot use <${el.tag}> as component root element because it may ` + - 'contain multiple nodes.', - { start: el.start } - ) - } - if (el.attrsMap.hasOwnProperty('v-for')) { - warnOnce( - 'Cannot use v-for on stateful component root element because ' + - 'it renders multiple elements.', - el.rawAttrsMap['v-for'] - ) - } - } - - parseHTML(template, { - warn, - expectHTML: options.expectHTML, - isUnaryTag: options.isUnaryTag, - canBeLeftOpenTag: options.canBeLeftOpenTag, - shouldDecodeNewlines: options.shouldDecodeNewlines, - shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref, - shouldKeepComment: options.comments, - outputSourceRange: options.outputSourceRange, - start (tag, attrs, unary, start, end) { - // check namespace. - // inherit parent ns if there is one - const ns = (currentParent && currentParent.ns) || platformGetTagNamespace(tag) - - // handle IE svg bug - /* istanbul ignore if */ - if (isIE && ns === 'svg') { - attrs = guardIESVGBug(attrs) - } - - let element: ASTElement = createASTElement(tag, attrs, currentParent) - if (ns) { - element.ns = ns - } - - if (process.env.NODE_ENV !== 'production') { - if (options.outputSourceRange) { - element.start = start - element.end = end - element.rawAttrsMap = element.attrsList.reduce((cumulated, attr) => { - cumulated[attr.name] = attr - return cumulated - }, {}) - } - attrs.forEach(attr => { - if (invalidAttributeRE.test(attr.name)) { - warn( - `Invalid dynamic argument expression: attribute names cannot contain ` + - `spaces, quotes, <, >, / or =.`, - { - start: attr.start + attr.name.indexOf(`[`), - end: attr.start + attr.name.length - } - ) - } - }) - } - - if (isForbiddenTag(element) && !isServerRendering()) { - element.forbidden = true - process.env.NODE_ENV !== 'production' && warn( - 'Templates should only be responsible for mapping the state to the ' + - 'UI. Avoid placing tags with side-effects in your templates, such as ' + - `<${tag}>` + ', as they will not be parsed.', - { start: element.start } - ) - } - - // apply pre-transforms - for (let i = 0; i < preTransforms.length; i++) { - element = preTransforms[i](element, options) || element - } - - if (!inVPre) { - processPre(element) - if (element.pre) { - inVPre = true - } - } - if (platformIsPreTag(element.tag)) { - inPre = true - } - if (inVPre) { - processRawAttrs(element) - } else if (!element.processed) { - // structural directives - processFor(element) - processIf(element) - processOnce(element) - } - - if (!root) { - root = element - if (process.env.NODE_ENV !== 'production') { - checkRootConstraints(root) - } - } - - if (!unary) { - currentParent = element - stack.push(element) - } else { - closeElement(element) - } - }, - - end (tag, start, end) { - const element = stack[stack.length - 1] - // pop stack - stack.length -= 1 - currentParent = stack[stack.length - 1] - if (process.env.NODE_ENV !== 'production' && options.outputSourceRange) { - element.end = end - } - closeElement(element) - }, - - chars (text: string, start: number, end: number) { - if (!currentParent) { - if (process.env.NODE_ENV !== 'production') { - if (text === template) { - warnOnce( - 'Component template requires a root element, rather than just text.', - { start } - ) - } else if ((text = text.trim())) { - warnOnce( - `text "${text}" outside root element will be ignored.`, - { start } - ) - } - } - return - } - // IE textarea placeholder bug - /* istanbul ignore if */ - if (isIE && - currentParent.tag === 'textarea' && - currentParent.attrsMap.placeholder === text - ) { - return - } - const children = currentParent.children - if (inPre || text.trim()) { - text = isTextTag(currentParent) ? text : decodeHTMLCached(text) - } else if (!children.length) { - // remove the whitespace-only node right after an opening tag - text = '' - } else if (whitespaceOption) { - if (whitespaceOption === 'condense') { - // in condense mode, remove the whitespace node if it contains - // line break, otherwise condense to a single space - text = lineBreakRE.test(text) ? '' : ' ' - } else { - text = ' ' - } - } else { - text = preserveWhitespace ? ' ' : '' - } - if (text) { - if (!inPre && whitespaceOption === 'condense') { - // condense consecutive whitespaces into single space - text = text.replace(whitespaceRE, ' ') - } - let res - let child: ?ASTNode - if (!inVPre && text !== ' ' && (res = parseText(text, delimiters))) { - child = { - type: 2, - expression: res.expression, - tokens: res.tokens, - text - } - } else if (text !== ' ' || !children.length || children[children.length - 1].text !== ' ') { - child = { - type: 3, - text - } - } - if (child) { - if (process.env.NODE_ENV !== 'production' && options.outputSourceRange) { - child.start = start - child.end = end - } - children.push(child) - } - } - }, - comment (text: string, start, end) { - // adding anyting as a sibling to the root node is forbidden - // comments should still be allowed, but ignored - if (currentParent) { - const child: ASTText = { - type: 3, - text, - isComment: true - } - if (process.env.NODE_ENV !== 'production' && options.outputSourceRange) { - child.start = start - child.end = end - } - currentParent.children.push(child) - } - } - }) - return root -} - -function processPre (el) { - if (getAndRemoveAttr(el, 'v-pre') != null) { - el.pre = true - } -} - -function processRawAttrs (el) { - const list = el.attrsList - const len = list.length - if (len) { - const attrs: Array = el.attrs = new Array(len) - for (let i = 0; i < len; i++) { - attrs[i] = { - name: list[i].name, - value: JSON.stringify(list[i].value) - } - if (list[i].start != null) { - attrs[i].start = list[i].start - attrs[i].end = list[i].end - } - } - } else if (!el.pre) { - // non root node in pre blocks with no attributes - el.plain = true - } -} - -export function processElement ( - element: ASTElement, - options: CompilerOptions -) { - processKey(element) - - // determine whether this is a plain element after - // removing structural attributes - element.plain = ( - !element.key && - !element.scopedSlots && - !element.attrsList.length - ) - - processRef(element) - processSlotContent(element) - processSlotOutlet(element) - processComponent(element) - for (let i = 0; i < transforms.length; i++) { - element = transforms[i](element, options) || element - } - processAttrs(element) - return element -} - -function processKey (el) { - const exp = getBindingAttr(el, 'key') - if (exp) { - if (process.env.NODE_ENV !== 'production') { - if (el.tag === 'template') { - warn( - `