<commit_before>var NavigationController,
    NavItem;

NavItem = Ember.Object.extend({
    label: '',
    url: '',
    order: '',

    isComplete: Ember.computed('label', 'url', function () {
        return !(Ember.isBlank(this.get('label')) || Ember.isBlank(this.get('url')));
    })
});

NavigationController = Ember.Controller.extend({
    blogUrl: Ember.computed('config.blogUrl', function () {
        var url = this.get('config.blogUrl');

        return url.slice(-1) !== '/' ? url + '/' : url;
    }),

    navigationItems: Ember.computed('model.navigation', function () {
        var navItems,
            lastItem,
            order = 0;

        try {
            navItems = JSON.parse(this.get('model.navigation') || [{}]);
        } catch (e) {
            navItems = [{}];
        }

        navItems = navItems.map(function (item) {
            item.order = order;
            order = order + 1;
            return NavItem.create(item);
        });

        navItems.sortBy('order');

        lastItem = navItems.get('lastObject');
        if (!lastItem || lastItem.get('isComplete')) {
            navItems.addObject(NavItem.create());
        }

        return navItems;
    }),

    navigationItemsObserver: Ember.observer('navigationItems.[]', function () {
        var navItems = this.get('navigationItems');

        navItems.forEach(function (item, index, items) {
            if (index === (items.length - 1)) {
                item.set('last', true);
            } else {
                item.set('last', false);
            }
        });
    }),

    updateOrder: function (indexes) {
        var navItems = this.get('navigationItems'),
            order = 0;

        indexes.forEach(function (index) {
            navItems[index].set('order', order);
            order = order + 1; // Increment order order by one
        });
    },

    actions: {
        addItem: function () {
            var navItems = this.get('navigationItems'),
                lastItem = navItems.get('lastObject');

            if (lastItem && lastItem.get('isComplete')) {
                lastItem.set('order', (navItems.length - 1)); // -1 because order is 0-index, length is 1-index
                navItems.addObject(NavItem.create()); // Adds new blank navItem
            }
        },

        deleteItem: function (item) {
            if (!item) {
                return;
            }

            this.get('navigationItems').removeObject(item);

            var navItems = this.get('navigationItems'),
                order = 0;

            navItems.forEach(function (item) {
                if (!item.last) { // Make sure we never apply an `order` attr to the last item
                    item.set('order', order);
                    order = order + 1; // Increment order order by one
                }
            });
        },

        updateUrl: function (url, navItem) {
            if (!navItem) {
                return;
            }

            if (Ember.isBlank(url)) {
                navItem.set('url', this.get('blogUrl'));

                return;
            }

            navItem.set('url', url);
        },

        save: function () {
            var self = this,
                navSetting,
                blogUrl = this.get('config').blogUrl,
                blogUrlRegex = new RegExp('^' + blogUrl + '(.*)', 'i'),
                match;

            navSetting = this.get('navigationItems').map(function (item) {
                var label,
                    url,
                    order;

                if (!item || !item.get('isComplete')) {
                    return;
                }

                label = item.get('label').trim();
                url = item.get('url').trim();
                order = item.get('order');

                // is this an internal URL?
                match = url.match(blogUrlRegex);

                if (match) {
                    url = match[1];

                    // if the last char is not a slash, then add one,
                    // this also handles the empty case for the homepage
                    if (url[url.length - 1] !== '/') {
                        url += '/';
                    }
                } else if (!validator.isURL(url) && url !== '' && url[0] !== '/') {
                    url = '/' + url;
                }

                // if navItem label is empty and URL is still the default, don't save
                if (!label && url === '/') {
                    return;
                }

                return {label: label, url: url, order: order};
            }).compact();

            // Sort JSON so nav items are stored in the correct order order
            navSetting.sort(function (a, b) {
                return a.order - b.order;
            });

            this.set('model.navigation', JSON.stringify(navSetting));

            // trigger change event because even if the final JSON is unchanged
            // we need to have navigationItems recomputed.
            this.get('model').notifyPropertyChange('navigation');

            this.notifications.closePassive();

            this.get('model').save().then(function () {
                self.notifications.showSuccess('Navigation items saved.');
            }).catch(function (err) {
                self.notifications.showErrors(err);
            });
        }
    }
});

export default NavigationController;
<commit_msg>Fix navigation deletion Closes #4928<commit_after>var NavigationController,
    NavItem;

NavItem = Ember.Object.extend({
    label: '',
    url: '',
    order: '',

    isComplete: Ember.computed('label', 'url', function () {
        return !(Ember.isBlank(this.get('label')) || Ember.isBlank(this.get('url')));
    })
});

NavigationController = Ember.Controller.extend({
    blogUrl: Ember.computed('config.blogUrl', function () {
        var url = this.get('config.blogUrl');

        return url.slice(-1) !== '/' ? url + '/' : url;
    }),

    navigationItems: Ember.computed('model.navigation', function (key, value) {
        if (arguments.length > 1) {
            return value.sortBy('order');
        }
        var order = 0,
            navItems,
            lastItem;
        try {
            navItems = JSON.parse(this.get('model.navigation') || [{}]);
        } catch (e) {
            navItems = [{}];
        }

        navItems = navItems.map(function (item) {
            item.order = order;
            order = order + 1;
            return NavItem.create(item);
        });

        navItems.sortBy('order');

        lastItem = navItems.get('lastObject');
        if (!lastItem || lastItem.get('isComplete')) {
            navItems.addObject(NavItem.create());
        }

        return navItems;
    }),

    updateLastNavItem: Ember.observer('navigationItems.[]', function () {
        var navItems = this.get('navigationItems');

        navItems.forEach(function (item, index, items) {
            if (index === (items.length - 1)) {
                item.set('last', true);
            } else {
                item.set('last', false);
            }
        });
    }),

    // called by the view after items have been rearranged
    updateOrder: function (indexes) {
        var navItems = this.get('navigationItems');

        indexes.forEach(function (index, newOrder) {
            navItems.objectAt(index).set('order', newOrder);
        });
    },

    actions: {
        addItem: function () {
            var navItems = this.get('navigationItems'),
                lastItem = navItems.get('lastObject');

            if (lastItem && lastItem.get('isComplete')) {
                lastItem.set('order', (navItems.length - 1)); // -1 because order is 0-index, length is 1-index
                navItems.addObject(NavItem.create()); // Adds new blank navItem
            }
        },

        deleteItem: function (item) {
            if (!item) {
                return;
            }
            var deletedItemOrder = item.get('order'),
                navItems = this.get('navigationItems');

            navItems.removeAt(navItems.indexOf(item));

            navItems.forEach(function (item) {
                if (!item.last && item.get('order') > deletedItemOrder) {
                    item.decrementProperty('order');
                }
            });

            this.set('navigationItems', navItems);
        },

        updateUrl: function (url, navItem) {
            if (!navItem) {
                return;
            }

            if (Ember.isBlank(url)) {
                navItem.set('url', this.get('blogUrl'));

                return;
            }

            navItem.set('url', url);
        },

        save: function () {
            var self = this,
                navSetting,
                blogUrl = this.get('config').blogUrl,
                blogUrlRegex = new RegExp('^' + blogUrl + '(.*)', 'i'),
                match;

            navSetting = this.get('navigationItems').map(function (item) {
                var label,
                    url,
                    order;

                if (!item || !item.get('isComplete')) {
                    return;
                }

                label = item.get('label').trim();
                url = item.get('url').trim();
                order = item.get('order');

                // is this an internal URL?
                match = url.match(blogUrlRegex);

                if (match) {
                    url = match[1];

                    // if the last char is not a slash, then add one,
                    // this also handles the empty case for the homepage
                    if (url[url.length - 1] !== '/') {
                        url += '/';
                    }
                } else if (!validator.isURL(url) && url !== '' && url[0] !== '/') {
                    url = '/' + url;
                }

                // if navItem label is empty and URL is still the default, don't save
                if (!label && url === '/') {
                    return;
                }

                return {label: label, url: url, order: order};
            }).compact();

            // Sort JSON so nav items are stored in the correct order
            navSetting.sort(function (a, b) {
                return a.order - b.order;
            });

            this.set('model.navigation', JSON.stringify(navSetting));

            // trigger change event because even if the final JSON is unchanged
            // we need to have navigationItems recomputed.
            this.get('model').notifyPropertyChange('navigation');

            this.notifications.closePassive();

            this.get('model').save().then(function () {
                self.notifications.showSuccess('Navigation items saved.');
            }).catch(function (err) {
                self.notifications.showErrors(err);
            });
        }
    }
});

export default NavigationController;
<|endoftext|>


<commit_before>'use strict'

module.exports = [
  {
    user: '@michal.brasna',
    services: ['tankovna', 'lokal-hamburk', 'globus']
  },
  {
    user: '@jan.pavlovsky',
    services: ['peters', 'meat-market', 'globus', 'lokal-hamburk']
  },
  {
    user: '@ottokovarik',
    services: ['tankovna', 'lokal-hamburk', 'globus']
  },
  {
    user: '@radim',
    services: ['tankovna', 'lokal-hamburk', 'u-zabranskych']
  },
  {
    user: '@tomas.pokorny',
    services: ['tankovna', 'lokal-hamburk']
  },
  {
    user: '@radek.carda',
    services: ['peters', 'globus', 'meat-market', 'lokal-hamburk']
  },
  {
    user: '@zdenek.cejka',
    services: ['peters', 'tankovna', 'u-sani', 'meat-market', 'globus']
  },
  {
    user: '@mafo',
    services: ['tankovna', 'lokal-hamburk', 'globus']
  },
  {
    user: '@martin.kadlec',
    services: ['tankovna', 'lokal-hamburk', 'globus']
  },
  {
    user: '@tomasbauer',
    services: ['tankovna', 'lokal-hamburk', 'globus']
  },
  {
    user: '@snajby',
    services: ['peters', 'tankovna', 'meat-market', 'lokal-hamburk', 'globus', 'u-zabranskych']
  },
  {
    user: '@milan',
    services: ['peters', 'tankovna', 'u-sani', 'meat-market', 'lokal-hamburk', 'globus']
  },
  {
    user: '@vaclavhosticka',
    services: ['peters', 'tankovna', 'meat-market', 'lokal-hamburk', 'globus', 'u-zabranskych']
  },
  {
    user: '@ango',
    services: ['peters', 'tankovna', 'meat-market', 'lokal-hamburk', 'globus', 'u-zabranskych', 'u-sani', 'u-tunelu']
  },
  {
    user: '@ondram',
    services: ['peters', 'tankovna', 'meat-market', 'lokal-hamburk', 'globus', 'u-zabranskych', 'u-sani', 'u-tunelu']
  },
  {
    user: '@jenism',
    services: ['peters', 'meat-market', 'globus', 'lokal-hamburk']
  },
  {
    user: '@petrkrejcik',
    services: ['tankovna', 'lokal-hamburk', 'globus', 'u-zabranskych', 'u-tunelu']
  }
]
<commit_msg>Add @adamsobotka, @jakubsimecek, @renata.vostra<commit_after>'use strict'

