HISE Logo Forum
    • Categories
    • Register
    • Login

    Namespaces in Javascript

    Scheduled Pinned Locked Moved Blog Entries
    13 Posts 2 Posters 3.2k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Christoph HartC
      Christoph Hart
      last edited by Christoph Hart

      In a ideal world, scripts are little code snippets that fulfill one purpose (and the design of HISE tries to enforce this paradigm as much as possible). However this isn't always the case, especially interface scripts tend to grow pretty quickly and reach a size where you have to think about organizing the structure of your code. A common solution for this task in other languages are namespaces which can be used to avoid naming conflicts and to group things that belong together.

      But in Javascript there is nothing like a namespace concept. Instead you need to create a Object and fill its properties:

      var MyStuff = {};
      
      MyStuff.property1 =  2;
      MyStuff.function1 = function(){ return 2;};
      
      Console.print(MyStuff.property1); // 2
      Console.print(MyStuff.function1()); // 2
      

      However this has some performance implications (every access needs to resolve the Object name first) as well as some limitations: almost every custom enhancement I added to the scripting engine of HISE like inline functions or const variables can't be members of objects and must be cranked into the global namespace.

      In my spirit of taking things from C++ that I like and port it to Javascript, I decided to add the namespace concept to the scripting engine. Huge parts of the parser needed to be rewritten so it's a bit experimental (there are a lot of edge case scenarios which had to be considered). But I think it's a valuable addition because you get a way of grouping functions and variables without any performance penalty like you do when using objects for it (the parser resolves the namespaces at compile time):

      const var property1 = 5;
      
      namespace MyStuff
      {
          const var property1 = 2;
          inline function function1()
          {
              return property1;
              // return MyStuff.property1; (within namespaces you can either use the prefix or not)
          };
      }
      
      namespace Other
      {
      	const var property1 = Mystuff.function1(); // works between namespaces
      }
      
      MyFunctions.doSomething(); // 2
      

      So far so good. However I tried to make the parser changes as uninvasive as possible and tried to avoid complicating the code, so there are some limitations of the namespace concept (compared to the C++ namespacing).
      However they should not affect the behaviour when using namespaces as intended (they are just adding some weirdness when you go off road).

      Caveats

      Leaking of global namespace

      Every namespace is a superset of the global namespace. That means that you can access global variables through the namespace prefix even if it is not defined within the global namespace:

      reg property1 = 5;
      
      namespace Empty
      {
      
      }
      
      Console.print(Empty.property1); // 5
      

      This is a side effect of allowing the access to the variable within its namespace with the namespace prefix as well as without (the autocomplete will always spit out the full namespace so it would be pretty stupid to autocomplete faulty stuff).

      No nesting of namespaces

      You can't nest namespaces (define namespaces within other namespaces). One level of grouping should be enough even for complex scripts.

      No standard var definitions within namespace

      Namespaces currently work only for const var and reg variables (you'll get another 32 reg slots with every namespace) as well as inline functions. I didn't want to change the standard Javascript var type because I can't forsee the side effects of this for the weirder use cases of Javascript. Like with every customization I add I try to stay compatible to the standard implementation, but to be honest with these two types you have pretty much any use case covered anyway - I actually never use the standard var type anymore.

      namespace Problem
      {
          var property1 = 5;
      }
      
      Console.print(Problem.property1); // 5 (is actual a side effect of the leaking described above)
      Console.print(property1); // 5 (should be undefined)
      

      No namespace wrapping of include()

      A common practice in C++ is to wrap #include statements into a namespace definition (this way you don't need to define the namespace in every header file). However this isn't supported in HISE so this won't work:

      // External File (externalFile.js)
      const var property1 = 2;
      
      // Script
      namespace External
      {
          include("externalFile.js");
      }
      
      Console.print(External.property1); // undefined
      

      Of course you can use namespaces in external files (it would pretty much defeat the purpose of the whole thing if this wasn't possible).

      No duplicated namespace usage

      Every namespace must be defined once. In C++ you can take up existing namespaces and add your variables to it, but this isn't supported in HISE.

      That's it. Feel free to play around with it (it will be included in Build 646) and write a comment if you find a bug or unexpected behaviour. If you really need to have one of the mentioned problems resolved, I could try to improve the parser to support it.

      1 Reply Last reply Reply Quote 1
      • d.healeyD
        d.healey
        last edited by

        Has build 645 been updated with this feature?

        Libre Wave - Freedom respecting instruments and effects
        My Patreon - HISE tutorials
        YouTube Channel - Public HISE tutorials

        1 Reply Last reply Reply Quote 0
        • Christoph HartC
          Christoph Hart
          last edited by

          Oops, my bad, I am talking about the upcoming 646 (I'll upload it in the next days)

          1 Reply Last reply Reply Quote 0
          • d.healeyD
            d.healey
            last edited by

            I thought so but wanted to check before I re-downloaded the current build

            Libre Wave - Freedom respecting instruments and effects
            My Patreon - HISE tutorials
            YouTube Channel - Public HISE tutorials

            1 Reply Last reply Reply Quote 0
            • Christoph HartC
              Christoph Hart
              last edited by

              Alright, Build 646 is online.

              1 Reply Last reply Reply Quote 0
              • d.healeyD
                d.healey
                last edited by

                That was quick :D

                Libre Wave - Freedom respecting instruments and effects
                My Patreon - HISE tutorials
                YouTube Channel - Public HISE tutorials

                1 Reply Last reply Reply Quote 0
                • d.healeyD
                  d.healey
                  last edited by

                  Can this be used within a namespace to refer to its own functions?

                  Libre Wave - Freedom respecting instruments and effects
                  My Patreon - HISE tutorials
                  YouTube Channel - Public HISE tutorials

                  1 Reply Last reply Reply Quote 0
                  • Christoph HartC
                    Christoph Hart
                    last edited by

                    Nope, this is reserved for object properties.

                    1 Reply Last reply Reply Quote 0
                    • d.healeyD
                      d.healey
                      last edited by

                      What about creating another keyword like self?

                      Libre Wave - Freedom respecting instruments and effects
                      My Patreon - HISE tutorials
                      YouTube Channel - Public HISE tutorials

                      1 Reply Last reply Reply Quote 0
                      • Christoph HartC
                        Christoph Hart
                        last edited by

                        Adding Python to the melting pot, I like it :)

                        Why do you need this? I would indeed prefer adding a new keyword like self, but I can't see any advantage yet.

                        1 Reply Last reply Reply Quote 0
                        • Christoph HartC
                          Christoph Hart
                          last edited by

                          If we're at it, what do you think about a private keyword?

                          namespace MyEncapsulatedStuff
                          {
                              private var internals = "Hidden";
                          
                              inline function getHiddenProperty()
                              {
                                  return self.internals; // :)
                              };
                          };
                          
                          Console.print(MyEncapsulatedStuff.internals); // undefined
                          Console.print(MyEncapsulatedStuff.getHiddenProperty()); // "Hidden"
                          

                          It would solve the problem of the weird Javascript encapsulation tactics.

                          1 Reply Last reply Reply Quote 0
                          • d.healeyD
                            d.healey
                            last edited by

                            A self keyword will be helpful for example when I have functions within a namespace that refer to each other and to private namespaced variables. Rather than writing out the namespace's name I could just put self and if I decide to change the namespace name I won't need to adjust the function and variable references within the namespace. The private keyword is a good idea :)

                            Libre Wave - Freedom respecting instruments and effects
                            My Patreon - HISE tutorials
                            YouTube Channel - Public HISE tutorials

                            1 Reply Last reply Reply Quote 0
                            • Christoph HartC
                              Christoph Hart
                              last edited by

                              You could also skip the namespace. and write the variable name without prefix. This will work even if there are global variables with the same name.

                              1 Reply Last reply Reply Quote 0
                              • First post
                                Last post

                              49

                              Online

                              1.7k

                              Users

                              11.7k

                              Topics

                              101.8k

                              Posts