<commit_before>var testFile = require("sdk/self").data.load("doctests.js")

eval(testFile);

exports["test doc regexp oldURLs"] = function(assert) {
  var str = 'WebMozilla';
  var test = str.match(docTests["oldURLs"].regex);
  assert.ok(2 == test.length , "test that 'en/' links are matched");
};

exports["test doc regexp emptyElem"] = function(assert) {
  var str = '

' +
            '
 \n\r
' +
            '

' +
            '

' +
            '' +
            '<input value="test"/>' +
            '
some text
' +
            '
some text
';
  var test = docTests["emptyElem"].check(str);
  assert.ok(test.length === 4, "test that empty elements are matched");
};

exports["test doc regexp languagesMacro"] = function(assert) {
  var str = '{{ languages( { "ja": "Ja/Browser_chrome_tests" } ) }}';
  var test = str.match(docTests["languagesMacro"].regex);
  assert.ok(1 == test.length , "test that the {{languages}} macro is matched");
};

exports["test doc regexp emptyBrackets"] = function(assert) {
  var str = '{{ foo() }} {{bar()}} {{foobar("abc")}} {{baz}}';
  var test = str.match(docTests["emptyBrackets"].regex);
  assert.ok(2 == test.length , "test that {{foo()}} macros are matched");
};

exports["test doc regexp styleAttribute"] = function(assert) {
  var str = '' +
            '

' +
            '

' +
            'test' +
            '';
  var test = str.match(docTests["styleAttribute"].regex);
  assert.ok(5 == test.length , "test that style= attributes are matched");
};

exports["test doc regexp nameAttribute"] = function(assert) {
  var str = '' +
            '

' +
            '
foo
' +
            '
foo bar
' +
            '
baz
';
  var test = str.match(docTests["nameAttribute"].regex);
  assert.ok(5 == test.length , "test that name= attributes are matched");
};

exports["test doc regexp spanCount"] = function(assert) {
  var str = 'what?' +
            '
nope
' +
            'bar' +
            '
foobar
' +
            'seoseoseo';
  var test = docTests["spanCount"].check(str);
  assert.ok(3 == test.length , "test that  elements are found");
};