module.exports = [
  {
    user: '@michal.brasna',
    services: ['tankovna', 'lokal-hamburk', 'globus']
  },
  {
    user: '@jan.pavlovsky',
    services: ['peters', 'meat-market', 'globus', 'lokal-hamburk']
  },
  {
    user: '@ottokovarik',
    services: ['tankovna', 'lokal-hamburk', 'globus']
  },
  {
    user: '@radim',
    services: ['tankovna', 'lokal-hamburk', 'u-zabranskych']
  },
  {
    user: '@tomas.pokorny',
    services: ['tankovna', 'lokal-hamburk']
  },
  {
    user: '@radek.carda',
    services: ['peters', 'globus', 'meat-market', 'lokal-hamburk']
  },
  {
    user: '@zdenek.cejka',
    services: ['peters', 'tankovna', 'u-sani', 'meat-market', 'globus']
  },
  {
    user: '@mafo',
    services: ['tankovna', 'lokal-hamburk', 'globus']
  },
  {
    user: '@martin.kadlec',
    services: ['tankovna', 'lokal-hamburk', 'globus']
  },
  {
    user: '@tomasbauer',
    services: ['tankovna', 'lokal-hamburk', 'globus']
  },
  {
    user: '@snajby',
    services: ['peters', 'tankovna', 'meat-market', 'lokal-hamburk', 'globus', 'u-zabranskych']
  },
  {
    user: '@milan',
    services: ['peters', 'tankovna', 'u-sani', 'meat-market', 'lokal-hamburk', 'globus']
  },
  {
    user: '@vaclavhosticka',
    services: ['peters', 'tankovna', 'meat-market', 'lokal-hamburk', 'globus', 'u-zabranskych']
  },
  {
    user: '@ango',
    services: ['peters', 'tankovna', 'meat-market', 'lokal-hamburk', 'globus', 'u-zabranskych', 'u-sani', 'u-tunelu']
  },
  {
    user: '@ondram',
    services: ['peters', 'tankovna', 'meat-market', 'lokal-hamburk', 'globus', 'u-zabranskych', 'u-sani', 'u-tunelu']
  },
  {
    user: '@jenism',
    services: ['peters', 'meat-market', 'globus', 'lokal-hamburk']
  },
  {
    user: '@petrkrejcik',
    services: ['tankovna', 'lokal-hamburk', 'globus', 'u-zabranskych', 'u-tunelu']
  },
  {
    user: '@adamsobotka',
    services: ['tankovna', 'lokal-hamburk', 'meat-market', 'globus']
  },
  {
    user: '@jakubsimecek',
    services: ['peters', 'tankovna', 'meat-market', 'lokal-hamburk', 'globus', 'u-zabranskych', 'u-sani', 'u-tunelu']
  },
  {
    user: '@renata.vostra',
    services: ['peters', 'tankovna', 'meat-market', 'lokal-hamburk', 'globus', 'u-zabranskych', 'u-tunelu']
  },
]
<|endoftext|>


<commit_before>var debug         = require('debug')('queue:bin:load-test');
var base          = require('taskcluster-base');
var Promise       = require('promise');
var _             = require('lodash');
var v1            = require('../routes/api/v1');
var https         = require('https');
var http          = require('http');
var hawk          = require('hawk');
var taskcluster   = require('taskcluster-client');
var assert        = require('assert');

/** Launch server */
var launch = async function(profile) {
  debug("Launching with profile: %s", profile);

  // Load configuration
  var cfg = base.config({
    defaults:     require('../config/defaults'),
    profile:      require('../config/' + profile),
    envs: [
      'server_publicUrl',
      'server_cookieSecret',
      'azure_accountName',
      'azure_accountKey',
      'aws_accessKeyId',
      'aws_secretAccessKey',
      'influx_connectionString',
      'auth_root_clientId',
      'auth_root_accessToken',
      'auth_azureAccounts',
      'auth_clientIdForTempCreds'
    ],
    filename:     'taskcluster-auth'
  });

  var fmt = (n) => {
    return Math.round(n * 100) / 100;
  };

  const CYCLE_SECONDS = 3 * 60 * 20;

  var success = 0;
  var failed  = 0;
  var summary = () => {
    console.log("%s req/s success: %s, failed: %s",
                fmt(success / CYCLE_SECONDS), success, failed)
    success = 0;
    failed  = 0;
  };

  var makeSignature = function() {
    var tempCreds = taskcluster.createTemporaryCredentials({
      start: new Date(),
      expiry: taskcluster.fromNow("1 hour"),
      scopes: ["auth:credentials"],
      credentials: cfg.get('auth:root')
    });
    var reqUrl = 'http://localhost:1207/v1/client/authed-client/credentials';
    var header = hawk.client.header(reqUrl, 'GET', {
      credentials: {
        id:         tempCreds.clientId,
        key:        tempCreds.accessToken,
        algorithm:  'sha256',
      },
      ext: new Buffer(JSON.stringify({
        certificate: JSON.parse(tempCreds.certificate)
      })).toString('base64')
    }).field;
    return {
      method:         'get',
      resource:       '/v1/client/authed-client/credentials',
      host:           'localhost',
      port:           1207,
      authorization:  header
    };
  };

  var loops = 0;
  var exiting = false;
  var startLoop = () => {
    loops += 1;
    (async() => {
      var agent = new https.Agent({keepAlive: true});
      if (cfg.get('server:publicUrl').substr(0, 5) != 'https') {
        agent = new http.Agent({keepAlive: true});
      }
      var Auth = taskcluster.createClient(v1.reference({
        baseUrl:      cfg.get('server:publicUrl') + '/v1',
      }));
      var auth = new Auth({
        //credentials:  cfg.get('auth:root'), //TODO: Try without this!!!
        retries:      0,
        agent:        agent
      });
      var reqForVerification = makeSignature();
      setInterval(function() {
        reqForVerification = makeSignature();
      }, 3 * 60 * 1000);
      while(true) {
        await auth.authenticateHawk(reqForVerification).then(result => {
          assert(result.error === false, "Validation error");
          success += 1;
        }).catch(err => {
          failed += 1;
          if (exiting) {
            console.log("Error: %s: %s", err.statusCode, err.message);
          }
        });

        if (exiting) {
          break;
        }
        await base.testing.sleep(10);
      }
    })().catch(function(err) {
      console.log("LOOP CRASHED!!!");
      console.log(err.stack);
    });
  };

  /*
  //  2 req in parallel
  while(loops < 2) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();

  //  4 req in parallel
  while(loops < 4) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();
  // */
  //  8 req in parallel
  while(loops < 8) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();

  /*
  // 16 req in parallel
  while(loops < 16) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();

  // 32 req in parallel
  while(loops < 32) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();

  // 48 req in parallel
  while(loops < 48) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();
  //

  // 64 req in parallel
  while(loops < 64) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();

  // 128 req in parallel
  while(loops < 128) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();
  //*/
  console.log("Exiting");
  exiting = true;
};

// If load-test.js is executed start the load-test
if (!module.parent) {
  // Find configuration profile
  var profile = process.argv[2];
  if (!profile) {
    console.log("Usage: load-test.js [profile]")
    console.error("ERROR: No configuration profile is provided");
  }
  // Launch with given profile
  launch(profile).then(function() {
    debug("Launched load-test successfully");
  }).catch(function(err) {
    debug("Failed to start load-test, err: %s, as JSON: %j", err, err, err.stack);
    // If we didn't launch the load-test we should crash
    process.exit(1);
  });
}

// Export launch in-case anybody cares
module.exports = launch;

<commit_msg>Test for an hour<commit_after>var debug         = require('debug')('queue:bin:load-test');
var base          = require('taskcluster-base');
var Promise       = require('promise');
var _             = require('lodash');
var v1            = require('../routes/api/v1');
var https         = require('https');
var http          = require('http');
var hawk          = require('hawk');
var taskcluster   = require('taskcluster-client');
var assert        = require('assert');

/** Launch server */
var launch = async function(profile) {
  debug("Launching with profile: %s", profile);

  // Load configuration
  var cfg = base.config({
    defaults:     require('../config/defaults'),
    profile:      require('../config/' + profile),
    envs: [
      'server_publicUrl',
      'server_cookieSecret',
      'azure_accountName',
      'azure_accountKey',
      'aws_accessKeyId',
      'aws_secretAccessKey',
      'influx_connectionString',
      'auth_root_clientId',
      'auth_root_accessToken',
      'auth_azureAccounts',
      'auth_clientIdForTempCreds'
    ],
    filename:     'taskcluster-auth'
  });

  var fmt = (n) => {
    return Math.round(n * 100) / 100;
  };

  const CYCLE_SECONDS = 3 * 60 * 20;

  var success = 0;
  var failed  = 0;
  var summary = () => {
    console.log("SUMMARY: %s req/s success: %s, failed: %s",
                fmt(success / CYCLE_SECONDS), success, failed)
    success = 0;
    failed  = 0;
  };

  setInterval(function() {
    console.log(" - %s req/s success: %s, failed: %s",
                fmt(success / CYCLE_SECONDS), success, failed)
  }, 10 * 60 * 1000);

  var makeSignature = function() {
    var tempCreds = taskcluster.createTemporaryCredentials({
      start: new Date(),
      expiry: taskcluster.fromNow("1 hour"),
      scopes: ["auth:credentials"],
      credentials: cfg.get('auth:root')
    });
    var reqUrl = 'http://localhost:1207/v1/client/authed-client/credentials';
    var header = hawk.client.header(reqUrl, 'GET', {
      credentials: {
        id:         tempCreds.clientId,
        key:        tempCreds.accessToken,
        algorithm:  'sha256',
      },
      ext: new Buffer(JSON.stringify({
        certificate: JSON.parse(tempCreds.certificate)
      })).toString('base64')
    }).field;
    return {
      method:         'get',
      resource:       '/v1/client/authed-client/credentials',
      host:           'localhost',
      port:           1207,
      authorization:  header
    };
  };

  var loops = 0;
  var exiting = false;
  var startLoop = () => {
    loops += 1;
    (async() => {
      var agent = new https.Agent({keepAlive: true});
      if (cfg.get('server:publicUrl').substr(0, 5) != 'https') {
        agent = new http.Agent({keepAlive: true});
      }
      var Auth = taskcluster.createClient(v1.reference({
        baseUrl:      cfg.get('server:publicUrl') + '/v1',
      }));
      var auth = new Auth({
        //credentials:  cfg.get('auth:root'), //TODO: Try without this!!!
        retries:      0,
        agent:        agent
      });
      var reqForVerification = makeSignature();
      setInterval(function() {
        reqForVerification = makeSignature();
      }, 3 * 60 * 1000);
      while(true) {
        await auth.authenticateHawk(reqForVerification).then(result => {
          assert(result.error === false, "Validation error");
          success += 1;
        }).catch(err => {
          failed += 1;
          if (exiting) {
            console.log("Error: %s: %s", err.statusCode, err.message);
          }
        });

        if (exiting) {
          break;
        }
        await base.testing.sleep(10);
      }
    })().catch(function(err) {
      console.log("LOOP CRASHED!!!");
      console.log(err.stack);
    });
  };

  /*
  //  2 req in parallel
  while(loops < 2) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();

  //  4 req in parallel
  while(loops < 4) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();
  // */
  //  8 req in parallel
  while(loops < 8) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();

  /*
  // 16 req in parallel
  while(loops < 16) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();

  // 32 req in parallel
  while(loops < 32) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();

  // 48 req in parallel
  while(loops < 48) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();
  //

  // 64 req in parallel
  while(loops < 64) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();

  // 128 req in parallel
  while(loops < 128) startLoop();
  await base.testing.sleep(CYCLE_SECONDS * 1000);
  summary();
  //*/
  console.log("Exiting");
  exiting = true;
};

