<commit_before>'use strict'

const slice            = require('../array/slice')
const apply            = require('../function/apply')
const merge            = require('./merge')
const assign           = require('./extend')
const compose          = require('./compose')
const isObject         = require('./is-object')
const isComposable     = require('./is-composable')
const extractFunctions = require('./extract-functions')

const rawUtilities = {
  methods : function methods() {
    let methodsObject = slice(arguments)
    return (this.compose || compose).call(this, {methods: apply(assign, undefined, [{}].concat(methodsObject))});
  },
  properties : function properties() {
    let propertiesObject = slice(arguments)
    return (this.compose || compose).call(this, {properties: apply(assign, undefined, [{}].concat(propertiesObject))});
  },
  initializers : function initializers() {
    let args = slice(arguments)
    return (this.compose || compose).call(this, {initializers: apply(extractFunctions, undefined, args)});
  },
  deepProperties : function deepProperties() {
    let propertiesObject = slice(arguments)
    return (this.compose || compose).call(this, {deepProperties: apply(merge, undefined, [{}].concat(propertiesObject))});
  },
  staticProperties : function staticProperties() {
    let propertiesObject = slice(arguments)
    return (this.compose || compose).call(this, {staticProperties: apply(assign, undefined, [{}].concat(propertiesObject))});
  },
  staticDeepProperties : function staticDeepProperties() {
    let propertiesObject = slice(arguments)
    return (this.compose || compose).call(this, {staticDeepProperties: apply(merge, undefined, [{}].concat(propertiesObject))});
  }
};

const baseStampit = compose({
  staticProperties: assign({
    refs: rawUtilities.properties,
    props: rawUtilities.properties,
    init: rawUtilities.initializers,
    deepProps: rawUtilities.deepProperties,
    statics: rawUtilities.staticProperties,

    create: function create () {
      return apply(this, undefined, arguments)
    }
  }, rawUtilities)
});

function stampit () {
  let _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]

  let methods = _ref.methods
  let properties = _ref.properties
  let props = _ref.props
  let refs = _ref.refs
  let initializers = _ref.initializers
  let init = _ref.init
  let deepProperties = _ref.deepProperties
  let deepProps = _ref.deepProps
  let propertyDescriptors = _ref.propertyDescriptors
  let staticProperties = _ref.staticProperties
  let statics = _ref.statics
  let staticDeepProperties = _ref.deepStaticProperties
  let staticPropertyDescriptors = _ref.staticPropertyDescriptors
  let configuration = _ref.configuration
  let deepConfiguration = _ref.deepConfiguration

  let args = slice(arguments, 1)

  const p = isObject(props) || isObject(refs) || isObject(properties)
    ? assign({}, props, refs, properties)
    : undefined;

  const dp = isObject(deepProps) || isObject(deepProperties)
    ? merge({}, deepProps, deepProperties)
    : undefined;

  const sp = isObject(statics) || isObject(staticProperties)
    ? assign({}, statics, staticProperties)
    : undefined;

  return apply(baseStampit.compose, baseStampit, [{
    methods: methods,
    properties: p,
    initializers: extractFunctions(init, initializers),
    deepProperties: dp,
    staticProperties: sp,
    staticDeepProperties: staticDeepProperties,
    propertyDescriptors: propertyDescriptors,
    staticPropertyDescriptors: staticPropertyDescriptors,
    configuration: configuration,
    deepConfiguration: deepConfiguration
  }].concat(args))
}

module.exports = assign(stampit, {
  isStamp: isComposable,
  isComposable: isComposable,
  compose: baseStampit.compose,
  refs: rawUtilities.properties,
  props: rawUtilities.properties,
  init: rawUtilities.initializers,
  deepProps: rawUtilities.deepProperties,
  statics: rawUtilities.staticProperties
}, rawUtilities)
<commit_msg>lint object/stamp<commit_after>'use strict'

const slice            = require('../array/slice')
const apply            = require('../function/apply')
const merge            = require('./merge')
const assign           = require('./extend')
const compose          = require('./compose')
const isObject         = require('./is-object')
const isComposable     = require('./is-composable')
const extractFunctions = require('./extract-functions')

const rawUtilities = {
  methods : function methods () {
    let methodsObject = slice(arguments)
    return (this.compose || compose).call(this, {methods: apply(assign, undefined, [{}].concat(methodsObject))})
  },
  properties : function properties () {
    let propertiesObject = slice(arguments)
    return (this.compose || compose).call(this, {properties: apply(assign, undefined, [{}].concat(propertiesObject))})
  },
  initializers : function initializers () {
    let args = slice(arguments)
    return (this.compose || compose).call(this, {initializers: apply(extractFunctions, undefined, args)})
  },
  deepProperties : function deepProperties () {
    let propertiesObject = slice(arguments)
    return (this.compose || compose).call(this, {deepProperties: apply(merge, undefined, [{}].concat(propertiesObject))})
  },
  staticProperties : function staticProperties () {
    let propertiesObject = slice(arguments)
    return (this.compose || compose).call(this, {staticProperties: apply(assign, undefined, [{}].concat(propertiesObject))})
  },
  staticDeepProperties : function staticDeepProperties () {
    let propertiesObject = slice(arguments)
    return (this.compose || compose).call(this, {staticDeepProperties: apply(merge, undefined, [{}].concat(propertiesObject))})
  }
}

const baseStampit = compose({
  staticProperties: assign({
    refs: rawUtilities.properties,
    props: rawUtilities.properties,
    init: rawUtilities.initializers,
    deepProps: rawUtilities.deepProperties,
    statics: rawUtilities.staticProperties,

    create: function create () {
      return apply(this, undefined, arguments)
    }
  }, rawUtilities)
})

function stampit () {
  let _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]

  let methods = _ref.methods
  let properties = _ref.properties
  let props = _ref.props
  let refs = _ref.refs
  let initializers = _ref.initializers
  let init = _ref.init
  let deepProperties = _ref.deepProperties
  let deepProps = _ref.deepProps
  let propertyDescriptors = _ref.propertyDescriptors
  let staticProperties = _ref.staticProperties
  let statics = _ref.statics
  let staticDeepProperties = _ref.deepStaticProperties
  let staticPropertyDescriptors = _ref.staticPropertyDescriptors
  let configuration = _ref.configuration
  let deepConfiguration = _ref.deepConfiguration

  let args = slice(arguments, 1)

  const p = isObject(props) || isObject(refs) || isObject(properties)
    ? assign({}, props, refs, properties)
    : undefined

  const dp = isObject(deepProps) || isObject(deepProperties)
    ? merge({}, deepProps, deepProperties)
    : undefined

  const sp = isObject(statics) || isObject(staticProperties)
    ? assign({}, statics, staticProperties)
    : undefined

  return apply(baseStampit.compose, baseStampit, [{
    methods: methods,
    properties: p,
    initializers: extractFunctions(init, initializers),
    deepProperties: dp,
    staticProperties: sp,
    staticDeepProperties: staticDeepProperties,
    propertyDescriptors: propertyDescriptors,
    staticPropertyDescriptors: staticPropertyDescriptors,
    configuration: configuration,
    deepConfiguration: deepConfiguration
  }].concat(args))
}

module.exports = assign(stampit, {
  isStamp: isComposable,
  isComposable: isComposable,
  compose: baseStampit.compose,
  refs: rawUtilities.properties,
  props: rawUtilities.properties,
  init: rawUtilities.initializers,
  deepProps: rawUtilities.deepProperties,
  statics: rawUtilities.staticProperties
}, rawUtilities)
<|endoftext|>


<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 */

THREE.Line = function ( geometry, material, mode ) {

	if ( mode === 1 ) {

		console.error( 'THREE.Line: THREE.LinePieces mode has been removed. Use THREE.LineSegments instead.' );

	}

	THREE.Object3D.call( this );

	this.type = 'Line';

	this.geometry = geometry !== undefined ? geometry : new THREE.Geometry();
	this.material = material !== undefined ? material : new THREE.LineBasicMaterial( { color: Math.random() * 0xffffff } );

};

THREE.Line.prototype = Object.create( THREE.Object3D.prototype );
THREE.Line.prototype.constructor = THREE.Line;

THREE.Line.prototype.raycast = ( function () {

	var inverseMatrix = new THREE.Matrix4();
	var ray = new THREE.Ray();
	var sphere = new THREE.Sphere();

	return function raycast( raycaster, intersects ) {

		var precision = raycaster.linePrecision;
		var precisionSq = precision * precision;

		var geometry = this.geometry;

		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();

		// Checking boundingSphere distance to ray

		sphere.copy( geometry.boundingSphere );
		sphere.applyMatrix4( this.matrixWorld );

		if ( raycaster.ray.isIntersectionSphere( sphere ) === false ) {

			return;

		}

		inverseMatrix.getInverse( this.matrixWorld );
		ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );

		var vStart = new THREE.Vector3();
		var vEnd = new THREE.Vector3();
		var interSegment = new THREE.Vector3();
		var interRay = new THREE.Vector3();
		var step = this instanceof THREE.LineSegments ? 2 : 1;

		if ( geometry instanceof THREE.BufferGeometry ) {

			var attributes = geometry.attributes;

			if ( attributes.index !== undefined ) {

				var indices = attributes.index.array;
				var positions = attributes.position.array;
				var offsets = geometry.groups;

				if ( offsets.length === 0 ) {

					offsets = [ {
						start: 0,
						count: indices.length
					} ];

				}

				for ( var oi = 0; oi < offsets.length; oi ++ ) {

					var offset = offsets[ oi ];

					var start = offset.start;
					var count = offset.count;

					for ( var i = start; i < start + count - 1; i += step ) {

						var a = indices[ i ];
						var b = indices[ i + 1 ];

						vStart.fromArray( positions, a * 3 );
						vEnd.fromArray( positions, b * 3 );

						var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );

						if ( distSq > precisionSq ) continue;

						var distance = ray.origin.distanceTo( interRay );

						if ( distance < raycaster.near || distance > raycaster.far ) continue;

						intersects.push( {

							distance: distance,
							// What do we want? intersection point on the ray or on the segment??
							// point: raycaster.ray.at( distance ),
							point: interSegment.clone().applyMatrix4( this.matrixWorld ),
							index: i,
							offsetIndex: oi,
							face: null,
							faceIndex: null,
							object: this

						} );

					}

				}

			} else {

				var positions = attributes.position.array;

				for ( var i = 0; i < positions.length / 3 - 1; i += step ) {

					vStart.fromArray( positions, 3 * i );
					vEnd.fromArray( positions, 3 * i + 3 );

					var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );

					if ( distSq > precisionSq ) continue;

					var distance = ray.origin.distanceTo( interRay );

					if ( distance < raycaster.near || distance > raycaster.far ) continue;

					intersects.push( {

						distance: distance,
						// What do we want? intersection point on the ray or on the segment??
						// point: raycaster.ray.at( distance ),
						point: interSegment.clone().applyMatrix4( this.matrixWorld ),
						index: i,
						face: null,
						faceIndex: null,
						object: this

					} );

				}

			}

		} else if ( geometry instanceof THREE.Geometry ) {

			var vertices = geometry.vertices;
			var nbVertices = vertices.length;

			for ( var i = 0; i < nbVertices - 1; i += step ) {

				var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );

				if ( distSq > precisionSq ) continue;

				var distance = ray.origin.distanceTo( interRay );

				if ( distance < raycaster.near || distance > raycaster.far ) continue;

				intersects.push( {

					distance: distance,
					// What do we want? intersection point on the ray or on the segment??
					// point: raycaster.ray.at( distance ),
					point: interSegment.clone().applyMatrix4( this.matrixWorld ),
					index: i,
					face: null,
					faceIndex: null,
					object: this

				} );

			}

		}

	};

}() );

