Traps are functions that can be assigned as listeners when properties on vexiscript objects are accessed.

There are two types of traps:

Traps are assigned using the ++= operator and unassigned using the --= operator.

A trap function can only ever be assigned once to the same property on the same object at any given time. Repeated assignments of the same function to the same property on the same object, without matching unassignments, are ignored. Respectively, repeat unassignments, without matching assignments, are also ignored.

To unassign a trap, you must either use a reference or the callee keyword from within an anonymous trap.

A full list of trap function properties is listed in Special Variables.

Read Traps

A read trap is a function with no arguments. It must contain a return statement. Assigning a read trap without a return statement will produce an exception.

To get the value of the property the trap is placed upon from within a read trap, use the cascade keyword. Note that reading the property directly will re-invoke the read trap.

 var obj = { a:5, b:4 };

 // anonymous read trap
 obj.a ++= function() { var a = cascade; return a*a; };
 obj.a == 25; // true

 // referenced read trap
 var readCubed = function() { var a = cascade; return a*a*a; };
 obj.b ++= readCubed;
 obj.b == 64; // true
 obj.b --= readCubed;
 obj.b == 4; // true

You can not write to the cascade keyword in a read trap.

Write Traps

A write trap is a js function with a single argument, which is the value being assigned to the property. It should contain either a return or put to the cascade keyword and will produce a warning if neither is present.

To put a value to the property at any point in the function, put to the cascade keyword. This may only be done once per execution of a write trap. Note that putting to the property directly will re-invoke the write trap.

To block a put - that is, cause the put to be ignored - simply return.

 <box id="a" enabled="true" focused="false" />
 <box id="b" enabled="false" focused="false" />

 var focusedWrite = function(v) {
     if (trapee.enabled) casade = v;
     else cascade = false;

 $a.focused ++= focusedWrite;
 $b.focused ++= focusedWrite;

 // $a accepts focus because it is enabled
 $a.focused = true;
 $a.focused == true;

 // $b declines focus because it is not enabled
 $b.focused = true;
 $b.focused == false;

You can not read from the cascade keyword in a write trap.

Trap Chains

When assigning multiple read or write traps to the same property on the same object, the traps are stacked in order of assignment to create a trap chain.

There are two paths of execution in a trap chain, known as pre-cascade and post-cascade. When a write or read occurs, the trap at the top of the stack enters its pre-cascade execution. When it cascades - either writing to cascade (write trap) or reading from cascade (read trap) - it passes the execution to the next trap, and so on, until either a trap returns or the put/get reaches the object. Then the execution enters the post-cascade of the next trap up in the stack fro the return point, and when a trap finishes, it passes the execution back up again in the stack.

We refer to this execution path as cascading through the trap chain.


 var obj = { a:true };

 var trap_1 = function(v) {"1: pre-cascade");
     cascade = v;"1: post-cascade");
 var trap_2 = function(v) {"2: pre-cascade");
     if (v==false) return;
     cascade = v;"2: post-cascade");
 var trap_3 = function(v) {"3: pre-cascade");
     cascade = v;"3: post-cascade");

 obj.a ++= trap_1;
 obj.a ++= trap_2;
 obj.a ++= trap_3;

 obj.a = true;
 // outputs:
 // 3: pre-cascade
 // 2: pre-cascade
 // 1: pre-cascade
 // 1: post-cascade
 // 2: post-cascade
 // 3: post-cascade

 obj.a = false;
 // outputs:
 // 3: pre-cascade
 // 2: pre-cascade
 // 3: post-cascade

For encapsulation reasons, traps are always stacked in order of assignment, and this order can not be altered except by removing, by reference, any traps in the chain.


Copyright © 2011 The Vexi Project (