exports["test doc regexp preWithoutClass"] = function(assert) {
  var str = '

' +
            '
foobar;
' +
            '

' +
            '

' +
            "
 \n\r foo
";
  var test = str.match(docTests["preWithoutClass"].regex);
  assert.ok(3 == test.length , "test that
 elements w/o syntax highlighter are found");
};

exports["test doc regexp summaryHeading"] = function(assert) {
  var str = '
Summary
' +
            '
Summary
' +
            '
Summary
' +
            '
Summary
';
  var test = str.match(docTests["summaryHeading"].regex);
  assert.ok(4 == test.length , "test that Summary headings are matched");
};

exports["test doc regexp jsRefWithParams"] = function(assert) {
  var str = '{{JSRef()}}' +
            '{{JSRef("Global_Objects")}}' +
            '{{JSRef("Global_Objects", "Math")}}' +
            '{{JSRef}}';
  var test = str.match(docTests["jsRefWithParams"].regex);
  assert.ok(3 == test.length , "test that JSRef macros with parameters are matched");
};

exports["test doc regexp exampleColonHeading"] = function(assert) {
  var str = '
Example
' +
            '
Example
' +
            '
Example: Foo
' +
            '
Example: Using Math.sin
' +
            '
Example: Foo
';
  var test = str.match(docTests["exampleColonHeading"].regex);
  assert.ok(3 == test.length , "test that headings with _Example:_ are matched");
};

exports["test doc regexp alertPrintInCode"] = function(assert) {
  var str = '
alert("foo")
' +
            '
print("bar")
' +
            '
var someOthercode = baz; ' +
            'alert("hello world"); \n var moreCode;
' +
            '
document.write("foobar");
';
  var test = docTests["alertPrintInCode"].check(str);
  assert.ok(4 == test.length , "test that alert, print, eval and d.write statements are matched");
};

exports["test doc regexp htmlComments"] = function(assert) {
  var str = '' +
            '' +
            '';
  var test = str.match(docTests["htmlComments"].regex);
  assert.ok(3 == test.length , "test that html comments are matched");
};

exports["test doc regexp fontElement"] = function(assert) {
  var str = '' +
            '';
  var test = str.match(docTests["fontElement"].regex);
  assert.ok(2 === test.length, "test that  tags are matched");
};

exports["test doc httpLinks"] = function(assert) {
  var str = 'some page' +
            'some page' +
            'some page' +
            'some page';
  var test = str.match(docTests["httpLinks"].regex);
  assert.ok(test.length === 1, "test that HTTP links are matched");
};

exports["test doc macroSyntaxError"] = function(assert) {
  var str = '{{macro}}' +
            '{{macro("param")}}' +
            '{{macro(123)}}' +
            '{{macro(123, "param")}}' +
            '{{macro(\'param\', 123, "param")}}' +
            '{{macro("param)}}' + // Missing closing double quote
            '{{macro(\'param)}}' + // Missing closing single quote
            '{{macro(param)}}' + // Missing quotes
            '{{macro(param")}}' + // Missing opening double quote
            '{{macro(param\')}}' + // Missing opening single quote
            '{{macro(\'param\', 123, "param)}}' + // Missing closing double quote, multiple parameters
            '{{macro("param"))}}' + // Double closing parameter list bracket
            '{{macro("param")}' + // Missing closing macro curly brace after double quoted parameter
            '{{macro(\'param\')}' + // Missing closing macro curly brace after single quoted parameter
            '{{macro("param"}}' + // Missing closing parameter list bracket after double quoted parameter
            '{{macro(\'param\'}}' + // Missing closing parameter list bracket after single quoted parameter
            '{{macro(param"}}' + // Missing opening double quote and missing closing parameter list bracket
            '{{macro(param"))}}'; // Missing opening double quote and double closing parameter list bracket
  var test = docTests["macroSyntaxError"].check(str);
  assert.ok(test.length === 15, "test that macro syntax errors are recognized " + test.length);
};

exports["test doc wrongHighlightedLine"] = function(assert) {
  var str = '
bla\nblubb
' +
            '
bla\nblubb
' +
            '
bla\nblubb
' +
            '
bla\nblubb
' +
            '
bla\nblubb
' +
            '
bla\nblubb
' +
            '
bla
blubb
' +
            '
bla
blubb
';
  var test = docTests["wrongHighlightedLine"].check(str);
  assert.ok(test.length === 5, "test that highlighted code line number is valid " + test.length);
};

exports["test doc headlinesWording"] = function(assert) {
  var str = '
Syntax
' +
            '
Errors
' +
            '
Returns
' +
            '
Parameters
';
  var test = docTests["headlinesWording"].check(str);
  assert.ok(test.length === 4, "test that wrong Syntax sub-headings and a order of them is recognized");
};

require("sdk/test").run(exports);<commit_msg>Added unit test for  in
 test (issue #42)<commit_after>var testFile = require("sdk/self").data.load("doctests.js")

eval(testFile);

exports["test doc regexp oldURLs"] = function(assert) {
  var str = 'WebMozilla';
  var test = str.match(docTests["oldURLs"].regex);
  assert.ok(2 == test.length , "test that 'en/' links are matched");
};

exports["test doc regexp emptyElem"] = function(assert) {
  var str = '

' +
            '
 \n\r
' +
            '

' +
            '

' +
            '' +
            '<input value="test"/>' +
            '
some text
' +
            '
some text
';
  var test = docTests["emptyElem"].check(str);
  assert.ok(test.length === 4, "test that empty elements are matched");
};

exports["test doc regexp languagesMacro"] = function(assert) {
  var str = '{{ languages( { "ja": "Ja/Browser_chrome_tests" } ) }}';
  var test = str.match(docTests["languagesMacro"].regex);
  assert.ok(1 == test.length , "test that the {{languages}} macro is matched");
};

exports["test doc regexp emptyBrackets"] = function(assert) {
  var str = '{{ foo() }} {{bar()}} {{foobar("abc")}} {{baz}}';
  var test = str.match(docTests["emptyBrackets"].regex);
  assert.ok(2 == test.length , "test that {{foo()}} macros are matched");
};

exports["test doc regexp styleAttribute"] = function(assert) {
  var str = '' +
            '

' +
            '

' +
            'test' +
            '';
  var test = str.match(docTests["styleAttribute"].regex);
  assert.ok(5 == test.length , "test that style= attributes are matched");
};

exports["test doc regexp nameAttribute"] = function(assert) {
  var str = '' +
            '

' +
            '
foo
' +
            '
foo bar
' +
            '
baz
';
  var test = str.match(docTests["nameAttribute"].regex);
  assert.ok(5 == test.length , "test that name= attributes are matched");
};

exports["test doc regexp spanCount"] = function(assert) {
  var str = 'what?' +
            '
nope
' +
            'bar' +
            '
foobar
' +
            'seoseoseo';
  var test = docTests["spanCount"].check(str);
  assert.ok(3 == test.length , "test that  elements are found");
};

exports["test doc regexp preWithoutClass"] = function(assert) {
  var str = '

' +
            '
foobar;
' +
            '

' +
            '

' +
            "
 \n\r foo
";
  var test = str.match(docTests["preWithoutClass"].regex);
  assert.ok(3 == test.length , "test that
 elements w/o syntax highlighter are found");
};

exports["test doc regexp summaryHeading"] = function(assert) {
  var str = '
Summary
' +
            '
Summary
' +
            '
Summary
' +
            '
Summary
';
  var test = str.match(docTests["summaryHeading"].regex);
  assert.ok(4 == test.length , "test that Summary headings are matched");
};

exports["test doc regexp jsRefWithParams"] = function(assert) {
  var str = '{{JSRef()}}' +
            '{{JSRef("Global_Objects")}}' +
            '{{JSRef("Global_Objects", "Math")}}' +
            '{{JSRef}}';
  var test = str.match(docTests["jsRefWithParams"].regex);
  assert.ok(3 == test.length , "test that JSRef macros with parameters are matched");
};

exports["test doc regexp exampleColonHeading"] = function(assert) {
  var str = '
Example
' +
            '
Example
' +
            '
Example: Foo
' +
            '
Example: Using Math.sin
' +
            '
Example: Foo
';
  var test = str.match(docTests["exampleColonHeading"].regex);
  assert.ok(3 == test.length , "test that headings with _Example:_ are matched");
};

exports["test doc regexp alertPrintInCode"] = function(assert) {
  var str = '
alert("foo")
' +
            '
print("bar")
' +
            '
var someOthercode = baz; ' +
            'alert("hello world"); \n var moreCode;
' +
            '
document.write("foobar");
';
  var test = docTests["alertPrintInCode"].check(str);
  assert.ok(4 == test.length , "test that alert, print, eval and d.write statements are matched");
};

exports["test doc regexp htmlComments"] = function(assert) {
  var str = '' +
            '' +
            '';
  var test = str.match(docTests["htmlComments"].regex);
  assert.ok(3 == test.length , "test that html comments are matched");
};

exports["test doc regexp fontElement"] = function(assert) {
  var str = '' +
            '';
  var test = str.match(docTests["fontElement"].regex);
  assert.ok(2 === test.length, "test that  tags are matched");
};

exports["test doc httpLinks"] = function(assert) {
  var str = 'some page' +
            'some page' +
            'some page' +
            'some page';
  var test = str.match(docTests["httpLinks"].regex);
  assert.ok(test.length === 1, "test that HTTP links are matched");
};

exports["test doc macroSyntaxError"] = function(assert) {
  var str = '{{macro}}' +
            '{{macro("param")}}' +
            '{{macro(123)}}' +
            '{{macro(123, "param")}}' +
            '{{macro(\'param\', 123, "param")}}' +
            '{{macro("param)}}' + // Missing closing double quote
            '{{macro(\'param)}}' + // Missing closing single quote
            '{{macro(param)}}' + // Missing quotes
            '{{macro(param")}}' + // Missing opening double quote
            '{{macro(param\')}}' + // Missing opening single quote
            '{{macro(\'param\', 123, "param)}}' + // Missing closing double quote, multiple parameters
            '{{macro("param"))}}' + // Double closing parameter list bracket
            '{{macro("param")}' + // Missing closing macro curly brace after double quoted parameter
            '{{macro(\'param\')}' + // Missing closing macro curly brace after single quoted parameter
            '{{macro("param"}}' + // Missing closing parameter list bracket after double quoted parameter
            '{{macro(\'param\'}}' + // Missing closing parameter list bracket after single quoted parameter
            '{{macro(param"}}' + // Missing opening double quote and missing closing parameter list bracket
            '{{macro(param"))}}'; // Missing opening double quote and double closing parameter list bracket
  var test = docTests["macroSyntaxError"].check(str);
  assert.ok(test.length === 15, "test that macro syntax errors are recognized " + test.length);
};

exports["test doc wrongHighlightedLine"] = function(assert) {
  var str = '
bla\nblubb
' +
            '
bla\nblubb
' +
            '
bla\nblubb
' +
            '
bla\nblubb
' +
            '
bla\nblubb
' +
            '
bla\nblubb
' +
            '
bla
blubb
' +
            '
bla
blubb
';
  var test = docTests["wrongHighlightedLine"].check(str);
  assert.ok(test.length === 5, "test that highlighted code line number is valid " + test.length);
};

exports["test doc headlinesWording"] = function(assert) {
  var str = '
Syntax
' +
            '
Errors
' +
            '
Returns
' +
            '
Parameters
';
  var test = docTests["headlinesWording"].check(str);
  assert.ok(test.length === 4, "test that wrong Syntax sub-headings and a order of them is recognized");
};

exports["test doc codeInPre"] = function(assert) {
  var str = '
no code
' +
            '
no code
' +
            '
some code
' +
            '
some codesome more inline code
' +
            '
foo\nsome code\nbar
\nsome code with\nline break\nbaz
';
  var test = docTests["codeInPre"].check(str);
  assert.ok(test.length === 5, "test that  elements within
 blocks are matched");
};

require("sdk/test").run(exports);<|endoftext|>


<commit_before>
class Observable {
  constructor() {
    this.observers = []
    this.errorObservers = []
    this.disposed = false
  }

  fireObserver(observer, signal, ...args) {
    if(typeof observer == 'function') return observer(signal, ...args)
    if(observer.notify) {
      return observer.notify(signal, ...args)
    }
    if(observer[signal]) {
      observer[signal](...args)
      return true
    }
    return false
  }

  fireObservers(signal, ...args) {
    if(this.disposed) return
    let handled = false
    for(var observer of this.observers) handled = this.fireObserver(observer, signal, ...args) || handled
    if(signal == 'error') {
      let error = args[0]
      handled = this.handleError(signal, error) || handled
      if(!handled) console.error("Unhandled observable error: "+ (error.message || error))
    }
  }

  handleError(error) {
    let handled = false
    for (var observer of this.errorObservers) {
      handled = true
      observer(error)
    }
    return handled
  }

  error(error) {
    this.fireObservers("error", error)
  }

  catch(errorObserver) {
    this.errorObservers.push(errorObserver)
  }

  observe(observer) {
    if(this.isDisposed()) this.respawn()
    this.observers.push(observer)
  }
  unobserve(observer) {
    let id = this.observers.indexOf(observer)
    if(id == -1) throw new Error("observer not found")
    this.observers.splice(id, 1)
    if(this.isUseless()) this.dispose()
  }

  isUseless() {
    return this.observers.length == 0
  }

  isDisposed() {
    return this.disposed
  }

  dispose() {
    this.disposed = true
  }

  respawn() {
    this.disposed = false
  }
}

module.exports = Observable
<commit_msg>error handling fix<commit_after>
class Observable {
  constructor() {
    this.observers = []
    this.errorObservers = []
    this.disposed = false
  }

  fireObserver(observer, signal, ...args) {
    if(typeof observer == 'function') return observer(signal, ...args)
    if(observer.notify) {
      return observer.notify(signal, ...args)
    }
    if(observer[signal]) {
      observer[signal](...args)
      return true
    }
    return false
  }

  fireObservers(signal, ...args) {
    if(this.disposed) return
    let handled = false
    for(var observer of this.observers) handled = this.fireObserver(observer, signal, ...args) || handled
    if(signal == 'error') {
      let error = args[0]
      handled = this.handleError(error) || handled
      if(!handled) console.error("Unhandled observable error: "+ (error.message || error))
    }
  }

  handleError(error) {
    let handled = false
    for (var observer of this.errorObservers) {
      handled = true
      observer(error)
    }
    return handled
  }

  error(error) {
    this.fireObservers("error", error)
  }

  catch(errorObserver) {
    this.errorObservers.push(errorObserver)
  }

  observe(observer) {
    if(this.isDisposed()) this.respawn()
    this.observers.push(observer)
  }
  unobserve(observer) {
    let id = this.observers.indexOf(observer)
    if(id == -1) throw new Error("observer not found")
    this.observers.splice(id, 1)
    if(this.isUseless()) this.dispose()
  }

  isUseless() {
    return this.observers.length == 0
  }

  isDisposed() {
    return this.disposed
  }

  dispose() {
    this.disposed = true
  }

  respawn() {
    this.disposed = false
  }
}

module.exports = Observable
<|endoftext|>


<commit_before>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

'use strict'

var fs = require('fs')
var path = require('path')
var _ = require('lodash')
var EOL = require('os').EOL

module.exports = function () {

  function loadEnvFile (root, envFile) {
    var ef
    var env = {}
    var lines
    var expr

    var p = path.resolve(path.join(root, envFile))
    if (fs.existsSync(p)) {
      ef = fs.readFileSync(p, 'utf8')

      lines = ef.split(EOL)
      _.each(lines, function (line) {
        if (!/^#.*/g.test(line)) {
          if ((expr = /(^[A-Za-z0-9_]+)=(.+$)/g.exec(line)) !== null) {
            env[expr[1]] = expr[2]
          }
        }
      })
    }
    return env
  }

  function loadEnvFiles (yamlPath, obj) {
    var env = {}
    var block

    if (typeof obj === 'object' && obj !== null) {
      console.warn('\n objjj=... '+ Object.entries(obj))
    } else {
      console.warn('\n obj=... '+ obj)
    }

    if (obj.env_file) {
      if (_.isArray(obj.env_file)) {
        _.each(obj.env_file, function (envFile) {
          if (obj.path) {
            block = loadEnvFile(obj.path, envFile)
          } else {
            block = loadEnvFile(path.dirname(yamlPath), envFile)
          }
          env = _.merge(env, block)
        })
      } else {
        if (obj.path) {
          block = loadEnvFile(obj.path, obj.env_file)
        } else {
          block = loadEnvFile(path.dirname(yamlPath), obj.env_file)
        }
        env = _.merge(env, block)
      }
    }
    return env
  }

  function buildEnvironmentBlock (envIn) {
    var env = {}

    if (_.isArray(envIn)) {
      if (envIn.length > 0) {
        _.each(envIn, function (ev) {
          var k = ev.substring(0, ev.indexOf('='))
          var v = ev.substring(ev.indexOf('=') + 1)
          env[k] = v
        })
      }
    } else if (_.isObject(envIn)) {
      env = envIn
    }

    return env
  }

  function findEnvVar (system, varName) {
    var result = null

    _.each(_.keys(system.topology.containers), function (key) {
      if (system.topology.containers[key].environment[varName]) {
        result = system.topology.containers[key].environment[varName]
      }
    })

    if (!result) {
      if (process.env[varName]) {
        result = process.env[varName]
      }
    }

    return result
  }

  function interpolate (system) {
    if (system.topology.containers && _.keys(system.topology.containers).length > 0) {
      _.each(_.keys(system.topology.containers), function (key) {
        var container = system.topology.containers[key]
        var cstr = JSON.stringify(container, null, 2)
        var envVar
        var value

        if (/\$\{([a-zA-Z0-9-_]+)\}/g.test(cstr)) {
          while ((envVar = /\$\{([a-zA-Z0-9-_]+)\}/g.exec(cstr)) !== null) {
            if (container.environment[envVar[1]]) {
              if (/\$\{([a-zA-Z0-9-_]+)\}/g.test(container.environment[envVar[1]])) {
                value = ''
              } else {
                value = container.environment[envVar[1]]
              }
              cstr = cstr.replace(new RegExp('\\$\\{' + envVar[1] + '\\}', 'g'), value)
            } else {
              if ((value = findEnvVar(system, envVar[1])) !== null) {
                if (/\$\{([a-zA-Z0-9-_]+)\}/g.test(value)) {
                  value = ''
                }
                cstr = cstr.replace(new RegExp('\\$\\{' + envVar[1] + '\\}', 'g'), value)
              } else {
                cstr = cstr.replace(new RegExp('\\$\\{' + envVar[1] + '\\}', 'g'), '')
              }
            }
          }
          system.topology.containers[key] = JSON.parse(cstr)
        }
      })
    }
  }

  return {
    loadEnvFile,
    loadEnvFiles,
    buildEnvironmentBlock,
    interpolate
  }
}

<commit_msg>merging back to master<commit_after>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

'use strict'

var fs = require('fs')
var path = require('path')
var _ = require('lodash')
var EOL = require('os').EOL

module.exports = function () {

  function loadEnvFile (root, envFile) {
    var ef
    var env = {}
    var lines
    var expr

    var p = path.resolve(path.join(root, envFile))
    if (fs.existsSync(p)) {
      ef = fs.readFileSync(p, 'utf8')

      lines = ef.split(EOL)
      _.each(lines, function (line) {
        if (!/^#.*/g.test(line)) {
          if ((expr = /(^[A-Za-z0-9_]+)=(.+$)/g.exec(line)) !== null) {
            env[expr[1]] = expr[2]
          }
        }
      })
    }
    return env
  }

  function loadEnvFiles (yamlPath, obj) {
    var env = {}
    var block

    if (typeof obj === 'object' && obj !== null) {
      console.warn('\n objjj=... ' + Object.entries(obj))
    } else {
      console.warn('\n obj=... ' + obj)
    }

    if (obj.env_file) {
      if (_.isArray(obj.env_file)) {
        _.each(obj.env_file, function (envFile) {
          if (obj.path) {
            block = loadEnvFile(obj.path, envFile)
          } else {
            block = loadEnvFile(path.dirname(yamlPath), envFile)
          }
          env = _.merge(env, block)
        })
      } else {
        if (obj.path) {
          block = loadEnvFile(obj.path, obj.env_file)
        } else {
          block = loadEnvFile(path.dirname(yamlPath), obj.env_file)
        }
        env = _.merge(env, block)
      }
    }
    return env
  }

  function buildEnvironmentBlock (envIn) {
    var env = {}

    if (_.isArray(envIn)) {
      if (envIn.length > 0) {
        _.each(envIn, function (ev) {
          var k = ev.substring(0, ev.indexOf('='))
          var v = ev.substring(ev.indexOf('=') + 1)
          env[k] = v
        })
      }
    } else if (_.isObject(envIn)) {
      env = envIn
    }

    return env
  }

  function findEnvVar (system, varName) {
    var result = null

    _.each(_.keys(system.topology.containers), function (key) {
      if (system.topology.containers[key].environment[varName]) {
        result = system.topology.containers[key].environment[varName]
      }
    })

    if (!result) {
      if (process.env[varName]) {
        result = process.env[varName]
      }
    }

    return result
  }

  function interpolate (system) {
    if (system.topology.containers && _.keys(system.topology.containers).length > 0) {
      _.each(_.keys(system.topology.containers), function (key) {
        var container = system.topology.containers[key]
        var cstr = JSON.stringify(container, null, 2)
        var envVar
        var value

        if (/\$\{([a-zA-Z0-9-_]+)\}/g.test(cstr)) {
          while ((envVar = /\$\{([a-zA-Z0-9-_]+)\}/g.exec(cstr)) !== null) {
            if (container.environment[envVar[1]]) {
              if (/\$\{([a-zA-Z0-9-_]+)\}/g.test(container.environment[envVar[1]])) {
                value = ''
              } else {
                value = container.environment[envVar[1]]
              }
              cstr = cstr.replace(new RegExp('\\$\\{' + envVar[1] + '\\}', 'g'), value)
            } else {
              if ((value = findEnvVar(system, envVar[1])) !== null) {
                if (/\$\{([a-zA-Z0-9-_]+)\}/g.test(value)) {
                  value = ''
                }
                cstr = cstr.replace(new RegExp('\\$\\{' + envVar[1] + '\\}', 'g'), value)
              } else {
                cstr = cstr.replace(new RegExp('\\$\\{' + envVar[1] + '\\}', 'g'), '')
              }
            }
          }
          system.topology.containers[key] = JSON.parse(cstr)
        }
      })
    }
  }

  return {
    loadEnvFile,
    loadEnvFiles,
    buildEnvironmentBlock,
    interpolate
  }
}

<|endoftext|>


<commit_before>var grunt = require('grunt');
var wrench = require('wrench');
var assert = require('assert');

grunt.task.init([]);
grunt.config.init({});

describe('jsloader', function() {

    beforeEach(function() {
        wrench.copyDirSyncRecursive('test/fixtures', 'tmp');
    });

    afterEach(function() {
        wrench.rmdirSyncRecursive('tmp');
    });

    describe('given a main file, and two scripts with one dependency',
    function() {

        beforeEach(function() {
            grunt.log.muted = true;
            grunt.config.init();
            grunt.config('jsloader', {
                test: {
                    main: 'tmp/main.js',
                    scripts: {
                        foo: 'tmp/foo.js',
                        bar: {
                            src: 'tmp/bar.js',
                            dep: 'foo'
                        }
                    }
                }
            });
            grunt.task.run('jsloader');
            grunt.task.start();
        });

        it('should add $script loading code to main file', function() {

            var changed = grunt.file.read('tmp/main.js');
            var expect = grunt.file.read('test/expected/main_with_script.js');

            assert.equal(expect, changed);

        });

        it('should not add $script.ready to files without dependencies',
        function() {

            var changed = grunt.file.read('tmp/foo.js');
            var expect = grunt.file.read('test/expected/foo_no_deps.js');

            assert.equal(expect, changed);

        });

        it('should $script.ready to block execution of the file until ' +
                'dependencies are loaded',
        function() {

            var changed = grunt.file.read('tmp/bar.js');
            var expect = grunt.file.read('test/expected/bar_depends_on_foo.js');

            assert.equal(expect, changed);

        });

    });

    describe('given a file with multiple dependencies', function() {

        beforeEach(function() {
            grunt.log.muted = true;
            grunt.config.init();
            grunt.config('jsloader', {
                test: {
                    main: 'tmp/main.js',
                    scripts: {
                        foo: 'tmp/foo.js',
                        bar: 'tmp/bar.js',
                        baz: {
                            src: 'tmp/baz.js',
                            dep: ['foo', 'bar']
                        }
                    }
                }
            });
            grunt.task.run('jsloader');
            grunt.task.start();
        });

        it('should add $script.ready to the file and include ' +
            'an array of dependencies',
        function() {

            var changed = grunt.file.read('tmp/baz.js');
            var expect =
                    grunt.file.read(
                        'test/expected/baz_depends_on_foo_and_bar.js'
                    );

            assert.equal(expect, changed);

        });

    });

    describe('given a main file where the placeholder has no whitespace, ' +
                'linebreak, or tab before it',
    function() {

        beforeEach(function() {
            grunt.log.muted = true;
            grunt.config.init();
            grunt.config('jsloader', {
                test: {
                    main: 'tmp/main_no_space.js',
                    scripts: {
                        foo: 'tmp/foo.js'
                    }
                }
            });
            grunt.task.run('jsloader');
            grunt.task.start();
        });

        it('should add $script loading code to main file', function() {

            var changed = grunt.file.read('tmp/main_no_space.js');
            var expect = grunt.file.read('test/expected/main_no_space.js');

            assert.equal(expect, changed);

        });

    });

});

<commit_msg>moved grunt mute to first beforeEach<commit_after>var grunt = require('grunt');
var wrench = require('wrench');
var assert = require('assert');

grunt.task.init([]);
grunt.config.init({});

describe('jsloader', function() {

    beforeEach(function() {
        wrench.copyDirSyncRecursive('test/fixtures', 'tmp');
        grunt.log.muted = true;
    });

    afterEach(function() {
        wrench.rmdirSyncRecursive('tmp');
    });

    describe('given a main file, and two scripts with one dependency',
    function() {

        beforeEach(function() {
            grunt.config.init();
            grunt.config('jsloader', {
                test: {
                    main: 'tmp/main.js',
                    scripts: {
                        foo: 'tmp/foo.js',
                        bar: {
                            src: 'tmp/bar.js',
                            dep: 'foo'
                        }
                    }
                }
            });
            grunt.task.run('jsloader');
            grunt.task.start();
        });

        it('should add $script loading code to main file', function() {

            var changed = grunt.file.read('tmp/main.js');
            var expect = grunt.file.read('test/expected/main_with_script.js');

            assert.equal(expect, changed);

        });

        it('should not add $script.ready to files without dependencies',
        function() {

            var changed = grunt.file.read('tmp/foo.js');
            var expect = grunt.file.read('test/expected/foo_no_deps.js');

            assert.equal(expect, changed);

        });

        it('should $script.ready to block execution of the file until ' +
                'dependencies are loaded',
        function() {

            var changed = grunt.file.read('tmp/bar.js');
            var expect = grunt.file.read('test/expected/bar_depends_on_foo.js');

            assert.equal(expect, changed);

        });

    });

    describe('given a file with multiple dependencies', function() {

        beforeEach(function() {
            grunt.config.init();
            grunt.config('jsloader', {
                test: {
                    main: 'tmp/main.js',
                    scripts: {
                        foo: 'tmp/foo.js',
                        bar: 'tmp/bar.js',
                        baz: {
                            src: 'tmp/baz.js',
                            dep: ['foo', 'bar']
                        }
                    }
                }
            });
            grunt.task.run('jsloader');
            grunt.task.start();
        });

        it('should add $script.ready to the file and include ' +
            'an array of dependencies',
        function() {

            var changed = grunt.file.read('tmp/baz.js');
            var expect =
                    grunt.file.read(
                        'test/expected/baz_depends_on_foo_and_bar.js'
                    );

            assert.equal(expect, changed);

        });

    });

    describe('given a main file where the placeholder has no whitespace, ' +
                'linebreak, or tab before it',
    function() {

        beforeEach(function() {
            grunt.config.init();
            grunt.config('jsloader', {
                test: {
                    main: 'tmp/main_no_space.js',
                    scripts: {
                        foo: 'tmp/foo.js'
                    }
                }
            });
            grunt.task.run('jsloader');
            grunt.task.start();
        });

        it('should add $script loading code to main file', function() {

            var changed = grunt.file.read('tmp/main_no_space.js');
            var expect = grunt.file.read('test/expected/main_no_space.js');

            assert.equal(expect, changed);

        });

    });

});

<|endoftext|>


<commit_before>const Graph = require('generic-digraph')
const MAX_BAL_BYTES = require('./constants.js').MAX_BAL_BYTES

module.exports = class Environment {
  constructor (data) {
    const defaults = {
      // gas tank
      gasPrice: 0,
      gasLimit: 0, // The gas limit for the block
      gasRefund: 0,
      // call infromation
      address: new Uint8Array(20),
      origin: new Uint8Array(20),
      coinbase: new Uint8Array(20),
      difficulty: new Uint8Array(20),
      caller: new Uint8Array(20),
      callValue: new Uint8Array(MAX_BAL_BYTES),
      callData: new ArrayBuffer(),
      // the ROM
      code: new ArrayBuffer(), // the current running code
      // output calls
      logs: [],
      suicideAddress: new ArrayBuffer(),
      // more output calls
      returnValue: new ArrayBuffer()
    }

    this.state = new Map()

    if (data) {
      data = JSON.parse(data)
    } else {
      data = {}
    }

    Object.assign(this, defaults, data)
    if (data.accounts) {
      this.accounts = new Graph()
      const self = this
      data.accounts.forEach((account) => {
        self.accounts.set(new Uint8Array(account[0]).toString(), account[1])
      })
    }

    if (data.address) {
      this.address = new Uint8Array(data.address)
    }

    if (data.origin) {
      this.origin = new Uint8Array(data.origin)
    }

    if (data.caller) {
      this.caller = new Uint8Array(data.caller)
    }

    if (data.callValue) {
      this.callValue = new Uint8Array(data.callValue)
    }

    if (data.callData) {
      this.callData = hexStr2arrayBuf(data.callData)
    }
  }

  getBalance (address) {
    return this.accounts.getValue(address.toString()).balance
  }

  getCode (address) {
    // STUB
  }

  getBlockHash (height) {
    // STUB
  }

  // kernal
  create (code, value) {
    // STUB
  }

  call (gas, address, value, data) {
    // STUB
    return // result
  }

  delegateCall (gas, address, data) {
    // STUB
    return // result
  }
}

function hexStr2arrayBuf (string) {
  const ab = new ArrayBuffer(string.length / 2)
  const view = new Uint8Array(ab)
  string = [...string]
  let temp = ''
  string.forEach((el, i) => {
    temp += el
    if (i % 2) {
      view[(i + 1) / 2 - 1] = parseInt(temp, 16)
      temp = ''
    }
  })
  return ab
}
<commit_msg>Use constants in Environment<commit_after>const Graph = require('generic-digraph')
const constants = require('./constants.js')

module.exports = class Environment {
  constructor (data) {
    const defaults = {
      // gas tank
      gasPrice: 0,
      gasLimit: 0, // The gas limit for the block
      gasRefund: 0,
      // call infromation
      address: new Uint8Array(constants.ADD_SIZE_BYTES),
      origin: new Uint8Array(constants.ADD_SIZE_BYTES),
      coinbase: new Uint8Array(constants.ADD_SIZE_BYTES),
      difficulty: new Uint8Array(20),
      caller: new Uint8Array(constants.ADD_SIZE_BYTES),
      callValue: new Uint8Array(constants.MAX_BAL_BYTES),
      callData: new ArrayBuffer(),
      // the ROM
      code: new ArrayBuffer(), // the current running code
      // output calls
      logs: [],
      suicideAddress: new ArrayBuffer(),
      // more output calls
      returnValue: new ArrayBuffer()
    }

    this.state = new Map()

    if (data) {
      data = JSON.parse(data)
    } else {
      data = {}
    }

    Object.assign(this, defaults, data)
    if (data.accounts) {
      this.accounts = new Graph()
      const self = this
      data.accounts.forEach((account) => {
        self.accounts.set(new Uint8Array(account[0]).toString(), account[1])
      })
    }

    if (data.address) {
      this.address = new Uint8Array(data.address)
    }

    if (data.origin) {
      this.origin = new Uint8Array(data.origin)
    }

    if (data.caller) {
      this.caller = new Uint8Array(data.caller)
    }

    if (data.callValue) {
      this.callValue = new Uint8Array(data.callValue)
    }

    if (data.callData) {
      this.callData = hexStr2arrayBuf(data.callData)
    }
  }

  getBalance (address) {
    return this.accounts.getValue(address.toString()).balance
  }

  getCode (address) {
    // STUB
  }

  getBlockHash (height) {
    // STUB
  }

  // kernal
  create (code, value) {
    // STUB
  }

  call (gas, address, value, data) {
    // STUB
    return // result
  }

  delegateCall (gas, address, data) {
    // STUB
    return // result
  }
}

function hexStr2arrayBuf (string) {
  const ab = new ArrayBuffer(string.length / 2)
  const view = new Uint8Array(ab)
  string = [...string]
  let temp = ''
  string.forEach((el, i) => {
    temp += el
    if (i % 2) {
      view[(i + 1) / 2 - 1] = parseInt(temp, 16)
      temp = ''
    }
  })
  return ab
}
<|endoftext|>


<commit_before>/**
 * CSS bootstrap template for Grunt
 */

// Basic template description.
exports.description = 'Create a CSS bootstrap directory.';
exports.warnOn = 'css';

// The actual init template.
exports.template = function(grunt, init, done) {

	grunt.helper('prompt', {}, [
			{
				name: 'maxwidth',
				message: 'Page max width',
				default: '1000px'
			},
			{
				name: 'footer',
				message: 'Sticky footer height',
				default: 'no sticky footer'
			},
			{
				name: 'gridCols',
				message: 'Grid: number of columns (or none)',
				default: '12'
			},
			{
				name: 'gridGutter',
				message: 'Grid: gutter width (0—19)',
				default: '5'
			}
		], function(err, props) {
		grunt.utils._.defaults(props, init.defaults);

		// Grid
		if (props.gridCols) {
			var anygrid = require('./_src/anygrid');
			props.gridCss = anygrid.generate(props.gridCols, props.gridGutter);
		}

		// Files to copy (and process).
		var files = init.filesToCopy(props);

		// Actually copy (and process) files.
		init.copyAndProcess(files, props);

		// All done!
		done();
	});

};
<commit_msg>Cssdir: Deprecate.<commit_after>/**
 * CSS bootstrap template for Grunt
 */

// Basic template description.
exports.description = '[Deprecated] Create a CSS bootstrap directory.';
exports.warnOn = 'css';

// The actual init template.
exports.template = function(grunt, init, done) {

	grunt.helper('prompt', {}, [
			{
				name: 'maxwidth',
				message: 'Page max width',
				default: '1000px'
			},
			{
				name: 'footer',
				message: 'Sticky footer height',
				default: 'no sticky footer'
			},
			{
				name: 'gridCols',
				message: 'Grid: number of columns (or none)',
				default: '12'
			},
			{
				name: 'gridGutter',
				message: 'Grid: gutter width (0—19)',
				default: '5'
			}
		], function(err, props) {
		grunt.utils._.defaults(props, init.defaults);

		// Grid
		if (props.gridCols) {
			var anygrid = require('./_src/anygrid');
			props.gridCss = anygrid.generate(props.gridCols, props.gridGutter);
		}

		// Files to copy (and process).
		var files = init.filesToCopy(props);

		// Actually copy (and process) files.
		init.copyAndProcess(files, props);

		// All done!
		done();
	});

};
<|endoftext|>


<commit_before>// **ShExLoader** return promise to load ShExC, ShExJ and N3 (Turtle) files.

var FS = require("fs");
var N3 = require("n3");
var ShExUtil = require("../lib/ShExUtil");
var ShExParser = require("../lib/ShExParser").Parser;
var Request = require("request-promise");
var Promise = require("promise");
var Path = require("path");
var Jsonld = require("jsonld");

/* Helper function to read from filesystem or web.
 */
function GET (f) {
  return f === "-" ?
    new Promise(function (fulfill, reject) {
      var inputChunks = [];

      //process.stdin.resume(); is old mode needed?
      process.stdin.setEncoding("utf8");

      process.stdin.on("data", function (chunk) {
        inputChunks.push(chunk);
      });

      process.stdin.on("end", function () {
        fulfill({text: inputChunks.join(""), url: f});
      });

      process.stdin.on("error", function (e) {
        reject(e);
      });
    }) : (f.match("^[a-z]+://.") && !f.match("^file://.")) ?
    // Read from http or whatever Request handles.
    Request(f).then(function (text) {
      return {text: text, url: f};
    }) :
  // Read from filesystem
  new Promise(function (fulfill, reject) {
    var filename = f;
    var fileURLmatch = filename.match("^file://[^/]*(/.*)$");
    if (fileURLmatch) {
      filename = fileURLmatch[1];
    }
    FS.readFile(filename, "utf8", function (error, text) {
      if (error) {
        reject(error)
      } else {
        fulfill({text: text, url: fileURLmatch ? f : "file://" + Path.resolve(process.cwd(), f)});
      }
    })
  });
}

function loadList (list, done) {
  return list.map(function (p) {
    return GET(p).then(function (loaded) {
      return done(loaded.text, loaded.url);
    });
  });
}

/* LoadPromise - load shex and json files into a single Schema and turtle into
 * a graph (Data).
 */
function LoadPromise (shex, json, turtle, jsonld) {
  var returns = {
    schema: ShExUtil.emptySchema(),
    data: N3.Store(),
    schemaMeta: [],
    dataMeta: []
  }

  function add (src, metaList, mediaType, f, target) {
    return loadList(src, function (text, url) {
      var meta = {mediaType: mediaType, url: url, base: url, prefixes: {}};
      metaList.push(meta);
      return new Promise(function (resolve, reject) {
        f(resolve, reject, text, mediaType, url, target, meta);
      });
    })
  }

  return Promise.all([].
                     // gather all the potentially remote inputs
                     concat(add(shex, returns.schemaMeta,
                                "text/shex", parseShExC, returns.schema)).
                     concat(add(json, returns.schemaMeta,
                                "text/json", parseShExJ, returns.schema)).
                     concat(add(turtle, returns.dataMeta,
                                "text.turtle", parseTurtle, returns.data)).
                     concat(add(jsonld, returns.dataMeta,
                                "application/ld+json", parseJSONLD, returns.data))
                    ).then(function () { return returns; });
}

function parseShExC (resolve, reject, text, mediaType, url, schema, meta) {
  try {
    var s = (new ShExParser(url)).parse(text);
    // !! horrible hack until I set a variable to know if there's a BASE.
    if (s.base === url) delete s.base;
    ShExUtil.merge(schema, s, true, true);
    meta.prefixes = schema.prefixes;
    meta.base = schema.base;
    resolve([mediaType, url]);
  } catch (e) {
    reject("error parsing ShEx " + url + ": " + e);
  }
}

function parseShExJ (resolve, reject, text, mediaType, url, schema, meta) {
  try {
    var s = JSON.parse(text);
    ShExUtil.merge(schema, s, true, true);
    meta.prefixes = schema.prefixes;
    meta.base = schema.base;
    resolve([mediaType, url]);
  } catch (e) {
    reject("error parsing JSON " + url + ": " + e);
  }
}

function parseTurtle (resolve, reject, text, mediaType, url, data, meta) {
  N3.Parser({documentIRI: url, blankNodePrefix: ""}).
    parse(text,
          function (error, triple, prefixes) {
            if (prefixes)
              meta.prefixes = prefixes;
              data.addPrefixes(prefixes);
            if (error) {
              reject("error parsing " + url + ": " + error);
            } else if (triple) {
              data.addTriple(triple)
            } else {
              meta.base = this._base;
              resolve([mediaType, url]);
            }
          });
}

function parseJSONLD (resolve, reject, text, mediaType, url, data, meta) {
  var struct = JSON.parse(text);
  Jsonld.toRDF(struct, {format: "application/nquads", base: url}, function (lderr, nquads) {
    if (lderr) {
      reject("error parsing JSON-ld " + url + ": " + lderr);
    } else {
      meta.prefixes = {}; // @@ take from @context?
      meta.base = url;    // @@ take from @context.base? (or vocab?)
      parseTurtle(resolve, reject, nquads, mediaType, url, data, meta);
    }
  });
}

function LoadExtensions () {
  return FS.
    readdirSync(__dirname + "/../extensions").
    filter(function (s) { return s.indexOf(".js") !== -1; }).
    reduce(function (ret, module) {
      var t = require(__dirname + "/../extensions/" + module);
      ret[t.url] = t;
      return ret;
    }, {});
}

// Expose ShExLoader, attaching all functions to it
if (typeof require !== "undefined" && typeof exports !== "undefined")
  module.exports = { load: LoadPromise, loadExtensions: LoadExtensions, GET: GET }; // node environment
else
  ShExLoader = LoadPromise;
<commit_msg>~ augment ShExC parsing error<commit_after>// **ShExLoader** return promise to load ShExC, ShExJ and N3 (Turtle) files.

var FS = require("fs");
var N3 = require("n3");
var ShExUtil = require("../lib/ShExUtil");
var ShExParser = require("../lib/ShExParser").Parser;
var Request = require("request-promise");
var Promise = require("promise");
var Path = require("path");
var Jsonld = require("jsonld");

/* Helper function to read from filesystem or web.
 */
function GET (f) {
  return f === "-" ?
    new Promise(function (fulfill, reject) {
      var inputChunks = [];

      //process.stdin.resume(); is old mode needed?
      process.stdin.setEncoding("utf8");

      process.stdin.on("data", function (chunk) {
        inputChunks.push(chunk);
      });

      process.stdin.on("end", function () {
        fulfill({text: inputChunks.join(""), url: f});
      });

      process.stdin.on("error", function (e) {
        reject(e);
      });
    }) : (f.match("^[a-z]+://.") && !f.match("^file://.")) ?
    // Read from http or whatever Request handles.
    Request(f).then(function (text) {
      return {text: text, url: f};
    }) :
  // Read from filesystem
  new Promise(function (fulfill, reject) {
    var filename = f;
    var fileURLmatch = filename.match("^file://[^/]*(/.*)$");
    if (fileURLmatch) {
      filename = fileURLmatch[1];
    }
    FS.readFile(filename, "utf8", function (error, text) {
      if (error) {
        reject(error)
      } else {
        fulfill({text: text, url: fileURLmatch ? f : "file://" + Path.resolve(process.cwd(), f)});
      }
    })
  });
}

function loadList (list, done) {
  return list.map(function (p) {
    return GET(p).then(function (loaded) {
      return done(loaded.text, loaded.url);
    });
  });
}

/* LoadPromise - load shex and json files into a single Schema and turtle into
 * a graph (Data).
 */
function LoadPromise (shex, json, turtle, jsonld) {
  var returns = {
    schema: ShExUtil.emptySchema(),
    data: N3.Store(),
    schemaMeta: [],
    dataMeta: []
  }

  function add (src, metaList, mediaType, f, target) {
    return loadList(src, function (text, url) {
      var meta = {mediaType: mediaType, url: url, base: url, prefixes: {}};
      metaList.push(meta);
      return new Promise(function (resolve, reject) {
        f(resolve, reject, text, mediaType, url, target, meta);
      });
    })
  }

  return Promise.all([].
                     // gather all the potentially remote inputs
                     concat(add(shex, returns.schemaMeta,
                                "text/shex", parseShExC, returns.schema)).
                     concat(add(json, returns.schemaMeta,
                                "text/json", parseShExJ, returns.schema)).
                     concat(add(turtle, returns.dataMeta,
                                "text.turtle", parseTurtle, returns.data)).
                     concat(add(jsonld, returns.dataMeta,
                                "application/ld+json", parseJSONLD, returns.data))
                    ).then(function () { return returns; });
}

function parseShExC (resolve, reject, text, mediaType, url, schema, meta) {
  try {
    var s = (new ShExParser(url)).parse(text);
    // !! horrible hack until I set a variable to know if there's a BASE.
    if (s.base === url) delete s.base;
    ShExUtil.merge(schema, s, true, true);
    meta.prefixes = schema.prefixes;
    meta.base = schema.base;
    resolve([mediaType, url]);
  } catch (e) {
    var e2 = Error("error parsing ShEx " + url + ": " + e);
    e2.stack = e.stack;
    reject(e2);
  }
}

function parseShExJ (resolve, reject, text, mediaType, url, schema, meta) {
  try {
    var s = JSON.parse(text);
    ShExUtil.merge(schema, s, true, true);
    meta.prefixes = schema.prefixes;
    meta.base = schema.base;
    resolve([mediaType, url]);
  } catch (e) {
    reject("error parsing JSON " + url + ": " + e);
  }
}

function parseTurtle (resolve, reject, text, mediaType, url, data, meta) {
  N3.Parser({documentIRI: url, blankNodePrefix: ""}).
    parse(text,
          function (error, triple, prefixes) {
            if (prefixes)
              meta.prefixes = prefixes;
              data.addPrefixes(prefixes);
            if (error) {
              reject("error parsing " + url + ": " + error);
            } else if (triple) {
              data.addTriple(triple)
            } else {
              meta.base = this._base;
              resolve([mediaType, url]);
            }
          });
}

function parseJSONLD (resolve, reject, text, mediaType, url, data, meta) {
  var struct = JSON.parse(text);
  Jsonld.toRDF(struct, {format: "application/nquads", base: url}, function (lderr, nquads) {
    if (lderr) {
      reject("error parsing JSON-ld " + url + ": " + lderr);
    } else {
      meta.prefixes = {}; // @@ take from @context?
      meta.base = url;    // @@ take from @context.base? (or vocab?)
      parseTurtle(resolve, reject, nquads, mediaType, url, data, meta);
    }
  });
}

function LoadExtensions () {
  return FS.
    readdirSync(__dirname + "/../extensions").
    filter(function (s) { return s.indexOf(".js") !== -1; }).
    reduce(function (ret, module) {
      var t = require(__dirname + "/../extensions/" + module);
      ret[t.url] = t;
      return ret;
    }, {});
}

// Expose ShExLoader, attaching all functions to it
if (typeof require !== "undefined" && typeof exports !== "undefined")
  module.exports = { load: LoadPromise, loadExtensions: LoadExtensions, GET: GET }; // node environment
else
  ShExLoader = LoadPromise;
<|endoftext|>


<commit_before>'use strict';

const SymbolTreeNode = require('./SymbolTreeNode');

/**
 * @module symbol-tree
 * @author Joris van der Wel <joris@jorisvanderwel.com>
 */

/**
 * @param [description='SymbolTree data'] Description used for the Symbol
 * @constructor
 * @alias module:symbol-tree
 */
module.exports = class SymbolTree {
        constructor(description) {
                this.symbol = Symbol(description || 'SymbolTree data');
        }

        /**
         * You can optionally initialize an object after its creation,
         * to take advantage of V8's fast properties
         * @method initialize
         * @param {Object} object
         * @return {Object} object
         */
        initialize(object) {
                this._node(object);

                return object;
        }

        _node(object) {
                if (!object) {
                        return null;
                }

                const node = object[this.symbol];

                if (node) {
                        return node;
                }

                return (object[this.symbol] = new SymbolTreeNode());
        }

        /**
         * Returns true if the object has any children.
         * `O(1)`
         * @method isEmpty
         * @param {Object} object
         * @return {Boolean}
         */
        isEmpty(object) {
                return this._node(object).isEmpty;
        }

        /**
         * Return the first child of the given object.
         * `O(1)`
         * @method first
         * @param {Object} object
         * @return {Object}
         */
        first(object) {
                return this._node(object).first;
        }

        /**
         * Return the last child of the given object.
         * `O(1)`
         * @method last
         * @param {Object} object
         * @return {Object}
         */
        last(object) {
                return this._node(object).last;
        }

        /**
         * Return the previous sibling of the given object.
         * `O(1)`
         * @method prev
         * @param {Object} object
         * @return {Object}
         */
        prev(object) {
                return this._node(object).prev;
        }

        /**
         * Return the next sibling of the given object.
         * `O(1)`
         * @method next
         * @param {Object} object
         * @return {Object}
         */
        next(object) {
                return this._node(object).next;
        }

        /**
         * Return the parent of the given object.
         * `O(1)`
         * @method parent
         * @param {Object} object
         * @return {Object}
         */
        parent(object) {
                return this._node(object).parent;
        }

        /**
         * Find the inclusive descendant that is last in tree order of the given object.
         *
         * `O(n)` (worst case)
         *
         * @method lastInclusiveDescendant
         * @param {Object} object
         * @return {Object}
         */
        lastInclusiveDescendant(object) {
                let last;

                while ( (last = this._node(object).last) ) {
                        object = last;
                }

                return object;
        }
         * Find the preceding object (A) of the given object (B).
         * An object A is preceding an object B if A and B are in the same tree
         * and A comes before B in tree order.
         * @method preceding
         * @param {Object} object
         * @param {Object} [treeRoot] If set, `treeRoot` must be an inclusive ancestor
         *        of the return value (or else null is returned). This check _assumes_
         *        that `root` is also an inclusive ancestor of the given `node`
         * @returns {?Object}
         */
        preceding(object, treeRoot) {
                if (object === treeRoot) {
                        return null;
                }

                const prev = this._node(object).prev;

                if (prev) {
                        return this.lastInclusiveDescendant(prev);
                }

                // if there is no previous sibling return the parent (might be null)
                return this._node(object).parent;
        }

        /**
         * Find the following object (A) of the given object (B).
         * An object A is following an object B if A and B are in the same tree
         * and A comes after B in tree order.
         * @method following
         * @param {!Object} object
         * @param {Object} [treeRoot] If set, `treeRoot` must be an inclusive ancestor
         *        of the return value (or else null is returned). This check _assumes_
         *        that `root` is also an inclusive ancestor of the given `node`
         * @param {Boolean} [skipChildren=false] If set, ignore the childen of `object`
         * @returns {?Object}
         */
        following(object, treeRoot, skipChildren) {
                const first = !skipChildren && this._node(object).first;

                if (first) {
                        return first;
                }

                do {
                        if (object === treeRoot) {
                                return null;
                        }

                        const next = this._node(object).next;

                        if (next) {
                                return next;
                        }

                        object = this._node(object).parent;
                        // https://github.com/jscs-dev/node-jscs/commit/07d30b77388a2e182a40b00891c7ac1837281016
                        // jscs:disable requirePaddingNewlinesBeforeKeywords
                } while (object);
                // jscs:enable requirePaddingNewlinesBeforeKeywords

                return null;
        }

        /**
         * Remove the object from this tree.
         * `O(1)`
         * Has no effect if already removed.
         * @method remove
         * @param {Object} removeObject
         * @return {Object} removeObject
         */
        remove(removeObject) {
                const removeNode = this._node(removeObject);
                const parentNode = this._node(removeNode.parent);
                const prevNode = this._node(removeNode.prev);
                const nextNode = this._node(removeNode.next);

                if (parentNode) {
                        if (parentNode.first === removeObject) {
                                parentNode.first = removeNode.next;
                        }

                        if (parentNode.last === removeObject) {
                                parentNode.last = removeNode.prev;
                        }
                }

                if (prevNode) {
                        prevNode.next = removeNode.next;
                }

                if (nextNode) {
                        nextNode.prev = removeNode.prev;
                }

                removeNode.parent = null;
                removeNode.prev = null;
                removeNode.next = null;

                return removeObject;
        }

        /**
         * Insert the given object before the reference object.
         * `O(1)`
         * `newObject` is now the previous sibling of `referenceObject`
         *
         * @method insertBefore
         * @param {Object} newObject
         * @param {Object} referenceObject
         * @throws {Error} If the newObject is already present in this SymbolTree
         * @return {Object} newObject
         */
        insertBefore(newObject, referenceObject) {
                const referenceNode = this._node(referenceObject);
                const prevNode = this._node(referenceNode.prev);
                const newNode = this._node(newObject);
                const parentNode = this._node(referenceNode.parent);

                if (newNode.isAttached) {
                        throw Error('Given object is already present in this SymbolTree, remove it first');
                }

                newNode.parent = referenceNode.parent;
                newNode.prev = referenceNode.prev;
                newNode.next = referenceObject;
                referenceNode.prev = newObject;

                if (prevNode) {
                        prevNode.next = newObject;
                }

                if (parentNode && parentNode.first === referenceObject) {
                        parentNode.first = newObject;
                }

                return newObject;
        }

        /**
         * Insert the given object after the reference object.
         * `O(1)`
         * `newObject` is now the next sibling of `referenceObject`
         *
         * @method insertAfter
         * @param {Object} newObject
         * @param {Object} referenceObject
         * @throws {Error} If the newObject is already present in this SymbolTree
         * @return {Object} newObject
         */
        insertAfter(newObject, referenceObject) {
                const referenceNode = this._node(referenceObject);
                const nextNode = this._node(referenceNode.next);
                const newNode = this._node(newObject);
                const parentNode = this._node(referenceNode.parent);

                if (newNode.isAttached) {
                        throw Error('Given object is already present in this SymbolTree, remove it first');
                }

                newNode.parent = referenceNode.parent;
                newNode.prev = referenceObject;
                newNode.next = referenceNode.next;
                referenceNode.next = newObject;

                if (nextNode) {
                        nextNode.prev = newObject;
                }

                if (parentNode && parentNode.last === referenceObject) {
                        parentNode.last = newObject;
                }

                return newObject;
        }

        /**
         * Insert the given object as the first child of the given reference object.
         * `O(1)`
         * `newObject` is now the first child of `referenceObject`
         *
         * @method insertFirst
         * @param {Object} newObject
         * @param {Object} referenceObject
         * @throws {Error} If the newObject is already present in this SymbolTree
         * @return {Object} newObject
         */
        insertFirst(newObject, referenceObject) {
                const referenceNode = this._node(referenceObject);
                const newNode = this._node(newObject);

                if (newNode.isAttached) {
                        throw Error('Given object is already present in this SymbolTree, remove it first');
                }

                if (referenceNode.isEmpty) {
                        newNode.parent = referenceObject;
                        referenceNode.first = newObject;
                        referenceNode.last = newObject;
                }
                else {
                        this.insertBefore(newObject, referenceNode.first);
                }

                return newObject;
        }

        /**
         * Insert the given object as the last child of the given reference object.
         * `O(1)`
         * `newObject` is now the last child of `referenceObject`
         *
         * @method insertLast
         * @param {Object} newObject
         * @param {Object} referenceObject
         * @throws {Error} If the newObject is already present in this SymbolTree
         * @return {Object} newObject
         */
        insertLast(newObject, referenceObject) {
                const referenceNode = this._node(referenceObject);
                const newNode = this._node(newObject);

                if (newNode.isAttached) {
                        throw Error('Given object is already present in this SymbolTree, remove it first');
                }

                if (referenceNode.isEmpty) {
                        newNode.parent = referenceObject;
                        referenceNode.first = newObject;
                        referenceNode.last = newObject;
                }
                else {
                        this.insertAfter(newObject, referenceNode.last);
                }

                return newObject;
        }
};
<commit_msg>Improve jsdoc<commit_after>'use strict';

/**
 * @module symbol-tree
 * @author Joris van der Wel <joris@jorisvanderwel.com>
 */

const SymbolTreeNode = require('./SymbolTreeNode');

class SymbolTree {

        /**
         * @constructor
         * @alias module:symbol-tree
         * @param [description='SymbolTree data'] Description used for the Symbol
         */
        constructor(description) {
                this.symbol = Symbol(description || 'SymbolTree data');
        }

        /**
         * You can optionally initialize an object after its creation,
         * to take advantage of V8's fast properties. Also useful if you would like to
         * freeze your object.
         *
         * `O(1)`
         *
         * @method
         * @alias module:symbol-tree#initialize
         * @param {Object} object
         * @return {Object} object
         */
        initialize(object) {
                this._node(object);

                return object;
        }

        _node(object) {
                if (!object) {
                        return null;
                }

                const node = object[this.symbol];

                if (node) {
                        return node;
                }

                return (object[this.symbol] = new SymbolTreeNode());
        }

        /**
         * Returns true if the object has any children.
         *
         * `O(1)`
         *
         * @method isEmpty
         * @memberOf module:symbol-tree#
         * @param {Object} object
         * @return {Boolean}
         */
        isEmpty(object) {
                return this._node(object).isEmpty;
        }

        /**
         * Return the first child of the given object.
         *
         * `O(1)`
         *
         * @method first
         * @memberOf module:symbol-tree#
         * @param {Object} object
         * @return {Object}
         */
        first(object) {
                return this._node(object).first;
        }

        /**
         * Return the last child of the given object.
         *
         * `O(1)`
         *
         * @method last
         * @memberOf module:symbol-tree#
         * @param {Object} object
         * @return {Object}
         */
        last(object) {
                return this._node(object).last;
        }

        /**
         * Return the previous sibling of the given object.
         *
         * `O(1)`
         *
         * @method prev
         * @memberOf module:symbol-tree#
         * @param {Object} object
         * @return {Object}
         */
        prev(object) {
                return this._node(object).prev;
        }

        /**
         * Return the next sibling of the given object.
         *
         * `O(1)`
         *
         * @method next
         * @memberOf module:symbol-tree#
         * @param {Object} object
         * @return {Object}
         */
        next(object) {
                return this._node(object).next;
        }

        /**
         * Return the parent of the given object.
         *
         * `O(1)`
         *
         * @method parent
         * @memberOf module:symbol-tree#
         * @param {Object} object
         * @return {Object}
         */
        parent(object) {
                return this._node(object).parent;
        }

        /**
         * Find the inclusive descendant that is last in tree order of the given object.
         *
         * `O(n)` (worst case)
         *
         * @method lastInclusiveDescendant
         * @memberOf module:symbol-tree#
         * @param {Object} object
         * @return {Object}
         */
        lastInclusiveDescendant(object) {
                let last;

                while ( (last = this._node(object).last) ) {
                        object = last;
                }

                return object;
        }

        /**
         * Find the preceding object (A) of the given object (B).
         * An object A is preceding an object B if A and B are in the same tree
         * and A comes before B in tree order.
         *
         * `O(n)` (worst case)
         *
         * @method preceding
         * @memberOf module:symbol-tree#
         * @param {Object} object
         * @param {Object} [treeRoot] If set, `treeRoot` must be an inclusive ancestor
         *        of the return value (or else null is returned). This check _assumes_
         *        that `root` is also an inclusive ancestor of the given `node`
         * @returns {?Object}
         */
        preceding(object, treeRoot) {
                if (object === treeRoot) {
                        return null;
                }

                const prev = this._node(object).prev;

                if (prev) {
                        return this.lastInclusiveDescendant(prev);
                }

                // if there is no previous sibling return the parent (might be null)
                return this._node(object).parent;
        }

        /**
         * Find the following object (A) of the given object (B).
         * An object A is following an object B if A and B are in the same tree
         * and A comes after B in tree order.
         *
         * `O(n)` (worst case)
         *
         * @method following
         * @memberOf module:symbol-tree#
         * @param {!Object} object
         * @param {Object} [treeRoot] If set, `treeRoot` must be an inclusive ancestor
         *        of the return value (or else null is returned). This check _assumes_
         *        that `root` is also an inclusive ancestor of the given `node`
         * @param {Boolean} [skipChildren=false] If set, ignore the childen of `object`
         * @returns {?Object}
         */
        following(object, treeRoot, skipChildren) {
                const first = !skipChildren && this._node(object).first;

                if (first) {
                        return first;
                }

                do {
                        if (object === treeRoot) {
                                return null;
                        }

                        const next = this._node(object).next;

                        if (next) {
                                return next;
                        }

                        object = this._node(object).parent;
                        // https://github.com/jscs-dev/node-jscs/commit/07d30b77388a2e182a40b00891c7ac1837281016
                        // jscs:disable requirePaddingNewlinesBeforeKeywords
                } while (object);
                // jscs:enable requirePaddingNewlinesBeforeKeywords

                return null;
        }

        /**
         * Remove the object from this tree.
         * Has no effect if already removed.
         *
         * `O(1)`
         *
         * @method remove
         * @memberOf module:symbol-tree#
         * @param {Object} removeObject
         * @return {Object} removeObject
         */
        remove(removeObject) {
                const removeNode = this._node(removeObject);
                const parentNode = this._node(removeNode.parent);
                const prevNode = this._node(removeNode.prev);
                const nextNode = this._node(removeNode.next);

                if (parentNode) {
                        if (parentNode.first === removeObject) {
                                parentNode.first = removeNode.next;
                        }

                        if (parentNode.last === removeObject) {
                                parentNode.last = removeNode.prev;
                        }
                }

                if (prevNode) {
                        prevNode.next = removeNode.next;
                }

                if (nextNode) {
                        nextNode.prev = removeNode.prev;
                }

                removeNode.parent = null;
                removeNode.prev = null;
                removeNode.next = null;

                return removeObject;
        }

        /**
         * Insert the given object before the reference object.
         * `newObject` is now the previous sibling of `referenceObject`.
         *
         * `O(1)`
         *
         * @method insertBefore
         * @memberOf module:symbol-tree#
         * @param {Object} newObject
         * @param {Object} referenceObject
         * @throws {Error} If the newObject is already present in this SymbolTree
         * @return {Object} newObject
         */
        insertBefore(newObject, referenceObject) {
                const referenceNode = this._node(referenceObject);
                const prevNode = this._node(referenceNode.prev);
                const newNode = this._node(newObject);
                const parentNode = this._node(referenceNode.parent);

                if (newNode.isAttached) {
                        throw Error('Given object is already present in this SymbolTree, remove it first');
                }

                newNode.parent = referenceNode.parent;
                newNode.prev = referenceNode.prev;
                newNode.next = referenceObject;
                referenceNode.prev = newObject;

                if (prevNode) {
                        prevNode.next = newObject;
                }

                if (parentNode && parentNode.first === referenceObject) {
                        parentNode.first = newObject;
                }

                return newObject;
        }

        /**
         * Insert the given object after the reference object.
         * `newObject` is now the next sibling of `referenceObject`.
         *
         * `O(1)`
         *
         * @method insertAfter
         * @memberOf module:symbol-tree#
         * @param {Object} newObject
         * @param {Object} referenceObject
         * @throws {Error} If the newObject is already present in this SymbolTree
         * @return {Object} newObject
         */
        insertAfter(newObject, referenceObject) {
                const referenceNode = this._node(referenceObject);
                const nextNode = this._node(referenceNode.next);
                const newNode = this._node(newObject);
                const parentNode = this._node(referenceNode.parent);

                if (newNode.isAttached) {
                        throw Error('Given object is already present in this SymbolTree, remove it first');
                }

                newNode.parent = referenceNode.parent;
                newNode.prev = referenceObject;
                newNode.next = referenceNode.next;
                referenceNode.next = newObject;

                if (nextNode) {
                        nextNode.prev = newObject;
                }

                if (parentNode && parentNode.last === referenceObject) {
                        parentNode.last = newObject;
                }

                return newObject;
        }

        /**
         * Insert the given object as the first child of the given reference object.
         * `newObject` is now the first child of `referenceObject`.
         *
         * `O(1)`
         *
         * @method insertFirst
         * @memberOf module:symbol-tree#
         * @param {Object} newObject
         * @param {Object} referenceObject
         * @throws {Error} If the newObject is already present in this SymbolTree
         * @return {Object} newObject
         */
        insertFirst(newObject, referenceObject) {
                const referenceNode = this._node(referenceObject);
                const newNode = this._node(newObject);

                if (newNode.isAttached) {
                        throw Error('Given object is already present in this SymbolTree, remove it first');
                }

                if (referenceNode.isEmpty) {
                        newNode.parent = referenceObject;
                        referenceNode.first = newObject;
                        referenceNode.last = newObject;
                }
                else {
                        this.insertBefore(newObject, referenceNode.first);
                }

                return newObject;
        }

        /**
         * Insert the given object as the last child of the given reference object.
         * `newObject` is now the last child of `referenceObject`.
         *
         * `O(1)`
         *
         * @method insertLast
         * @memberOf module:symbol-tree#
         * @param {Object} newObject
         * @param {Object} referenceObject
         * @throws {Error} If the newObject is already present in this SymbolTree
         * @return {Object} newObject
         */
        insertLast(newObject, referenceObject) {
                const referenceNode = this._node(referenceObject);
                const newNode = this._node(newObject);

                if (newNode.isAttached) {
                        throw Error('Given object is already present in this SymbolTree, remove it first');
                }

                if (referenceNode.isEmpty) {
                        newNode.parent = referenceObject;
                        referenceNode.first = newObject;
                        referenceNode.last = newObject;
                }
                else {
                        this.insertAfter(newObject, referenceNode.last);
                }

                return newObject;
        }
}

module.exports = SymbolTree;<|endoftext|>


<commit_before>elation.require(['engine.things.generic', 'utils.template'], function() {
  elation.template.add('janusweb.edit.object',
      '<Object id=^{id}^ js_id=^{js_id}^ locked=^false^ pos=^{pos.x} {pos.y} {pos.z}^ vel=^{vel.x} {vel.y} {vel.z}^ accel=^{accel.x} {accel.y} {accel.z}^ xdir=^{xdir}^ ydir=^{ydir}^ zdir=^{zdir}^ scale=^{scale.x} {scale.y} {scale.z}^ col=^{col}^ lighting=^{lighting}^ visible=^{visible}^ />');

  elation.component.add('engine.things.janusbase', function() {
    this.postinit = function() {
      elation.engine.things.janusbase.extendclass.postinit.call(this);
      this.frameupdates = [];
      this.defineProperties({
        room:     { type: 'object' },
        janus:    { type: 'object' },
        js_id:    { type: 'string' },
        color:    { type: 'color', default: new THREE.Color(0xffffff), set: this.updateMaterial },
        fwd:      { type: 'vector3', default: new THREE.Vector3(0,0,1), set: this.pushFrameUpdate },
        xdir:     { type: 'vector3', default: new THREE.Vector3(1,0,0), set: this.pushFrameUpdate },
        ydir:     { type: 'vector3', default: new THREE.Vector3(0,1,0), set: this.pushFrameUpdate },
        zdir:     { type: 'vector3', default: new THREE.Vector3(0,0,1), set: this.pushFrameUpdate },
        lighting: { type: 'boolean', default: true },
        sync:     { type: 'boolean', default: false },
        rotate_axis: { type: 'string', default: '0 1 0' },
        rotate_deg_per_sec: { type: 'string' },
      });
      //if (this.col) this.color = this.col;
      this.jschildren = [];
      elation.events.add(this.room, 'janusweb_script_frame_end', elation.bind(this, this.handleFrameUpdates));
    }
    this.createForces = function() {
      elation.events.add(this.objects.dynamics, 'physics_collide', elation.bind(this, this.handleCollision));

      var rotate_axis = this.properties.rotate_axis,
          rotate_speed = this.properties.rotate_deg_per_sec;
      if (rotate_axis && rotate_speed) {
        var speed = (rotate_speed * Math.PI/180);
        var axisparts = rotate_axis.split(' ');
        var axis = new THREE.Vector3().set(axisparts[0], axisparts[1], axisparts[2]);
        axis.multiplyScalar(speed);
        this.objects.dynamics.setAngularVelocity(axis);
      }

    }
    this.setProperties = function(props) {
      var n = this.properties.room.parseNode(props);
      var rebuild = false;

      if (n.pos) this.properties.position.fromArray(n.pos);
      if (n.scale) this.properties.scale.fromArray(n.scale);
      if (n.orientation) this.properties.orientation.copy(n.orientation);

      if (n.id && n.id != this.properties.render.model) {
        this.properties.render.model = n.id;
        rebuild = true;
      }
      var curcol = this.properties.col || [1,1,1];
      if (n.col && (n.col[0] != curcol[0] || n.col[1] != curcol[1] || n.col[2] != curcol[2])) {
        this.properties.col = n.col;
        rebuild = true;
      }
      if (rebuild) {
        //this.set('visible', true, true);
      }
      if (n.accel) this.properties.acceleration.fromArray(n.accel.split(' ').map(parseFloat));
      if (n.vel) this.objects.dynamics.setVelocity(this.properties.velocity.fromArray(n.vel.split(' ').map(parseFloat)));
      this.refresh();
    }
    this.summarizeXML = function() {
      //'<Object id=^{id}^ js_id=^{js_id}^ locked=^false^ pos=^{pos.x} {pos.y} {pos.z}^ vel=^{vel.x} {vel.y} {vel.z}^ accel=^{accel.x} {accel.y} {accel.z}^ xdir=^{xdir}^ ydir=^{ydir}^ zdir=^{zdir}^ scale=^{scale.x} {scale.y} {scale.z}^ col=^{color}^ lighting=^{lighting}^ visible=^{visible}^ />');

      var matrix = new THREE.Matrix4().makeRotationFromQuaternion(this.properties.orientation);
      var xdir = new THREE.Vector3(),
          ydir = new THREE.Vector3(),
          zdir = new THREE.Vector3();
      matrix.extractBasis(xdir, ydir, zdir);

      var objdef = {
        id: this.properties.render.model,
        js_id: this.properties.js_id,
        pos: this.properties.position,
        vel: this.properties.velocity,
        accel: this.properties.acceleration,
        scale: this.properties.scale,
        xdir: xdir.toArray().join(' '),
        ydir: ydir.toArray().join(' '),
        zdir: zdir.toArray().join(' '),
        col: this.properties.color,
        lighting: this.properties.lighting,
        visible: this.properties.visible,
      };

      var xml = elation.template.get('janusweb.edit.object', objdef);
      return xml;
    }
    this.getProxyObject = function() {
      if (!this._proxyobject) {
        this._proxyobject = new elation.proxy(this, {
          js_id:    ['property', 'properties.js_id'],
          pos:      ['property', 'position'],
          vel:      ['property', 'velocity'],
          accel:    ['property', 'acceleration'],
          mass:     ['property', 'mass'],
          scale:    ['property', 'scale'],
          col:      ['property', 'color'],
          fwd:      ['property', 'zdir'],
          xdir:     ['property', 'xdir'],
          ydir:     ['property', 'ydir'],
          zdir:     ['property', 'zdir'],
          sync:     ['property', 'sync'],
          children: ['property', 'jschildren'],

          oncollision: ['callback', 'collision'],
          appendChild: ['function', 'appendChild']
        });
      }
      return this._proxyobject;
    }
    this.start = function() {
    }
    this.stop = function() {
    }
    this.pushFrameUpdate = function(key, value) {
//console.log('frame update!', key, value);
      this.frameupdates[key] = value;
    }
    this.handleFrameUpdates = function() {
      var updatenames = Object.keys(this.frameupdates);
      if (updatenames.length > 0) {
        var updates = this.frameupdates;
        if ('fwd' in updates) {
          this.properties.zdir.copy(this.fwd);
          updates.zdir = this.properties.zdir;
        }
        var xdir = this.properties.xdir,
            ydir = this.properties.ydir,
            zdir = this.properties.zdir;

        if ( ('xdir' in updates) &&
            !('ydir' in updates) &&
            !('zdir' in updates)) {
          zdir.crossVectors(xdir, ydir);
          this.updateVectors(true);
        }
        if (!('xdir' in updates) &&
            !('ydir' in updates) &&
             ('zdir' in updates)) {
          xdir.crossVectors(ydir, zdir);
          this.updateVectors(true);
        }
        if (!('xdir' in updates) &&
             ('ydir' in updates) &&
             ('zdir' in updates)) {
          xdir.crossVectors(zdir, ydir);
          this.updateVectors(true);
        }
        if ( ('xdir' in updates) &&
            !('ydir' in updates) &&
             ('zdir' in updates)) {
          ydir.crossVectors(xdir, zdir).multiplyScalar(-1);
          this.updateVectors(true);
        }
        if ( ('xdir' in updates) &&
             ('ydir' in updates) &&
            !('zdir' in updates)) {
          zdir.crossVectors(xdir, ydir);
          this.updateVectors(true);
        }

        if (!('xdir' in updates) &&
            !('ydir' in updates) &&
            !('zdir' in updates)) {
          // None specified, so update the vectors from the orientation quaternion
          this.updateVectors(false);
        }
        this.frameupdates = {};
      } else {
        this.updateVectors(false);
      }
    }
    this.updateVectors = function(updateOrientation) {
      if (updateOrientation) {
        //var quat = this.room.getOrientation(this.properties.xdir.toArray().join(' '), this.properties.ydir.toArray().join(' '), this.properties.zdir.toArray().join(' '));
        this.xdir.normalize();
        this.ydir.normalize();
        this.zdir.normalize();
        var mat4 = new THREE.Matrix4().makeBasis(this.xdir, this.ydir, this.properties.zdir.clone().negate());
        var quat = new THREE.Quaternion();
        var pos = new THREE.Vector3();
        var scale = new THREE.Vector3();
        quat.setFromRotationMatrix(mat4);
        //mat4.decompose(pos, this.orientation, scale);
        //this.orientation.normalize();
//console.log(mat4.elements);
        this.properties.orientation.copy(quat);
//console.log(this.xdir.toArray(), this.ydir.toArray(), this.zdir.toArray(), this.orientation.toArray());
//console.log(this.properties.orientation, this.properties.orientation.toArray());
      } else if (this.objects['3d']) {
        //this.objects['3d'].matrix.extractBasis(this.properties.xdir, this.properties.ydir, this.properties.zdir);
      }
    }
    this.appendChild = function(obj) {
      var proxyobj = obj
      if (elation.utils.isString(obj)) {
        proxyobj = this.room.jsobjects[obj];
      }
      if (proxyobj) {
        //var realobj = this.room.getObjectFromProxy(proxyobj);
        var realobj = proxyobj._target;
        if (realobj) {
          this.add(realobj);
          this.updateScriptChildren();
        }
      }
    }
    this.removeChild = function(obj) {
      var proxyobj = obj
      if (elation.utils.isString(obj)) {
        proxyobj = this.room.jsobjects[obj];
      }
      if (proxyobj) {
        //var realobj = this.room.getObjectFromProxy(proxyobj);
        var realobj = proxyobj._target;
        if (realobj) {
          this.remove(realobj);
          this.updateScriptChildren();
        }
      }
    }
    this.updateScriptChildren = function() {
      this.jschildren = [];
      var keys = Object.keys(this.children);
      for (var i = 0; i < keys.length; i++) {
        this.jschildren.push(this.children[keys[i]].getProxyObject());
      }
    }
    this.handleCollision = function(ev) {
      var obj1 = ev.data.bodies[0],
          obj2 = ev.data.bodies[1];
      //var proxy1 = obj1.getProxy(),
      //    proxy2 = obj2.getProxy();
      var other = (obj1.object == this ? obj2.object : obj1.object);
      if (other) {
        if (other.getProxyObject) {
          var proxy = other.getProxyObject();
          //console.log('I collided', proxy, this);
          elation.events.fire({type: 'collision', element: this, data: proxy});
        } else {
console.error('dunno what this is', other);
        }
      }
    }
  }, elation.engine.things.generic);
});
<commit_msg>Remove unnecessary negation in basis matrix computation<commit_after>elation.require(['engine.things.generic', 'utils.template'], function() {
  elation.template.add('janusweb.edit.object',
      '<Object id=^{id}^ js_id=^{js_id}^ locked=^false^ pos=^{pos.x} {pos.y} {pos.z}^ vel=^{vel.x} {vel.y} {vel.z}^ accel=^{accel.x} {accel.y} {accel.z}^ xdir=^{xdir}^ ydir=^{ydir}^ zdir=^{zdir}^ scale=^{scale.x} {scale.y} {scale.z}^ col=^{col}^ lighting=^{lighting}^ visible=^{visible}^ />');

  elation.component.add('engine.things.janusbase', function() {
    this.postinit = function() {
      elation.engine.things.janusbase.extendclass.postinit.call(this);
      this.frameupdates = [];
      this.defineProperties({
        room:     { type: 'object' },
        janus:    { type: 'object' },
        js_id:    { type: 'string' },
        color:    { type: 'color', default: new THREE.Color(0xffffff), set: this.updateMaterial },
        fwd:      { type: 'vector3', default: new THREE.Vector3(0,0,1), set: this.pushFrameUpdate },
        xdir:     { type: 'vector3', default: new THREE.Vector3(1,0,0), set: this.pushFrameUpdate },
        ydir:     { type: 'vector3', default: new THREE.Vector3(0,1,0), set: this.pushFrameUpdate },
        zdir:     { type: 'vector3', default: new THREE.Vector3(0,0,1), set: this.pushFrameUpdate },
        lighting: { type: 'boolean', default: true },
        sync:     { type: 'boolean', default: false },
        rotate_axis: { type: 'string', default: '0 1 0' },
        rotate_deg_per_sec: { type: 'string' },
      });
      //if (this.col) this.color = this.col;
      this.jschildren = [];
      elation.events.add(this.room, 'janusweb_script_frame_end', elation.bind(this, this.handleFrameUpdates));
    }
    this.createForces = function() {
      elation.events.add(this.objects.dynamics, 'physics_collide', elation.bind(this, this.handleCollision));

      var rotate_axis = this.properties.rotate_axis,
          rotate_speed = this.properties.rotate_deg_per_sec;
      if (rotate_axis && rotate_speed) {
        var speed = (rotate_speed * Math.PI/180);
        var axisparts = rotate_axis.split(' ');
        var axis = new THREE.Vector3().set(axisparts[0], axisparts[1], axisparts[2]);
        axis.multiplyScalar(speed);
        this.objects.dynamics.setAngularVelocity(axis);
      }

    }
    this.setProperties = function(props) {
      var n = this.properties.room.parseNode(props);
      var rebuild = false;

      if (n.pos) this.properties.position.fromArray(n.pos);
      if (n.scale) this.properties.scale.fromArray(n.scale);
      if (n.orientation) this.properties.orientation.copy(n.orientation);

      if (n.id && n.id != this.properties.render.model) {
        this.properties.render.model = n.id;
        rebuild = true;
      }
      var curcol = this.properties.col || [1,1,1];
      if (n.col && (n.col[0] != curcol[0] || n.col[1] != curcol[1] || n.col[2] != curcol[2])) {
        this.properties.col = n.col;
        rebuild = true;
      }
      if (rebuild) {
        //this.set('visible', true, true);
      }
      if (n.accel) this.properties.acceleration.fromArray(n.accel.split(' ').map(parseFloat));
      if (n.vel) this.objects.dynamics.setVelocity(this.properties.velocity.fromArray(n.vel.split(' ').map(parseFloat)));
      this.refresh();
    }
    this.summarizeXML = function() {
      //'<Object id=^{id}^ js_id=^{js_id}^ locked=^false^ pos=^{pos.x} {pos.y} {pos.z}^ vel=^{vel.x} {vel.y} {vel.z}^ accel=^{accel.x} {accel.y} {accel.z}^ xdir=^{xdir}^ ydir=^{ydir}^ zdir=^{zdir}^ scale=^{scale.x} {scale.y} {scale.z}^ col=^{color}^ lighting=^{lighting}^ visible=^{visible}^ />');

      var matrix = new THREE.Matrix4().makeRotationFromQuaternion(this.properties.orientation);
      var xdir = new THREE.Vector3(),
          ydir = new THREE.Vector3(),
          zdir = new THREE.Vector3();
      matrix.extractBasis(xdir, ydir, zdir);

      var objdef = {
        id: this.properties.render.model,
        js_id: this.properties.js_id,
        pos: this.properties.position,
        vel: this.properties.velocity,
        accel: this.properties.acceleration,
        scale: this.properties.scale,
        xdir: xdir.toArray().join(' '),
        ydir: ydir.toArray().join(' '),
        zdir: zdir.toArray().join(' '),
        col: this.properties.color,
        lighting: this.properties.lighting,
        visible: this.properties.visible,
      };

      var xml = elation.template.get('janusweb.edit.object', objdef);
      return xml;
    }
    this.getProxyObject = function() {
      if (!this._proxyobject) {
        this._proxyobject = new elation.proxy(this, {
          js_id:    ['property', 'properties.js_id'],
          pos:      ['property', 'position'],
          vel:      ['property', 'velocity'],
          accel:    ['property', 'acceleration'],
          mass:     ['property', 'mass'],
          scale:    ['property', 'scale'],
          col:      ['property', 'color'],
          fwd:      ['property', 'zdir'],
          xdir:     ['property', 'xdir'],
          ydir:     ['property', 'ydir'],
          zdir:     ['property', 'zdir'],
          sync:     ['property', 'sync'],
          children: ['property', 'jschildren'],

          oncollision: ['callback', 'collision'],
          appendChild: ['function', 'appendChild']
        });
      }
      return this._proxyobject;
    }
    this.start = function() {
    }
    this.stop = function() {
    }
    this.pushFrameUpdate = function(key, value) {
//console.log('frame update!', key, value);
      this.frameupdates[key] = value;
    }
    this.handleFrameUpdates = function() {
      var updatenames = Object.keys(this.frameupdates);
      if (updatenames.length > 0) {
        var updates = this.frameupdates;
        if ('fwd' in updates) {
          this.properties.zdir.copy(this.fwd);
          updates.zdir = this.properties.zdir;
        }
        var xdir = this.properties.xdir,
            ydir = this.properties.ydir,
            zdir = this.properties.zdir;

        if ( ('xdir' in updates) &&
            !('ydir' in updates) &&
            !('zdir' in updates)) {
          zdir.crossVectors(xdir, ydir);
          this.updateVectors(true);
        }
        if (!('xdir' in updates) &&
            !('ydir' in updates) &&
             ('zdir' in updates)) {
          xdir.crossVectors(ydir, zdir);
          this.updateVectors(true);
        }
        if (!('xdir' in updates) &&
             ('ydir' in updates) &&
             ('zdir' in updates)) {
          xdir.crossVectors(zdir, ydir);
          this.updateVectors(true);
        }
        if ( ('xdir' in updates) &&
            !('ydir' in updates) &&
             ('zdir' in updates)) {
          ydir.crossVectors(xdir, zdir).multiplyScalar(-1);
          this.updateVectors(true);
        }
        if ( ('xdir' in updates) &&
             ('ydir' in updates) &&
            !('zdir' in updates)) {
          zdir.crossVectors(xdir, ydir);
          this.updateVectors(true);
        }

        if (!('xdir' in updates) &&
            !('ydir' in updates) &&
            !('zdir' in updates)) {
          // None specified, so update the vectors from the orientation quaternion
          this.updateVectors(false);
        }
        this.frameupdates = {};
      } else {
        this.updateVectors(false);
      }
    }
    this.updateVectors = function(updateOrientation) {
      if (updateOrientation) {
        //var quat = this.room.getOrientation(this.properties.xdir.toArray().join(' '), this.properties.ydir.toArray().join(' '), this.properties.zdir.toArray().join(' '));
        //this.xdir.normalize();
        //this.ydir.normalize();
        //this.zdir.normalize();
        var mat4 = new THREE.Matrix4();
        mat4.makeBasis(this.xdir, this.ydir, this.properties.zdir);
/*
        mat4.set(
          this.xdir.x, this.xdir.y, this.xdir.z, 0,
          this.ydir.x, this.ydir.y, this.ydir.z, 0,
          this.zdir.x, this.zdir.y, this.zdir.z, 0,
          0, 0, 0, 1
        );
*/

        var quat = new THREE.Quaternion();
        var pos = new THREE.Vector3();
        var scale = new THREE.Vector3();
        quat.setFromRotationMatrix(mat4);
        //mat4.decompose(pos, this.orientation, scale);
        //this.orientation.normalize();
//console.log(mat4.elements);
        this.properties.orientation.copy(quat);
//console.log(this.xdir.toArray(), this.ydir.toArray(), this.zdir.toArray(), this.orientation.toArray());
//console.log(this.properties.orientation, this.properties.orientation.toArray());
      } else if (this.objects['3d']) {
        //this.objects['3d'].matrix.extractBasis(this.properties.xdir, this.properties.ydir, this.properties.zdir);
      }
    }
    this.appendChild = function(obj) {
      var proxyobj = obj
      if (elation.utils.isString(obj)) {
        proxyobj = this.room.jsobjects[obj];
      }
      if (proxyobj) {
        //var realobj = this.room.getObjectFromProxy(proxyobj);
        var realobj = proxyobj._target;
        if (realobj) {
          this.add(realobj);
          this.updateScriptChildren();
        }
      }
    }
    this.removeChild = function(obj) {
      var proxyobj = obj
      if (elation.utils.isString(obj)) {
        proxyobj = this.room.jsobjects[obj];
      }
      if (proxyobj) {
        //var realobj = this.room.getObjectFromProxy(proxyobj);
        var realobj = proxyobj._target;
        if (realobj) {
          this.remove(realobj);
          this.updateScriptChildren();
        }
      }
    }
    this.updateScriptChildren = function() {
      this.jschildren = [];
      var keys = Object.keys(this.children);
      for (var i = 0; i < keys.length; i++) {
        this.jschildren.push(this.children[keys[i]].getProxyObject());
      }
    }
    this.handleCollision = function(ev) {
      var obj1 = ev.data.bodies[0],
          obj2 = ev.data.bodies[1];
      //var proxy1 = obj1.getProxy(),
      //    proxy2 = obj2.getProxy();
      var other = (obj1.object == this ? obj2.object : obj1.object);
      if (other) {
        if (other.getProxyObject) {
          var proxy = other.getProxyObject();
          //console.log('I collided', proxy, this);
          elation.events.fire({type: 'collision', element: this, data: proxy});
        } else {
console.error('dunno what this is', other);
        }
      }
    }
  }, elation.engine.things.generic);
});
<|endoftext|>