// If load-test.js is executed start the load-test
if (!module.parent) {
  // Find configuration profile
  var profile = process.argv[2];
  if (!profile) {
    console.log("Usage: load-test.js [profile]")
    console.error("ERROR: No configuration profile is provided");
  }
  // Launch with given profile
  launch(profile).then(function() {
    debug("Launched load-test successfully");
  }).catch(function(err) {
    debug("Failed to start load-test, err: %s, as JSON: %j", err, err, err.stack);
    // If we didn't launch the load-test we should crash
    process.exit(1);
  });
}

// Export launch in-case anybody cares
module.exports = launch;

<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

/**
 * Binary to run a pg server.
 * (C) 2015 Alex Fernández.
 */

// requires
var Log = require('log');
var stdio = require('stdio');
var server = require('../lib/server.js');
var packageJson = require(__dirname + '/../package.json');

// globals
var log = new Log('info');

// constants
var PORT = 5433;

// init
var options = stdio.getopt({
	version: {key: 'v', description: 'Display version and quit'},
	port: {key: 'p', args: 1, description: 'Port to connect to', default: PORT},
	host: {key: 'h', args: 1, description: 'Host to connect to'},
	quiet: {key: 'q', description: 'Do not log any messages'},
	debug: {key: 'd', description: 'Show debug messages'},
});
if (options.version)
{
	console.log('Loadtest version: %s', packageJson.version);
	process.exit(0);
}
if (options.args && options.args.length > 0)
{
	console.error('Too many arguments: %s', options.args);
	options.printHelp();
	process.exit(1);
}
server.start(options, function(error)
{
	if (error)
	{
		return console.error('Could not start server on port %s: %s', options.port, error);
	}
	log.info('Pooled PostgreSQL server started on port %s', options.port);
});

<commit_msg>Changed -q to -s for consistency.<commit_after>#!/usr/bin/env node
'use strict';

/**
 * Binary to run a pg server.
 * (C) 2015 Alex Fernández.
 */

// requires
var Log = require('log');
var stdio = require('stdio');
var server = require('../lib/server.js');
var packageJson = require(__dirname + '/../package.json');

// globals
var log = new Log('info');

// constants
var PORT = 5433;

// init
var options = stdio.getopt({
	version: {key: 'v', description: 'Display version and quit'},
	port: {key: 'p', args: 1, description: 'Port to connect to', default: PORT},
	host: {key: 'h', args: 1, description: 'Host to connect to'},
	silent: {key: 's', description: 'Do not log any messages'},
	debug: {key: 'd', description: 'Show debug messages'},
});
if (options.version)
{
	console.log('Loadtest version: %s', packageJson.version);
	process.exit(0);
}
if (options.args && options.args.length > 0)
{
	console.error('Too many arguments: %s', options.args);
	options.printHelp();
	process.exit(1);
}
server.start(options, function(error)
{
	if (error)
	{
		return console.error('Could not start server on port %s: %s', options.port, error);
	}
	log.info('Pooled PostgreSQL server started on port %s', options.port);
});

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIOloNS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
({
	/**
	 * Test to verify action menu works when interacting with the menu items
	 * which has attachToBody attribute set
	 * using AURA API
	 * TODO: Disabling test in IE7&8, bug W-2320774
	 */
	testActionMenuWithAttachToBodySet:{
		browsers: ["-IE7","-IE8"],
		test: [function(cmp) {
				actionMenu = cmp.find("actionMenuAttachToBody");
	        	menuLabel = cmp.find("triggerAttachToBody");
	        	item1 = "actionItemAttachToBody1";
	        	item2 = "actionItemAttachToBody2";
	        	item3 = "actionItemAttachToBody3";

	        	//check menu is default to hidden by using AURA API
	        	$A.test.assertFalse(actionMenu.get('v.visible'),"Action Menu should not be visible");

	        	//check menu is default to hidden by using DOM API
	        	$A.test.assertTrue($A.util.hasClass(actionMenu.getElement(),"uiMenuList"), "Class name should be just uiMenuList");
	        	$A.test.assertFalse($A.util.hasClass(actionMenu.getElement(),"visible"), "Class name should not contain visible");
	        	menuLabel.get("e.click").fire();

	            //Check if secondItem in the menu is disabled
	            $A.test.addWaitForWithFailureMessage(true, function(){return cmp.find(item2).get("v.disabled");}, "Check if Item2 in the menu is disabled");
			}, function(cmp) {
				//make sure menuItem is attached to body directly and its not attached to uiMenu instead
	            //Test case for W-2181713
				var actionMenuParentElement = actionMenu.getElement().parentNode;
				var bodyElement = document.getElementsByTagName("body")[0];
	            $A.test.assertEquals(actionMenuParentElement, bodyElement,"Menu Item List should be attached to body");

	            //Make sure horizontal alignment of menuItem is correct with reference to triggerElement
	            var actionMenuLeftPostionValue = actionMenu.getElement().getBoundingClientRect().left;
	            var triggerLeftPositonValue = menuLabel.getElement().getBoundingClientRect().left;
	            $A.test.assertEquals(actionMenuLeftPostionValue, triggerLeftPositonValue,"Menu Item is not alligned properly wrt to trigger it should be at left:"+triggerLeftPositonValue);

	            var disableAttrValue = cmp.find(item1).get("v.disabled");
				$A.test.assertFalse(disableAttrValue,"Menu item 1 should be clickable");

				//check menu is visible by using AURA API
	        	$A.test.assertTrue(actionMenu.get('v.visible'),"Menu should be visible");

	        	$A.test.assertTrue($A.util.hasClass(actionMenu.getElement(),"visible"), "Class name should be uiMenuList visible");

	        	//disable ActionItem1
	        	cmp.find(item1).set("v.disabled", true);
	        	var disableAttrValue = cmp.find(item1).get("v.disabled");
	            $A.test.assertTrue(disableAttrValue,"Menu item 1 should not be clickable");

	            //click actionItem3 and check if label is updated
	            cmp.find(item3).get("e.click").fire();
	            $A.test.addWaitForWithFailureMessage(cmp.find(item3).get('v.label'), function(){return menuLabel.get('v.label')}, "Label should be updated to "+ cmp.find(item3).get('v.label'));
	        }
        ]
    },

    /**
     * Test first item in menuList is focused.
     * TODO: Disabling test in IE7&8, bug W-2320774
     */
    testFocusOnFirstMenuItem:{
    	browsers: ["-IE7","-IE8"],
    	test: function(cmp){
			trigger = cmp.find("trigger");
			trigger.get("e.click").fire();
			var menuItem1 = cmp.find("actionItem1");
			$A.test.addWaitForWithFailureMessage(menuItem1.get('v.label'), function(){return $A.test.getActiveElementText()}, "Focus should be on item 1");
		}
	}
})
<commit_msg>Test fix to avoid flappers<commit_after>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIOloNS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
({
	/**
	 * Test to verify action menu works when interacting with the menu items
	 * which has attachToBody attribute set
	 * using AURA API
	 * TODO: Disabling test in IE7&8, bug W-2320774
	 */
	testActionMenuWithAttachToBodySet:{
		browsers: ["-IE7","-IE8"],
		test: [function(cmp) {
				actionMenu = cmp.find("actionMenuAttachToBody");
	        	menuLabel = cmp.find("triggerAttachToBody");
	        	item1 = "actionItemAttachToBody1";
	        	item2 = "actionItemAttachToBody2";
	        	item3 = "actionItemAttachToBody3";

	        	//check menu is default to hidden by using AURA API
	        	$A.test.assertFalse(actionMenu.get('v.visible'),"Action Menu should not be visible");

	        	//check menu is default to hidden by using DOM API
	        	$A.test.assertTrue($A.util.hasClass(actionMenu.getElement(),"uiMenuList"), "Class name should be just uiMenuList");
	        	$A.test.assertFalse($A.util.hasClass(actionMenu.getElement(),"visible"), "Class name should not contain visible");
	        	menuLabel.get("e.click").fire();

	            //Check if secondItem in the menu is disabled
	            $A.test.addWaitForWithFailureMessage(true, function(){return cmp.find(item2).get("v.disabled");}, "Check if Item2 in the menu is disabled");
			}, function(cmp) {
				//make sure menuItem is attached to body directly and its not attached to uiMenu instead
	            //Test case for W-2181713
				var actionMenuParentElement = actionMenu.getElement().parentNode;
				var bodyElement = document.getElementsByTagName("body")[0];
	            $A.test.assertEquals(actionMenuParentElement, bodyElement,"Menu Item List should be attached to body");

	            //Make sure horizontal alignment of menuItem is correct with reference to triggerElement
	            var actionMenuLeftPostionValue = Math.round(actionMenu.getElement().getBoundingClientRect().left);
	            var triggerLeftPositonValue = Math.round(menuLabel.getElement().getBoundingClientRect().left);
	            $A.test.assertEquals(actionMenuLeftPostionValue, triggerLeftPositonValue,"Menu Item is not alligned properly wrt to trigger it should be at left:"+triggerLeftPositonValue);

	            var disableAttrValue = cmp.find(item1).get("v.disabled");
				$A.test.assertFalse(disableAttrValue,"Menu item 1 should be clickable");

				//check menu is visible by using AURA API
	        	$A.test.assertTrue(actionMenu.get('v.visible'),"Menu should be visible");

	        	$A.test.assertTrue($A.util.hasClass(actionMenu.getElement(),"visible"), "Class name should be uiMenuList visible");

	        	//disable ActionItem1
	        	cmp.find(item1).set("v.disabled", true);
	        	var disableAttrValue = cmp.find(item1).get("v.disabled");
	            $A.test.assertTrue(disableAttrValue,"Menu item 1 should not be clickable");

	            //click actionItem3 and check if label is updated
	            cmp.find(item3).get("e.click").fire();
	            $A.test.addWaitForWithFailureMessage(cmp.find(item3).get('v.label'), function(){return menuLabel.get('v.label')}, "Label should be updated to "+ cmp.find(item3).get('v.label'));
	        }
        ]
    },

    /**
     * Test first item in menuList is focused.
     * TODO: Disabling test in IE7&8, bug W-2320774
     */
    testFocusOnFirstMenuItem:{
    	browsers: ["-IE7","-IE8"],
    	test: function(cmp){
			trigger = cmp.find("trigger");
			trigger.get("e.click").fire();
			var menuItem1 = cmp.find("actionItem1");
			$A.test.addWaitForWithFailureMessage(menuItem1.get('v.label'), function(){return $A.test.getActiveElementText()}, "Focus should be on item 1");
		}
	}
})
<|endoftext|>


