<commit_before>/**
 * @license
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * 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 CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var StringProperty = Model.create({
  extendsModel: 'Property',

  name:  'StringProperty',
  help:  "Describes a properties of type String.",

  properties: [
    {
      name: 'displayHeight',
      type: 'int',
      displayWidth: 8,
      defaultValue: 1,
      help: 'The display height of the property.'
    },
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'String',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 70,
      defaultValue: 'String',
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      defaultValueFn: function() { return this.displayHeight > 1 ? 'TextAreaView' : 'TextFieldView'; }
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    }
  ]
});

var BooleanProperty = Model.create({
  extendsModel: 'Property',

  name:  'BooleanProperty',
  help:  "Describes a properties of type String.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Boolean',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 70,
      defaultValue: 'bool',
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      defaultValue: 'BooleanView'
    },
    {
      name: 'defaultValue',
      defaultValue: false
    },
    {
      name: 'preSet',
      defaultValue: function (v) { return !!v; },
      help: 'The Java type of this property.'
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    }
  ]
});

/*
  preSet: function (d) {
  return typeof d === 'string' ? new Date(d) : d;
  },
  tableFormatter: function(d) {
  return d.toDateString();
  },
  valueFactory: function() { return new Date(); }

*/

var DateProperty = Model.create({
  extendsModel: 'Property',

  name:  'DateProperty',
  help:  "Describes a properties of type String.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Date',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'displayWidth',
      defaultValue: 50
    },
    {
      name: 'javaType',
      type: 'String',
      defaultValue: 'Date',
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      // TODO: create custom DateView
      defaultValue: 'DateFieldView'
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    },
    {
      name: 'preSet',
      defaultValue: function (d) {
        return typeof d === 'string' ? new Date(d) : d;
      }
    },
    {
      name: 'tableFormatter',
      defaultValue2: function(d) {
        return d.toDateString();
      },
      defaultValue: function(d) {
        return d.toRelativeDateString();
      }
    }
  ]
});

var DateTimeProperty = Model.create({
  extendsModel: 'DateProperty',

  name:  'DateTimeProperty',
  help:  "Describes a properties of type String.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 25,
      defaultValue: 'datetime',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'preSet',
      defaultValue: function(d) {
        if ( typeof d === 'number' ) return new Date(d);
        if ( typeof d === 'string' ) return new Date(d);
        return d;
      }
    },
    {
      name: 'view',
      defaultValue: 'DateTimeFieldView'
    }
  ]
});

var IntegerProperty = Model.create({
  extendsModel: 'Property',

  name:  'IntegerProperty',
  help:  "Describes a properties of type Integer.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Integer',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'displayWidth',
      defaultValue: 10
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 10,
      defaultValue: 'int',
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      defaultValue: 'IntFieldView'
    },
    {
      name: 'defaultValue',
      defaultValue: 0
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    },
    {
      name: 'compareProperty',
      defaultValue: function(o1, o2) {
        return o1 === o2 ? 0 : o1 > o2 ? 1 : -1;
      }
    }
  ]
});

var FloatProperty = Model.create({
  extendsModel: 'Property',

  name:  'FloatProperty',
  help:  "Describes a properties of type Float.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Float',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 10,
      defaultValue: 'double',
      help: 'The Java type of this property.'
    },
    {
      name: 'displayWidth',
      defaultValue: 15
    },
    {
      name: 'view',
      defaultValue: 'FloatFieldView'
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    }
  ]
});

var FunctionProperty = Model.create({
  extendsModel: 'Property',

  name:  'FunctionProperty',
  help:  "Describes a properties of type Function.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Function',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 10,
      defaultValue: 'Function',
      help: 'The Java type of this property.'
    },
    {
      name: 'displayWidth',
      defaultValue: 15
    },
    {
      name: 'view',
      defaultValue: 'FunctionView'
    },
    {
      name: 'defaultValue',
      defaultValue: function() {}
    },
    {
      name: 'fromElement',
      defaultValue: function(e) {
        var txt = e.innerHTML;

        return txt.startsWith('function') ?
          eval(txt) :
          new Function(txt) ;
      }
    }
  ]
});

var ArrayProperty = Model.create({
  extendsModel: 'Property',

  name:  'ArrayProperty',
  help:  "Describes a properties of type Array.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Array',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'subType',
      type: 'String',
      displayWidth: 20,
      defaultValue: '',
      help: 'The FOAM sub-type of this property.'
    },
    {
      name: 'preSet',
      defaultValue: function(a, _, prop) {
        var m = GLOBAL[prop.subType];

        if ( ! m ) return a;

        for ( var i = 0 ; i < a.length ; i++ ) {
          // TODO: remove when 'redundant model_'s removed
          /*
            if ( a[i].model_ ) {
            if ( a[i].model_ == prop.subType ) {
            console.log('********* redundant model_ ', prop.subType)
            } else {
            console.log('*');
            }
            }
          */
          a[i] = a[i].model_ ? FOAM(a[i]) : m.create(a[i]);
        }

        return a;
      }
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 10,
      defaultValueFn: function(p) { return p.subType + '[]'; },
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      defaultValue: 'ArrayView'
    },
    {
      name: 'valueFactory',
      defaultValue: function() { return []; }
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    }
  ]
});

var ReferenceProperty = Model.create({
  extendsModel: 'Property',

  name:  'ReferenceProperty',
  help:  "A foreign key reference to another Entity.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Reference',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'subType',
      type: 'String',
      displayWidth: 20,
      defaultValue: '',
      help: 'The FOAM sub-type of this property.'
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 10,
      // TODO: should obtain primary-key type from subType
      defaultValueFn: function(p) { return 'Object'; },
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      // TODO: should be 'KeyView'
      defaultValue: 'TextFieldView'
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    }
  ]
});

var StringArrayProperty = Model.create({
  extendsModel: 'Property',

  name:  'StringArrayProperty',
  help:  "An array of String values.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Array[]',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'subType',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'String',
      help: 'The FOAM sub-type of this property.'
    },
    {
      name: 'displayWidth',
      defaultValue: 50
    },
    {
      name: 'valueFactory',
      defaultValue: function() { return []; }
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 10,
      defaultValue: 'String[]',
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      defaultValue: 'StringArrayView'
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    }
  ]
});

var ReferenceArrayProperty = StringArrayProperty;
var EMailProperty = StringProperty;
var URLProperty = StringProperty;
<commit_msg>Added new DAOProperty property type.<commit_after>/**
 * @license
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * 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 CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var StringProperty = Model.create({
  extendsModel: 'Property',

  name:  'StringProperty',
  help:  "Describes a properties of type String.",

  properties: [
    {
      name: 'displayHeight',
      type: 'int',
      displayWidth: 8,
      defaultValue: 1,
      help: 'The display height of the property.'
    },
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'String',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 70,
      defaultValue: 'String',
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      defaultValueFn: function() { return this.displayHeight > 1 ? 'TextAreaView' : 'TextFieldView'; }
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    }
  ]
});

var BooleanProperty = Model.create({
  extendsModel: 'Property',

  name:  'BooleanProperty',
  help:  "Describes a properties of type String.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Boolean',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 70,
      defaultValue: 'bool',
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      defaultValue: 'BooleanView'
    },
    {
      name: 'defaultValue',
      defaultValue: false
    },
    {
      name: 'preSet',
      defaultValue: function (v) { return !!v; },
      help: 'The Java type of this property.'
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    }
  ]
});

/*
  preSet: function (d) {
  return typeof d === 'string' ? new Date(d) : d;
  },
  tableFormatter: function(d) {
  return d.toDateString();
  },
  valueFactory: function() { return new Date(); }

*/

var DateProperty = Model.create({
  extendsModel: 'Property',

  name:  'DateProperty',
  help:  "Describes a properties of type String.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Date',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'displayWidth',
      defaultValue: 50
    },
    {
      name: 'javaType',
      type: 'String',
      defaultValue: 'Date',
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      // TODO: create custom DateView
      defaultValue: 'DateFieldView'
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    },
    {
      name: 'preSet',
      defaultValue: function (d) {
        return typeof d === 'string' ? new Date(d) : d;
      }
    },
    {
      name: 'tableFormatter',
      defaultValue2: function(d) {
        return d.toDateString();
      },
      defaultValue: function(d) {
        return d.toRelativeDateString();
      }
    }
  ]
});

var DateTimeProperty = Model.create({
  extendsModel: 'DateProperty',

  name:  'DateTimeProperty',
  help:  "Describes a properties of type String.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 25,
      defaultValue: 'datetime',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'preSet',
      defaultValue: function(d) {
        if ( typeof d === 'number' ) return new Date(d);
        if ( typeof d === 'string' ) return new Date(d);
        return d;
      }
    },
    {
      name: 'view',
      defaultValue: 'DateTimeFieldView'
    }
  ]
});

var IntegerProperty = Model.create({
  extendsModel: 'Property',

  name:  'IntegerProperty',
  help:  "Describes a properties of type Integer.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Integer',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'displayWidth',
      defaultValue: 10
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 10,
      defaultValue: 'int',
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      defaultValue: 'IntFieldView'
    },
    {
      name: 'defaultValue',
      defaultValue: 0
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    },
    {
      name: 'compareProperty',
      defaultValue: function(o1, o2) {
        return o1 === o2 ? 0 : o1 > o2 ? 1 : -1;
      }
    }
  ]
});

var FloatProperty = Model.create({
  extendsModel: 'Property',

  name:  'FloatProperty',
  help:  "Describes a properties of type Float.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Float',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 10,
      defaultValue: 'double',
      help: 'The Java type of this property.'
    },
    {
      name: 'displayWidth',
      defaultValue: 15
    },
    {
      name: 'view',
      defaultValue: 'FloatFieldView'
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    }
  ]
});

var FunctionProperty = Model.create({
  extendsModel: 'Property',

  name:  'FunctionProperty',
  help:  "Describes a properties of type Function.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Function',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 10,
      defaultValue: 'Function',
      help: 'The Java type of this property.'
    },
    {
      name: 'displayWidth',
      defaultValue: 15
    },
    {
      name: 'view',
      defaultValue: 'FunctionView'
    },
    {
      name: 'defaultValue',
      defaultValue: function() {}
    },
    {
      name: 'fromElement',
      defaultValue: function(e) {
        var txt = e.innerHTML;

        return txt.startsWith('function') ?
          eval(txt) :
          new Function(txt) ;
      }
    }
  ]
});