THREE.Line.prototype.clone = function () {

	return new this.constructor( this.geometry, this.material ).copy( this );

};

THREE.Line.prototype.toJSON = function ( meta ) {

	var data = THREE.Object3D.prototype.toJSON.call( this, meta );

	// only serialize if not in meta geometries cache
	if ( meta.geometries[ this.geometry.uuid ] === undefined ) {

		meta.geometries[ this.geometry.uuid ] = this.geometry.toJSON();

	}

	// only serialize if not in meta materials cache
	if ( meta.materials[ this.material.uuid ] === undefined ) {

		meta.materials[ this.material.uuid ] = this.material.toJSON();

	}

	data.object.geometry = this.geometry.uuid;
	data.object.material = this.material.uuid;

	return data;

};

// DEPRECATED

THREE.LineStrip = 0;
THREE.LinePieces = 1;
<commit_msg>Line: Nicer backwards compatibility for THREE.LinePieces.<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 */

THREE.Line = function ( geometry, material, mode ) {

	if ( mode === 1 ) {

		console.warn( 'THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.' );
		return new THREE.LineSegments( geometry, material );

	}

	THREE.Object3D.call( this );

	this.type = 'Line';

	this.geometry = geometry !== undefined ? geometry : new THREE.Geometry();
	this.material = material !== undefined ? material : new THREE.LineBasicMaterial( { color: Math.random() * 0xffffff } );

};

THREE.Line.prototype = Object.create( THREE.Object3D.prototype );
THREE.Line.prototype.constructor = THREE.Line;

THREE.Line.prototype.raycast = ( function () {

	var inverseMatrix = new THREE.Matrix4();
	var ray = new THREE.Ray();
	var sphere = new THREE.Sphere();

	return function raycast( raycaster, intersects ) {

		var precision = raycaster.linePrecision;
		var precisionSq = precision * precision;

		var geometry = this.geometry;

		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();

		// Checking boundingSphere distance to ray

		sphere.copy( geometry.boundingSphere );
		sphere.applyMatrix4( this.matrixWorld );

		if ( raycaster.ray.isIntersectionSphere( sphere ) === false ) {

			return;

		}

		inverseMatrix.getInverse( this.matrixWorld );
		ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );

		var vStart = new THREE.Vector3();
		var vEnd = new THREE.Vector3();
		var interSegment = new THREE.Vector3();
		var interRay = new THREE.Vector3();
		var step = this instanceof THREE.LineSegments ? 2 : 1;

		if ( geometry instanceof THREE.BufferGeometry ) {

			var attributes = geometry.attributes;

			if ( attributes.index !== undefined ) {

				var indices = attributes.index.array;
				var positions = attributes.position.array;
				var offsets = geometry.groups;

				if ( offsets.length === 0 ) {

					offsets = [ {
						start: 0,
						count: indices.length
					} ];

				}

				for ( var oi = 0; oi < offsets.length; oi ++ ) {

					var offset = offsets[ oi ];

					var start = offset.start;
					var count = offset.count;

					for ( var i = start; i < start + count - 1; i += step ) {

						var a = indices[ i ];
						var b = indices[ i + 1 ];

						vStart.fromArray( positions, a * 3 );
						vEnd.fromArray( positions, b * 3 );

						var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );

						if ( distSq > precisionSq ) continue;

						var distance = ray.origin.distanceTo( interRay );

						if ( distance < raycaster.near || distance > raycaster.far ) continue;

						intersects.push( {

							distance: distance,
							// What do we want? intersection point on the ray or on the segment??
							// point: raycaster.ray.at( distance ),
							point: interSegment.clone().applyMatrix4( this.matrixWorld ),
							index: i,
							offsetIndex: oi,
							face: null,
							faceIndex: null,
							object: this

						} );

					}

				}

			} else {

				var positions = attributes.position.array;

				for ( var i = 0; i < positions.length / 3 - 1; i += step ) {

					vStart.fromArray( positions, 3 * i );
					vEnd.fromArray( positions, 3 * i + 3 );

					var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );

					if ( distSq > precisionSq ) continue;

					var distance = ray.origin.distanceTo( interRay );

					if ( distance < raycaster.near || distance > raycaster.far ) continue;

					intersects.push( {

						distance: distance,
						// What do we want? intersection point on the ray or on the segment??
						// point: raycaster.ray.at( distance ),
						point: interSegment.clone().applyMatrix4( this.matrixWorld ),
						index: i,
						face: null,
						faceIndex: null,
						object: this

					} );

				}

			}

		} else if ( geometry instanceof THREE.Geometry ) {

			var vertices = geometry.vertices;
			var nbVertices = vertices.length;

			for ( var i = 0; i < nbVertices - 1; i += step ) {

				var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );

				if ( distSq > precisionSq ) continue;

				var distance = ray.origin.distanceTo( interRay );

				if ( distance < raycaster.near || distance > raycaster.far ) continue;

				intersects.push( {

					distance: distance,
					// What do we want? intersection point on the ray or on the segment??
					// point: raycaster.ray.at( distance ),
					point: interSegment.clone().applyMatrix4( this.matrixWorld ),
					index: i,
					face: null,
					faceIndex: null,
					object: this

				} );

			}

		}

	};

}() );

THREE.Line.prototype.clone = function () {

	return new this.constructor( this.geometry, this.material ).copy( this );

};

THREE.Line.prototype.toJSON = function ( meta ) {

	var data = THREE.Object3D.prototype.toJSON.call( this, meta );

	// only serialize if not in meta geometries cache
	if ( meta.geometries[ this.geometry.uuid ] === undefined ) {

		meta.geometries[ this.geometry.uuid ] = this.geometry.toJSON();

	}

	// only serialize if not in meta materials cache
	if ( meta.materials[ this.material.uuid ] === undefined ) {

		meta.materials[ this.material.uuid ] = this.material.toJSON();

	}

	data.object.geometry = this.geometry.uuid;
	data.object.material = this.material.uuid;

	return data;

};

// DEPRECATED

THREE.LineStrip = 0;
THREE.LinePieces = 1;
<|endoftext|>


<commit_before>(function(timbre) {
    "use strict";

    function WaveListener(_args) {
        timbre.ListenerObject.call(this, _args);

        this._.buffer = new Float32Array(1024);
        this._.samples    = 0;
        this._.writeIndex = 0;

        this._.plotFlush = true;

        this.once("init", oninit);

        timbre.fn.fixAR(this);
    }
    timbre.fn.extend(WaveListener, timbre.ListenerObject);

    var oninit = function() {
        if (!this._.interval) {
            this.interval = 1000;
        }
    };

    var $ = WaveListener.prototype;

    Object.defineProperties($, {
        interval: {
            set: function(value) {
                var _ = this._;
                if (typeof value === "number" && value > 0) {
                    _.interval    = value;
                    _.samplesIncr = value * 0.001 * timbre.samplerate / 1024;
                    if (_.samplesIncr < 1) {
                        _.samplesIncr = 1;
                    }
                }
            },
            get: function() {
                return this._.interval;
            }
        }
    });

    $.bang = function() {
        var _ = this._;
        var buffer = _.buffer;

        for (var i = 1024; i--; ) {
            buffer[i] = 0;
        }
        _.samples    = 0;
        _.writeIndex = 0;
        this.emit("bang");
        return this;
    };

    $.seq = function(seq_id) {
        var _ = this._;
        var cell = this.cell;

        if (this.seq_id !== seq_id) {
            this.seq_id = seq_id;

            var inputs = this.inputs;
            var i, imax = inputs.length;
            var j, jmax = cell.length;
            var tmp;

            for (j = jmax; j--; ) {
                cell[j] = 0;
            }

            for (i = 0; i < imax; ++i) {
                tmp = inputs[i].seq(seq_id);
                for (j = jmax; j--; ) {
                    cell[j] += tmp[j];
                }
            }

            var samples     = _.samples;
            var samplesIncr = _.samplesIncr;
            var buffer      = _.buffer;
            var writeIndex  = _.writeIndex;
            var emit = false;
            var mul = _.mul, add = _.add;

            for (j = 0; j < jmax; ++j) {
                if (samples <= 0) {
                    buffer[writeIndex++] = cell[j];
                    writeIndex &= 1023;
                    emit = _.plotFlush = true;
                    samples += samplesIncr;
                }
                cell[j] = cell[j] * mul + add;
                --samples;
            }
            _.samples    = samples;
            _.writeIndex = writeIndex;

            if (emit) {
                this.emit("wave");
            }
        }

        return cell;
    };

    $.plot = function(opts) {
        var _ = this._;
        if (_.plotFlush) {
            var data   = new Float32Array(1024);
            var buffer = _.buffer;
            for (var i = 0, j = _.writeIndex; i < 1024; i++) {
                data[i] = buffer[++j & 1023];
            }
            _.plotData  = data;
            _.plotFlush = null;
        }
        return WaveListener.__super__.plot.call(this, opts);
    };

    timbre.fn.register("wave", WaveListener);
})(timbre);
<commit_msg>add property T("wave").size<commit_after>(function(timbre) {
    "use strict";

    function WaveListener(_args) {
        timbre.ListenerObject.call(this, _args);

        this._.samples    = 0;
        this._.writeIndex = 0;

        this._.plotFlush = true;

        this.once("init", oninit);

        timbre.fn.fixAR(this);
    }
    timbre.fn.extend(WaveListener, timbre.ListenerObject);

    var oninit = function() {
        if (!this._.buffer) {
            this.size = 1024;
        }
        if (!this._.interval) {
            this.interval = 1000;
        }
    };

    var $ = WaveListener.prototype;

    Object.defineProperties($, {
        size: {
            set: function(value) {
                var _ = this._;
                if (!_.buffer) {
                    if (typeof value === "number") {
                        var n = (value < 64) ? 64 : (value > 2048) ? 2048 : value;
                        _.buffer = new Float32Array(n);
                        if (_.reservedinterval) {
                            this.interval = _.reservedinterval;
                            _.reservedinterval = null;
                        }
                    }
                }
            },
            get: function() {
                return this._.buffer.length;
            }
        },
        interval: {
            set: function(value) {
                var _ = this._;
                if (typeof value === "number" && value > 0) {
                    if (!_.buffer) {
                        _.reservedinterval = value;
                    } else {
                        _.interval    = value;
                        _.samplesIncr = value * 0.001 * timbre.samplerate / _.buffer.length;
                        if (_.samplesIncr < 1) {
                            _.samplesIncr = 1;
                        }
                    }
                }
            },
            get: function() {
                return this._.interval;
            }
        }
    });

    $.bang = function() {
        var _ = this._;
        var buffer = _.buffer;

        for (var i = buffer.length; i--; ) {
            buffer[i] = 0;
        }
        _.samples    = 0;
        _.writeIndex = 0;
        this.emit("bang");
        return this;
    };

    $.seq = function(seq_id) {
        var _ = this._;
        var cell = this.cell;

        if (this.seq_id !== seq_id) {
            this.seq_id = seq_id;

            var inputs = this.inputs;
            var i, imax = inputs.length;
            var j, jmax = cell.length;
            var tmp;

            for (j = jmax; j--; ) {
                cell[j] = 0;
            }

            for (i = 0; i < imax; ++i) {
                tmp = inputs[i].seq(seq_id);
                for (j = jmax; j--; ) {
                    cell[j] += tmp[j];
                }
            }

            var samples     = _.samples;
            var samplesIncr = _.samplesIncr;
            var buffer      = _.buffer;
            var writeIndex  = _.writeIndex;
            var emit = false;
            var mul = _.mul, add = _.add;
            var mask = buffer.length - 1;

            for (j = 0; j < jmax; ++j) {
                if (samples <= 0) {
                    buffer[writeIndex++] = cell[j];
                    writeIndex &= mask;
                    emit = _.plotFlush = true;
                    samples += samplesIncr;
                }
                cell[j] = cell[j] * mul + add;
                --samples;
            }
            _.samples    = samples;
            _.writeIndex = writeIndex;

            if (emit) {
                this.emit("wave");
            }
        }

        return cell;
    };

    $.plot = function(opts) {
        var _ = this._;
        if (_.plotFlush) {
            var buffer = _.buffer;
            var mask   = buffer.length - 1;
            var data   = new Float32Array(buffer.length);
            var j = _.writeIndex;
            for (var i = 0, imax = buffer.length; i < imax; i++) {
                data[i] = buffer[++j & mask];
            }
            _.plotData  = data;
            _.plotFlush = null;
        }
        return WaveListener.__super__.plot.call(this, opts);
    };

    timbre.fn.register("wave", WaveListener);
})(timbre);
<|endoftext|>


