class BaseXYType {
constructor(stateValue) { // injected state object.
this.setX = function setX (x) {
return (stateValue.x = x);
};
this.setY = function setY (y) {
return (stateValue.y = y);
};
Object.defineProperty(this, "x", {
get: function getX () {
return stateValue.x;
},
enumerable: true
});
Object.defineProperty(this, "y", {
get: function getY () {
return stateValue.y;
},
enumerable: true
});
Object.defineProperty(this, 'valueOf', {
value: function valueOf () {
return Object.assign({}, stateValue);
}
});
Object.defineProperty(this, 'toString', {
value: function toString () {
return JSON.stringify(stateValue);
}
});
}
setPosition(x, y) { // prototypal method.
this.setX(x);
this.setY(y);
return this.valueOf();
}
}
class SameXYType extends BaseXYType {
// - Traits in JavaScript should be applicable types/objects that are
// just containers of trait and object composition rules which
// exclusively will be executed at a trait's apply time.
constructor(stateValue) { // injected state object.
super(stateValue);
withSameInternalXAndYState.call(this, stateValue);
}
}
var withSameInternalXAndYState = Trait.create(function (use, applicator) {
// local functions in order to enable shared code, thus achieving less memory consumption.
//
function afterReturningStateChangeXHandler(returnValue, argsArray, payloadList) {
var
stateValue = payloadList[0];
stateValue.y = argsArray[0]; // same y from x.
}
function afterReturningStateChangeYHandler(returnValue, argsArray, payloadList) {
var
stateValue = payloadList[0];
stateValue.x = argsArray[0]; // same x from y.
}
function setPositionInterceptor(proceedSetPosition, interceptor, argsArray, payloadList) {
var
x = argsArray[0],
y = argsArray[1];
if (x !== y) {
throw (new TypeError([x, "!==", y].join(" ")));
}
return proceedSetPosition.call(this, x, y);
}
applicator(function sameXAndYBehavior (stateValue) {
// no additional trait specific behavior within the applicator
}).requires([
"setX",
"setY",
"setPosition"
]).afterReturning(
"setX", afterReturningStateChangeXHandler
).afterReturning(
"setY", afterReturningStateChangeYHandler
).around(
"setPosition", setPositionInterceptor
);
});
var
base_1 = new BaseXYType({ x: 7, y: 11 }),
base_2 = new BaseXYType({ x: 99, y: 1 }),
same_1 = new SameXYType({ x: 13, y: 5 }),
same_2 = new SameXYType({ x: 99, y: 1 });
console.log('("" + base_1) : ', ("" + base_1));
console.log('("" + base_2) : ', ("" + base_2));
console.log('("" + same_1) : ', ("" + same_1));
console.log('("" + same_2) : ', ("" + same_2));
console.log('base_1.valueOf() : ', base_1.valueOf());
console.log('base_2.valueOf() : ', base_2.valueOf());
console.log('same_1.valueOf() : ', same_1.valueOf());
console.log('same_2.valueOf() : ', same_2.valueOf());
console.log('base_1.x : ', base_1.x);
console.log('(base_1.x = "foo") : ', (base_1.x = "foo"));
console.log('base_1.x : ', base_1.x);
console.log('base_1.y : ', base_1.y);
console.log('(base_1.y = "bar") : ', (base_1.y = "bar"));
console.log('base_1.y : ', base_1.y);
console.log('same_2.x : ', same_2.x);
console.log('(same_2.x = "biz") : ', (same_2.x = "biz"));
console.log('same_2.x : ', same_2.x);
console.log('same_2.y : ', same_2.y);
console.log('(same_2.y = "baz") : ', (same_2.y = "baz"));
console.log('same_2.y : ', same_2.y);
console.log('base_1.setY("foo") : ', base_1.setY("foo"));
console.log('base_1.y : ', base_1.y);
console.log('base_2.setX("bar") : ', base_2.setX("bar"));
console.log('base_2.x : ', base_2.x);
console.log('base_1.setPosition("brown", "fox") : ', base_1.setPosition("brown", "fox"));
console.log('("" + base_1) : ', ("" + base_1));
console.log('base_2.setPosition("lazy", "dog") : ', base_2.setPosition("lazy", "dog"));
console.log('("" + base_2) : ', ("" + base_2));
console.log('same_1.setY(543) : ', same_1.setY(543));
console.log('same_1.x : ', same_1.x);
console.log('same_1.y : ', same_1.y);
console.log('same_1.valueOf() : ', same_1.valueOf());
console.log('same_2.setY(79) : ', same_2.setY(79));
console.log('same_2.x : ', same_2.x);
console.log('same_2.y : ', same_2.y);
console.log('same_2.valueOf() : ', same_2.valueOf());
console.log('same_1.setPosition(77, 77) : ', same_1.setPosition(77, 77));
console.log('("" + same_1) : ', ("" + same_1));
console.log('same_2.setPosition(42, 42") : ', same_2.setPosition(42, 42));
console.log('("" + same_2) : ', ("" + same_2));
console.log('same_1.setPosition("apple", "pear") : ', same_1.setPosition("apple", "pear"));
console.log('("" + same_1) : ', ("" + same_1));
console.log('same_1.setPosition("apple", "pear") : ', same_1.setPosition("prune", "prune"));
console.log('("" + same_1) : ', ("" + same_1));
.as-console-wrapper { max-height: 100%!important; top: 0; }
<script>(function(r){function g(a){var c="none",b;Y(a)&&(ta(a)?c=ua:(b=Z(a),t("^class\s+"+a.name+"\s+\{").test(b)?c=va:t("\([^)]*\)\s+=>\s+\(").test(b)?c=wa:z(a)&&(c=xa(a)?ya:za(a)||Aa(a)||Ba(a)?Ca:aa)));return c===aa}function C(a){return["^\[object\s+",a,"\]$"].join("")}function v(a,c){var b=Da[c];return!!b&&0<=b.indexOf(a)}function M(a,c,b){return function(){var d=arguments;c.apply(b,d);return a.apply(b,d)}}function N(a,c,b){return function(){var d=arguments,e=a.apply(b,d);c.apply(b,d);return e}}function Ea(a,c,b,d){return function(){var e=arguments;c.call(b,e,d);return a.apply(b,e)}}function Fa(a,c,b,d){return function(){var e=arguments,f=a.apply(b,e);c.call(b,e,d);return f}}function Ga(a,c,b,d){return function(){var e=arguments,f=a.apply(b,e);c.call(b,f,e,d);return f}}function Ha(a,c,b,d){return function(){var e=arguments,f;try{f=a.apply(b,e)}catch(l){c.call(b,l,e,d)}return f}}function Ia(a,c,b,d){return function(){var e=arguments,f,g;try{f=a.apply(b,e)}catch(m){g=m}c.call(b,g||f,e,d);return f}}function Ja(a,c,b,d){return function(){return c.call(b,a,c,arguments,d)}}function Ka(a,c){return function(){var b=this[a];g(b)||(b=u);this[a]=M(b,c,this)}}function La(a,c){return function(){var b=this[a];g(b)||(b=u);this[a]=N(b,c,this)}}function Ma(a,c){return function(b){var d=this[a];g(d)||(d=u);this[a]=Ea(d,c,this,b)}}function Na(a,c){return function(b){var d=this[a];g(d)||(d=u);this[a]=Fa(d,c,this,b)}}function Oa(a,c){return function(b){var d=this[a];g(d)||(d=u);this[a]=Ga(d,c,this,b)}}function Pa(a,c){return function(b){var d=this[a];g(d)||(d=u);this[a]=Ha(d,c,this,b)}}function Qa(a,c){return function(b){var d=this[a];g(d)||(d=u);this[a]=Ia(d,c,this,b)}}function Ra(a,c){return function(b){var d=this[a];g(d)||(d=u);this[a]=Ja(d,c,this,b)}}function ba(a,c,b){a.useTraits.rules.push(new A({type:"without",traitList:c,methodNameList:b}))}function ca(a,c,b,d){a.useTraits.rules.push(new A({type:"as",trait:c,methodName:b,methodAlias:d}))}function da(a){return ea(p(a)).reduce(function(a,b){q(b)&&a.push(F(b));return a},[])}function fa(){var a,c,b,d,e;if(O(this))if(d=this.valueOf(),e=d.parentLink,w(e))if(b=e.getSetup(),a=b.chainData,c=a.recentCalleeName,v(c,"without"))if(c=da(arguments),1<=c.length)a.recentCalleeName="without",ba(b,d.traitList,c);else throw new h("Not even a single <String> type was passed to 'without' as to be excluded method name.");else{a=["u2026 invalid chaining of '",c,"().without()'"].join("");if("applyBehavior"==c)throw new n([a," in case of excluding one or more certain behaviors."].join(""));throw new n(a);}else throw new k("Please do not spoof the context of 'use'.");else throw new k("Please do not spoof the context of 'apply'.");return e}function P(a,c){var b=a.getSetup();if(Sa(c,a.valueOf().traitList))b.chainData.recentCalleeName="applyTraits",b=new Q({traitList:c,parentLink:a}),a.putChild(b);else throw new h("Any trait that got passed to 'apply' needs to be registered before via 'use'.");return b}function Sa(a,c){return a.every(function(a){return 0<=c.indexOf(a)})}function Ta(){var a;a=this.getSetup();var c=this.valueOf().traitList;I(this,a,a.chainData.recentCalleeName);a=P(this,c);return fa.apply(a,arguments)}function Ua(){var a=this.getSetup(),c=this.valueOf().traitList;I(this,a,a.chainData.recentCalleeName);return P(this,c)}function ga(){var a,c,b;b=p(arguments);if(w(this))if(a=this.getSetup(),c=a.chainData,c=c.recentCalleeName,I(this,a,c),a=["u2026 invalid chaining of '",c,"().apply()'"].join(""),v(c,"apply"))if(x(b[0]))if(q(b[1]))if(v(c,"applyBehavior")){c=b[0];b=F(b[1]);a=this.getSetup();var d;if(0<=this.valueOf().traitList.indexOf(c))if(d={},c.call(d),g(d[b]))a.chainData.recentCalleeName="applyBehavior",b=new R({trait:c,methodName:b,parentLink:this}),this.putChild(b);else throw new k(["The requested '",b,"' method has not been implemented by the trait that got passed to 'apply'."].join(""));else throw new h("Any trait that got passed to 'apply' needs to be registered before via 'use'.");}else throw new n([a," in case of applying just a certain behavior."].join(""));else if(p(b).every(x))if(v(c,"applyTraits"))b=P(this,b);else throw new n([a," in case of applying from one or more traits."].join(""));else throw new h("'apply(u2026)' excepts either, as its 2nd delimiting argument, just a 'String' type or exclusively one or more 'Trait' and 'Function' types.");else throw new h("'apply(<Trait|Function>, u2026)' excepts as its 1st argument explicitly either a 'Trait' or a 'Function' type.");else throw new n(a);else throw new k("'use(u2026).apply(u2026)' only works within a validly chained context, please do not try spoofing the latter.");return b}function ha(){var a;a=this;if(O(a)||G(a))a=a.valueOf(),a=a.parentLink,a=ga.apply(a,arguments);else throw new k("Please do not spoof the context of 'apply'.");return a}function I(a,c,b){var d,e;a&&!c.chainData.isTerminated&&(d=a.getChild())&&(e=d.valueOf())&&("applyTraits"==b&&O(d)?ba(c,e.traitList,[]):"applyBehavior"==b&&G(d)&&(a=e.methodName,ca(c,e.trait,a,a)));c.chainData.recentCalleeName="apply"}function R(a){this.valueOf=function(){return{trait:a.trait,methodName:a.methodName,parentLink:a.parentLink}};this.toString=function(){return["ApplyLink::singleBehavior :: ",S.stringify(a)].join("")};return this}function G(a){var c;return null!=a&&(a instanceof R||g(a.as)&&g(a.after)&&g(a.before)&&g(a.valueOf)&&(c=a.valueOf())&&x(c.trait)&&q(c.methodName)&&w(c.parentLink))}function Q(a){this.valueOf=function(){return{traitList:a.traitList,parentLink:a.parentLink}};this.toString=function(){return["ApplyLink::fromTraits :: ",S.stringify(a)].join("")};return this}function O(a){var c;return null!=a&&(a instanceof Q||g(a.without)&&g(a.valueOf)&&(c=a.valueOf())&&T(c.traitList)&&w(c.parentLink))}function U(a,c){var b=null;this.getSetup=function(){return c};this.deleteChild=function(){b=null};this.putChild=function(a){b=a};this.getChild=function(){return b};this.valueOf=function(){return{traitList:p(a.traitList)}};this.toString=function(){return["UseRoot :: ",S.stringify(a)].join("")};this.apply=g