var ArrayProperty = Model.create({
  extendsModel: 'Property',

  name:  'ArrayProperty',
  help:  "Describes a properties of type Array.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Array',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'subType',
      type: 'String',
      displayWidth: 20,
      defaultValue: '',
      help: 'The FOAM sub-type of this property.'
    },
    {
      name: 'preSet',
      defaultValue: function(a, _, prop) {
        var m = GLOBAL[prop.subType];

        if ( ! m ) return a;

        for ( var i = 0 ; i < a.length ; i++ ) {
          // TODO: remove when 'redundant model_'s removed
          /*
            if ( a[i].model_ ) {
            if ( a[i].model_ == prop.subType ) {
            console.log('********* redundant model_ ', prop.subType)
            } else {
            console.log('*');
            }
            }
          */
          a[i] = a[i].model_ ? FOAM(a[i]) : m.create(a[i]);
        }

        return a;
      }
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 10,
      defaultValueFn: function(p) { return p.subType + '[]'; },
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      defaultValue: 'ArrayView'
    },
    {
      name: 'valueFactory',
      defaultValue: function() { return []; }
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    }
  ]
});

var ReferenceProperty = Model.create({
  extendsModel: 'Property',

  name:  'ReferenceProperty',
  help:  "A foreign key reference to another Entity.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Reference',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'subType',
      type: 'String',
      displayWidth: 20,
      defaultValue: '',
      help: 'The FOAM sub-type of this property.'
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 10,
      // TODO: should obtain primary-key type from subType
      defaultValueFn: function(p) { return 'Object'; },
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      // TODO: should be 'KeyView'
      defaultValue: 'TextFieldView'
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    }
  ]
});

var StringArrayProperty = Model.create({
  extendsModel: 'Property',

  name:  'StringArrayProperty',
  help:  "An array of String values.",

  properties: [
    {
      name: 'type',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'Array[]',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'subType',
      type: 'String',
      displayWidth: 20,
      defaultValue: 'String',
      help: 'The FOAM sub-type of this property.'
    },
    {
      name: 'displayWidth',
      defaultValue: 50
    },
    {
      name: 'valueFactory',
      defaultValue: function() { return []; }
    },
    {
      name: 'javaType',
      type: 'String',
      displayWidth: 10,
      defaultValue: 'String[]',
      help: 'The Java type of this property.'
    },
    {
      name: 'view',
      defaultValue: 'StringArrayView'
    },
    {
      name: 'prototag',
      label: 'Protobuf tag',
      type: 'Integer',
      required: false,
      help: 'The protobuf tag number for this field.'
    }
  ]
});

var DAOProperty = Model.create({
  extendsModel: 'Property',

  name:  'DAOProperty',
  help:  "Describes a DAO property.",

  properties: [
    {
      name: 'type',
      defaultValue: 'DAO',
      help: 'The FOAM type of this property.'
    },
    {
      name: 'view',
      defaultValue: 'ArrayView'
    },
    {
      name: 'setter',
      defaultValue: function(dao, name) {
        if ( ! this.instance_[name] ) this.instance_[name] = ProxyDAO.create();
        this.instance_[name].delegate = dao;
      }
    }
  ]
});

var ReferenceArrayProperty = StringArrayProperty;
var EMailProperty = StringProperty;
var URLProperty = StringProperty;
<|endoftext|>


<commit_before>var buster = require("buster-node");
var assert = buster.referee.assert;
var refute = buster.referee.refute;
var autotest = require("../lib/buster-autotest");
var wt = require("fs-watch-tree");
var cp = require("child_process");
var util = require("util");
var path = require("path");
var glob = require("multi-glob");
var oi = require("../lib/on-interrupt");
var events = require("events");

buster.testCase("Autotest", {
    setUp: function () {
        this.stub(oi, "onInterrupt");
        var self = this;
        this.stdout = "";
        this.stub(util, "print", function (str) { self.stdout += str; });
        this.stub(util, "puts", function (str) { self.stdout += str + "\n"; });
        this.processes = [];
        this.stub(cp, "spawn", function () {
            var process = new events.EventEmitter();
            process.kill = self.spy();
            process.stdout = new events.EventEmitter();
            process.stderr = new events.EventEmitter();
            self.processes.push(process);
            self.process = process;
            return process;
        });
        this.stub(wt, "watchTree");
        this.stub(glob, "glob").yields(null, []);
        this.clock = this.useFakeTimers();
    },

    "watches directory": function () {
        autotest.watch("/some/dir");
        assert.calledOnceWith(wt.watchTree, "/some/dir");
    },

    "on change": {
        setUp: function () {
            this.emitChange = function (name, opt) {
                opt = opt || {};
                wt.watchTree.args[0][2]({
                    isMkdir: function () { return opt.isMkdir; },
                    isDirectory: function () { return opt.isDir; },
                    name: name
                });
            };
            this.failTests = function () { this.process.emit("exit", 1); };
            this.passTests = function () { this.process.emit("exit", 0); };
        },

        "does not run tests immediately": function () {
            autotest.watch("/some/dir");
            this.emitChange();
            refute.called(cp.spawn);
        },

        "does not run tests for mkdir event": function () {
            autotest.watch("/some/dir");
            this.emitChange("test", { isMkdir: true });
            this.clock.tick(10);
            refute.called(cp.spawn);
        },

        "runs tests after 10ms": function () {
            autotest.watch("/some/dir");
            this.emitChange();
            this.clock.tick(10);
            assert.calledOnce(cp.spawn);
            assert.calledWith(cp.spawn, "buster-test");
        },

        "runs specific test": function () {
            autotest.watch("/some/dir");
            this.emitChange("some/file.js");
            this.clock.tick(10);
            assert.calledWith(cp.spawn, "buster-test", ["-t", "some/file.js"]);
        },

        "runs all tests when name is unavailable": function () {
            autotest.watch("/some/dir");
            this.emitChange();
            this.clock.tick(10);
            assert.calledWith(cp.spawn, "buster-test", []);
        },

        "runs all tests when directory": function () {
            autotest.watch("/some/dir");
            this.emitChange("test", { isDir: true });
            this.clock.tick(10);
            assert.calledWith(cp.spawn, "buster-test", []);
        },

        "adds changed test file to existing -t argument": function () {
            autotest.watch("/some/dir", { argv: ["-t", "file.js"] });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            assert.calledWith(
                cp.spawn,
                "buster-test",
                ["-t", "file.js,test/thing-test.js"]
            );
        },

        "uses --tests if present": function () {
            autotest.watch("/some/dir", { argv: ["--tests", "file.js"] });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            assert.calledWith(
                cp.spawn,
                "buster-test",
                ["--tests", "file.js,test/thing-test.js"]
            );
        },

        "runs with all provided options": function () {
            autotest.watch("/some/dir", {
                argv: ["-r", "specification", "--tests", "file.js", "--node"]
            });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            assert.calledWith(
                cp.spawn,
                "buster-test",
                [
                    "-r",
                    "specification",
                    "--tests",
                    "file.js,test/thing-test.js",
                    "--node"
                ]
            );
        },

        "does not run if already running": function () {
            autotest.watch("/some/dir", { argv: ["--tests", "file.js"] });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);

            assert.calledOnce(cp.spawn);
        },

        "issues new run when previous is completed": function () {
            autotest.watch("/some/dir", { argv: ["--tests", "file.js"] });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.process.emit("exit");
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);

            assert.calledTwice(cp.spawn);
        },

        "kills test process after 1 second": function () {
            autotest.watch("/some/dir", { argv: ["--tests", "file.js"] });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.process.stdout.emit("data", "Running...");
            this.clock.tick(1000);

            assert.calledOnce(this.process.kill);
        },

        "runs tests after killing process": function () {
            autotest.watch("/some/dir", { argv: ["--tests", "file.js"] });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.process.stdout.emit("data", "Running...");
            this.clock.tick(1000);
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);

            assert.calledTwice(cp.spawn);
        },

        "runs all tests when passing after failing": function () {
            autotest.watch("/some/dir");
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.failTests();
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.passTests();

            assert.calledThrice(cp.spawn);
            assert.calledWith(cp.spawn, "buster-test", []);
        },

        "runs originally selected tests when pass after fail": function () {
            autotest.watch("/some/dir", { argv: ["-t", "test/boing.js"] });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.failTests();
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.passTests();

            assert.calledThrice(cp.spawn);
            assert.calledWith(cp.spawn, "buster-test", ["-t", "test/boing.js"]);
        },

        "does not run all tests when failing after passing": function () {
            autotest.watch("/some/dir");
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.passTests();
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.failTests();

            assert.calledTwice(cp.spawn);
        },

        "does not re-run all tests after all passing": function () {
            autotest.watch("/some/dir");
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.passTests();
            this.clock.tick(20);

            assert.calledTwice(cp.spawn);
        },

        "runs related test files": function () {
            glob.glob.restore();
            this.stub(glob, "glob").yields(null, ["test/buster-autotest-test.js"]);
            autotest.watch(path.join(__dirname, "../"));
            this.emitChange("lib/buster-autotest.js");
            this.clock.tick(10);

            assert.calledWith(cp.spawn, "buster-test", [
                "-t",
                "test/buster-autotest-test.js,lib/buster-autotest.js"
            ]);
        }
    }
});
<commit_msg>tests removed for deleted feature 'run all tests...' (commit ed7b34d6a7)<commit_after>var buster = require("buster-node");
var assert = buster.referee.assert;
var refute = buster.referee.refute;
var autotest = require("../lib/buster-autotest");
var wt = require("fs-watch-tree");
var cp = require("child_process");
var util = require("util");
var path = require("path");
var glob = require("multi-glob");
var oi = require("../lib/on-interrupt");
var events = require("events");