<commit_before>const requireQUnit = require('qunit/src/cli/require-qunit');
const FindReporter = require('qunit/src/cli/find-reporter');
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const execa = require('execa');
const qunitRun = require('qunit/src/cli/run');

const EMBER_BIN = 'ember';
exec(EMBER_BIN, ['build']);

require('./yarn-link-local');

global.QUnit = requireQUnit();

let cwd = path.resolve(__dirname, '..');

let tests = glob.sync('dist/@glimmer/**/*-node-test.js', { cwd });

let result = qunitRun(tests, {
  requires: [],
  reporter: FindReporter.findReporter('tap'),
});

console.log(result);

// Executes a command and pipes stdout back to the user.
function exec(command, args) {
  execa.sync(command, args, {
    stdio: 'inherit',
    preferLocal: true,
  });
}
<commit_msg>bin/run-qunit: Remove unused `fs` import<commit_after>const requireQUnit = require('qunit/src/cli/require-qunit');
const FindReporter = require('qunit/src/cli/find-reporter');
const path = require('path');
const glob = require('glob');
const execa = require('execa');
const qunitRun = require('qunit/src/cli/run');

const EMBER_BIN = 'ember';
exec(EMBER_BIN, ['build']);

require('./yarn-link-local');

global.QUnit = requireQUnit();

let cwd = path.resolve(__dirname, '..');

let tests = glob.sync('dist/@glimmer/**/*-node-test.js', { cwd });

let result = qunitRun(tests, {
  requires: [],
  reporter: FindReporter.findReporter('tap'),
});

console.log(result);

// Executes a command and pipes stdout back to the user.
function exec(command, args) {
  execa.sync(command, args, {
    stdio: 'inherit',
    preferLocal: true,
  });
}
<|endoftext|>


<commit_before>import * as React from 'react'
import * as Immutable from 'immutable'

import Course from 'app/elements/course'
import Semester from 'app/elements/semester'

import studentActions from 'app/flux/studentActions'
import {expandYear} from 'app/helpers/semesterName'
import findFirstAvailableSemester from 'app/helpers/findFirstAvailableSemester'
import calculateNextScheduleId from 'app/helpers/calculateNextScheduleId'

var Year = React.createClass({
	canAddSemester() {
		return findFirstAvailableSemester(this.props.student.schedules, this.props.year) <= 5
	},

	addSemester() {
		var nextAvailableSemester = findFirstAvailableSemester(this.props.student.schedules, this.props.year)

		studentActions.addSchedule(this.props.student.id, {
			year: this.props.year, semester: nextAvailableSemester,
			sequence: 1, active: true,
		})
	},

	removeYear() {
		var currentYearSchedules = this.props.student.schedules.filter((s) => s.year === this.props.year)
		var scheduleIds = currentYearSchedules.map(s => s.id)

		studentActions.destroyMultipleSchedules(this.props.student.id, scheduleIds)
	},

	getInitialState() {
		return {
			schedules: Immutable.List()
		}
	},

	componentWillMount() {
		this.componentWillReceiveProps(this.props)
	},

	componentWillReceiveProps(nextProps) {
		let thisYearSchedules = nextProps.student.schedulesByYear.get(nextProps.year)
		let schedules = thisYearSchedules.filter(s => s.active)
		this.setState({schedules})
	},

	shouldComponentUpdate(nextProps, nextState) {
		return nextState.schedules !== this.state.schedules
	},

	render() {
		let terms = this.state.schedules
			.sortBy(schedule => schedule.semester)
			.map((schedule) =>
				React.createElement(Semester, {
					key: schedule.semester,
					student: this.props.student,
					semester: schedule.semester,
					year: this.props.year,
				}))
			.toList()

		let niceYear = expandYear(this.props.year)

		return React.createElement('div', {className: 'year'},
			React.createElement('header', {className: 'year-title'},
				React.createElement('h1', null, niceYear),
				React.createElement('button', {
					className: 'remove-year',
					title: `Remove the year ${niceYear}`,
					onClick: this.removeYear,
				})
			),
			React.createElement('div',
				{className: 'semester-list'},
				terms.toJS()
			),
			React.createElement('button', {
				className: 'add-semester',
				title: 'Add Semester',
				disabled: !this.canAddSemester(),
				onClick: this.addSemester,
			})
		)
	},
})

export default Year
<commit_msg>Use schedule.id in the Semester key<commit_after>import * as React from 'react'
import * as Immutable from 'immutable'

import Course from 'app/elements/course'
import Semester from 'app/elements/semester'

import studentActions from 'app/flux/studentActions'
import {expandYear} from 'app/helpers/semesterName'
import findFirstAvailableSemester from 'app/helpers/findFirstAvailableSemester'
import calculateNextScheduleId from 'app/helpers/calculateNextScheduleId'

var Year = React.createClass({
	canAddSemester() {
		return findFirstAvailableSemester(this.props.student.schedules, this.props.year) <= 5
	},

	addSemester() {
		var nextAvailableSemester = findFirstAvailableSemester(this.props.student.schedules, this.props.year)

		studentActions.addSchedule(this.props.student.id, {
			year: this.props.year, semester: nextAvailableSemester,
			sequence: 1, active: true,
		})
	},

	removeYear() {
		var currentYearSchedules = this.props.student.schedules.filter((s) => s.year === this.props.year)
		var scheduleIds = currentYearSchedules.map(s => s.id)

		studentActions.destroyMultipleSchedules(this.props.student.id, scheduleIds)
	},

	getInitialState() {
		return {
			schedules: Immutable.List()
		}
	},

	componentWillMount() {
		this.componentWillReceiveProps(this.props)
	},

	componentWillReceiveProps(nextProps) {
		let thisYearSchedules = nextProps.student.schedulesByYear.get(nextProps.year)
		let schedules = thisYearSchedules.filter(s => s.active)
		this.setState({schedules})
	},

	shouldComponentUpdate(nextProps, nextState) {
		return nextState.schedules !== this.state.schedules
	},

	render() {
		let terms = this.state.schedules
			.sortBy(schedule => schedule.semester)
			.map((schedule) =>
				React.createElement(Semester, {
					key: `${schedule.year}-${schedule.semester}-${schedule.id}`,
					student: this.props.student,
					semester: schedule.semester,
					year: this.props.year,
				}))
			.toList()

		let niceYear = expandYear(this.props.year)

		return React.createElement('div', {className: 'year'},
			React.createElement('header', {className: 'year-title'},
				React.createElement('h1', null, niceYear),
				React.createElement('button', {
					className: 'remove-year',
					title: `Remove the year ${niceYear}`,
					onClick: this.removeYear,
				})
			),
			React.createElement('div',
				{className: 'semester-list'},
				terms.toJS()
			),
			React.createElement('button', {
				className: 'add-semester',
				title: 'Add Semester',
				disabled: !this.canAddSemester(),
				onClick: this.addSemester,
			})
		)
	},
})

export default Year
<|endoftext|>


<commit_before>// load depedencies
var _ = require('lodash');
var Utils = require('../utils/utils');

var ignore = [
    "the",
    "this",
    "that",
    "they",
    "she",
    "before",
    "could",
    "would",
    "should",
    "think",
    "feel",
    "said",
    "says",
    "will",
    "its",
    "it's",
    "there",
    "their",
    "they're"
];

module.exports = (function() {
    var frequency = function(word, content) {
        var regex = new RegExp(word, 'gi');
        var count = (content.match(regex) || []).length;

        return count;
    };

    function tf(word, content) {
        var tf = frequency(word, content) / wordCount(content);

        return tf;
    };

    function idf(word, docs) {
        var idf = Math.log(docs.length) / containing(word, docs);

        return idf;
    };

    function containing(word, docs) {
        var count = 0;
        for (var i = 0, n = docs.length; i < n; i++) {
            if (frequency(word, docs[i]) > 0) {
                count += 1;
            }
        }

        return count;
    }

    var wordCount = function (content) {
        return Utils.splitWords(content).length;
    }

    var tfidf = function(word, content, docs) {
        if (word.length < 3 || ignore.indexOf(word) !== -1) {
            return 0;
        }

        return tf(word, content) * idf(word, docs);
    };

    return {
        tfidf: tfidf,
        frequency: frequency
    };
})();
<commit_msg>TF-IDF comments<commit_after>// load depedencies
var _ = require('lodash');
var Utils = require('../utils/utils');

// words to ignore
// TODO: add this to the database
var ignore = [
    "the",
    "this",
    "that",
    "they",
    "she",
    "before",
    "could",
    "would",
    "should",
    "think",
    "feel",
    "said",
    "says",
    "will",
    "its",
    "it's",
    "there",
    "their",
    "they're"
];

/*
 * Calcuate Term Frequency--Inverse Document Frequency
 */
module.exports = (function() {
    // calculate frequency
    var frequency = function(word, content) {
        var regex = new RegExp(word, 'gi');
        var count = (content.match(regex) || []).length;

        return count;
    };

    // calculate term frequency
    function tf(word, content) {
        var tf = frequency(word, content) / wordCount(content);

        return tf;
    };

    // calculate inverse document frequency
    function idf(word, docs) {
        var idf = Math.log(docs.length) / containing(word, docs);

        return idf;
    };

    // number of times a word occurs across all documents
    function documentCount(word, docs) {
        var count = 0;
        for (var i = 0, n = docs.length; i < n; i++) {
            if (frequency(word, docs[i]) > 0) {
                count += 1;
            }
        }

        return count;
    }

    // word count in a document
    var wordCount = function (content) {
        return Utils.splitWords(content).length;
    }

    // calculate TF-IDF
    var tfidf = function(word, content, docs) {
        if (word.length < 3 || ignore.indexOf(word) !== -1) {
            return 0;
        }

        return tf(word, content) * idf(word, docs);
    };

    return {
        tfidf: tfidf,
        frequency: frequency
    };
})();
<|endoftext|>


