diff --git a/extra.mjs b/extra.mjs index c231999..9a3134a 100644 --- a/extra.mjs +++ b/extra.mjs @@ -1,33 +1,23 @@ import reactive from "./reactive.mjs" import readable from "./readable.mjs" -import observe from "./observe.mjs" +import { + Observer, + iObserver +} from "./observer.mjs" import { fullpipe } from "./utils.mjs" - import { constant, pipe, isUndefined, noop } from "./operation.mjs" -import { - injectProperties -} from "./tools.mjs" import { DomPrinter } from "./dom.mjs" -/** - * Base class for controllers, models and Views - */ -export class EventBroker { - constructor(){ - observe.call(this) - } -} - /** * it handle the data logic of the app * it takes an array of names that will be @@ -38,14 +28,13 @@ export class EventBroker { */ export function Model(self, ...props){ - class Model extends self { + class Model extends iObserver(self) { constructor(...args){ super(...args) initModel.apply(this, props) } } reactive.call(Model.prototype) - observe.call(Model.prototype) return Model; } @@ -62,11 +51,10 @@ function initModel(...props){ * @param {function} render */ -export class ViewBase extends EventBroker {} - -injectProperties.call(ViewBase.prototype, { - print: new DomPrinter() -}) +export class ViewBase extends Observer { + print = new DomPrinter() + render(){} +} export function View(render = constant("")) { class View extends ViewBase { @@ -83,7 +71,7 @@ export function View(render = constant("")) { * calling the method trigger */ const HANDLERS = Symbol('handlers'); -export class Router extends EventBroker { +export class Router extends Observer { constructor(method = "reduce", handler = reducer) { super() this[HANDLERS] = []; @@ -147,13 +135,11 @@ class Handler { */ const REGISTERED = Symbol('registered') const TRIGGER = Symbol("trigger") -export class Controller extends EventBroker { +export class Controller extends Observer { + [REGISTERED] = {} constructor(init = {}, trigger = pipe){ super() - Object.assign( - this[REGISTERED] = {}, - init - ) + this[REGISTERED] = init this[TRIGGER] = trigger; } @@ -196,7 +182,7 @@ function getter(self, p) { * @param {function} handler */ -export class Gateway extends EventBroker { +export class Gateway extends Observer { constructor(handler = fullpipe){ super() this[HANDLER] = handler diff --git a/framework.mjs b/framework.mjs new file mode 100644 index 0000000..c30694b --- /dev/null +++ b/framework.mjs @@ -0,0 +1,16 @@ +import { iObserver } from "./observer.mjs" + +export class Base extends iObserver(class { + constructor() { + assign.apply(this, arguments) + } +}){} + +export function assign(...args){ + const proto = this.constructor.prototype + Object.assign(this, ...args) + if(proto !== Object.getPrototypeOf(this)) { + throw new TypeError("override __proto__") + } + return this +} \ No newline at end of file diff --git a/observe.mjs b/observer.mjs similarity index 89% rename from observe.mjs rename to observer.mjs index eeb67bc..f2872d5 100644 --- a/observe.mjs +++ b/observer.mjs @@ -1,5 +1,5 @@ /** - * Observable interface + * observer interface * @module * @see module:tools */ @@ -22,7 +22,7 @@ export const OBSERVERS = Symbol("observers") /** * Interface definition - * @interface observable + * @interface observer */ const HANDLERS = { on, @@ -34,12 +34,22 @@ const HANDLERS = { /** * Interface definition - * @lends observable + * @lends observer */ -export function observable() { +export function observer() { return injectProperties.call(this, HANDLERS) } -export default observable + +export default observer + +export function iObserver(self = Object) { + class Observer extends self {} + observer.call(Observer.prototype) + return Observer +} + +export const Observer = iObserver() + /** * Builds the event list if not exist diff --git a/reactive.mjs b/reactive.mjs index ea85608..3c1ba0c 100644 --- a/reactive.mjs +++ b/reactive.mjs @@ -24,6 +24,15 @@ export default function reactive() { return injectProperties.call(this, HANDLERS) } +export function iReactive(self = Object) { + class Reactive extends self {} + reactive.call(Reactive.prototype) + return Reactive +} + +export const Reactive = iReactive() + + function buildBinder (list, build, val) { var recurring = 0 const setter = (v) => { diff --git a/readable.mjs b/readable.mjs index 1192a90..f6e49b2 100644 --- a/readable.mjs +++ b/readable.mjs @@ -36,6 +36,14 @@ export default function readable( return injectProperties.call(this, opt) } +export function iReadable(self = Object) { + class Readable extends self {} + readable.call(Readable.prototype) + return Readable +} + +export const Readable = iReadable() + function broadcast(){ this[BUFFER] = arguments flush.apply(this, arguments) diff --git a/test.mjs b/test.mjs index 37e66cc..d4443b7 100644 --- a/test.mjs +++ b/test.mjs @@ -3,7 +3,7 @@ * @module * @see module:tools * @see module:reactive - * @see module:observe + * @see module:observer */ import { @@ -17,9 +17,13 @@ import { ASSERT_T, } from "./debug.mjs" -import observable from "./observe.mjs" +import { + Base +} from "./framework.mjs" -import reactive from "./reactive.mjs" +import { + iReactive +} from "./reactive.mjs" DEBUG(true) @@ -30,12 +34,12 @@ export const states = { PASSED: "PASSED" } -export class Test { - constructor(description, test = pipe, ...opt) { +export class Test extends iReactive(Base) { + constructor(description, test = pipe) { good(description, String) good(test, Function) + super() this.id = ++COUNTER - this.options = opt; this.description = description; this.test = test; this.bindable("result") @@ -70,9 +74,6 @@ export class Test { Test.prototype.print = consolePrinter; -observable.call(Test.prototype) -reactive.call(Test.prototype) - export default Test; async function resolver(args, ok, ko, resolve) { diff --git a/tests/run.mjs b/tests/run.mjs index e411f17..5001e86 100644 --- a/tests/run.mjs +++ b/tests/run.mjs @@ -4,7 +4,9 @@ import readable from "../readable.mjs"; import reactive from "../reactive.mjs"; import * as extra from "../extra.mjs"; import { - random, + Observer +} from "../observer.mjs"; +import { delay, RegObj, debounce, @@ -23,8 +25,7 @@ import { ASSERT_T, } from "../debug.mjs"; import { - View, - EventBroker + View } from "../extra.mjs"; const isBrowser = typeof Document != 'undefined' && document.body @@ -286,28 +287,32 @@ export async function testExtra() { export async function testRegObj() { return await new Test("reg obj", async () =>{ ASSERT_T("foobar!".match(new RegObj(/\w+(bar\!)/, "baz")).baz == "bar!") - }) + }).run() } -export async function testEventBroker() { - return await new Test("event broker", async () =>{ - var evt = new EventBroker() - var x = 0 +export async function testObserver() { + return await new Test("event broker", async (x = 0) =>{ + var evt = new Observer() var handler = () => ++x evt.on('one', handler) evt.on('two', handler) evt.on('three', handler) - + await delay(100) evt.fireLast('one') evt.fireLast('two') evt.fireLast('three') - + await delay(100) - + ASSERT_T(x == 1) - }) + var evt = new class extends Observer {}, y + evt.on('e', x => (y = x)) + evt.fire('e', x) + ASSERT_T(x == y) + return x + }).run() } export async function testDebounce() {