Files
liquidjs/src/scope.js
T

80 lines
2.3 KiB
JavaScript

const lexical = require('./lexical.js');
var Scope = {
safeGet: function(str) {
var i;
// 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--) {
var v = getPropertyByPath(this.scopes[i], str);
if (v !== undefined) return v;
}
},
get: function(str) {
var val = this.safeGet(str);
if (val === undefined && this.opts.strict) {
throw new Error(`[strict_variables] undefined variable: ${str}`);
}
return val;
},
set: function(k, v) {
setPropertyByPath(this.scopes[this.scopes.length - 1], k, v);
return this;
},
push: function(ctx) {
if (!ctx) throw new Error(`trying to push ${ctx} into scopes`);
return this.scopes.push(ctx);
},
pop: function() {
return this.scopes.pop();
}
};
function setPropertyByPath(obj, path, val) {
if (path instanceof String || typeof path === 'string') {
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] || {};
}
return obj;
}
return obj[path] = val;
}
function getPropertyByPath(obj, path) {
if (path instanceof String || typeof path === 'string') {
var paths = path.replace(/\[/g, '.').replace(/\]/g, '').split('.');
paths.forEach(p => obj = obj && obj[p]);
return obj;
}
return obj[path];
}
exports.factory = function(_ctx, opts) {
opts = opts || {};
opts.strict = opts.strict || false;
var scope = Object.create(Scope);
scope.opts = opts;
scope.scopes = [_ctx || {}];
return scope;
};