<commit_before>(function(undefined) {
  // The Opal object that is exposed globally
  var Opal = this.Opal = {};

  // Very root class
  function BasicObject(){}

  // Core Object class
  function Object(){}

  // Class' class
  function Class(){}

  // the class of nil
  function NilClass(){}

  // TopScope is used for inheriting constants from the top scope
  var TopScope = function(){};

  // Opal just acts as the top scope
  TopScope.prototype = Opal;

  // To inherit scopes
  Opal.constructor  = TopScope;

  // This is a useful reference to global object inside ruby files
  Opal.global = this;

  // Minify common function calls
  var __hasOwn = Opal.hasOwnProperty;
  var __slice  = Opal.slice = Array.prototype.slice;

  // Generates unique id for every ruby object
  var unique_id = 0;

  // Return next unique id
  Opal.uid = function() {
    return unique_id++;
  };

  // Table holds all class variables
  Opal.cvars = {};

  // Globals table
  Opal.gvars = {};

  /*
   * Create a new constants scope for the given class with the given
   * base. Constants are looked up through their parents, so the base
   * scope will be the outer scope of the new klass.
   */
  function create_scope(base, klass, id) {
    var const_alloc   = function() {};
    var const_scope   = const_alloc.prototype = new base.constructor();
    klass._scope      = const_scope;
    const_scope.base  = klass;
    const_scope.constructor = const_alloc;

    if (id) {
      base[id] = base.constructor[id] = klass;
    }
  }

  /*
    Define a bridged class. Bridged classes will always be in the top level
    scope, and will always be a subclass of Object.
  */
  Opal.bridge = function(name, constructor) {
    var klass = bridge_class(constructor);

    klass._name = name;

    create_scope(Opal, klass, name);

    return klass;
  };

  Opal.klass = function(base, superklass, id, constructor) {
    var klass;
    if (typeof(base) !== 'function') {
      base = base.constructor;
    }

    if (superklass === null) {
      superklass = Object;
    }

    if (__hasOwn.call(base._scope, id)) {
      klass = base._scope[id];
    }
    else {
      klass = boot_class(superklass, constructor);

      klass._name = (base === Object ? id : base._name + '::' + id);

      create_scope(base._scope, klass);

      base[id] = base._scope[id] = klass;

      if (superklass.$inherited) {
        superklass.$inherited(klass);
      }
    }

    return klass;
  };

  // Define new module (or return existing module)
  Opal.module = function(base, id, constructor) {
    var klass;
    if (typeof(base) !== 'function') {
      base = base.constructor;
    }

    if (__hasOwn.call(base._scope, id)) {
      klass = base._scope[id];
    }
    else {
      klass = boot_class(Class, constructor);
      klass._name = (base === Object ? id : base._name + '::' + id);

      klass._included_in = [];

      create_scope(base._scope, klass, id);
    }

    return klass;
  };

  // Utility function to raise a "no block given" error
  var no_block_given = function() {
    throw new Error('no block given');
  };

  // Boot a base class (makes instances).
  var boot_defclass = function(id, constructor, superklass) {
    if (superklass) {
      var ctor           = function() {};
          ctor.prototype = superklass.prototype;

      constructor.prototype = new ctor();
    }

    var prototype = constructor.prototype;

    prototype.constructor = constructor;
    prototype.constructor      = constructor;

    constructor._name         = id;
    constructor._super        = superklass;
    constructor._methods      = [];
    constructor._smethods     = [];

    constructor['$==='] = module_eqq;
    constructor.$to_s = module_to_s;
    constructor.toString = module_to_s;

    Opal[id] = constructor;

    return constructor;
  };

  // Create generic class with given superclass.
  var boot_class = Opal.boot = function(superklass, constructor) {
    var ctor = function() {};
        ctor.prototype = superklass.prototype;

    constructor.prototype = new ctor();
    var prototype = constructor.prototype;

    prototype.constructor = constructor;

    constructor._super        = superklass;
    constructor._methods      = [];
    constructor.constructor   = Class;

    constructor['$===']  = module_eqq;
    constructor.$to_s    = module_to_s;
    constructor.toString = module_to_s;

    constructor['$[]'] = undefined;
    constructor.$call  = undefined;

    var smethods;

    smethods = superklass._smethods.slice();

    constructor._smethods = smethods;
    for (var i = 0, length = smethods.length; i < length; i++) {
      var m = smethods[i];
      constructor[m] = superklass[m];
    }

    var inherited = superklass._inherited;

    if (!inherited) {
      inherited = superklass._inherited = [];
    }

    inherited.push(constructor);

    return constructor;
  };

  var bridge_class = function(constructor) {
    var i, length, m;

    constructor.prototype.constructor = constructor;

    constructor._super        = Object;
    constructor.constructor   = Class;
    constructor._methods      = [];
    constructor._smethods     = [];

    constructor['$===']  = module_eqq;
    constructor.$to_s    = module_to_s;
    constructor.toString = module_to_s;

    var smethods = constructor._smethods = Class._methods.slice();
    for (i = 0, length = smethods.length; i < length; i++) {
      m = smethods[i];
      constructor[m] = Object[m];
    }

    bridged_classes.push(constructor);

    var table = Object.prototype, methods = Object._methods;

    for (i = 0, length = methods.length; i < length; i++) {
      m = methods[i];
      constructor.prototype[m] = table[m];
    }

    constructor._smethods.push('$allocate');

    return constructor;
  };

  Opal.puts = function(a) { console.log(a); };

  // Method missing dispatcher
  Opal.mm = function(mid) {
    var dispatcher = function() {
      var args = __slice.call(arguments);

      if (this.$method_missing) {
        this.$method_missing._p = dispatcher._p;
        return this.$method_missing.apply(this, [mid].concat(args));
      }
      else {
        native_send._p = dispatcher._p;
        return native_send(this, mid, args);
      }
    };

    return dispatcher;
  };

  // send a method to a native object
  var native_send = function(obj, mid, args) {
    var prop, block = native_send._p;
    native_send._p = null;

    if (prop = native_methods[mid]) {
      return prop(obj, args, block);
    }

    prop = obj[mid];

    if (typeof(prop) === "function") {
      prop = prop.apply(obj, args.$to_native());
    }
    else if (mid.charAt(mid.length - 1) === "=") {
      prop = mid.slice(0, mid.length - 1);
      return obj[prop] = args[0];
    }

    if (prop != null) {
      return prop;
    }

    return nil;
  };

  var native_methods = {
    "==": function(obj, args) {
      return obj === args[0];
    },

    "[]": function(obj, args) {
      var prop = obj[args[0]];

      if (prop != null) {
        return prop;
      }

      return nil;
    },

    "[]=": function(obj, args) {
      var value = args[1];

      if (value === nil) {
        value = null;
      }

      return obj[args[0]] = value;
    },

    "respond_to?": function(obj, args) {
      return obj[args[0]] != null;
    },

    "each": function(obj, args, block) {
      var prop;

      if (obj.length === +obj.length) {
        for (var i = 0, len = obj.length; i < len; i++) {
          prop = obj[i];

          if (prop == null) {
            prop = nil;
          }

          block(prop);
        }
      }
      else {
        for (var key in obj) {
          prop = obj[key];

          if (prop == null) {
            prop = nil;
          }

          block(key, prop);
        }
      }

      return obj;
    },

    "to_a": function(obj, args) {
      var result = [];

      for (var i = 0, length = obj.length; i < length; i++) {
        result.push(obj[i]);
      }

      return result;
    },

    "to_h": function(obj) {
      var keys = [], values = {}, value;

      for (var key in obj) {
        keys.push(key);

        if ((value = obj[key]) == null) {
          values[key] = nil;
        }
        else {
          values[key] = value;
        }
      }

      return Opal.hash2(keys, values);
    }
  };

  // Const missing dispatcher
  Opal.cm = function(name) {
    return this.base.$const_missing(name);
  };

  // Arity count error dispatcher
  Opal.ac = function(actual, expected, object, meth) {
    var inspect = ((typeof(object) !== 'function') ? object.constructor._name + '#' : object._name + '.') + meth;
    var msg = '[' + inspect + '] wrong number of arguments(' + actual + ' for ' + expected + ')';
    throw Opal.ArgumentError.$new(msg);
  };

  /*
    Call a ruby method on a ruby object with some arguments:

      var my_array = [1, 2, 3, 4]
      Opal.send(my_array, 'length')     # => 4
      Opal.send(my_array, 'reverse!')   # => [4, 3, 2, 1]

    A missing method will be forwarded to the object via
    method_missing.

    The result of either call with be returned.

    @param [Object] recv the ruby object
    @param [String] mid ruby method to call
  */
  Opal.send = function(recv, mid) {
    var args = __slice.call(arguments, 2),
        func = recv['$' + mid];

    if (func) {
      return func.apply(recv, args);
    }

    return recv.$method_missing.apply(recv, [mid].concat(args));
  };

  Opal.block_send = function(recv, mid, block) {
    var args = __slice.call(arguments, 3),
        func = recv['$' + mid];

    if (func) {
      func._p = block;
      return func.apply(recv, args);
    }

    return recv.$method_missing.apply(recv, [mid].concat(args));
  };

  // Implementation of Class#===
  function module_eqq(object) {
    if (object == null) {
      return false;
    }

    var search = object.constructor;

    while (search) {
      if (search === this) {
        return true;
      }

      search = search._super;
    }

    return false;
  }

  // Implementation of Class#to_s
  function module_to_s() {
    return this._name;
  }

  /**
   * Donate methods for a class/module
   */
  Opal.donate = function(klass, defined, indirect) {
    var methods = klass._methods, included_in = klass._included_in;

    // if (!indirect) {
      klass._methods = methods.concat(defined);
    // }

    if (included_in) {
      for (var i = 0, length = included_in.length; i < length; i++) {
        var includee = included_in[i];
        var dest = includee.prototype;

        for (var j = 0, jj = defined.length; j < jj; j++) {
          var method = defined[j];
          dest[method] = klass.prototype[method];
        }

        if (includee._included_in) {
          Opal.donate(includee, defined, true);
        }
      }
    }
  };

  /*
    Define a singleton method on the given klass

        Opal.defs(Array, '$foo', function() {})

    @param [Function] klass
    @param [String] mid the method_id
    @param [Function] body function body
  */
  Opal.defs = function(klass, mid, body) {
    klass._smethods.push(mid);
    klass[mid] = body;

    var inherited = klass._inherited;
    if (inherited && inherited.length) {
      for (var i = 0, length = inherited.length, subclass; i < length; i++) {
        subclass = inherited[i];
        if (!subclass[mid]) {
          Opal.defs(subclass, mid, body);
        }
      }
    }
  };

  // Defines methods onto Object (which are then donated to bridged classes)
  Object._defn = function (mid, body) {
    this.prototype[mid] = body;
    Opal.donate(this, [mid]);
  };

  // Initialization
  // --------------

  boot_defclass('BasicObject', BasicObject);
  boot_defclass('Object', Object, BasicObject);
  boot_defclass('Class', Class, Object);

  Class.prototype = Function.prototype;

  BasicObject.constructor = Object.constructor = Class.constructor = Class;

  var bridged_classes = Object._included_in = [];

  Opal.base = Object;
  BasicObject._scope = Object._scope = Opal;
  Opal.Module = Opal.Class;
  Opal.Kernel = Object;

  create_scope(Opal, Class);

  Object.prototype.toString = function() {
    return this.$to_s();
  };

  Opal.top = new Object;

  Opal.klass(Object, Object, 'NilClass', NilClass);
  var nil = Opal.nil = new NilClass;
  nil.call = nil.apply = function() { throw Opal.LocalJumpError.$new('no block given'); };

  Opal.breaker  = new Error('unexpected break');

  Opal.bridge('Array', Array);
  Opal.bridge('Boolean', Boolean);
  Opal.bridge('Numeric', Number);
  Opal.bridge('String', String);
  Opal.bridge('Proc', Function);
  Opal.bridge('Exception', Error);
  Opal.bridge('Regexp', RegExp);
  Opal.bridge('Time', Date);
}).call(this);
<commit_msg>This is not the comparison you are looking for<commit_after>(function(undefined) {
  // The Opal object that is exposed globally
  var Opal = this.Opal = {};

  // Very root class
  function BasicObject(){}

  // Core Object class
  function Object(){}

  // Class' class
  function Class(){}

  // the class of nil
  function NilClass(){}

  // TopScope is used for inheriting constants from the top scope
  var TopScope = function(){};

  // Opal just acts as the top scope
  TopScope.prototype = Opal;

  // To inherit scopes
  Opal.constructor  = TopScope;

  // This is a useful reference to global object inside ruby files
  Opal.global = this;

  // Minify common function calls
  var __hasOwn = Opal.hasOwnProperty;
  var __slice  = Opal.slice = Array.prototype.slice;

  // Generates unique id for every ruby object
  var unique_id = 0;

  // Return next unique id
  Opal.uid = function() {
    return unique_id++;
  };

  // Table holds all class variables
  Opal.cvars = {};

  // Globals table
  Opal.gvars = {};

  /*
   * Create a new constants scope for the given class with the given
   * base. Constants are looked up through their parents, so the base
   * scope will be the outer scope of the new klass.
   */
  function create_scope(base, klass, id) {
    var const_alloc   = function() {};
    var const_scope   = const_alloc.prototype = new base.constructor();
    klass._scope      = const_scope;
    const_scope.base  = klass;
    const_scope.constructor = const_alloc;

    if (id) {
      base[id] = base.constructor[id] = klass;
    }
  }

  /*
    Define a bridged class. Bridged classes will always be in the top level
    scope, and will always be a subclass of Object.
  */
  Opal.bridge = function(name, constructor) {
    var klass = bridge_class(constructor);

    klass._name = name;

    create_scope(Opal, klass, name);

    return klass;
  };

  Opal.klass = function(base, superklass, id, constructor) {
    var klass;
    if (typeof(base) !== 'function') {
      base = base.constructor;
    }

    if (superklass === null) {
      superklass = Object;
    }

    if (__hasOwn.call(base._scope, id)) {
      klass = base._scope[id];
    }
    else {
      klass = boot_class(superklass, constructor);

      klass._name = (base === Object ? id : base._name + '::' + id);

      create_scope(base._scope, klass);

      base[id] = base._scope[id] = klass;

      if (superklass.$inherited) {
        superklass.$inherited(klass);
      }
    }

    return klass;
  };

  // Define new module (or return existing module)
  Opal.module = function(base, id, constructor) {
    var klass;
    if (typeof(base) !== 'function') {
      base = base.constructor;
    }

    if (__hasOwn.call(base._scope, id)) {
      klass = base._scope[id];
    }
    else {
      klass = boot_class(Class, constructor);
      klass._name = (base === Object ? id : base._name + '::' + id);

      klass._included_in = [];

      create_scope(base._scope, klass, id);
    }

    return klass;
  };

  // Utility function to raise a "no block given" error
  var no_block_given = function() {
    throw new Error('no block given');
  };

  // Boot a base class (makes instances).
  var boot_defclass = function(id, constructor, superklass) {
    if (superklass) {
      var ctor           = function() {};
          ctor.prototype = superklass.prototype;

      constructor.prototype = new ctor();
    }

    var prototype = constructor.prototype;

    prototype.constructor = constructor;
    prototype.constructor      = constructor;

    constructor._name         = id;
    constructor._super        = superklass;
    constructor._methods      = [];
    constructor._smethods     = [];

    constructor['$==='] = module_eqq;
    constructor.$to_s = module_to_s;
    constructor.toString = module_to_s;

    Opal[id] = constructor;

    return constructor;
  };

  // Create generic class with given superclass.
  var boot_class = Opal.boot = function(superklass, constructor) {
    var ctor = function() {};
        ctor.prototype = superklass.prototype;

    constructor.prototype = new ctor();
    var prototype = constructor.prototype;

    prototype.constructor = constructor;

    constructor._super        = superklass;
    constructor._methods      = [];
    constructor.constructor   = Class;

    constructor['$===']  = module_eqq;
    constructor.$to_s    = module_to_s;
    constructor.toString = module_to_s;

    constructor['$[]'] = undefined;
    constructor.$call  = undefined;

    var smethods;

    smethods = superklass._smethods.slice();

    constructor._smethods = smethods;
    for (var i = 0, length = smethods.length; i < length; i++) {
      var m = smethods[i];
      constructor[m] = superklass[m];
    }

    var inherited = superklass._inherited;

    if (!inherited) {
      inherited = superklass._inherited = [];
    }

    inherited.push(constructor);

    return constructor;
  };

  var bridge_class = function(constructor) {
    var i, length, m;

    constructor.prototype.constructor = constructor;

    constructor._super        = Object;
    constructor.constructor   = Class;
    constructor._methods      = [];
    constructor._smethods     = [];

    constructor['$===']  = module_eqq;
    constructor.$to_s    = module_to_s;
    constructor.toString = module_to_s;

    var smethods = constructor._smethods = Class._methods.slice();
    for (i = 0, length = smethods.length; i < length; i++) {
      m = smethods[i];
      constructor[m] = Object[m];
    }

    bridged_classes.push(constructor);

    var table = Object.prototype, methods = Object._methods;

    for (i = 0, length = methods.length; i < length; i++) {
      m = methods[i];
      constructor.prototype[m] = table[m];
    }

    constructor._smethods.push('$allocate');

    return constructor;
  };

  Opal.puts = function(a) { console.log(a); };

  // Method missing dispatcher
  Opal.mm = function(mid) {
    var dispatcher = function() {
      var args = __slice.call(arguments);

      if (this.$method_missing) {
        this.$method_missing._p = dispatcher._p;
        return this.$method_missing.apply(this, [mid].concat(args));
      }
      else {
        native_send._p = dispatcher._p;
        return native_send(this, mid, args);
      }
    };

    return dispatcher;
  };

  // send a method to a native object
  var native_send = function(obj, mid, args) {
    var prop, block = native_send._p;
    native_send._p = null;

    if ( (prop = native_methods[mid]) ) {
      return prop(obj, args, block);
    }

    prop = obj[mid];

    if (typeof(prop) === "function") {
      prop = prop.apply(obj, args.$to_native());
    }
    else if (mid.charAt(mid.length - 1) === "=") {
      prop = mid.slice(0, mid.length - 1);
      return obj[prop] = args[0];
    }

    if (prop != null) {
      return prop;
    }

    return nil;
  };

  var native_methods = {
    "==": function(obj, args) {
      return obj === args[0];
    },

    "[]": function(obj, args) {
      var prop = obj[args[0]];

      if (prop != null) {
        return prop;
      }

      return nil;
    },

    "[]=": function(obj, args) {
      var value = args[1];

      if (value === nil) {
        value = null;
      }

      return obj[args[0]] = value;
    },

    "respond_to?": function(obj, args) {
      return obj[args[0]] != null;
    },

    "each": function(obj, args, block) {
      var prop;

      if (obj.length === +obj.length) {
        for (var i = 0, len = obj.length; i < len; i++) {
          prop = obj[i];

          if (prop == null) {
            prop = nil;
          }

          block(prop);
        }
      }
      else {
        for (var key in obj) {
          prop = obj[key];

          if (prop == null) {
            prop = nil;
          }

          block(key, prop);
        }
      }

      return obj;
    },

    "to_a": function(obj, args) {
      var result = [];

      for (var i = 0, length = obj.length; i < length; i++) {
        result.push(obj[i]);
      }

      return result;
    },

    "to_h": function(obj) {
      var keys = [], values = {}, value;

      for (var key in obj) {
        keys.push(key);

        if ((value = obj[key]) == null) {
          values[key] = nil;
        }
        else {
          values[key] = value;
        }
      }

      return Opal.hash2(keys, values);
    }
  };

  // Const missing dispatcher
  Opal.cm = function(name) {
    return this.base.$const_missing(name);
  };

  // Arity count error dispatcher
  Opal.ac = function(actual, expected, object, meth) {
    var inspect = ((typeof(object) !== 'function') ? object.constructor._name + '#' : object._name + '.') + meth;
    var msg = '[' + inspect + '] wrong number of arguments(' + actual + ' for ' + expected + ')';
    throw Opal.ArgumentError.$new(msg);
  };

  /*
    Call a ruby method on a ruby object with some arguments:

      var my_array = [1, 2, 3, 4]
      Opal.send(my_array, 'length')     # => 4
      Opal.send(my_array, 'reverse!')   # => [4, 3, 2, 1]

    A missing method will be forwarded to the object via
    method_missing.

    The result of either call with be returned.

    @param [Object] recv the ruby object
    @param [String] mid ruby method to call
  */
  Opal.send = function(recv, mid) {
    var args = __slice.call(arguments, 2),
        func = recv['$' + mid];

    if (func) {
      return func.apply(recv, args);
    }

    return recv.$method_missing.apply(recv, [mid].concat(args));
  };

  Opal.block_send = function(recv, mid, block) {
    var args = __slice.call(arguments, 3),
        func = recv['$' + mid];

    if (func) {
      func._p = block;
      return func.apply(recv, args);
    }

    return recv.$method_missing.apply(recv, [mid].concat(args));
  };

  // Implementation of Class#===
  function module_eqq(object) {
    if (object == null) {
      return false;
    }

    var search = object.constructor;

    while (search) {
      if (search === this) {
        return true;
      }

      search = search._super;
    }

    return false;
  }

  // Implementation of Class#to_s
  function module_to_s() {
    return this._name;
  }

  /**
   * Donate methods for a class/module
   */
  Opal.donate = function(klass, defined, indirect) {
    var methods = klass._methods, included_in = klass._included_in;

    // if (!indirect) {
      klass._methods = methods.concat(defined);
    // }

    if (included_in) {
      for (var i = 0, length = included_in.length; i < length; i++) {
        var includee = included_in[i];
        var dest = includee.prototype;

        for (var j = 0, jj = defined.length; j < jj; j++) {
          var method = defined[j];
          dest[method] = klass.prototype[method];
        }

        if (includee._included_in) {
          Opal.donate(includee, defined, true);
        }
      }
    }
  };

  /*
    Define a singleton method on the given klass

        Opal.defs(Array, '$foo', function() {})

    @param [Function] klass
    @param [String] mid the method_id
    @param [Function] body function body
  */
  Opal.defs = function(klass, mid, body) {
    klass._smethods.push(mid);
    klass[mid] = body;

    var inherited = klass._inherited;
    if (inherited && inherited.length) {
      for (var i = 0, length = inherited.length, subclass; i < length; i++) {
        subclass = inherited[i];
        if (!subclass[mid]) {
          Opal.defs(subclass, mid, body);
        }
      }
    }
  };

  // Defines methods onto Object (which are then donated to bridged classes)
  Object._defn = function (mid, body) {
    this.prototype[mid] = body;
    Opal.donate(this, [mid]);
  };

  // Initialization
  // --------------

  boot_defclass('BasicObject', BasicObject);
  boot_defclass('Object', Object, BasicObject);
  boot_defclass('Class', Class, Object);

  Class.prototype = Function.prototype;

  BasicObject.constructor = Object.constructor = Class.constructor = Class;

  var bridged_classes = Object._included_in = [];

  Opal.base = Object;
  BasicObject._scope = Object._scope = Opal;
  Opal.Module = Opal.Class;
  Opal.Kernel = Object;

  create_scope(Opal, Class);

  Object.prototype.toString = function() {
    return this.$to_s();
  };

  Opal.top = new Object;

  Opal.klass(Object, Object, 'NilClass', NilClass);
  var nil = Opal.nil = new NilClass;
  nil.call = nil.apply = function() { throw Opal.LocalJumpError.$new('no block given'); };

  Opal.breaker  = new Error('unexpected break');

  Opal.bridge('Array', Array);
  Opal.bridge('Boolean', Boolean);
  Opal.bridge('Numeric', Number);
  Opal.bridge('String', String);
  Opal.bridge('Proc', Function);
  Opal.bridge('Exception', Error);
  Opal.bridge('Regexp', RegExp);
  Opal.bridge('Time', Date);
}).call(this);
<|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla Skywriter.
 *
 * The Initial Developer of the Original Code is
 * Mozilla.
 * Portions created by the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Julian Viereck (julian.viereck@gmail.com)
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {
"use strict";

// If you're developing a new keymapping and want to get an idea what's going
// on, then enable debugging.
var DEBUG = false;

function StateHandler(keymapping) {
    this.keymapping = this.$buildKeymappingRegex(keymapping);
}

StateHandler.prototype = {
    /*
     * Build the RegExp from the keymapping as RegExp can't stored directly
     * in the metadata JSON and as the RegExp used to match the keys/buffer
     * need to be adapted.
     */
    $buildKeymappingRegex: function(keymapping) {
        for (var state in keymapping) {
            this.$buildBindingsRegex(keymapping[state]);
        }
        return keymapping;
    },

    $buildBindingsRegex: function(bindings) {
        // Escape a given Regex string.
        bindings.forEach(function(binding) {
            if (binding.key) {
                binding.key = new RegExp('^' + binding.key + '$');
            } else if (Array.isArray(binding.regex)) {
                if (!('key' in binding))
                  binding.key = new RegExp('^' + binding.regex[1] + '$');
                binding.regex = new RegExp(binding.regex.join('') + '$');
            } else if (binding.regex) {
                binding.regex = new RegExp(binding.regex + '$');
            }
        });
    },

    $composeBuffer: function(data, hashId, key, e) {
        // Initialize the data object.
        if (data.state == null || data.buffer == null) {
            data.state = "start";
            data.buffer = "";
        }

        var keyArray = [];
        if (hashId & 1) keyArray.push("ctrl");
        if (hashId & 8) keyArray.push("command");
        if (hashId & 2) keyArray.push("option");
        if (hashId & 4) keyArray.push("shift");
        if (key)        keyArray.push(key);

        var symbolicName = keyArray.join("-");
        var bufferToUse = data.buffer + symbolicName;

        // Don't add the symbolic name to the key buffer if the alt_ key is
        // part of the symbolic name. If it starts with alt_, this means
        // that the user hit an alt keycombo and there will be a single,
        // new character detected after this event, which then will be
        // added to the buffer (e.g. alt_j will result in ∆).
        //
        // We test for 2 and not for & 2 as we only want to exclude the case where
        // the option key is pressed alone.
        if (hashId != 2) {
            data.buffer = bufferToUse;
        }

        var bufferObj = {
            bufferToUse: bufferToUse,
            symbolicName: symbolicName,
        };

        if (e) {
            bufferObj.keyIdentifier = e.keyIdentifier
        }

        return bufferObj;
    },

    $find: function(data, buffer, symbolicName, hashId, key, keyIdentifier) {
        // Holds the command to execute and the args if a command matched.
        var result = {};

        // Loop over all the bindings of the keymap until a match is found.
        this.keymapping[data.state].some(function(binding) {
            var match;

            // Check if the key matches.
            if (binding.key && !binding.key.test(symbolicName)) {
                return false;
            }

            // Check if the regex matches.
            if (binding.regex && !(match = binding.regex.exec(buffer))) {
                return false;
            }

            // Check if the match function matches.
            if (binding.match && !binding.match(buffer, hashId, key, symbolicName, keyIdentifier)) {
                return false;
            }

            // Check for disallowed matches.
            if (binding.disallowMatches) {
                for (var i = 0; i < binding.disallowMatches.length; i++) {
                    if (!!match[binding.disallowMatches[i]]) {
                        return false;
                    }
                }
            }

            // If there is a command to execute, then figure out the
            // command and the arguments.
            if (binding.exec) {
                result.command = binding.exec;

                // Build the arguments.
                if (binding.params) {
                    var value;
                    result.args = {};
                    binding.params.forEach(function(param) {
                        if (param.match != null && match != null) {
                            value = match[param.match] || param.defaultValue;
                        } else {
                            value = param.defaultValue;
                        }

                        if (param.type === 'number') {
                            value = parseInt(value);
                        }

                        result.args[param.name] = value;
                    });
                }
                data.buffer = "";
            }

            // Handle the 'then' property.
            if (binding.then) {
                data.state = binding.then;
                data.buffer = "";
            }

            // If no command is set, then execute the "null" fake command.
            if (result.command == null) {
                result.command = "null";
            }

            if (DEBUG) {
                console.log("KeyboardStateMapper#find", binding);
            }
            return true;
        });

        if (result.command) {
            return result;
        } else {
            data.buffer = "";
            return false;
        }
    },

    /*
     * This function is called by keyBinding.
     */
    handleKeyboard: function(data, hashId, key, keyCode, e) {
        if (hashId == -1)
            hashId = 0
        // If we pressed any command key but no other key, then ignore the input.
        // Otherwise "shift-" is added to the buffer, and later on "shift-g"
        // which results in "shift-shift-g" which doesn't make sense.
        if (hashId != 0 && (key == "" || key == String.fromCharCode(0))) {
            return null;
        }

        // Compute the current value of the keyboard input buffer.
        var r = this.$composeBuffer(data, hashId, key, e);
        var buffer = r.bufferToUse;
        var symbolicName = r.symbolicName;
        var keyId = r.keyIdentifier;

        r = this.$find(data, buffer, symbolicName, hashId, key, keyId);
        if (DEBUG) {
            console.log("KeyboardStateMapper#match", buffer, symbolicName, r);
        }

        return r;
    }
}

/*
 * This is a useful matching function and therefore is defined here so that
 * users of KeyboardStateMapper can use it.
 *
 * @return boolean
 *          If no command key (Command|Option|Shift|Ctrl) is pressed, it
 *          returns true. If the only the Shift key is pressed + a character
 *          true is returned as well. Otherwise, false is returned.
 *          Summing up, the function returns true whenever the user typed
 *          a normal character on the keyboard and no shortcut.
 */
exports.matchCharacterOnly = function(buffer, hashId, key, symbolicName) {
    // If no command keys are pressed, then catch the input.
    if (hashId == 0) {
        return true;
    }
    // If only the shift key is pressed and a character key, then
    // catch that input as well.
    else if ((hashId == 4) && key.length == 1) {
        return true;
    }
    // Otherwise, we let the input got through.
    else {
        return false;
    }
};

exports.StateHandler = StateHandler;
});
<commit_msg>fix trailing "," in object literal<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla Skywriter.
 *
 * The Initial Developer of the Original Code is
 * Mozilla.
 * Portions created by the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Julian Viereck (julian.viereck@gmail.com)
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {
"use strict";

// If you're developing a new keymapping and want to get an idea what's going
// on, then enable debugging.
var DEBUG = false;

function StateHandler(keymapping) {
    this.keymapping = this.$buildKeymappingRegex(keymapping);
}

StateHandler.prototype = {
    /*
     * Build the RegExp from the keymapping as RegExp can't stored directly
     * in the metadata JSON and as the RegExp used to match the keys/buffer
     * need to be adapted.
     */
    $buildKeymappingRegex: function(keymapping) {
        for (var state in keymapping) {
            this.$buildBindingsRegex(keymapping[state]);
        }
        return keymapping;
    },

    $buildBindingsRegex: function(bindings) {
        // Escape a given Regex string.
        bindings.forEach(function(binding) {
            if (binding.key) {
                binding.key = new RegExp('^' + binding.key + '$');
            } else if (Array.isArray(binding.regex)) {
                if (!('key' in binding))
                  binding.key = new RegExp('^' + binding.regex[1] + '$');
                binding.regex = new RegExp(binding.regex.join('') + '$');
            } else if (binding.regex) {
                binding.regex = new RegExp(binding.regex + '$');
            }
        });
    },

    $composeBuffer: function(data, hashId, key, e) {
        // Initialize the data object.
        if (data.state == null || data.buffer == null) {
            data.state = "start";
            data.buffer = "";
        }

        var keyArray = [];
        if (hashId & 1) keyArray.push("ctrl");
        if (hashId & 8) keyArray.push("command");
        if (hashId & 2) keyArray.push("option");
        if (hashId & 4) keyArray.push("shift");
        if (key)        keyArray.push(key);

        var symbolicName = keyArray.join("-");
        var bufferToUse = data.buffer + symbolicName;

        // Don't add the symbolic name to the key buffer if the alt_ key is
        // part of the symbolic name. If it starts with alt_, this means
        // that the user hit an alt keycombo and there will be a single,
        // new character detected after this event, which then will be
        // added to the buffer (e.g. alt_j will result in ∆).
        //
        // We test for 2 and not for & 2 as we only want to exclude the case where
        // the option key is pressed alone.
        if (hashId != 2) {
            data.buffer = bufferToUse;
        }

        var bufferObj = {
            bufferToUse: bufferToUse,
            symbolicName: symbolicName
        };

        if (e) {
            bufferObj.keyIdentifier = e.keyIdentifier
        }

        return bufferObj;
    },

    $find: function(data, buffer, symbolicName, hashId, key, keyIdentifier) {
        // Holds the command to execute and the args if a command matched.
        var result = {};

        // Loop over all the bindings of the keymap until a match is found.
        this.keymapping[data.state].some(function(binding) {
            var match;

            // Check if the key matches.
            if (binding.key && !binding.key.test(symbolicName)) {
                return false;
            }

            // Check if the regex matches.
            if (binding.regex && !(match = binding.regex.exec(buffer))) {
                return false;
            }

            // Check if the match function matches.
            if (binding.match && !binding.match(buffer, hashId, key, symbolicName, keyIdentifier)) {
                return false;
            }

            // Check for disallowed matches.
            if (binding.disallowMatches) {
                for (var i = 0; i < binding.disallowMatches.length; i++) {
                    if (!!match[binding.disallowMatches[i]]) {
                        return false;
                    }
                }
            }

            // If there is a command to execute, then figure out the
            // command and the arguments.
            if (binding.exec) {
                result.command = binding.exec;

                // Build the arguments.
                if (binding.params) {
                    var value;
                    result.args = {};
                    binding.params.forEach(function(param) {
                        if (param.match != null && match != null) {
                            value = match[param.match] || param.defaultValue;
                        } else {
                            value = param.defaultValue;
                        }

                        if (param.type === 'number') {
                            value = parseInt(value);
                        }

                        result.args[param.name] = value;
                    });
                }
                data.buffer = "";
            }

            // Handle the 'then' property.
            if (binding.then) {
                data.state = binding.then;
                data.buffer = "";
            }

            // If no command is set, then execute the "null" fake command.
            if (result.command == null) {
                result.command = "null";
            }

            if (DEBUG) {
                console.log("KeyboardStateMapper#find", binding);
            }
            return true;
        });

        if (result.command) {
            return result;
        } else {
            data.buffer = "";
            return false;
        }
    },

    /*
     * This function is called by keyBinding.
     */
    handleKeyboard: function(data, hashId, key, keyCode, e) {
        if (hashId == -1)
            hashId = 0
        // If we pressed any command key but no other key, then ignore the input.
        // Otherwise "shift-" is added to the buffer, and later on "shift-g"
        // which results in "shift-shift-g" which doesn't make sense.
        if (hashId != 0 && (key == "" || key == String.fromCharCode(0))) {
            return null;
        }

        // Compute the current value of the keyboard input buffer.
        var r = this.$composeBuffer(data, hashId, key, e);
        var buffer = r.bufferToUse;
        var symbolicName = r.symbolicName;
        var keyId = r.keyIdentifier;

        r = this.$find(data, buffer, symbolicName, hashId, key, keyId);
        if (DEBUG) {
            console.log("KeyboardStateMapper#match", buffer, symbolicName, r);
        }

        return r;
    }
}

/*
 * This is a useful matching function and therefore is defined here so that
 * users of KeyboardStateMapper can use it.
 *
 * @return boolean
 *          If no command key (Command|Option|Shift|Ctrl) is pressed, it
 *          returns true. If the only the Shift key is pressed + a character
 *          true is returned as well. Otherwise, false is returned.
 *          Summing up, the function returns true whenever the user typed
 *          a normal character on the keyboard and no shortcut.
 */
exports.matchCharacterOnly = function(buffer, hashId, key, symbolicName) {
    // If no command keys are pressed, then catch the input.
    if (hashId == 0) {
        return true;
    }
    // If only the shift key is pressed and a character key, then
    // catch that input as well.
    else if ((hashId == 4) && key.length == 1) {
        return true;
    }
    // Otherwise, we let the input got through.
    else {
        return false;
    }
};

exports.StateHandler = StateHandler;
});
<|endoftext|>


