Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 45 additions & 28 deletions bind.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,16 @@ function bind(target, targetPath, descriptor) {
var convert = descriptor.convert;
var revert = descriptor.revert;

var sourceSyntax = descriptor.sourceSyntax = parse(sourcePath);
var targetSyntax = descriptor.targetSyntax = parse(targetPath);
var sourceSyntax = descriptor.sourceSyntax = bind.parse(sourcePath);
var targetSyntax = descriptor.targetSyntax = bind.parse(targetPath);

var solution = solve(targetSyntax, sourceSyntax);
var solution = bind.solve(targetSyntax, sourceSyntax);
targetSyntax = solution[0];
sourceSyntax = solution[1];

if (twoWay) {
if (targetSyntax.type === "rangeContent") {
return bindRangeContent(
return bind.bindRangeContent(
targetScope,
targetSyntax.args[0],
sourceScope,
Expand All @@ -87,9 +87,14 @@ function bind(target, targetPath, descriptor) {
}
}

var cancel = function cancel() {
cancel.cancelSourceToTarget();
cancel.cancelTargetToSource();
};

// <- source to target
trace && console.log("DEFINE BINDING", targetPath, ONE_WAY, sourcePath, target);
var cancelSourceToTarget = bindOneWay(
cancel.cancelSourceToTarget = bind.bindOneWay(
targetScope,
targetSyntax,
sourceScope,
Expand All @@ -100,15 +105,15 @@ function bind(target, targetPath, descriptor) {
);

// flip the arrow
var solution = solve(sourceSyntax, targetSyntax);
var solution = bind.solve(sourceSyntax, targetSyntax);
sourceSyntax = solution[0];
targetSyntax = solution[1];

// -> target to source
var cancelTargetToSource = Function.noop;
if (twoWay) {
trace && console.log("DEFINE BINDING", targetPath, ONE_WAY_RIGHT, sourcePath, source);
cancelTargetToSource = bindOneWay(
cancelTargetToSource = bind.bindOneWay(
sourceScope,
sourceSyntax,
targetScope,
Expand All @@ -118,14 +123,16 @@ function bind(target, targetPath, descriptor) {
trace
);
}
cancel.cancelTargetToSource = cancelTargetToSource;

return function cancel() {
cancelSourceToTarget();
cancelTargetToSource();
};

return cancel;
}

bind.parse = parse;
bind.solve = solve;
bind.bindOneWay = bindOneWay;
bind.bindRangeContent = bindRangeContent;

function bindOneWay(
targetScope,
targetSyntax,
Expand All @@ -136,7 +143,7 @@ function bindOneWay(
trace
) {

var observeSource = compileObserver(sourceSyntax);
var observeSource = bindOneWay.compileObserver(sourceSyntax);
if (convert) {
observeSource = Observers.makeConverterObserver(
observeSource,
Expand All @@ -145,7 +152,7 @@ function bindOneWay(
);
}

var bindTarget = compileBinder(targetSyntax);
var bindTarget = bindOneWay.compileBinder(targetSyntax);
return bindTarget(
observeSource,
sourceScope,
Expand All @@ -158,6 +165,8 @@ function bindOneWay(
);

}
bindOneWay.compileObserver = compileObserver;
bindOneWay.compileBinder = compileBinder;

function bindRangeContent(
targetScope,
Expand All @@ -170,10 +179,10 @@ function bindRangeContent(
trace
) {

var observeSource = compileObserver(sourceSyntax);
var observeTarget = compileObserver(targetSyntax);
var assignSource = compileAssigner(sourceSyntax);
var assignTarget = compileAssigner(targetSyntax);
var observeSource = bindRangeContent.compileObserver(sourceSyntax);
var observeTarget = bindRangeContent.compileObserver(targetSyntax);
var assignSource = bindRangeContent.compileAssigner(sourceSyntax);
var assignTarget = bindRangeContent.compileAssigner(targetSyntax);

var cancel = Function.noop;

Expand All @@ -193,7 +202,7 @@ function bindRangeContent(
// prevent the target from overwriting an existing source.

isActive = true;
var cancelTargetObserver = observeTarget(function replaceRangeContentTarget(_target) {
cancelRangeContentBinding.cancelTargetObserver = observeTarget(function replaceRangeContentTarget(_target) {
cancel();
cancel = Function.noop;
trace && console.log("RANGE CONTENT TARGET", trace.targetPath, "SET TO", _target);
Expand All @@ -213,7 +222,7 @@ function bindRangeContent(
}, targetScope);
isActive = false;

var cancelSourceObserver = observeSource(function replaceRangeContentSource(_source) {
cancelRangeContentBinding.cancelSourceObserver = observeSource(function replaceRangeContentSource(_source) {
cancel();
cancel = Function.noop;
trace && console.log("RANGE CONTENT SOURCE", trace.sourcePath, "SET TO", _source);
Expand Down Expand Up @@ -261,19 +270,27 @@ function bindRangeContent(
}
trace && console.log("RANGE CONTENT BOUND", trace.targetPath, TWO_WAY, trace.sourcePath);
isActive = true;
var cancelSourceRangeChangeObserver = observeRangeChange(source, sourceRangeChange, sourceScope);
var cancelTargetRangeChangeObserver = observeRangeChange(target, targetRangeChange, targetScope);
cancelRangeContentBinding.cancelSourceRangeChangeObserver = observeRangeChange(source, sourceRangeChange, sourceScope);
cancelRangeContentBinding.cancelTargetRangeChangeObserver = observeRangeChange(target, targetRangeChange, targetScope);
isActive = false;
return function cancelRangeContentBinding() {

function cancelRangeContentBinding() {
trace && console.log("RANGE CONTENT UNBOUND", trace.targetPath, TWO_WAY, trace.sourcePath);
cancelSourceRangeChangeObserver();
cancelTargetRangeChangeObserver();
cancelRangeContentBinding.cancelSourceRangeChangeObserver();
cancelRangeContentBinding.cancelTargetRangeChangeObserver();
};

return cancelRangeContentBinding;
}

return function cancelRangeContentBinding() {
function cancelRangeContentBinding() {
cancel();
cancelTargetObserver();
cancelSourceObserver();
cancelRangeContentBinding.cancelTargetObserver();
cancelRangeContentBinding.cancelSourceObserver();
};

return cancelRangeContentBinding;
}
bindRangeContent.compileObserver = compileObserver;
bindRangeContent.compileAssigner = compileAssigner;

24 changes: 15 additions & 9 deletions bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,17 @@ function defineBinding(object, name, descriptor, commonDescriptor) {
if (bindingsForName.has(name)) {
throw new Error("Can't bind to already bound target, " + JSON.stringify(name));
}
else if (ONE_WAY in descriptor || TWO_WAY in descriptor || COMPUTE in descriptor) {
//Replaced (ONE_WAY in descriptor[ONE_WAY] || TWO_WAY in descriptor || COMPUTE in descriptor)
else if (descriptor[ONE_WAY] || descriptor[TWO_WAY] || descriptor[COMPUTE]) {
bindingsForName.set(name,descriptor);
descriptor.target = object;
if((parameters = descriptor.parameters || commonDescriptor.parameters))
descriptor.parameters = parameters;
if((document = descriptor.document || commonDescriptor.document))
descriptor.document = document;
descriptor.components = descriptor.components || commonDescriptor.components;

descriptor.cancel = (COMPUTE in descriptor)
//Replaced (COMPUTE in descriptor)
descriptor.cancel = (descriptor[COMPUTE])
? defineBinding.compute(object, name, descriptor)
: defineBinding.bind(object, name, descriptor);

Expand All @@ -74,33 +75,36 @@ defineBinding.bind = bind;
exports.getBindings = getBindings;
function getBindings(object) {
var value;
return bindingsForObject.get(object) || (bindingsForObject.set(object, ( value = new Map)) && value);
return getBindings.bindingsForObject.get(object) || (getBindings.bindingsForObject.set(object, ( value = new Map)) && value);
}
getBindings.bindingsForObject = bindingsForObject;

exports.getBinding = getBinding;
function getBinding(object, name) {
var bindingsForName = getBindings(object);
return bindingsForName.get(name);
return getBinding.getBindings(object).get(name);
}
getBinding.getBindings = getBindings;

exports.cancelBindings = cancelBindings;
function cancelBindings(object) {
var bindings = getBindings(object),
mapIter = bindings.keys();

while (name = mapIter.next().value) {
cancelBinding(object, name, bindings);
cancelBindings.cancelBinding(object, name, bindings);
}

// for (var name in bindings) {
// cancelBinding(object, name);
// }
}
cancelBindings.getBindings = getBindings;
cancelBindings.cancelBinding = cancelBinding;

exports.cancelBinding = cancelBinding;
function cancelBinding(object, name, bindings/*private argument to call from cancelBindings*/) {
if(!bindings) {
bindings = getBindings(object);
bindings = cancelBinding.getBindings(object);
if (!bindings.has(name)) {
throw new Error("Can't cancel non-existent binding to " + JSON.stringify(name));
}
Expand All @@ -112,7 +116,9 @@ function cancelBinding(object, name, bindings/*private argument to call from can
exports.count--;

if (bindings.size < 1) {
bindingsForObject.delete(object);
cancelBinding.bindingsForObject.delete(object);
}
}
}
cancelBinding.getBindings = getBindings;
cancelBinding.bindingsForObject = bindingsForObject;
45 changes: 28 additions & 17 deletions compile-evaluator.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,44 +299,55 @@ var semantics = compile.semantics = {
} else {
if (!operators.hasOwnProperty(syntax.type)) {
operators[syntax.type] = function (object) {
var args = Array.prototype.slice.call(arguments, 1);
if (!object[syntax.type])
throw new TypeError("Can't call " + JSON.stringify(syntax.type) + " of " + object);

if(args.length === 1) {
return object[syntax.type].call(object, args[0]);
if(arguments.length === 2) {
return object[syntax.type].call(object, arguments[1]);
}
else if(args.length === 2) {
return object[syntax.type].call(object, args[0], args[1]);
else if(arguments.length === 3) {
return object[syntax.type].call(object, arguments[1], arguments[2]);
}
else {
var args = Array.prototype.slice.call(arguments, 1);
return object[syntax.type].apply(object, args);
}

};
}
var operator = operators[syntax.type];
var argEvaluators = syntax.args.map(this.compile, this);
return function (scope) {
var args = argEvaluators.map(function (evaluateArg) {
return evaluateArg(scope);
});
if (!args.every(Operators.defined))
return;
var compiledSyntax = function compiledSyntax(scope) {
var args = [], i, iArg,
argEvaluators = compiledSyntax.argEvaluators,
argEvaluator = compiledSyntax.argEvaluator,
evaluatedArg;

for(i=0;(iArg = argEvaluators[i]);i++) {
evaluatedArg = iArg(scope);
if(Operators.defined(evaluatedArg)) {
args[i] = (iArg(scope));
}
else {
return;
}
}

if(args.length === 1) {
return operator.call(null, args[0]);
return compiledSyntax.operator.call(null, args[0]);
}
else if(args.length === 2) {
return operator.call(null, args[0], args[1]);
return compiledSyntax.operator.call(null, args[0], args[1]);
}
else {
return operator.apply(null, args);
return compiledSyntax.operator.apply(null, args);
}

};
compiledSyntax.operator = operators[syntax.type];
compiledSyntax.argEvaluators = syntax.args.map(this.compile, this);
compiledSyntax.argEvaluator = this.argEvaluator;

return compiledSyntax;
}

}

};
35 changes: 21 additions & 14 deletions compile-observer.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,8 @@ var semantics = compile.semantics = {
},

compile: function compile(syntax) {
var compilers = this.compilers,
syntaxType = syntax.type;
if (syntax.type === LITERAL) {
var syntaxType = syntax.type;
if (syntaxType === LITERAL) {
return Observers.makeLiteralObserver(syntax.value);
} else if (syntaxType === VALUE) {
return Observers.observeValue;
Expand All @@ -94,20 +93,28 @@ var semantics = compile.semantics = {
}
return Observers.makeObjectObserver(observers);
} else {
if (!compilers.hasOwnProperty(syntaxType)) {
compilers[syntaxType] = Observers.makeMethodObserverMaker(syntaxType);
if (!this.compilers.hasOwnProperty(syntaxType)) {
this.compilers[syntaxType] = Observers.makeMethodObserverMaker(syntaxType);
}

var argObservers = [];
for(var i=0, args = syntax.args, countI = args.length;i<countI;i++) {
argObservers[i] = this.compile(args[i]);
var args = syntax.args,
countI = args.length;
if (countI === 1) {
return this.compilers[syntaxType].call(null, this.compile(args[0]));
}
else if (countI === 2) {
return this.compilers[syntaxType].call(null, this.compile(args[0]), this.compile(args[1]));
}
else if (countI === 3) {
return this.compilers[syntaxType].call(null, this.compile(args[0]), this.compile(args[1]), this.compile(args[2]));
}
else {
var argObservers = [];
for(var i=0;i<countI;i++) {
argObservers[i] = this.compile(args[i]);
}
return this.compilers[syntaxType].apply(null, argObservers);
}

return (countI === 1)
? compilers[syntaxType].call(null, argObservers[0])
: (countI === 2)
? compilers[syntaxType].call(null, argObservers[0], argObservers[1])
: compilers[syntaxType].apply(null, argObservers);
}
}

Expand Down
Loading