-2

Here are two rulesets that illustrate a totally unexpected behavior. Is this a bug?

Functions get executed even though they are not called anywhere or script breaks with a javascript error. The solution is to always end a declaration with a semicolon like this:

test1 = function(){console.log("test1");}  ;// <==

but this is dangerous I think because this is not mandatory in javascript.

Example 1 bookmarklet:

javascript:(function(){
  var d=document;var s=d.createElement('script');s.text=&quot;
  KOBJ_config={'rids':['a1135x27']};&quot;;d.body.appendChild(s);
  var l=d.createElement('script');l.src='http://init.kobj.net/js/shared/kobj-static.js';
  d.body.appendChild(l);})()

Example 2 bookmarklet :

javascript:(function(){
  var d=document;var s=d.createElement('script');s.text=&quot;
  KOBJ_config={'rids':['a1135x27']};&quot;;d.body.appendChild(s);
  var l=d.createElement('script');l.src='http://init.kobj.net/js/shared/kobj-static.js';
  d.body.appendChild(l);})()

Rulesets:

ruleset a1135x27 {
  meta {
    name "odd1"
    description <<
        demonstrate oddity 1
    >>
    author "Loïc Devaux"
    logging on
  }

  dispatch {
    // Some example dispatch domains
    // domain "example.com"
    // domain "other.example.com"
  }

  global {

    emit  <|



       /* this breaks javascript code*/
       // => 16:27:58 ERROR general Closure Executed with error a1135x27 - 13025536774875610960847698152Exception: test1 is not defined
       test1 = function(){console.log("test1")}

        /* this won't break */
        //test1 = function(){console.log("test1")};
        /* */

       /* this won't break */
       //test1 = function(){console.log("test1")}
       //test2 = function(){console.log("test2")};
       /* */

    |>;
  }

  rule first_rule {
    select when pageview ".*" setting ()
    pre { 

        }
    {
      emit <|

           test1();


          |>;  
    }

  }




}



ruleset a1135x28 {
  meta {
    name "odd2"
    description <<
        demonstrate oddity 2
    >>
    author "Loic Devaux"
    logging on
  }

 dispatch {
    // Some example dispatch domains
    // domain "example.com"
    // domain "other.example.com"
  }

  global {

    emit  <|

       /*  test1 will be executed even though it hasn't been called anywhere */
       //test1 = function(){console.log("test1");}
        /* */

        /* test1 won't get executed */
        /* 
            test1 = function(){console.log("test1");};
        */
        /* */


        /* this won't break and test2 will be executed although it hasn't been called anywhere */

            test1 = function(){console.log("test1");}
            test2 = function(){console.log("test2");}

        /* */


    |>;
  }

  rule first_rule {
    select when pageview ".*" setting ()
    pre { 

        }
    {
      emit <|

          console.log('running first_rule');

          |>;  
    }

  }




}
Jacob
  • 77,566
  • 24
  • 149
  • 228
Loic Devaux
  • 316
  • 2
  • 9
  • Look at the generated javascript http://ktest.heroku.com/a1135x28 - There is something amiss when your only action is an emit block. – Randall Bohn Apr 14 '11 at 22:42
  • Here is the code I get: `KOBJ.registerClosure('a1135x28', function($K) { (function(){ test1 = function(){console.log("test1");} test2 = function(){console.log("test2");} (function(){function callBacks () { }; console.log('running first_rule'); ; callBacks(); }()); }()); }, '13028242450729780623313977184');` Where did you detect the problem at that level? – Loic Devaux Apr 14 '11 at 23:41
  • 1
    There should be a line with 'rule_name' :'first_rule','rid' :'a421x52' in it. Also, after the lines emitted from the global block there is an anonymous function. This becomes the parameter of the test2 function, so it is in fact called. Putting a ';' on the final line of your emit block will prevent this. – Randall Bohn Apr 15 '11 at 03:06
  • So would you consider this as a bug? I am mentionning this because from time to time I just paste a function in the global section without thinking and without the semicolon and then those strange things happen. It can be misleading for beginners like me. – Loic Devaux Apr 15 '11 at 15:40

1 Answers1

2

The right thing to do here is write valid javascript. In your code example, you regularly leave off important semicolons. Remember that while javascript is fairly tolerant of syntactic problems, they can get you into trouble in unexpected ways.

test2 = function(){console.log("test2")};

should be

test2 = function(){console.log("test2");};

because both the assignment is a statement, is is the console.log() method call.

When you emit invalid javascript, all sorts of odd stuff is likely to occur. While most result in a javascript syntax error, the closures that KNS uses to wrap your code (and prevent unintended variable leakage) can have the side effects you observe.

In short: If there is a bug here, it's the javascript parser's flexibility in letting you omit important semicolons. This is not considered a KRL bug.

TelegramSam
  • 2,770
  • 1
  • 17
  • 22
  • 1
    Ok good. May I suggest some "-wall" or "-pedantic" key in the meta section that would check the code with [JSlint](https://github.com/douglascrockford/JSLint) and put some more warnings in the log when enabled? There is a [discussion](http://stackoverflow.com/questions/444080/do-you-recommend-using-semicolons-after-every-statement-in-javascript) about putting semicolons in javascript and it mentions this problem which is linked to code with missing semicolons executed inside a closure I guess. – Loic Devaux Apr 16 '11 at 13:58
  • 1
    We have discussed linting code in clownhats (<| |>). I like the meta option as well. – TelegramSam Apr 18 '11 at 23:42
  • [javascript-linting-for-emit-blocks](http://devex.kynetx.com/questions/215/javascript-linting-for-emit-blocks) – Loic Devaux Apr 19 '11 at 02:31