<commit_before>const steps = [];
let callCount = 0;

function trace(step) {
  const { type, context } = step;

  if (type === 'enter') {
    callCount++;
  }

  steps.push({
    callCount,
    ...step,
  });

  return context;
}

function binarySearch(list, item) {
  let outerContext = trace({
    type: 'enter',
    line: 0,
    context: { list, item },
  });

  let low = 0;
  outerContext = trace({
    type: 'assign',
    line: 1,
    context: {
      ...outerContext,
      low,
    },
  });

  let high = list.length - 1;
  outerContext = trace({
    type: 'assign',
    line: 2,
    context: {
      ...outerContext,
      high,
    }
  });

  // TODO: Keep this context inside while block, but udpate low/high in the
  // outer context
  let innerContext = { ...outerContext };
  while (trace({
    type: 'compare',
    line: 4,
    context: innerContext,
    compared: ['low', 'high'],
  }) && low <= high) {
    const mid = Math.round((low + high) / 2);
    innerContext = trace({
      type: 'assign',
      line: 5,
      context: {
        ...innerContext,
        mid,
      },
    });

    const guess = list[mid];
    innerContext = trace({
      type: 'assign',
      line: 6,
      context: {
        ...innerContext,
        guess,
      },
    });

    trace({
      type: 'compare',
      line: 8,
      context: innerContext,
      compared: ['guess', 'item'],
    });
    if (guess === item) {
      trace({
        type: 'return',
        line: 9,
        context: innerContext,
        returnValue: mid,
      });
      return mid;
    }

    trace({
      type: 'compare',
      line: 11,
      context: innerContext,
      compared: ['guess', 'item'],
    });
    if (guess > item) {
      high = mid - 1;
      innerContext = trace({
        type: 'assign',
        line: 12,
        context: {
          ...innerContext,
          high,
        }
      });
    } else {
      low = mid + 1;
      innerContext = trace({
        type: 'assign',
        line: 14,
        context: {
          ...innerContext,
          low,
        }
      });
    }
  }

  trace({
    type: 'return',
    line: 18,
    context: outerContext,
    returnValue: null,
  });
  return null;
}