<commit_before>module.exports = Observations;
var Class = require('chip-utils/class');
var LinkedList = require('chip-utils/linked-list');
var Observer = require('./observer');
var computed = require('./computed');
var ObservableHash = require('./observable-hash');
var expressions = require('expressions-js');

var queue = setTimeout;
var cancelQueue = clearTimeout;

if (global.Promise) {
  var currentQueueId = 1;
  var queued = {};

  queue = function(listener) {
    var reqId = currentQueueId++;
    queued[reqId] = true;
    Promise.resolve().then(function() {
      if (queued[reqId]) {
        delete queued[reqId];
        listener();
      }
    });
    return reqId;
  };

  cancelQueue = function(reqId) {
    delete queued[reqId];
  };
}

function Observations() {
  // Bind all methods to this instance
  Object.getOwnPropertyNames(this.constructor.prototype).forEach(function(name) {
    if (typeof this[name] === 'function') {
      this[name] = this[name].bind(this);
    }
  }, this);
  this.globals = {};
  this.formatters = {};
  this.observers = new LinkedList();
  this.callbacks = [];
  this.listeners = [];
  this.syncing = false;
  this.callbacksRunning = false;
  this.rerun = false;
  this.cycles = 0;
  this.maxCycles = 10;
  this.timeout = null;
  this.pendingSync = null;
  this.computed = computed.create(this);
  this.expressions = expressions;
}

Class.extend(Observations, {
  ObservableHash: ObservableHash,

  /**
   * Creates a new ObservableHash with useful methods for managing data using watch, track, and computed.
   * @param {Object} computedMap [OPTIONAL] An initial computed map for this hash
   * @return {ObservableHash} An object for putting your data on for accessibility
   */
  createHash: function(computedMap) {
    var hash = new ObservableHash(this);
    if (computedMap) hash.addComputed(computedMap);
    return hash;
  },

  /**
   * Observes any changes to the result of the expression on the context object and calls the callback.
   * @param {Object} context The context to bind the expression against
   * @param {String} expression The expression to observe
   * @param {Function} onChange The function which will be called when the expression value changes
   * @return {Observer} The observer created
   */
  watch: function(context, expression, onChange, callbackContext) {
    var observer = this.createObserver(expression, onChange, callbackContext || context);
    observer.bind(context);
    return observer;
  },

  // Alias for `watch`, DEPRECATED
  observe: function(context, expression, onChange, callbackContext) {
    return this.watch(context, expression, onChange, callbackContext);
  },

  /**
   * Observe an expression and call `onAdd` and `onRemove` whenever a member is added/removed from the array or object.
   * @param {Object} context The context to bind the expression against
   * @param {String} expression The expression to observe
   * @param {Function} onAdd The function which will be called when a member is added to the source
   * @param {Function} onRemove The function which will be called when a member is removed from the source
   * @return {Observer} The observer created
   */
  track: function(context, expression, onAdd, onRemove, callbackContext) {
    var observer = this.createMemberObserver(expression, onAdd, onRemove, callbackContext);
    observer.bind(context);
    return observer;
  },

  // Alias for `createMemberObserver`, DEPRECATED
  observeMembers: function(expression, onAdd, onRemove, callbackContext) {
    return this.createMemberObserver(expression, onAdd, onRemove, callbackContext);
  },

  /**
   * Creates a new observer attached to this observations object. When the observer is bound to a context it will be
   * added to this `observations` and synced when this `observations.sync` is called.
   * @param {String} expression The expression to observe
   * @param {Function} callback The function which will be called when the expression value changes
   * @return {Observer} The observer
   */
  createObserver: function(expression, callback, callbackContext) {
    return new Observer(this, expression, callback, callbackContext);
  },

  /**
   * Observe an expression and call `onAdd` and `onRemove` whenever a member is added/removed from the array or object.
   * @param {String} expression The expression to observe
   * @param {Function} onAdd The function which will be called when a member is added to the source
   * @param {Function} onRemove The function which will be called when a member is removed from the source
   * @return {Observer} The observer
   */
  createMemberObserver: function(expression, onAdd, onRemove, callbackContext) {
    if (!onAdd) onAdd = function(){};
    if (!onRemove) onRemove = function(){};

    var observer = this.createObserver(expression, this.createMemberObserverCallback.bind(this, onAdd, onRemove, callbackContext));

    observer.getChangeRecords = true;
    return observer;
  },

  createMemberObserverCallback: function(onAdd, onRemove, callbackContext, source, oldValue, changes) {
    if (changes) {
      // call onRemoved on everything first
      changes.forEach(function(change) {
        if (change.type === 'splice') {
          change.removed.forEach(function(item, index) {
            // Only call onRemove if this item was removed completely, not if it just changed location in the array
            if (source.indexOf(item) === -1) {
              onRemove.call(callbackContext, item, index + change.index);
            }
          }, callbackContext);
        } else {
          if (change.oldValue != null) {
            onRemove.call(callbackContext, change.oldValue, change.name);
          }
        }
      });

      // call onAdded second, allowing for items that changed location to be accurately processed
      changes.forEach(function(change) {
        if (change.type === 'splice') {
          source.slice(change.index, change.index + change.addedCount).forEach(function(item, index) {
            // Only call onAdd if this item was added, not if it changed location in the array
            if (oldValue.indexOf(item) === -1) {
              onAdd.call(callbackContext, item, index + change.index, source);
            }
          }, callbackContext);
        } else {
          var value = source[change.name];
          if (value != null) {
            onAdd.call(callbackContext, value, change.name, source);
          }
        }
      });
    } else if (Array.isArray(source)) {
      source.forEach(onAdd, callbackContext);
    } else if (source && typeof source === 'object') {
      Object.keys(source).forEach(function(key) {
        var value = source[key];
        if (value != null) {
          onAdd.call(callbackContext, value, key, source);
        }
      });
    } else if (Array.isArray(oldValue)) {
      oldValue.forEach(onRemove, callbackContext);
    } else if (oldValue && typeof oldValue === 'object') {
      // If undefined (or something that isn't an array/object) remove the observers
      Object.keys(oldValue).forEach(function(key) {
        var value = oldValue[key];
        if (value != null) {
          onRemove.call(callbackContext, value, key, oldValue);
        }
      });
    }
  },

  /**
   * Parses an expression into a function using the globals and formatters objects associated with this instance of
   * observations.
   * @param {String} expression The expression string to parse into a function
   * @param {Object} options Additional options to pass to the parser.
   *                        `{ isSetter: true }` will make this expression a setter that accepts a value.
   *                        `{ extraArgs: [ 'argName' ]` will make extra arguments to pass in to the function.
   * @return {Function} A function that may be called to execute the expression (call it against a context using=
   * `func.call(context)` in order to get the data from the context correct)
   */
  getExpression: function(expression, options) {
    if (options && options.isSetter) {
      return expressions.parseSetter(expression, this.globals, this.formatters, options.extraArgs);
    } else if (options && options.extraArgs) {
      var allArgs = [expression, this.globals, this.formatters].concat(options.extraArgs);
      return expressions.parse.apply(expressions, allArgs);
    } else {
      return expressions.parse(expression, this.globals, this.formatters);
    }
  },

  /**
   * Gets the value of an expression from the given context object
   * @param {Object} context The context object the expression will be evaluated against
   * @param {String} expression The expression to evaluate
   * @return {mixed} The result of the expression against the context
   */
  get: function(context, expression) {
    return this.getExpression(expression).call(context);
  },

  /**
   * Sets the value on the expression in the given context object
   * @param {Object} context The context object the expression will be evaluated against
   * @param {String} expression The expression to set a value with
   * @param {mixed} value The value to set on the expression
   * @return {mixed} The result of the expression against the context
   */
  set: function(source, expression, value) {
    return this.getExpression(expression, { isSetter: true }).call(source, value);
  },

  // Schedules an observer sync cycle which checks all the observers to see if they've changed.
  sync: function(callback) {
    if (typeof callback === 'function') {
      this.afterSync(callback);
    }

    if (this.pendingSync) {
      return false;
    }

    this.pendingSync = queue(this.syncNow);
    return true;
  },

  // Runs the observer sync cycle which checks all the observers to see if they've changed.
  syncNow: function(callback) {
    if (typeof callback === 'function') {
      this.afterSync(callback);
    }

    cancelQueue(this.pendingSync);
    this.pendingSync = null;

    if (this.syncing) {
      this.rerun = true;
      return false;
    }

    this.runSync();
    return true;
  },

  runSync: function() {
    this.syncing = true;
    this.rerun = true;
    this.cycles = 0;

    var i, l;

    // Allow callbacks to run the sync cycle again immediately, but stop at `maxCyles` (default 10) cycles so we don't
    // run infinite loops
    while (this.rerun) {
      if (++this.cycles === this.maxCycles) {
        throw new Error('Infinite observer syncing, an observer is calling Observer.sync() too many times');
      }
      this.rerun = false;
      // the observer array may increase or decrease in size (remaining observers) during the sync
      this.observers.forEach(syncObserver);
    }

    this.callbacksRunning = true;

    var callbacks = this.callbacks;
    this.callbacks = [];
    while (callbacks.length) {
      callbacks.shift()();
    }

    for (i = 0, l = this.listeners.length; i < l; i++) {
      var listener = this.listeners[i];
      listener();
    }

    this.callbacksRunning = false;
    this.syncing = false;
    this.cycles = 0;
  },

  // After the next sync (or the current if in the middle of one), run the provided callback
  afterSync: function(callback) {
    if (typeof callback !== 'function') {
      throw new TypeError('callback must be a function');
    }

    if (this.callbacksRunning) {
      this.sync();
    }

    this.callbacks.push(callback);
  },

  onSync: function(listener) {
    if (typeof listener !== 'function') {
      throw new TypeError('listener must be a function');
    }

    this.listeners.push(listener);
  },

  offSync: function(listener) {
    if (typeof listener !== 'function') {
      throw new TypeError('listener must be a function');
    }

    var index = this.listeners.indexOf(listener);
    if (index !== -1) {
      this.listeners.splice(index, 1).pop();
    }
  },

  // Adds a new observer to be synced with changes. If `skipUpdate` is true then the callback will only be called when a
  // change is made, not initially.
  add: function(observer, skipUpdate) {
    this.observers.add(observer);
    if (!skipUpdate) {
      observer.forceUpdateNextSync = true;
      observer.sync();
    }
  },

  // Removes an observer, stopping it from being run
  remove: function(observer) {
    this.observers.remove(observer);
  },

});

