PHP Classes

File: public/js/lib/vue/src/parsers/path.js

Recommend this page to a friend!
  Classes of Sergey Beskorovayniy   Silex MVC Blog   public/js/lib/vue/src/parsers/path.js   Download  
File: public/js/lib/vue/src/parsers/path.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Silex MVC Blog
MVC based blog using on the Silex micro-framework
Author: By
Last change:
Date: 8 years ago
Size: 6,729 bytes
 

Contents

Class file image Download
import { parseExpression } from './expression' import { isLiteral, stripQuotes, isObject, isArray, warn, set } from '../util/index' import Cache from '../cache' var pathCache = new Cache(1000) // actions var APPEND = 0 var PUSH = 1 var INC_SUB_PATH_DEPTH = 2 var PUSH_SUB_PATH = 3 // states var BEFORE_PATH = 0 var IN_PATH = 1 var BEFORE_IDENT = 2 var IN_IDENT = 3 var IN_SUB_PATH = 4 var IN_SINGLE_QUOTE = 5 var IN_DOUBLE_QUOTE = 6 var AFTER_PATH = 7 var ERROR = 8 var pathStateMachine = [] pathStateMachine[BEFORE_PATH] = { 'ws': [BEFORE_PATH], 'ident': [IN_IDENT, APPEND], '[': [IN_SUB_PATH], 'eof': [AFTER_PATH] } pathStateMachine[IN_PATH] = { 'ws': [IN_PATH], '.': [BEFORE_IDENT], '[': [IN_SUB_PATH], 'eof': [AFTER_PATH] } pathStateMachine[BEFORE_IDENT] = { 'ws': [BEFORE_IDENT], 'ident': [IN_IDENT, APPEND] } pathStateMachine[IN_IDENT] = { 'ident': [IN_IDENT, APPEND], '0': [IN_IDENT, APPEND], 'number': [IN_IDENT, APPEND], 'ws': [IN_PATH, PUSH], '.': [BEFORE_IDENT, PUSH], '[': [IN_SUB_PATH, PUSH], 'eof': [AFTER_PATH, PUSH] } pathStateMachine[IN_SUB_PATH] = { "'": [IN_SINGLE_QUOTE, APPEND], '"': [IN_DOUBLE_QUOTE, APPEND], '[': [IN_SUB_PATH, INC_SUB_PATH_DEPTH], ']': [IN_PATH, PUSH_SUB_PATH], 'eof': ERROR, 'else': [IN_SUB_PATH, APPEND] } pathStateMachine[IN_SINGLE_QUOTE] = { "'": [IN_SUB_PATH, APPEND], 'eof': ERROR, 'else': [IN_SINGLE_QUOTE, APPEND] } pathStateMachine[IN_DOUBLE_QUOTE] = { '"': [IN_SUB_PATH, APPEND], 'eof': ERROR, 'else': [IN_DOUBLE_QUOTE, APPEND] } /** * Determine the type of a character in a keypath. * * @param {Char} ch * @return {String} type */ function getPathCharType (ch) { if (ch === undefined) { return 'eof' } var code = ch.charCodeAt(0) switch (code) { case 0x5B: // [ case 0x5D: // ] case 0x2E: // . case 0x22: // " case 0x27: // ' case 0x30: // 0 return ch case 0x5F: // _ case 0x24: // $ return 'ident' case 0x20: // Space case 0x09: // Tab case 0x0A: // Newline case 0x0D: // Return case 0xA0: // No-break space case 0xFEFF: // Byte Order Mark case 0x2028: // Line Separator case 0x2029: // Paragraph Separator return 'ws' } // a-z, A-Z if ( (code >= 0x61 && code <= 0x7A) || (code >= 0x41 && code <= 0x5A) ) { return 'ident' } // 1-9 if (code >= 0x31 && code <= 0x39) { return 'number' } return 'else' } /** * Format a subPath, return its plain form if it is * a literal string or number. Otherwise prepend the * dynamic indicator (*). * * @param {String} path * @return {String} */ function formatSubPath (path) { var trimmed = path.trim() // invalid leading 0 if (path.charAt(0) === '0' && isNaN(path)) { return false } return isLiteral(trimmed) ? stripQuotes(trimmed) : '*' + trimmed } /** * Parse a string path into an array of segments * * @param {String} path * @return {Array|undefined} */ function parse (path) { var keys = [] var index = -1 var mode = BEFORE_PATH var subPathDepth = 0 var c, newChar, key, type, transition, action, typeMap var actions = [] actions[PUSH] = function () { if (key !== undefined) { keys.push(key) key = undefined } } actions[APPEND] = function () { if (key === undefined) { key = newChar } else { key += newChar } } actions[INC_SUB_PATH_DEPTH] = function () { actions[APPEND]() subPathDepth++ } actions[PUSH_SUB_PATH] = function () { if (subPathDepth > 0) { subPathDepth-- mode = IN_SUB_PATH actions[APPEND]() } else { subPathDepth = 0 key = formatSubPath(key) if (key === false) { return false } else { actions[PUSH]() } } } function maybeUnescapeQuote () { var nextChar = path[index + 1] if ((mode === IN_SINGLE_QUOTE && nextChar === "'") || (mode === IN_DOUBLE_QUOTE && nextChar === '"')) { index++ newChar = '\\' + nextChar actions[APPEND]() return true } } while (mode != null) { index++ c = path[index] if (c === '\\' && maybeUnescapeQuote()) { continue } type = getPathCharType(c) typeMap = pathStateMachine[mode] transition = typeMap[type] || typeMap['else'] || ERROR if (transition === ERROR) { return // parse error } mode = transition[0] action = actions[transition[1]] if (action) { newChar = transition[2] newChar = newChar === undefined ? c : newChar if (action() === false) { return } } if (mode === AFTER_PATH) { keys.raw = path return keys } } } /** * External parse that check for a cache hit first * * @param {String} path * @return {Array|undefined} */ export function parsePath (path) { var hit = pathCache.get(path) if (!hit) { hit = parse(path) if (hit) { pathCache.put(path, hit) } } return hit } /** * Get from an object from a path string * * @param {Object} obj * @param {String} path */ export function getPath (obj, path) { return parseExpression(path).get(obj) } /** * Warn against setting non-existent root path on a vm. */ var warnNonExistent if (process.env.NODE_ENV !== 'production') { warnNonExistent = function (path, vm) { warn( 'You are setting a non-existent path "' + path.raw + '" ' + 'on a vm instance. Consider pre-initializing the property ' + 'with the "data" option for more reliable reactivity ' + 'and better performance.', vm ) } } /** * Set on an object from a path * * @param {Object} obj * @param {String | Array} path * @param {*} val */ export function setPath (obj, path, val) { var original = obj if (typeof path === 'string') { path = parse(path) } if (!path || !isObject(obj)) { return false } var last, key for (var i = 0, l = path.length; i < l; i++) { last = obj key = path[i] if (key.charAt(0) === '*') { key = parseExpression(key.slice(1)).get.call(original, original) } if (i < l - 1) { obj = obj[key] if (!isObject(obj)) { obj = {} if (process.env.NODE_ENV !== 'production' && last._isVue) { warnNonExistent(path, last) } set(last, key, obj) } } else { if (isArray(obj)) { obj.$set(key, val) } else if (key in obj) { obj[key] = val } else { if (process.env.NODE_ENV !== 'production' && obj._isVue) { warnNonExistent(path, obj) } set(obj, key, val) } } } return true }