buster.testCase("Autotest", {
    setUp: function () {
        this.stub(oi, "onInterrupt");
        var self = this;
        this.stdout = "";
        this.stub(util, "print", function (str) { self.stdout += str; });
        this.stub(util, "puts", function (str) { self.stdout += str + "\n"; });
        this.processes = [];
        this.stub(cp, "spawn", function () {
            var process = new events.EventEmitter();
            process.kill = self.spy();
            process.stdout = new events.EventEmitter();
            process.stderr = new events.EventEmitter();
            self.processes.push(process);
            self.process = process;
            return process;
        });
        this.stub(wt, "watchTree");
        this.stub(glob, "glob").yields(null, []);
        this.clock = this.useFakeTimers();
    },

    "watches directory": function () {
        autotest.watch("/some/dir");
        assert.calledOnceWith(wt.watchTree, "/some/dir");
    },

    "on change": {
        setUp: function () {
            this.emitChange = function (name, opt) {
                opt = opt || {};
                wt.watchTree.args[0][2]({
                    isMkdir: function () { return opt.isMkdir; },
                    isDirectory: function () { return opt.isDir; },
                    name: name
                });
            };
            this.failTests = function () { this.process.emit("exit", 1); };
            this.passTests = function () { this.process.emit("exit", 0); };
        },

        "does not run tests immediately": function () {
            autotest.watch("/some/dir");
            this.emitChange();
            refute.called(cp.spawn);
        },

        "does not run tests for mkdir event": function () {
            autotest.watch("/some/dir");
            this.emitChange("test", { isMkdir: true });
            this.clock.tick(10);
            refute.called(cp.spawn);
        },

        "runs tests after 10ms": function () {
            autotest.watch("/some/dir");
            this.emitChange();
            this.clock.tick(10);
            assert.calledOnce(cp.spawn);
            assert.calledWith(cp.spawn, "buster-test");
        },

        "runs specific test": function () {
            autotest.watch("/some/dir");
            this.emitChange("some/file.js");
            this.clock.tick(10);
            assert.calledWith(cp.spawn, "buster-test", ["-t", "some/file.js"]);
        },

        "runs all tests when name is unavailable": function () {
            autotest.watch("/some/dir");
            this.emitChange();
            this.clock.tick(10);
            assert.calledWith(cp.spawn, "buster-test", []);
        },

        "runs all tests when directory": function () {
            autotest.watch("/some/dir");
            this.emitChange("test", { isDir: true });
            this.clock.tick(10);
            assert.calledWith(cp.spawn, "buster-test", []);
        },

        "adds changed test file to existing -t argument": function () {
            autotest.watch("/some/dir", { argv: ["-t", "file.js"] });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            assert.calledWith(
                cp.spawn,
                "buster-test",
                ["-t", "file.js,test/thing-test.js"]
            );
        },

        "uses --tests if present": function () {
            autotest.watch("/some/dir", { argv: ["--tests", "file.js"] });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            assert.calledWith(
                cp.spawn,
                "buster-test",
                ["--tests", "file.js,test/thing-test.js"]
            );
        },

        "runs with all provided options": function () {
            autotest.watch("/some/dir", {
                argv: ["-r", "specification", "--tests", "file.js", "--node"]
            });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            assert.calledWith(
                cp.spawn,
                "buster-test",
                [
                    "-r",
                    "specification",
                    "--tests",
                    "file.js,test/thing-test.js",
                    "--node"
                ]
            );
        },

        "does not run if already running": function () {
            autotest.watch("/some/dir", { argv: ["--tests", "file.js"] });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);

            assert.calledOnce(cp.spawn);
        },

        "issues new run when previous is completed": function () {
            autotest.watch("/some/dir", { argv: ["--tests", "file.js"] });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.process.emit("exit");
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);

            assert.calledTwice(cp.spawn);
        },

        "kills test process after 1 second": function () {
            autotest.watch("/some/dir", { argv: ["--tests", "file.js"] });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.process.stdout.emit("data", "Running...");
            this.clock.tick(1000);

            assert.calledOnce(this.process.kill);
        },

        "runs tests after killing process": function () {
            autotest.watch("/some/dir", { argv: ["--tests", "file.js"] });
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);
            this.process.stdout.emit("data", "Running...");
            this.clock.tick(1000);
            this.emitChange("test/thing-test.js");
            this.clock.tick(10);

            assert.calledTwice(cp.spawn);
        },

        "runs related test files": function () {
            glob.glob.restore();
            this.stub(glob, "glob").yields(null,
                ["test/buster-autotest-test.js"]);
            autotest.watch(path.join(__dirname, "../"));
            this.emitChange("lib/buster-autotest.js");
            this.clock.tick(10);

            assert.calledWith(cp.spawn, "buster-test", [
                "-t",
                "test/buster-autotest-test.js,lib/buster-autotest.js"
            ]);
        }
    }
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2020 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview This file is a universal registry that provides generic methods
 *    for registering and unregistering different types of classes.
 * @author aschmiedt@google.com (Abby Schmiedt)
 */
'use strict';

goog.provide('Blockly.registry');

goog.requireType('Blockly.blockRendering.Renderer');
goog.requireType('Blockly.Cursor');
goog.requireType('Blockly.Events.Abstract');
goog.requireType('Blockly.Field');
goog.requireType('Blockly.IBlockDragger');
goog.requireType('Blockly.IConnectionChecker');
goog.requireType('Blockly.IFlyout');
goog.requireType('Blockly.IMetricsManager');
goog.requireType('Blockly.IToolbox');
goog.requireType('Blockly.Options');
goog.requireType('Blockly.Theme');
goog.requireType('Blockly.ToolboxItem');

/**
 * A map of maps. With the keys being the type and name of the class we are
 * registering and the value being the constructor function.
 * e.g. {'field': {'field_angle': Blockly.FieldAngle}}
 *
 * @type {Object<string, Object<string, function(new:?)>>}
 */
Blockly.registry.typeMap_ = Object.create(null);

/**
 * The string used to register the default class for a type of plugin.
 * @type {string}
 */
Blockly.registry.DEFAULT = 'default';

/**
 * A name with the type of the element stored in the generic.
 * @param {string} name The name of the registry type.
 * @constructor
 * @template T
 */
Blockly.registry.Type = function(name) {
  /**
   * @type {string}
   * @private
   */
  this.name_ = name;
};

/**
 * Returns the name of the type.
 * @return {string} The name.
 * @override
 */
Blockly.registry.Type.prototype.toString = function() {
  return this.name_;
};

/** @type {!Blockly.registry.Type<Blockly.IConnectionChecker>} */
Blockly.registry.Type.CONNECTION_CHECKER =
    new Blockly.registry.Type('connectionChecker');

/** @type {!Blockly.registry.Type<Blockly.Cursor>} */
Blockly.registry.Type.CURSOR = new Blockly.registry.Type('cursor');

/** @type {!Blockly.registry.Type<Blockly.Events.Abstract>} */
Blockly.registry.Type.EVENT = new Blockly.registry.Type('event');

/** @type {!Blockly.registry.Type<Blockly.Field>} */
Blockly.registry.Type.FIELD = new Blockly.registry.Type('field');

/** @type {!Blockly.registry.Type<Blockly.blockRendering.Renderer>} */
Blockly.registry.Type.RENDERER = new Blockly.registry.Type('renderer');

/** @type {!Blockly.registry.Type<Blockly.IToolbox>} */
Blockly.registry.Type.TOOLBOX = new Blockly.registry.Type('toolbox');

/** @type {!Blockly.registry.Type<Blockly.Theme>} */
Blockly.registry.Type.THEME = new Blockly.registry.Type('theme');

/** @type {!Blockly.registry.Type<Blockly.ToolboxItem>} */
Blockly.registry.Type.TOOLBOX_ITEM = new Blockly.registry.Type('toolboxItem');

/** @type {!Blockly.registry.Type<Blockly.IFlyout>} */
Blockly.registry.Type.FLYOUTS_VERTICAL_TOOLBOX =
    new Blockly.registry.Type('flyoutsVerticalToolbox');

/** @type {!Blockly.registry.Type<Blockly.IFlyout>} */
Blockly.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX =
    new Blockly.registry.Type('flyoutsHorizontalToolbox');

/** @type {!Blockly.registry.Type<Blockly.IMetricsManager>} */
Blockly.registry.Type.METRICS_MANAGER =
    new Blockly.registry.Type('metricsManager');

/** @type {!Blockly.registry.Type<Blockly.IBlockDragger>} */
Blockly.registry.Type.BLOCK_DRAGGER =
    new Blockly.registry.Type('blockDragger');

/**
 * Registers a class based on a type and name.
 * @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
 *     (e.g. Field, Renderer)
 * @param {string} name The plugin's name. (Ex. field_angle, geras)
 * @param {?function(new:T, ...?)|Object} registryItem The class or object to
 *     register.
 * @param {boolean=} opt_allowOverrides True to prevent an error when overriding
 *     an already registered item.
 * @throws {Error} if the type or name is empty, a name with the given type has
 *     already been registered, or if the given class or object is not valid for
 * it's type.
 * @template T
 */
Blockly.registry.register = function(
    type, name, registryItem, opt_allowOverrides) {
  if ((!(type instanceof Blockly.registry.Type) && typeof type != 'string') ||
      String(type).trim() == '') {
    throw Error(
        'Invalid type "' + type + '". The type must be a' +
        ' non-empty string or a Blockly.registry.Type.');
  }
  type = String(type).toLowerCase();

  if ((typeof name != 'string') || (name.trim() == '')) {
    throw Error(
        'Invalid name "' + name + '". The name must be a' +
        ' non-empty string.');
  }
  name = name.toLowerCase();
  if (!registryItem) {
    throw Error('Can not register a null value');
  }
  var typeRegistry = Blockly.registry.typeMap_[type];
  // If the type registry has not been created, create it.
  if (!typeRegistry) {
    typeRegistry = Blockly.registry.typeMap_[type] = Object.create(null);
  }

  // Validate that the given class has all the required properties.
  Blockly.registry.validate_(type, registryItem);

  // Don't throw an error if opt_allowOverrides is true.
  if (!opt_allowOverrides && typeRegistry[name]) {
    throw Error(
        'Name "' + name + '" with type "' + type + '" already registered.');
  }
  typeRegistry[name] = registryItem;
};

/**
 * Checks the given registry item for properties that are required based on the
 * type.
 * @param {string} type The type of the plugin. (e.g. Field, Renderer)
 * @param {Function|Object} registryItem A class or object that we are checking
 *     for the required properties.
 * @private
 */
Blockly.registry.validate_ = function(type, registryItem) {
  switch (type) {
    case String(Blockly.registry.Type.FIELD):
      if (typeof registryItem.fromJson != 'function') {
        throw Error('Type "' + type + '" must have a fromJson function');
      }
      break;
  }
};

/**
 * Unregisters the registry item with the given type and name.
 * @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
 *     (e.g. Field, Renderer)
 * @param {string} name The plugin's name. (Ex. field_angle, geras)
 * @template T
 */
Blockly.registry.unregister = function(type, name) {
  type = String(type).toLowerCase();
  name = name.toLowerCase();
  var typeRegistry = Blockly.registry.typeMap_[type];
  if (!typeRegistry || !typeRegistry[name]) {
    console.warn('Unable to unregister [' + name + '][' + type + '] from the ' +
      'registry.');
    return;
  }
  delete Blockly.registry.typeMap_[type][name];
};

/**
 * Gets the registry item for the given name and type. This can be either a
 * class or an object.
 * @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
 *     (e.g. Field, Renderer)
 * @param {string} name The plugin's name. (Ex. field_angle, geras)
 * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we
 *     are unable to find the plugin.
 * @return {?function(new:T, ...?)|Object} The class or object with the given
 *     name and type or null if none exists.
 * @template T
 */
Blockly.registry.getItem_ = function(type, name, opt_throwIfMissing) {
  type = String(type).toLowerCase();
  name = name.toLowerCase();
  var typeRegistry = Blockly.registry.typeMap_[type];
  if (!typeRegistry || !typeRegistry[name]) {
    var msg = 'Unable to find [' + name + '][' + type + '] in the registry.';
    if (opt_throwIfMissing) {
      throw new Error(msg + ' You must require or register a ' + type +
        ' plugin.');
    } else {
      console.warn(msg);
    }
    return null;
  }
  return typeRegistry[name];
};

