fix scope hidding

This commit is contained in:
harttle
2016-11-06 22:08:26 +08:00
parent fd2df81f9c
commit 1e7873afc0
2 changed files with 48 additions and 36 deletions
+32 -28
View File
@@ -1,33 +1,35 @@
const _ = require('./util/underscore.js'); const _ = require('./util/underscore.js');
const lexical = require('./lexical.js'); const lexical = require('./lexical.js');
const assert = require('./util/assert.js'); const assert = require('./util/assert.js');
const referenceError = /undefined variable|Cannot read property .* of undefined/;
var Scope = { var Scope = {
safeGet: function(str) { getAll: function(str) {
var i; var ctx = {};
// get all
if (str === undefined) {
var ctx = {};
for (i = this.scopes.length - 1; i >= 0; i--) {
var scp = this.scopes[i];
for (var k in scp) {
if (scp.hasOwnProperty(k)) {
ctx[k] = scp[k];
}
}
}
return ctx;
}
// get one path
for (i = this.scopes.length - 1; i >= 0; i--) { for (i = this.scopes.length - 1; i >= 0; i--) {
var v = this.getPropertyByPath(this.scopes[i], str); _.assign(ctx, this.scopes[i]);
if (v !== undefined) return v;
} }
return ctx;
}, },
get: function(str) { get: function(str) {
var val = this.safeGet(str); for (var i = this.scopes.length - 1; i >= 0; i--) {
if (val === undefined && this.opts.strict_variables) { try {
throw new Error(`[strict_variables] undefined variable: ${str}`); return this.getPropertyByPath(this.scopes[i], str);
} catch (e) {
if (!referenceError.test(e.message) || this.opts.strict_variables) {
e.message += ': ' + str;
throw e;
}
}
}
if(this.opts.strict_variables){
throw new TypeError('undefined variable: ' + str);
}
},
safeGet: function(str) {
try {
var val = this.safeGet(str);
} catch (e) {;
} }
return val; return val;
}, },
@@ -65,12 +67,14 @@ var Scope = {
}, },
getPropertyByPath: function(obj, path) { getPropertyByPath: function(obj, path) {
if (_.isString(path) && path.length) { var paths = this.propertyAccessSeq(path + '');
var paths = this.propertyAccessSeq(path); var varName = paths.shift();
paths.forEach(p => obj = obj && obj[p]); if (!obj.hasOwnProperty(varName)) {
return obj; throw new TypeError('undefined variable');
} }
return obj[path]; var variable = obj[varName];
paths.forEach(p => variable = variable[p]);
return variable;
}, },
/* /*
@@ -96,11 +100,11 @@ var Scope = {
assert(j !== -1, `unbalanced []: ${str}`); assert(j !== -1, `unbalanced []: ${str}`);
name = str.slice(i + 1, j); name = str.slice(i + 1, j);
// foo[1] // foo[1]
if(lexical.isInteger(name)){ if (lexical.isInteger(name)) {
seq.push(name); seq.push(name);
} }
// foo["bar"] // foo["bar"]
else{ else {
seq.push(this.get(name)); seq.push(this.get(name));
} }
name = ''; name = '';
+16 -8
View File
@@ -83,7 +83,7 @@ describe('scope', function() {
}); });
it('should get all properties when arguments empty', function() { it('should get all properties when arguments empty', function() {
expect(scope.get()).deep.equal(ctx); expect(scope.getAll()).deep.equal(ctx);
}); });
it('should access child property via dot syntax', function() { it('should access child property via dot syntax', function() {
@@ -116,7 +116,7 @@ describe('scope', function() {
}); });
}); });
describe('.push(), .pop()', function() { describe('.push()', function() {
it('should throw when trying to push non-object', function() { it('should throw when trying to push non-object', function() {
expect(function() { expect(function() {
scope.push(false); scope.push(false);
@@ -130,7 +130,14 @@ describe('scope', function() {
expect(scope.get('foo')).to.equal('foo'); expect(scope.get('foo')).to.equal('foo');
expect(scope.get('bar')).to.equal('bar'); expect(scope.get('bar')).to.equal('bar');
}); });
it('should hide deep properties by push', function(){
scope.set('bar', {bar: 'bar'});
scope.push({bar: {foo: 'foo'}});
expect(scope.get('bar.foo')).to.equal('foo');
expect(scope.get('bar.bar')).to.equal(undefined);
});
});
describe('.pop()', function() {
it('should pop scope', function() { it('should pop scope', function() {
scope.push({ scope.push({
foo: 'foo' foo: 'foo'
@@ -140,7 +147,7 @@ describe('scope', function() {
}); });
}); });
describe('.push(), .pop()', function() { describe('.unshift()', function() {
it('should throw when trying to unshift non-object', function() { it('should throw when trying to unshift non-object', function() {
expect(function() { expect(function() {
scope.unshift(false); scope.unshift(false);
@@ -150,11 +157,12 @@ describe('scope', function() {
scope.unshift({ scope.unshift({
foo: 'blue', foo: 'blue',
foo1: 'foo1' foo1: 'foo1'
}) });
scope.get('foo').should.equal('zoo'); expect(scope.get('foo')).to.equal('zoo');
scope.get('foo1').should.equal('foo1'); expect(scope.get('foo1')).to.equal('foo1');
}); });
});
describe('.shift()', function() {
it('should shift scope', function() { it('should shift scope', function() {
scope.unshift({ scope.unshift({
foo: 'blue', foo: 'blue',