+plus and +formation, what’s the difference?

+plus

+plus is the way to define and support mapping between DOM tree and data tree rooted at some object or namespace. So if you have these two declarations, markup:

<style>@import url(plus.css)</style>
<section model="person">
    <label>First</label> <input(name.first)>
    <label>Second</label> <input(name.last)>
    <label>Age</label> <input|integer(age)>
</section>

and script

namespace person {
  var name = { first: "Albert", last:"Einshtein" };
  var age = 53;
}

then the +plus will establish live two-way mapping (binding)  between DOM elements above and the data structure.

When the user changes value of input(name.first) field  (short form of <input name="name.first"> in Sciter) the following happens:

  1. Sciter generates “change” DOM event;
  2. +plus handles that event and
  3. updates value of person.name.first in data namespace.

And when data gets changed by some other code like

person.name.first = "Some other name";

then pretty much similar flow occurs:

  1. Sciter determines that filed first  has changed on observable object.
  2. Sciter calls attached function-observer – each object/array inside bound namespace has an observer function attached to it.
  3. And that function-observer updates bound DOM element.

As you see, in order binding to work both-ways, each data node (object, array) in bound namespace has to have corresponding observer attached to it.

+formation

The main difference from the above is that the +formation does not require separate data structure.  The formation is a data structure by itself naturally mapped to markup structure.

This markup:

<section(person)>
    <label>First</label> <input(name.first)>
    <label>Second</label> <input(name.last)>
    <label>Age</label> <input|integer(age)>
</section

gets mapped by formation() function to the [formation] tree structure:

And code can access that tree directly as:

var root = formation( self );
// setting whole formation:
root.person.value = {
   name : {
     first: "Albert",
     last: "Einshtein"
   },
   age:69
 };

// or setting particular field in the formation:
root.person.name.first.value = "Some other name";

Note: root.person.name.first is a direct reference to <input> DOM element thus .value is required.

The formation is a data structure derived from actual DOM tree (its projection)  and so you can use normal DOM events to be notified when some data changes by the user:

root.person.name.first.on("change", function() {...}) // or
self.on("change", "section[name=person]", function() {...}) // any change in person fields.

Resume

Essentially +plus and +formation are aimed to the same task – update UI from code and update/notify code about some changes in UI.

  • +plus
    • pros: Allows to bind arbitrary data structure to arbitrary DOM tree.
    • cons: Can be memory and CPU consuming on large data and DOM trees.
  • +formation
    • pros: Fast and not CPU consuming.  Yet allows to access “fields of interest” by using dot notation (“paths in formation”):  root.person.name.first.state.disabled = true;
    • cons: data structure you get (the formation tree) is bound with DOM structure. So when you change DOM structure then  formation paths in code may change.

Optimising ‘+=’ and ‘+’ operators for strings.

This simple code:

var s = "";
for(var i = 0; i < 50000; ++i) {
  s += "*";
}

code used to run in Sciter in 874ms.

After implementing simple and obvious optimization it runs now in just 4ms.

String concatenation was implemented as simple string allocation of size(r) = size(s1) + size(s2) and memcpy of s1 and s2 into that new string r.

Memory allocation in script is cheap - just increment memory pointer by size of requested memory chunk and you are done. So in theory that naïve strcat shall be lightning fast. But it is definitely not. There is a hidden cost of GC cycles - at the moment of concatenation r,s1 and s2 shall be present in memory.

So "0123456789" + "A" needs memory for 10 + 1 + 11 = 22 characters. And on each iteration that number increases - the VM is busy cleaning garbage most of the time.

So when someone from C# and Java crowds is saying you that memory allocation is cheap take it with a grain of salt.

Sciter assistant for Visual Studio Code

Early BETA of Sciter Assistant for Microsoft Visual Code by ConrLab.

MS-visual-code-sciter

Microsoft Visual Code, Sciter assistant in actions 

Supports syntax and editing of Sciter HTML and CSS flavours and TIScript.

Code completion in CSS including @mixin/@const constructs and script for this and variables starting from el....

If to update user settings (File->Preferences->User Settings) like this:
code-preferences

then by using Ctrl-K, Ctrl-S sequence you can run it in sciter.exe.

scapp.exe – standalone Sciter executable.

Adding scapp.exe to the SDK.

The ScApp is an executable that contains Sciter engine linked statically – has no external dependencies.

scapp.exe can be started without parameters or with a file name that has either .htm, .tis or .scapp extension:

> scapp.exe

or

> scapp.exe tetris.scapp

If it starts without parameters then it will try to look for either main.htm, main.tis or main.scapp in current folder.

If .htm[l] file is given Sciter window will be created and the document will be loaded to it.

The .scapp file is a zip file containing /main.tis at root. The main.tis is expected to contain code creating windows and calling Sciter.run(); – GUI message pump loop:

  // create first window, it may call Sciter.requestQuit(0) to exit from the loop below
  var window = View.window { ... };
  // run message pump loop of the application
  return Sciter.run(); 

Essentially it will just execute the script in the same way as tiscript.exe does.

At the mean time, event handler assignment…

Sciter supports event handler assignment in jQuery style:

element.on("event", "selector", function(evt) {...});

That looks mostly OK but for some reason I feel it as “aesthetically non pleasant” so thinking about alternatives.

One feasible option/idea may look like this:

// subscribe function for "click" event on element
element << function "click" (evt) {...};