function syncObserver(observer) {
  observer.sync();
}
<commit_msg>Revert "Move away from requestAnimationFrame"<commit_after>module.exports = Observations;
var Class = require('chip-utils/class');
var LinkedList = require('chip-utils/linked-list');
var Observer = require('./observer');
var computed = require('./computed');
var ObservableHash = require('./observable-hash');
var expressions = require('expressions-js');
var requestAnimationFrame = global.requestAnimationFrame || setTimeout;
var cancelAnimationFrame = global.cancelAnimationFrame || clearTimeout;

function Observations() {
  // Bind all methods to this instance
  Object.getOwnPropertyNames(this.constructor.prototype).forEach(function(name) {
    if (typeof this[name] === 'function') {
      this[name] = this[name].bind(this);
    }
  }, this);
  this.globals = {};
  this.formatters = {};
  this.observers = new LinkedList();
  this.callbacks = [];
  this.listeners = [];
  this.syncing = false;
  this.callbacksRunning = false;
  this.rerun = false;
  this.cycles = 0;
  this.maxCycles = 10;
  this.timeout = null;
  this.pendingSync = null;
  this.computed = computed.create(this);
  this.expressions = expressions;
  this.windows = [ window ];
}

Class.extend(Observations, {
  ObservableHash: ObservableHash,

  /**
   * Creates a new ObservableHash with useful methods for managing data using watch, track, and computed.
   * @param {Object} computedMap [OPTIONAL] An initial computed map for this hash
   * @return {ObservableHash} An object for putting your data on for accessibility
   */
  createHash: function(computedMap) {
    var hash = new ObservableHash(this);
    if (computedMap) hash.addComputed(computedMap);
    return hash;
  },

  /**
   * Observes any changes to the result of the expression on the context object and calls the callback.
   * @param {Object} context The context to bind the expression against
   * @param {String} expression The expression to observe
   * @param {Function} onChange The function which will be called when the expression value changes
   * @return {Observer} The observer created
   */
  watch: function(context, expression, onChange, callbackContext) {
    var observer = this.createObserver(expression, onChange, callbackContext || context);
    observer.bind(context);
    return observer;
  },

  // Alias for `watch`, DEPRECATED
  observe: function(context, expression, onChange, callbackContext) {
    return this.watch(context, expression, onChange, callbackContext);
  },

  /**
   * Observe an expression and call `onAdd` and `onRemove` whenever a member is added/removed from the array or object.
   * @param {Object} context The context to bind the expression against
   * @param {String} expression The expression to observe
   * @param {Function} onAdd The function which will be called when a member is added to the source
   * @param {Function} onRemove The function which will be called when a member is removed from the source
   * @return {Observer} The observer created
   */
  track: function(context, expression, onAdd, onRemove, callbackContext) {
    var observer = this.createMemberObserver(expression, onAdd, onRemove, callbackContext);
    observer.bind(context);
    return observer;
  },

  // Alias for `createMemberObserver`, DEPRECATED
  observeMembers: function(expression, onAdd, onRemove, callbackContext) {
    return this.createMemberObserver(expression, onAdd, onRemove, callbackContext);
  },

  /**
   * Creates a new observer attached to this observations object. When the observer is bound to a context it will be
   * added to this `observations` and synced when this `observations.sync` is called.
   * @param {String} expression The expression to observe
   * @param {Function} callback The function which will be called when the expression value changes
   * @return {Observer} The observer
   */
  createObserver: function(expression, callback, callbackContext) {
    return new Observer(this, expression, callback, callbackContext);
  },

  /**
   * Observe an expression and call `onAdd` and `onRemove` whenever a member is added/removed from the array or object.
   * @param {String} expression The expression to observe
   * @param {Function} onAdd The function which will be called when a member is added to the source
   * @param {Function} onRemove The function which will be called when a member is removed from the source
   * @return {Observer} The observer
   */
  createMemberObserver: function(expression, onAdd, onRemove, callbackContext) {
    if (!onAdd) onAdd = function(){};
    if (!onRemove) onRemove = function(){};

    var observer = this.createObserver(expression, this.createMemberObserverCallback.bind(this, onAdd, onRemove, callbackContext));

    observer.getChangeRecords = true;
    return observer;
  },

  createMemberObserverCallback: function(onAdd, onRemove, callbackContext, source, oldValue, changes) {
    if (changes) {
      // call onRemoved on everything first
      changes.forEach(function(change) {
        if (change.type === 'splice') {
          change.removed.forEach(function(item, index) {
            // Only call onRemove if this item was removed completely, not if it just changed location in the array
            if (source.indexOf(item) === -1) {
              onRemove.call(callbackContext, item, index + change.index);
            }
          }, callbackContext);
        } else {
          if (change.oldValue != null) {
            onRemove.call(callbackContext, change.oldValue, change.name);
          }
        }
      });

      // call onAdded second, allowing for items that changed location to be accurately processed
      changes.forEach(function(change) {
        if (change.type === 'splice') {
          source.slice(change.index, change.index + change.addedCount).forEach(function(item, index) {
            // Only call onAdd if this item was added, not if it changed location in the array
            if (oldValue.indexOf(item) === -1) {
              onAdd.call(callbackContext, item, index + change.index, source);
            }
          }, callbackContext);
        } else {
          var value = source[change.name];
          if (value != null) {
            onAdd.call(callbackContext, value, change.name, source);
          }
        }
      });
    } else if (Array.isArray(source)) {
      source.forEach(onAdd, callbackContext);
    } else if (source && typeof source === 'object') {
      Object.keys(source).forEach(function(key) {
        var value = source[key];
        if (value != null) {
          onAdd.call(callbackContext, value, key, source);
        }
      });
    } else if (Array.isArray(oldValue)) {
      oldValue.forEach(onRemove, callbackContext);
    } else if (oldValue && typeof oldValue === 'object') {
      // If undefined (or something that isn't an array/object) remove the observers
      Object.keys(oldValue).forEach(function(key) {
        var value = oldValue[key];
        if (value != null) {
          onRemove.call(callbackContext, value, key, oldValue);
        }
      });
    }
  },

  /**
   * Parses an expression into a function using the globals and formatters objects associated with this instance of
   * observations.
   * @param {String} expression The expression string to parse into a function
   * @param {Object} options Additional options to pass to the parser.
   *                        `{ isSetter: true }` will make this expression a setter that accepts a value.
   *                        `{ extraArgs: [ 'argName' ]` will make extra arguments to pass in to the function.
   * @return {Function} A function that may be called to execute the expression (call it against a context using=
   * `func.call(context)` in order to get the data from the context correct)
   */
  getExpression: function(expression, options) {
    if (options && options.isSetter) {
      return expressions.parseSetter(expression, this.globals, this.formatters, options.extraArgs);
    } else if (options && options.extraArgs) {
      var allArgs = [expression, this.globals, this.formatters].concat(options.extraArgs);
      return expressions.parse.apply(expressions, allArgs);
    } else {
      return expressions.parse(expression, this.globals, this.formatters);
    }
  },

  /**
   * Gets the value of an expression from the given context object
   * @param {Object} context The context object the expression will be evaluated against
   * @param {String} expression The expression to evaluate
   * @return {mixed} The result of the expression against the context
   */
  get: function(context, expression) {
    return this.getExpression(expression).call(context);
  },

  /**
   * Sets the value on the expression in the given context object
   * @param {Object} context The context object the expression will be evaluated against
   * @param {String} expression The expression to set a value with
   * @param {mixed} value The value to set on the expression
   * @return {mixed} The result of the expression against the context
   */
  set: function(source, expression, value) {
    return this.getExpression(expression, { isSetter: true }).call(source, value);
  },

  // Schedules an observer sync cycle which checks all the observers to see if they've changed.
  sync: function(callback) {
    if (typeof callback === 'function') {
      this.afterSync(callback);
    }

    if (this.pendingSync) {
      return false;
    }

    this.windows = this.windows.filter(this.removeClosed);
    this.pendingSync = this.windows.map(this.queueSync);
    return true;
  },

  // Runs the observer sync cycle which checks all the observers to see if they've changed.
  syncNow: function(callback) {
    if (typeof callback === 'function') {
      this.afterSync(callback);
    }

    if (this.pendingSync) {
      this.pendingSync.forEach(this.cancelQueue);
      this.pendingSync = null;
    }

    if (this.syncing) {
      this.rerun = true;
      return false;
    }

    this.runSync();
    return true;
  },

  runSync: function() {
    this.syncing = true;
    this.rerun = true;
    this.cycles = 0;

    var i, l;

    // Allow callbacks to run the sync cycle again immediately, but stop at `maxCyles` (default 10) cycles so we don't
    // run infinite loops
    while (this.rerun) {
      if (++this.cycles === this.maxCycles) {
        throw new Error('Infinite observer syncing, an observer is calling Observer.sync() too many times');
      }
      this.rerun = false;
      // the observer array may increase or decrease in size (remaining observers) during the sync
      this.observers.forEach(syncObserver);
    }

    this.callbacksRunning = true;

    var callbacks = this.callbacks;
    this.callbacks = [];
    while (callbacks.length) {
      callbacks.shift()();
    }

    for (i = 0, l = this.listeners.length; i < l; i++) {
      var listener = this.listeners[i];
      listener();
    }

    this.callbacksRunning = false;
    this.syncing = false;
    this.cycles = 0;
  },

  // After the next sync (or the current if in the middle of one), run the provided callback
  afterSync: function(callback) {
    if (typeof callback !== 'function') {
      throw new TypeError('callback must be a function');
    }

    if (this.callbacksRunning) {
      this.sync();
    }

    this.callbacks.push(callback);
  },

  onSync: function(listener) {
    if (typeof listener !== 'function') {
      throw new TypeError('listener must be a function');
    }

    this.listeners.push(listener);
  },

  offSync: function(listener) {
    if (typeof listener !== 'function') {
      throw new TypeError('listener must be a function');
    }

    var index = this.listeners.indexOf(listener);
    if (index !== -1) {
      this.listeners.splice(index, 1).pop();
    }
  },

  // Adds a new observer to be synced with changes. If `skipUpdate` is true then the callback will only be called when a
  // change is made, not initially.
  add: function(observer, skipUpdate) {
    this.observers.add(observer);
    if (!skipUpdate) {
      observer.forceUpdateNextSync = true;
      observer.sync();
    }
  },

  // Removes an observer, stopping it from being run
  remove: function(observer) {
    this.observers.remove(observer);
  },

  removeClosed: function(win) {
    return !win.closed;
  },

  queueSync: function(win) {
    var reqId = win.requestAnimationFrame(this.syncNow);
    return [win, reqId];
  },

  cancelQueue: function(queue) {
    var win = queue[0];
    var reqId = queue[1];
    win.cancelAnimationFrame(reqId);
  },
});

function syncObserver(observer) {
  observer.sync();
}
<|endoftext|>


<commit_before>
import {EventEmitter} from 'events';

/**
 * Provides Jupyter outputs to an output area.
 *
 * This class manages the conversion of Jupyter messages to output state, and
 * handles adding the output state to the output area.
 */
export class OutputModel extends EventEmitter {