const items = [
  'bear', 'cat', 'cow', 'dog', 'fox', 'pig', 'rat',
];

binarySearch(items, 'bear');

const React = require('react');
const ReactDOM = require('react-dom');

const fnDef =
`function binarySearch(list, item) {
  let low = 0;
  let high = list.length - 1;

  while (low <= high) {
    const mid = Math.round(low + high);
    const guess = list[mid];

    if (guess === item) {
      return mid;
    }
    if (guess > item) {
      high = mid - 1;
    } else {
      low = mid + 1;
    }
  }

  return null;
}`;

function SourceCode({
  def,
  line,
}) {
  return (

        {def.split('\n').map((fnLine, i) =>

            {fnLine}

        )}

  );
}

SourceCode.propTypes = {
  def: React.PropTypes.string.isRequired,
  line: React.PropTypes.number.isRequired,
};

function Preview({
  context,
}) {
  return (

      {Object.keys(context).map(key =>

          {key} = {JSON.stringify(context[key])}

      )}

  );
}

Preview.propTypes = {
  context: React.PropTypes.object.isRequired,
};

class App extends React.Component {
  render() {
    const { steps, step, onPrev, onNext } = this.props;
    const { line, context } = steps[step];

    return (

          <button disabled={step <= 0} onClick={onPrev}>back</button>
          <button disabled={step >= steps.length - 1} onClick={onNext}>forward</button>

        <SourceCode
          def={fnDef}
          line={line}
        />
        <Preview
          context={context}
        />

    );
  }
}