/**
 * Returns whether or not the registry contains an item with the given type and
 * name.
 * @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
 *     (e.g. Field, Renderer)
 * @param {string} name The plugin's name. (Ex. field_angle, geras)
 * @return {boolean} True if the registry has an item with the given type and
 *     name, false otherwise.
 * @template T
 */
Blockly.registry.hasItem = function(type, name) {
  type = String(type).toLowerCase();
  name = name.toLowerCase();
  var typeRegistry = Blockly.registry.typeMap_[type];
  if (!typeRegistry) {
    return false;
  }
  return !!(typeRegistry[name]);
};

/**
 * Gets the class for the given name and type.
 * @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
 *     (e.g. Field, Renderer)
 * @param {string} name The plugin's name. (Ex. field_angle, geras)
 * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we
 *     are unable to find the plugin.
 * @return {?function(new:T, ...?)} The class with the given name and type or
 *     null if none exists.
 * @template T
 */
Blockly.registry.getClass = function(type, name, opt_throwIfMissing) {
  return /** @type {?function(new:T, ...?)} */ (
    Blockly.registry.getItem_(type, name, opt_throwIfMissing));
};

/**
 * Gets the object for the given name and type.
 * @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
 *     (e.g. Category)
 * @param {string} name The plugin's name. (Ex. logic_category)
 * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we
 *     are unable to find the object.
 * @return {?T} The object with the given name and type or null if none exists.
 * @template T
 */
Blockly.registry.getObject = function(type, name, opt_throwIfMissing) {
  return /** @type {T} */ (
    Blockly.registry.getItem_(type, name, opt_throwIfMissing));
};

/**
 * Gets the class from Blockly options for the given type.
 * This is used for plugins that override a built in feature. (e.g. Toolbox)
 * @param {!Blockly.registry.Type<T>} type The type of the plugin.
 * @param {!Blockly.Options} options The option object to check for the given
 *     plugin.
 * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we
 *     are unable to find the plugin.
 * @return {?function(new:T, ...?)} The class for the plugin.
 * @template T
 */
Blockly.registry.getClassFromOptions = function(type, options,
    opt_throwIfMissing) {
  var typeName = type.toString();
  var plugin = options.plugins[typeName] || Blockly.registry.DEFAULT;

  // If the user passed in a plugin class instead of a registered plugin name.
  if (typeof plugin == 'function') {
    return plugin;
  }
  return Blockly.registry.getClass(type, plugin, opt_throwIfMissing);
};
<commit_msg>Migrate core/registry.js to ES6 const/let<commit_after>/**
 * @license
 * Copyright 2020 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview This file is a universal registry that provides generic methods
 *    for registering and unregistering different types of classes.
 * @author aschmiedt@google.com (Abby Schmiedt)
 */
'use strict';

goog.provide('Blockly.registry');

goog.requireType('Blockly.blockRendering.Renderer');
goog.requireType('Blockly.Cursor');
goog.requireType('Blockly.Events.Abstract');
goog.requireType('Blockly.Field');
goog.requireType('Blockly.IBlockDragger');
goog.requireType('Blockly.IConnectionChecker');
goog.requireType('Blockly.IFlyout');
goog.requireType('Blockly.IMetricsManager');
goog.requireType('Blockly.IToolbox');
goog.requireType('Blockly.Options');
goog.requireType('Blockly.Theme');
goog.requireType('Blockly.ToolboxItem');

/**
 * A map of maps. With the keys being the type and name of the class we are
 * registering and the value being the constructor function.
 * e.g. {'field': {'field_angle': Blockly.FieldAngle}}
 *
 * @type {Object<string, Object<string, function(new:?)>>}
 */
Blockly.registry.typeMap_ = Object.create(null);

/**
 * The string used to register the default class for a type of plugin.
 * @type {string}
 */
Blockly.registry.DEFAULT = 'default';

/**
 * A name with the type of the element stored in the generic.
 * @param {string} name The name of the registry type.
 * @constructor
 * @template T
 */
Blockly.registry.Type = function(name) {
  /**
   * @type {string}
   * @private
   */
  this.name_ = name;
};

/**
 * Returns the name of the type.
 * @return {string} The name.
 * @override
 */
Blockly.registry.Type.prototype.toString = function() {
  return this.name_;
};

/** @type {!Blockly.registry.Type<Blockly.IConnectionChecker>} */
Blockly.registry.Type.CONNECTION_CHECKER =
    new Blockly.registry.Type('connectionChecker');

/** @type {!Blockly.registry.Type<Blockly.Cursor>} */
Blockly.registry.Type.CURSOR = new Blockly.registry.Type('cursor');

/** @type {!Blockly.registry.Type<Blockly.Events.Abstract>} */
Blockly.registry.Type.EVENT = new Blockly.registry.Type('event');

/** @type {!Blockly.registry.Type<Blockly.Field>} */
Blockly.registry.Type.FIELD = new Blockly.registry.Type('field');

/** @type {!Blockly.registry.Type<Blockly.blockRendering.Renderer>} */
Blockly.registry.Type.RENDERER = new Blockly.registry.Type('renderer');

/** @type {!Blockly.registry.Type<Blockly.IToolbox>} */
Blockly.registry.Type.TOOLBOX = new Blockly.registry.Type('toolbox');

/** @type {!Blockly.registry.Type<Blockly.Theme>} */
Blockly.registry.Type.THEME = new Blockly.registry.Type('theme');

/** @type {!Blockly.registry.Type<Blockly.ToolboxItem>} */
Blockly.registry.Type.TOOLBOX_ITEM = new Blockly.registry.Type('toolboxItem');

/** @type {!Blockly.registry.Type<Blockly.IFlyout>} */
Blockly.registry.Type.FLYOUTS_VERTICAL_TOOLBOX =
    new Blockly.registry.Type('flyoutsVerticalToolbox');

/** @type {!Blockly.registry.Type<Blockly.IFlyout>} */
Blockly.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX =
    new Blockly.registry.Type('flyoutsHorizontalToolbox');

/** @type {!Blockly.registry.Type<Blockly.IMetricsManager>} */
Blockly.registry.Type.METRICS_MANAGER =
    new Blockly.registry.Type('metricsManager');

/** @type {!Blockly.registry.Type<Blockly.IBlockDragger>} */
Blockly.registry.Type.BLOCK_DRAGGER =
    new Blockly.registry.Type('blockDragger');

/**
 * Registers a class based on a type and name.
 * @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
 *     (e.g. Field, Renderer)
 * @param {string} name The plugin's name. (Ex. field_angle, geras)
 * @param {?function(new:T, ...?)|Object} registryItem The class or object to
 *     register.
 * @param {boolean=} opt_allowOverrides True to prevent an error when overriding
 *     an already registered item.
 * @throws {Error} if the type or name is empty, a name with the given type has
 *     already been registered, or if the given class or object is not valid for
 * it's type.
 * @template T
 */
Blockly.registry.register = function(
    type, name, registryItem, opt_allowOverrides) {
  if ((!(type instanceof Blockly.registry.Type) && typeof type != 'string') ||
      String(type).trim() == '') {
    throw Error(
        'Invalid type "' + type + '". The type must be a' +
        ' non-empty string or a Blockly.registry.Type.');
  }
  type = String(type).toLowerCase();

  if ((typeof name != 'string') || (name.trim() == '')) {
    throw Error(
        'Invalid name "' + name + '". The name must be a' +
        ' non-empty string.');
  }
  name = name.toLowerCase();
  if (!registryItem) {
    throw Error('Can not register a null value');
  }
  let typeRegistry = Blockly.registry.typeMap_[type];
  // If the type registry has not been created, create it.
  if (!typeRegistry) {
    typeRegistry = Blockly.registry.typeMap_[type] = Object.create(null);
  }

  // Validate that the given class has all the required properties.
  Blockly.registry.validate_(type, registryItem);

  // Don't throw an error if opt_allowOverrides is true.
  if (!opt_allowOverrides && typeRegistry[name]) {
    throw Error(
        'Name "' + name + '" with type "' + type + '" already registered.');
  }
  typeRegistry[name] = registryItem;
};

/**
 * Checks the given registry item for properties that are required based on the
 * type.
 * @param {string} type The type of the plugin. (e.g. Field, Renderer)
 * @param {Function|Object} registryItem A class or object that we are checking
 *     for the required properties.
 * @private
 */
Blockly.registry.validate_ = function(type, registryItem) {
  switch (type) {
    case String(Blockly.registry.Type.FIELD):
      if (typeof registryItem.fromJson != 'function') {
        throw Error('Type "' + type + '" must have a fromJson function');
      }
      break;
  }
};

/**
 * Unregisters the registry item with the given type and name.
 * @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
 *     (e.g. Field, Renderer)
 * @param {string} name The plugin's name. (Ex. field_angle, geras)
 * @template T
 */
Blockly.registry.unregister = function(type, name) {
  type = String(type).toLowerCase();
  name = name.toLowerCase();
  const typeRegistry = Blockly.registry.typeMap_[type];
  if (!typeRegistry || !typeRegistry[name]) {
    console.warn('Unable to unregister [' + name + '][' + type + '] from the ' +
      'registry.');
    return;
  }
  delete Blockly.registry.typeMap_[type][name];
};

/**
 * Gets the registry item for the given name and type. This can be either a
 * class or an object.
 * @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
 *     (e.g. Field, Renderer)
 * @param {string} name The plugin's name. (Ex. field_angle, geras)
 * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we
 *     are unable to find the plugin.
 * @return {?function(new:T, ...?)|Object} The class or object with the given
 *     name and type or null if none exists.
 * @template T
 */
Blockly.registry.getItem_ = function(type, name, opt_throwIfMissing) {
  type = String(type).toLowerCase();
  name = name.toLowerCase();
  const typeRegistry = Blockly.registry.typeMap_[type];
  if (!typeRegistry || !typeRegistry[name]) {
    const msg = 'Unable to find [' + name + '][' + type + '] in the registry.';
    if (opt_throwIfMissing) {
      throw new Error(msg + ' You must require or register a ' + type +
        ' plugin.');
    } else {
      console.warn(msg);
    }
    return null;
  }
  return typeRegistry[name];
};

/**
 * Returns whether or not the registry contains an item with the given type and
 * name.
 * @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
 *     (e.g. Field, Renderer)
 * @param {string} name The plugin's name. (Ex. field_angle, geras)
 * @return {boolean} True if the registry has an item with the given type and
 *     name, false otherwise.
 * @template T
 */
Blockly.registry.hasItem = function(type, name) {
  type = String(type).toLowerCase();
  name = name.toLowerCase();
  const typeRegistry = Blockly.registry.typeMap_[type];
  if (!typeRegistry) {
    return false;
  }
  return !!(typeRegistry[name]);
};