    /**
     * Public constructor
     */
    constructor() {
        super();
        this.clearQueued = false;
        this._state = [];
    }

    /**
     * State
     * @return {Output[]}
     */
    get state() {
        return this._state.slice();
    }
    /**
     * State
     * @param  {Output[]} value new state
     */
    set state(value) {
        this.emit('change', value, this._state);
        this._state = value;
    }

    /**
     * Consumes a Jupyter msg protocol message.
     * Ignores messages that it doesn't know how to handle.
     * @param  {any}     msg Jupyter protocol msg JSON
     * @return {boolean}     was the msg consumed
     */
    consumeMessage(msg) {
        let state = this.state;
        if (this._clearQueued) {
            state = [];
            this._clearQueued = false;
        }

        let output = {};
        let msgType = output.output_type = msg.header.msg_type;
        let content = msg.content;
        switch (msgType) {
            case 'clear_output':
                // msg spec v4 had stdout, stderr, display keys
                // v4.1 replaced these with just wait
                // The default behavior is the same (stdout=stderr=display=True, wait=False),
                // so v4 messages will still be properly handled,
                // except for the rarely used clearing less than all output.
                if (msg.content.wait) {
                    this._clearQueued = true;
                } else {
                    state = [];
                }
                return true;
            case 'stream':
                output.text = content.text;
                output.name = content.name;
                break;
            case 'display_data':
                output.data = content.data;
                output.metadata = content.metadata;
                break;
            case 'execute_result':
                output.data = content.data;
                output.metadata = content.metadata;
                output.execution_count = content.execution_count;
                break;
            case 'error':
                output.ename = content.ename;
                output.evalue = content.evalue;
                output.traceback = content.traceback;
                break;
            default:
                console.warn('unhandled output message', msg);
                return false;
        }
        state.push(output);
        this.state = state;
        return true;
    }
}
<commit_msg>Added error throwing to output model<commit_after>
import {EventEmitter} from 'events';

/**
 * Provides Jupyter outputs to an output area.
 *
 * This class manages the conversion of Jupyter messages to output state, and
 * handles adding the output state to the output area.
 */
export class OutputModel extends EventEmitter {

    /**
     * Public constructor
     */
    constructor() {
        super();
        this.clearQueued = false;
        this._state = [];
    }

    /**
     * State
     * @return {Output[]}
     */
    get state() {
        return this._state.slice();
    }
    /**
     * State
     * @param  {Output[]} value new state
     */
    set state(value) {
        this.emit('change', value, this._state);
        this._state = value;
    }

    /**
     * Consumes a Jupyter msg protocol message.
     * Ignores messages that it doesn't know how to handle.
     * @param  {any}     msg Jupyter protocol msg JSON
     * @return {boolean}     was the msg consumed
     */
    consumeMessage(msg) {
        let state = this.state;
        if (this._clearQueued) {
            state = [];
            this._clearQueued = false;
        }

        let output = {};
        let msgType = output.output_type = msg.header.msg_type;
        let content = msg.content;
        switch (msgType) {
            case 'clear_output':
                // msg spec v4 had stdout, stderr, display keys
                // v4.1 replaced these with just wait
                // The default behavior is the same (stdout=stderr=display=True, wait=False),
                // so v4 messages will still be properly handled,
                // except for the rarely used clearing less than all output.
                if (msg.content.wait) {
                    this._clearQueued = true;
                } else {
                    state = [];
                }
                return true;
            case 'stream':
                output.text = content.text;
                output.name = content.name;
                break;
            case 'display_data':
                output.data = content.data;
                output.metadata = content.metadata;
                break;
            case 'execute_result':
                output.data = content.data;
                output.metadata = content.metadata;
                output.execution_count = content.execution_count;
                break;
            case 'error':
                output.ename = content.ename;
                output.evalue = content.evalue;
                output.traceback = content.traceback;
                break;
            default:
                throw new Error('unhandled output message', msg);
                return false;
        }
        state.push(output);
        this.state = state;
        return true;
    }
}
<|endoftext|>


<commit_before>import React, { Fragment } from 'react'
import {
  Heading,
  Container,
  Card,
  Flex,
  Box,
  Text,
  LargeButton,
  Icon,
  Section,
  Link as A
} from '@hackclub/design-system'
import Helmet from 'react-helmet'
import Link from 'gatsby-link'
import Nav from 'components/Nav'
import Stat from 'components/Stat'
import {
  Triangle,
  Hexagon,
  Pentagon,
  Square,
  Circle,
  Line
} from 'components/Shapes'
import DonateForm from 'components/donate/DonateForm'
import Spent from 'components/donate/Spent'
import Footer from 'components/Footer'
import commaNumber from 'comma-number'
import donors from 'components/donate/donors.json'

const Header = Section.withComponent('header').extend`
  background: url('/pattern.svg');
  > div {
    display: grid;
    grid-gap: ${({ theme }) => theme.space[4]}px;
    ${({ theme }) => theme.mediaQueries.md} {
      grid-template-columns: 3fr 2fr;
    }
  }
`

const Row = Box.extend`
  text-align: left;
  ${({ theme }) => theme.mediaQueries.md} {
    display: grid;
    grid-gap: ${({ theme }) => theme.space[3]}px;
    grid-template-columns: ${({ reverse }) =>
      reverse ? '3fr 2fr' : '2fr 3fr'};
  }
`

const Financials = Box.extend`
  display: grid;
  border-radius: ${({ theme }) => theme.radius};
  overflow: hidden;

  ${({ theme }) => theme.mediaQueries.md} {
    grid-template-columns: 2fr 3fr;
  }
`

const Stats = Box.extend`
  div {
    width: 100%;
    display: block;
    text-align: left !important;
  }
  span:before {
    content: '$';
    font-size: ${({ theme }) => theme.fontSizes[4]}px;
    margin-left: -12px;
    vertical-align: super;
  }
  p {
    color: ${({ theme }) => theme.colors.red[1]};
  }
`

const Shapes = Box.extend`
  display: none;
  ${({ theme }) => theme.mediaQueries.md} {
    display: block;
    float: right;
    position: relative;
    z-index: -1;
    svg {
      position: absolute;
    }
  }
`

const WishShapes = Shapes.extend`
  svg {
    &:first-child {
      top: 0;
      right: 0;
      color: rgba(115, 45, 228, 0.75);
      z-index: 1;
    }
    &:last-child {
      top: 0;
      right: 4rem;
      color: rgba(45, 228, 207, 0.75);
    }
  }
`
const ContributionShapes = Shapes.extend`
  svg {
    right: 12rem;
    top: 1rem;
    color: ${({ theme }) => theme.colors.pink[4]};
  }
`
const DonorsShapes = Shapes.extend`
  svg:first-child {
    right: 8rem;
    top: 2rem;
    color: ${({ theme }) => theme.colors.orange[4]};
  }
  svg:last-child {
    right: 4rem;
    top: 4rem;
    color: ${({ theme }) => theme.hexa('blue.4', 0.75)};
  }
`

const headline = { f: [5, 6], mb: 3, style: { lineHeight: '1.125' } }
const subhline = { f: [3, 4], style: { lineHeight: '1.375' } }
const subtext = { f: [3, 4], style: { lineHeight: '1.5' } }

const contentContainer = {
  maxWidth: 64,
  w: 1,
  p: 3,
  color: 'black',
  style: { position: 'relative' }
}
const content = { maxWidth: 48, mx: 0, color: 'black' }

A.link = A.withComponent(Link)

const title = 'Donate to Hack Club'
const description =
  'Contribute today to empower the next generation and help start a coding club at every high school.'

const stats = {
  monthly: 6742.71,
  student: 3,
  club: 60
}

const DonorCard = ({ children }) => (
  <Card bg="snow" p={3} m={2} color="black">
    <Text>
      <Flex align="center">{children}</Flex>
    </Text>
  </Card>
)

const DonorListing = ({ name, url }) =>
  url ? (

      <DonorCard>
        {name} <Icon name="open_in_new" color="gray.4" ml={1} size={16} />
      </DonorCard>

  ) : (
    <DonorCard children={name} />
  )

export default () => (
  <Fragment>
    <Helmet
      title={title}
      meta={[
        { name: 'twitter:title', content: title },
        { name: 'description', content: description },
        { name: 'twitter:description', content: description },
        { property: 'og:title', content: title },
        { property: 'og:description', content: description },
        { property: 'og:url', content: 'https://hackclub.com/donate' }
      ]}
    />

      <Container {...contentContainer} align="left" py={[4]}>
        <Container maxWidth={36} mx={0}>
          <Heading.h1 color="primary" f={[3, 4]} caps>
            Donate to Hack Club
          </Heading.h1>
          <Heading.h2 my={3} {...headline}>
            We rely on people like you to bring coding to the world.
          </Heading.h2>
          <Text {...subhline}>
            Contribute today to empower the next generation. Help start a Hack
            Club at every high school.
          </Text>
          <Text mt={3} f={2} color="muted">
            Your contribution is tax-deductible.

            Hack Club is a 501(c)(3) non-profit with the EIN 81-2908499.
          </Text>
        </Container>
        <Card
          bg="snow"
          p={[3, 4]}
          mt={[0, -3, -4, -5]}
          style={{ overflow: 'hidden' }}
        >
          <DonateForm />
        </Card>
      </Container>

    <Container {...contentContainer}>
      <WishShapes mt={3}>
        <Triangle size={128} rotate={64} />
        <Circle size={128} />
      </WishShapes>
      <Container {...content}>
        <Heading.h2 {...headline}>Transparent, free, and open.</Heading.h2>
        <Text my={3} {...subtext}>
          Hack Club is a new kind of non-profit with{' '}
          total transparency. We open source all of our{' '}
          content
          {' and '}
          code. Many of our leaders
          and members are also available on{' '}
          our Slack.
        </Text>
        <Text my={3} {...subtext}>
          You deserve to know exactly where your contribution will go—so{' '}

            all of our financials are public
          .
        </Text>
      </Container>
      <Row my={5} {...content}>
        <Box>
          <Heading.h2 {...headline}>
            Every last contribution is for our clubs.
          </Heading.h2>
          <ContributionShapes>
            <Pentagon size={128} rotate={16} />
          </ContributionShapes>
        </Box>
        <Box>
          <Text {...subtext}>
            We strive to build a maximally-efficient organization, spending 98%
            of funds given directly on our clubs.
          </Text>
          <Text mt={3} {...subtext}>
            When you give to Hack Club, your money goes where students need it
            most.
          </Text>
          <Financials mt={4}>
            <Box bg="primary" color="white" p={[3, 4]} pr={2}>
              <Heading.h3 f={4} mb={2} caps>
                Financials
              </Heading.h3>
              <Stats>
                <Stat
                  f={6}
                  value={commaNumber(stats.monthly)}
                  label="monthly spend"
                  mb={3}
                  w={1}
                />
                <Stat f={6} mb={2} value={stats.club} label="per club" />
                <Stat f={6} value={stats.student} label="per student" />
              </Stats>
            </Box>
            <Box bg="snow" p={[3, 4]}>
              <Heading.h3 f={4} my={0} caps>
                Spending breakdown
              </Heading.h3>
              <Spent />
            </Box>
          </Financials>
        </Box>
      </Row>
      <Container {...content}>
        <Heading.h2 {...headline}>
          Contribute more than just dollars.
        </Heading.h2>
        <Text my={3} {...subtext}>
          We accept donations of time, technical or hard science fiction books,
          stocks/other securities, and cryptocurrency.
        </Text>
        <Text my={3} {...subtext}>
          Please get in touch at{' '}
          donate@hackclub.com if you’re
          interested in making a contribution or have any questions.
        </Text>
      </Container>
      <Row my={5} {...content}>
        <Box>
          <Heading.h2 {...headline}>Some of our amazing donors.</Heading.h2>
          <DonorsShapes>
            <Hexagon size={128} rotate={64} />
            <Circle size={128} />
          </DonorsShapes>
        </Box>
        <Flex m={-2} wrap>
          {Object.keys(donors).map(name => (
            <DonorListing key={name} name={name} url={donors[name]} />
          ))}
        </Flex>
      </Row>
    </Container>

  </Fragment>
)
<commit_msg>Fix DOM nesting warning<commit_after>import React, { Fragment } from 'react'
import {
  Heading,
  Container,
  Card,
  Flex,
  Box,
  Text,
  LargeButton,
  Icon,
  Section,
  Link as A
} from '@hackclub/design-system'
import Helmet from 'react-helmet'
import Link from 'gatsby-link'
import Nav from 'components/Nav'
import Stat from 'components/Stat'
import {
  Triangle,
  Hexagon,
  Pentagon,
  Square,
  Circle,
  Line
} from 'components/Shapes'
import DonateForm from 'components/donate/DonateForm'
import Spent from 'components/donate/Spent'
import Footer from 'components/Footer'
import commaNumber from 'comma-number'
import donors from 'components/donate/donors.json'

