Browse Source

annotate core util

dev
Evan You 9 years ago
parent
commit
0bd9a31858
  1. 6
      src/core/config.js
  2. 13
      src/core/util/env.js
  3. 22
      src/core/util/lang.js
  4. 70
      src/core/util/options.js
  5. 94
      src/core/util/props.js
  6. 7
      src/shared/util.js

6
src/core/config.js

@ -2,6 +2,7 @@
export type Config = {
preserveWhitespace: boolean,
optionMergeStrategies: { [key: string]: Function },
silent: boolean,
isReservedTag: (x: string) => boolean,
isUnknownElement: (x: string) => boolean,
@ -18,6 +19,11 @@ const config: Config = {
*/
preserveWhitespace: true,
/**
* Option merge strategies (used in core/util/options)
*/
optionMergeStrategies: Object.create(null),
/**
* Whether to suppress warnings.
*/

13
src/core/util/env.js

@ -1,3 +1,5 @@
/* @flow */
/* global MutationObserver */
// can we use __proto__?
export const hasProto = '__proto__' in {}
@ -41,13 +43,13 @@ export const nextTick = (function () {
if (typeof MutationObserver !== 'undefined' && !(isWechat && isIos)) {
let counter = 1
const observer = new MutationObserver(nextTickHandler)
const textNode = document.createTextNode(counter)
const textNode = document.createTextNode(String(counter))
observer.observe(textNode, {
characterData: true
})
timerFunc = function () {
counter = (counter + 1) % 2
textNode.data = counter
textNode.data = String(counter)
}
} else {
// webpack attempts to inject a shim for setImmediate
@ -58,7 +60,7 @@ export const nextTick = (function () {
: typeof global !== 'undefined' ? global : {}
timerFunc = context.setImmediate || setTimeout
}
return function (cb, ctx) {
return function (cb: Function, ctx?: Object) {
const func = ctx
? function () { cb.call(ctx) }
: cb
@ -77,13 +79,14 @@ if (typeof Set !== 'undefined' && Set.toString().match(/native code/)) {
} else {
// a non-standard Set polyfill that only works with primitive keys.
_Set = class Set {
set: Object;
constructor () {
this.set = Object.create(null)
}
has (key) {
has (key: string | number) {
return this.set[key] !== undefined
}
add (key) {
add (key: string | number) {
this.set[key] = 1
}
clear () {

22
src/core/util/lang.js

@ -1,23 +1,17 @@
/* @flow */
/**
* Check if a string starts with $ or _
*
* @param {String} str
* @return {Boolean}
*/
export function isReserved (str) {
export function isReserved (str: string): boolean {
const c = (str + '').charCodeAt(0)
return c === 0x24 || c === 0x5F
}
/**
* Define a property.
*
* @param {Object} obj
* @param {String} key
* @param {*} val
* @param {Boolean} [enumerable]
*/
export function def (obj, key, val, enumerable) {
export function def (obj: Object, key: string, val: any, enumerable?: boolean) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
@ -30,15 +24,15 @@ export function def (obj, key, val, enumerable) {
* Parse simple path.
*/
const bailRE = /[^\w\.]/
export function parsePath (path) {
export function parsePath (path: string): any {
if (bailRE.test(path)) {
return
} else {
path = path.split('.')
const segments = path.split('.')
return function (obj) {
for (let i = 0; i < path.length; i++) {
for (let i = 0; i < segments.length; i++) {
if (!obj) return
obj = obj[path[i]]
obj = obj[segments[i]]
}
return obj
}

70
src/core/util/options.js

@ -1,3 +1,5 @@
/* @flow */
import Vue from '../instance/index'
import config from '../config'
import { warn } from './debug'
@ -8,6 +10,7 @@ import {
isPlainObject,
hasOwn,
camelize,
capitalize,
isBuiltInTag
} from 'shared/util'
@ -15,14 +18,8 @@ import {
* Option overwriting strategies are functions that handle
* how to merge a parent option value and a child option
* value into the final value.
*
* All strategy functions follow the same signature:
*
* @param {*} parentVal
* @param {*} childVal
* @param {Vue} [vm]
*/
const strats = config.optionMergeStrategies = Object.create(null)
const strats = config.optionMergeStrategies
/**
* Options with restrictions
@ -52,7 +49,7 @@ if (process.env.NODE_ENV !== 'production') {
/**
* Helper that recursively merges two data objects together.
*/
function mergeData (to, from) {
function mergeData (to: Object, from: ?Object): Object {
let key, toVal, fromVal
for (key in from) {
toVal = to[key]
@ -69,7 +66,11 @@ function mergeData (to, from) {
/**
* Data
*/
strats.data = function (parentVal, childVal, vm) {
strats.data = function (
parentVal: any,
childVal: any,
vm?: Vue
): ?Function {
if (!vm) {
// in a Vue.extend merge, both should be functions
if (!childVal) {
@ -119,7 +120,10 @@ strats.data = function (parentVal, childVal, vm) {
/**
* Hooks and param attributes are merged as arrays.
*/
function mergeHook (parentVal, childVal) {
function mergeHook (
parentVal: ?Array<Function>,
childVal: ?Function | ?Array<Function>
): ?Array<Function> {
return childVal
? parentVal
? parentVal.concat(childVal)
@ -140,7 +144,7 @@ config._lifecycleHooks.forEach(hook => {
* a three-way merge between constructor options, instance
* options and parent options.
*/
function mergeAssets (parentVal, childVal) {
function mergeAssets (parentVal: ?Object, childVal: ?Object): Object {
const res = Object.create(parentVal || null)
return childVal
? extend(res, childVal)
@ -157,7 +161,7 @@ config._assetTypes.forEach(function (type) {
* Watchers hashes should not overwrite one
* another, so we merge them as arrays.
*/
strats.watch = function (parentVal, childVal) {
strats.watch = function (parentVal: ?Object, childVal: ?Object): ?Object {
if (!childVal) return parentVal
if (!parentVal) return childVal
const ret = {}
@ -180,7 +184,7 @@ strats.watch = function (parentVal, childVal) {
*/
strats.props =
strats.methods =
strats.computed = function (parentVal, childVal) {
strats.computed = function (parentVal: ?Object, childVal: ?Object): ?Object {
if (!childVal) return parentVal
if (!parentVal) return childVal
const ret = Object.create(null)
@ -192,7 +196,7 @@ strats.computed = function (parentVal, childVal) {
/**
* Default strategy.
*/
const defaultStrat = function (parentVal, childVal) {
const defaultStrat = function (parentVal: any, childVal: any): any {
return childVal === undefined
? parentVal
: childVal
@ -201,10 +205,8 @@ const defaultStrat = function (parentVal, childVal) {
/**
* Make sure component options get converted to actual
* constructors.
*
* @param {Object} options
*/
function guardComponents (options) {
function guardComponents (options: Object) {
if (options.components) {
const components = options.components
let def
@ -227,10 +229,8 @@ function guardComponents (options) {
/**
* Ensure all props option syntax are normalized into the
* Object-based format.
*
* @param {Object} options
*/
function guardProps (options) {
function guardProps (options: Object) {
const props = options.props
if (!props) return
const res = {}
@ -258,7 +258,10 @@ function guardProps (options) {
options.props = res
}
function guardDirectives (options) {
/**
* Normalize raw function directives into object format.
*/
function guardDirectives (options: Object) {
const dirs = options.directives
if (dirs) {
for (const key in dirs) {
@ -272,13 +275,8 @@ function guardDirectives (options) {
/**
* Merge two option objects into a new one.
* Core utility used in both instantiation and inheritance.
*
* @param {Object} parent
* @param {Object} child
* @param {Vue} [vm] - if vm is present, indicates this is
* an instantiation merge.
*/
export function mergeOptions (parent, child, vm) {
export function mergeOptions (parent: Object, child: Object, vm?: Vue) {
guardComponents(child)
guardProps(child)
guardDirectives(child)
@ -319,25 +317,23 @@ export function mergeOptions (parent, child, vm) {
* Resolve an asset.
* This function is used because child instances need access
* to assets defined in its ancestor chain.
*
* @param {Object} options
* @param {String} type
* @param {String} id
* @param {Boolean} warnMissing
* @return {Object|Function}
*/
export function resolveAsset (options, type, id, warnMissing) {
export function resolveAsset (
options: Object,
type: string,
id: string,
warnMissing?: boolean
): any {
/* istanbul ignore if */
if (typeof id !== 'string') {
return
}
const assets = options[type]
let camelizedId
const res = assets[id] ||
// camelCase ID
assets[camelizedId = camelize(id)] ||
assets[camelize(id)] ||
// Pascal Case ID
assets[camelizedId.charAt(0).toUpperCase() + camelizedId.slice(1)]
assets[capitalize(camelize(id))]
if (process.env.NODE_ENV !== 'production' && warnMissing && !res) {
warn(
'Failed to resolve ' + type.slice(0, -1) + ': ' + id,

94
src/core/util/props.js

@ -1,8 +1,18 @@
/* @flow */
import type Vue from '../instance/index'
import { hasOwn, isObject, isPlainObject } from 'shared/util'
import { observe, observerState } from '../observer/index'
import { warn } from './debug'
export function validateProp (vm, key, propsData) {
type PropOptions = {
type: Function | Array<Function> | null,
default: any,
required: ?boolean,
validator: ?Function
}
export function validateProp (vm: Vue, key: string, propsData: ?Object): any {
if (!propsData) return
const prop = vm.$options.props[key]
const absent = hasOwn(propsData, key)
@ -24,12 +34,8 @@ export function validateProp (vm, key, propsData) {
/**
* Get the default value of a prop.
*
* @param {Vue} vm
* @param {Object} prop
* @return {*}
*/
function getPropDefaultValue (vm, prop, name) {
function getPropDefaultValue (vm: Vue, prop: PropOptions, name: string): any {
// no default, return undefined
if (!hasOwn(prop, 'default')) {
// absent boolean value defaults to false
@ -55,23 +61,23 @@ function getPropDefaultValue (vm, prop, name) {
/**
* Assert whether a prop is valid.
*
* @param {Object} prop
* @param {String} name
* @param {*} value
* @param {Vue} vm
* @param {Boolean} absent
*/
function assertProp (prop, name, value, vm, absent) {
function assertProp (
prop: PropOptions,
name: string,
value: any,
vm: Vue,
absent: boolean
) {
if (prop.required && absent) {
process.env.NODE_ENV !== 'production' && warn(
warn(
'Missing required prop: "' + name + '"',
vm
)
return false
return
}
if (value == null) {
return true
return
}
let type = prop.type
let valid = !type
@ -87,37 +93,32 @@ function assertProp (prop, name, value, vm, absent) {
}
}
if (!valid) {
if (process.env.NODE_ENV !== 'production') {
warn(
'Invalid prop: type check failed for prop "' + name + '".' +
' Expected ' + expectedTypes.map(formatType).join(', ') +
', got ' + formatValue(value) + '.',
vm
)
}
return false
warn(
'Invalid prop: type check failed for prop "' + name + '".' +
' Expected ' + expectedTypes.join(', ') +
', got ' + Object.prototype.toString.call(value).slice(8, -1) + '.',
vm
)
return
}
const validator = prop.validator
if (validator) {
if (!validator(value)) {
process.env.NODE_ENV !== 'production' && warn(
warn(
'Invalid prop: custom validator check failed for prop "' + name + '".',
vm
)
return false
}
}
return true
}
/**
* Assert the type of a value
*
* @param {*} value
* @param {Function} type
* @return {Object}
*/
function assertType (value, type) {
function assertType (value: any, type: Function): {
valid: boolean,
expectedType: string
} {
let valid
let expectedType
if (type === String) {
@ -133,12 +134,13 @@ function assertType (value, type) {
expectedType = 'function'
valid = typeof value === expectedType
} else if (type === Object) {
expectedType = 'object'
expectedType = 'Object'
valid = isPlainObject(value)
} else if (type === Array) {
expectedType = 'array'
expectedType = 'Array'
valid = Array.isArray(value)
} else {
expectedType = type.name || type.toString()
valid = value instanceof type
}
return {
@ -146,25 +148,3 @@ function assertType (value, type) {
expectedType
}
}
/**
* Format type for output
*
* @param {String} type
* @return {String}
*/
function formatType (type) {
return type
? type.charAt(0).toUpperCase() + type.slice(1)
: 'custom type'
}
/**
* Format value
*
* @param {*} value
* @return {String}
*/
function formatValue (val) {
return Object.prototype.toString.call(val).slice(8, -1)
}

7
src/shared/util.js

@ -80,6 +80,13 @@ export const camelize = cached((str: string): string => {
return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
})
/**
* Capitalize a string.
*/
export const capitalize = cached((str: string): string => {
return str.charAt(0).toUpperCase() + str.slice(1)
})
/**
* Hyphenate a camelCase string.
*/

Loading…
Cancel
Save