Comparing version 2.0.0 to 2.0.1
@@ -90,11 +90,11 @@ // @flow | ||
v1: IValue<T1>, | ||
) : void; | ||
) : IValue<T>; | ||
$bind<T, T1, T2> ( | ||
func : (a1 : T1, a2 : T2) => T, | ||
v1: IValue<T1>, v2: IValue<T2>, | ||
) : void; | ||
) : IValue<T>; | ||
$bind<T, T1, T2, T3> ( | ||
func : (a1 : T1, a2 : T2, a3 : T3) => T, | ||
v1: IValue<T1>, v2: IValue<T2>, v3: IValue<T3>, | ||
) : void; | ||
) : IValue<T>; | ||
$bind<T, T1, T2, T3, T4> ( | ||
@@ -104,3 +104,3 @@ func : (a1 : T1, a2 : T2, a3 : T3, a4 : T4) => T, | ||
v4: IValue<T4>, | ||
) : void; | ||
) : IValue<T>; | ||
$bind<T, T1, T2, T3, T4, T5> ( | ||
@@ -110,3 +110,3 @@ func : (a1 : T1, a2 : T2, a3 : T3, a4 : T4, a5 : T5) => T, | ||
v4: IValue<T4>, v5: IValue<T5>, | ||
) : void; | ||
) : IValue<T>; | ||
$bind<T, T1, T2, T3, T4, T5, T6> ( | ||
@@ -116,3 +116,3 @@ func : (a1 : T1, a2 : T2, a3 : T3, a4 : T4, a5 : T5, a6 : T6) => T, | ||
v4: IValue<T4>, v5: IValue<T5>, v6: IValue<T6>, | ||
) : void; | ||
) : IValue<T>; | ||
$bind<T, T1, T2, T3, T4, T5, T6, T7> ( | ||
@@ -123,3 +123,3 @@ func : (a1 : T1, a2 : T2, a3 : T3, a4 : T4, a5 : T5, a6 : T6, a7 : T7) => T, | ||
v7: IValue<T7>, | ||
) : void; | ||
) : IValue<T>; | ||
$bind<T, T1, T2, T3, T4, T5, T6, T7, T8> ( | ||
@@ -130,3 +130,3 @@ func : (a1 : T1, a2 : T2, a3 : T3, a4 : T4, a5 : T5, a6 : T6, a7 : T7, a8 : T8) => T, | ||
v7: IValue<T7>, v8: IValue<T8>, | ||
) : void; | ||
) : IValue<T>; | ||
$bind<T, T1, T2, T3, T4, T5, T6, T7, T8, T9> ( | ||
@@ -137,3 +137,3 @@ func : (a1 : T1, a2 : T2, a3 : T3, a4 : T4, a5 : T5, a6 : T6, a7 : T7, a8 : T8, a9 : T9) => T, | ||
v7: IValue<T7>, v8: IValue<T8>, v9: IValue<T9>, | ||
) : void; | ||
) : IValue<T>; | ||
@@ -334,3 +334,4 @@ $enable () : void; | ||
node : T, | ||
callback : ($ : T) => void | ||
callback : ($ : T) => void, | ||
callback1 : ($ : T) => void | ||
) : this; | ||
@@ -609,5 +610,5 @@ $if ( | ||
} | ||
declare export class Watch extends Fragment { | ||
slot : Slot<>; | ||
model : IValue<any>; | ||
declare export class Watch<T> extends Fragment { | ||
slot : Slot<T>; | ||
model : IValue<T>; | ||
@@ -614,0 +615,0 @@ constructor () : void; |
@@ -1,2 +0,2 @@ | ||
import { Extension } from "./node"; | ||
import { Fragment } from "./node"; | ||
import { Destroyable } from "../core/destroyable"; | ||
@@ -66,3 +66,3 @@ import { Signal } from "../core/signal"; | ||
*/ | ||
export class InterceptorNode extends Extension { | ||
export class InterceptorNode extends Fragment { | ||
constructor() { | ||
@@ -69,0 +69,0 @@ super(...arguments); |
@@ -207,4 +207,5 @@ import { Reactive, ReactivePrivate } from "../core/core"; | ||
* @param callback {function($ : *)} | ||
* @param callback1 {function($ : *)} | ||
*/ | ||
$create(node, callback) { | ||
$create(node, callback, callback1) { | ||
const $ = this.$; | ||
@@ -216,2 +217,5 @@ node.$.parent = this; | ||
} | ||
if (callback1) { | ||
callback1(node); | ||
} | ||
this.$$pushNode(node); | ||
@@ -952,2 +956,15 @@ node.$init().$ready(); | ||
} | ||
$$insertAdjacent(node) { | ||
if (this.$.unmounted) { | ||
if (this.$.next) { | ||
this.$.next.$$insertAdjacent(node); | ||
} | ||
else { | ||
this.$.parent.$$appendNode(node); | ||
} | ||
} | ||
else { | ||
super.$$insertAdjacent(node); | ||
} | ||
} | ||
$$appendNode(node) { | ||
@@ -1060,3 +1077,3 @@ const $ = this.$; | ||
*/ | ||
class SwitchedNode extends Extension { | ||
class SwitchedNode extends Fragment { | ||
/** | ||
@@ -1063,0 +1080,0 @@ * Constructs a switch node and define a sync function |
@@ -16,3 +16,3 @@ import { Fragment } from "./node"; | ||
$createWatchers() { | ||
this.$watch(() => { | ||
this.$watch((value) => { | ||
this.$children.forEach(child => { | ||
@@ -22,8 +22,8 @@ child.$destroy(); | ||
this.$children.splice(0); | ||
this.slot.release(this); | ||
this.slot.release(this, value); | ||
}, this.model); | ||
} | ||
$compose() { | ||
this.slot.release(this); | ||
this.slot.release(this, this.model.$); | ||
} | ||
} |
@@ -11,3 +11,3 @@ import { BaseView } from "./base-view"; | ||
super(); | ||
this.model = this.$ref(new ArrayModel); | ||
this.model = new ArrayModel; | ||
this.$seal(); | ||
@@ -19,4 +19,3 @@ } | ||
$ready() { | ||
const arr = this.model.$; | ||
arr.forEach(item => { | ||
this.model.forEach(item => { | ||
this.createChild(item, item); | ||
@@ -23,0 +22,0 @@ }); |
@@ -36,4 +36,4 @@ import { RepeatNode, RepeatNodePrivate } from "./repeat-node"; | ||
const $ = this.$; | ||
this.model.$.listener.onAdd($.addHandler); | ||
this.model.$.listener.onRemove($.removeHandler); | ||
this.model.listener.onAdd($.addHandler); | ||
this.model.listener.onRemove($.removeHandler); | ||
super.$ready(); | ||
@@ -46,6 +46,6 @@ } | ||
const $ = this.$; | ||
this.model.$.listener.offAdd($.addHandler); | ||
this.model.$.listener.offRemove($.removeHandler); | ||
this.model.listener.offAdd($.addHandler); | ||
this.model.listener.offRemove($.removeHandler); | ||
super.$destroy(); | ||
} | ||
} |
@@ -11,6 +11,6 @@ import { BaseView } from "./base-view"; | ||
super(); | ||
this.model = this.$ref(new MapModel); | ||
this.model = new MapModel; | ||
} | ||
$ready() { | ||
const map = this.model.$; | ||
const map = this.model; | ||
map.forEach((value, key) => { | ||
@@ -17,0 +17,0 @@ this.createChild(key, value); |
@@ -11,6 +11,6 @@ import { BaseView } from "./base-view"; | ||
super(); | ||
this.model = this.$ref(new ObjectModel); | ||
this.model = new ObjectModel; | ||
} | ||
$ready() { | ||
const obj = this.model.$; | ||
const obj = this.model; | ||
for (const key in obj) { | ||
@@ -17,0 +17,0 @@ this.createChild(key, obj[key]); |
@@ -11,7 +11,7 @@ import { BaseView } from "./base-view"; | ||
super(); | ||
this.model = this.$ref(new SetModel()); | ||
this.model = new SetModel(); | ||
} | ||
$ready() { | ||
const $ = this.$; | ||
const set = this.model.$; | ||
const set = this.model; | ||
set.forEach(item => { | ||
@@ -18,0 +18,0 @@ $.app.$run.callCallback(() => { |
@@ -6,3 +6,3 @@ { | ||
"types": "types/index.d.ts", | ||
"version": "2.0.0", | ||
"version": "2.0.1", | ||
"exports": { | ||
@@ -9,0 +9,0 @@ "import": "./lib/index.js", |
230
README.md
@@ -1,131 +0,165 @@ | ||
# Vasille.js | ||
# Vasille | ||
|Intro| | ||
|:---:| | ||
|![Vasille.js logo](https://gitlab.com/vasille-js/vasille-js/-/raw/master/img/logo.png)| | ||
|Vasille.js is **very fast** javascript frontend framework, it is not using virtual DOM, it updates DOM directly using an own reactive mechanism.| | ||
![Vasille.js logo](https://gitlab.com/vasille-js/vasille-js/-/raw/v2/img/logo.png) | ||
This framework is in active development, if you want to contribute contact | ||
the maintainer: Lelițac Vasile (lixcode@vivaldi.net). | ||
`Vasille` core library is frontend solution for `safe`, `fast` & `powerful` applications. | ||
### Table of content | ||
## Table of content | ||
[[_TOC_]] | ||
## Project roadmap | ||
<hr> | ||
| Feature | Deadline | Status | | ||
|---------------------------------------------|--------------|------------| | ||
| Initial Version | 01.07.2021 | Ready | | ||
| Patch to 1.1 | 02.12.2021 | Ready | | ||
| Describe API | 02.14.2021 | Ready | | ||
| Describe JS API | 02.15.2021 | Ready | | ||
| Describe VCC architecture | 02.22.2021 | Waiting | | ||
| Code and debug VCC | 03.xx.2021 | | | ||
| First enterprise ready version | xx.xx.2021 | | | ||
| Boost by HTML templates | xx.xx.2021 | | | ||
## Installation | ||
## API documentation | ||
``` | ||
npm install vasille --save | ||
``` | ||
### Getting ready be example | ||
* JavaScript Example | ||
* TypeScript Example | ||
* Flow.js Example | ||
Currently, the [API](pages/API.md) is in development, | ||
but the [JavaScript API](pages/JavaScriptAPI.md) | ||
is available. | ||
### Flow.js typedef | ||
Add the next line to `[libs]` section in your `.flowconfig` file | ||
``` | ||
node_modules/vasille/flow-typed | ||
``` | ||
* [API Documentation](https://gitlab.com/vasille-js/vasille-js/-/blob/master/pages/API.md) | ||
* [JS API Documentation](https://gitlab.com/vasille-js/vasille-js/-/blob/master/pages/JavaScriptAPI.md) | ||
<hr> | ||
## Tools in development | ||
## How SAFE is Vasille | ||
* **Vasille.js** is a component based framework without any dependencies | ||
* **Reactive Reference** is a build in reactivity library of Vasille.js | ||
* **Vasille Language** is a user-friendy language to describe Vasille.js | ||
components | ||
* **VCC** (*Vasille Component Compiler*) translate code from Vasille | ||
language to high-effective Vasille.js components performing a | ||
lot of performance improvements. | ||
## How it works | ||
The safe of your application is ensured by | ||
* `100%` coverage of `vasille` code by unit tests. | ||
Each function, each branch are working as designed. | ||
* `strong typing` makes your javascript/typescript code safe as C++ code. | ||
All entities of `vasille` core library are strong typed, including: | ||
* data fields & properties. | ||
* computed properties (function parameters & result). | ||
* methods. | ||
* events (defined handlers & event emit). | ||
* DOM events & DOM operation (attributing, styling, etc.). | ||
* slots of component. | ||
* references to children. | ||
* What you write is what you get - there is no hidden operations, you can control everything. | ||
* No asynchronous code, when the line of code is executed, the DOM and reactive things are already synced. | ||
To test the speed of frameworks (inclusive Vasille JS) I had created a map, | ||
which can be zoomed up to 32x, this project was called "Project x32". | ||
## How FAST is Vasille | ||
On the next image is demonstrated the difference between 1x zoom (on the | ||
left side) and x32 zoom (on the right side): | ||
![x1-x32](https://gitlab.com/vasille-js/vasille-js/-/raw/master/img/x1-x32.png) | ||
The test project was coded using the next frameworks: | ||
* Angular / | ||
[Try Initial](https://vasille-js.gitlab.io/project-x32/angular/) / | ||
[Try Optimized](https://vasille-js.gitlab.io/project-x32-if/angular/). | ||
* React / | ||
[Try Initial](https://vasille-js.gitlab.io/project-x32/react/) / | ||
[Try Optimized](https://vasille-js.gitlab.io/project-x32-if/react/). | ||
* Vue 2 / | ||
[Try Initial](https://vasille-js.gitlab.io/project-x32/vue-2/) / | ||
[Try Optimized](https://vasille-js.gitlab.io/project-x32-if/vue-2/). | ||
* Vue 3 / | ||
[Try Initial](https://vasille-js.gitlab.io/project-x32/vue-3/) / | ||
[Try Optimized](https://vasille-js.gitlab.io/project-x32-if/vue-3/). | ||
* Svelte / | ||
[Try Initial](https://vasille-js.gitlab.io/project-x32/svelte/) / | ||
[Try Optimized](https://vasille-js.gitlab.io/project-x32-if/svelte/). | ||
* Vasille / | ||
[Try Initial](https://vasille-js.gitlab.io/project-x32/vasille-js/) / | ||
[Try Optimized](https://vasille-js.gitlab.io/project-x32-if/vasille-js/). | ||
There are 100 random squares over each brick, on small zoom the squares | ||
are hidden to optimize browser performance, because the page is composed | ||
of over than 23 000 nodes. The random squares added one by one to not | ||
freeze zoom animation. The zoom animation duration is 300ms, and it | ||
must consist of 20 frames on 60Hz screen. | ||
The result of test are demonstrated in figures 1 & 2. | ||
The test result are measured in FPS (frames per second), which is calculated as `1000 / ft`, | ||
where `ft` is an average frame time in ms of 20 frames. All values are absolute. Higher is better. | ||
The project x32 was coded using the next frameworks: | ||
* Angular. | ||
* React. | ||
* Vue 2. | ||
* Vue 3. | ||
* Svelte. | ||
* Vasille JS. | ||
The initial version is updating all the page content in each frame. | ||
The page reactivity connections are very complex, and we get poor results in Angular, React, Vue & Svelte. | ||
### Measuring zoom performance | ||
The optimized version disables the offscreen & non-actual content, which simplifies the | ||
reactivity complexity in time. Angular & Svelte give result similar to Vasille. | ||
React & Vue continue to be slow in the beginning of test. | ||
After zooming in each production build and measuring performance | ||
I had got the next results: | ||
![results 1](https://gitlab.com/vasille-js/vasille-js/-/raw/master/img/scores-wo.png) | ||
**Conclusion:** The reactivity system of Vasille is very fast | ||
and its complexity is not slowing down the application. | ||
The Vue & React builds are the slowest: the average frame time of: | ||
* React build is 1263.48ms. | ||
* Vue 3 build is 971.80ms. | ||
* Vue 2 build is 823.56ms. | ||
<hr> | ||
There is the same graphic in logarithmic scale: | ||
![results 1](https://gitlab.com/vasille-js/vasille-js/-/raw/master/img/scores-wo-log.png) | ||
| ||
Let's analyze the Angular, Svelte & Vasille JS results: | ||
* Angular & Svelte has a similar result, the average time of frame | ||
is 53.94ms for Angular & 53.98 for Svelte. | ||
* The Vasille JS is the unique framework which support the zoom | ||
animation at 60fps without any additional optimization. | ||
Average time of frame is 3.22ms. | ||
Figure 1: Initial version | ||
#### Try it: | ||
* [Project x32 powered by Angular](https://vasille-js.gitlab.io/project-x32/angular/) | ||
* [Project x32 powered by React](https://vasille-js.gitlab.io/project-x32/react/) | ||
* [Project x32 powered by Vue 2](https://vasille-js.gitlab.io/project-x32/vue-2/) | ||
* [Project x32 powered by Vue 3](https://vasille-js.gitlab.io/project-x32/vue-3/) | ||
* [Project x32 powered by Svelte](https://vasille-js.gitlab.io/project-x32/svelte/) | ||
* [Project x32 powered by Vasille JS](https://vasille-js.gitlab.io/project-x32/vasille-js/) | ||
![results 1](https://gitlab.com/vasille-js/vasille-js/-/raw/v2/img/scores-wo.png) | ||
### Let's optimize Project x32 | ||
<hr> | ||
To optimize the Project x32 realizations, the optimization consist | ||
of removing the off-screen components, that change will decrease | ||
the number of components. So let's zoom each optimized build | ||
from x1 to x32. | ||
| ||
Tests results: | ||
![results 2](https://gitlab.com/vasille-js/vasille-js/-/raw/master/img/scores-o.png) | ||
Figure 2: Optimized version | ||
After X8 the number of onscreen components is very small, the optimization has a good result. | ||
The Reactive frameworks are the slowest before and after optimization. | ||
![results 2](https://gitlab.com/vasille-js/vasille-js/-/raw/v2/img/scores-o.png) | ||
There is the same graphic in logarithmic scale: | ||
![results 2](https://gitlab.com/vasille-js/vasille-js/-/raw/master/img/scores-o-log.png) | ||
<hr> | ||
After optimization Angular, Svelte & Vasille JS has very good | ||
results close to Vasille JS before optimization. | ||
## How POWERFUL is Vasille | ||
#### Try it: | ||
* [Optimized Project x32 powered by Angular](https://vasille-js.gitlab.io/project-x32-if/angular/) | ||
* [Optimized Project x32 powered by React](https://vasille-js.gitlab.io/project-x32-if/react/) | ||
* [Optimized Project x32 powered by Vue 2](https://vasille-js.gitlab.io/project-x32-if/vue-2/) | ||
* [Optimized Project x32 powered by Vue 3](https://vasille-js.gitlab.io/project-x32-if/vue-3/) | ||
* [Optimized Project x32 powered by Svelte](https://vasille-js.gitlab.io/project-x32-if/svelte/) | ||
* [Optimized Project x32 powered by Vasille JS](https://vasille-js.gitlab.io/project-x32-if/vasille-js/) | ||
The secret of `Vasille` is a good task decomposition. The core library is composed of | ||
an effective reactive module and a DOM generation engine based on it. | ||
## Conclusions | ||
The main goal of Vasille JS is not to be the fastest JavaScript framework, | ||
but to ensure excellent performance without any optimizations. | ||
<hr> | ||
### Reactivity Module | ||
Reactivity module is used to create a model of data. It can contain self-updating values, | ||
forward-only shared data. Reactivity of objects/fields can be disabled/enabled manually. | ||
![Reactivity Module](https://gitlab.com/vasille-js/vasille-js/-/raw/v2/img/reactive.png) | ||
* `Destroyable` is an entity which has a custom destructor. | ||
* `IValue<T>` is a common interface for any value container, with next members: | ||
* `get $` gets the encapsulated value. | ||
* `set $` manually update the encapsulated value, if enabled triggers updating of all linked data. | ||
* `disable` disables the reactivity. | ||
* `enable` enables the reactivity and triggers updating of all linked data. | ||
* `Reference<T>` contains a value of type `T`. | ||
* `Mirror<T>` syncs self value with another `IValue` container, can be used to share a value forward-only. | ||
* `Pointer<T>` same as `Mirror`, but it can switch between `IValue` target anytime. | ||
* `Expression<ReturnType, Args...>` is a self-updating value. | ||
* `Reactive` is a reactive object which can have multiple reactive fields, emit/receive events/signals. | ||
<hr> | ||
### DOM Generation Engine | ||
DOM Generation Engine is used to describe a virtual DOM of reactive fragments, | ||
which will be reflected into a browser DOM and keep up to date it. | ||
![DOM Generation Engine](https://gitlab.com/vasille-js/vasille-js/-/raw/v2/img/nodes.png) | ||
* `Fragment` describes a virtual DOM node, which has siblings, children, parent & slots. | ||
* `TextNode` reflects a `Text` node. | ||
* `INode` reflects a `Element` node. | ||
* `Tag` reflect a self created `Element` node. | ||
* `Extension` reflects an existing `Element` node. | ||
* `Component` reflects a `Element` node created by a `Tag` child. | ||
* `AppNode` is root of a `Vasille` application, can be used to create applications in application. | ||
* `App` is root of a definitive `Vasille` application. | ||
* `DebugNode` reflects a `Comment` node, useful for debug. | ||
* `Watch` recompose children nodes on model value change. | ||
* `RepeatNode` creates multiples children nodes using the same code multiple time. | ||
* `Repeater` repeat slot content `n` times. | ||
* `BaseView` represent a view in context of MVC (Model-View-Controller). | ||
* `ObjectView` repeats slot content for each value of `ObjectModel`. | ||
* `MapView` repeats slot content for each `MapModel` value. | ||
* `SetView` repeats slot content for each `SetModel` value. | ||
* `ArrayView` repeats slot content for each `ArrayModel` value respecting its order. | ||
* `InterceptorNode` is used to send an event/signal from one child to other | ||
without manually creating of interceptors. | ||
## API documentation | ||
There are several API, and most of it are WIP (Work In Progress): | ||
* [OOP API - Ready](https://gitlab.com/vasille-js/vasille-js/-/blob/v2/pages/OOP-API.md) | ||
* [Procedural API - WIP](https://gitlab.com/vasille-js/vasille-js/-/blob/v2/pages/Procedural-API.md) | ||
* [Final API - WIP](https://gitlab.com/vasille-js/vasille-js/-/blob/v2/pages/API.md) | ||
## Questions | ||
@@ -132,0 +166,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { Extension } from "./node"; | ||
import { Fragment } from "./node"; | ||
import { Destroyable } from "../core/destroyable"; | ||
@@ -38,3 +38,3 @@ import { Signal } from "../core/signal"; | ||
*/ | ||
export declare class InterceptorNode<t1 = void, t2 = void, t3 = void, t4 = void, t5 = void, t6 = void, t7 = void, t8 = void, t9 = void> extends Extension { | ||
export declare class InterceptorNode<t1 = void, t2 = void, t3 = void, t4 = void, t5 = void, t6 = void, t7 = void, t8 = void, t9 = void> extends Fragment { | ||
/** | ||
@@ -41,0 +41,0 @@ * Internal interceptor |
@@ -130,4 +130,5 @@ import { Reactive, ReactivePrivate } from "../core/core"; | ||
* @param callback {function($ : *)} | ||
* @param callback1 {function($ : *)} | ||
*/ | ||
$create<T extends Fragment>(node: T, callback?: ($: T) => void): this; | ||
$create<T extends Fragment>(node: T, callback?: ($: T) => void, callback1?: ($: T) => void): this; | ||
/** | ||
@@ -640,2 +641,3 @@ * Defines an if node | ||
protected $$findFirstChild(): Node; | ||
$$insertAdjacent(node: Node): void; | ||
$$appendNode(node: Node): void; | ||
@@ -642,0 +644,0 @@ /** |
@@ -9,3 +9,3 @@ import { Fragment } from "./node"; | ||
*/ | ||
export declare class Watch extends Fragment { | ||
export declare class Watch<T> extends Fragment { | ||
/** | ||
@@ -15,3 +15,3 @@ * Default slot | ||
*/ | ||
slot: Slot; | ||
slot: Slot<T>; | ||
/** | ||
@@ -21,3 +21,3 @@ * iValue to watch | ||
*/ | ||
model: IValue<unknown>; | ||
model: IValue<T>; | ||
constructor(); | ||
@@ -24,0 +24,0 @@ $createWatchers(): void; |
import { RepeatNode, RepeatNodePrivate } from "./repeat-node"; | ||
import { IValue } from "../core/ivalue"; | ||
import { IModel } from "../models/model"; | ||
@@ -32,5 +31,5 @@ /** | ||
* Property which will contain a model | ||
* @type {IValue<*>} | ||
* @type {IModel} | ||
*/ | ||
model: IValue<Model>; | ||
model: Model; | ||
constructor($1?: BaseViewPrivate<K, T>); | ||
@@ -37,0 +36,0 @@ /** |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
5878
174
0
196418
70