const Header = Section.withComponent('header').extend`
  background: url('/pattern.svg');
  > div {
    display: grid;
    grid-gap: ${({ theme }) => theme.space[4]}px;
    ${({ theme }) => theme.mediaQueries.md} {
      grid-template-columns: 3fr 2fr;
    }
  }
`

const Row = Box.extend`
  text-align: left;
  ${({ theme }) => theme.mediaQueries.md} {
    display: grid;
    grid-gap: ${({ theme }) => theme.space[3]}px;
    grid-template-columns: ${({ reverse }) =>
      reverse ? '3fr 2fr' : '2fr 3fr'};
  }
`

const Financials = Box.extend`
  display: grid;
  border-radius: ${({ theme }) => theme.radius};
  overflow: hidden;

  ${({ theme }) => theme.mediaQueries.md} {
    grid-template-columns: 2fr 3fr;
  }
`

const Stats = Box.extend`
  div {
    width: 100%;
    display: block;
    text-align: left !important;
  }
  span:before {
    content: '$';
    font-size: ${({ theme }) => theme.fontSizes[4]}px;
    margin-left: -12px;
    vertical-align: super;
  }
  p {
    color: ${({ theme }) => theme.colors.red[1]};
  }
`

const Shapes = Box.extend`
  display: none;
  ${({ theme }) => theme.mediaQueries.md} {
    display: block;
    float: right;
    position: relative;
    z-index: -1;
    svg {
      position: absolute;
    }
  }
`

const WishShapes = Shapes.extend`
  svg {
    &:first-child {
      top: 0;
      right: 0;
      color: rgba(115, 45, 228, 0.75);
      z-index: 1;
    }
    &:last-child {
      top: 0;
      right: 4rem;
      color: rgba(45, 228, 207, 0.75);
    }
  }
`
const ContributionShapes = Shapes.extend`
  svg {
    right: 12rem;
    top: 1rem;
    color: ${({ theme }) => theme.colors.pink[4]};
  }
`
const DonorsShapes = Shapes.extend`
  svg:first-child {
    right: 8rem;
    top: 2rem;
    color: ${({ theme }) => theme.colors.orange[4]};
  }
  svg:last-child {
    right: 4rem;
    top: 4rem;
    color: ${({ theme }) => theme.hexa('blue.4', 0.75)};
  }
`

const headline = { f: [5, 6], mb: 3, style: { lineHeight: '1.125' } }
const subhline = { f: [3, 4], style: { lineHeight: '1.375' } }
const subtext = { f: [3, 4], style: { lineHeight: '1.5' } }

const contentContainer = {
  maxWidth: 64,
  w: 1,
  p: 3,
  color: 'black',
  style: { position: 'relative' }
}
const content = { maxWidth: 48, mx: 0, color: 'black' }

A.link = A.withComponent(Link)

const title = 'Donate to Hack Club'
const description =
  'Contribute today to empower the next generation and help start a coding club at every high school.'

const stats = {
  monthly: 6742.71,
  student: 3,
  club: 60
}

const DonorCard = ({ children }) => (
  <Card bg="snow" p={3} m={2} color="black">
    <Flex align="center">{children}</Flex>
  </Card>
)

const DonorListing = ({ name, url }) =>
  url ? (

      <DonorCard>
        {name} <Icon name="open_in_new" color="gray.4" ml={1} size={16} />
      </DonorCard>

  ) : (
    <DonorCard children={name} />
  )

export default () => (
  <Fragment>
    <Helmet
      title={title}
      meta={[
        { name: 'twitter:title', content: title },
        { name: 'description', content: description },
        { name: 'twitter:description', content: description },
        { property: 'og:title', content: title },
        { property: 'og:description', content: description },
        { property: 'og:url', content: 'https://hackclub.com/donate' }
      ]}
    />

      <Container {...contentContainer} align="left" py={[4]}>
        <Container maxWidth={36} mx={0}>
          <Heading.h1 color="primary" f={[3, 4]} caps>
            Donate to Hack Club
          </Heading.h1>
          <Heading.h2 my={3} {...headline}>
            We rely on people like you to bring coding to the world.
          </Heading.h2>
          <Text {...subhline}>
            Contribute today to empower the next generation. Help start a Hack
            Club at every high school.
          </Text>
          <Text mt={3} f={2} color="muted">
            Your contribution is tax-deductible.

            Hack Club is a 501(c)(3) non-profit with the EIN 81-2908499.
          </Text>
        </Container>
        <Card
          bg="snow"
          p={[3, 4]}
          mt={[0, -3, -4, -5]}
          style={{ overflow: 'hidden' }}
        >
          <DonateForm />
        </Card>
      </Container>

    <Container {...contentContainer}>
      <WishShapes mt={3}>
        <Triangle size={128} rotate={64} />
        <Circle size={128} />
      </WishShapes>
      <Container {...content}>
        <Heading.h2 {...headline}>Transparent, free, and open.</Heading.h2>
        <Text my={3} {...subtext}>
          Hack Club is a new kind of non-profit with{' '}
          total transparency. We open source all of our{' '}
          content
          {' and '}
          code. Many of our leaders
          and members are also available on{' '}
          our Slack.
        </Text>
        <Text my={3} {...subtext}>
          You deserve to know exactly where your contribution will go—so{' '}

            all of our financials are public
          .
        </Text>
      </Container>
      <Row my={5} {...content}>
        <Box>
          <Heading.h2 {...headline}>
            Every last contribution is for our clubs.
          </Heading.h2>
          <ContributionShapes>
            <Pentagon size={128} rotate={16} />
          </ContributionShapes>
        </Box>
        <Box>
          <Text {...subtext}>
            We strive to build a maximally-efficient organization, spending 98%
            of funds given directly on our clubs.
          </Text>
          <Text mt={3} {...subtext}>
            When you give to Hack Club, your money goes where students need it
            most.
          </Text>
          <Financials mt={4}>
            <Box bg="primary" color="white" p={[3, 4]} pr={2}>
              <Heading.h3 f={4} mb={2} caps>
                Financials
              </Heading.h3>
              <Stats>
                <Stat
                  f={6}
                  value={commaNumber(stats.monthly)}
                  label="monthly spend"
                  mb={3}
                  w={1}
                />
                <Stat f={6} mb={2} value={stats.club} label="per club" />
                <Stat f={6} value={stats.student} label="per student" />
              </Stats>
            </Box>
            <Box bg="snow" p={[3, 4]}>
              <Heading.h3 f={4} my={0} caps>
                Spending breakdown
              </Heading.h3>
              <Spent />
            </Box>
          </Financials>
        </Box>
      </Row>
      <Container {...content}>
        <Heading.h2 {...headline}>
          Contribute more than just dollars.
        </Heading.h2>
        <Text my={3} {...subtext}>
          We accept donations of time, technical or hard science fiction books,
          stocks/other securities, and cryptocurrency.
        </Text>
        <Text my={3} {...subtext}>
          Please get in touch at{' '}
          donate@hackclub.com if you’re
          interested in making a contribution or have any questions.
        </Text>
      </Container>
      <Row my={5} {...content}>
        <Box>
          <Heading.h2 {...headline}>Some of our amazing donors.</Heading.h2>
          <DonorsShapes>
            <Hexagon size={128} rotate={64} />
            <Circle size={128} />
          </DonorsShapes>
        </Box>
        <Flex m={-2} wrap>
          {Object.keys(donors).map(name => (
            <DonorListing key={name} name={name} url={donors[name]} />
          ))}
        </Flex>
      </Row>
    </Container>

  </Fragment>
)
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2018 Glayzzle (BSD3 License)
 * @authors https://github.com/glayzzle/php-parser/graphs/contributors
 * @url http://glayzzle.com
 */
"use strict";

module.exports = {
  /**
   * Reads a while statement
   * ```ebnf
   * while ::= T_WHILE (statement | ':' inner_statement_list T_ENDWHILE ';')
   * ```
   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L587
   * @return {While}
   */
  read_while: function() {
    const result = this.node("while");
    let test = null;
    let body = null;
    let shortForm = false;
    if (this.expect("(")) this.next();
    test = this.read_expr();
    if (this.expect(")")) this.next();
    if (this.token === ":") {
      shortForm = true;
      body = this.read_short_form(this.tok.T_ENDWHILE);
    } else {
      body = this.read_statement();
    }
    return result(test, body, shortForm);
  },
  /**
   * Reads a do / while loop
   * ```ebnf
   * do ::= T_DO statement T_WHILE '(' expr ')' ';'
   * ```
   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L423
   * @return {Do}
   */
  read_do: function() {
    const result = this.node("do");
    let test = null;
    let body = null;
    body = this.read_statement();
    if (this.expect(this.tok.T_WHILE)) {
      if (this.next().expect("(")) this.next();
      test = this.read_expr();
      if (this.expect(")")) this.next();
      if (this.expect(";")) this.next();
    }
    return result(test, body);
  },
  /**
   * Read a for incremental loop
   * ```ebnf
   * for ::= T_FOR '(' for_exprs ';' for_exprs ';' for_exprs ')' for_statement
   * for_statement ::= statement | ':' inner_statement_list T_ENDFOR ';'
   * for_exprs ::= expr? (',' expr)*
   * ```
   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L425
   * @return {For}
   */
  read_for: function() {
    const result = this.node("for");
    let init = [];
    let test = [];
    let increment = [];
    let body = null;
    let shortForm = false;
    if (this.expect("(")) this.next();
    if (this.token !== ";") {
      init = this.read_list(this.read_expr, ",");
      if (this.expect(";")) this.next();
    } else {
      this.next();
    }
    if (this.token !== ";") {
      test = this.read_list(this.read_expr, ",");
      if (this.expect(";")) this.next();
    } else {
      this.next();
    }
    if (this.token !== ")") {
      increment = this.read_list(this.read_expr, ",");
      if (this.expect(")")) this.next();
    } else {
      this.next();
    }
    if (this.token === ":") {
      shortForm = true;
      body = this.read_short_form(this.tok.T_ENDFOR);
    } else {
      body = this.read_statement();
    }
    return result(init, test, increment, body, shortForm);
  },
  /**
   * Reads a foreach loop
   * ```ebnf
   * foreach ::= '(' expr T_AS foreach_variable (T_DOUBLE_ARROW foreach_variable)? ')' statement
   * ```
   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L438
   * @return {Foreach}
   */
  read_foreach: function() {
    const result = this.node("foreach");
    let source = null;
    let key = null;
    let value = null;
    let body = null;
    let shortForm = false;
    if (this.expect("(")) this.next();
    source = this.read_expr();
    if (this.expect(this.tok.T_AS)) {
      this.next();
      value = this.read_foreach_variable();
      if (this.token === this.tok.T_DOUBLE_ARROW) {
        key = value;
        value = this.next().read_foreach_variable();
      }
    }

    if (this.expect(")")) this.next();

    if (this.token === ":") {
      shortForm = true;
      body = this.read_short_form(this.tok.T_ENDFOREACH);
    } else {
      body = this.read_statement();
    }
    return result(source, key, value, body, shortForm);
  },
  /**
   * Reads a foreach variable statement
   * ```ebnf
   * foreach_variable =
   *    variable |
   *    '&' variable |
   *    T_LIST '(' assignment_list ')' |
   *    '[' assignment_list ']'
   * ```
   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L544
   * @return {Expression}
   */
  read_foreach_variable: function() {
    if (this.token === this.tok.T_LIST || this.token === "[") {
      const isShort = this.token === "[";
      const result = this.node("list");
      this.next();
      if (isShort && this.expect("(")) this.next();
      const assignList = this.read_assignment_list();
      if (this.expect(isShort ? "]": ")")) this.next();
      return result(assignList, isShort);
    } else {
      return this.read_variable(false, false, false);
    }
  }
};
<commit_msg>disable the list node on foreach keys<commit_after>/**
 * Copyright (C) 2018 Glayzzle (BSD3 License)
 * @authors https://github.com/glayzzle/php-parser/graphs/contributors
 * @url http://glayzzle.com
 */
