Skip to content

Commit bc0fd37

Browse files
committed
New ExpParser implementation
- extract all paths and replace them with correct reference - in the process, create missing bindings on the owner vm's compiler
1 parent 5b7b00f commit bc0fd37

File tree

2 files changed

+44
-58
lines changed

2 files changed

+44
-58
lines changed

src/compiler.js

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ function Compiler (vm, options) {
7373
// and register child id on parent
7474
var childId = utils.attr(el, 'id')
7575
if (parent) {
76-
vm.$parent = parent.vm
76+
def(vm, '$parent', parent.vm)
7777
if (childId) {
7878
compiler.childId = childId
7979
parent.vm.$[childId] = vm
@@ -101,7 +101,7 @@ function Compiler (vm, options) {
101101
// which should be inenumerable but configurable
102102
if (compiler.repeat) {
103103
vm.$index = compiler.repeatIndex
104-
vm.$collection = compiler.repeatCollection
104+
def(vm, '$collection', compiler.repeatCollection)
105105
compiler.createBinding('$index')
106106
}
107107

@@ -409,25 +409,14 @@ CompilerProto.createBinding = function (key, isExp, isFn) {
409409
if (isExp) {
410410
// a complex expression binding
411411
// we need to generate an anonymous computed property for it
412-
var result = ExpParser.parse(key)
413-
if (result.getter) {
412+
var getter = ExpParser.parse(key, compiler)
413+
if (getter) {
414414
log(' created expression binding: ' + key)
415415
binding.value = isFn
416-
? result.getter
417-
: { $get: result.getter }
416+
? getter
417+
: { $get: getter }
418418
compiler.markComputed(binding)
419419
compiler.exps.push(binding)
420-
// need to create the bindings for keys
421-
// that do not exist yet
422-
if (result.paths) {
423-
var i = result.paths.length, v
424-
while (i--) {
425-
v = result.paths[i]
426-
if (!bindings[v]) {
427-
compiler.rootCompiler.createBinding(v)
428-
}
429-
}
430-
}
431420
}
432421
} else {
433422
log(' created binding: ' + key)

src/exp-parser.js

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
var utils = require('./utils')
1+
var utils = require('./utils'),
2+
hasOwn = Object.prototype.hasOwnProperty
23

34
// Variable extraction scooped from https://github.com/RubyLouvre/avalon
45

@@ -37,25 +38,45 @@ function getVariables (code) {
3738
}
3839

3940
/**
40-
* Based on top level variables, extract full keypaths accessed.
41-
* We need full paths because we need to define them in the compiler's
42-
* bindings, so that they emit 'get' events during dependency tracking.
41+
* Filter
4342
*/
44-
// function getPaths (code, vars) {
45-
// var pathRE = new RegExp("\\b(" + vars.join('|') + ")[$\\w\\.]*\\b", 'g')
46-
// return code.match(pathRE)
47-
// }
48-
4943
function filterUnique (vars) {
5044
var hash = utils.hash(),
5145
i = vars.length,
52-
key
46+
key, res = []
5347
while (i--) {
5448
key = vars[i]
5549
if (hash[key]) continue
5650
hash[key] = 1
51+
res.push(key)
5752
}
58-
return Object.keys(hash)
53+
return res
54+
}
55+
56+
function getRel (path, compiler) {
57+
var rel = '',
58+
vm = compiler.vm,
59+
dot = path.indexOf('.'),
60+
key = dot > -1
61+
? path.slice(0, dot)
62+
: path
63+
while (true) {
64+
if (hasOwn.call(vm, key)) {
65+
break
66+
} else {
67+
if (vm.$parent) {
68+
vm = vm.$parent
69+
rel += '$parent.'
70+
} else {
71+
break
72+
}
73+
}
74+
}
75+
compiler = vm.$compiler
76+
if (!hasOwn.call(compiler.bindings, path)) {
77+
compiler.createBinding(path)
78+
}
79+
return rel
5980
}
6081

6182
/**
@@ -81,41 +102,17 @@ module.exports = {
81102
* from an arbitrary expression, together with a list of paths to be
82103
* created as bindings.
83104
*/
84-
parse: function (exp) {
105+
parse: function (exp, compiler) {
85106
// extract variable names
86107
var vars = getVariables(exp)
87108
if (!vars.length) {
88-
return {
89-
getter: makeGetter('return ' + exp, exp)
90-
}
109+
return makeGetter('return ' + exp, exp)
91110
}
92-
console.log(vars)
93111
vars = filterUnique(vars)
94-
// var args = [],
95-
// v, i, keyPrefix,
96-
// l = vars.length,
97-
// hash = Object.create(null)
98-
// for (i = 0; i < l; i++) {
99-
// v = vars[i]
100-
// // avoid duplicate keys
101-
// if (hash[v]) continue
102-
// hash[v] = v
103-
// // push assignment
104-
// keyPrefix = v.charAt(0)
105-
// args.push(v + (
106-
// (keyPrefix === '$' || keyPrefix === '_')
107-
// ? '=this.' + v
108-
// : '=this.$get("' + v + '")'
109-
// ))
110-
// }
111-
// args = 'var ' + args.join(',') + ';return ' + exp
112112
var pathRE = new RegExp("\\b(" + vars.join('|') + ")[$\\w\\.]*\\b", 'g'),
113-
paths = exp.match(pathRE),
114-
body = 'return ' + exp.replace(pathRE, 'this.$&')
115-
console.log(paths, body)
116-
return {
117-
getter: makeGetter(body, exp),
118-
paths: paths
119-
}
113+
body = 'return ' + exp.replace(pathRE, function (path) {
114+
return 'this.' + getRel(path, compiler) + path
115+
})
116+
return makeGetter(body, exp)
120117
}
121118
}

0 commit comments

Comments
 (0)