That above is a direct equivalent of

element.on("click", function (evt) {...});

And in full form, with selector

// subscribe function for "click" event on <button id=first> element
self << function ["click","button#first"] (evt) {...};

The main challenge here is to stay in constraints of JS syntax/grammar …

Question about script optimizations in Sciter

Code in question is this:

$(div#sidebarHeader).first.onClick = function()
{
   // Toggle collapse/expand icon
   $(div#sidebarHeader).first.attributes.toggleClass("icon-horizontal-collapse");
   $(div#sidebarHeader).first.attributes.toggleClass("icon-horizontal-expand");
}

Is it optimal? If not then how to make it better?

A bit about script implementation architecture in Sciter

Speed of parsing is as critical in Sciter cases as speed of execution. eval(source) function is a first class citizen as any other function. Sciter’s script implementation uses fast compiler producing bytecodes and VM executing those bytecodes. That’s pretty fast if taken as a whole. But bytecode optimization options are quite limited for the compiler as they take time of script loading.

Thus you should expect script statements to be executed literally.

So these two lines:

$(div#sidebarHeader).first.attributes.toggleClass("icon-horizontal-collapse");
$(div#sidebarHeader).first.attributes.toggleClass("icon-horizontal-expand");

will produce two pretty much identical bytecode sequences that will be executed one by one. Script is quite simple and will be executed fast enough though.

But common engineering sense is required, as usual .

The main problem in code above is not in the script itself but in three identical calls of $ function. Keep in mind that $(selector) execution is in general O(N) complex lookup. The engine may do some optimizations but in general element-by-selector lookup in that complex – to find particular element you may need to scan whole DOM tree to find first satisfying element.

These three calls can simply be replaced by just one:

$(div#sidebarHeader > :first-child ).onClick = function()
{
   // Toggle collapse/expand icon
   this.attributes.toggleClass("icon-horizontal-collapse");
   this.attributes.toggleClass("icon-horizontal-expand");
}

Yet $(div#sidebarHeader > :first-child ).onClick = ... assignment will be executed strictly once – at load time of the document.

And another common sense reasoning about DOM classes in this case…

We don’t need two independent classes here. Single “collapsed” class-flag will work just OK as element can be either expanded or collapsed but not in between of these two states. So our code will look as simple as this:

$(div#sidebarHeader > .icon-horizontal).onClick = function()
{
   this.attributes.toggleClass("collapsed");
}

with the markup:

<div id="sidebarHeader">
  <span class="icon-horizontal">...</span>
  ...
</div>

And styles:

.icon-horizontal {  } /* normal styles */
.icon-horizontal.collapsed {  } /* collapsed styles */

The reasoning above is not just Sciter specific but is also valid for conventional browsers.

Adding inline C functions to Sciter :)

As a response to WebAssembly initiative I am thinking about adding native inline C functions to Sciter.

// that is inline C function declared directly in script:

function getAverageColor( image ) C {
   typedef struct {
     byte r;
     byte g;
     byte b;
     byte a;
   } rgba;

   rgba*    pix   = image_pixels(image);
   unsigned total = image_pixels_count(image);  
   rgba*    pix_end  = pix + total;

   unsigned int r = 0, g = 0, b = 0, a = 0;
   
   for(; pix < pix_end; ++pix )  {     
     r += pix->r;   
     g += pix->g;
     b += pix->b;
     a += pix->a;
   }

   rgba out;
   out.r = r / total;
   out.g = g / total;
   out.b = b / total;
   out.a = a / total;
   return out;   
}

And so we can call that function in script when we will need to get maximum performance:

var img = new Image(w,h,element);
var averageColor = getAverageColor(img);

Such functions will be translated on the fly into native code and so executed as fast as possible.

Huh?

Generators and yield feature in Sciter Script

yield-sign

In Sciter any function that contains yield keyword is treated as a generator function.

Main purpose of the generator is to produce sequence of values – on each generator invocation it returns next value.
Generator returns next value when yield <expression> is executed by the generator.

Consider this generator function:

function  ordinals() {
   yield "first";
   yield "second";
   yield "third";
}

And the code that uses it:

for(var ordinal in ordinals()) 
  stdout.println(ordinal);

Body of the loop will be executed three times as on each generator invocation next yield will emit its value.
And so you will get this output:

> first
> second
> third

The yield (in generators) and await (asynchronous tasks) are internal incarnations of the same mechanism – coroutines.

task/await feature in TIScript

At the moment I am working on await feature in TIScript.

Await is a way to solve callback / promise “hell” in languages like JavaScript and so Sciter Script:

Callback hell

Consider the following code that uses await:

function setupUsersMottoTask(userName)
{
  try {
     var user = await request(#get, "http://example.com/user/" + userName);
     var userMotto = await request(#get, "http://example.com/user/" + user.id + "/avatar");
     self.$(#user > .motto).text = userMotto;
  } catch (e) {
     self.$(#user > .motto).text = "motto unavailable";
  }
}
setupUsersMottoTask("monster"); // runs asynchronously as it is a Task function.

Without await that code above would look like as a ladder of callbacks and error handlers.

Essentially await linearize asynchronous code making it running as normal sequential code.

In Sciter Script any function that uses await inside is automatically declared as asynchronous task function. Invocation of such function starts the task and returns immediately. Such function returns promise and so it’s call can also be used in other awaits.