/**
 * Gets the class for the given name and type.
 * @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
 *     (e.g. Field, Renderer)
 * @param {string} name The plugin's name. (Ex. field_angle, geras)
 * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we
 *     are unable to find the plugin.
 * @return {?function(new:T, ...?)} The class with the given name and type or
 *     null if none exists.
 * @template T
 */
Blockly.registry.getClass = function(type, name, opt_throwIfMissing) {
  return /** @type {?function(new:T, ...?)} */ (
    Blockly.registry.getItem_(type, name, opt_throwIfMissing));
};

/**
 * Gets the object for the given name and type.
 * @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
 *     (e.g. Category)
 * @param {string} name The plugin's name. (Ex. logic_category)
 * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we
 *     are unable to find the object.
 * @return {?T} The object with the given name and type or null if none exists.
 * @template T
 */
Blockly.registry.getObject = function(type, name, opt_throwIfMissing) {
  return /** @type {T} */ (
    Blockly.registry.getItem_(type, name, opt_throwIfMissing));
};

/**
 * Gets the class from Blockly options for the given type.
 * This is used for plugins that override a built in feature. (e.g. Toolbox)
 * @param {!Blockly.registry.Type<T>} type The type of the plugin.
 * @param {!Blockly.Options} options The option object to check for the given
 *     plugin.
 * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we
 *     are unable to find the plugin.
 * @return {?function(new:T, ...?)} The class for the plugin.
 * @template T
 */
Blockly.registry.getClassFromOptions = function(type, options,
    opt_throwIfMissing) {
  const typeName = type.toString();
  const plugin = options.plugins[typeName] || Blockly.registry.DEFAULT;

  // If the user passed in a plugin class instead of a registered plugin name.
  if (typeof plugin == 'function') {
    return plugin;
  }
  return Blockly.registry.getClass(type, plugin, opt_throwIfMissing);
};
<|endoftext|>


<commit_before>(function() {

  /* globals require, describe, it, expect, console */

  'use strict';

  try {

    var document = require("jsdom").jsdom("");
    // window = document.createWindow();
    // navigator = window.navigator;
    // CSSStyleDeclaration = window.CSSStyleDeclaration;

    var d3 = require("../src/d3.layout.cloud");

    var fs = require("fs");

    describe('d3.layout.cloud', function() {

      it('should create an svg', function() {

        var w = 960 * 1,
          h = 600 * 1;

        var layout = d3.layout.cloud()
          .padding(0)
          .size([w, h])
          .font("Impact")
          .text(function(d) {
            return d.key;
          })
          .on("end", draw);

        var start = +new Date();

        for (var i = 0; i < 2; i++) {
          parseText("this is a small cloud");
        }

        function parseText(text) {
          var tags = {};
          text.split(/\s+/g).forEach(function(word) {
            word = word.replace(/[^A-Za-z0-9]/g, "");
            if (word.length <= 3) return;
            tags[word] = (tags[word] || 0) + 1;
          });
          tags = d3.entries(tags).sort(function(a, b) {
            return b.value - a.value;
          }).slice(0, 500);
          var min = +tags[tags.length - 1].value || 1,
            max = +tags[0].value;
          layout.fontSize(function(d) {
            return min + (d - min) / (max - min);
          }).words(tags).start();
        }

        function draw() {
          console.log(+new Date() - start);
        }

        expect(document).toBeDefined();
        expect(document.getElementsByTagName('svg')).toBeDefined();
        expect(document.getElementsByTagName('svg').length).toEqual(' ');
      });

    });

  } catch (e) {
    console.log(e);
    console.log(e, e.stack);
  }

})();<commit_msg>tests load in browser<commit_after>(function() {

  /* globals require, describe, it, expect, console */

  'use strict';

  try {

    var localdocument;
    var locald3;
    try {
      localdocument = document;
      locald3 = d3;
    } catch (e) {
      localdocument = require("jsdom").jsdom("");
      locald3 = require("../src/d3.layout.cloud");
    }
    // window = localdocument.createWindow();
    // navigator = window.navigator;
    // CSSStyleDeclaration = window.CSSStyleDeclaration;

    describe('d3.layout.cloud', function() {

      it('should create an svg', function() {

        var w = 960 * 1,
          h = 600 * 1;

        var layout = locald3.layout.cloud()
          .padding(0)
          .size([w, h])
          .font("Impact")
          .text(function(d) {
            return d.key;
          })
          .on("end", draw);

        var start = +new Date();

        for (var i = 0; i < 2; i++) {
          parseText("this is a small cloud");
        }

        function parseText(text) {
          var tags = {};
          text.split(/\s+/g).forEach(function(word) {
            word = word.replace(/[^A-Za-z0-9]/g, "");
            if (word.length <= 3) return;
            tags[word] = (tags[word] || 0) + 1;
          });
          tags = locald3.entries(tags).sort(function(a, b) {
            return b.value - a.value;
          }).slice(0, 500);
          var min = +tags[tags.length - 1].value || 1,
            max = +tags[0].value;
          layout.fontSize(function(d) {
            return min + (d - min) / (max - min);
          }).words(tags).start();
        }

        function draw() {
          console.log(+new Date() - start);
        }

        expect(localdocument).toBeDefined();
        expect(localdocument.getElementsByTagName('svg')).toBeDefined();
        expect(localdocument.getElementsByTagName('svg').length).toEqual(' ');
      });

    });

  } catch (e) {
    console.log(e);
    console.log(e, e.stack);
  }

})();<|endoftext|>


<commit_before>function AudioFilePlayer(){
	return AudioFilePlayer.super_.apply(this, arguments);
}