"use strict";

module.exports = {
  /**
   * Reads a while statement
   * ```ebnf
   * while ::= T_WHILE (statement | ':' inner_statement_list T_ENDWHILE ';')
   * ```
   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L587
   * @return {While}
   */
  read_while: function() {
    const result = this.node("while");
    let test = null;
    let body = null;
    let shortForm = false;
    if (this.expect("(")) this.next();
    test = this.read_expr();
    if (this.expect(")")) this.next();
    if (this.token === ":") {
      shortForm = true;
      body = this.read_short_form(this.tok.T_ENDWHILE);
    } else {
      body = this.read_statement();
    }
    return result(test, body, shortForm);
  },
  /**
   * Reads a do / while loop
   * ```ebnf
   * do ::= T_DO statement T_WHILE '(' expr ')' ';'
   * ```
   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L423
   * @return {Do}
   */
  read_do: function() {
    const result = this.node("do");
    let test = null;
    let body = null;
    body = this.read_statement();
    if (this.expect(this.tok.T_WHILE)) {
      if (this.next().expect("(")) this.next();
      test = this.read_expr();
      if (this.expect(")")) this.next();
      if (this.expect(";")) this.next();
    }
    return result(test, body);
  },
  /**
   * Read a for incremental loop
   * ```ebnf
   * for ::= T_FOR '(' for_exprs ';' for_exprs ';' for_exprs ')' for_statement
   * for_statement ::= statement | ':' inner_statement_list T_ENDFOR ';'
   * for_exprs ::= expr? (',' expr)*
   * ```
   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L425
   * @return {For}
   */
  read_for: function() {
    const result = this.node("for");
    let init = [];
    let test = [];
    let increment = [];
    let body = null;
    let shortForm = false;
    if (this.expect("(")) this.next();
    if (this.token !== ";") {
      init = this.read_list(this.read_expr, ",");
      if (this.expect(";")) this.next();
    } else {
      this.next();
    }
    if (this.token !== ";") {
      test = this.read_list(this.read_expr, ",");
      if (this.expect(";")) this.next();
    } else {
      this.next();
    }
    if (this.token !== ")") {
      increment = this.read_list(this.read_expr, ",");
      if (this.expect(")")) this.next();
    } else {
      this.next();
    }
    if (this.token === ":") {
      shortForm = true;
      body = this.read_short_form(this.tok.T_ENDFOR);
    } else {
      body = this.read_statement();
    }
    return result(init, test, increment, body, shortForm);
  },
  /**
   * Reads a foreach loop
   * ```ebnf
   * foreach ::= '(' expr T_AS foreach_variable (T_DOUBLE_ARROW foreach_variable)? ')' statement
   * ```
   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L438
   * @return {Foreach}
   */
  read_foreach: function() {
    const result = this.node("foreach");
    let source = null;
    let key = null;
    let value = null;
    let body = null;
    let shortForm = false;
    if (this.expect("(")) this.next();
    source = this.read_expr();
    if (this.expect(this.tok.T_AS)) {
      this.next();
      value = this.read_foreach_variable();
      if (this.token === this.tok.T_DOUBLE_ARROW) {
        key = value;
        value = this.next().read_foreach_variable();
      }
    }

    // grammatically correct but not supported by PHP
    if (key && key.kind === 'list') {
      this.raiseError(
        "Fatal Error : Cannot use list as key element"
      );
    }

    if (this.expect(")")) this.next();

    if (this.token === ":") {
      shortForm = true;
      body = this.read_short_form(this.tok.T_ENDFOREACH);
    } else {
      body = this.read_statement();
    }
    return result(source, key, value, body, shortForm);
  },
  /**
   * Reads a foreach variable statement
   * ```ebnf
   * foreach_variable =
   *    variable |
   *    '&' variable |
   *    T_LIST '(' assignment_list ')' |
   *    '[' assignment_list ']'
   * ```
   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L544
   * @return {Expression}
   */
  read_foreach_variable: function() {
    if (this.token === this.tok.T_LIST || this.token === "[") {
      const isShort = this.token === "[";
      const result = this.node("list");
      this.next();
      if (!isShort && this.expect("(")) this.next();
      const assignList = this.read_array_pair_list(isShort);
      if (this.expect(isShort ? "]": ")")) this.next();
      return result(assignList, isShort);
    } else {
      return this.read_variable(false, false, false);
    }
  }
};
<|endoftext|>


<commit_before>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * All rights reserved.
 */

var Segment = this.Segment = Base.extend({
	beans: true,

	initialize: function(arg0, arg1, arg2, arg3, arg4, arg5) {
		if (arguments.length == 0) {
			this._point = SegmentPoint.create(this, 0, 0);
		} else if (arguments.length == 1) {
			// TODO: If beans are not activated, this won't copy from
			// an existing segment. OK?
			if (arg0.point) {
				this._point = SegmentPoint.create(this, arg0.point);
				this._handleIn = SegmentPoint.create(this, arg0.handleIn);
				this._handleOut = SegmentPoint.create(this, arg0.handleOut);
			} else {
				this._point = SegmentPoint.create(this, arg0);
			}
		} else if (arguments.length < 6) {
			if (arguments.length == 2 && !arg1.x) {
				this._point = SegmentPoint.create(this, arg0, arg1);
			} else {
				this._point = SegmentPoint.create(this, arg0);
				// Doesn't matter if these arguments exist, it creates 0, 0
				// points otherwise
				this._handleIn = SegmentPoint.create(this, arg1);
				this._handleOut = SegmentPoint.create(this, arg2);
			}
		} else if (arguments.length == 6) {
			this._point = SegmentPoint.create(this, arg0, arg1);
			this._handleIn = SegmentPoint.create(this, arg2, arg3);
			this._handleOut = SegmentPoint.create(this, arg4, arg5);
		}
		if (!this._handleIn)
			this._handleIn = SegmentPoint.create(this, 0, 0);
		if (!this._handleOut)
			this._handleOut = SegmentPoint.create(this, 0, 0);
	},

	getPoint: function() {
		return this._point;
	},

	setPoint: function(point) {
		point = Point.read(arguments);
		// Do not replace the internal object but update it instead, so
		// references to it are kept alive.
		this._point.set(point.x, point.y);
	},

	getHandleIn: function() {
		return this._handleIn;
	},

	setHandleIn: function(point) {
		point = Point.read(arguments);
		// See #setPoint:
		this._handleIn.set(point.x, point.y);
		// Update corner accordingly
		// this.corner = !this._handleIn.isParallel(this._handleOut);
	},

	getHandleInIfSet: function() {
		return this._handleIn._x == 0 && this._handleIn._y == 0
			? null : this._handleIn;
	},

	getHandleOut: function() {
		return this._handleOut;
	},

	setHandleOut: function(point) {
		point = Point.read(arguments);
		// See #setPoint:
		this._handleOut.set(point.x, point.y);
		// Update corner accordingly
		// this.corner = !this._handleIn.isParallel(this._handleOut);
	},

	getHandleOutIfSet: function() {
		return this._handleOut._x == 0 && this._handleOut._y == 0
			? null : this._handleOut;
	},

	getIndex: function() {
		// TODO: Cache and update indices instead of searching?
		// TODO: Return null instead of -1?
		return this._path ? this._path._segments.indexOf(this) : -1;
	},

	getPath: function() {
		return this._path;
	},

	getCurve: function() {
		if (this._path != null) {
			var index = this.getIndex();
			// The last segment of an open path belongs to the last curve
			if (!this._path.closed && index == this._path._segments.length - 1)
				index--;
			return this._path.getCurves()[index] || null;
		}
		return null;
	},

	getNext: function() {
		var segments = this._path && this._path._segments;
		return segments && (segments[this.getIndex() + 1]
				|| this._path.closed && segments[0]) || null;
	},

	getPrevious: function() {
		var segments = this._path && this._path._segments;
		return segments && (segments[this.getIndex() - 1]
				|| this._path.closed && segments[segments.length - 1]) || null;
	},

	_isSelected: function(point) {
		var state = this._selectionState;
		return point == this._point ? !!(state & SelectionState.POINT)
			: point == this._handleIn ? !!(state & SelectionState.HANDLE_IN)
			: point == this._handleOut ? !!(state & SelectionState.HANDLE_OUT)
			: false;
	},

	_setSelected: function(point, selected) {
		if (!this._path)
			return;
		var selected = !!selected, // convert to boolean
			state = this._selectionState,
			wasSelected = !!state,
			// For performance reasons use array indices to access the various
			// selection states: 0 = point, 1 = handleIn, 2 = handleOut
			selection = [
				!!(state & SelectionState.POINT),
				!!(state & SelectionState.HANDLE_IN),
				!!(state & SelectionState.HANDLE_OUT)
			];
		if (point == this._point) {
			if (selected) {
				// We're selecting point, deselect the handles
				selection[1] = selection[2] = false;
			} else {
				var previous = this.getPrevious(),
					next = this.getNext();
				// When deselecting a point, the handles get selected instead
				// depending on the selection state of their neighbors.
				selection[1] = previous && (previous._point.isSelected()
						|| previous._handleOut.isSelected());
				selection[2] = next && (next._point.isSelected()
						|| next._handleIn.isSelected());
			}
			selection[0] = selected;
		} else {
			var index = point == this._handleIn ? 1 : 2;
			if (selection[index] != selected) {
				// When selecting handles, the point get deselected.
				if (selected)
					selection[0] = false;
				selection[index] = selected;
			}
		}
		this._selectionState = (selection[0] ? SelectionState.POINT : 0)
				| (selection[1] ? SelectionState.HANDLE_IN : 0)
				| (selection[2] ? SelectionState.HANDLE_OUT : 0);
		// If the selection state of the segment has changed, we need to let
		// it's path know and possibly add or remove it from
		// document._selectedItems
		if (wasSelected != !!this._selectionState) {
			var path = this._path,
				count = path._selectedSegmentCount
						+= this._selectionState ? 1 : -1;
			if (count <= 1)
				path._document._selectItem(path, count == 1);
		}
	},

	isSelected: function() {
		return this._isSelected(this._point);
	},

	setSelected: function(selected) {
		this._setSelected(this._point, selected);
	},

	reverse: function() {
		return new Segment(this._point, this._handleOut, this._handleIn);
	},

	clone: function() {
		return new Segment(this);
	},

	remove: function() {
		if (this._path) {
			this._path._segments.splice(this.getIndex(), 1);
			if (this.isSelected())
				this._path._selectedSegmentCount--;
			return true;
		}
		return false;
	},

	toString: function() {
		return '{ point: ' + this._point
				+ (!this._handleIn.isZero()
					? ', handleIn: ' + this._handleIn : '')
				+ (this._handleOut.isZero()
					? ', handleOut: ' + this._handleOut : '')
				+ ' }';
	},

	_transformCoordinates: function(matrix, coords, change) {
		// Use matrix.transform version() that takes arrays of multiple
		// points for largely improved performance, as no calls to
		// Point.read() and Point constructors are necessary.
		var point = this._point,
			// If a matrix is defined, only transform handles if they are set.
			// This saves some computation time. If no matrix is set, always
			// use the real handles, as we just want to receive a filled
			// coords array for getBounds().
			handleIn =  matrix && this.getHandleInIfSet() || this._handleIn,
			handleOut = matrix && this.getHandleOutIfSet() || this._handleOut,
			x = point._x,
			y = point._y;
		coords[0] = x;
		coords[1] = y;
		var index = 2;
		// We need to convert handles to absolute coordinates in order
		// to transform them.
		if (handleIn) {
			coords[index++] = handleIn._x + x;
			coords[index++] = handleIn._y + y;
		}
		if (handleOut) {
			coords[index++] = handleOut._x + x;
			coords[index++] = handleOut._y + y;
		}
		if (matrix) {
			matrix.transform(coords, 0, coords, 0, index / 2);
			x = coords[0];
			y = coords[1];
			if (change) {
				// If change is true, we need to set the new values back
				point._x = x;
				point._y = y;
				index  = 2;
				if (handleIn) {
					handleIn._x = coords[index++] - x;
					handleIn._y = coords[index++] - y;
				}
				if (handleOut) {
					handleOut._x = coords[index++] - x;
					handleOut._y = coords[index++] - y;
				}
			} else {
				// We want to receive the results in coords, so make sure
				// handleIn and out are defined too, even if they're 0
				if (!handleIn) {
					coords[index++] = x;
					coords[index++] = y;
				}
				if (!handleOut) {
					coords[index++] = x;
					coords[index++] = y;
				}
			}
		}
	}
});
<commit_msg>Segment#isSelected() only checks for selection state of point. We need to check _selectionState instead to mirror behaviour in #_setSelected().<commit_after>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * All rights reserved.
 */

