UNPKG

derby

Version:

MVC framework making it easy to write realtime, collaborative applications that run in both Node.js and browsers.

839 lines (838 loc) 35.6 kB
var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.ScopedModelExpression = exports.ViewParentExpression = exports.SequenceExpression = exports.OperatorExpression = exports.NewExpression = exports.FnExpression = exports.ObjectExpression = exports.ArrayExpression = exports.DeferRenderExpression = exports.BracketsExpression = exports.AttributePathExpression = exports.AliasPathExpression = exports.RelativePathExpression = exports.PathExpression = exports.LiteralExpression = exports.Expression = exports.ExpressionMeta = exports.renderObject = exports.renderArray = exports.renderTemplate = exports.renderValue = exports.pathSegments = exports.templateTruthy = exports.lookup = void 0; var serializeObject = require("serialize-object"); var operatorFns = require("./operatorFns"); var templates_1 = require("./templates"); var util_1 = require("./util"); function lookup(segments, value) { if (!segments) return value; for (var i = 0, len = segments.length; i < len; i++) { if (value == null) return value; value = value[segments[i]]; } return value; } exports.lookup = lookup; // Unlike JS, `[]` is falsey. Otherwise, truthiness is the same as JS function templateTruthy(value) { return (Array.isArray(value)) ? value.length > 0 : !!value; } exports.templateTruthy = templateTruthy; function pathSegments(segments) { var result = []; for (var i = 0; i < segments.length; i++) { var segment = segments[i]; result[i] = (typeof segment === 'object') ? segment.item : segment; } return result; } exports.pathSegments = pathSegments; function renderValue(value, context) { return (typeof value !== 'object') ? value : (value instanceof templates_1.Template) ? renderTemplate(value, context) : (Array.isArray(value)) ? renderArray(value, context) : renderObject(value, context); } exports.renderValue = renderValue; function renderTemplate(template, context) { var i = 1000; var value = template; while (value instanceof templates_1.Template) { if (--i < 0) throw new Error('Maximum template render passes exceeded'); value = value.get(context, true); } return value; } exports.renderTemplate = renderTemplate; function renderArray(array, context) { for (var i = 0; i < array.length; i++) { if (hasTemplateProperty(array[i])) { return renderArrayProperties(array, context); } } return array; } exports.renderArray = renderArray; function renderObject(object, context) { return (hasTemplateProperty(object)) ? renderObjectProperties(object, context) : object; } exports.renderObject = renderObject; function hasTemplateProperty(object) { if (!object) return false; if (object.constructor !== Object) return false; return Object.values(object).some(function (value) { return value instanceof templates_1.Template; }); } function renderArrayProperties(array, context) { var out = new Array(array.length); for (var i = 0; i < array.length; i++) { out[i] = renderValue(array[i], context); } return out; } function renderObjectProperties(object, context) { var out = {}; for (var key in object) { (0, util_1.checkKeyIsSafe)(key); out[key] = renderValue(object[key], context); } return out; } var ExpressionMeta = /** @class */ (function () { function ExpressionMeta(source, blockType, isEnd, as, keyAs, unescaped, bindType, valueType) { this.module = 'expressions'; this.type = 'ExpressionMeta'; this.source = source; this.blockType = blockType; this.isEnd = isEnd; this.as = as; this.keyAs = keyAs; this.unescaped = unescaped; this.bindType = bindType; this.valueType = valueType; } ExpressionMeta.prototype.serialize = function () { return serializeObject.instance(this, this.source, this.blockType, this.isEnd, this.as, this.keyAs, this.unescaped, this.bindType, this.valueType); }; return ExpressionMeta; }()); exports.ExpressionMeta = ExpressionMeta; var Expression = /** @class */ (function () { function Expression(meta) { this.module = 'expressions'; this.type = 'Expression'; this.meta = meta; } Expression.prototype.serialize = function () { return serializeObject.instance(this, this.meta); }; Expression.prototype.toString = function () { return this.meta && this.meta.source; }; Expression.prototype.truthy = function (context) { var blockType = this.meta.blockType; if (blockType === 'else') return true; var value = this.get(context, true); var truthy = templateTruthy(value); return (blockType === 'unless') ? !truthy : truthy; }; Expression.prototype.get = function (_context, _flag) { return undefined; }; // Return the expression's segment list with context objects Expression.prototype.resolve = function (_context) { return undefined; }; // Return a list of segment lists or null Expression.prototype.dependencies = function (_context, _options) { return undefined; }; // Return the pathSegments that the expression currently resolves to or null Expression.prototype.pathSegments = function (context) { var segments = this.resolve(context); return segments && pathSegments(segments); }; Expression.prototype.set = function (context, value) { var segments = this.pathSegments(context); if (!segments) throw new Error('Expression does not support setting'); context.controller.model._set(segments, value); }; Expression.prototype._resolvePatch = function (context, segments) { return (context && context.expression === this && context.item != null) ? segments.concat(context) : segments; }; Expression.prototype.isUnbound = function (context) { // If the template being rendered has an explicit bindType keyword, such as: // {{unbound #item.text}} var bindType = this.meta && this.meta.bindType; if (bindType === 'unbound') return true; if (bindType === 'bound') return false; // Otherwise, inherit from the context return context.unbound; }; Expression.prototype._lookupAndContextifyValue = function (value, context) { if (this.segments && this.segments.length) { // If expression has segments, e.g. `bar.baz` in `#foo.bar.baz`, then // render the base value (e.g. `#foo`) if it's a template and look up the // value at the indicated path. value = renderTemplate(value, context); value = lookup(this.segments, value); } if (value instanceof templates_1.Template && !(value instanceof templates_1.ContextClosure)) { // If we're not immediately rendering the template, then create a ContextClosure // so that the value renders with the correct context later. value = new templates_1.ContextClosure(value, context); } return value; }; return Expression; }()); exports.Expression = Expression; var LiteralExpression = /** @class */ (function (_super) { __extends(LiteralExpression, _super); function LiteralExpression(value, meta) { var _this = _super.call(this, meta) || this; _this.type = 'LiteralExpression'; _this.value = value; return _this; } LiteralExpression.prototype.serialize = function () { return serializeObject.instance(this, this.value, this.meta); }; LiteralExpression.prototype.get = function () { return this.value; }; return LiteralExpression; }(Expression)); exports.LiteralExpression = LiteralExpression; var PathExpression = /** @class */ (function (_super) { __extends(PathExpression, _super); function PathExpression(segments, meta) { var _this = _super.call(this, meta) || this; _this.type = 'PathExpression'; _this.segments = segments; return _this; } PathExpression.prototype.serialize = function () { return serializeObject.instance(this, this.segments, this.meta); }; PathExpression.prototype.get = function (context) { // See View::dependencies. This is needed in order to handle the case of // getting dependencies within a component template, in which case we cannot // access model data separate from rendering. if (!context.controller) return; return lookup(this.segments, context.controller.model.data); }; PathExpression.prototype.resolve = function (context) { // See View::dependencies. This is needed in order to handle the case of // getting dependencies within a component template, in which case we cannot // access model data separate from rendering. if (!context.controller) return; var component = context.controller; var segments = (0, util_1.concat)(component._scope, this.segments); return this._resolvePatch(context, segments); }; PathExpression.prototype.dependencies = function (context, options) { // See View::dependencies. This is needed in order to handle the case of // getting dependencies within a component template, in which case we cannot // access model data separate from rendering. if (!context.controller) return; var value = lookup(this.segments, context.controller.model.data); var dependencies = getDependencies(value, context, options); return appendDependency(dependencies, this, context); }; return PathExpression; }(Expression)); exports.PathExpression = PathExpression; var RelativePathExpression = /** @class */ (function (_super) { __extends(RelativePathExpression, _super); function RelativePathExpression(segments, meta) { var _this = _super.call(this, meta) || this; _this.type = 'RelativePathExpression'; _this.segments = segments; _this.meta = meta; return _this; } RelativePathExpression.prototype.serialize = function () { return serializeObject.instance(this, this.segments, this.meta); }; RelativePathExpression.prototype.get = function (context) { var relativeContext = context.forRelative(this); var value = relativeContext.get(); return this._lookupAndContextifyValue(value, relativeContext); }; RelativePathExpression.prototype.resolve = function (context) { var relativeContext = context.forRelative(this); var base = (relativeContext.expression) ? relativeContext.expression.resolve(relativeContext) : []; if (!base) return; var segments = base.concat(this.segments); return this._resolvePatch(context, segments); }; RelativePathExpression.prototype.dependencies = function (context, options) { // Return inner dependencies from our ancestor // (e.g., {{ with foo[bar] }} ... {{ this.x }} has 'bar' as a dependency.) var relativeContext = context.forRelative(this); var dependencies = relativeContext.expression && relativeContext.expression.dependencies(relativeContext, options); return swapLastDependency(dependencies, this, context); }; return RelativePathExpression; }(Expression)); exports.RelativePathExpression = RelativePathExpression; var AliasPathExpression = /** @class */ (function (_super) { __extends(AliasPathExpression, _super); function AliasPathExpression(alias, segments, meta) { var _this = _super.call(this, meta) || this; _this.type = 'AliasPathExpression'; _this.alias = alias; _this.segments = segments; _this.meta = meta; return _this; } AliasPathExpression.prototype.serialize = function () { return serializeObject.instance(this, this.alias, this.segments, this.meta); }; AliasPathExpression.prototype.get = function (context) { var aliasContext = context.forAlias(this.alias); if (!aliasContext) return; if (aliasContext.keyAlias === this.alias) { return aliasContext.item; } var value = aliasContext.get(); return this._lookupAndContextifyValue(value, aliasContext); }; AliasPathExpression.prototype.resolve = function (context) { var aliasContext = context.forAlias(this.alias); if (!aliasContext) return; if (aliasContext.keyAlias === this.alias) return; var base = aliasContext.expression.resolve(aliasContext); if (!base) return; var segments = base.concat(this.segments); return this._resolvePatch(context, segments); }; AliasPathExpression.prototype.dependencies = function (context, options) { var aliasContext = context.forAlias(this.alias); if (!aliasContext) return; if (aliasContext.keyAlias === this.alias) { // For keyAliases, use a dependency of the entire list, so that it will // always update when the list itself changes. This is over-binding, but // would otherwise be much more complex var base = aliasContext.expression.resolve(aliasContext.parent); if (!base) return; return [base]; } var dependencies = aliasContext.expression.dependencies(aliasContext, options); return swapLastDependency(dependencies, this, context); }; return AliasPathExpression; }(Expression)); exports.AliasPathExpression = AliasPathExpression; var AttributePathExpression = /** @class */ (function (_super) { __extends(AttributePathExpression, _super); function AttributePathExpression(attribute, segments, meta) { var _this = _super.call(this, meta) || this; _this.type = 'AttributePathExpression'; _this.attribute = attribute; _this.segments = segments; return _this; } AttributePathExpression.prototype.serialize = function () { return serializeObject.instance(this, this.attribute, this.segments, this.meta); }; AttributePathExpression.prototype.get = function (context) { var attributeContext = context.forAttribute(this.attribute); if (!attributeContext) return; var value = attributeContext.attributes[this.attribute]; if (value instanceof Expression) { value = value.get(attributeContext); } return this._lookupAndContextifyValue(value, attributeContext); }; AttributePathExpression.prototype.resolve = function (context) { var attributeContext = context.forAttribute(this.attribute); if (!attributeContext) return; // Attributes may be a template, an expression, or a literal value var base; var value = attributeContext.attributes[this.attribute]; if (value instanceof Expression || value instanceof templates_1.Template) { base = value.resolve(attributeContext); } if (!base) return; var segments = base.concat(this.segments); return this._resolvePatch(context, segments); }; AttributePathExpression.prototype.dependencies = function (context, options) { var attributeContext = context.forAttribute(this.attribute); if (!attributeContext) return; // Attributes may be a template, an expression, or a literal value var value = attributeContext.attributes[this.attribute]; var dependencies = getDependencies(value, attributeContext, options); return swapLastDependency(dependencies, this, context); }; return AttributePathExpression; }(Expression)); exports.AttributePathExpression = AttributePathExpression; var BracketsExpression = /** @class */ (function (_super) { __extends(BracketsExpression, _super); function BracketsExpression(before, inside, afterSegments, meta) { var _this = _super.call(this, meta) || this; _this.type = 'BracketsExpression'; _this.serialize = function () { return serializeObject.instance(this, this.before, this.inside, this.afterSegments, this.meta); }; _this.before = before; _this.inside = inside; _this.afterSegments = afterSegments; _this.meta = meta; return _this; } BracketsExpression.prototype.get = function (context) { var inside = this.inside.get(context); if (inside == null) return; var before = this.before.get(context); if (!before) return; var base = before[inside]; return (this.afterSegments) ? lookup(this.afterSegments, base) : base; }; BracketsExpression.prototype.resolve = function (context) { // Get and split the current value of the expression inside the brackets var inside = this.inside.get(context); if (inside == null) return; // Concat the before, inside, and optional after segments var base = this.before.resolve(context); if (!base) return; var segments = (this.afterSegments) ? base.concat(inside, this.afterSegments) : base.concat(inside); return this._resolvePatch(context, segments); }; BracketsExpression.prototype.dependencies = function (context, options) { var before = this.before.dependencies(context, options); if (before) before.pop(); var inner = this.inside.dependencies(context, options); var dependencies = (0, util_1.concat)(before, inner); return appendDependency(dependencies, this, context); }; return BracketsExpression; }(Expression)); exports.BracketsExpression = BracketsExpression; // This Expression is used to wrap a template so that when its containing // Expression--such as an ObjectExpression or ArrayExpression--is evaluated, // it returns the template unrendered and wrapped in the current context. // Separating evaluation of the containing expression from template rendering // is used to support array attributes of views. This way, we can evaluate an // array and iterate through it separately from rendering template content var DeferRenderExpression = /** @class */ (function (_super) { __extends(DeferRenderExpression, _super); function DeferRenderExpression(template, meta) { var _this = _super.call(this, meta) || this; _this.type = 'DeferRenderExpression'; if (!(template instanceof templates_1.Template)) { throw new Error('DeferRenderExpression requires a Template argument'); } _this.template = template; _this.meta = meta; return _this; } DeferRenderExpression.prototype.serialize = function () { return serializeObject.instance(this, this.template, this.meta); }; DeferRenderExpression.prototype.get = function (context) { return new templates_1.ContextClosure(this.template, context); }; return DeferRenderExpression; }(Expression)); exports.DeferRenderExpression = DeferRenderExpression; var ArrayExpression = /** @class */ (function (_super) { __extends(ArrayExpression, _super); function ArrayExpression(items, afterSegments, meta) { var _this = _super.call(this, meta) || this; _this.type = 'ArrayExpression'; _this.items = items; _this.afterSegments = afterSegments; _this.meta = meta; return _this; } ArrayExpression.prototype.serialize = function () { return serializeObject.instance(this, this.items, this.afterSegments, this.meta); }; ArrayExpression.prototype.get = function (context) { var items = new Array(this.items.length); for (var i = 0; i < this.items.length; i++) { var value = this.items[i].get(context); items[i] = value; } return (this.afterSegments) ? lookup(this.afterSegments, items) : items; }; ArrayExpression.prototype.dependencies = function (context, options) { if (!this.items) return; var dependencies; for (var i = 0; i < this.items.length; i++) { var itemDependencies = this.items[i].dependencies(context, options); dependencies = (0, util_1.concat)(dependencies, itemDependencies); } return dependencies; }; return ArrayExpression; }(Expression)); exports.ArrayExpression = ArrayExpression; var ObjectExpression = /** @class */ (function (_super) { __extends(ObjectExpression, _super); function ObjectExpression(properties, afterSegments, meta) { var _this = _super.call(this, meta) || this; _this.type = 'ObjectExpression'; _this.properties = properties; _this.afterSegments = afterSegments; return _this; } ObjectExpression.prototype.serialize = function () { return serializeObject.instance(this, this.properties, this.afterSegments, this.meta); }; ObjectExpression.prototype.get = function (context) { var object = {}; for (var key in this.properties) { (0, util_1.checkKeyIsSafe)(key); var value = this.properties[key].get(context); object[key] = value; } return (this.afterSegments) ? lookup(this.afterSegments, object) : object; }; ObjectExpression.prototype.dependencies = function (context, options) { if (!this.properties) return; var dependencies; for (var key in this.properties) { var propertyDependencies = this.properties[key].dependencies(context, options); dependencies = (0, util_1.concat)(dependencies, propertyDependencies); } return dependencies; }; return ObjectExpression; }(Expression)); exports.ObjectExpression = ObjectExpression; var FnExpression = /** @class */ (function (_super) { __extends(FnExpression, _super); function FnExpression(segments, args, afterSegments, meta) { var _this = _super.call(this, meta) || this; _this.type = 'FnExpression'; _this.segments = segments; _this.args = args; _this.afterSegments = afterSegments; _this.meta = meta; var parentSegments = segments && segments.slice(); _this.lastSegment = parentSegments && parentSegments.pop(); _this.parentSegments = (parentSegments && parentSegments.length) ? parentSegments : null; return _this; } FnExpression.prototype.serialize = function () { return serializeObject.instance(this, this.segments, this.args, this.afterSegments, this.meta); }; FnExpression.prototype.get = function (context) { var value = this.apply(context); // Lookup property underneath computed value if needed return (this.afterSegments) ? lookup(this.afterSegments, value) : value; }; FnExpression.prototype.apply = function (context, extraInputs) { // See View::dependencies. This is needed in order to handle the case of // getting dependencies within a component template, in which case we cannot // access model data separate from rendering. if (!context.controller) return; var parent = this._lookupParent(context); var fn = parent[this.lastSegment]; var getFn = fn.get || fn; var out = this._applyFn(getFn, context, extraInputs, parent); return out; }; FnExpression.prototype._lookupParent = function (context) { // Lookup function on current controller var controller = context.controller; var segments = this.parentSegments; var parent = (segments) ? lookup(segments, controller) : controller; if (parent && parent[this.lastSegment]) return parent; // Otherwise lookup function on page var page = controller.page; if (controller !== page) { parent = (segments) ? lookup(segments, page) : page; if (parent && parent[this.lastSegment]) return parent; } // Otherwise lookup function on global parent = (segments) ? lookup(segments, global) : global; if (parent && parent[this.lastSegment]) return parent; // Throw if not found throw new Error('Function not found for: ' + this.segments.join('.')); }; FnExpression.prototype._getInputs = function (context) { var inputs = []; for (var i = 0, len = this.args.length; i < len; i++) { var value = this.args[i].get(context); inputs.push(renderValue(value, context)); } return inputs; }; FnExpression.prototype._applyFn = function (fn, context, extraInputs, thisArg) { // Apply if there are no path inputs if (!this.args) { return (extraInputs) ? fn.apply(thisArg, extraInputs) : fn.call(thisArg); } // Otherwise, get the current value for path inputs and apply var inputs = this._getInputs(context); if (extraInputs) { for (var i = 0, len = extraInputs.length; i < len; i++) { inputs.push(extraInputs[i]); } } return fn.apply(thisArg, inputs); }; FnExpression.prototype.dependencies = function (context, options) { var dependencies = []; if (!this.args) return dependencies; for (var i = 0, len = this.args.length; i < len; i++) { var argDependencies = this.args[i].dependencies(context, options); if (!argDependencies || argDependencies.length < 1) continue; var end = argDependencies.length - 1; for (var j = 0; j < end; j++) { dependencies.push(argDependencies[j]); } var last = argDependencies[end]; if (last[last.length - 1] !== '*') { last = last.concat('*'); } dependencies.push(last); } return dependencies; }; FnExpression.prototype.set = function (context, value) { var controller = context.controller; var fn, parent; while (controller) { parent = (this.parentSegments) ? lookup(this.parentSegments, controller) : controller; fn = parent && parent[this.lastSegment]; if (fn) { break; } // controller could be a Component or a PageBase in practice, // using `as Component` to avoid a runtime instanceof check. controller = controller.parent; } var setFn = fn && fn.set; if (!setFn) throw new Error('No setter function for: ' + this.segments.join('.')); var inputs = this._getInputs(context); inputs.unshift(value); var out = setFn.apply(parent, inputs); for (var i in out) { this.args[i].set(context, out[i]); } }; return FnExpression; }(Expression)); exports.FnExpression = FnExpression; var NewExpression = /** @class */ (function (_super) { __extends(NewExpression, _super); function NewExpression(segments, args, afterSegments, meta) { var _this = _super.call(this, segments, args, afterSegments, meta) || this; _this.type = 'NewExpression'; return _this; } NewExpression.prototype._applyFn = function (Fn, context) { // Apply if there are no path inputs if (!this.args) return new Fn(); // Otherwise, get the current value for path inputs and apply var inputs = this._getInputs(context); inputs.unshift(null); // eslint-disable-next-line prefer-spread return new (Fn.bind.apply(Fn, inputs))(); }; return NewExpression; }(FnExpression)); exports.NewExpression = NewExpression; var OperatorExpression = /** @class */ (function (_super) { __extends(OperatorExpression, _super); function OperatorExpression(name, args, afterSegments, meta) { var _this = _super.call(this, null, args, afterSegments, meta) || this; _this.type = 'OperatorExpression'; _this.name = name; _this.getFn = operatorFns.get[name]; _this.setFn = operatorFns.set[name]; return _this; } OperatorExpression.prototype.serialize = function () { return serializeObject.instance(this, this.name, this.args, this.afterSegments, this.meta); }; OperatorExpression.prototype.apply = function (context) { var inputs = this._getInputs(context); return this.getFn.apply(null, inputs); }; OperatorExpression.prototype.set = function (context, value) { var inputs = this._getInputs(context); inputs.unshift(value); var out = this.setFn.apply(null, inputs); for (var i in out) { this.args[i].set(context, out[i]); } }; return OperatorExpression; }(FnExpression)); exports.OperatorExpression = OperatorExpression; var SequenceExpression = /** @class */ (function (_super) { __extends(SequenceExpression, _super); function SequenceExpression(args, afterSegments, meta) { var _this = _super.call(this, ',', args, afterSegments, meta) || this; _this.type = 'SequenceExpression'; _this.getFn = operatorFns.get[',']; _this.args = args; _this.afterSegments = afterSegments; _this.meta = meta; return _this; } SequenceExpression.prototype.serialize = function () { return serializeObject.instance(this, this.args, this.afterSegments, this.meta); }; SequenceExpression.prototype.resolve = function (context) { var last = this.args[this.args.length - 1]; return last.resolve(context); }; SequenceExpression.prototype.dependencies = function (context, options) { var dependencies = []; for (var i = 0, len = this.args.length; i < len; i++) { var argDependencies = this.args[i].dependencies(context, options); for (var j = 0, jLen = argDependencies.length; j < jLen; j++) { dependencies.push(argDependencies[j]); } } return dependencies; }; return SequenceExpression; }(OperatorExpression)); exports.SequenceExpression = SequenceExpression; // For each method that takes a context argument, get the nearest parent view // context, then delegate methods to the inner expression var ViewParentExpression = /** @class */ (function (_super) { __extends(ViewParentExpression, _super); function ViewParentExpression(expression, meta) { var _this = _super.call(this, meta) || this; _this.type = 'ViewParentExpression'; _this.expression = expression; return _this; } ViewParentExpression.prototype.serialize = function () { return serializeObject.instance(this, this.expression, this.meta); }; ViewParentExpression.prototype.get = function (context) { var parentContext = context.forViewParent(); return this.expression.get(parentContext); }; ViewParentExpression.prototype.resolve = function (context) { var parentContext = context.forViewParent(); return this.expression.resolve(parentContext); }; ViewParentExpression.prototype.dependencies = function (context, options) { var parentContext = context.forViewParent(); return this.expression.dependencies(parentContext, options); }; ViewParentExpression.prototype.pathSegments = function (context) { var parentContext = context.forViewParent(); return this.expression.pathSegments(parentContext); }; ViewParentExpression.prototype.set = function (context, value) { var parentContext = context.forViewParent(); return this.expression.set(parentContext, value); }; return ViewParentExpression; }(Expression)); exports.ViewParentExpression = ViewParentExpression; var ScopedModelExpression = /** @class */ (function (_super) { __extends(ScopedModelExpression, _super); function ScopedModelExpression(expression, meta) { var _this = _super.call(this, meta) || this; _this.type = 'ScopedModelExpression'; _this.expression = expression; _this.meta = meta; return _this; } ScopedModelExpression.prototype.serialize = function () { return serializeObject.instance(this, this.expression, this.meta); }; // Return a scoped model instead of the value ScopedModelExpression.prototype.get = function (context) { var segments = this.pathSegments(context); if (!segments) return; return context.controller.model.scope(segments.join('.')); }; // Delegate other methods to the inner expression ScopedModelExpression.prototype.resolve = function (context) { return this.expression.resolve(context); }; ScopedModelExpression.prototype.dependencies = function (context, options) { return this.expression.dependencies(context, options); }; ScopedModelExpression.prototype.pathSegments = function (context) { return this.expression.pathSegments(context); }; ScopedModelExpression.prototype.set = function (context, value) { return this.expression.set(context, value); }; return ScopedModelExpression; }(Expression)); exports.ScopedModelExpression = ScopedModelExpression; function getDependencies(value, context, options) { if (value instanceof Expression || value instanceof templates_1.Template) { return value.dependencies(context, options); } } function appendDependency(dependencies, expression, context) { var segments = expression.resolve(context); if (!segments) return dependencies; if (dependencies) { dependencies.push(segments); return dependencies; } return [segments]; } function swapLastDependency(dependencies, expression, context) { if (!expression.segments.length) { return dependencies; } var segments = expression.resolve(context); if (!segments) return dependencies; if (dependencies) { dependencies.pop(); dependencies.push(segments); return dependencies; } return [segments]; }