refactor: option merging + extract helper functions
This commit is contained in:
parent
7bc28a6e61
commit
149d82d618
@ -3,7 +3,6 @@ import {
|
|||||||
Component,
|
Component,
|
||||||
render,
|
render,
|
||||||
nodeOps,
|
nodeOps,
|
||||||
ComponentInstance,
|
|
||||||
observable,
|
observable,
|
||||||
nextTick
|
nextTick
|
||||||
} from '@vue/renderer-test'
|
} from '@vue/renderer-test'
|
||||||
@ -41,7 +40,7 @@ describe('Parent chain management', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const root = nodeOps.createElement('div')
|
const root = nodeOps.createElement('div')
|
||||||
const parent = render(h(Parent), root) as ComponentInstance
|
const parent = render(h(Parent), root) as Component
|
||||||
|
|
||||||
expect(child.$parent).toBe(parent)
|
expect(child.$parent).toBe(parent)
|
||||||
expect(child.$root).toBe(parent)
|
expect(child.$root).toBe(parent)
|
||||||
@ -100,7 +99,7 @@ describe('Parent chain management', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const root = nodeOps.createElement('div')
|
const root = nodeOps.createElement('div')
|
||||||
const parent = render(h(Parent), root) as ComponentInstance
|
const parent = render(h(Parent), root) as Component
|
||||||
|
|
||||||
expect(child.$parent).toBe(parent)
|
expect(child.$parent).toBe(parent)
|
||||||
expect(child.$root).toBe(parent)
|
expect(child.$root).toBe(parent)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { EMPTY_OBJ, NOOP } from './utils'
|
import { EMPTY_OBJ, NOOP, isArray } from '@vue/shared'
|
||||||
import { VNode, Slots, RenderNode, MountedVNode } from './vdom'
|
import { VNode, Slots, RenderNode, MountedVNode } from './vdom'
|
||||||
import {
|
import {
|
||||||
Data,
|
Data,
|
||||||
@ -44,30 +44,30 @@ interface PublicInstanceMethods {
|
|||||||
$emit(name: string, ...payload: any[]): this
|
$emit(name: string, ...payload: any[]): this
|
||||||
}
|
}
|
||||||
|
|
||||||
interface APIMethods<P, D> {
|
export interface APIMethods<P = {}, D = {}> {
|
||||||
data?(): Partial<D>
|
data(): Partial<D>
|
||||||
render(props: Readonly<P>, slots: Slots, attrs: Data, parentVNode: VNode): any
|
render(props: Readonly<P>, slots: Slots, attrs: Data, parentVNode: VNode): any
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LifecycleMethods {
|
export interface LifecycleMethods {
|
||||||
beforeCreate?(): void
|
beforeCreate(): void
|
||||||
created?(): void
|
created(): void
|
||||||
beforeMount?(): void
|
beforeMount(): void
|
||||||
mounted?(): void
|
mounted(): void
|
||||||
beforeUpdate?(vnode: VNode): void
|
beforeUpdate(vnode: VNode): void
|
||||||
updated?(vnode: VNode): void
|
updated(vnode: VNode): void
|
||||||
beforeUnmount?(): void
|
beforeUnmount(): void
|
||||||
unmounted?(): void
|
unmounted(): void
|
||||||
errorCaptured?(): (
|
errorCaptured(): (
|
||||||
err: Error,
|
err: Error,
|
||||||
type: ErrorTypes,
|
type: ErrorTypes,
|
||||||
instance: ComponentInstance | null,
|
instance: ComponentInstance | null,
|
||||||
vnode: VNode
|
vnode: VNode
|
||||||
) => boolean | void
|
) => boolean | void
|
||||||
activated?(): void
|
activated(): void
|
||||||
deactivated?(): void
|
deactivated(): void
|
||||||
renderTracked?(e: DebuggerEvent): void
|
renderTracked(e: DebuggerEvent): void
|
||||||
renderTriggered?(e: DebuggerEvent): void
|
renderTriggered(e: DebuggerEvent): void
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ComponentClass extends ComponentClassOptions {
|
export interface ComponentClass extends ComponentClassOptions {
|
||||||
@ -88,9 +88,10 @@ export type ComponentType = ComponentClass | FunctionalComponent
|
|||||||
// It extends InternalComponent with mounted instance properties.
|
// It extends InternalComponent with mounted instance properties.
|
||||||
export interface ComponentInstance<P = {}, D = {}>
|
export interface ComponentInstance<P = {}, D = {}>
|
||||||
extends InternalComponent,
|
extends InternalComponent,
|
||||||
APIMethods<P, D>,
|
Partial<APIMethods<P, D>>,
|
||||||
LifecycleMethods {
|
Partial<LifecycleMethods> {
|
||||||
constructor: ComponentClass
|
constructor: ComponentClass
|
||||||
|
render: APIMethods<P, D>['render']
|
||||||
|
|
||||||
$vnode: MountedVNode
|
$vnode: MountedVNode
|
||||||
$data: D
|
$data: D
|
||||||
@ -157,7 +158,7 @@ class InternalComponent implements PublicInstanceMethods {
|
|||||||
|
|
||||||
// eventEmitter interface
|
// eventEmitter interface
|
||||||
$on(event: string, fn: Function): this {
|
$on(event: string, fn: Function): this {
|
||||||
if (Array.isArray(event)) {
|
if (isArray(event)) {
|
||||||
for (let i = 0; i < event.length; i++) {
|
for (let i = 0; i < event.length; i++) {
|
||||||
this.$on(event[i], fn)
|
this.$on(event[i], fn)
|
||||||
}
|
}
|
||||||
@ -181,7 +182,7 @@ class InternalComponent implements PublicInstanceMethods {
|
|||||||
if (this._events) {
|
if (this._events) {
|
||||||
if (!event && !fn) {
|
if (!event && !fn) {
|
||||||
this._events = null
|
this._events = null
|
||||||
} else if (Array.isArray(event)) {
|
} else if (isArray(event)) {
|
||||||
for (let i = 0; i < event.length; i++) {
|
for (let i = 0; i < event.length; i++) {
|
||||||
this.$off(event[i], fn)
|
this.$off(event[i], fn)
|
||||||
}
|
}
|
||||||
@ -223,7 +224,7 @@ class InternalComponent implements PublicInstanceMethods {
|
|||||||
|
|
||||||
function invokeListeners(value: Function | Function[], payload: any[]) {
|
function invokeListeners(value: Function | Function[], payload: any[]) {
|
||||||
// TODO handle error
|
// TODO handle error
|
||||||
if (Array.isArray(value)) {
|
if (isArray(value)) {
|
||||||
for (let i = 0; i < value.length; i++) {
|
for (let i = 0; i < value.length; i++) {
|
||||||
value[i](...payload)
|
value[i](...payload)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { NOOP } from './utils'
|
import { NOOP, isFunction } from '@vue/shared'
|
||||||
import { computed, stop, ComputedGetter } from '@vue/observer'
|
import { computed, stop, ComputedGetter } from '@vue/observer'
|
||||||
import { ComponentInstance } from './component'
|
import { ComponentInstance } from './component'
|
||||||
import { ComponentComputedOptions } from './componentOptions'
|
import { ComponentComputedOptions } from './componentOptions'
|
||||||
@ -17,7 +17,7 @@ export function initializeComputed(
|
|||||||
const proxy = instance.$proxy
|
const proxy = instance.$proxy
|
||||||
for (const key in computedOptions) {
|
for (const key in computedOptions) {
|
||||||
const option = computedOptions[key]
|
const option = computedOptions[key]
|
||||||
const getter = typeof option === 'function' ? option : option.get || NOOP
|
const getter = isFunction(option) ? option : option.get || NOOP
|
||||||
handles[key] = computed(getter, proxy)
|
handles[key] = computed(getter, proxy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
import { ComponentInstance } from './component'
|
import {
|
||||||
|
ComponentInstance,
|
||||||
|
ComponentClass,
|
||||||
|
APIMethods,
|
||||||
|
LifecycleMethods
|
||||||
|
} from './component'
|
||||||
import { Slots } from './vdom'
|
import { Slots } from './vdom'
|
||||||
|
import { isArray, isObject, isFunction } from '@vue/shared'
|
||||||
|
import { normalizePropsOptions } from './componentProps'
|
||||||
|
|
||||||
export type Data = Record<string, any>
|
export type Data = Record<string, any>
|
||||||
|
|
||||||
@ -73,3 +80,100 @@ export interface WatchOptions {
|
|||||||
deep?: boolean
|
deep?: boolean
|
||||||
immediate?: boolean
|
immediate?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ReservedKeys = { [K in keyof (APIMethods & LifecycleMethods)]: 1 }
|
||||||
|
|
||||||
|
export const reservedMethods: ReservedKeys = {
|
||||||
|
data: 1,
|
||||||
|
render: 1,
|
||||||
|
beforeCreate: 1,
|
||||||
|
created: 1,
|
||||||
|
beforeMount: 1,
|
||||||
|
mounted: 1,
|
||||||
|
beforeUpdate: 1,
|
||||||
|
updated: 1,
|
||||||
|
beforeUnmount: 1,
|
||||||
|
unmounted: 1,
|
||||||
|
errorCaptured: 1,
|
||||||
|
activated: 1,
|
||||||
|
deactivated: 1,
|
||||||
|
renderTracked: 1,
|
||||||
|
renderTriggered: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is called in the base component constructor and the return value is
|
||||||
|
// set on the instance as $options.
|
||||||
|
export function resolveComponentOptionsFromClass(
|
||||||
|
Component: ComponentClass
|
||||||
|
): ComponentOptions {
|
||||||
|
if (Component.options) {
|
||||||
|
return Component.options
|
||||||
|
}
|
||||||
|
const staticDescriptors = Object.getOwnPropertyDescriptors(Component)
|
||||||
|
const options = {} as any
|
||||||
|
for (const key in staticDescriptors) {
|
||||||
|
const { enumerable, get, value } = staticDescriptors[key]
|
||||||
|
if (enumerable || get) {
|
||||||
|
options[key] = get ? get() : value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const instanceDescriptors = Object.getOwnPropertyDescriptors(
|
||||||
|
Component.prototype
|
||||||
|
)
|
||||||
|
for (const key in instanceDescriptors) {
|
||||||
|
const { get, value } = instanceDescriptors[key]
|
||||||
|
if (get) {
|
||||||
|
// computed properties
|
||||||
|
;(options.computed || (options.computed = {}))[key] = get
|
||||||
|
// there's no need to do anything for the setter
|
||||||
|
// as it's already defined on the prototype
|
||||||
|
} else if (isFunction(value)) {
|
||||||
|
if (key in reservedMethods) {
|
||||||
|
options[key] = value
|
||||||
|
} else {
|
||||||
|
;(options.methods || (options.methods = {}))[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
options.props = normalizePropsOptions(options.props)
|
||||||
|
Component.options = options
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mergeComponentOptions(to: any, from: any): ComponentOptions {
|
||||||
|
const res: any = Object.assign({}, to)
|
||||||
|
if (from.mixins) {
|
||||||
|
from.mixins.forEach((mixin: any) => {
|
||||||
|
from = mergeComponentOptions(from, mixin)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for (const key in from) {
|
||||||
|
const value = from[key]
|
||||||
|
const existing = res[key]
|
||||||
|
if (isFunction(value) && isFunction(existing)) {
|
||||||
|
if (key === 'data') {
|
||||||
|
// for data we need to merge the returned value
|
||||||
|
res[key] = function() {
|
||||||
|
return Object.assign(existing(), value())
|
||||||
|
}
|
||||||
|
} else if (/^render|^errorCaptured/.test(key)) {
|
||||||
|
// render, renderTracked, renderTriggered & errorCaptured
|
||||||
|
// are never merged
|
||||||
|
res[key] = value
|
||||||
|
} else {
|
||||||
|
// merge lifecycle hooks
|
||||||
|
res[key] = function(...args: any[]) {
|
||||||
|
existing.call(this, ...args)
|
||||||
|
value.call(this, ...args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (isArray(value) && isArray(existing)) {
|
||||||
|
res[key] = existing.concat(value)
|
||||||
|
} else if (isObject(value) && isObject(existing)) {
|
||||||
|
res[key] = Object.assign({}, existing, value)
|
||||||
|
} else {
|
||||||
|
res[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
@ -2,19 +2,40 @@ import { immutable, unwrap, lock, unlock } from '@vue/observer'
|
|||||||
import { ComponentInstance } from './component'
|
import { ComponentInstance } from './component'
|
||||||
import {
|
import {
|
||||||
Data,
|
Data,
|
||||||
ComponentPropsOptions,
|
|
||||||
PropOptions,
|
PropOptions,
|
||||||
Prop,
|
Prop,
|
||||||
PropType
|
PropType,
|
||||||
|
ComponentPropsOptions
|
||||||
} from './componentOptions'
|
} from './componentOptions'
|
||||||
import { EMPTY_OBJ, camelize, hyphenate, capitalize } from './utils'
|
import {
|
||||||
|
EMPTY_OBJ,
|
||||||
|
camelize,
|
||||||
|
hyphenate,
|
||||||
|
capitalize,
|
||||||
|
isString,
|
||||||
|
isFunction,
|
||||||
|
isArray,
|
||||||
|
isObject
|
||||||
|
} from '@vue/shared'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
|
|
||||||
const EMPTY_PROPS = { props: EMPTY_OBJ }
|
const EMPTY_PROPS = { props: EMPTY_OBJ }
|
||||||
|
|
||||||
|
const enum BooleanFlags {
|
||||||
|
shouldCast = '1',
|
||||||
|
shouldCastTrue = '2'
|
||||||
|
}
|
||||||
|
|
||||||
|
type NormalizedProp = PropOptions & {
|
||||||
|
[BooleanFlags.shouldCast]?: boolean
|
||||||
|
[BooleanFlags.shouldCastTrue]?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
type NormalizedPropsOptions = Record<string, NormalizedProp>
|
||||||
|
|
||||||
export function initializeProps(
|
export function initializeProps(
|
||||||
instance: ComponentInstance,
|
instance: ComponentInstance,
|
||||||
options: ComponentPropsOptions | undefined,
|
options: NormalizedPropsOptions | undefined,
|
||||||
data: Data | null
|
data: Data | null
|
||||||
) {
|
) {
|
||||||
const { props, attrs } = resolveProps(data, options)
|
const { props, attrs } = resolveProps(data, options)
|
||||||
@ -31,13 +52,13 @@ export function initializeProps(
|
|||||||
// - else: everything goes in `props`.
|
// - else: everything goes in `props`.
|
||||||
export function resolveProps(
|
export function resolveProps(
|
||||||
rawData: any,
|
rawData: any,
|
||||||
rawOptions: ComponentPropsOptions | void
|
_options: NormalizedPropsOptions | void
|
||||||
): { props: Data; attrs?: Data } {
|
): { props: Data; attrs?: Data } {
|
||||||
const hasDeclaredProps = rawOptions !== void 0
|
const hasDeclaredProps = _options !== void 0
|
||||||
|
const options = _options as NormalizedPropsOptions
|
||||||
if (!rawData && !hasDeclaredProps) {
|
if (!rawData && !hasDeclaredProps) {
|
||||||
return EMPTY_PROPS
|
return EMPTY_PROPS
|
||||||
}
|
}
|
||||||
const options = normalizePropsOptions(rawOptions) as NormalizedPropsOptions
|
|
||||||
const props: any = {}
|
const props: any = {}
|
||||||
let attrs: any = void 0
|
let attrs: any = void 0
|
||||||
if (rawData != null) {
|
if (rawData != null) {
|
||||||
@ -66,8 +87,7 @@ export function resolveProps(
|
|||||||
// default values
|
// default values
|
||||||
if (hasDefault && currentValue === void 0) {
|
if (hasDefault && currentValue === void 0) {
|
||||||
const defaultValue = opt.default
|
const defaultValue = opt.default
|
||||||
props[key] =
|
props[key] = isFunction(defaultValue) ? defaultValue() : defaultValue
|
||||||
typeof defaultValue === 'function' ? defaultValue() : defaultValue
|
|
||||||
}
|
}
|
||||||
// boolean casting
|
// boolean casting
|
||||||
if (opt[BooleanFlags.shouldCast]) {
|
if (opt[BooleanFlags.shouldCast]) {
|
||||||
@ -129,58 +149,34 @@ export function updateProps(instance: ComponentInstance, nextData: Data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const enum BooleanFlags {
|
export function normalizePropsOptions(
|
||||||
shouldCast = '1',
|
|
||||||
shouldCastTrue = '2'
|
|
||||||
}
|
|
||||||
|
|
||||||
type NormalizedProp = PropOptions & {
|
|
||||||
[BooleanFlags.shouldCast]?: boolean
|
|
||||||
[BooleanFlags.shouldCastTrue]?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
type NormalizedPropsOptions = Record<string, NormalizedProp>
|
|
||||||
|
|
||||||
const normalizationCache = new WeakMap<
|
|
||||||
ComponentPropsOptions,
|
|
||||||
NormalizedPropsOptions
|
|
||||||
>()
|
|
||||||
|
|
||||||
function normalizePropsOptions(
|
|
||||||
raw: ComponentPropsOptions | void
|
raw: ComponentPropsOptions | void
|
||||||
): NormalizedPropsOptions {
|
): NormalizedPropsOptions | void {
|
||||||
if (!raw) {
|
if (!raw) {
|
||||||
return EMPTY_OBJ
|
return
|
||||||
}
|
|
||||||
const hit = normalizationCache.get(raw)
|
|
||||||
if (hit) {
|
|
||||||
return hit
|
|
||||||
}
|
}
|
||||||
const normalized: NormalizedPropsOptions = {}
|
const normalized: NormalizedPropsOptions = {}
|
||||||
if (Array.isArray(raw)) {
|
if (isArray(raw)) {
|
||||||
for (let i = 0; i < raw.length; i++) {
|
for (let i = 0; i < raw.length; i++) {
|
||||||
if (__DEV__ && typeof raw !== 'string') {
|
if (__DEV__ && !isString(raw[i])) {
|
||||||
warn(`props must be strings when using array syntax.`)
|
warn(`props must be strings when using array syntax.`, raw[i])
|
||||||
}
|
}
|
||||||
normalized[camelize(raw[i])] = EMPTY_OBJ
|
normalized[camelize(raw[i])] = EMPTY_OBJ
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (__DEV__ && typeof raw !== 'object') {
|
if (__DEV__ && !isObject(raw)) {
|
||||||
warn(`invalid props options`, raw)
|
warn(`invalid props options`, raw)
|
||||||
}
|
}
|
||||||
for (const key in raw) {
|
for (const key in raw) {
|
||||||
const opt = raw[key]
|
const opt = raw[key]
|
||||||
const prop = (normalized[camelize(key)] =
|
const prop = (normalized[camelize(key)] =
|
||||||
Array.isArray(opt) || typeof opt === 'function'
|
isArray(opt) || isFunction(opt) ? { type: opt } : opt) as NormalizedProp
|
||||||
? { type: opt }
|
|
||||||
: opt) as NormalizedProp
|
|
||||||
const booleanIndex = getTypeIndex(Boolean, prop.type)
|
const booleanIndex = getTypeIndex(Boolean, prop.type)
|
||||||
const stringIndex = getTypeIndex(String, prop.type)
|
const stringIndex = getTypeIndex(String, prop.type)
|
||||||
prop[BooleanFlags.shouldCast] = booleanIndex > -1
|
prop[BooleanFlags.shouldCast] = booleanIndex > -1
|
||||||
prop[BooleanFlags.shouldCastTrue] = booleanIndex < stringIndex
|
prop[BooleanFlags.shouldCastTrue] = booleanIndex < stringIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
normalizationCache.set(raw, normalized)
|
|
||||||
return normalized
|
return normalized
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,13 +195,13 @@ function getTypeIndex(
|
|||||||
type: Prop<any>,
|
type: Prop<any>,
|
||||||
expectedTypes: PropType<any> | void | null | true
|
expectedTypes: PropType<any> | void | null | true
|
||||||
): number {
|
): number {
|
||||||
if (Array.isArray(expectedTypes)) {
|
if (isArray(expectedTypes)) {
|
||||||
for (let i = 0, len = expectedTypes.length; i < len; i++) {
|
for (let i = 0, len = expectedTypes.length; i < len; i++) {
|
||||||
if (isSameType(expectedTypes[i], type)) {
|
if (isSameType(expectedTypes[i], type)) {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (expectedTypes != null && typeof expectedTypes === 'object') {
|
} else if (isObject(expectedTypes)) {
|
||||||
return isSameType(expectedTypes, type) ? 0 : -1
|
return isSameType(expectedTypes, type) ? 0 : -1
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
@ -235,7 +231,7 @@ function validateProp(
|
|||||||
// type check
|
// type check
|
||||||
if (type != null && type !== true) {
|
if (type != null && type !== true) {
|
||||||
let isValid = false
|
let isValid = false
|
||||||
const types = Array.isArray(type) ? type : [type]
|
const types = isArray(type) ? type : [type]
|
||||||
const expectedTypes = []
|
const expectedTypes = []
|
||||||
// value is valid as long as one of the specified types match
|
// value is valid as long as one of the specified types match
|
||||||
for (let i = 0; i < types.length && !isValid; i++) {
|
for (let i = 0; i < types.length && !isValid; i++) {
|
||||||
@ -269,7 +265,7 @@ function assertType(value: any, type: Prop<any>): AssertionResult {
|
|||||||
} else if (expectedType === 'Object') {
|
} else if (expectedType === 'Object') {
|
||||||
valid = toRawType(value) === 'Object'
|
valid = toRawType(value) === 'Object'
|
||||||
} else if (expectedType === 'Array') {
|
} else if (expectedType === 'Array') {
|
||||||
valid = Array.isArray(value)
|
valid = isArray(value)
|
||||||
} else {
|
} else {
|
||||||
valid = value instanceof type
|
valid = value instanceof type
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { ComponentInstance } from './component'
|
import { ComponentInstance } from './component'
|
||||||
|
import { isString, isFunction } from '@vue/shared'
|
||||||
|
|
||||||
const bindCache = new WeakMap()
|
const bindCache = new WeakMap()
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ const renderProxyHandlers = {
|
|||||||
// TODO warn non-present property
|
// TODO warn non-present property
|
||||||
}
|
}
|
||||||
const value = Reflect.get(target, key, receiver)
|
const value = Reflect.get(target, key, receiver)
|
||||||
if (typeof value === 'function') {
|
if (isFunction(value)) {
|
||||||
// auto bind
|
// auto bind
|
||||||
return getBoundMethod(value, target, receiver)
|
return getBoundMethod(value, target, receiver)
|
||||||
} else {
|
} else {
|
||||||
@ -56,7 +57,7 @@ const renderProxyHandlers = {
|
|||||||
receiver: any
|
receiver: any
|
||||||
): boolean {
|
): boolean {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
if (typeof key === 'string' && key[0] === '$') {
|
if (isString(key) && key[0] === '$') {
|
||||||
// TODO warn setting immutable properties
|
// TODO warn setting immutable properties
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// import { EMPTY_OBJ } from './utils'
|
|
||||||
import { ComponentInstance } from './component'
|
import { ComponentInstance } from './component'
|
||||||
import { observable } from '@vue/observer'
|
import { observable } from '@vue/observer'
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { VNodeFlags } from './flags'
|
import { VNodeFlags } from './flags'
|
||||||
import { EMPTY_OBJ } from './utils'
|
import { EMPTY_OBJ, isArray, isFunction, isObject } from '@vue/shared'
|
||||||
import { h } from './h'
|
import { h } from './h'
|
||||||
import { VNode, MountedVNode, createFragment } from './vdom'
|
import { VNode, MountedVNode, createFragment } from './vdom'
|
||||||
import {
|
import {
|
||||||
@ -13,7 +13,10 @@ import { initializeState } from './componentState'
|
|||||||
import { initializeProps, resolveProps } from './componentProps'
|
import { initializeProps, resolveProps } from './componentProps'
|
||||||
import { initializeComputed, teardownComputed } from './componentComputed'
|
import { initializeComputed, teardownComputed } from './componentComputed'
|
||||||
import { initializeWatch, teardownWatch } from './componentWatch'
|
import { initializeWatch, teardownWatch } from './componentWatch'
|
||||||
import { ComponentOptions } from './componentOptions'
|
import {
|
||||||
|
ComponentOptions,
|
||||||
|
resolveComponentOptionsFromClass
|
||||||
|
} from './componentOptions'
|
||||||
import { createRenderProxy } from './componentProxy'
|
import { createRenderProxy } from './componentProxy'
|
||||||
import { handleError, ErrorTypes } from './errorHandling'
|
import { handleError, ErrorTypes } from './errorHandling'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
@ -58,7 +61,7 @@ export function initializeComponentInstance(instance: ComponentInstance) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.$options = resolveComponentOptions(instance.constructor)
|
instance.$options = resolveComponentOptionsFromClass(instance.constructor)
|
||||||
instance.$parentVNode = currentVNode as MountedVNode
|
instance.$parentVNode = currentVNode as MountedVNode
|
||||||
|
|
||||||
// renderProxy
|
// renderProxy
|
||||||
@ -143,9 +146,9 @@ function normalizeComponentRoot(
|
|||||||
): VNode {
|
): VNode {
|
||||||
if (vnode == null) {
|
if (vnode == null) {
|
||||||
vnode = createTextVNode('')
|
vnode = createTextVNode('')
|
||||||
} else if (typeof vnode !== 'object') {
|
} else if (!isObject(vnode)) {
|
||||||
vnode = createTextVNode(vnode + '')
|
vnode = createTextVNode(vnode + '')
|
||||||
} else if (Array.isArray(vnode)) {
|
} else if (isArray(vnode)) {
|
||||||
if (vnode.length === 1) {
|
if (vnode.length === 1) {
|
||||||
vnode = normalizeComponentRoot(vnode[0], componentVNode)
|
vnode = normalizeComponentRoot(vnode[0], componentVNode)
|
||||||
} else {
|
} else {
|
||||||
@ -158,13 +161,13 @@ function normalizeComponentRoot(
|
|||||||
(flags & VNodeFlags.COMPONENT || flags & VNodeFlags.ELEMENT)
|
(flags & VNodeFlags.COMPONENT || flags & VNodeFlags.ELEMENT)
|
||||||
) {
|
) {
|
||||||
if (el) {
|
if (el) {
|
||||||
vnode = cloneVNode(vnode)
|
vnode = cloneVNode(vnode as VNode)
|
||||||
}
|
}
|
||||||
if (flags & VNodeFlags.COMPONENT) {
|
if (flags & VNodeFlags.COMPONENT) {
|
||||||
vnode.parentVNode = componentVNode
|
vnode.parentVNode = componentVNode
|
||||||
}
|
}
|
||||||
} else if (el) {
|
} else if (el) {
|
||||||
vnode = cloneVNode(vnode)
|
vnode = cloneVNode(vnode as VNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vnode
|
return vnode
|
||||||
@ -209,7 +212,7 @@ export function createComponentClassFromOptions(
|
|||||||
// name -> displayName
|
// name -> displayName
|
||||||
if (key === 'name') {
|
if (key === 'name') {
|
||||||
options.displayName = options.name
|
options.displayName = options.name
|
||||||
} else if (typeof value === 'function') {
|
} else if (isFunction(value)) {
|
||||||
// lifecycle hook / data / render
|
// lifecycle hook / data / render
|
||||||
if (__COMPAT__) {
|
if (__COMPAT__) {
|
||||||
if (key === 'render') {
|
if (key === 'render') {
|
||||||
@ -229,7 +232,7 @@ export function createComponentClassFromOptions(
|
|||||||
} else if (key === 'computed') {
|
} else if (key === 'computed') {
|
||||||
for (const computedKey in value) {
|
for (const computedKey in value) {
|
||||||
const computed = value[computedKey]
|
const computed = value[computedKey]
|
||||||
const isGet = typeof computed === 'function'
|
const isGet = isFunction(computed)
|
||||||
Object.defineProperty(proto, computedKey, {
|
Object.defineProperty(proto, computedKey, {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
get: isGet ? computed : computed.get,
|
get: isGet ? computed : computed.get,
|
||||||
@ -250,37 +253,3 @@ export function createComponentClassFromOptions(
|
|||||||
}
|
}
|
||||||
return AnonymousComponent as ComponentClass
|
return AnonymousComponent as ComponentClass
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called in the base component constructor and the return value is
|
|
||||||
// set on the instance as $options.
|
|
||||||
export function resolveComponentOptions(
|
|
||||||
Component: ComponentClass
|
|
||||||
): ComponentOptions {
|
|
||||||
if (Component.options) {
|
|
||||||
return Component.options
|
|
||||||
}
|
|
||||||
const staticDescriptors = Object.getOwnPropertyDescriptors(Component)
|
|
||||||
const options = {} as any
|
|
||||||
for (const key in staticDescriptors) {
|
|
||||||
const { enumerable, get, value } = staticDescriptors[key]
|
|
||||||
if (enumerable || get) {
|
|
||||||
options[key] = get ? get() : value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const instanceDescriptors = Object.getOwnPropertyDescriptors(
|
|
||||||
Component.prototype
|
|
||||||
)
|
|
||||||
for (const key in instanceDescriptors) {
|
|
||||||
const { get, value } = instanceDescriptors[key]
|
|
||||||
if (get) {
|
|
||||||
// computed properties
|
|
||||||
;(options.computed || (options.computed = {}))[key] = get
|
|
||||||
// there's no need to do anything for the setter
|
|
||||||
// as it's already defined on the prototype
|
|
||||||
} else if (typeof value === 'function') {
|
|
||||||
;(options.methods || (options.methods = {}))[key] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Component.options = options
|
|
||||||
return options
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
import { EMPTY_OBJ, NOOP } from './utils'
|
import {
|
||||||
|
EMPTY_OBJ,
|
||||||
|
NOOP,
|
||||||
|
isFunction,
|
||||||
|
isArray,
|
||||||
|
isString,
|
||||||
|
isObject
|
||||||
|
} from '@vue/shared'
|
||||||
import { ComponentInstance } from './component'
|
import { ComponentInstance } from './component'
|
||||||
import { ComponentWatchOptions, WatchOptions } from './componentOptions'
|
import { ComponentWatchOptions, WatchOptions } from './componentOptions'
|
||||||
import { autorun, stop } from '@vue/observer'
|
import { autorun, stop } from '@vue/observer'
|
||||||
@ -13,11 +20,11 @@ export function initializeWatch(
|
|||||||
if (options !== void 0) {
|
if (options !== void 0) {
|
||||||
for (const key in options) {
|
for (const key in options) {
|
||||||
const opt = options[key]
|
const opt = options[key]
|
||||||
if (Array.isArray(opt)) {
|
if (isArray(opt)) {
|
||||||
opt.forEach(o => setupWatcher(instance, key, o))
|
opt.forEach(o => setupWatcher(instance, key, o))
|
||||||
} else if (typeof opt === 'function') {
|
} else if (isFunction(opt)) {
|
||||||
setupWatcher(instance, key, opt)
|
setupWatcher(instance, key, opt)
|
||||||
} else if (typeof opt === 'string') {
|
} else if (isString(opt)) {
|
||||||
setupWatcher(instance, key, (instance as any)[opt])
|
setupWatcher(instance, key, (instance as any)[opt])
|
||||||
} else if (opt.handler) {
|
} else if (opt.handler) {
|
||||||
setupWatcher(instance, key, opt.handler, opt)
|
setupWatcher(instance, key, opt.handler, opt)
|
||||||
@ -35,10 +42,9 @@ export function setupWatcher(
|
|||||||
const handles = instance._watchHandles || (instance._watchHandles = new Set())
|
const handles = instance._watchHandles || (instance._watchHandles = new Set())
|
||||||
const proxy = instance.$proxy
|
const proxy = instance.$proxy
|
||||||
|
|
||||||
const rawGetter =
|
const rawGetter = isString(keyOrFn)
|
||||||
typeof keyOrFn === 'string'
|
? parseDotPath(keyOrFn, proxy)
|
||||||
? parseDotPath(keyOrFn, proxy)
|
: () => keyOrFn.call(proxy)
|
||||||
: () => keyOrFn.call(proxy)
|
|
||||||
|
|
||||||
if (__DEV__ && rawGetter === NOOP) {
|
if (__DEV__ && rawGetter === NOOP) {
|
||||||
warn(
|
warn(
|
||||||
@ -116,11 +122,11 @@ function parseDotPath(path: string, ctx: any): Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function traverse(value: any, seen: Set<any> = new Set()) {
|
function traverse(value: any, seen: Set<any> = new Set()) {
|
||||||
if (value === null || typeof value !== 'object' || seen.has(value)) {
|
if (!isObject(value) || seen.has(value)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
seen.add(value)
|
seen.add(value)
|
||||||
if (Array.isArray(value)) {
|
if (isArray(value)) {
|
||||||
for (let i = 0; i < value.length; i++) {
|
for (let i = 0; i < value.length; i++) {
|
||||||
traverse(value[i], seen)
|
traverse(value[i], seen)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { autorun, stop } from '@vue/observer'
|
import { autorun, stop } from '@vue/observer'
|
||||||
import { queueJob } from '@vue/scheduler'
|
import { queueJob } from '@vue/scheduler'
|
||||||
import { VNodeFlags, ChildrenFlags } from './flags'
|
import { VNodeFlags, ChildrenFlags } from './flags'
|
||||||
import { EMPTY_OBJ, reservedPropRE, lis } from './utils'
|
import { EMPTY_OBJ, reservedPropRE, isString } from '@vue/shared'
|
||||||
import {
|
import {
|
||||||
VNode,
|
VNode,
|
||||||
MountedVNode,
|
MountedVNode,
|
||||||
@ -297,7 +297,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
contextVNode: MountedVNode | null
|
contextVNode: MountedVNode | null
|
||||||
) {
|
) {
|
||||||
const { tag, children, childFlags, ref } = vnode
|
const { tag, children, childFlags, ref } = vnode
|
||||||
const target = typeof tag === 'string' ? platformQuerySelector(tag) : tag
|
const target = isString(tag) ? platformQuerySelector(tag) : tag
|
||||||
|
|
||||||
if (__DEV__ && !target) {
|
if (__DEV__ && !target) {
|
||||||
// TODO warn poartal target not found
|
// TODO warn poartal target not found
|
||||||
@ -1410,3 +1410,49 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
|
|
||||||
return { render }
|
return { render }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://en.wikipedia.org/wiki/Longest_increasing_subsequence
|
||||||
|
export function lis(arr: number[]): number[] {
|
||||||
|
const p = arr.slice()
|
||||||
|
const result = [0]
|
||||||
|
let i
|
||||||
|
let j
|
||||||
|
let u
|
||||||
|
let v
|
||||||
|
let c
|
||||||
|
const len = arr.length
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
const arrI = arr[i]
|
||||||
|
if (arrI !== 0) {
|
||||||
|
j = result[result.length - 1]
|
||||||
|
if (arr[j] < arrI) {
|
||||||
|
p[i] = j
|
||||||
|
result.push(i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
u = 0
|
||||||
|
v = result.length - 1
|
||||||
|
while (u < v) {
|
||||||
|
c = ((u + v) / 2) | 0
|
||||||
|
if (arr[result[c]] < arrI) {
|
||||||
|
u = c + 1
|
||||||
|
} else {
|
||||||
|
v = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (arrI < arr[result[u]]) {
|
||||||
|
if (u > 0) {
|
||||||
|
p[i] = result[u - 1]
|
||||||
|
}
|
||||||
|
result[u] = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
u = result.length
|
||||||
|
v = result[u - 1]
|
||||||
|
while (u-- > 0) {
|
||||||
|
result[u] = v
|
||||||
|
v = p[v]
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
} from './vdom'
|
} from './vdom'
|
||||||
import { isObservable } from '@vue/observer'
|
import { isObservable } from '@vue/observer'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
|
import { isString, isArray, isFunction, isObject } from '@vue/shared'
|
||||||
|
|
||||||
export const Fragment = Symbol()
|
export const Fragment = Symbol()
|
||||||
export const Portal = Symbol()
|
export const Portal = Symbol()
|
||||||
@ -98,10 +99,7 @@ interface createElement extends VNodeFactories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const h = ((tag: ElementType, data?: any, children?: any): VNode => {
|
export const h = ((tag: ElementType, data?: any, children?: any): VNode => {
|
||||||
if (
|
if (isArray(data) || !isObject(data) || data._isVNode) {
|
||||||
Array.isArray(data) ||
|
|
||||||
(data != null && (typeof data !== 'object' || data._isVNode))
|
|
||||||
) {
|
|
||||||
children = data
|
children = data
|
||||||
data = null
|
data = null
|
||||||
}
|
}
|
||||||
@ -133,7 +131,7 @@ export const h = ((tag: ElementType, data?: any, children?: any): VNode => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof tag === 'string') {
|
if (isString(tag)) {
|
||||||
// element
|
// element
|
||||||
return createElementVNode(
|
return createElementVNode(
|
||||||
tag,
|
tag,
|
||||||
@ -160,10 +158,7 @@ export const h = ((tag: ElementType, data?: any, children?: any): VNode => {
|
|||||||
ref
|
ref
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (__DEV__ && !isFunction(tag) && !isObject(tag)) {
|
||||||
__DEV__ &&
|
|
||||||
(!tag || (typeof tag !== 'function' && typeof tag !== 'object'))
|
|
||||||
) {
|
|
||||||
warn('Invalid component passed to h(): ', tag)
|
warn('Invalid component passed to h(): ', tag)
|
||||||
}
|
}
|
||||||
// component
|
// component
|
||||||
|
@ -10,21 +10,26 @@ export * from '@vue/observer'
|
|||||||
// Scheduler API
|
// Scheduler API
|
||||||
export { nextTick } from '@vue/scheduler'
|
export { nextTick } from '@vue/scheduler'
|
||||||
|
|
||||||
// Internal API
|
|
||||||
export {
|
|
||||||
createComponentInstance,
|
|
||||||
createComponentClassFromOptions
|
|
||||||
} from './componentUtils'
|
|
||||||
|
|
||||||
// Optional APIs
|
// Optional APIs
|
||||||
// these are imported on-demand and can be tree-shaken
|
// these are imported on-demand and can be tree-shaken
|
||||||
export { applyDirectives } from './optional/directive'
|
export { applyDirectives } from './optional/directive'
|
||||||
export { Provide, Inject } from './optional/context'
|
export { Provide, Inject } from './optional/context'
|
||||||
export { createAsyncComponent } from './optional/asyncComponent'
|
export { createAsyncComponent } from './optional/asyncComponent'
|
||||||
export { KeepAlive } from './optional/keepAlive'
|
export { KeepAlive } from './optional/keepAlive'
|
||||||
|
export { mixins } from './optional/mixin'
|
||||||
|
|
||||||
// flags & types
|
// flags & types
|
||||||
export { ComponentType, ComponentClass, FunctionalComponent } from './component'
|
export { ComponentType, ComponentClass, FunctionalComponent } from './component'
|
||||||
export * from './componentOptions'
|
|
||||||
export { VNodeFlags, ChildrenFlags } from './flags'
|
export { VNodeFlags, ChildrenFlags } from './flags'
|
||||||
export { VNode, Slots } from './vdom'
|
export { VNode, Slots } from './vdom'
|
||||||
|
|
||||||
|
// Internal API, for libraries or renderers that need to perform low level work
|
||||||
|
export {
|
||||||
|
reservedMethods,
|
||||||
|
resolveComponentOptionsFromClass,
|
||||||
|
mergeComponentOptions
|
||||||
|
} from './componentOptions'
|
||||||
|
export {
|
||||||
|
createComponentInstance,
|
||||||
|
createComponentClassFromOptions
|
||||||
|
} from './componentUtils'
|
||||||
|
@ -2,6 +2,7 @@ import { ChildrenFlags } from '../flags'
|
|||||||
import { createComponentVNode, Slots } from '../vdom'
|
import { createComponentVNode, Slots } from '../vdom'
|
||||||
import { Component, ComponentType, ComponentClass } from '../component'
|
import { Component, ComponentType, ComponentClass } from '../component'
|
||||||
import { unwrap } from '@vue/observer'
|
import { unwrap } from '@vue/observer'
|
||||||
|
import { isFunction } from '@vue/shared'
|
||||||
|
|
||||||
interface AsyncComponentFactory {
|
interface AsyncComponentFactory {
|
||||||
(): Promise<ComponentType>
|
(): Promise<ComponentType>
|
||||||
@ -21,7 +22,7 @@ type AsyncComponentOptions = AsyncComponentFactory | AsyncComponentFullOptions
|
|||||||
export function createAsyncComponent(
|
export function createAsyncComponent(
|
||||||
options: AsyncComponentOptions
|
options: AsyncComponentOptions
|
||||||
): ComponentClass {
|
): ComponentClass {
|
||||||
if (typeof options === 'function') {
|
if (isFunction(options)) {
|
||||||
options = { factory: options }
|
options = { factory: options }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ return applyDirectives(
|
|||||||
|
|
||||||
import { VNode, cloneVNode, VNodeData } from '../vdom'
|
import { VNode, cloneVNode, VNodeData } from '../vdom'
|
||||||
import { ComponentInstance } from '../component'
|
import { ComponentInstance } from '../component'
|
||||||
import { EMPTY_OBJ } from '../utils'
|
import { EMPTY_OBJ } from '@vue/shared'
|
||||||
|
|
||||||
interface DirectiveBinding {
|
interface DirectiveBinding {
|
||||||
instance: ComponentInstance
|
instance: ComponentInstance
|
||||||
|
@ -2,6 +2,7 @@ import { Component, ComponentClass, ComponentInstance } from '../component'
|
|||||||
import { VNode, Slots, cloneVNode } from '../vdom'
|
import { VNode, Slots, cloneVNode } from '../vdom'
|
||||||
import { VNodeFlags } from '../flags'
|
import { VNodeFlags } from '../flags'
|
||||||
import { warn } from '../warning'
|
import { warn } from '../warning'
|
||||||
|
import { isString, isArray } from '@vue/shared'
|
||||||
|
|
||||||
type MatchPattern = string | RegExp | string[] | RegExp[]
|
type MatchPattern = string | RegExp | string[] | RegExp[]
|
||||||
|
|
||||||
@ -119,9 +120,9 @@ function getName(comp: ComponentClass): string | void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function matches(pattern: MatchPattern, name: string): boolean {
|
function matches(pattern: MatchPattern, name: string): boolean {
|
||||||
if (Array.isArray(pattern)) {
|
if (isArray(pattern)) {
|
||||||
return (pattern as any).some((p: string | RegExp) => matches(p, name))
|
return (pattern as any).some((p: string | RegExp) => matches(p, name))
|
||||||
} else if (typeof pattern === 'string') {
|
} else if (isString(pattern)) {
|
||||||
return pattern.split(',').indexOf(name) > -1
|
return pattern.split(',').indexOf(name) > -1
|
||||||
} else if (pattern.test) {
|
} else if (pattern.test) {
|
||||||
return pattern.test(name)
|
return pattern.test(name)
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
import { Component } from '../component'
|
import { Component } from '../component'
|
||||||
|
import { createComponentClassFromOptions } from '../componentUtils'
|
||||||
|
import {
|
||||||
|
ComponentOptions,
|
||||||
|
resolveComponentOptionsFromClass,
|
||||||
|
mergeComponentOptions
|
||||||
|
} from '../componentOptions'
|
||||||
|
import { normalizePropsOptions } from '../componentProps'
|
||||||
|
import { isFunction } from '@vue/shared'
|
||||||
|
|
||||||
interface ComponentConstructor<This = Component> {
|
interface ComponentConstructor<This = Component> {
|
||||||
new (): This
|
new (): This
|
||||||
@ -25,7 +33,19 @@ export function mixins<
|
|||||||
V = ExtractInstance<T>
|
V = ExtractInstance<T>
|
||||||
>(...args: T): ComponentConstructorWithMixins<V>
|
>(...args: T): ComponentConstructorWithMixins<V>
|
||||||
export function mixins(...args: any[]): any {
|
export function mixins(...args: any[]): any {
|
||||||
// TODO
|
let options: ComponentOptions = {}
|
||||||
|
args.forEach(mixin => {
|
||||||
|
if (isFunction(mixin)) {
|
||||||
|
options = mergeComponentOptions(
|
||||||
|
options,
|
||||||
|
resolveComponentOptionsFromClass(mixin)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
mixin.props = normalizePropsOptions(mixin.props)
|
||||||
|
options = mergeComponentOptions(options, mixin)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return createComponentClassFromOptions(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Example usage
|
/* Example usage
|
||||||
|
@ -1,105 +0,0 @@
|
|||||||
export const EMPTY_OBJ: { readonly [key: string]: any } = Object.freeze({})
|
|
||||||
|
|
||||||
export const NOOP = () => {}
|
|
||||||
|
|
||||||
export const onRE = /^on/
|
|
||||||
export const vnodeHookRE = /^vnode/
|
|
||||||
export const handlersRE = /^on|^vnode/
|
|
||||||
export const reservedPropRE = /^(?:key|ref|slots)$|^vnode/
|
|
||||||
|
|
||||||
export function normalizeStyle(
|
|
||||||
value: any
|
|
||||||
): Record<string, string | number> | void {
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
const res: Record<string, string | number> = {}
|
|
||||||
for (let i = 0; i < value.length; i++) {
|
|
||||||
const normalized = normalizeStyle(value[i])
|
|
||||||
if (normalized) {
|
|
||||||
for (const key in normalized) {
|
|
||||||
res[key] = normalized[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
} else if (value && typeof value === 'object') {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function normalizeClass(value: any): string {
|
|
||||||
let res = ''
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
res = value
|
|
||||||
} else if (Array.isArray(value)) {
|
|
||||||
for (let i = 0; i < value.length; i++) {
|
|
||||||
res += normalizeClass(value[i]) + ' '
|
|
||||||
}
|
|
||||||
} else if (typeof value === 'object') {
|
|
||||||
for (const name in value) {
|
|
||||||
if (value[name]) {
|
|
||||||
res += name + ' '
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res.trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
const camelizeRE = /-(\w)/g
|
|
||||||
export const camelize = (str: string): string => {
|
|
||||||
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''))
|
|
||||||
}
|
|
||||||
|
|
||||||
const hyphenateRE = /\B([A-Z])/g
|
|
||||||
export const hyphenate = (str: string): string => {
|
|
||||||
return str.replace(hyphenateRE, '-$1').toLowerCase()
|
|
||||||
}
|
|
||||||
|
|
||||||
export const capitalize = (str: string): string => {
|
|
||||||
return str.charAt(0).toUpperCase() + str.slice(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://en.wikipedia.org/wiki/Longest_increasing_subsequence
|
|
||||||
export function lis(arr: number[]): number[] {
|
|
||||||
const p = arr.slice()
|
|
||||||
const result = [0]
|
|
||||||
let i
|
|
||||||
let j
|
|
||||||
let u
|
|
||||||
let v
|
|
||||||
let c
|
|
||||||
const len = arr.length
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
const arrI = arr[i]
|
|
||||||
if (arrI !== 0) {
|
|
||||||
j = result[result.length - 1]
|
|
||||||
if (arr[j] < arrI) {
|
|
||||||
p[i] = j
|
|
||||||
result.push(i)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
u = 0
|
|
||||||
v = result.length - 1
|
|
||||||
while (u < v) {
|
|
||||||
c = ((u + v) / 2) | 0
|
|
||||||
if (arr[result[c]] < arrI) {
|
|
||||||
u = c + 1
|
|
||||||
} else {
|
|
||||||
v = c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (arrI < arr[result[u]]) {
|
|
||||||
if (u > 0) {
|
|
||||||
p[i] = result[u - 1]
|
|
||||||
}
|
|
||||||
result[u] = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
u = result.length
|
|
||||||
v = result[u - 1]
|
|
||||||
while (u-- > 0) {
|
|
||||||
result[u] = v
|
|
||||||
v = p[v]
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
@ -5,7 +5,14 @@ import {
|
|||||||
} from './component'
|
} from './component'
|
||||||
import { VNodeFlags, ChildrenFlags } from './flags'
|
import { VNodeFlags, ChildrenFlags } from './flags'
|
||||||
import { createComponentClassFromOptions } from './componentUtils'
|
import { createComponentClassFromOptions } from './componentUtils'
|
||||||
import { normalizeClass, normalizeStyle, handlersRE, EMPTY_OBJ } from './utils'
|
import {
|
||||||
|
handlersRE,
|
||||||
|
EMPTY_OBJ,
|
||||||
|
isObject,
|
||||||
|
isArray,
|
||||||
|
isFunction,
|
||||||
|
isString
|
||||||
|
} from '@vue/shared'
|
||||||
import { RawChildrenType, RawSlots } from './h'
|
import { RawChildrenType, RawSlots } from './h'
|
||||||
|
|
||||||
// Vue core is platform agnostic, so we are not using Element for "DOM" nodes.
|
// Vue core is platform agnostic, so we are not using Element for "DOM" nodes.
|
||||||
@ -98,15 +105,6 @@ export function createVNode(
|
|||||||
return vnode
|
return vnode
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeClassAndStyle(data: VNodeData) {
|
|
||||||
if (data.class != null) {
|
|
||||||
data.class = normalizeClass(data.class)
|
|
||||||
}
|
|
||||||
if (data.style != null) {
|
|
||||||
data.style = normalizeStyle(data.style)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createElementVNode(
|
export function createElementVNode(
|
||||||
tag: string,
|
tag: string,
|
||||||
data: VNodeData | null,
|
data: VNodeData | null,
|
||||||
@ -122,6 +120,50 @@ export function createElementVNode(
|
|||||||
return createVNode(flags, tag, data, children, childFlags, key, ref, null)
|
return createVNode(flags, tag, data, children, childFlags, key, ref, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeClassAndStyle(data: VNodeData) {
|
||||||
|
if (data.class != null) {
|
||||||
|
data.class = normalizeClass(data.class)
|
||||||
|
}
|
||||||
|
if (data.style != null) {
|
||||||
|
data.style = normalizeStyle(data.style)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeStyle(value: any): Record<string, string | number> | void {
|
||||||
|
if (isArray(value)) {
|
||||||
|
const res: Record<string, string | number> = {}
|
||||||
|
for (let i = 0; i < value.length; i++) {
|
||||||
|
const normalized = normalizeStyle(value[i])
|
||||||
|
if (normalized) {
|
||||||
|
for (const key in normalized) {
|
||||||
|
res[key] = normalized[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
} else if (isObject(value)) {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeClass(value: any): string {
|
||||||
|
let res = ''
|
||||||
|
if (isString(value)) {
|
||||||
|
res = value
|
||||||
|
} else if (isArray(value)) {
|
||||||
|
for (let i = 0; i < value.length; i++) {
|
||||||
|
res += normalizeClass(value[i]) + ' '
|
||||||
|
}
|
||||||
|
} else if (isObject(value)) {
|
||||||
|
for (const name in value) {
|
||||||
|
if (value[name]) {
|
||||||
|
res += name + ' '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res.trim()
|
||||||
|
}
|
||||||
|
|
||||||
export function createComponentVNode(
|
export function createComponentVNode(
|
||||||
comp: any,
|
comp: any,
|
||||||
data: VNodeData | null,
|
data: VNodeData | null,
|
||||||
@ -134,8 +176,7 @@ export function createComponentVNode(
|
|||||||
let flags: VNodeFlags
|
let flags: VNodeFlags
|
||||||
|
|
||||||
// flags
|
// flags
|
||||||
const compType = typeof comp
|
if (isObject(comp)) {
|
||||||
if (compType === 'object') {
|
|
||||||
if (comp.functional) {
|
if (comp.functional) {
|
||||||
// object literal functional
|
// object literal functional
|
||||||
flags = VNodeFlags.COMPONENT_FUNCTIONAL
|
flags = VNodeFlags.COMPONENT_FUNCTIONAL
|
||||||
@ -155,7 +196,7 @@ export function createComponentVNode(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// assumes comp is function here now
|
// assumes comp is function here now
|
||||||
if (__DEV__ && compType !== 'function') {
|
if (__DEV__ && !isFunction(comp)) {
|
||||||
// TODO warn invalid comp value in dev
|
// TODO warn invalid comp value in dev
|
||||||
}
|
}
|
||||||
if (comp.prototype && comp.prototype.render) {
|
if (comp.prototype && comp.prototype.render) {
|
||||||
@ -178,14 +219,13 @@ export function createComponentVNode(
|
|||||||
? ChildrenFlags.DYNAMIC_SLOTS
|
? ChildrenFlags.DYNAMIC_SLOTS
|
||||||
: ChildrenFlags.NO_CHILDREN
|
: ChildrenFlags.NO_CHILDREN
|
||||||
if (children != null) {
|
if (children != null) {
|
||||||
const childrenType = typeof children
|
if (isFunction(children)) {
|
||||||
if (childrenType === 'function') {
|
|
||||||
// function as children
|
// function as children
|
||||||
slots = { default: children }
|
slots = { default: children }
|
||||||
} else if (Array.isArray(children) || (children as any)._isVNode) {
|
} else if (isArray(children) || (children as any)._isVNode) {
|
||||||
// direct vnode children
|
// direct vnode children
|
||||||
slots = { default: () => children }
|
slots = { default: () => children }
|
||||||
} else if (typeof children === 'object') {
|
} else if (isObject(children)) {
|
||||||
// slot object as children
|
// slot object as children
|
||||||
slots = children
|
slots = children
|
||||||
}
|
}
|
||||||
@ -313,7 +353,7 @@ export function cloneVNode(vnode: VNode, extraData?: VNodeData): VNode {
|
|||||||
|
|
||||||
function normalizeChildren(vnode: VNode, children: any) {
|
function normalizeChildren(vnode: VNode, children: any) {
|
||||||
let childFlags
|
let childFlags
|
||||||
if (Array.isArray(children)) {
|
if (isArray(children)) {
|
||||||
const { length } = children
|
const { length } = children
|
||||||
if (length === 0) {
|
if (length === 0) {
|
||||||
childFlags = ChildrenFlags.NO_CHILDREN
|
childFlags = ChildrenFlags.NO_CHILDREN
|
||||||
@ -356,7 +396,7 @@ export function normalizeVNodes(
|
|||||||
newChild = createTextVNode('')
|
newChild = createTextVNode('')
|
||||||
} else if (child._isVNode) {
|
} else if (child._isVNode) {
|
||||||
newChild = child.el ? cloneVNode(child) : child
|
newChild = child.el ? cloneVNode(child) : child
|
||||||
} else if (Array.isArray(child)) {
|
} else if (isArray(child)) {
|
||||||
normalizeVNodes(child, newChildren, currentPrefix + i + '|')
|
normalizeVNodes(child, newChildren, currentPrefix + i + '|')
|
||||||
} else {
|
} else {
|
||||||
newChild = createTextVNode(child + '')
|
newChild = createTextVNode(child + '')
|
||||||
@ -386,7 +426,7 @@ function normalizeSlots(slots: { [name: string]: any }): Slots {
|
|||||||
function normalizeSlot(value: any): VNode[] {
|
function normalizeSlot(value: any): VNode[] {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return [createTextVNode('')]
|
return [createTextVNode('')]
|
||||||
} else if (Array.isArray(value)) {
|
} else if (isArray(value)) {
|
||||||
return normalizeVNodes(value)
|
return normalizeVNodes(value)
|
||||||
} else if (value._isVNode) {
|
} else if (value._isVNode) {
|
||||||
return [value]
|
return [value]
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ComponentType, ComponentClass, FunctionalComponent } from './component'
|
import { ComponentType, ComponentClass, FunctionalComponent } from './component'
|
||||||
import { EMPTY_OBJ } from './utils'
|
import { EMPTY_OBJ, isString } from '@vue/shared'
|
||||||
import { VNode } from './vdom'
|
import { VNode } from './vdom'
|
||||||
import { Data } from './componentOptions'
|
import { Data } from './componentOptions'
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ function formatProps(props: Data) {
|
|||||||
const res = []
|
const res = []
|
||||||
for (const key in props) {
|
for (const key in props) {
|
||||||
const value = props[key]
|
const value = props[key]
|
||||||
if (typeof value === 'string') {
|
if (isString(value)) {
|
||||||
res.push(`${key}=${JSON.stringify(value)}`)
|
res.push(`${key}=${JSON.stringify(value)}`)
|
||||||
} else {
|
} else {
|
||||||
res.push(`${key}=`, value)
|
res.push(`${key}=`, value)
|
||||||
|
@ -2,6 +2,7 @@ import { observable, immutable, unwrap } from './index'
|
|||||||
import { OperationTypes } from './operations'
|
import { OperationTypes } from './operations'
|
||||||
import { track, trigger } from './autorun'
|
import { track, trigger } from './autorun'
|
||||||
import { LOCKED } from './lock'
|
import { LOCKED } from './lock'
|
||||||
|
import { isObject } from '@vue/shared'
|
||||||
|
|
||||||
const hasOwnProperty = Object.prototype.hasOwnProperty
|
const hasOwnProperty = Object.prototype.hasOwnProperty
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ function createGetter(isImmutable: boolean) {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
track(target, OperationTypes.GET, key)
|
track(target, OperationTypes.GET, key)
|
||||||
return res !== null && typeof res === 'object'
|
return isObject(res)
|
||||||
? isImmutable
|
? isImmutable
|
||||||
? // need to lazy access immutable and observable here to avoid
|
? // need to lazy access immutable and observable here to avoid
|
||||||
// circular dependency
|
// circular dependency
|
||||||
|
@ -2,8 +2,8 @@ import { unwrap, observable, immutable } from './index'
|
|||||||
import { track, trigger } from './autorun'
|
import { track, trigger } from './autorun'
|
||||||
import { OperationTypes } from './operations'
|
import { OperationTypes } from './operations'
|
||||||
import { LOCKED } from './lock'
|
import { LOCKED } from './lock'
|
||||||
|
import { isObject } from '@vue/shared'
|
||||||
|
|
||||||
const isObject = (value: any) => value !== null && typeof value === 'object'
|
|
||||||
const toObservable = (value: any) =>
|
const toObservable = (value: any) =>
|
||||||
isObject(value) ? observable(value) : value
|
isObject(value) ? observable(value) : value
|
||||||
const toImmutable = (value: any) => (isObject(value) ? immutable(value) : value)
|
const toImmutable = (value: any) => (isObject(value) ? immutable(value) : value)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { isObject, EMPTY_OBJ } from '@vue/shared'
|
||||||
import { mutableHandlers, immutableHandlers } from './baseHandlers'
|
import { mutableHandlers, immutableHandlers } from './baseHandlers'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -28,7 +29,6 @@ export { OperationTypes } from './operations'
|
|||||||
export { computed, ComputedGetter } from './computed'
|
export { computed, ComputedGetter } from './computed'
|
||||||
export { lock, unlock } from './lock'
|
export { lock, unlock } from './lock'
|
||||||
|
|
||||||
const EMPTY_OBJ = {}
|
|
||||||
const collectionTypes: Set<any> = new Set([Set, Map, WeakMap, WeakSet])
|
const collectionTypes: Set<any> = new Set([Set, Map, WeakMap, WeakSet])
|
||||||
const observableValueRE = /^\[object (?:Object|Array|Map|Set|WeakMap|WeakSet)\]$/
|
const observableValueRE = /^\[object (?:Object|Array|Map|Set|WeakMap|WeakSet)\]$/
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ function createObservable(
|
|||||||
baseHandlers: ProxyHandler<any>,
|
baseHandlers: ProxyHandler<any>,
|
||||||
collectionHandlers: ProxyHandler<any>
|
collectionHandlers: ProxyHandler<any>
|
||||||
) {
|
) {
|
||||||
if (target === null || typeof target !== 'object') {
|
if (!isObject(target)) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
console.warn(`value is not observable: ${String(target)}`)
|
console.warn(`value is not observable: ${String(target)}`)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { createRenderer, VNode, ComponentInstance } from '@vue/core'
|
import { createRenderer, VNode, Component } from '@vue/core'
|
||||||
import { nodeOps } from './nodeOps'
|
import { nodeOps } from './nodeOps'
|
||||||
import { patchData } from './patchData'
|
import { patchData } from './patchData'
|
||||||
import { teardownVNode } from './teardownVNode'
|
import { teardownVNode } from './teardownVNode'
|
||||||
@ -12,7 +12,7 @@ const { render: _render } = createRenderer({
|
|||||||
type publicRender = (
|
type publicRender = (
|
||||||
node: VNode | null,
|
node: VNode | null,
|
||||||
container: HTMLElement
|
container: HTMLElement
|
||||||
) => ComponentInstance | null
|
) => Component | null
|
||||||
export const render = _render as publicRender
|
export const render = _render as publicRender
|
||||||
|
|
||||||
// re-export everything from core
|
// re-export everything from core
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { isString } from '@vue/shared'
|
||||||
|
|
||||||
// style properties that should NOT have "px" added when numeric
|
// style properties that should NOT have "px" added when numeric
|
||||||
const nonNumericRE = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i
|
const nonNumericRE = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i
|
||||||
|
|
||||||
@ -5,7 +7,7 @@ export function patchStyle(el: any, prev: any, next: any, data: any) {
|
|||||||
const { style } = el
|
const { style } = el
|
||||||
if (!next) {
|
if (!next) {
|
||||||
el.removeAttribute('style')
|
el.removeAttribute('style')
|
||||||
} else if (typeof next === 'string') {
|
} else if (isString(next)) {
|
||||||
style.cssText = next
|
style.cssText = next
|
||||||
} else {
|
} else {
|
||||||
for (const key in next) {
|
for (const key in next) {
|
||||||
@ -15,7 +17,7 @@ export function patchStyle(el: any, prev: any, next: any, data: any) {
|
|||||||
}
|
}
|
||||||
style[key] = value
|
style[key] = value
|
||||||
}
|
}
|
||||||
if (prev && typeof prev !== 'string') {
|
if (prev && !isString(prev)) {
|
||||||
for (const key in prev) {
|
for (const key in prev) {
|
||||||
if (!next[key]) {
|
if (!next[key]) {
|
||||||
style[key] = ''
|
style[key] = ''
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { createRenderer, VNode, ComponentInstance } from '@vue/core'
|
import { createRenderer, VNode, Component } from '@vue/core'
|
||||||
import { nodeOps, TestElement } from './nodeOps'
|
import { nodeOps, TestElement } from './nodeOps'
|
||||||
import { patchData } from './patchData'
|
import { patchData } from './patchData'
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ const { render: _render } = createRenderer({
|
|||||||
type publicRender = (
|
type publicRender = (
|
||||||
node: VNode | null,
|
node: VNode | null,
|
||||||
container: TestElement
|
container: TestElement
|
||||||
) => ComponentInstance | null
|
) => Component | null
|
||||||
export const render = _render as publicRender
|
export const render = _render as publicRender
|
||||||
|
|
||||||
export { serialize } from './serialize'
|
export { serialize } from './serialize'
|
||||||
|
1
packages/shared/README.md
Normal file
1
packages/shared/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# @vue/shared
|
4
packages/shared/package.json
Normal file
4
packages/shared/package.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"name": "@vue/shared",
|
||||||
|
"private": true
|
||||||
|
}
|
29
packages/shared/src/index.ts
Normal file
29
packages/shared/src/index.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
export const EMPTY_OBJ: { readonly [key: string]: any } = Object.freeze({})
|
||||||
|
|
||||||
|
export const NOOP = () => {}
|
||||||
|
|
||||||
|
export const onRE = /^on/
|
||||||
|
export const vnodeHookRE = /^vnode/
|
||||||
|
export const handlersRE = /^on|^vnode/
|
||||||
|
export const reservedPropRE = /^(?:key|ref|slots)$|^vnode/
|
||||||
|
|
||||||
|
export const isArray = Array.isArray
|
||||||
|
export const isFunction = (val: any): val is Function =>
|
||||||
|
typeof val === 'function'
|
||||||
|
export const isString = (val: any): val is string => typeof val === 'string'
|
||||||
|
export const isObject = (val: any): val is Record<any, any> =>
|
||||||
|
val !== null && typeof val === 'object'
|
||||||
|
|
||||||
|
const camelizeRE = /-(\w)/g
|
||||||
|
export const camelize = (str: string): string => {
|
||||||
|
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''))
|
||||||
|
}
|
||||||
|
|
||||||
|
const hyphenateRE = /\B([A-Z])/g
|
||||||
|
export const hyphenate = (str: string): string => {
|
||||||
|
return str.replace(hyphenateRE, '-$1').toLowerCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const capitalize = (str: string): string => {
|
||||||
|
return str.charAt(0).toUpperCase() + str.slice(1)
|
||||||
|
}
|
@ -16,7 +16,7 @@ class Vue {
|
|||||||
// convert it to a class
|
// convert it to a class
|
||||||
const Component = createComponentClassFromOptions(options || {})
|
const Component = createComponentClassFromOptions(options || {})
|
||||||
const vnode = h(Component)
|
const vnode = h(Component)
|
||||||
const instance = createComponentInstance(vnode, Component, null)
|
const instance = createComponentInstance(vnode, Component)
|
||||||
|
|
||||||
function mount(el: any) {
|
function mount(el: any) {
|
||||||
const dom = typeof el === 'string' ? document.querySelector(el) : el
|
const dom = typeof el === 'string' ? document.querySelector(el) : el
|
||||||
|
@ -95,12 +95,13 @@ function createConfig(output, plugins = []) {
|
|||||||
// during a single build.
|
// during a single build.
|
||||||
hasTSChecked = true
|
hasTSChecked = true
|
||||||
|
|
||||||
|
const externals = Object.keys(aliasOptions).filter(p => p !== '@vue/shared')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
input: resolve(`src/index.ts`),
|
input: resolve(`src/index.ts`),
|
||||||
// Global and Browser ESM builds inlines everything so that they can be
|
// Global and Browser ESM builds inlines everything so that they can be
|
||||||
// used alone.
|
// used alone.
|
||||||
external:
|
external: isGlobalBuild || isBrowserESMBuild ? [] : externals,
|
||||||
isGlobalBuild || isBrowserESMBuild ? [] : Object.keys(aliasOptions),
|
|
||||||
plugins: [
|
plugins: [
|
||||||
tsPlugin,
|
tsPlugin,
|
||||||
aliasPlugin,
|
aliasPlugin,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
|
|
||||||
const targets = exports.targets = fs.readdirSync('packages').filter(f => {
|
const targets = (exports.targets = fs.readdirSync('packages').filter(f => {
|
||||||
return fs.statSync(`packages/${f}`).isDirectory()
|
return f !== 'shared' && fs.statSync(`packages/${f}`).isDirectory()
|
||||||
})
|
}))
|
||||||
|
|
||||||
exports.fuzzyMatchTarget = partialTarget => {
|
exports.fuzzyMatchTarget = partialTarget => {
|
||||||
const matched = []
|
const matched = []
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
],
|
],
|
||||||
"rootDir": ".",
|
"rootDir": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"@vue/shared": ["packages/shared/src"],
|
||||||
"@vue/core": ["packages/core/src"],
|
"@vue/core": ["packages/core/src"],
|
||||||
"@vue/observer": ["packages/observer/src"],
|
"@vue/observer": ["packages/observer/src"],
|
||||||
"@vue/scheduler": ["packages/scheduler/src"],
|
"@vue/scheduler": ["packages/scheduler/src"],
|
||||||
|
Loading…
Reference in New Issue
Block a user