<commit_before>QUnit.module('templateParser', {
  before: function() {
    this.parse = function() {
      this.result = this.parser.parse(this.source);
    };
  },
  beforeEach: function() {
    this.parser = smodules.templateParser();
    this.source = '';
    this.result = null;
  },
});

QUnit.test('normal block', function(assert) {
  this.source = '
foo {left}bar{right}
';
  this.parse();

  assert.strictEqual(this.result.length, 1);
  assert.strictEqual(this.result[0].type, 'normal');
  assert.strictEqual(this.result[0].expr, '
foo {bar}
');
});

QUnit.test('literal block', function(assert) {
  this.source ='
{literal}{foo} {left}bar{right} {left}/literal{right} function() {};{/literal}
',
  this.parse();

  assert.strictEqual(this.result.length, 3);
  assert.strictEqual(this.result[0].type, 'normal');
  assert.strictEqual(this.result[0].expr, '
');
  assert.strictEqual(this.result[1].type, 'literal');
  assert.strictEqual(this.result[1].expr, '{foo} {bar} {/literal} function() {};');
  assert.strictEqual(this.result[2].type, 'normal');
  assert.strictEqual(this.result[2].expr, '
');
});

QUnit.test('holder block - no filters', function(assert) {
  this.source = '{ $foo.bar }',
  this.parse();

  assert.strictEqual(this.result.length, 1);
  assert.strictEqual(this.result[0].type, 'holder');
  assert.strictEqual(this.result[0].keys.length, 2);
  assert.strictEqual(this.result[0].keys[0], 'foo');
  assert.strictEqual(this.result[0].keys[1], 'bar');
  assert.strictEqual(this.result[0].filters.length, 0);
});

QUnit.test('holder block - filters with no args', function(assert) {
  this.source  = '{ $foo | filter1 | filter2 }';
  this.parse();

  var filter1 = this.result[0].filters[0];
  var filter2 = this.result[0].filters[1];

  assert.strictEqual(filter1.name, 'filter1');
  assert.strictEqual(filter1.args.length, 0);
  assert.strictEqual(filter2.name, 'filter2');
  assert.strictEqual(filter2.args.length, 0);
});

QUnit.test('holder block - filter with args - null, true and false', function(assert) {
  this.source = '{ $foo | filter : null, true, false }';
  this.parse();

  var filter = this.result[0].filters[0];

  assert.strictEqual(filter.args[0], null);
  assert.strictEqual(filter.args[1], true);
  assert.strictEqual(filter.args[2], false);
});

QUnit.test('holder block - filter with args - string', function(assert) {
  this.source = '{ $foo | filter : "test", "{delimiter}", "it\'s string" }';
  this.parse();

  var filter = this.result[0].filters[0];

  assert.strictEqual(filter.args[0], 'test');
  assert.strictEqual(filter.args[1], '{delimiter}');
  assert.strictEqual(filter.args[2], 'it\'s string');
});

QUnit.test('holder block - filter with args - number', function(assert) {
  this.source = '{ $foo | filter : 0, 10, -99, 12.3, -0.123, 1e+1, 1e1, 10e-1 }',
  this.parse();

  var filter = this.result[0].filters[0];

  assert.strictEqual(filter.args[0], 0);
  assert.strictEqual(filter.args[1], 10);
  assert.strictEqual(filter.args[2], -99);
  assert.strictEqual(filter.args[3], 12.3);
  assert.strictEqual(filter.args[4], -0.123);
  assert.strictEqual(filter.args[5], 10);
  assert.strictEqual(filter.args[6], 10);
  assert.strictEqual(filter.args[7], 1);
});

QUnit.test('if block - if elseif else', function(assert) {
  var section;

  this.source =
    '{ if $value1 }' +
    '
value1
' +
    '{ elseif $value2 }' +
    '
value2
' +
    '{ elseif $value3 }' +
    '
value3
' +
    '{ else }' +
    '
value4
' +
    '{ /if }',
  this.parse();

  assert.strictEqual(this.result[0].type, 'if');
  assert.strictEqual(this.result[0].sections.length, 4);

  section = this.result[0].sections[0];
  assert.strictEqual(section.header.type, 'if');
  assert.strictEqual(section.blocks.length, 1);
  assert.strictEqual(section.blocks[0].type, 'normal');
  assert.strictEqual(section.blocks[0].expr, '
value1
');

  section = this.result[0].sections[1];
  assert.strictEqual(section.header.type, 'elseif');
  assert.strictEqual(section.blocks.length, 1);
  assert.strictEqual(section.blocks[0].type, 'normal');
  assert.strictEqual(section.blocks[0].expr, '
value2
');

  section = this.result[0].sections[2];
  assert.strictEqual(section.header.type, 'elseif');
  assert.strictEqual(section.blocks.length, 1);
  assert.strictEqual(section.blocks[0].type, 'normal');
  assert.strictEqual(section.blocks[0].expr, '
value3
');

  section = this.result[0].sections[3];
  assert.strictEqual(section.header.type, 'else');
  assert.strictEqual(section.blocks.length, 1);
  assert.strictEqual(section.blocks[0].type, 'normal');
  assert.strictEqual(section.blocks[0].expr, '
value4
');
});

QUnit.test('if block - condition - simple', function(assert) {
  this.source =
    '{ if $foo === "hoge" }' +
    '
hoge
' +
    '{ /if }';
  this.parse();

  var stack = this.result[0].sections[0].header.stack;

  assert.strictEqual(stack.length, 3);
  assert.strictEqual(stack[0].type, 'var');
  assert.strictEqual(stack[0].keys.join('.'), 'foo');
  assert.strictEqual(stack[1].type, 'value');
  assert.strictEqual(stack[1].value, 'hoge');
  assert.strictEqual(stack[2].type, 'comp');
  assert.strictEqual(stack[2].expr, '===');
});

QUnit.test('if block - condition - redundant round brackets', function(assert) {
  this.source =
    '{ if ( ( ( $foo === "hoge" ) ) ) }' +
    '
hoge
' +
    '{ /if }';
  this.parse();

  var stack = this.result[0].sections[0].header.stack;

  assert.strictEqual(stack.length, 3);
  assert.strictEqual(stack[0].type, 'var');
  assert.strictEqual(stack[0].keys.join('.'), 'foo');
  assert.strictEqual(stack[1].type, 'value');
  assert.strictEqual(stack[1].value, 'hoge');
  assert.strictEqual(stack[2].type, 'comp');
  assert.strictEqual(stack[2].expr, '===');
});

QUnit.test('if block - condition - complicated', function(assert) {
  this.source =
    '{ if $val1 gt 10 and $val2 gte -1 or $val3 lt 1.0 and $val4 lte -1.0 }' +
    '
ok
' +
    '{ /if }';
  this.parse();

  var stack  = this.result[0].sections[0].header.stack;

  assert.strictEqual(stack.length, 15);
  assert.strictEqual(stack[0].type, 'var');
  assert.strictEqual(stack[0].keys.join('.'), 'val1');
  assert.strictEqual(stack[1].type, 'value');
  assert.strictEqual(stack[1].value, 10);
  assert.strictEqual(stack[2].type, 'comp');
  assert.strictEqual(stack[2].expr, 'gt');
  assert.strictEqual(stack[3].type, 'var');
  assert.strictEqual(stack[3].keys.join('.'), 'val2');
  assert.strictEqual(stack[4].type, 'value');
  assert.strictEqual(stack[4].value, -1);
  assert.strictEqual(stack[5].type, 'comp');
  assert.strictEqual(stack[5].expr, 'gte');
  assert.strictEqual(stack[6].type, 'andor');
  assert.strictEqual(stack[6].expr, 'and');
  assert.strictEqual(stack[7].type, 'var');
  assert.strictEqual(stack[7].keys.join('.'), 'val3');
  assert.strictEqual(stack[8].type, 'value');
  assert.strictEqual(stack[8].value, 1.0);
  assert.strictEqual(stack[9].type, 'comp');
  assert.strictEqual(stack[9].expr, 'lt');
  assert.strictEqual(stack[10].type, 'var');
  assert.strictEqual(stack[10].keys.join('.'), 'val4');
  assert.strictEqual(stack[11].type, 'value');
  assert.strictEqual(stack[11].value, -1.0);
  assert.strictEqual(stack[12].type, 'comp');
  assert.strictEqual(stack[12].expr, 'lte');
  assert.strictEqual(stack[13].type, 'andor');
  assert.strictEqual(stack[13].expr, 'and');
  assert.strictEqual(stack[14].type, 'andor');
  assert.strictEqual(stack[14].expr, 'or');
});

QUnit.test('if block - condition - inversion of lval and rval', function(assert) {
  this.source =
    '{ if 10 !== $price }' +
    '
ok
' +
    '{ /if }';
  this.parse();

  var stack  = this.result[0].sections[0].header.stack;

  assert.strictEqual(stack.length, 3);
  assert.strictEqual(stack[0].type, 'value');
  assert.strictEqual(stack[0].value, 10);
  assert.strictEqual(stack[1].type, 'var');
  assert.strictEqual(stack[1].keys.join('.'), 'price');
  assert.strictEqual(stack[2].type, 'comp');
  assert.strictEqual(stack[2].expr, '!==');
});

QUnit.test('if block - condition - priority of and/or', function(assert) {
  this.source =
    '{ if ( $var1 or $var2 ) and $var3 }' +
    '
ok
' +
    '{ /if }';
  this.parse();

  var stack  = this.result[0].sections[0].header.stack;

  assert.strictEqual(stack.length, 5);
  assert.strictEqual(stack[0].type, 'var');
  assert.strictEqual(stack[0].keys.join('.'), 'var1');
  assert.strictEqual(stack[1].type, 'var');
  assert.strictEqual(stack[1].keys.join('.'), 'var2');
  assert.strictEqual(stack[2].type, 'andor');
  assert.strictEqual(stack[2].expr, 'or');
  assert.strictEqual(stack[3].type, 'var');
  assert.strictEqual(stack[3].keys.join('.'), 'var3');
  assert.strictEqual(stack[4].type, 'andor');
  assert.strictEqual(stack[4].expr, 'and');
});

QUnit.test('for block - only value part in dummy variable', function(assert) {
  this.source =
    '{ for $item in $items }' +
    '
{ $item | h }
' +
    '{ /for }';
  this.parse();

  var block  = this.result[0];

  assert.strictEqual(block.type, 'for');
  assert.strictEqual(block.header.array.join('.'), 'items');
  assert.strictEqual(typeof block.header.k, 'undefined');
  assert.strictEqual(block.header.v, 'item');
  assert.strictEqual(block.blocks.length, 3);
});

QUnit.test('for block - use index in dummy variable', function(assert) {
  this.source =
    '{ for $idx, $item in $items }' +
    '
{ $item | h }
' +
    '{ /for }';
  this.parse();

  var block  = this.result[0];

  assert.strictEqual(block.header.k, 'idx');
  assert.strictEqual(block.header.v, 'item');
});
<commit_msg>[QUnit] add tests for normal block<commit_after>QUnit.module('templateParser', {
  before: function() {
    this.parse = function() {
      this.result = this.parser.parse(this.source);
    };
  },
  beforeEach: function() {
    this.parser = smodules.templateParser();
    this.source = '';
    this.result = null;
  },
});

QUnit.test('normal block - plain text', function(assert) {
  this.source = 'Hello, world!';
  this.parse();

  assert.strictEqual(this.result.length, 1);
  assert.strictEqual(this.result[0].type, 'normal');
  assert.strictEqual(this.result[0].expr, 'Hello, world!');
});

QUnit.test('normal block - html tags', function(assert) {
  this.source =
    '
' +
    '
one
' +
    '
two
' +
    '
';
  this.parse();

  assert.strictEqual(this.result.length, 1);
  assert.strictEqual(this.result[0].type, 'normal');
  assert.strictEqual(this.result[0].expr, '

one

two

');
});

QUnit.test('normal block - literal tag', function(assert) {
  this.source = '
{left}Hello, world!{right}
';
  this.parse();

  assert.strictEqual(this.result.length, 1);
  assert.strictEqual(this.result[0].type, 'normal');
  assert.strictEqual(this.result[0].expr, '
{Hello, world!}
');
});

QUnit.test('literal block', function(assert) {
  this.source ='
{literal}{foo} {left}bar{right} {left}/literal{right} function() {};{/literal}
',
  this.parse();

  assert.strictEqual(this.result.length, 3);
  assert.strictEqual(this.result[0].type, 'normal');
  assert.strictEqual(this.result[0].expr, '
');
  assert.strictEqual(this.result[1].type, 'literal');
  assert.strictEqual(this.result[1].expr, '{foo} {bar} {/literal} function() {};');
  assert.strictEqual(this.result[2].type, 'normal');
  assert.strictEqual(this.result[2].expr, '
');
});

QUnit.test('holder block - no filters', function(assert) {
  this.source = '{ $foo.bar }',
  this.parse();

  assert.strictEqual(this.result.length, 1);
  assert.strictEqual(this.result[0].type, 'holder');
  assert.strictEqual(this.result[0].keys.length, 2);
  assert.strictEqual(this.result[0].keys[0], 'foo');
  assert.strictEqual(this.result[0].keys[1], 'bar');
  assert.strictEqual(this.result[0].filters.length, 0);
});

QUnit.test('holder block - filters with no args', function(assert) {
  this.source  = '{ $foo | filter1 | filter2 }';
  this.parse();

  var filter1 = this.result[0].filters[0];
  var filter2 = this.result[0].filters[1];

  assert.strictEqual(filter1.name, 'filter1');
  assert.strictEqual(filter1.args.length, 0);
  assert.strictEqual(filter2.name, 'filter2');
  assert.strictEqual(filter2.args.length, 0);
});

QUnit.test('holder block - filter with args - null, true and false', function(assert) {
  this.source = '{ $foo | filter : null, true, false }';
  this.parse();

  var filter = this.result[0].filters[0];

  assert.strictEqual(filter.args[0], null);
  assert.strictEqual(filter.args[1], true);
  assert.strictEqual(filter.args[2], false);
});

QUnit.test('holder block - filter with args - string', function(assert) {
  this.source = '{ $foo | filter : "test", "{delimiter}", "it\'s string" }';
  this.parse();

  var filter = this.result[0].filters[0];

  assert.strictEqual(filter.args[0], 'test');
  assert.strictEqual(filter.args[1], '{delimiter}');
  assert.strictEqual(filter.args[2], 'it\'s string');
});

QUnit.test('holder block - filter with args - number', function(assert) {
  this.source = '{ $foo | filter : 0, 10, -99, 12.3, -0.123, 1e+1, 1e1, 10e-1 }',
  this.parse();

  var filter = this.result[0].filters[0];

  assert.strictEqual(filter.args[0], 0);
  assert.strictEqual(filter.args[1], 10);
  assert.strictEqual(filter.args[2], -99);
  assert.strictEqual(filter.args[3], 12.3);
  assert.strictEqual(filter.args[4], -0.123);
  assert.strictEqual(filter.args[5], 10);
  assert.strictEqual(filter.args[6], 10);
  assert.strictEqual(filter.args[7], 1);
});

QUnit.test('if block - if elseif else', function(assert) {
  var section;

  this.source =
    '{ if $value1 }' +
    '
value1
' +
    '{ elseif $value2 }' +
    '
value2
' +
    '{ elseif $value3 }' +
    '
value3
' +
    '{ else }' +
    '
value4
' +
    '{ /if }',
  this.parse();

  assert.strictEqual(this.result[0].type, 'if');
  assert.strictEqual(this.result[0].sections.length, 4);

  section = this.result[0].sections[0];
  assert.strictEqual(section.header.type, 'if');
  assert.strictEqual(section.blocks.length, 1);
  assert.strictEqual(section.blocks[0].type, 'normal');
  assert.strictEqual(section.blocks[0].expr, '
value1
');

  section = this.result[0].sections[1];
  assert.strictEqual(section.header.type, 'elseif');
  assert.strictEqual(section.blocks.length, 1);
  assert.strictEqual(section.blocks[0].type, 'normal');
  assert.strictEqual(section.blocks[0].expr, '
value2
');

  section = this.result[0].sections[2];
  assert.strictEqual(section.header.type, 'elseif');
  assert.strictEqual(section.blocks.length, 1);
  assert.strictEqual(section.blocks[0].type, 'normal');
  assert.strictEqual(section.blocks[0].expr, '
value3
');

  section = this.result[0].sections[3];
  assert.strictEqual(section.header.type, 'else');
  assert.strictEqual(section.blocks.length, 1);
  assert.strictEqual(section.blocks[0].type, 'normal');
  assert.strictEqual(section.blocks[0].expr, '
value4
');
});

QUnit.test('if block - condition - simple', function(assert) {
  this.source =
    '{ if $foo === "hoge" }' +
    '
hoge
' +
    '{ /if }';
  this.parse();

  var stack = this.result[0].sections[0].header.stack;

  assert.strictEqual(stack.length, 3);
  assert.strictEqual(stack[0].type, 'var');
  assert.strictEqual(stack[0].keys.join('.'), 'foo');
  assert.strictEqual(stack[1].type, 'value');
  assert.strictEqual(stack[1].value, 'hoge');
  assert.strictEqual(stack[2].type, 'comp');
  assert.strictEqual(stack[2].expr, '===');
});

QUnit.test('if block - condition - redundant round brackets', function(assert) {
  this.source =
    '{ if ( ( ( $foo === "hoge" ) ) ) }' +
    '
hoge
' +
    '{ /if }';
  this.parse();

  var stack = this.result[0].sections[0].header.stack;

  assert.strictEqual(stack.length, 3);
  assert.strictEqual(stack[0].type, 'var');
  assert.strictEqual(stack[0].keys.join('.'), 'foo');
  assert.strictEqual(stack[1].type, 'value');
  assert.strictEqual(stack[1].value, 'hoge');
  assert.strictEqual(stack[2].type, 'comp');
  assert.strictEqual(stack[2].expr, '===');
});

QUnit.test('if block - condition - complicated', function(assert) {
  this.source =
    '{ if $val1 gt 10 and $val2 gte -1 or $val3 lt 1.0 and $val4 lte -1.0 }' +
    '
ok
' +
    '{ /if }';
  this.parse();

  var stack  = this.result[0].sections[0].header.stack;

  assert.strictEqual(stack.length, 15);
  assert.strictEqual(stack[0].type, 'var');
  assert.strictEqual(stack[0].keys.join('.'), 'val1');
  assert.strictEqual(stack[1].type, 'value');
  assert.strictEqual(stack[1].value, 10);
  assert.strictEqual(stack[2].type, 'comp');
  assert.strictEqual(stack[2].expr, 'gt');
  assert.strictEqual(stack[3].type, 'var');
  assert.strictEqual(stack[3].keys.join('.'), 'val2');
  assert.strictEqual(stack[4].type, 'value');
  assert.strictEqual(stack[4].value, -1);
  assert.strictEqual(stack[5].type, 'comp');
  assert.strictEqual(stack[5].expr, 'gte');
  assert.strictEqual(stack[6].type, 'andor');
  assert.strictEqual(stack[6].expr, 'and');
  assert.strictEqual(stack[7].type, 'var');
  assert.strictEqual(stack[7].keys.join('.'), 'val3');
  assert.strictEqual(stack[8].type, 'value');
  assert.strictEqual(stack[8].value, 1.0);
  assert.strictEqual(stack[9].type, 'comp');
  assert.strictEqual(stack[9].expr, 'lt');
  assert.strictEqual(stack[10].type, 'var');
  assert.strictEqual(stack[10].keys.join('.'), 'val4');
  assert.strictEqual(stack[11].type, 'value');
  assert.strictEqual(stack[11].value, -1.0);
  assert.strictEqual(stack[12].type, 'comp');
  assert.strictEqual(stack[12].expr, 'lte');
  assert.strictEqual(stack[13].type, 'andor');
  assert.strictEqual(stack[13].expr, 'and');
  assert.strictEqual(stack[14].type, 'andor');
  assert.strictEqual(stack[14].expr, 'or');
});

QUnit.test('if block - condition - inversion of lval and rval', function(assert) {
  this.source =
    '{ if 10 !== $price }' +
    '
ok
' +
    '{ /if }';
  this.parse();

  var stack  = this.result[0].sections[0].header.stack;

  assert.strictEqual(stack.length, 3);
  assert.strictEqual(stack[0].type, 'value');
  assert.strictEqual(stack[0].value, 10);
  assert.strictEqual(stack[1].type, 'var');
  assert.strictEqual(stack[1].keys.join('.'), 'price');
  assert.strictEqual(stack[2].type, 'comp');
  assert.strictEqual(stack[2].expr, '!==');
});

QUnit.test('if block - condition - priority of and/or', function(assert) {
  this.source =
    '{ if ( $var1 or $var2 ) and $var3 }' +
    '
ok
' +
    '{ /if }';
  this.parse();

  var stack  = this.result[0].sections[0].header.stack;

  assert.strictEqual(stack.length, 5);
  assert.strictEqual(stack[0].type, 'var');
  assert.strictEqual(stack[0].keys.join('.'), 'var1');
  assert.strictEqual(stack[1].type, 'var');
  assert.strictEqual(stack[1].keys.join('.'), 'var2');
  assert.strictEqual(stack[2].type, 'andor');
  assert.strictEqual(stack[2].expr, 'or');
  assert.strictEqual(stack[3].type, 'var');
  assert.strictEqual(stack[3].keys.join('.'), 'var3');
  assert.strictEqual(stack[4].type, 'andor');
  assert.strictEqual(stack[4].expr, 'and');
});

QUnit.test('for block - only value part in dummy variable', function(assert) {
  this.source =
    '{ for $item in $items }' +
    '
{ $item | h }
' +
    '{ /for }';
  this.parse();

  var block  = this.result[0];

  assert.strictEqual(block.type, 'for');
  assert.strictEqual(block.header.array.join('.'), 'items');
  assert.strictEqual(typeof block.header.k, 'undefined');
  assert.strictEqual(block.header.v, 'item');
  assert.strictEqual(block.blocks.length, 3);
});

QUnit.test('for block - use index in dummy variable', function(assert) {
  this.source =
    '{ for $idx, $item in $items }' +
    '
{ $item | h }
' +
    '{ /for }';
  this.parse();

  var block  = this.result[0];

  assert.strictEqual(block.header.k, 'idx');
  assert.strictEqual(block.header.v, 'item');
});
<|endoftext|>


<commit_before>import Ember from 'ember';
import DS from 'ember-data';
import moment from 'moment';

const NUM_VERSIONS = 5;
const { computed } = Ember;

export default Ember.Controller.extend({
    isDownloading: false,

    downloadsContext: Ember.computed('requestedVersion', 'model', 'crate', function() {
        return this.get('requestedVersion') ? this.get('model') : this.get('crate');
    }),
    extraDownloads: Ember.computed('downloads.meta.extra_downloads', function() {
        return this.get('downloads.meta.extra_downloads') || [];
    }),

    fetchingFollowing: true,
    following: false,
    currentVersion: computed.alias('model'),
    requestedVersion: null,
    keywords: computed.alias('crate.keywords'),

    sortedVersions: computed.readOnly('crate.versions'),

    smallSortedVersions: computed('sortedVersions', function() {
        return this.get('sortedVersions').slice(0, NUM_VERSIONS);
    }),

    hasMoreVersions: computed.gt('sortedVersions.length', NUM_VERSIONS),

    anyLinks: computed.or('crate.homepage',
                          'crate.wiki',
                          'crate.mailing_list',
                          'crate.documentation',
                          'crate.repository'),

    displayedAuthors: computed('currentVersion.authors.[]', function() {
        return DS.PromiseArray.create({
            promise: this.get('currentVersion.authors').then((authors) => {
                var ret = authors.slice();
                var others = authors.get('meta');
                for (var i = 0; i < others.names.length; i++) {
                    ret.push({ name: others.names[i] });
                }
                return ret;
            })
        });
    }),

    anyKeywords: computed.gt('keywords.length', 0),

    currentDependencies: computed('currentVersion.dependencies', function() {
        var deps = this.get('currentVersion.dependencies');

        if (deps === null) {
            return [];
        }

        return DS.PromiseArray.create({
            promise: deps.then((deps) => {
                var non_dev = deps.filter((dep) => dep.get('kind') !== 'dev');
                var map = {};
                var ret = [];

                non_dev.forEach((dep) => {
                    if (!(dep.get('crate_id') in map)) {
                        map[dep.get('crate_id')] = 1;
                        ret.push(dep);
                    }
                });

                return ret;
            })
        });
    }),

    currentDevDependencies: computed('currentVersion.dependencies', function() {
        var deps = this.get('currentVersion.dependencies');
        if (deps === null) {
            return [];
        }
        return DS.PromiseArray.create({
            promise: deps.then((deps) => {
                return deps.filterBy('kind', 'dev');
            }),
        });
    }),

    actions: {
        download(version) {
            this.set('isDownloading', true);

            version.getDownloadUrl().then(url => {
                this.incrementProperty('crate.downloads');
                this.incrementProperty('currentVersion.downloads');
                Ember.$('#download-frame').attr('src', url);
            }).finally(() => this.set('isDownloading', false));
        },

        toggleFollow() {
            this.set('fetchingFollowing', true);

            let crate = this.get('crate');
            let op = this.toggleProperty('following') ?
                crate.follow() : crate.unfollow();

            return op.finally(() => this.set('fetchingFollowing', false));
        },
    },

    downloadData: Ember.computed('downloads', 'extraDownloads', function() {
        let { downloads, extraDownloads: extra } = this.getProperties('downloads', 'extraDownloads');
        if (!downloads || !extra) {
            return;
        }

        var dates = {};
        var versions = [];
        for (var i = 0; i < 90; i++) {
            var now = moment().subtract(i, 'days');
            dates[now.format('MMM D')] = { date: now, cnt: {} };
        }

        downloads.forEach((d) => {
            var version_id = d.get('version.id');
            var key = moment(d.get('date')).utc().format('MMM D');
            if (dates[key]) {
                var prev = dates[key].cnt[version_id] || 0;
                dates[key].cnt[version_id] = prev + d.get('downloads');
            }
        });

        extra.forEach((d) => {
            var key = moment(d.date).utc().format('MMM D');
            if (dates[key]) {
                var prev = dates[key].cnt[null] || 0;
                dates[key].cnt[null] = prev + d.downloads;
            }
        });
        if (this.get('requestedVersion')) {
            versions.push(this.get('model').getProperties('id', 'num'));
        } else {
            this.get('smallSortedVersions').forEach(version => {
                versions.push(version.getProperties('id', 'num'));
            });
        }
        if (extra.length > 0) {
            versions.push({
                id: null,
                num: 'Other'
            });
        }

        var headers = ['Date'];
        versions.sort((b) => b.num).reverse();
        for (i = 0; i < versions.length; i++) {
            headers.push(versions[i].num);
        }
        var data = [headers];
        for (var date in dates) {
            var row = [dates[date].date.toDate()];
            for (i = 0; i < versions.length; i++) {
                row.push(dates[date].cnt[versions[i].id] || 0);
            }
            data.push(row);
        }

        return data;
    }),
});
<commit_msg>controllers/crate/version: Fix "downloadData" property dependencies<commit_after>import Ember from 'ember';
import DS from 'ember-data';
import moment from 'moment';

const NUM_VERSIONS = 5;
const { computed } = Ember;

export default Ember.Controller.extend({
    isDownloading: false,

    downloadsContext: Ember.computed('requestedVersion', 'model', 'crate', function() {
        return this.get('requestedVersion') ? this.get('model') : this.get('crate');
    }),
    extraDownloads: Ember.computed('downloads.meta.extra_downloads', function() {
        return this.get('downloads.meta.extra_downloads') || [];
    }),

    fetchingFollowing: true,
    following: false,
    currentVersion: computed.alias('model'),
    requestedVersion: null,
    keywords: computed.alias('crate.keywords'),

    sortedVersions: computed.readOnly('crate.versions'),

    smallSortedVersions: computed('sortedVersions', function() {
        return this.get('sortedVersions').slice(0, NUM_VERSIONS);
    }),

    hasMoreVersions: computed.gt('sortedVersions.length', NUM_VERSIONS),

    anyLinks: computed.or('crate.homepage',
                          'crate.wiki',
                          'crate.mailing_list',
                          'crate.documentation',
                          'crate.repository'),

    displayedAuthors: computed('currentVersion.authors.[]', function() {
        return DS.PromiseArray.create({
            promise: this.get('currentVersion.authors').then((authors) => {
                var ret = authors.slice();
                var others = authors.get('meta');
                for (var i = 0; i < others.names.length; i++) {
                    ret.push({ name: others.names[i] });
                }
                return ret;
            })
        });
    }),

    anyKeywords: computed.gt('keywords.length', 0),

    currentDependencies: computed('currentVersion.dependencies', function() {
        var deps = this.get('currentVersion.dependencies');

        if (deps === null) {
            return [];
        }

        return DS.PromiseArray.create({
            promise: deps.then((deps) => {
                var non_dev = deps.filter((dep) => dep.get('kind') !== 'dev');
                var map = {};
                var ret = [];

                non_dev.forEach((dep) => {
                    if (!(dep.get('crate_id') in map)) {
                        map[dep.get('crate_id')] = 1;
                        ret.push(dep);
                    }
                });

                return ret;
            })
        });
    }),

    currentDevDependencies: computed('currentVersion.dependencies', function() {
        var deps = this.get('currentVersion.dependencies');
        if (deps === null) {
            return [];
        }
        return DS.PromiseArray.create({
            promise: deps.then((deps) => {
                return deps.filterBy('kind', 'dev');
            }),
        });
    }),

    actions: {
        download(version) {
            this.set('isDownloading', true);

            version.getDownloadUrl().then(url => {
                this.incrementProperty('crate.downloads');
                this.incrementProperty('currentVersion.downloads');
                Ember.$('#download-frame').attr('src', url);
            }).finally(() => this.set('isDownloading', false));
        },

        toggleFollow() {
            this.set('fetchingFollowing', true);

            let crate = this.get('crate');
            let op = this.toggleProperty('following') ?
                crate.follow() : crate.unfollow();

            return op.finally(() => this.set('fetchingFollowing', false));
        },
    },

    downloadData: Ember.computed('downloads', 'extraDownloads', 'requestedVersion', function() {
        let { downloads, extraDownloads: extra } = this.getProperties('downloads', 'extraDownloads');
        if (!downloads || !extra) {
            return;
        }

        var dates = {};
        var versions = [];
        for (var i = 0; i < 90; i++) {
            var now = moment().subtract(i, 'days');
            dates[now.format('MMM D')] = { date: now, cnt: {} };
        }

        downloads.forEach((d) => {
            var version_id = d.get('version.id');
            var key = moment(d.get('date')).utc().format('MMM D');
            if (dates[key]) {
                var prev = dates[key].cnt[version_id] || 0;
                dates[key].cnt[version_id] = prev + d.get('downloads');
            }
        });

        extra.forEach((d) => {
            var key = moment(d.date).utc().format('MMM D');
            if (dates[key]) {
                var prev = dates[key].cnt[null] || 0;
                dates[key].cnt[null] = prev + d.downloads;
            }
        });
        if (this.get('requestedVersion')) {
            versions.push(this.get('model').getProperties('id', 'num'));
        } else {
            this.get('smallSortedVersions').forEach(version => {
                versions.push(version.getProperties('id', 'num'));
            });
        }
        if (extra.length > 0) {
            versions.push({
                id: null,
                num: 'Other'
            });
        }

        var headers = ['Date'];
        versions.sort((b) => b.num).reverse();
        for (i = 0; i < versions.length; i++) {
            headers.push(versions[i].num);
        }
        var data = [headers];
        for (var date in dates) {
            var row = [dates[date].date.toDate()];
            for (i = 0; i < versions.length; i++) {
                row.push(dates[date].cnt[versions[i].id] || 0);
            }
            data.push(row);
        }

        return data;
    }),
});
<|endoftext|>


<commit_before>import Ember from 'ember';
import DS from 'ember-data';
import moment from 'moment';

const NUM_VERSIONS = 5;
const { computed } = Ember;

export default Ember.Controller.extend({
    isDownloading: false,

    downloadsContext: computed('requestedVersion', 'model', 'crate', function() {
        return this.get('requestedVersion') ? this.get('model') : this.get('crate');
    }),
    downloads: computed.alias('downloadsContext.version_downloads'),
    extraDownloads: computed('downloads.content.meta.extra_downloads', function() {
        return this.get('downloads.content.meta.extra_downloads') || [];
    }),

    fetchingFollowing: true,
    following: false,
    currentVersion: computed.alias('model'),
    requestedVersion: null,
    keywords: computed.alias('crate.keywords'),

    sortedVersions: computed.readOnly('crate.versions'),

    smallSortedVersions: computed('sortedVersions', function() {
        return this.get('sortedVersions').slice(0, NUM_VERSIONS);
    }),

    hasMoreVersions: computed.gt('sortedVersions.length', NUM_VERSIONS),

    anyLinks: computed.or('crate.homepage',
                          'crate.wiki',
                          'crate.mailing_list',
                          'crate.documentation',
                          'crate.repository'),

    displayedAuthors: computed('currentVersion.authors.[]', function() {
        return DS.PromiseArray.create({
            promise: this.get('currentVersion.authors').then((authors) => {
                var ret = authors.slice();
                var others = authors.get('meta');
                for (var i = 0; i < others.names.length; i++) {
                    ret.push({ name: others.names[i] });
                }
                return ret;
            })
        });
    }),

    anyKeywords: computed.gt('keywords.length', 0),

    currentDependencies: computed('currentVersion.dependencies', function() {
        var deps = this.get('currentVersion.dependencies');

        if (deps === null) {
            return [];
        }

        return DS.PromiseArray.create({
            promise: deps.then((deps) => {
                var non_dev = deps.filter((dep) => dep.get('kind') !== 'dev');
                var map = {};
                var ret = [];

                non_dev.forEach((dep) => {
                    if (!(dep.get('crate_id') in map)) {
                        map[dep.get('crate_id')] = 1;
                        ret.push(dep);
                    }
                });

                return ret;
            })
        });
    }),

    currentDevDependencies: computed('currentVersion.dependencies', function() {
        var deps = this.get('currentVersion.dependencies');
        if (deps === null) {
            return [];
        }
        return DS.PromiseArray.create({
            promise: deps.then((deps) => {
                return deps.filterBy('kind', 'dev');
            }),
        });
    }),

    actions: {
        download(version) {
            this.set('isDownloading', true);

            version.getDownloadUrl().then(url => {
                this.incrementProperty('crate.downloads');
                this.incrementProperty('currentVersion.downloads');
                Ember.$('#download-frame').attr('src', url);
            }).finally(() => this.set('isDownloading', false));
        },

        toggleFollow() {
            this.set('fetchingFollowing', true);

            let crate = this.get('crate');
            let op = this.toggleProperty('following') ?
                crate.follow() : crate.unfollow();

            return op.finally(() => this.set('fetchingFollowing', false));
        },
    },

    downloadData: computed('downloads', 'extraDownloads', 'requestedVersion', function() {
        let { downloads, extraDownloads: extra } = this.getProperties('downloads', 'extraDownloads');
        if (!downloads || !extra) {
            return;
        }

        var dates = {};
        var versions = [];
        for (var i = 0; i < 90; i++) {
            var now = moment().subtract(i, 'days');
            dates[now.format('MMM D')] = { date: now, cnt: {} };
        }

        downloads.forEach((d) => {
            var version_id = d.get('version.id');
            var key = moment(d.get('date')).utc().format('MMM D');
            if (dates[key]) {
                var prev = dates[key].cnt[version_id] || 0;
                dates[key].cnt[version_id] = prev + d.get('downloads');
            }
        });

        extra.forEach((d) => {
            var key = moment(d.date).utc().format('MMM D');
            if (dates[key]) {
                var prev = dates[key].cnt[null] || 0;
                dates[key].cnt[null] = prev + d.downloads;
            }
        });
        if (this.get('requestedVersion')) {
            versions.push(this.get('model').getProperties('id', 'num'));
        } else {
            this.get('smallSortedVersions').forEach(version => {
                versions.push(version.getProperties('id', 'num'));
            });
        }
        if (extra.length > 0) {
            versions.push({
                id: null,
                num: 'Other'
            });
        }

        var headers = ['Date'];
        versions.sort((b) => b.num).reverse();
        for (i = 0; i < versions.length; i++) {
            headers.push(versions[i].num);
        }
        var data = [headers];
        for (var date in dates) {
            var row = [dates[date].date.toDate()];
            for (i = 0; i < versions.length; i++) {
                row.push(dates[date].cnt[versions[i].id] || 0);
            }
            data.push(row);
        }

        return data;
    }),
});
<commit_msg>controllers/crate/version: Simplify "extraDownloads" property<commit_after>import Ember from 'ember';
import DS from 'ember-data';
import moment from 'moment';

const NUM_VERSIONS = 5;
const { computed } = Ember;

export default Ember.Controller.extend({
    isDownloading: false,

    downloadsContext: computed('requestedVersion', 'model', 'crate', function() {
        return this.get('requestedVersion') ? this.get('model') : this.get('crate');
    }),
    downloads: computed.alias('downloadsContext.version_downloads'),
    extraDownloads: computed.alias('downloads.content.meta.extra_downloads'),

    fetchingFollowing: true,
    following: false,
    currentVersion: computed.alias('model'),
    requestedVersion: null,
    keywords: computed.alias('crate.keywords'),

    sortedVersions: computed.readOnly('crate.versions'),

    smallSortedVersions: computed('sortedVersions', function() {
        return this.get('sortedVersions').slice(0, NUM_VERSIONS);
    }),

    hasMoreVersions: computed.gt('sortedVersions.length', NUM_VERSIONS),

    anyLinks: computed.or('crate.homepage',
                          'crate.wiki',
                          'crate.mailing_list',
                          'crate.documentation',
                          'crate.repository'),

    displayedAuthors: computed('currentVersion.authors.[]', function() {
        return DS.PromiseArray.create({
            promise: this.get('currentVersion.authors').then((authors) => {
                var ret = authors.slice();
                var others = authors.get('meta');
                for (var i = 0; i < others.names.length; i++) {
                    ret.push({ name: others.names[i] });
                }
                return ret;
            })
        });
    }),

    anyKeywords: computed.gt('keywords.length', 0),

    currentDependencies: computed('currentVersion.dependencies', function() {
        var deps = this.get('currentVersion.dependencies');

        if (deps === null) {
            return [];
        }

        return DS.PromiseArray.create({
            promise: deps.then((deps) => {
                var non_dev = deps.filter((dep) => dep.get('kind') !== 'dev');
                var map = {};
                var ret = [];

                non_dev.forEach((dep) => {
                    if (!(dep.get('crate_id') in map)) {
                        map[dep.get('crate_id')] = 1;
                        ret.push(dep);
                    }
                });

                return ret;
            })
        });
    }),

    currentDevDependencies: computed('currentVersion.dependencies', function() {
        var deps = this.get('currentVersion.dependencies');
        if (deps === null) {
            return [];
        }
        return DS.PromiseArray.create({
            promise: deps.then((deps) => {
                return deps.filterBy('kind', 'dev');
            }),
        });
    }),

    actions: {
        download(version) {
            this.set('isDownloading', true);

            version.getDownloadUrl().then(url => {
                this.incrementProperty('crate.downloads');
                this.incrementProperty('currentVersion.downloads');
                Ember.$('#download-frame').attr('src', url);
            }).finally(() => this.set('isDownloading', false));
        },

        toggleFollow() {
            this.set('fetchingFollowing', true);

            let crate = this.get('crate');
            let op = this.toggleProperty('following') ?
                crate.follow() : crate.unfollow();

            return op.finally(() => this.set('fetchingFollowing', false));
        },
    },

    downloadData: computed('downloads', 'extraDownloads', 'requestedVersion', function() {
        let downloads = this.get('downloads');
        if (!downloads) {
            return;
        }

        let extra = this.get('extraDownloads') || [];

        var dates = {};
        var versions = [];
        for (var i = 0; i < 90; i++) {
            var now = moment().subtract(i, 'days');
            dates[now.format('MMM D')] = { date: now, cnt: {} };
        }

        downloads.forEach((d) => {
            var version_id = d.get('version.id');
            var key = moment(d.get('date')).utc().format('MMM D');
            if (dates[key]) {
                var prev = dates[key].cnt[version_id] || 0;
                dates[key].cnt[version_id] = prev + d.get('downloads');
            }
        });

        extra.forEach((d) => {
            var key = moment(d.date).utc().format('MMM D');
            if (dates[key]) {
                var prev = dates[key].cnt[null] || 0;
                dates[key].cnt[null] = prev + d.downloads;
            }
        });
        if (this.get('requestedVersion')) {
            versions.push(this.get('model').getProperties('id', 'num'));
        } else {
            this.get('smallSortedVersions').forEach(version => {
                versions.push(version.getProperties('id', 'num'));
            });
        }
        if (extra.length > 0) {
            versions.push({
                id: null,
                num: 'Other'
            });
        }

        var headers = ['Date'];
        versions.sort((b) => b.num).reverse();
        for (i = 0; i < versions.length; i++) {
            headers.push(versions[i].num);
        }
        var data = [headers];
        for (var date in dates) {
            var row = [dates[date].date.toDate()];
            for (i = 0; i < versions.length; i++) {
                row.push(dates[date].cnt[versions[i].id] || 0);
            }
            data.push(row);
        }

        return data;
    }),
});
<|endoftext|>


<commit_before>describe('setCorrectingInterval', function() {
  var noop = function() { };

  it('should be defined', function() {
    expect(setCorrectingInterval).to.be.ok;
  });

  it('should return a unique id', function() {
  	var iter = 5,
      defined = {};

    for (var i = 0; i < iter; i++) {
      var intervalId = setCorrectingInterval(noop, 1000);
      defined[intervalId] = true;
      clearCorrectingInterval(intervalId);
    }

    expect(Object.keys(defined).length).to.equal(iter);
  });

  it('should execute callback after defined delay', function(done) {
    var delay = 500,
      now = Date.now(),
      intervalId;

    intervalId = setCorrectingInterval(function() {
      expect(Math.abs(Date.now() - now - delay)).to.be.within(0, 25);
      clearCorrectingInterval(intervalId);
      done();
    }, delay);
  });

  it('should continuously execute callback after defined delay', function(done) {
    var delay = 100,
      iter = 0,
      intervalId;

    intervalId = setCorrectingInterval(function() {
      if (++iter === 2) {
        clearCorrectingInterval(intervalId);
        done();
      }
    }, delay);
  });

  it('should be relatively accurate', function(done) {
    var delay = target = 200,
      previousDelay = undefined,
      now = Date.now();

    setCorrectingInterval(function() {
      // Expect at least one interval to be more accurate than its
      //  previous before timeout occurs

      var thisDelay = Date.now() - now - target;
      if (previousDelay !== 'undefined' && thisDelay < previousDelay) done();
      previousDelay = thisDelay;
      target += delay;
    }, delay)
  });
});

describe('clearCorrectingInterval', function() {
  it('should be defined', function() {
    expect(clearCorrectingInterval).to.be.ok;
  });

  it('should clear a running interval', function(done) {
    var iter = 0,
      intervalId;

    intervalId = setCorrectingInterval(function() {
      if (++iter === 2) throw new Error('expected to clear interval');
      clearCorrectingInterval(intervalId);
    }, 50);

    setTimeout(function() {
      done();
    }, 200);
  });

  it('should gracefully handle bad input', function() {
    clearCorrectingInterval(null);
    clearCorrectingInterval(0);
    clearCorrectingInterval('');
  });
});
<commit_msg>Add test to check for graceful handling of bad input to setCorrectingInterval<commit_after>describe('setCorrectingInterval', function() {
  var noop = function() { };

  it('should be defined', function() {
    expect(setCorrectingInterval).to.be.ok;
  });

  it('should return a unique id', function() {
  	var iter = 5,
      defined = {};

    for (var i = 0; i < iter; i++) {
      var intervalId = setCorrectingInterval(noop, 1000);
      defined[intervalId] = true;
      clearCorrectingInterval(intervalId);
    }

    expect(Object.keys(defined).length).to.equal(iter);
  });

  it('should execute callback after defined delay', function(done) {
    var delay = 500,
      now = Date.now(),
      intervalId;

    intervalId = setCorrectingInterval(function() {
      expect(Math.abs(Date.now() - now - delay)).to.be.within(0, 25);
      clearCorrectingInterval(intervalId);
      done();
    }, delay);
  });

  it('should continuously execute callback after defined delay', function(done) {
    var delay = 100,
      iter = 0,
      intervalId;

    intervalId = setCorrectingInterval(function() {
      if (++iter === 2) {
        clearCorrectingInterval(intervalId);
        done();
      }
    }, delay);
  });

  it('should be relatively accurate', function(done) {
    var delay = target = 200,
      previousDelay = undefined,
      now = Date.now();

    setCorrectingInterval(function() {
      // Expect at least one interval to be more accurate than its
      //  previous before timeout occurs

      var thisDelay = Date.now() - now - target;
      if (previousDelay !== 'undefined' && thisDelay < previousDelay) done();
      previousDelay = thisDelay;
      target += delay;
    }, delay)
  });

  it('should gracefully handle bad input', function() {
    var intervalId;
    intervalId = setCorrectingInterval(noop);
    clearCorrectingInterval(intervalId);
    intervalId = setCorrectingInterval(noop, '');
    clearCorrectingInterval(intervalId);
    intervalId = setCorrectingInterval(noop, -100);
    clearCorrectingInterval(intervalId);
  });
});

describe('clearCorrectingInterval', function() {
  it('should be defined', function() {
    expect(clearCorrectingInterval).to.be.ok;
  });

  it('should clear a running interval', function(done) {
    var iter = 0,
      intervalId;

    intervalId = setCorrectingInterval(function() {
      if (++iter === 2) throw new Error('expected to clear interval');
      clearCorrectingInterval(intervalId);
    }, 50);

    setTimeout(function() {
      done();
    }, 200);
  });

  it('should gracefully handle bad input', function() {
    clearCorrectingInterval(null);
    clearCorrectingInterval(0);
    clearCorrectingInterval('');
  });
});
<|endoftext|>


<commit_before>import {expect} from 'src/external/chai.js';
import {MockEvent, createHTML, testWorld, loadComponent} from './templates-fixture.js';
import {pt,rect} from 'src/client/graphics.js';
import components from 'src/client/morphic/component-loader.js'

describe("LivelyScriptTest",  function() {

  var that;
  before("load", async function() {
    this.timeout(35000);
    var templateName = "lively-script";
    await loadComponent(templateName)
  });

  it("should load", async function() {

  });

  it("should exec script", async function() {
    self.thisScriptWasHere = undefined
    var root =

    testWorld().appendChild(root)
    var source = `<lively-script></lively-script>`
    root.innerHTML = source
    await components.loadUnresolved(root);
    await lively.sleep(10); // ok, there is aysnc behavior here... give it a chance to run
    expect(self.thisScriptWasHere, "script not run").not.be.undefined
  });

  it("should exec two scripts after each other", async function() {
    self.thisScriptWasHere = undefined
    self.testScriptExecOrder = []
    var root =

    testWorld().appendChild(root)
    var source = `<lively-script id="a">
        self.thisScriptWasHere = this;
        self.testScriptExecOrder.push(this.id)
      </lively-script>
      <lively-script id="b">
        self.secondScriptWasHere = this
        self.testScriptExecOrder.push(this.id)
      </lively-script>`
    root.innerHTML = source
    await components.loadUnresolved(root);
    await lively.sleep(50); // ok, there is aysnc behavior here... give it a chance to run
    expect(self.thisScriptWasHere, "script not run").not.be.undefined
    expect(self.secondScriptWasHere, "second script not run").not.be.undefined
    expect(self.secondScriptWasHere, "first is second?").not.equal(self.thisScriptWasHere)
    expect(self.testScriptExecOrder, "script exec order").deep.equal(["a", "b"])
  });

  it("should exec in order", async function() {
    this.timeout(35000);
    self.thisScriptWasHere = undefined
    self.testScriptExecOrder = []
    var root =

    testWorld().appendChild(root)
    var source = `
      <lively-script id="a">
        self.testScriptExecOrder.push(this.id)
      </lively-script>
      <lively-script id="b">
        self.testScriptExecOrder.push(this.id)
      </lively-script>
      <lively-script id="c">
        self.testScriptExecOrder.push(this.id)
      </lively-script>
      <lively-script id="d">
        self.testScriptExecOrder.push(this.id)
      </lively-script>
      <lively-script id="e">
        self.testScriptExecOrder.push(this.id)
      </lively-script>`
    root.innerHTML = source
    await components.loadUnresolved(root);
    await lively.sleep(150); // ok, there is aysnc behavior here... give it a chance to run
    expect(self.testScriptExecOrder, "script exec order" + JSON.stringify(self.testScriptExecOrder)).deep.equal(
      ["a", "b", "c", "d", "e"])
  });

  after("cleanup", function() {
    testWorld().innerHTML = "";
  });

});
<commit_msg>fix lively_script test<commit_after>import {expect} from 'src/external/chai.js';
import {MockEvent, createHTML, testWorld, loadComponent} from './templates-fixture.js';
import {pt,rect} from 'src/client/graphics.js';
import components from 'src/client/morphic/component-loader.js'

describe("LivelyScriptTest",  function() {

  var that;
  before("load", async function() {
    this.timeout(35000);
    var templateName = "lively-script";
    await loadComponent(templateName)
  });

  it("should load", async function() {

  });

  it("should exec script", async function() {
    self.thisScriptWasHere = undefined
    var root =

    var source = `<lively-script></lively-script>`
    testWorld().appendChild(root)
    root.innerHTML = source
    await components.loadUnresolved(root);
    await lively.sleep(10); // ok, there is aysnc behavior here... give it a chance to run
    expect(self.thisScriptWasHere, "script not run").not.be.undefined
  });

  it("should exec two scripts after each other", async function() {
    self.thisScriptWasHere = undefined
    self.testScriptExecOrder = []
    var root =

    testWorld().appendChild(root)
    var source = `<lively-script id="a">
        self.thisScriptWasHere = this;
        self.testScriptExecOrder.push(this.id)
      </lively-script>
      <lively-script id="b">
        self.secondScriptWasHere = this
        self.testScriptExecOrder.push(this.id)
      </lively-script>`
    root.innerHTML = source
    await components.loadUnresolved(root);
    await lively.sleep(50); // ok, there is aysnc behavior here... give it a chance to run
    expect(self.thisScriptWasHere, "script not run").not.be.undefined
    expect(self.secondScriptWasHere, "second script not run").not.be.undefined
    expect(self.secondScriptWasHere, "first is second?").not.equal(self.thisScriptWasHere)
    expect(self.testScriptExecOrder, "script exec order").deep.equal(["a", "b"])
  });

  it("should exec in order", async function() {
    this.timeout(35000);
    self.thisScriptWasHere = undefined
    self.testScriptExecOrder = []
    var root =

    testWorld().appendChild(root)
    var source = `
      <lively-script id="a">
        self.testScriptExecOrder.push(this.id)
      </lively-script>
      <lively-script id="b">
        self.testScriptExecOrder.push(this.id)
      </lively-script>
      <lively-script id="c">
        self.testScriptExecOrder.push(this.id)
      </lively-script>
      <lively-script id="d">
        self.testScriptExecOrder.push(this.id)
      </lively-script>
      <lively-script id="e">
        self.testScriptExecOrder.push(this.id)
      </lively-script>`
    root.innerHTML = source
    await components.loadUnresolved(root);
    await lively.sleep(150); // ok, there is aysnc behavior here... give it a chance to run
    expect(self.testScriptExecOrder, "script exec order" + JSON.stringify(self.testScriptExecOrder)).deep.equal(
      ["a", "b", "c", "d", "e"])
  });

  after("cleanup", function() {
    testWorld().innerHTML = "";
  });

});
<|endoftext|>


<commit_before>'use strict';

const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
const path = require('path');

const config = require('../.jsdoc.json');

async function replacer() {

  await require('./preprocess');

  let data = await fs.readFileAsync(path.join(config.opts.destination, 'replaced/itbl.js'), 'utf8');

  let replaced = data
    .replace('<!-- replace for docdown -->', '@name itbl._Wrapper') // almighty fudge as docdown can't do classes
  ;

  return await fs.writeFileAsync(path.join(config.opts.destination, 'replaced/itbl.js'), replaced, 'utf8');
}

module.exports = replacer()
  .catch(error => {
    console.error('Error occurred:', error);
  })
;
<commit_msg>fudge for line endings<commit_after>'use strict';

const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
const path = require('path');

const config = require('../.jsdoc.json');

async function replacer() {

  await require('./preprocess');

  let data = await fs.readFileAsync(path.join(config.opts.destination, 'replaced/itbl.js'), 'utf8');

  let replaced = data
    .replace('<!-- replace for docdown -->', '@name itbl._Wrapper') // almighty fudge as docdown can't do classes
    .replace(/\r\n/g, '\n');
  ;

  return await fs.writeFileAsync(path.join(config.opts.destination, 'replaced/itbl.js'), replaced, 'utf8');
}

module.exports = replacer()
  .catch(error => {
    console.error('Error occurred:', error);
  })
;
<|endoftext|>


<commit_before>angular.module("tjsModelViewer", [])
.directive(
    "tjsModelViewer",
    [function () {
        return {
            restrict: "E",
            scope: {
                assimpUrl: "=assimpUrl"
            },
            link: function (scope, elem, attr) {
                var container,
                    container2,
                    camera,
                    scene,
                    renderer,
                    axes,
                    camera2,
                    scene2,
                    renderer2,
                    axes2,
                    cube,
                    CANVAS_WIDTH = 200,
                    CANVAS_HEIGHT = 200,
                    CAM_DISTANCE = 300;

                init();
                animate();

                // main canvas
                // -----------------------------------------------

                var onProgress = function ( xhr ) {
                    if ( xhr.lengthComputable ) {
                        var percentComplete = xhr.loaded / xhr.total * 100;
                        console.log( Math.round(percentComplete, 2) + '% downloaded' );
                    }
                };

                var onError = function ( xhr ) {
                };

                function init() {

                    // dom

                    // renderer
                    renderer = new THREE.WebGLRenderer();
                    renderer.setClearColor( 0xffffff, 1 );
                    renderer.setSize( window.innerWidth, window.innerHeight );
                    //container.appendChild( renderer.domElement );
                    elem[0].appendChild(renderer.domElement);

                    // scene
                    scene = new THREE.Scene();

                    // lighting

                    var ambient = new THREE.AmbientLight( 0x101030 );
                    scene.add( ambient );

                    var directionalLight = new THREE.DirectionalLight( 0xffeedd );
                    directionalLight.position.set( 0, 0, 1 );
                    scene.add( directionalLight );

                    // camera
                    camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 );
                    camera.position.y = 150;
                    camera.position.z = 500;

                    // controls
                    controls = new THREE.TrackballControls( camera, renderer.domElement );

                    // cube
                    cube = new THREE.Mesh(
                            new THREE.BoxGeometry( 200, 200, 200, 1, 1, 1 ),
                            new THREE.MeshBasicMaterial( { color : 0xff0000, wireframe: true }
                                ) );
                    scene.add( cube );

                    // Texture
                    //
                    var texture = new THREE.Texture();
                    var textureLoader = new THREE.ImageLoader( manager );
                    textureLoader.load( 'textures/UV_Grid_Sm.jpg', function ( image ) {
                            texture.image = image;
                            texture.needsUpdate = true;
                            } );

                    var manager = new THREE.LoadingManager();
                    manager.onProgress = function ( item, loaded, total ) {
                        console.log( item, loaded, total );
                    };

                    // OBJ
                    var objLoader = new THREE.OBJLoader( manager );

                    //objLoader.load( 'models/male02.obj', function ( object ) {
                    objLoader.load( 'models/Male_full_body.obj', function ( object ) {
                    //objLoader.load( 'models/man.obj', function ( object ) {
                        object.traverse( function ( child ) {
                            if ( child instanceof THREE.Mesh ) {
                                child.material.map = texture;
                            }
                        } );

                        // object.position.y = - 80;
                        scene.add( object );
                    }, onProgress, onError );

                    // axes
                    axes = new THREE.AxisHelper( 100 );
                    scene.add( axes );

                    // inset canvas
                    // -----------------------------------------------

                    //// dom
                    //container2 = document.getElementById('inset');

                    //// renderer
                    //renderer2 = new THREE.WebGLRenderer();
                    //renderer2.setClearColor( 0xf0f0f0, 1 );
                    //renderer2.setSize( CANVAS_WIDTH, CANVAS_HEIGHT );
                    //container2.appendChild( renderer2.domElement );

                    //// scene
                    //scene2 = new THREE.Scene();

                    //// camera
                    //camera2 = new THREE.PerspectiveCamera( 50, CANVAS_WIDTH / CANVAS_HEIGHT, 1, 1000 );
                    //camera2.up = camera.up; // important!

                    //// axes
                    //axes2 = new THREE.AxisHelper( 100 );
                    //scene2.add( axes2 );
                }

                // animate
                // -----------------------------------------------

                function render() {

                    renderer.render( scene, camera );
                    //renderer2.render( scene2, camera2 );

                }

                function animate() {

                    requestAnimationFrame( animate );

                    controls.update();

                    //camera2.position.copy( camera.position );
                    //camera2.position.sub( controls.target ); // added by @libe
                    //camera2.position.setLength( CAM_DISTANCE );

                    //camera2.lookAt( scene2.position );
                    render();

                }
            }
        }
    }]);

<commit_msg>corrected pathing in code.<commit_after>angular.module("tjsModelViewer", [])
.directive(
    "tjsModelViewer",
    [function () {
        return {
            restrict: "E",
            scope: {
                assimpUrl: "=assimpUrl"
            },
            link: function (scope, elem, attr) {
                var container,
                    container2,
                    camera,
                    scene,
                    renderer,
                    axes,
                    camera2,
                    scene2,
                    renderer2,
                    axes2,
                    cube,
                    CANVAS_WIDTH = 200,
                    CANVAS_HEIGHT = 200,
                    CAM_DISTANCE = 300;

                init();
                animate();

                // main canvas
                // -----------------------------------------------

                var onProgress = function ( xhr ) {
                    if ( xhr.lengthComputable ) {
                        var percentComplete = xhr.loaded / xhr.total * 100;
                        console.log( Math.round(percentComplete, 2) + '% downloaded' );
                    }
                };

                var onError = function ( xhr ) {
                };

                function init() {

                    // dom

                    // renderer
                    renderer = new THREE.WebGLRenderer();
                    renderer.setClearColor( 0xffffff, 1 );
                    renderer.setSize( window.innerWidth, window.innerHeight );
                    //container.appendChild( renderer.domElement );
                    elem[0].appendChild(renderer.domElement);

                    // scene
                    scene = new THREE.Scene();

                    // lighting

                    var ambient = new THREE.AmbientLight( 0x101030 );
                    scene.add( ambient );

                    var directionalLight = new THREE.DirectionalLight( 0xffeedd );
                    directionalLight.position.set( 0, 0, 1 );
                    scene.add( directionalLight );

                    // camera
                    camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 );
                    camera.position.y = 150;
                    camera.position.z = 500;

                    // controls
                    controls = new THREE.TrackballControls( camera, renderer.domElement );

                    // cube
                    cube = new THREE.Mesh(
                            new THREE.BoxGeometry( 200, 200, 200, 1, 1, 1 ),
                            new THREE.MeshBasicMaterial( { color : 0xff0000, wireframe: true }
                                ) );
                    scene.add( cube );

                    // Texture
                    //
                    var texture = new THREE.Texture();
                    var textureLoader = new THREE.ImageLoader( manager );
                    textureLoader.load( 'textures/UV_Grid_Sm.jpg', function ( image ) {
                            texture.image = image;
                            texture.needsUpdate = true;
                            } );

                    var manager = new THREE.LoadingManager();
                    manager.onProgress = function ( item, loaded, total ) {
                        console.log( item, loaded, total );
                    };

                    // OBJ
                    var objLoader = new THREE.OBJLoader( manager );

                    //objLoader.load( 'models/male02.obj', function ( object ) {
                    objLoader.load( 'models/astronauts/Male_full_body.obj', function ( object ) {
                    //objLoader.load( 'models/man.obj', function ( object ) {
                        object.traverse( function ( child ) {
                            if ( child instanceof THREE.Mesh ) {
                                child.material.map = texture;
                            }
                        } );

                        // object.position.y = - 80;
                        scene.add( object );
                    }, onProgress, onError );

                    // axes
                    axes = new THREE.AxisHelper( 100 );
                    scene.add( axes );

                    // inset canvas
                    // -----------------------------------------------

                    //// dom
                    //container2 = document.getElementById('inset');

                    //// renderer
                    //renderer2 = new THREE.WebGLRenderer();
                    //renderer2.setClearColor( 0xf0f0f0, 1 );
                    //renderer2.setSize( CANVAS_WIDTH, CANVAS_HEIGHT );
                    //container2.appendChild( renderer2.domElement );

                    //// scene
                    //scene2 = new THREE.Scene();

                    //// camera
                    //camera2 = new THREE.PerspectiveCamera( 50, CANVAS_WIDTH / CANVAS_HEIGHT, 1, 1000 );
                    //camera2.up = camera.up; // important!

                    //// axes
                    //axes2 = new THREE.AxisHelper( 100 );
                    //scene2.add( axes2 );
                }

                // animate
                // -----------------------------------------------

                function render() {

                    renderer.render( scene, camera );
                    //renderer2.render( scene2, camera2 );

                }

                function animate() {

                    requestAnimationFrame( animate );

                    controls.update();

                    //camera2.position.copy( camera.position );
                    //camera2.position.sub( controls.target ); // added by @libe
                    //camera2.position.setLength( CAM_DISTANCE );

                    //camera2.lookAt( scene2.position );
                    render();

                }
            }
        }
    }]);

<|endoftext|>


<commit_before>/*
 * test.lb.base.template.string.js - Unit Tests of lb.base.template.string
 *
 * Author:    Eric Bréchemier <legalbox@eric.brechemier.name>
 * Copyright: Legal-Box (c) 2010-2011, All Rights Reserved
 * License:   BSD License - http://creativecommons.org/licenses/BSD/
 * Version:   2011-01-11
 *
 * Based on Test Runner from bezen.org JavaScript library
 * CC-BY: Eric Bréchemier - http://bezen.org/javascript/
 */

/*requires lb.base.template.string.js */
/*jslint white:false, onevar:false, plusplus:false */
/*global lb, bezen, window */
(function() {
  // Builder of
  // Closure object for Test of lb.base.template.string

  // Define aliases
      /*requires bezen.assert.js */
  var assert = bezen.assert,
      /*requires bezen.object.js */
      object = bezen.object,
      /*requires bezen.testrunner.js */
      testrunner = bezen.testrunner,
      /*requires bezen.dom.js*/
      element = bezen.dom.element;

  function testNamespace(){

    assert.isTrue( object.exists(window,'lb','base','template','string'),
                           "lb.base.template.string namespace was not found");
  }

  function testWithValuesFrom(){
    var ut = lb.base.template.string.withValuesFrom;

    var filter = ut();
    assert.equals( typeof ut, 'function',
                                  "function getter expected to be returned");
    assert.equals( filter('param'), null,
                             "no replacement value expected (missing data)");

    filter = ut({param: 'value'});
    assert.equals( filter('param'), 'value',
                                "replacement value expected (single value)");
    assert.equals( filter('other'), null,
        "no replacement value expected for missing property (single value)");

    filter = ut({
      section:{
        subsection:{
          param: 'nestedValue'
        }
      }
    });
    assert.equals( filter('section.subsection.param'), 'nestedValue',
      "replacement value expected for nested property (single nested value)");
    assert.equals( filter('other'), null,
  "no replacement value expected for missing property (single nested value)");
  }

  function testReplaceParams(){
    var ut = lb.base.template.string.replaceParams;

    assert.equals( ut(), null,
                            "null expected when required getter is missing");

    var captured = [];
    var returnValues = [];
    function captureParams(key){
      captured.push(key);
      return returnValues.pop();
    }

    var filter = ut(captureParams);
    assert.equals( typeof filter, 'function',
                              "a filter function is expected to be returned");

    var noParam = 'No param to replace';
    assert.equals( filter(noParam), noParam,
                              "no change expected without params to replace");
    assert.arrayEquals(captured, [],
                      "no call to getter expected without params to replace");

    var noParamReally = 'No #param, #here!#really$#';
    assert.equals( filter(noParamReally), noParamReally,
                      "no change expected without params to replace, really");
    assert.arrayEquals(captured, [],
              "no call to getter expected without params to replace, really");

    var rangeParam = '#abc-xyz_ABC-XYZ_0-9#';
    captured = [];
    returnValues = ['value'];
    assert.equals( filter(rangeParam), 'value',
                                       "replacement expected for parameter "+
                                    "with large range of characters in name");
    assert.arrayEquals(captured, ['abc-xyz_ABC-XYZ_0-9'],
      "param name with large range of characters expected in call to getter");

    var nestedParam = '#a.b.c.d#';
    captured = [];
    returnValues = ['value'];
    assert.equals( filter(nestedParam),'value',
                              "replacement expected for nested param value");
    assert.arrayEquals(captured,['a.b.c.d'],
                              "dotted param nam expected in call to getter");

    var paramInText = 'Before #param# after';
    captured = [];
    returnValues = ['value'];
    assert.equals( filter(paramInText), 'Before value after',
                               "parameter in text expectec to be replaced");
    assert.arrayEquals(captured,['param'],
                        "name of param in text expected in call to getter");

    var missingParam = '#missing#';
    captured = [];
    returnValues = [null];
    assert.equals( filter(missingParam), missingParam,
                          "missing parameter expected to be left unreplaced");
    assert.arrayEquals(captured,['missing'],
                          "name of missing param expected in call to getter");

    var multipleParams = 'Before#param1##param2##param3#After';
    captured = [];
    returnValues = [';value1;','',';value3'];
    assert.equals( filter(multipleParams), 'Before;value1;;value3;After',
        "multiple parameters expected to be replaced, including empty string");
    assert.arrayEquals(captured,['param1','param2','param3'],
                "multiple parameters expected in sequence in calls to getter");
  }

  var tests = {
    testNamespace: testNamespace,
    testWithValuesFrom: testWithValuesFrom,
    testReplaceParams: testReplaceParams
  };

  testrunner.define(tests, "lb.base.template.string");
  return tests;

}());
<commit_msg>Fixed unit tests of replaceParams()<commit_after>/*
 * test.lb.base.template.string.js - Unit Tests of lb.base.template.string
 *
 * Author:    Eric Bréchemier <legalbox@eric.brechemier.name>
 * Copyright: Legal-Box (c) 2010-2011, All Rights Reserved
 * License:   BSD License - http://creativecommons.org/licenses/BSD/
 * Version:   2011-01-11
 *
 * Based on Test Runner from bezen.org JavaScript library
 * CC-BY: Eric Bréchemier - http://bezen.org/javascript/
 */

/*requires lb.base.template.string.js */
/*jslint white:false, onevar:false, plusplus:false */
/*global lb, bezen, window */
(function() {
  // Builder of
  // Closure object for Test of lb.base.template.string

  // Define aliases
      /*requires bezen.assert.js */
  var assert = bezen.assert,
      /*requires bezen.object.js */
      object = bezen.object,
      /*requires bezen.testrunner.js */
      testrunner = bezen.testrunner,
      /*requires bezen.dom.js*/
      element = bezen.dom.element;

  function testNamespace(){

    assert.isTrue( object.exists(window,'lb','base','template','string'),
                           "lb.base.template.string namespace was not found");
  }

  function testWithValuesFrom(){
    var ut = lb.base.template.string.withValuesFrom;

    var filter = ut();
    assert.equals( typeof ut, 'function',
                                  "function getter expected to be returned");
    assert.equals( filter('param'), null,
                             "no replacement value expected (missing data)");

    filter = ut({param: 'value'});
    assert.equals( filter('param'), 'value',
                                "replacement value expected (single value)");
    assert.equals( filter('other'), null,
        "no replacement value expected for missing property (single value)");

    filter = ut({
      section:{
        subsection:{
          param: 'nestedValue'
        }
      }
    });
    assert.equals( filter('section.subsection.param'), 'nestedValue',
      "replacement value expected for nested property (single nested value)");
    assert.equals( filter('other'), null,
  "no replacement value expected for missing property (single nested value)");
  }

  function testReplaceParams(){
    var ut = lb.base.template.string.replaceParams;

    assert.equals( ut(), null,
                            "null expected when required getter is missing");

    var captured = [];
    var returnValues = [];
    function captureParams(key){
      captured.push(key);
      return returnValues.shift();
    }

    var filter = ut(captureParams);
    assert.equals( typeof filter, 'function',
                              "a filter function is expected to be returned");

    var noParam = 'No param to replace';
    assert.equals( filter(noParam), noParam,
                              "no change expected without params to replace");
    assert.arrayEquals(captured, [],
                      "no call to getter expected without params to replace");

    var noParamReally = 'No #param, #here!#really$#';
    assert.equals( filter(noParamReally), noParamReally,
                      "no change expected without params to replace, really");
    assert.arrayEquals(captured, [],
              "no call to getter expected without params to replace, really");

    var rangeParam = '#abc-xyz_ABC-XYZ_0-9#';
    captured = [];
    returnValues = ['value'];
    assert.equals( filter(rangeParam), 'value',
                                       "replacement expected for parameter "+
                                    "with large range of characters in name");
    assert.arrayEquals(captured, ['abc-xyz_ABC-XYZ_0-9'],
      "param name with large range of characters expected in call to getter");

    var nestedParam = '#a.b.c.d#';
    captured = [];
    returnValues = ['value'];
    assert.equals( filter(nestedParam),'value',
                              "replacement expected for nested param value");
    assert.arrayEquals(captured,['a.b.c.d'],
                              "dotted param nam expected in call to getter");

    var paramInText = 'Before #param# after';
    captured = [];
    returnValues = ['value'];
    assert.equals( filter(paramInText), 'Before value after',
                               "parameter in text expectec to be replaced");
    assert.arrayEquals(captured,['param'],
                        "name of param in text expected in call to getter");

    var missingParam = '#missing#';
    captured = [];
    returnValues = [null];
    assert.equals( filter(missingParam), missingParam,
                          "missing parameter expected to be left unreplaced");
    assert.arrayEquals(captured,['missing'],
                          "name of missing param expected in call to getter");

    var multipleParams = 'Before#param1##param2##param3#After';
    captured = [];
    returnValues = [';value1;','',';value3;'];
    assert.equals( filter(multipleParams), 'Before;value1;;value3;After',
        "multiple parameters expected to be replaced, including empty string");
    assert.arrayEquals(captured,['param1','param2','param3'],
                "multiple parameters expected in sequence in calls to getter");
  }

  var tests = {
    testNamespace: testNamespace,
    testWithValuesFrom: testWithValuesFrom,
    testReplaceParams: testReplaceParams
  };

  testrunner.define(tests, "lb.base.template.string");
  return tests;

}());
<|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 _ = require('lodash');
var async = require('async');
var spawn = require('cross-spawn');
var execSync = require('child_process').execSync;
var psTree = require('ps-tree');
var winPsTree = require('winpstree');
var fs = require('fs');
var path = require('path');
var dotenv = require('dotenv');

module.exports = function() {
  var isWin = /^win/.test(process.platform);

  var handleIpAddress = function(container, cmd) {
    var ipAddress;

    ipAddress = container.specific.ipAddress || '127.0.0.1';
    cmd = cmd.replace(/__TARGETIP__/g, ipAddress);
    return cmd;
  };

  var generateEnvironment = function(containerEnv) {
    var envArgs = ' ';
    _.each(_.keys(containerEnv), function(key) {
      if (isWin) {
        envArgs += 'set ' + key + '=' + containerEnv[key] + '&&';
      }
      else {
        envArgs += key + '=' + containerEnv[key] + ' ';
      }
    });
    return envArgs;
  };

  var run = function(mode, container, exitCb, cb) {
    var cmd = container.specific.execute.exec;
    var cwd = container.specific.path;
    var envFile = getEnvFile(container);

    var env;
    var toExec;
    var child = {};
    var envArgs = '';
    var called = false;

    if (cmd.slice(0, 5) === 'node ' && cmd.slice(0, 7) !== 'node -r') {
      // use same node running fuge
      var fugePath = process.mainModule.filename;
      cmd = process.argv[0] + ' -r ' + fugePath + ' ' + cmd.slice(5);
      container.type = 'node';
    }

    if (envFile && !fs.existsSync(envFile)) {
      return cb('Error: ' + envFile + ' does not exist');
    }

    if (container.specific && container.specific.environment) {
      envArgs = generateEnvironment(container.specific.environment);
    }

    if (envFile) {
      var envFileData = dotenv.parse(fs.readFileSync(envFile));
      envArgs += ' ' + generateEnvironment(envFileData || {});
    }

    if (isWin) {
      toExec = envArgs + ' ' + cmd;
    }
    else {
      toExec = envArgs + ' exec ' + cmd;
    }

    toExec = handleIpAddress(container, toExec);

    console.log('running: ' + toExec);

    env = Object.create(process.env);
    if (mode !== 'preview') {
      var options = {cwd: cwd, env: env, stdio: [0, 'pipe', 'pipe'], detached: false};
      if (container.type === 'node' && !isWin) {
        options.stdio[3] = 'ipc';
      }

      if (isWin) {
        child = spawn(process.env.comspec, ['/c', toExec], options);
      }
      else {
        child = spawn('/bin/bash', ['-c', toExec], options);
      }

      child.unref();

      child.on('error', function(err) {
        if (!called) {
          called = true;
          exitCb(child.pid, container.name, err);
        }
      });

      child.on('exit', function(code) {
        if (!called) {
          called = true;
          exitCb(child.pid, container.name, code);
        }
      });
    }
    else {
      child.detail = { cmd: cmd,
        environment: container.specific.environment,
        cwd: cwd };
    }

    cb(null, child);

    function getEnvFile(container) {
      /* jshint ignore:start */
      var envFile = container.specific.source.env_file;
      /* jshint ignore:end */
      var yamlPath = container.specific.yamlPath;
      return envFile && path.resolve(path.dirname(yamlPath), envFile);
    }
  };

  var start = function(mode, container, config, exitCb, cb) {
    if (container && container.specific && container.specific.execute && container.specific.execute.exec) {
      if (container.type === 'docker' && !config.runDocker) {
        console.log('docker disabled, skipping: ' + container.specific.execute.exec);
        cb();
      }
      else {
        run(mode, container, exitCb, cb);
      }
    }
    else {
      if (container.name !== '__proxy') {
        console.log('warning: ' + container.name + ' not started, missing execute statement');
      }
      cb();
    }
  };

  var getContainerId = function(psOutput, container) {
    var lines = psOutput.split('\n');
    var re = new RegExp('^([a-f0-9]+)\\s+' + container.specific.execute.image + '.*');
    var id = null;
    var match;

    _.each(lines, function(line) {
      match = re.exec(line);
      if (match) {
        id = match[1];
      }
    });
    return id;
  };

  var kill = function kill(container, pid, signal, cb) {
    var psOutput;
    var id;

    if (pid) {
      try {
        if (container.type === 'docker') {
          if (!psOutput) {
            psOutput = execSync('docker ps').toString();
          }
          id = getContainerId(psOutput, container);
          if (id) {
            execSync('docker kill ' + id);
          }
          cb(null);
        }
        else {
          if (isWin) {
            winPsTree(pid, function(err, childPids) {
              async.eachSeries(childPids, function(childPid, next) {
                console.log('sending ' + signal + ' to child process: ' + childPid);
                try { process.kill(childPid, signal); } catch(e) {}
                next();
              }, function() {
                console.log('sending ' + signal + ' to parent process: ' + pid);
                try { process.kill(pid, signal); } catch(e) {}
                cb(null);
              });
            });
          }
          else {
            psTree(pid, function(err, children) {
              async.eachSeries(children, function(child, next) {
                console.log('sending ' + signal + ' to  child process: ' + child.PID);
                try { process.kill(child.PID, signal); } catch(e) {}
                next();
              }, function() {
                console.log('sending ' + signal + ' to  parent process: ' + pid);
                try { process.kill(pid, signal); } catch(e) {}
                cb(null);
              });
            });
          }
        }
      }
      catch (e) {
        console.log(e);
      }
    }
  };

  var stop = function stop(container, pid, cb) {
    kill(container, pid, 'SIGKILL', cb);
  };

  return {
    kill: kill,
    start: start,
    stop: stop
  };
};
<commit_msg>See notes, - removed cross spawn, it won't work in our case - updated win strings to be verbatum to solve the issue of spacing - note, this is naive, we probably need a batch file generator<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 _ = require('lodash');
var async = require('async');
var spawn = require('child_process').spawn;
var execSync = require('child_process').execSync;
var psTree = require('ps-tree');
var winPsTree = require('winpstree');
var fs = require('fs');
var path = require('path');
var dotenv = require('dotenv');

module.exports = function() {
  var isWin = /^win/.test(process.platform);

  var handleIpAddress = function(container, cmd) {
    var ipAddress;

    ipAddress = container.specific.ipAddress || '127.0.0.1';
    cmd = cmd.replace(/__TARGETIP__/g, ipAddress);
    return cmd;
  };

  var generateEnvironment = function(containerEnv) {
    var envArgs = ' ';
    _.each(_.keys(containerEnv), function(key) {
      if (isWin) {
        envArgs += 'set ' + key + '=' + containerEnv[key] + '&&';
      }
      else {
        envArgs += key + '=' + containerEnv[key] + ' ';
      }
    });
    return envArgs;
  };

  var run = function(mode, container, exitCb, cb) {
    var cmd = container.specific.execute.exec;
    var cwd = container.specific.path;
    var envFile = getEnvFile(container);

    var env;
    var toExec;
    var child = {};
    var envArgs = '';
    var called = false;

    if (cmd.slice(0, 5) === 'node ' && cmd.slice(0, 7) !== 'node -r') {
      // use same node running fuge
      var fugePath = process.mainModule.filename;

      // quote windows path to handle potential spaces
      var nodePath = isWin ? ('"' + process.argv[0] + '"') : process.argv[0];

      cmd = nodePath + ' -r ' + fugePath + ' ' + cmd.slice(5);
      container.type = 'node';
    }

    if (envFile && !fs.existsSync(envFile)) {
      return cb('Error: ' + envFile + ' does not exist');
    }

    if (container.specific && container.specific.environment) {
      envArgs = generateEnvironment(container.specific.environment);
    }

    if (envFile) {
      var envFileData = dotenv.parse(fs.readFileSync(envFile));
      envArgs += ' ' + generateEnvironment(envFileData || {});
    }

    if (isWin) {
      toExec = envArgs + ' ' + cmd;
    }
    else {
      toExec = envArgs + ' exec ' + cmd;
    }

    toExec = handleIpAddress(container, toExec);

    console.log('running: ' + toExec);

    env = Object.create(process.env);
    if (mode !== 'preview') {
      var options = {cwd: cwd, env: env, stdio: [0, 'pipe', 'pipe'], detached: false};
      if (container.type === 'node' && !isWin) {
        options.stdio[3] = 'ipc';
      }

      if (isWin) {
        child = spawn(process.env.comspec, ['/s', '/c', '"', toExec, '"'], options);
      }
      else {
        child = spawn('/bin/bash', ['-c', toExec], options);
      }

      child.unref();

      child.on('error', function(err) {
        if (!called) {
          called = true;
          exitCb(child.pid, container.name, err);
        }
      });

      child.on('exit', function(code) {
        if (!called) {
          called = true;
          exitCb(child.pid, container.name, code);
        }
      });
    }
    else {
      child.detail = { cmd: cmd,
        environment: container.specific.environment,
        cwd: cwd };
    }

    cb(null, child);

    function getEnvFile(container) {
      /* jshint ignore:start */
      var envFile = container.specific.source.env_file;
      /* jshint ignore:end */
      var yamlPath = container.specific.yamlPath;
      return envFile && path.resolve(path.dirname(yamlPath), envFile);
    }
  };

  var start = function(mode, container, config, exitCb, cb) {
    if (container && container.specific && container.specific.execute && container.specific.execute.exec) {
      if (container.type === 'docker' && !config.runDocker) {
        console.log('docker disabled, skipping: ' + container.specific.execute.exec);
        cb();
      }
      else {
        run(mode, container, exitCb, cb);
      }
    }
    else {
      if (container.name !== '__proxy') {
        console.log('warning: ' + container.name + ' not started, missing execute statement');
      }
      cb();
    }
  };

  var getContainerId = function(psOutput, container) {
    var lines = psOutput.split('\n');
    var re = new RegExp('^([a-f0-9]+)\\s+' + container.specific.execute.image + '.*');
    var id = null;
    var match;

    _.each(lines, function(line) {
      match = re.exec(line);
      if (match) {
        id = match[1];
      }
    });
    return id;
  };

  var kill = function kill(container, pid, signal, cb) {
    var psOutput;
    var id;

    if (pid) {
      try {
        if (container.type === 'docker') {
          if (!psOutput) {
            psOutput = execSync('docker ps').toString();
          }
          id = getContainerId(psOutput, container);
          if (id) {
            execSync('docker kill ' + id);
          }
          cb(null);
        }
        else {
          if (isWin) {
            winPsTree(pid, function(err, childPids) {
              async.eachSeries(childPids, function(childPid, next) {
                console.log('sending ' + signal + ' to child process: ' + childPid);
                try { process.kill(childPid, signal); } catch(e) {}
                next();
              }, function() {
                console.log('sending ' + signal + ' to parent process: ' + pid);
                try { process.kill(pid, signal); } catch(e) {}
                cb(null);
              });
            });
          }
          else {
            psTree(pid, function(err, children) {
              async.eachSeries(children, function(child, next) {
                console.log('sending ' + signal + ' to  child process: ' + child.PID);
                try { process.kill(child.PID, signal); } catch(e) {}
                next();
              }, function() {
                console.log('sending ' + signal + ' to  parent process: ' + pid);
                try { process.kill(pid, signal); } catch(e) {}
                cb(null);
              });
            });
          }
        }
      }
      catch (e) {
        console.log(e);
      }
    }
  };

  var stop = function stop(container, pid, cb) {
    kill(container, pid, 'SIGKILL', cb);
  };

  return {
    kill: kill,
    start: start,
    stop: stop
  };
};
<|endoftext|>


<commit_before>var RENDER_NEW_QUOTE_TIMEOUT,
    LOAD_QUOTE_TIMEOUT;

$(function() {
  History.Adapter.bind(window, 'statechange', function() {
    clearTimeout(RENDER_NEW_QUOTE_TIMEOUT);
    clearTimeout(LOAD_QUOTE_TIMEOUT);
    var quote = History.getState().data;
    if (quote.id && quote.id != CURRENT_QUOTE.id)
      renderNewQuote(quote);
  });

  function loadNewQuote() {
    $.getJSON("quote", {t: new Date().getTime()})
     .done(function(quote) {
      if (hasQuoteOnScreenAlready(quote))
        loadNewQuote();
      else {
        clearTimeout(RENDER_NEW_QUOTE_TIMEOUT);
        RENDER_NEW_QUOTE_TIMEOUT = setTimeout(function() {
          History.pushState(quote, null, quote.id);
        }, timeForReading());
      }
    })
     .fail(function() {
       clearTimeout(LOAD_QUOTE_TIMEOUT);
       LOAD_QUOTE_TIMEOUT = setTimeout(loadQuote, 5000);
     });
  }

  function renderNewQuote(quote) {
    if (hasQuoteOnScreenAlready(quote)) return;

    $("blockquote").fadeOut(animationTimeout, function() {
      $(this).find(".content").html(quote.c).end()
             .find(".author").html(quote.a).end();
      showQuote(quote);
    });
  }

  function hasQuoteOnScreenAlready(quote) {
    return $("blockquote").is(":visible") && CURRENT_QUOTE.id == quote.id;
  }

  function renderTwitterButton() {
    var btn = 'Tweet';
    $("#tweet-button").empty().html(btn);

    if (!window.twttr)
      $.getScript("//platform.twitter.com/widgets.js", function() {
        twttr.widgets.load();
      });
    else
      twttr.widgets.load();
  }

  function renderFacebookButton() {
    var btn = '

';
    $("#fb-button").empty().html(btn);

    if (!window.FB)
      $.getScript("//connect.facebook.net/en_US/all.js#xfbml=1", function() {
        FB.XFBML.parse();
      });
    else
      FB.XFBML.parse();
  }

  function showQuote(quote) {
    $("blockquote").fadeIn(animationTimeout);
    CURRENT_QUOTE = quote;
    renderTwitterButton();
    renderFacebookButton();
    _gaq.push(['_trackPageview']);
    loadNewQuote();
  }

  function timeForReading() {
    var averageWPM = 200;
    var additionalFactor = 1.5;
    var time = (CURRENT_QUOTE.c + " " + CURRENT_QUOTE.a).split(" ").length * 60 / averageWPM * additionalFactor;
    return Math.ceil(Math.min(5, time) * 1000);
  }

  var animationTimeout = 1000;
  History.replaceState(CURRENT_QUOTE, null, CURRENT_QUOTE.id);
  renderNewQuote(CURRENT_QUOTE);
});
<commit_msg>fix function call<commit_after>var RENDER_NEW_QUOTE_TIMEOUT,
    LOAD_QUOTE_TIMEOUT;

$(function() {
  History.Adapter.bind(window, 'statechange', function() {
    clearTimeout(RENDER_NEW_QUOTE_TIMEOUT);
    clearTimeout(LOAD_QUOTE_TIMEOUT);
    var quote = History.getState().data;
    if (quote.id && quote.id != CURRENT_QUOTE.id)
      renderNewQuote(quote);
  });

  function loadNewQuote() {
    $.getJSON("quote", {t: new Date().getTime()})
     .done(function(quote) {
      if (hasQuoteOnScreenAlready(quote))
        loadNewQuote();
      else {
        clearTimeout(RENDER_NEW_QUOTE_TIMEOUT);
        RENDER_NEW_QUOTE_TIMEOUT = setTimeout(function() {
          History.pushState(quote, null, quote.id);
        }, timeForReading());
      }
    })
     .fail(function() {
       clearTimeout(LOAD_QUOTE_TIMEOUT);
       LOAD_QUOTE_TIMEOUT = setTimeout(loadNewQuote, 5000);
     });
  }

  function renderNewQuote(quote) {
    if (hasQuoteOnScreenAlready(quote)) return;

    $("blockquote").fadeOut(animationTimeout, function() {
      $(this).find(".content").html(quote.c).end()
             .find(".author").html(quote.a).end();
      showQuote(quote);
    });
  }

  function hasQuoteOnScreenAlready(quote) {
    return $("blockquote").is(":visible") && CURRENT_QUOTE.id == quote.id;
  }

  function renderTwitterButton() {
    var btn = 'Tweet';
    $("#tweet-button").empty().html(btn);

    if (!window.twttr)
      $.getScript("//platform.twitter.com/widgets.js", function() {
        twttr.widgets.load();
      });
    else
      twttr.widgets.load();
  }

  function renderFacebookButton() {
    var btn = '

';
    $("#fb-button").empty().html(btn);

    if (!window.FB)
      $.getScript("//connect.facebook.net/en_US/all.js#xfbml=1", function() {
        FB.XFBML.parse();
      });
    else
      FB.XFBML.parse();
  }

  function showQuote(quote) {
    $("blockquote").fadeIn(animationTimeout);
    CURRENT_QUOTE = quote;
    renderTwitterButton();
    renderFacebookButton();
    _gaq.push(['_trackPageview']);
    loadNewQuote();
  }

  function timeForReading() {
    var averageWPM = 200;
    var additionalFactor = 1.5;
    var time = (CURRENT_QUOTE.c + " " + CURRENT_QUOTE.a).split(" ").length * 60 / averageWPM * additionalFactor;
    return Math.ceil(Math.min(5, time) * 1000);
  }

  var animationTimeout = 1000;
  History.replaceState(CURRENT_QUOTE, null, CURRENT_QUOTE.id);
  renderNewQuote(CURRENT_QUOTE);
});
<|endoftext|>