var Segment = this.Segment = Base.extend({
	beans: true,

	initialize: function(arg0, arg1, arg2, arg3, arg4, arg5) {
		if (arguments.length == 0) {
			this._point = SegmentPoint.create(this, 0, 0);
		} else if (arguments.length == 1) {
			// TODO: If beans are not activated, this won't copy from
			// an existing segment. OK?
			if (arg0.point) {
				this._point = SegmentPoint.create(this, arg0.point);
				this._handleIn = SegmentPoint.create(this, arg0.handleIn);
				this._handleOut = SegmentPoint.create(this, arg0.handleOut);
			} else {
				this._point = SegmentPoint.create(this, arg0);
			}
		} else if (arguments.length < 6) {
			if (arguments.length == 2 && !arg1.x) {
				this._point = SegmentPoint.create(this, arg0, arg1);
			} else {
				this._point = SegmentPoint.create(this, arg0);
				// Doesn't matter if these arguments exist, it creates 0, 0
				// points otherwise
				this._handleIn = SegmentPoint.create(this, arg1);
				this._handleOut = SegmentPoint.create(this, arg2);
			}
		} else if (arguments.length == 6) {
			this._point = SegmentPoint.create(this, arg0, arg1);
			this._handleIn = SegmentPoint.create(this, arg2, arg3);
			this._handleOut = SegmentPoint.create(this, arg4, arg5);
		}
		if (!this._handleIn)
			this._handleIn = SegmentPoint.create(this, 0, 0);
		if (!this._handleOut)
			this._handleOut = SegmentPoint.create(this, 0, 0);
	},

	getPoint: function() {
		return this._point;
	},

	setPoint: function(point) {
		point = Point.read(arguments);
		// Do not replace the internal object but update it instead, so
		// references to it are kept alive.
		this._point.set(point.x, point.y);
	},

	getHandleIn: function() {
		return this._handleIn;
	},

	setHandleIn: function(point) {
		point = Point.read(arguments);
		// See #setPoint:
		this._handleIn.set(point.x, point.y);
		// Update corner accordingly
		// this.corner = !this._handleIn.isParallel(this._handleOut);
	},

	getHandleInIfSet: function() {
		return this._handleIn._x == 0 && this._handleIn._y == 0
			? null : this._handleIn;
	},

	getHandleOut: function() {
		return this._handleOut;
	},

	setHandleOut: function(point) {
		point = Point.read(arguments);
		// See #setPoint:
		this._handleOut.set(point.x, point.y);
		// Update corner accordingly
		// this.corner = !this._handleIn.isParallel(this._handleOut);
	},

	getHandleOutIfSet: function() {
		return this._handleOut._x == 0 && this._handleOut._y == 0
			? null : this._handleOut;
	},

	getIndex: function() {
		// TODO: Cache and update indices instead of searching?
		// TODO: Return null instead of -1?
		return this._path ? this._path._segments.indexOf(this) : -1;
	},

	getPath: function() {
		return this._path;
	},

	getCurve: function() {
		if (this._path != null) {
			var index = this.getIndex();
			// The last segment of an open path belongs to the last curve
			if (!this._path.closed && index == this._path._segments.length - 1)
				index--;
			return this._path.getCurves()[index] || null;
		}
		return null;
	},

	getNext: function() {
		var segments = this._path && this._path._segments;
		return segments && (segments[this.getIndex() + 1]
				|| this._path.closed && segments[0]) || null;
	},

	getPrevious: function() {
		var segments = this._path && this._path._segments;
		return segments && (segments[this.getIndex() - 1]
				|| this._path.closed && segments[segments.length - 1]) || null;
	},

	_isSelected: function(point) {
		var state = this._selectionState;
		return point == this._point ? !!(state & SelectionState.POINT)
			: point == this._handleIn ? !!(state & SelectionState.HANDLE_IN)
			: point == this._handleOut ? !!(state & SelectionState.HANDLE_OUT)
			: false;
	},

	_setSelected: function(point, selected) {
		if (!this._path)
			return;
		var selected = !!selected, // convert to boolean
			state = this._selectionState,
			wasSelected = !!state,
			// For performance reasons use array indices to access the various
			// selection states: 0 = point, 1 = handleIn, 2 = handleOut
			selection = [
				!!(state & SelectionState.POINT),
				!!(state & SelectionState.HANDLE_IN),
				!!(state & SelectionState.HANDLE_OUT)
			];
		if (point == this._point) {
			if (selected) {
				// We're selecting point, deselect the handles
				selection[1] = selection[2] = false;
			} else {
				var previous = this.getPrevious(),
					next = this.getNext();
				// When deselecting a point, the handles get selected instead
				// depending on the selection state of their neighbors.
				selection[1] = previous && (previous._point.isSelected()
						|| previous._handleOut.isSelected());
				selection[2] = next && (next._point.isSelected()
						|| next._handleIn.isSelected());
			}
			selection[0] = selected;
		} else {
			var index = point == this._handleIn ? 1 : 2;
			if (selection[index] != selected) {
				// When selecting handles, the point get deselected.
				if (selected)
					selection[0] = false;
				selection[index] = selected;
			}
		}
		this._selectionState = (selection[0] ? SelectionState.POINT : 0)
				| (selection[1] ? SelectionState.HANDLE_IN : 0)
				| (selection[2] ? SelectionState.HANDLE_OUT : 0);
		// If the selection state of the segment has changed, we need to let
		// it's path know and possibly add or remove it from
		// document._selectedItems
		if (wasSelected != !!this._selectionState) {
			var path = this._path,
				count = path._selectedSegmentCount
						+= this._selectionState ? 1 : -1;
			if (count <= 1)
				path._document._selectItem(path, count == 1);
		}
	},

	isSelected: function() {
		return this._isSelected(this._point);
	},

	setSelected: function(selected) {
		this._setSelected(this._point, selected);
	},

	reverse: function() {
		return new Segment(this._point, this._handleOut, this._handleIn);
	},

	clone: function() {
		return new Segment(this);
	},

	remove: function() {
		if (this._path) {
			this._path._segments.splice(this.getIndex(), 1);
			if (this._selectionState) {
				this._path._selectedSegmentCount--;
				this._selectionState = 0;
			}
			return true;
		}
		return false;
	},

	toString: function() {
		return '{ point: ' + this._point
				+ (!this._handleIn.isZero()
					? ', handleIn: ' + this._handleIn : '')
				+ (this._handleOut.isZero()
					? ', handleOut: ' + this._handleOut : '')
				+ ' }';
	},

	_transformCoordinates: function(matrix, coords, change) {
		// Use matrix.transform version() that takes arrays of multiple
		// points for largely improved performance, as no calls to
		// Point.read() and Point constructors are necessary.
		var point = this._point,
			// If a matrix is defined, only transform handles if they are set.
			// This saves some computation time. If no matrix is set, always
			// use the real handles, as we just want to receive a filled
			// coords array for getBounds().
			handleIn =  matrix && this.getHandleInIfSet() || this._handleIn,
			handleOut = matrix && this.getHandleOutIfSet() || this._handleOut,
			x = point._x,
			y = point._y;
		coords[0] = x;
		coords[1] = y;
		var index = 2;
		// We need to convert handles to absolute coordinates in order
		// to transform them.
		if (handleIn) {
			coords[index++] = handleIn._x + x;
			coords[index++] = handleIn._y + y;
		}
		if (handleOut) {
			coords[index++] = handleOut._x + x;
			coords[index++] = handleOut._y + y;
		}
		if (matrix) {
			matrix.transform(coords, 0, coords, 0, index / 2);
			x = coords[0];
			y = coords[1];
			if (change) {
				// If change is true, we need to set the new values back
				point._x = x;
				point._y = y;
				index  = 2;
				if (handleIn) {
					handleIn._x = coords[index++] - x;
					handleIn._y = coords[index++] - y;
				}
				if (handleOut) {
					handleOut._x = coords[index++] - x;
					handleOut._y = coords[index++] - y;
				}
			} else {
				// We want to receive the results in coords, so make sure
				// handleIn and out are defined too, even if they're 0
				if (!handleIn) {
					coords[index++] = x;
					coords[index++] = y;
				}
				if (!handleOut) {
					coords[index++] = x;
					coords[index++] = y;
				}
			}
		}
	}
});
<|endoftext|>