cover all

This commit is contained in:
harttle
2017-08-14 22:07:08 +08:00
parent 7904f823a8
commit 72597c52e5
14 changed files with 268 additions and 205 deletions
+49 -53
View File
@@ -1,7 +1,6 @@
const _ = require('./util/underscore.js')
const lexical = require('./lexical.js')
const assert = require('./util/assert.js')
const toStr = Object.prototype.toString
var Scope = {
getAll: function () {
@@ -12,32 +11,16 @@ var Scope = {
return ctx
},
get: function (str) {
for (var i = this.scopes.length - 1; i >= 0; i--) {
try {
return this.getPropertyByPath(this.scopes[i], str)
} catch (e) {
if (/undefined variable/.test(e.message)) {
continue
}
if (/Cannot read property/.test(e.message)) {
if (this.opts.strict_variables) {
e.message += ': ' + str
throw e
} else {
continue
}
} else {
e.message += ': ' + str
throw e
}
try {
return this.getPropertyByPath(this.scopes, str)
} catch (e) {
if (!/undefined variable/.test(e.message) || this.opts.strict_variables) {
throw e
}
}
if (this.opts.strict_variables) {
throw new TypeError('undefined variable: ' + str)
}
},
set: function (k, v) {
this.setPropertyByPath(this.scopes[this.scopes.length - 1], k, v)
setPropertyByPath(this.scopes[this.scopes.length - 1], k, v)
return this
},
push: function (ctx) {
@@ -54,39 +37,23 @@ var Scope = {
shift: function () {
return this.scopes.shift()
},
setPropertyByPath: function (obj, path, val) {
if (_.isString(path)) {
var paths = path.replace(/\[/g, '.').replace(/\]/g, '').split('.')
for (var i = 0; i < paths.length; i++) {
var key = paths[i]
if (i === paths.length - 1) {
return (obj[key] = val)
}
if (undefined === obj[key]) obj[key] = {}
// case for readonly objects
obj = obj[key] || {}
}
}
},
getPropertyByPath: function (obj, path) {
getPropertyByPath: function (scopes, path) {
var paths = this.propertyAccessSeq(path + '')
var varName = paths.shift()
if (!obj.hasOwnProperty(varName)) {
throw new TypeError('undefined variable')
if (!paths.length) {
throw new TypeError('undefined variable: ' + path)
}
var variable = obj[varName]
var lastName = paths.pop()
paths.forEach(p => (variable = variable[p]))
if (undefined !== lastName) {
if (lastName === 'size' &&
(toStr.call(variable) === '[object Array]' ||
toStr.call(variable) === '[object String]')) {
return variable.length
}
variable = variable[lastName]
}
return variable
var key = paths.shift()
var value = getValueFromScopes(key, scopes)
return paths.reduce(
(value, key) => {
if (_.isNil(value)) {
throw new TypeError('undefined variable: ' + key)
}
return getValueFromParent(key, value)
},
value
)
},
/*
@@ -144,6 +111,35 @@ var Scope = {
}
}
function setPropertyByPath (obj, path, val) {
var paths = (path + '').replace(/\[/g, '.').replace(/\]/g, '').split('.')
for (var i = 0; i < paths.length; i++) {
var key = paths[i]
if (i === paths.length - 1) {
return (obj[key] = val)
}
if (undefined === obj[key]) obj[key] = {}
// case for readonly objects
obj = obj[key] || {}
}
}
function getValueFromParent (key, value) {
return (key === 'size' && (_.isArray(value) || _.isString(value)))
? value.length
: value[key]
}
function getValueFromScopes (key, scopes) {
for (var i = scopes.length - 1; i > -1; i--) {
var scope = scopes[i]
if (scope.hasOwnProperty(key)) {
return scope[key]
}
}
throw new TypeError('undefined variable: ' + key)
}
function matchRightBracket (str, begin) {
var stack = 1 // count of '[' - count of ']'
for (var i = begin; i < str.length; i++) {
+3 -9
View File
@@ -1,5 +1,4 @@
const lexical = require('./lexical.js')
const _ = require('./util/underscore.js')
const Promise = require('any-promise')
const Syntax = require('./syntax.js')
const assert = require('./util/assert.js')
@@ -28,14 +27,9 @@ module.exports = function () {
}
return Promise.resolve()
.then(() => typeof impl.render === 'function'
? impl.render(scope, obj) : '')
.catch(function (e) {
if (_.isError(e)) {
throw e
}
var msg = `Please reject with an Error in ${impl.render}, got ${e}`
throw new Error(msg)
})
? impl.render(scope, obj)
: ''
)
},
parse: function (token, tokens) {
this.type = 'tag'
-3
View File
@@ -2,9 +2,6 @@ const AssertionError = require('./error.js').AssertionError
function assert (predicate, message) {
if (!predicate) {
if (message instanceof Error) {
throw message
}
message = message || `expect ${predicate} to be true`
throw new AssertionError(message)
}
+13 -1
View File
@@ -1,3 +1,5 @@
const toStr = Object.prototype.toString
/*
* Checks if value is classified as a String primitive or object.
* @param {any} value The value to check.
@@ -7,6 +9,15 @@ function isString (value) {
return value instanceof String || typeof value === 'string'
}
function isNil (value) {
return value === null || value === undefined
}
function isArray (value) {
// be compatible with IE 8
return toStr.call(value) === '[object Array]'
}
function isError (value) {
var signature = Object.prototype.toString.call(value)
// [object XXXError]
@@ -53,7 +64,6 @@ function assign (object) {
}
function _assignBinary (dst, src) {
if (!dst) return dst
forOwn(src, function (v, k) {
dst[k] = v
})
@@ -115,6 +125,8 @@ function range (start, stop, step) {
exports.isString = isString
exports.isObject = isObject
exports.isArray = isArray
exports.isNil = isNil
exports.isError = isError
exports.range = range