App.propTypes = {
  steps: React.PropTypes.array.isRequired,
  step: React.PropTypes.number.isRequired,
  onPrev: React.PropTypes.func.isRequired,
  onNext: React.PropTypes.func.isRequired,
};

/* global document */
const container = document.body.appendChild(document.createElement('div'));
let currentStep = 0;

function render(step) {
  ReactDOM.render((
    <App
      steps={steps}
      step={step}
      onPrev={() => {
        render(currentStep -= 1);
      }}
      onNext={() => {
        render(currentStep += 1);
      }}
    />
  ), container);
}

render(currentStep);
<commit_msg>Simplify tracing<commit_after>const steps = [];
let callCount = 0;

function trace(step) {
  const { type, context } = step;

  if (type === 'enter') {
    callCount++;
  }

  steps.push({
    callCount,
    ...step,
  });

  return context;
}

function binarySearch(list, item) {
  trace({
    type: 'enter',
    line: 0,
    context: { list, item },
  });

  let low = 0;
  trace({
    type: 'assign',
    line: 1,
    context: { list, item, low },
  });

  let high = list.length - 1;
  trace({
    type: 'assign',
    line: 2,
    context: { list, item, low, high },
  });

  while (trace({
    type: 'compare',
    line: 4,
    context: { list, item, low, high },
    compared: ['low', 'high'],
  }) && low <= high) {
    const mid = Math.round((low + high) / 2);
    trace({
      type: 'assign',
      line: 5,
      context: { list, item, low, high, mid },
    });

    const guess = list[mid];
    trace({
      type: 'assign',
      line: 6,
      context: { list, item, low, high, mid, guess },
    });

    trace({
      type: 'compare',
      line: 8,
      context: { list, item, low, high, mid, guess },
      compared: ['guess', 'item'],
    });
    if (guess === item) {
      trace({
        type: 'return',
        line: 9,
        context: { list, item, low, high, mid, guess },
        returnValue: mid,
      });
      return mid;
    }

    trace({
      type: 'compare',
      line: 11,
      context: { list, item, low, high, mid, guess },
      compared: ['guess', 'item'],
    });
    if (guess > item) {
      high = mid - 1;
      trace({
        type: 'assign',
        line: 12,
        context: { list, item, low, high, mid, guess },
      });
    } else {
      low = mid + 1;
      trace({
        type: 'assign',
        line: 14,
        context: { list, item, low, high, mid, guess },
      });
    }
  }

  trace({
    type: 'return',
    line: 18,
    context: { list, item, low, high },
    returnValue: null,
  });
  return null;
}

const items = [
  'bear', 'cat', 'cow', 'dog', 'fox', 'pig', 'rat',
];

binarySearch(items, 'bear');

const React = require('react');
const ReactDOM = require('react-dom');

const fnDef =
`function binarySearch(list, item) {
  let low = 0;
  let high = list.length - 1;

  while (low <= high) {
    const mid = Math.round((low + high) / 2);
    const guess = list[mid];

    if (guess === item) {
      return mid;
    }
    if (guess > item) {
      high = mid - 1;
    } else {
      low = mid + 1;
    }
  }

  return null;
}`;

function SourceCode({
  def,
  line,
}) {
  return (

        {def.split('\n').map((fnLine, i) =>

            {fnLine}

        )}

  );
}

SourceCode.propTypes = {
  def: React.PropTypes.string.isRequired,
  line: React.PropTypes.number.isRequired,
};

function Preview({
  context,
}) {
  return (

      {Object.keys(context).map(key =>

          {key} = {JSON.stringify(context[key])}

      )}

  );
}

Preview.propTypes = {
  context: React.PropTypes.object.isRequired,
};

class App extends React.Component {
  render() {
    const { steps, step, onPrev, onNext } = this.props;
    const { line, context } = steps[step];

    return (

          <button disabled={step <= 0} onClick={onPrev}>back</button>
          <button disabled={step >= steps.length - 1} onClick={onNext}>forward</button>

        <SourceCode
          def={fnDef}
          line={line}
        />
        <Preview
          context={context}
        />

    );
  }
}

App.propTypes = {
  steps: React.PropTypes.array.isRequired,
  step: React.PropTypes.number.isRequired,
  onPrev: React.PropTypes.func.isRequired,
  onNext: React.PropTypes.func.isRequired,
};

/* global document */
const container = document.body.appendChild(document.createElement('div'));
let currentStep = 0;

function render(step) {
  ReactDOM.render((
    <App
      steps={steps}
      step={step}
      onPrev={() => {
        render(currentStep -= 1);
      }}
      onNext={() => {
        render(currentStep += 1);
      }}
    />
  ), container);
}

render(currentStep);
<|endoftext|>