(function() {

	/*
	loader.includeJS("/js/soundmanager2.js", function() { //-nodebug-jsmin
		console.log("loaded mp3 player");
		soundManager.setup({
			url: '/swf/', //sound manager swf directory
			flashVersion: 9,
			onready: function() {
				console.log("mp3 player is ready");
				//that.isReady = true;
				soundManager.isReady = true;
				//eventHandlers.onApiReady && eventHandlers.onApiReady(that);
			}
		});
	});
	*/

	var EVENT_MAP = {
		"onplay": "onPlaying",
		"onresume": "onPlaying",
		"onpause": "onPaused",
		"onstop": "onPaused",
		"onfinish": "onEnded"
	};

	function Player(eventHandlers, embedVars) {
		this.label = 'Audio file';
		this.eventHandlers = eventHandlers || {};
		this.embedVars = embedVars || {};
		this.element = null;
		this.widget = null;
		this.isReady = false;
		this.trackInfo = {};
		var i, loading, that = this;

		this.soundOptions = {
			id: null,
			url: null,
			autoLoad: true,
			autoPlay: true,
			ontimeout: function(e) {
				//console.log("AudioFilePlayer timeout event:", e);
				that.eventHandlers.onError && that.eventHandlers.onError(that, {code:"timeout", source:"AudioFilePlayer"});
			}
		};

		for (i in EVENT_MAP)
			(function(i) {
				that.soundOptions[i] = function() {
					//console.log("event:", i, this);
					var handler = eventHandlers[EVENT_MAP[i]];
					handler && handler(that);
				}
			})(i);

		loading = setInterval(function(){
			try {
				if (window["soundManager"]) {
					clearInterval(loading);
					that.isReady = true;
					eventHandlers.onApiReady && eventHandlers.onApiReady(that);
				}
			}
			catch (e) {
				that.eventHandlers.onError && that.eventHandlers.onError(that, {source:"AudioFilePlayer", exception:e});
			};
		}, 200);
	}

	Player.prototype.getEid = function(url) {
		url = (url || "").split("#").pop();
		if (!url)
			return null;
		var ext = url.split(".").pop().toLowerCase();
		return (ext == "mp3" || ext == "ogg") ? url : null;
	}

	Player.prototype.fetchMetadata = function(url, cb){
		url = this.getEid(url);
		if (!url)
			return cb();
		cb({
			title: url.split("/").pop()
		});
		// TODO : also use getTrackInfo()
	}

	Player.prototype.getTrackInfo = function(callback) {
		var that = this, i = setInterval(function() {
			//console.log("info", that.widget.duration)
			if (that.widget && that.widget.duration) {
				clearInterval(i);
				callback(that.trackInfo = {
					duration: that.widget.duration / 1000, // that.widget.durationEstimate / 1000
					position: that.widget.position / 1000
				});
				//that.eventHandlers.onTrackInfo && that.eventHandlers.onTrackInfo(that.widget);
			}
		}, 500);
	}

	Player.prototype.getTrackPosition = function(callback) {
		var that = this;
		//console.log("position", that.widget.position)
		this.getTrackInfo(function(){
			callback(that.trackInfo.position);
			that.eventHandlers.onTrackInfo && that.eventHandlers.onTrackInfo(that.trackInfo);
		});
	};

	Player.prototype.setTrackPosition = function(pos) {
		this.widget && this.widget.setPosition(Math.floor(Math.min(this.widget.duration, pos * 1000) - 2000));
	};

	Player.prototype.embed = function(vars) {
		if (!vars || !vars.trackId)
			return;
		//console.log("AudioFilePlayer embed vars:", vars);
		this.embedVars = vars = vars || {};
		this.soundOptions.id = vars.playerId = vars.playerId || 'mp3Player' + (new Date()).getTime();
		this.soundOptions.url = vars.trackId.replace(/^\/fi\//, ""); // remove eId prefix /fi/ if necessary
		this.trackInfo = {};
		if (this.widget) {
			this.pause();
			this.widget = null;
			delete this.widget;
		}
		//console.log("-> soundManager parameters", this.soundOptions);
		this.widget = soundManager.createSound(this.soundOptions);
		//console.log("-> soundManager instance", !!this.widget);
		this.eventHandlers.onEmbedReady && this.eventHandlers.onEmbedReady(this);
		this.eventHandlers.onTrackInfo && this.getTrackInfo(this.eventHandlers.onTrackInfo);
		this.play();
	}

	Player.prototype.play = function(id) {
		//console.log("mp3 play", id)
		this.isReady && this.embed({trackId:id});
	}

	Player.prototype.resume = function() {
		this.isReady && this.widget && this.widget.resume();
	}

	Player.prototype.pause = function() {
		try {
			this.isReady && this.widget && this.widget.pause();
		}
		catch(e) {
			console.error(e.stack);
		}
	}

	Player.prototype.stop = function() {
		this.widget && this.widget.stop();
	}

	Player.prototype.setVolume = function(vol) {
		if (this.widget && this.widget.setVolume && this.soundOptions)
			/*this.widget*/soundManager.setVolume(this.soundOptions.id, 100 * vol);
	}

	//return Player;
	//inherits(AudioFilePlayer, Player);
	AudioFilePlayer.prototype = Player.prototype;
	AudioFilePlayer.super_ = Player;
})();
<commit_msg>fix: ignore GET parameters (?xxx=yyy) from audio file url<commit_after>function AudioFilePlayer(){
	return AudioFilePlayer.super_.apply(this, arguments);
}

(function() {

	/*
	loader.includeJS("/js/soundmanager2.js", function() { //-nodebug-jsmin
		console.log("loaded mp3 player");
		soundManager.setup({
			url: '/swf/', //sound manager swf directory
			flashVersion: 9,
			onready: function() {
				console.log("mp3 player is ready");
				//that.isReady = true;
				soundManager.isReady = true;
				//eventHandlers.onApiReady && eventHandlers.onApiReady(that);
			}
		});
	});
	*/

	var EVENT_MAP = {
		"onplay": "onPlaying",
		"onresume": "onPlaying",
		"onpause": "onPaused",
		"onstop": "onPaused",
		"onfinish": "onEnded"
	};

	function Player(eventHandlers, embedVars) {
		this.label = 'Audio file';
		this.eventHandlers = eventHandlers || {};
		this.embedVars = embedVars || {};
		this.element = null;
		this.widget = null;
		this.isReady = false;
		this.trackInfo = {};
		var i, loading, that = this;

		this.soundOptions = {
			id: null,
			url: null,
			autoLoad: true,
			autoPlay: true,
			ontimeout: function(e) {
				//console.log("AudioFilePlayer timeout event:", e);
				that.eventHandlers.onError && that.eventHandlers.onError(that, {code:"timeout", source:"AudioFilePlayer"});
			}
		};

		for (i in EVENT_MAP)
			(function(i) {
				that.soundOptions[i] = function() {
					//console.log("event:", i, this);
					var handler = eventHandlers[EVENT_MAP[i]];
					handler && handler(that);
				}
			})(i);

		loading = setInterval(function(){
			try {
				if (window["soundManager"]) {
					clearInterval(loading);
					that.isReady = true;
					eventHandlers.onApiReady && eventHandlers.onApiReady(that);
				}
			}
			catch (e) {
				that.eventHandlers.onError && that.eventHandlers.onError(that, {source:"AudioFilePlayer", exception:e});
			};
		}, 200);
	}

	Player.prototype.getEid = function(url) {
		url = (url || "").split("#").pop();
		if (!url)
			return null;
		var ext = url.split("?")[0].split(".").pop().toLowerCase();
		return (ext == "mp3" || ext == "ogg") ? url.replace(/^\/fi\//, "") : null;
	}

	Player.prototype.fetchMetadata = function(url, cb){
		url = this.getEid(url);
		if (!url)
			return cb();
		cb({
			title: url.split("/").pop()
		});
		// TODO : also use getTrackInfo()
	}

	Player.prototype.getTrackInfo = function(callback) {
		var that = this, i = setInterval(function() {
			//console.log("info", that.widget.duration)
			if (that.widget && that.widget.duration) {
				clearInterval(i);
				callback(that.trackInfo = {
					duration: that.widget.duration / 1000, // that.widget.durationEstimate / 1000
					position: that.widget.position / 1000
				});
				//that.eventHandlers.onTrackInfo && that.eventHandlers.onTrackInfo(that.widget);
			}
		}, 500);
	}

	Player.prototype.getTrackPosition = function(callback) {
		var that = this;
		//console.log("position", that.widget.position)
		this.getTrackInfo(function(){
			callback(that.trackInfo.position);
			that.eventHandlers.onTrackInfo && that.eventHandlers.onTrackInfo(that.trackInfo);
		});
	};

	Player.prototype.setTrackPosition = function(pos) {
		this.widget && this.widget.setPosition(Math.floor(Math.min(this.widget.duration, pos * 1000) - 2000));
	};

	Player.prototype.embed = function(vars) {
		if (!vars || !vars.trackId)
			return;
		//console.log("AudioFilePlayer embed vars:", vars);
		this.embedVars = vars = vars || {};
		this.soundOptions.id = vars.playerId = vars.playerId || 'mp3Player' + (new Date()).getTime();
		this.soundOptions.url = vars.trackId.replace(/^\/fi\//, ""); // remove eId prefix /fi/ if necessary
		this.trackInfo = {};
		if (this.widget) {
			this.pause();
			this.widget = null;
			delete this.widget;
		}
		//console.log("-> soundManager parameters", this.soundOptions);
		this.widget = soundManager.createSound(this.soundOptions);
		//console.log("-> soundManager instance", !!this.widget);
		this.eventHandlers.onEmbedReady && this.eventHandlers.onEmbedReady(this);
		this.eventHandlers.onTrackInfo && this.getTrackInfo(this.eventHandlers.onTrackInfo);
		this.play();
	}

	Player.prototype.play = function(id) {
		//console.log("mp3 play", id)
		this.isReady && this.embed({trackId:id});
	}

	Player.prototype.resume = function() {
		this.isReady && this.widget && this.widget.resume();
	}

	Player.prototype.pause = function() {
		try {
			this.isReady && this.widget && this.widget.pause();
		}
		catch(e) {
			console.error(e.stack);
		}
	}

	Player.prototype.stop = function() {
		this.widget && this.widget.stop();
	}

	Player.prototype.setVolume = function(vol) {
		if (this.widget && this.widget.setVolume && this.soundOptions)
			/*this.widget*/soundManager.setVolume(this.soundOptions.id, 100 * vol);
	}

	//return Player;
	//inherits(AudioFilePlayer, Player);
	AudioFilePlayer.prototype = Player.prototype;
	AudioFilePlayer.super_ = Player;
})();
<|endoftext|>


<commit_before>(function(mod) {
  if (typeof exports == "object" && typeof module == "object") // CommonJS
    return mod(require("../lib/infer"), require("../lib/tern"));
  if (typeof define == "function" && define.amd) // AMD
    return define(["../lib/infer", "../lib/tern"], mod);
  mod(tern, tern);
})(function(infer, tern) {
  "use strict";

  function flattenPath(path) {
    if (!/(^|\/)(\.\/|[^\/]+\/\.\.\/)/.test(path)) return path;
    var parts = path.split("/");
    for (var i = 0; i < parts.length; ++i) {
      if (parts[i] == "." || !parts[i]) parts.splice(i--, 1);
      else if (i && parts[i] == "..") parts.splice(i-- - 1, 2);
    }
    return parts.join("/");
  }

  function resolveName(name, data) {
    var excl = name.indexOf("!");
    if (excl > -1) name = name.slice(0, excl);

    var opts = data.options;
    var hasExt = /\.js$/.test(name);
    if (hasExt || /^(?:\w+:|\/)/.test(name))
      return name + (hasExt ? "" : ".js");

    var base = opts.baseURL || "";
    if (base && base.charAt(base.length - 1) != "/") base += "/";
    if (opts.paths) {
      var known = opts.paths[name];
      if (known) return flattenPath(base + known + ".js");
      var dir = name.match(/^([^\/]+)(\/.*)$/);
      if (dir) {
        var known = opts.paths[dir[1]];
        if (known) return flattenPath(base + known + dir[2] + ".js");
      }
    }
    return flattenPath(base + name + ".js");
  }

  function getRequire(data) {
    if (!data.require) {
      data.require = new infer.Fn("require", infer.ANull, [infer.cx().str], ["module"], new infer.AVal);
      data.require.computeRet = function(_self, _args, argNodes) {
        if (argNodes.length && argNodes[0].type == "Literal" && typeof argNodes[0].value == "string")
          return getInterface(argNodes[0].value, data);
        return infer.ANull;
      };
    }
    return data.require;
  }

  function getInterface(name, data) {
    if (name == "require") return getRequire(data);
    if (name == "module") return infer.cx().definitions.requirejs.module;

    if (data.options.override && Object.prototype.hasOwnProperty.call(data.options.override, name)) {
      var over = data.options.override[name];
      if (typeof over == "string" && over.charAt(0) == "=") return infer.def.parsePath(over.slice(1));
      if (typeof over == "object") {
        var known = getKnownModule(name, data);
        if (known) return known;
        var scope = data.interfaces[stripJSExt(name)] = new infer.Obj(null, stripJSExt(name));
        infer.def.load(over, scope);
        return scope;
      }
      name = over;
    }

    if (!/^(https?:|\/)|\.js$/.test(name))
      name = resolveName(name, data);
    name = flattenPath(name);

    var known = getKnownModule(name, data);

    if (!known) {
      known = getModule(name, data);
      data.server.addFile(name, null, data.currentFile);
    }
    return known;
  }

  function getKnownModule(name, data) {
    return data.interfaces[stripJSExt(name)];
  }

  function getModule(name, data) {
    var known = getKnownModule(name, data);
    if (!known) {
      known = data.interfaces[stripJSExt(name)] = new infer.AVal;
      known.origin = name;
    }
    return known;
  }

  var EXPORT_OBJ_WEIGHT = 50;

  function stripJSExt(f) {
    return f.replace(/\.js$/, '');
  }

  var path = {
    dirname: function(path) {
      var lastSep = path.lastIndexOf("/");
      return lastSep == -1 ? "" : path.slice(0, lastSep);
    },
    relative: function(from, to) {
      if (to.indexOf(from) == 0) return to.slice(from.length);
      else return to;
    },
    join: function(a, b) {
      if (b && b.charAt(0) != ".") return b;
      if (a && b) return a + "/" + b;
      else return (a || "") + (b || "");
    },
  };

  infer.registerFunction("requireJS", function(_self, args, argNodes) {
    var server = infer.cx().parent, data = server && server._requireJS;
    if (!data || !args.length) return infer.ANull;

    var name = data.currentFile;
    var out = getModule(name, data);

    var deps = [], fn;
    if (argNodes && args.length > 1) {
      var node = argNodes[args.length == 2 ? 0 : 1];
      var base = path.relative(server.options.projectDir, path.dirname(node.sourceFile.name));
      if (node.type == "Literal" && typeof node.value == "string") {
        deps.push(getInterface(path.join(base, node.value), data));
      } else if (node.type == "ArrayExpression") for (var i = 0; i < node.elements.length; ++i) {
        var elt = node.elements[i];
        if (elt.type == "Literal" && typeof elt.value == "string") {
          if (elt.value == "exports") {
            var exports = new infer.Obj(true);
            deps.push(exports);
            out.addType(exports, EXPORT_OBJ_WEIGHT);
          } else {
            deps.push(getInterface(path.join(base, elt.value), data));
          }
        }
      }
    } else if (argNodes && args.length == 1 && argNodes[0].type == "FunctionExpression" && argNodes[0].params.length) {
      // Simplified CommonJS call
      var exports = new infer.Obj(true);
      deps.push(getInterface("require", data), exports);
      out.addType(exports, EXPORT_OBJ_WEIGHT);
      fn = args[0];
    }

    if (!fn) {
      fn = args[Math.min(args.length - 1, 2)];
      if (!fn.isEmpty() && !fn.getFunctionType()) fn = null;
    }

    if (fn) fn.propagate(new infer.IsCallee(infer.ANull, deps, null, out));
    else if (args.length) args[0].propagate(out);

    return infer.ANull;
  });

  // Parse simple ObjectExpression AST nodes to their corresponding JavaScript objects.
  function parseExprNode(node) {
    switch (node.type) {
    case "ArrayExpression":
      return node.elements.map(parseExprNode);
    case "Literal":
      return node.value;
    case "ObjectExpression":
      var obj = {};
      node.properties.forEach(function(prop) {
        var key = prop.key.name || prop.key.value;
        obj[key] = parseExprNode(prop.value);
      });
      return obj;
    }
  }

  infer.registerFunction("requireJSConfig", function(_self, _args, argNodes) {
    var server = infer.cx().parent, data = server && server._requireJS;
    if (data && argNodes && argNodes.length && argNodes[0].type == "ObjectExpression") {
      var config = parseExprNode(argNodes[0]);
      for (var key in config) if (config.hasOwnProperty(key)) {
        var value = config[key], exists = data.options[key];
        if (!exists) {
          data.options[key] = value;
        } else if (key == "paths") {
          for (var path in value) if (value.hasOwnProperty(path) && !data.options.paths[path])
            data.options.paths[path] = value[path];
        }
      }
    }
    return infer.ANull;
  });

  function preCondenseReach(state) {
    var interfaces = infer.cx().parent._requireJS.interfaces;
    var rjs = state.roots["!requirejs"] = new infer.Obj(null);
    for (var name in interfaces) {
      var prop = rjs.defProp(name.replace(/\./g, "`"));
      interfaces[name].propagate(prop);
      prop.origin = interfaces[name].origin;
    }
  }

  function postLoadDef(data) {
    var cx = infer.cx(), interfaces = cx.definitions[data["!name"]]["!requirejs"];
    var data = cx.parent._requireJS;
    if (interfaces) for (var name in interfaces.props) {
      interfaces.props[name].propagate(getInterface(name, data));
    }
  }

  tern.registerPlugin("requirejs", function(server, options) {
    server._requireJS = {
      interfaces: Object.create(null),
      options: options || {},
      currentFile: null,
      server: server
    };

    server.on("beforeLoad", function(file) {
      this._requireJS.currentFile = file.name;
    });
    server.on("reset", function() {
      this._requireJS.interfaces = Object.create(null);
      this._requireJS.require = null;
    });
    return {
      defs: defs,
      passes: {
        preCondenseReach: preCondenseReach,
        postLoadDef: postLoadDef
      },
    };
  });

  var defs = {
    "!name": "requirejs",
    "!define": {
      module: {
        id: "string",
        uri: "string",
        config: "fn() -> ?",
        exports: "?"
      }
    },
    requirejs: {
      "!type": "fn(deps: [string], callback: fn(), errback: fn()) -> !custom:requireJS",
      onError: "fn(err: +Error)",
      load: "fn(context: ?, moduleName: string, url: string)",
      config: "fn(config: ?) -> !custom:requireJSConfig",
      version: "string",
      isBrowser: "bool"
    },
    require: "requirejs",
    define: {
      "!type": "fn(deps: [string], callback: fn()) -> !custom:requireJS",
      amd: {
        jQuery: "bool"
      }
    }
  };
});
<commit_msg>[requirejs plugin] Use full path for getRequire<commit_after>(function(mod) {
  if (typeof exports == "object" && typeof module == "object") // CommonJS
    return mod(require("../lib/infer"), require("../lib/tern"));
  if (typeof define == "function" && define.amd) // AMD
    return define(["../lib/infer", "../lib/tern"], mod);
  mod(tern, tern);
})(function(infer, tern) {
  "use strict";

  function flattenPath(path) {
    if (!/(^|\/)(\.\/|[^\/]+\/\.\.\/)/.test(path)) return path;
    var parts = path.split("/");
    for (var i = 0; i < parts.length; ++i) {
      if (parts[i] == "." || !parts[i]) parts.splice(i--, 1);
      else if (i && parts[i] == "..") parts.splice(i-- - 1, 2);
    }
    return parts.join("/");
  }

  function resolveName(name, data) {
    var excl = name.indexOf("!");
    if (excl > -1) name = name.slice(0, excl);

    var opts = data.options;
    var hasExt = /\.js$/.test(name);
    if (hasExt || /^(?:\w+:|\/)/.test(name))
      return name + (hasExt ? "" : ".js");

    var base = opts.baseURL || "";
    if (base && base.charAt(base.length - 1) != "/") base += "/";
    if (opts.paths) {
      var known = opts.paths[name];
      if (known) return flattenPath(base + known + ".js");
      var dir = name.match(/^([^\/]+)(\/.*)$/);
      if (dir) {
        var known = opts.paths[dir[1]];
        if (known) return flattenPath(base + known + dir[2] + ".js");
      }
    }
    return flattenPath(base + name + ".js");
  }

  function getRequire(data) {
    if (!data.require) {
      data.require = new infer.Fn("require", infer.ANull, [infer.cx().str], ["module"], new infer.AVal);
      data.require.computeRet = function(_self, _args, argNodes) {
        if (argNodes.length && argNodes[0].type == "Literal" && typeof argNodes[0].value == "string")
          return getInterface(path.join(path.dirname(data.currentFile), argNodes[0].value), data);
        return infer.ANull;
      };
    }
    return data.require;
  }

  function getInterface(name, data) {
    if (name == "require") return getRequire(data);
    if (name == "module") return infer.cx().definitions.requirejs.module;

    if (data.options.override && Object.prototype.hasOwnProperty.call(data.options.override, name)) {
      var over = data.options.override[name];
      if (typeof over == "string" && over.charAt(0) == "=") return infer.def.parsePath(over.slice(1));
      if (typeof over == "object") {
        var known = getKnownModule(name, data);
        if (known) return known;
        var scope = data.interfaces[stripJSExt(name)] = new infer.Obj(null, stripJSExt(name));
        infer.def.load(over, scope);
        return scope;
      }
      name = over;
    }

    if (!/^(https?:|\/)|\.js$/.test(name))
      name = resolveName(name, data);
    name = flattenPath(name);

    var known = getKnownModule(name, data);

    if (!known) {
      known = getModule(name, data);
      data.server.addFile(name, null, data.currentFile);
    }
    return known;
  }

  function getKnownModule(name, data) {
    return data.interfaces[stripJSExt(name)];
  }

  function getModule(name, data) {
    var known = getKnownModule(name, data);
    if (!known) {
      known = data.interfaces[stripJSExt(name)] = new infer.AVal;
      known.origin = name;
    }
    return known;
  }

  var EXPORT_OBJ_WEIGHT = 50;

  function stripJSExt(f) {
    return f.replace(/\.js$/, '');
  }

  var path = {
    dirname: function(path) {
      var lastSep = path.lastIndexOf("/");
      return lastSep == -1 ? "" : path.slice(0, lastSep);
    },
    relative: function(from, to) {
      if (to.indexOf(from) == 0) return to.slice(from.length);
      else return to;
    },
    join: function(a, b) {
      if (b && b.charAt(0) != ".") return b;
      if (a && b) return a + "/" + b;
      else return (a || "") + (b || "");
    },
  };

  infer.registerFunction("requireJS", function(_self, args, argNodes) {
    var server = infer.cx().parent, data = server && server._requireJS;
    if (!data || !args.length) return infer.ANull;

    var name = data.currentFile;
    var out = getModule(name, data);

    var deps = [], fn;
    if (argNodes && args.length > 1) {
      var node = argNodes[args.length == 2 ? 0 : 1];
      var base = path.relative(server.options.projectDir, path.dirname(node.sourceFile.name));
      if (node.type == "Literal" && typeof node.value == "string") {
        deps.push(getInterface(path.join(base, node.value), data));
      } else if (node.type == "ArrayExpression") for (var i = 0; i < node.elements.length; ++i) {
        var elt = node.elements[i];
        if (elt.type == "Literal" && typeof elt.value == "string") {
          if (elt.value == "exports") {
            var exports = new infer.Obj(true);
            deps.push(exports);
            out.addType(exports, EXPORT_OBJ_WEIGHT);
          } else {
            deps.push(getInterface(path.join(base, elt.value), data));
          }
        }
      }
    } else if (argNodes && args.length == 1 && argNodes[0].type == "FunctionExpression" && argNodes[0].params.length) {
      // Simplified CommonJS call
      var exports = new infer.Obj(true);
      deps.push(getInterface("require", data), exports);
      out.addType(exports, EXPORT_OBJ_WEIGHT);
      fn = args[0];
    }

    if (!fn) {
      fn = args[Math.min(args.length - 1, 2)];
      if (!fn.isEmpty() && !fn.getFunctionType()) fn = null;
    }

    if (fn) fn.propagate(new infer.IsCallee(infer.ANull, deps, null, out));
    else if (args.length) args[0].propagate(out);

    return infer.ANull;
  });

  // Parse simple ObjectExpression AST nodes to their corresponding JavaScript objects.
  function parseExprNode(node) {
    switch (node.type) {
    case "ArrayExpression":
      return node.elements.map(parseExprNode);
    case "Literal":
      return node.value;
    case "ObjectExpression":
      var obj = {};
      node.properties.forEach(function(prop) {
        var key = prop.key.name || prop.key.value;
        obj[key] = parseExprNode(prop.value);
      });
      return obj;
    }
  }

  infer.registerFunction("requireJSConfig", function(_self, _args, argNodes) {
    var server = infer.cx().parent, data = server && server._requireJS;
    if (data && argNodes && argNodes.length && argNodes[0].type == "ObjectExpression") {
      var config = parseExprNode(argNodes[0]);
      for (var key in config) if (config.hasOwnProperty(key)) {
        var value = config[key], exists = data.options[key];
        if (!exists) {
          data.options[key] = value;
        } else if (key == "paths") {
          for (var path in value) if (value.hasOwnProperty(path) && !data.options.paths[path])
            data.options.paths[path] = value[path];
        }
      }
    }
    return infer.ANull;
  });

  function preCondenseReach(state) {
    var interfaces = infer.cx().parent._requireJS.interfaces;
    var rjs = state.roots["!requirejs"] = new infer.Obj(null);
    for (var name in interfaces) {
      var prop = rjs.defProp(name.replace(/\./g, "`"));
      interfaces[name].propagate(prop);
      prop.origin = interfaces[name].origin;
    }
  }

  function postLoadDef(data) {
    var cx = infer.cx(), interfaces = cx.definitions[data["!name"]]["!requirejs"];
    var data = cx.parent._requireJS;
    if (interfaces) for (var name in interfaces.props) {
      interfaces.props[name].propagate(getInterface(name, data));
    }
  }

  tern.registerPlugin("requirejs", function(server, options) {
    server._requireJS = {
      interfaces: Object.create(null),
      options: options || {},
      currentFile: null,
      server: server
    };

    server.on("beforeLoad", function(file) {
      this._requireJS.currentFile = file.name;
    });
    server.on("reset", function() {
      this._requireJS.interfaces = Object.create(null);
      this._requireJS.require = null;
    });
    return {
      defs: defs,
      passes: {
        preCondenseReach: preCondenseReach,
        postLoadDef: postLoadDef
      },
    };
  });

  var defs = {
    "!name": "requirejs",
    "!define": {
      module: {
        id: "string",
        uri: "string",
        config: "fn() -> ?",
        exports: "?"
      }
    },
    requirejs: {
      "!type": "fn(deps: [string], callback: fn(), errback: fn()) -> !custom:requireJS",
      onError: "fn(err: +Error)",
      load: "fn(context: ?, moduleName: string, url: string)",
      config: "fn(config: ?) -> !custom:requireJSConfig",
      version: "string",
      isBrowser: "bool"
    },
    require: "requirejs",
    define: {
      "!type": "fn(deps: [string], callback: fn()) -> !custom:requireJS",
      amd: {
        jQuery: "bool"
      }
    }
  };
});
<|endoftext|>


<commit_before>// Plugin which registers mail received to a certain address
// and extracts a From: address from the mail and puts that address
// in the mail_from.blocklist file. You need to be running the
// mail_from.blocklist plugin for this to work fully.

var fs = require('fs');
var utils = require('./utils');

exports.hook_data = function (next, connection) {
    // enable mail body parsing
    connection.transaction.parse_body = 1;
    next();
}

exports.hook_data_post = function (next, connection) {
    var recip = (this.config.get('block_me.recipient') || '').toLowerCase();
    var senders = this.config.get('block_me.senders', 'list');

    // Make sure only 1 recipient
    if (connection.transaction.rcpt_to.length != 1) {
        return next();
    }

    // Check recipient is the right one
    if (connection.transaction.rcpt_to[0].address().toLowerCase() != recip) {
        return next();
    }

    // Check sender is in list
    var sender = connection.transaction.mail_from.address();
    if (!utils.in_array(sender, senders)) {
        return next(DENY, "You are not allowed to block mail, " + sender);
    }

    // Now extract the "From" from the body...
    var to_block = extract_from_line(connection.transaction.body);
    if (!to_block) {
        this.logerror("No sender found in email");
        return next();
    }

    this.loginfo("Blocking new sender: " + to_block);

    connection.transaction.notes.block_me = 1;

    // add to mail_from.blocklist
    fs.open('./config/mail_from.blocklist', 'a', function (err, fd) {
        if (!err) {
            fs.write(fd, to_block + "\n", null, 'UTF-8', function (err, written) {
                fs.close(fd);
            });
        }
        else {
            plugin.logerror("Unable to append to mail_from.blocklist: " + err);
        }
    });

    next();
}

exports.hook_queue = function (next, connection) {
    if (connection.transaction.notes.block_me) {
        // pretend we queued this mail
        return next(OK);
    }

    next();
}

// Example: From: 	Site Tucano Gold <contato@tucanogold.com.br>
function extract_from_line(body) {
    var matches = body.bodytext.match(/\bFrom:[^<\n]*<([^>\n]*)>/);
    if (matches) {
        return matches[1];
    }

    for (var i=0,l=body.children.length; i < l; i++) {
        var from = extract_from_line(body.children[i]);
        if (from) {
            return from;
        }
    }

    return null;
}
<commit_msg>Only run if relaying<commit_after>// Plugin which registers mail received to a certain address
// and extracts a From: address from the mail and puts that address
// in the mail_from.blocklist file. You need to be running the
// mail_from.blocklist plugin for this to work fully.

var fs = require('fs');
var utils = require('./utils');

exports.hook_data = function (next, connection) {
    // enable mail body parsing
    connection.transaction.parse_body = 1;
    next();
}

exports.hook_data_post = function (next, connection) {
    if (!connection.relaying) {
        return next();
    }

    var recip = (this.config.get('block_me.recipient') || '').toLowerCase();
    var senders = this.config.get('block_me.senders', 'list');

    // Make sure only 1 recipient
    if (connection.transaction.rcpt_to.length != 1) {
        return next();
    }

    // Check recipient is the right one
    if (connection.transaction.rcpt_to[0].address().toLowerCase() != recip) {
        return next();
    }

    // Check sender is in list
    var sender = connection.transaction.mail_from.address();
    if (!utils.in_array(sender, senders)) {
        return next(DENY, "You are not allowed to block mail, " + sender);
    }

    // Now extract the "From" from the body...
    var to_block = extract_from_line(connection.transaction.body);
    if (!to_block) {
        this.logerror("No sender found in email");
        return next();
    }

    this.loginfo("Blocking new sender: " + to_block);

    connection.transaction.notes.block_me = 1;

    // add to mail_from.blocklist
    fs.open('./config/mail_from.blocklist', 'a', function (err, fd) {
        if (!err) {
            fs.write(fd, to_block + "\n", null, 'UTF-8', function (err, written) {
                fs.close(fd);
            });
        }
        else {
            plugin.logerror("Unable to append to mail_from.blocklist: " + err);
        }
    });

    next();
}

exports.hook_queue = function (next, connection) {
    if (connection.transaction.notes.block_me) {
        // pretend we queued this mail
        return next(OK);
    }

    next();
}

// Example: From: 	Site Tucano Gold <contato@tucanogold.com.br>
function extract_from_line(body) {
    var matches = body.bodytext.match(/\bFrom:[^<\n]*<([^>\n]*)>/);
    if (matches) {
        return matches[1];
    }

    for (var i=0,l=body.children.length; i < l; i++) {
        var from = extract_from_line(body.children[i]);
        if (from) {
            return from;
        }
    }

    return null;
}
<|endoftext|>


<commit_before>function ChannelsPlugin(bot) {
	var self = this;
	self.name = "channels";
	self.help = "Channel management and autojoining";
	self.depend = ["cmd"];

	self.autojoins = [];
	self.autojoinTime = 5000;

	self.events = {
		"invite": function(channel, from) {
			bot.join(channel);
		},

		"cmd#join": function(nick, to, args) {
			for (var i = 1; i < args.length; i++)
				bot.join(args[i]);
		},

		"cmd#part": function(nick, to, args) {
			if (args.length > 1) {
				for (var i = 1; i < args.length; i++)
					bot.part(args[i]);
			}
			else
				bot.part(to);
		},

		"cmd#cycle": function(nick, to, args) {
			if (args.length > 1) {
				for (var i = 1; i < args.length; i++) {
					bot.part(args[i]);
					bot.join(args[i]);
				}
			}
			else {
				bot.part(to);
				bot.join(to);
			}
		},

		"cmd#autojoin": function(nick, to, args) {
			var chan = args[1] || to;
			var i = self.autojoins.indexOf(chan);
			if (i != -1) {
				self.autojoins.splice(i, 1);
				bot.say(to, "not autojoining " + chan);
			}
			else {
				self.autojoins.push(chan);
				bot.say(to, "autojoining " + chan);
				if (!(chan in bot.chans))
					bot.join(chan);
			}
		},

		"part": function(channel, nick) {
			if ((nick == bot.nick) && (self.autojoins.indexOf(channel) != -1))
				setTimeout(function() {
					bot.join(channel);
				}, self.autojoinTime);
		},

		"kick": function(channel, nick) {
			if ((nick == bot.nick) && (self.autojoins.indexOf(channel) != -1))
				setTimeout(function() {
					bot.join(channel);
				}, self.autojoinTime);
		}
	}
}

module.exports = ChannelsPlugin;
<commit_msg>Make autojoin channels persistent, require auth level to change<commit_after>function ChannelsPlugin(bot) {
	var self = this;
	self.name = "channels";
	self.help = "Channel management and autojoining";
	self.depend = ["cmd", "auth"];

	self.autojoins = [];
	self.autojoinTime = 5000;

	self.load = function(data) {
		if (data !== undefined) {
			self.autojoins = data.autojoins;
			self.autojoinTime = data.autojoinTime;
		}
	};

	self.unload = function() {
		var data = {};
		data.autojoins = self.autojoins;
		data.autojoinTime = self.autojoinTime;
		return data;
	};

	self.enable = function() {
		for (var i = 0; i < self.autojoins.length; i++) {
			bot.join(self.autojoins[i]);
		}
	};

	self.events = {
		"invite": function(channel, from) {
			bot.join(channel);
		},

		"cmd#join": function(nick, to, args) {
			for (var i = 1; i < args.length; i++)
				bot.join(args[i]);
		},

		"cmd#part": function(nick, to, args) {
			if (args.length > 1) {
				for (var i = 1; i < args.length; i++)
					bot.part(args[i]);
			}
			else
				bot.part(to);
		},

		"cmd#cycle": function(nick, to, args) {
			if (args.length > 1) {
				for (var i = 1; i < args.length; i++) {
					bot.part(args[i]);
					bot.join(args[i]);
				}
			}
			else {
				bot.part(to);
				bot.join(to);
			}
		},

		"cmd#autojoin": bot.plugins.auth.proxy(6, function(nick, to, args) {
			var chan = args[1] || to;
			var i = self.autojoins.indexOf(chan);
			if (i != -1) {
				self.autojoins.splice(i, 1);
				bot.say(to, "not autojoining " + chan);
			}
			else {
				self.autojoins.push(chan);
				bot.say(to, "autojoining " + chan);
				if (!(chan in bot.chans))
					bot.join(chan);
			}
		}),

		"cmd#autojoins": bot.plugins.auth.proxy(6, function(nick, to, args) {
			bot.say(to, "autojoins: " + self.autojoins.join(", "));
		}),

		"part": function(channel, nick) {
			if ((nick == bot.nick) && (self.autojoins.indexOf(channel) != -1))
				setTimeout(function() {
					bot.join(channel);
				}, self.autojoinTime);
		},

		"kick": function(channel, nick) {
			if ((nick == bot.nick) && (self.autojoins.indexOf(channel) != -1))
				setTimeout(function() {
					bot.join(channel);
				}, self.autojoinTime);
		}
	}
}

module.exports = ChannelsPlugin;
<|endoftext|>


<commit_before>document.getElementsByAttribute = Element.prototype.getElementsByAttribute = function(attr)
{
    var matches = [],
        elements = this.getElementsByTagName('*');
    for (var i = 0; i < elements.length; i++) {
        if ( elements[i].getAttribute(attr) ) matches.push(elements[i]);
    }
    return matches;
};s

//
data

// console.log(document.getElementsByAttribute('data-p'))[0];<commit_msg>removal of 's'<commit_after>document.getElementsByAttribute = Element.prototype.getElementsByAttribute = function(attr)
{
    var matches = [],
        elements = this.getElementsByTagName('*');
    for (var i = 0; i < elements.length; i++) {
        if ( elements[i].getAttribute(attr) ) matches.push(elements[i]);
    }
    return matches;
};

//
data

// console.log(document.getElementsByAttribute('data-p'))[0];<|endoftext|>