<commit_before>import * as search from 'searchtabular';
import React, { Component } from 'react';
import Item from './Item';
import SearchBar from './Search';
import Pagination from '../Tickets/Pagination';
import { compose } from 'redux';
import { multiInfix } from '../../helpers/utils';

class List extends Component {

	render() {
    const { query, rows } = this.props;
    const columns = this.props.fields.map((field) => field={
      property: field.name,
      header: {
        label: field.label,
      },
      filterType:field.filterType,
    });

    const searchExecutor = search.multipleColumns({
      columns,
      query,
      strategy: multiInfix });
    const visibleItems = compose(searchExecutor)(rows);

		return (

 List View

			 <SearchBar
          filter={this.props.filter}
          fields={this.props.fields}
          onFilter={this.props.onFilter}
        />
        {visibleItems.map(item =>
          <Item
            item={item}
            fields={this.props.fields}
            onEdit={this.props.onEdit}
            onDelete={this.props.onDelete}
            key={item.id}
          />
        )}

		);
	}
}

export default List;<commit_msg>Removed unnecessary packages<commit_after>import * as search from 'searchtabular';
import React, { Component } from 'react';
import Item from './Item';
import SearchBar from './Search';
import { compose } from 'redux';
import { multiInfix } from '../../helpers/utils';

class List extends Component {

	render() {
    const { query, rows } = this.props;
    const columns = this.props.fields.map((field) => field={
      property: field.name,
      header: {
        label: field.label,
      },
      filterType:field.filterType,
    });

    const searchExecutor = search.multipleColumns({
      columns,
      query,
      strategy: multiInfix });
    const visibleItems = compose(searchExecutor)(rows);

		return (

 List View

			 <SearchBar
          filter={this.props.filter}
          fields={this.props.fields}
          onFilter={this.props.onFilter}
        />
        {visibleItems.map(item =>
          <Item
            item={item}
            fields={this.props.fields}
            onEdit={this.props.onEdit}
            onDelete={this.props.onDelete}
            key={item.id}
          />
        )}

		);
	}
}

export default List;<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import ContextMenu from '../ContextMenu';
import AddNodeModal from '../AddNodeModal';
import Node from '../Node';
import styles from './styles.css';

import {
  persistState,
  removeNode,
  addParent,
  removeParent,
  changeNetworkProperty,
  changeNodePosition,
} from '../../actions';

import {
  getNetwork,
  getNodes,
  getInferenceResults,
} from '../../selectors';

class Canvas extends Component {
  constructor(props) {
    super(props);

    this.state = {
      arrows: [],
      contextMenuItems: [],
      newNodePosition: null,
      addingNodeArrow: null,
    };

    this.rectRefs = {};
    this.movingNode = null;
    this.nodeToAddChildrenTo = null;

    this.canvasContextMenuItems = [
      {
        key: 'add-node',
        text: 'Adicionar variável',
        onClick: () => this.setState({ newNodePosition: this.contextMenuPosition }),
      },
    ];

    this.nodeContextMenuItems = [
      {
        key: 'add-children',
        text: 'Adicionar filho',
        onClick: () => (this.nodeToAddChildrenTo = this.contextMenuNode),
      },
      {
        key: 'remove-node',
        text: 'Remover variável',
        onClick: () => {
          this.props.dispatch(removeNode(this.contextMenuNode.id));
          setTimeout(() => this.calculateArrows(), 0);
        },
      },
    ];

    this.arrowContextMenuItems = [
      {
        key: 'remove-link',
        text: 'Remover ligação',
        onClick: () => {
          const { childId, parentId } = this.contextMenuArrow;
          this.props.dispatch(removeParent(childId, parentId));
          setTimeout(() => this.calculateArrows(), 0);
        },
      },
    ];
  }

  componentDidMount() {
    this.calculateArrows();
  }

  calculateArrows = () => {
    const getNodeLinksPositions = node => {
      const { height, width } = this.rectRefs[node.id].getBoundingClientRect();

      const top = {
        x: node.position.x + width / 2,
        y: node.position.y,
        type: 'top',
      };

      const right = {
        x: node.position.x + width,
        y: node.position.y + height / 2,
        type: 'right',
      };

      const bottom = {
        x: node.position.x + width / 2,
        y: node.position.y + height,
        type: 'bottom',
      };

      const left = {
        x: node.position.x,
        y: node.position.y + height / 2,
        type: 'left',
      };

      return [top, right, bottom, left];
    };

    const getDistance = (p1, p2) => (
      Math.sqrt((Math.abs(p2.x - p1.x) ** 2) + (Math.abs(p2.y - p1.y) ** 2))
    );

    const getNearestPoints = (node1, node2) => {
      const ps1 = getNodeLinksPositions(node1);
      const ps2 = getNodeLinksPositions(node2);

      let p1 = ps1[0];
      let p2 = ps2[0];

      for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
          if (getDistance(p1, p2) > getDistance(ps1[i], ps2[j])) {
            p1 = ps1[i];
            p2 = ps2[j];
          }
        }
      }

      return { p1, p2 };
    };

    const { nodes } = this.props;
    const arrows = [];

    nodes.forEach(node => {
      node.parents.forEach(parentId => {
        const parent = nodes.find(x => x.id === parentId);
        const points = getNearestPoints(parent, node);

        arrows.push({
          key: `${parentId}-${node.id}`,
          from: points.p1,
          to: points.p2,
          parentId,
          childId: node.id,
        });
      });
    });

    this.setState({ arrows });
  };

  handleArrowMouseDown = (arrow, e) => {
    if (e.button === 2) {
      e.stopPropagation();

      this.contextMenuArrow = arrow;
      this.setState({ contextMenuItems: this.arrowContextMenuItems });
      this.contextMenu.handleContainerMouseDown(e);
    }
  };

  handleNodeMouseDown = (node, e) => {
    e.stopPropagation();

    this.props.dispatch(changeNetworkProperty('selectedNodes', [node.id]));

    if (e.button === 0) {
      this.contextMenu.hide();

      if (this.nodeToAddChildrenTo !== null) {
        this.props.dispatch(addParent(node.id, this.nodeToAddChildrenTo.id));
        this.nodeToAddChildrenTo = null;
        this.setState({ addingNodeArrow: null });
        setTimeout(() => this.calculateArrows(), 0);
      }

      this.movingNode = {
        id: node.id,
        initialPosition: {
          x: node.position.x,
          y: node.position.y,
        },
        initialMousePosition: {
          x: e.clientX,
          y: e.clientY,
        },
      };
    } else if (e.button === 2) {
      this.contextMenuNode = node;
      this.setState({ contextMenuItems: this.nodeContextMenuItems });
      this.contextMenu.handleContainerMouseDown(e);
    }
  };

  handleMouseDown = e => {
    // Use setTimeout to ensure that the blur event of inputs in the properties panel is fired.
    setTimeout(() => {
      this.props.dispatch(changeNetworkProperty('selectedNodes', []));
    }, 0);

    if (this.nodeToAddChildrenTo !== null) {
      this.nodeToAddChildrenTo = null;
      this.setState({ addingNodeArrow: null });
    }

    if (e.button === 2) {
      const rect = this.canvas.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;

      this.contextMenuPosition = { x, y };
      this.setState({ contextMenuItems: this.canvasContextMenuItems });
      this.contextMenu.handleContainerMouseDown(e);
    }
  };

  handleMouseMove = e => {
    if (this.movingNode !== null) {
      const { id, initialPosition, initialMousePosition } = this.movingNode;

      const difX = e.clientX - initialMousePosition.x;
      const difY = e.clientY - initialMousePosition.y;

      const newX = initialPosition.x + difX;
      const newY = initialPosition.y + difY;

      this.props.dispatch(changeNodePosition(id, newX, newY));

      this.calculateArrows();
    }

    if (this.nodeToAddChildrenTo !== null) {
      const canvasRect = this.canvas.getBoundingClientRect();
      const nodeRect = this.rectRefs[this.nodeToAddChildrenTo.id].getBoundingClientRect();

      const from = {
        x: nodeRect.left + (nodeRect.width / 2) - canvasRect.left,
        y: nodeRect.top + (nodeRect.height / 2) - canvasRect.top,
      };

      const to = {
        x: e.clientX - canvasRect.left,
        y: e.clientY - canvasRect.top,
      };

      this.setState({
        addingNodeArrow: { from, to },
      });
    }
  };

  handleMouseUp = () => {
    if (this.movingNode !== null) {
      this.movingNode = null;
      this.props.dispatch(persistState());
    }
  };

  handleMouseLeave = () => {
    if (this.movingNode !== null) {
      this.movingNode = null;
      this.props.dispatch(persistState());
    }

    if (this.nodeToAddChildrenTo !== null) {
      this.nodeToAddChildrenTo = null;
      this.setState({ addingNodeArrow: null });
    }
  };

  renderDefs = () => (
    <defs>
      <marker
        id="triangle"
        viewBox="0 0 10 10"
        markerWidth="6"
        markerHeight="6"
        refX="8"
        refY="5"
        orient="auto"
      >
        <path d="M0,0 L10,5 L0,10" fill="#333" />
      </marker>
    </defs>
  );

  renderArrow = arrow => {
    const makeControlPoint = (point, n = 50) => {
      const control = { ...point };

      if (control.type === 'top') {
        control.y -= n;
      } else if (control.type === 'bottom') {
        control.y += n;
      } else if (control.type === 'left') {
        control.x -= n;
      } else if (control.type === 'right') {
        control.x += n;
      }

      return control;
    };

    const makeLine = (from, to) => {
      const c1 = makeControlPoint(from);
      const c2 = makeControlPoint(to);

      return `M${from.x},${from.y} C${c1.x},${c1.y} ${c2.x},${c2.y} ${to.x},${to.y}`;
    };

    const d = makeLine(arrow.from, arrow.to);
    const style = { cursor: 'pointer' };
    const onMouseDown = e => this.handleArrowMouseDown(arrow, e);

    return (
      <g key={arrow.key}>
        <path
          d={d}
          fill="none"
          stroke="transparent"
          strokeWidth="15"
          style={style}
          onMouseDown={onMouseDown}
        />
        <path
          d={d}
          fill="none"
          stroke="#333"
          strokeWidth="2"
          markerEnd="url(#triangle)"
          style={style}
          onMouseDown={onMouseDown}
        />
      </g>
    );
  };

  renderNode = node => (
    <Node
      key={node.id}
      id={node.id}
      states={node.states}
      results={this.props.inferenceResults[node.id]}
      selected={this.props.network.selectedNodes.some(x => x === node.id)}
      rectRef={ref => {
        this.rectRefs[node.id] = ref;
      }}
      onMouseDown={e => this.handleNodeMouseDown(node, e)}
      x={node.position.x}
      y={node.position.y}
    />
  );

  render() {
    let addingNodeArrow = null;

    if (this.state.addingNodeArrow != null) {
      const { from, to } = this.state.addingNodeArrow;

      addingNodeArrow = (
        <path
          d={`M${from.x},${from.y} ${to.x},${to.y}`}
          fill="none"
          stroke="#333"
          strokeWidth="2"
          strokeDasharray="5,5"
          markerEnd="url(#triangle)"
        />
      );
    }

    return (

          <svg
            className={styles.canvas}
            onContextMenu={e => e.preventDefault()}
            onMouseDown={this.handleMouseDown}
            onMouseMove={this.handleMouseMove}
            onMouseUp={this.handleMouseUp}
            onMouseLeave={this.handleMouseLeave}
            height={this.props.network.height}
            width={this.props.network.width}
            ref={ref => (this.canvas = ref)}
          >
            {this.renderDefs()}
            {this.state.arrows.map(this.renderArrow)}
            {this.props.nodes.map(this.renderNode)}
            {addingNodeArrow}
          </svg>

          <ContextMenu
            ref={ref => (this.contextMenu = ref)}
            items={this.state.contextMenuItems}
          />

          <AddNodeModal
            position={this.state.newNodePosition}
            onRequestClose={() => this.setState({ newNodePosition: null })}
          />

    );
  }
}

Canvas.propTypes = {
  dispatch: PropTypes.func.isRequired,
  network: PropTypes.object.isRequired,
  nodes: PropTypes.array.isRequired,
  inferenceResults: PropTypes.object.isRequired,
};

const mapStateToProps = state => ({
  network: getNetwork(state),
  nodes: getNodes(state),
  inferenceResults: getInferenceResults(state),
});

export default connect(mapStateToProps, null, null, { withRef: true })(Canvas);
<commit_msg>Fix english<commit_after>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import ContextMenu from '../ContextMenu';
import AddNodeModal from '../AddNodeModal';
import Node from '../Node';
import styles from './styles.css';

import {
  persistState,
  removeNode,
  addParent,
  removeParent,
  changeNetworkProperty,
  changeNodePosition,
} from '../../actions';

import {
  getNetwork,
  getNodes,
  getInferenceResults,
} from '../../selectors';

class Canvas extends Component {
  constructor(props) {
    super(props);

    this.state = {
      arrows: [],
      contextMenuItems: [],
      newNodePosition: null,
      addingChildArrow: null,
    };

    this.rectRefs = {};
    this.movingNode = null;
    this.nodeToAddChildTo = null;

    this.canvasContextMenuItems = [
      {
        key: 'add-node',
        text: 'Adicionar variável',
        onClick: () => this.setState({ newNodePosition: this.contextMenuPosition }),
      },
    ];

    this.nodeContextMenuItems = [
      {
        key: 'add-child',
        text: 'Adicionar filho',
        onClick: () => (this.nodeToAddChildTo = this.contextMenuNode),
      },
      {
        key: 'remove-node',
        text: 'Remover variável',
        onClick: () => {
          this.props.dispatch(removeNode(this.contextMenuNode.id));
          setTimeout(() => this.calculateArrows(), 0);
        },
      },
    ];

    this.arrowContextMenuItems = [
      {
        key: 'remove-link',
        text: 'Remover ligação',
        onClick: () => {
          const { childId, parentId } = this.contextMenuArrow;
          this.props.dispatch(removeParent(childId, parentId));
          setTimeout(() => this.calculateArrows(), 0);
        },
      },
    ];
  }

  componentDidMount() {
    this.calculateArrows();
  }

  calculateArrows = () => {
    const getNodeLinksPositions = node => {
      const { height, width } = this.rectRefs[node.id].getBoundingClientRect();

      const top = {
        x: node.position.x + width / 2,
        y: node.position.y,
        type: 'top',
      };

      const right = {
        x: node.position.x + width,
        y: node.position.y + height / 2,
        type: 'right',
      };

      const bottom = {
        x: node.position.x + width / 2,
        y: node.position.y + height,
        type: 'bottom',
      };

      const left = {
        x: node.position.x,
        y: node.position.y + height / 2,
        type: 'left',
      };

      return [top, right, bottom, left];
    };

    const getDistance = (p1, p2) => (
      Math.sqrt((Math.abs(p2.x - p1.x) ** 2) + (Math.abs(p2.y - p1.y) ** 2))
    );

    const getNearestPoints = (node1, node2) => {
      const ps1 = getNodeLinksPositions(node1);
      const ps2 = getNodeLinksPositions(node2);

      let p1 = ps1[0];
      let p2 = ps2[0];

      for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
          if (getDistance(p1, p2) > getDistance(ps1[i], ps2[j])) {
            p1 = ps1[i];
            p2 = ps2[j];
          }
        }
      }

      return { p1, p2 };
    };

    const { nodes } = this.props;
    const arrows = [];

    nodes.forEach(node => {
      node.parents.forEach(parentId => {
        const parent = nodes.find(x => x.id === parentId);
        const points = getNearestPoints(parent, node);

        arrows.push({
          key: `${parentId}-${node.id}`,
          from: points.p1,
          to: points.p2,
          parentId,
          childId: node.id,
        });
      });
    });

    this.setState({ arrows });
  };

  handleArrowMouseDown = (arrow, e) => {
    if (e.button === 2) {
      e.stopPropagation();

      this.contextMenuArrow = arrow;
      this.setState({ contextMenuItems: this.arrowContextMenuItems });
      this.contextMenu.handleContainerMouseDown(e);
    }
  };

  handleNodeMouseDown = (node, e) => {
    e.stopPropagation();

    this.props.dispatch(changeNetworkProperty('selectedNodes', [node.id]));

    if (e.button === 0) {
      this.contextMenu.hide();

      if (this.nodeToAddChildTo !== null) {
        this.props.dispatch(addParent(node.id, this.nodeToAddChildTo.id));
        this.nodeToAddChildTo = null;
        this.setState({ addingChildArrow: null });
        setTimeout(() => this.calculateArrows(), 0);
      }

      this.movingNode = {
        id: node.id,
        initialPosition: {
          x: node.position.x,
          y: node.position.y,
        },
        initialMousePosition: {
          x: e.clientX,
          y: e.clientY,
        },
      };
    } else if (e.button === 2) {
      this.contextMenuNode = node;
      this.setState({ contextMenuItems: this.nodeContextMenuItems });
      this.contextMenu.handleContainerMouseDown(e);
    }
  };

  handleMouseDown = e => {
    // Use setTimeout to ensure that the blur event of inputs in the properties panel is fired.
    setTimeout(() => {
      this.props.dispatch(changeNetworkProperty('selectedNodes', []));
    }, 0);

    if (this.nodeToAddChildTo !== null) {
      this.nodeToAddChildTo = null;
      this.setState({ addingChildArrow: null });
    }

    if (e.button === 2) {
      const rect = this.canvas.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;

      this.contextMenuPosition = { x, y };
      this.setState({ contextMenuItems: this.canvasContextMenuItems });
      this.contextMenu.handleContainerMouseDown(e);
    }
  };

  handleMouseMove = e => {
    if (this.movingNode !== null) {
      const { id, initialPosition, initialMousePosition } = this.movingNode;

      const difX = e.clientX - initialMousePosition.x;
      const difY = e.clientY - initialMousePosition.y;

      const newX = initialPosition.x + difX;
      const newY = initialPosition.y + difY;

      this.props.dispatch(changeNodePosition(id, newX, newY));

      this.calculateArrows();
    }

    if (this.nodeToAddChildTo !== null) {
      const canvasRect = this.canvas.getBoundingClientRect();
      const nodeRect = this.rectRefs[this.nodeToAddChildTo.id].getBoundingClientRect();

      const from = {
        x: nodeRect.left + (nodeRect.width / 2) - canvasRect.left,
        y: nodeRect.top + (nodeRect.height / 2) - canvasRect.top,
      };

      const to = {
        x: e.clientX - canvasRect.left,
        y: e.clientY - canvasRect.top,
      };

      this.setState({
        addingChildArrow: { from, to },
      });
    }
  };

  handleMouseUp = () => {
    if (this.movingNode !== null) {
      this.movingNode = null;
      this.props.dispatch(persistState());
    }
  };

  handleMouseLeave = () => {
    if (this.movingNode !== null) {
      this.movingNode = null;
      this.props.dispatch(persistState());
    }

    if (this.nodeToAddChildTo !== null) {
      this.nodeToAddChildTo = null;
      this.setState({ addingChildArrow: null });
    }
  };

  renderDefs = () => (
    <defs>
      <marker
        id="triangle"
        viewBox="0 0 10 10"
        markerWidth="6"
        markerHeight="6"
        refX="8"
        refY="5"
        orient="auto"
      >
        <path d="M0,0 L10,5 L0,10" fill="#333" />
      </marker>
    </defs>
  );

  renderArrow = arrow => {
    const makeControlPoint = (point, n = 50) => {
      const control = { ...point };

      if (control.type === 'top') {
        control.y -= n;
      } else if (control.type === 'bottom') {
        control.y += n;
      } else if (control.type === 'left') {
        control.x -= n;
      } else if (control.type === 'right') {
        control.x += n;
      }

      return control;
    };

    const makeLine = (from, to) => {
      const c1 = makeControlPoint(from);
      const c2 = makeControlPoint(to);

      return `M${from.x},${from.y} C${c1.x},${c1.y} ${c2.x},${c2.y} ${to.x},${to.y}`;
    };

    const d = makeLine(arrow.from, arrow.to);
    const style = { cursor: 'pointer' };
    const onMouseDown = e => this.handleArrowMouseDown(arrow, e);

    return (
      <g key={arrow.key}>
        <path
          d={d}
          fill="none"
          stroke="transparent"
          strokeWidth="15"
          style={style}
          onMouseDown={onMouseDown}
        />
        <path
          d={d}
          fill="none"
          stroke="#333"
          strokeWidth="2"
          markerEnd="url(#triangle)"
          style={style}
          onMouseDown={onMouseDown}
        />
      </g>
    );
  };

  renderNode = node => (
    <Node
      key={node.id}
      id={node.id}
      states={node.states}
      results={this.props.inferenceResults[node.id]}
      selected={this.props.network.selectedNodes.some(x => x === node.id)}
      rectRef={ref => {
        this.rectRefs[node.id] = ref;
      }}
      onMouseDown={e => this.handleNodeMouseDown(node, e)}
      x={node.position.x}
      y={node.position.y}
    />
  );

  render() {
    let addingChildArrow = null;

    if (this.state.addingChildArrow != null) {
      const { from, to } = this.state.addingChildArrow;

      addingChildArrow = (
        <path
          d={`M${from.x},${from.y} ${to.x},${to.y}`}
          fill="none"
          stroke="#333"
          strokeWidth="2"
          strokeDasharray="5,5"
          markerEnd="url(#triangle)"
        />
      );
    }

    return (

          <svg
            className={styles.canvas}
            onContextMenu={e => e.preventDefault()}
            onMouseDown={this.handleMouseDown}
            onMouseMove={this.handleMouseMove}
            onMouseUp={this.handleMouseUp}
            onMouseLeave={this.handleMouseLeave}
            height={this.props.network.height}
            width={this.props.network.width}
            ref={ref => (this.canvas = ref)}
          >
            {this.renderDefs()}
            {this.state.arrows.map(this.renderArrow)}
            {this.props.nodes.map(this.renderNode)}
            {addingChildArrow}
          </svg>

          <ContextMenu
            ref={ref => (this.contextMenu = ref)}
            items={this.state.contextMenuItems}
          />

          <AddNodeModal
            position={this.state.newNodePosition}
            onRequestClose={() => this.setState({ newNodePosition: null })}
          />

    );
  }
}

Canvas.propTypes = {
  dispatch: PropTypes.func.isRequired,
  network: PropTypes.object.isRequired,
  nodes: PropTypes.array.isRequired,
  inferenceResults: PropTypes.object.isRequired,
};

const mapStateToProps = state => ({
  network: getNetwork(state),
  nodes: getNodes(state),
  inferenceResults: getInferenceResults(state),
});

export default connect(mapStateToProps, null, null, { withRef: true })(Canvas);
<|endoftext|>


<commit_before>"use strict";

var events = require ("events");
var util = require ("util");
var Request = require ("./request");
var opcode = require ("./opcode");

var Reader = module.exports = function (remote, globalOptions){
  events.EventEmitter.call (this);

  this._windowStart = 1;
  this._windowBlocksIndex = {};
  this._windowBlocks = [];
  this._preFilterFn = function (e){
    return e.block >= me._windowStart;
  };
  this._postFilterFn = function (e){
    return e.block < me._windowStart;
  };
  this._sortFn = function (a, b){
    return a.block - b.block;
  };
  this._lastReceived = false;
  this._windowSize = null;
  this._pending = null;
  this._expected = null;
  this._oack = null;
  this._firstWindow = true;
  this._windowFull = function (){
    me._notifyWindow ();
  };
  this._mayRollover = false;
  this._rolloverFix = 0;

  var me = this;
  this._request = new Request (opcode.RRQ, remote, globalOptions)
      .on ("error", function (error){
        me._retransmitter.reset ();
        me.emit ("error", error);
      })
      .on ("abort", function (){
        me._retransmitter.reset ();
        me.emit ("abort");
      })
      .on ("close", function (){
        me._retransmitter.reset ();
        me.emit ("close");
      })
      .on ("ready", function (stats, oack){
        //The reader doesn't make use of the rollover option, it's not safe
        //because there isn't an specification for default values
        me._pending = me._windowSize = stats.windowSize;
        me._blockSize = stats.blockSize;

        //Start the timer for the first time
        me._retransmit ();
        me._oack = oack;

        delete stats.rollover;
        me.emit ("stats", stats);
      })
      .on ("timeout", function (){
        me._retransmitter.reset ();
      })
      .on ("data", function (data){
        me._onData (data);
      });

  this._retransmitter = this._request.createRetransmitter ();
};

util.inherits (Reader, events.EventEmitter);

Reader.prototype.abort = function (){
  this._request.abort ();
};

Reader.prototype._blockToRetransmit = function (){
  if (!this._windowBlocks.length){
    //Resend ACK for the oack
    if (this._oack) return 0;
    //Rollover
    if (this._windowStart === 0 ||
        (this._windowStart === 1 && !this._firstWindow)) return 65535;
    //First empty window will never happen (oack case treated before)
    //This is mostly executed by classic tftp server implementations
    return this._windowStart - 1;
  }

  //Sort the blocks and find the last well-received one
  this._sortWindow ();
  //-1 if rollovered to 0
  var last = this._windowStart - 1;

  for (var i=0; i<this._windowBlocks.length; i++){
    if (last + 1 !== this._windowBlocks[i].block){
      return last === -1 || (this._mayRollover && last === 0) ? 65535 : last;
    }
    if (++last === 65535){
      //Is not possible to determine the next expected block: 0 or 1, so assume
      //that the last valid block is 65535 even if there are more valid blocks
      //already received
      return 65535;
    }
  }

  //The last block of the window is missing
  return last;
};

Reader.prototype._retransmit = function (){
  var me = this;
  this._retransmitter.start (function (){
    var block = me._blockToRetransmit ();console.log(block)
    if (block === undefined) return;
    if (block > 0){
      //Update the window and emit back to the client the data
      //By default rollovers to 1
      me._windowStart = block === 65535 ? 1 : block + 1;
      //The last block could have been received
      me._lastReceived = false;
      me._notifyWindow (block);
    }
    me._request.sendAck (block);
  });
};

Reader.prototype._sortWindow = function (){
  if (this._mayRollover){
    //Example: [65535, 65534, 1, 0] -> [65534, 65535, 0, 1]
    var preRoll = this._windowBlocks.filter (this._preFilterFn);
    var postRoll = this._windowBlocks.filter (this._postFilterFn);
    preRoll.sort (this._sortFn);
    postRoll.sort (this._sortFn);
    this._windowBlocks = preRoll.concat (postRoll);
  }else{
    this._windowBlocks.sort (this._sortFn);
  }
};

Reader.prototype._notifyWindow = function (block){
  this._pending = this._windowSize;
  var arr;

  //Emit data
  if (block){
    //Error recovery, slow case
    //Two loops must be executed because a rollovered window, eg: [65535, 0, 1]
    var index = null;
    arr = [];
    for (var i=0; i<this._windowBlocks.length; i++){
      //Search the index of the last valid block
      if (this._windowBlocks[i].block === block){
        index = i;
        break;
      }
    }
    if (index !== null){
      //Copy the valid blocks
      for (var i=0; i<=index; i++){
        arr.push (this._windowBlocks[i]);
      }
    }
  }else{
    //Fast case
    arr = this._windowBlocks;
  }

  var me = this;
  arr.forEach (function (message){
    //Ignore DATA packets with 0 length, they are received when the file can be
    //split up in blocks that perfectly fits a window
    if (message.data.length){
      me.emit ("data", message.data);
    }
  });

  if (this._lastReceived) return this._request.close ();

  this._windowBlocks = [];
  this._windowBlocksIndex = {};
  this._oack = false;
  this._firstWindow = false;
  this._mayRollover = false;
};

Reader.prototype._onData = function (message){//console.log("<< " + message.block)
  if (message.block === 0){
    //The server has rollovered to 0
    this._rolloverFix = 1;
  }

  //Check is the curernt window may rollover
  var windowEnd = this._windowStart + this._windowSize - 1;
  if (!this._mayRollover){
    this._mayRollover = windowEnd - 65535 > 0;
  }

  //Check the validity of the block if the current window doesn't rollover and
  //the block is outside the valid range, it could be a duplicate (sorcerer's
  //apprendice syndrome)
  if (!this._mayRollover &&
      message.block < this._windowStart || message.block > windowEnd) return;

  //Ignore duplicates
  if (this._windowBlocksIndex[message.block]) return;

  //Insert new block
  this._windowBlocksIndex[message.block] = true;
  this._windowBlocks.push (message);

  //Update the pending packets
  if (message.data.length < this._blockSize){
    //Last packet
    this._pending = message.block - this._windowStart + 1 -
        this._windowBlocks.length;
    this._lastReceived = true;
  }else{
    this._pending--;
  }

  if (!this._pending){
    //Send ACK for the latest block
    this._windowStart += this._windowSize;
    if (this._windowStart > 65535){
      //By default rollovers to 1
      this._windowStart -= 65535 + this._rolloverFix;
    }

    //Sort the blocks
    this._sortWindow ();

    //Cancel the current timer and set it again
    this._retransmitter.reset ();
    this._retransmit ();

    //ACK the current window
    this._request.sendAck (
        this._windowBlocks[this._windowBlocks.length - 1].block,
        this._windowFull);
  }
};<commit_msg>speed improvements<commit_after>"use strict";

var events = require ("events");
var util = require ("util");
var Request = require ("./request");
var opcode = require ("./opcode");

var Reader = module.exports = function (remote, globalOptions){
  events.EventEmitter.call (this);

  this._windowStart = 1;
  this._windowBlocksIndex = {};
  this._windowBlocks = [];
  this._preFilterFn = function (e){
    return e.block >= me._windowStart;
  };
  this._postFilterFn = function (e){
    return e.block < me._windowStart;
  };
  this._sortFn = function (a, b){
    return a.block - b.block;
  };
  this._lastReceived = false;
  this._windowSize = null;
  this._pending = null;
  this._expected = null;
  this._oack = null;
  this._firstWindow = true;
  this._windowFullFn = function (){
    me._notifyWindow ();
  };
  this._restransmitterStartFn = function (){
    var block = me._blockToRetransmit ();
    if (block > 0){
      //Update the window and emit back to the client the data
      //By default rollovers to 1
      me._windowStart = block === 65535 ? 1 : block + 1;
      //The last block could have been received
      me._lastReceived = false;
      me._notifyWindow (block);
    }
    me._request.sendAck (block);
  };
  this._mayRollover = false;
  this._rolloverFix = 0;

  var me = this;
  this._request = new Request (opcode.RRQ, remote, globalOptions)
      .on ("error", function (error){
        me._retransmitter.reset ();
        me.emit ("error", error);
      })
      .on ("abort", function (){
        me._retransmitter.reset ();
        me.emit ("abort");
      })
      .on ("close", function (){
        me._retransmitter.reset ();
        me.emit ("close");
      })
      .on ("ready", function (stats, oack){
        //The reader doesn't make use of the rollover option, it's not safe
        //because there isn't an specification for default values
        me._pending = me._windowSize = stats.windowSize;
        me._blockSize = stats.blockSize;

        //Start the timer for the first time
        me._retransmitter.start (me._restransmitterStartFn);
        me._oack = oack;

        delete stats.rollover;
        me.emit ("stats", stats);
      })
      .on ("timeout", function (){
        me._retransmitter.reset ();
      })
      .on ("data", function (data){
        me._onData (data);
      });

  this._retransmitter = this._request.createRetransmitter ();
};

util.inherits (Reader, events.EventEmitter);

Reader.prototype.abort = function (){
  this._request.abort ();
};

Reader.prototype._blockToRetransmit = function (){
  if (!this._windowBlocks.length){
    //Resend ACK for the oack
    if (this._oack) return 0;
    //Rollover
    if (this._windowStart === 0 ||
        (this._windowStart === 1 && !this._firstWindow)) return 65535;
    //First empty window will never happen (oack case treated before)
    //This is mostly executed by classic tftp server implementations
    return this._windowStart - 1;
  }

  //Sort the blocks and find the last well-received one
  this._sortWindow ();
  //-1 if rollovered to 0
  var last = this._windowStart - 1;

  for (var i=0; i<this._windowBlocks.length; i++){
    if (last + 1 !== this._windowBlocks[i].block){
      return last === -1 || (this._mayRollover && last === 0) ? 65535 : last;
    }
    if (++last === 65535){
      //Is not possible to determine the next expected block: 0 or 1, so assume
      //that the last valid block is 65535 even if there are more valid blocks
      //already received
      return 65535;
    }
  }

  //The last block of the window is missing
  return last;
};

Reader.prototype._retransmit = function (){
  this._retransmitter.start (this._restransmitterStartFn);
};

Reader.prototype._sortWindow = function (){
  if (this._mayRollover){
    //Example: [65535, 65534, 1, 0] -> [65534, 65535, 0, 1]
    var preRoll = this._windowBlocks.filter (this._preFilterFn);
    var postRoll = this._windowBlocks.filter (this._postFilterFn);
    preRoll.sort (this._sortFn);
    postRoll.sort (this._sortFn);
    this._windowBlocks = preRoll.concat (postRoll);
  }else{
    this._windowBlocks.sort (this._sortFn);
  }
};

Reader.prototype._notifyWindow = function (block){
  this._pending = this._windowSize;
  var arr;

  //Emit data
  if (block){
    //Error recovery, slow case
    //Two loops must be executed because a rollovered window, eg: [65535, 0, 1]
    var index = null;
    arr = [];
    for (var i=0; i<this._windowBlocks.length; i++){
      //Search the index of the last valid block
      if (this._windowBlocks[i].block === block){
        index = i;
        break;
      }
    }
    if (index !== null){
      //Copy the valid blocks
      for (var i=0; i<=index; i++){
        arr.push (this._windowBlocks[i]);
      }
    }
  }else{
    //Fast case
    arr = this._windowBlocks;
  }

  var me = this;
  arr.forEach (function (message){
    //Ignore DATA packets with 0 length, they are received when the file can be
    //split up in blocks that perfectly fits a window
    if (message.data.length){
      me.emit ("data", message.data);
    }
  });

  if (this._lastReceived) return this._request.close ();

  this._windowBlocks = [];
  this._windowBlocksIndex = {};
  this._oack = false;
  this._firstWindow = false;
  this._mayRollover = false;
};

Reader.prototype._onData = function (message){//console.log("<< " + message.block)
  if (message.block === 0){
    //The server has rollovered to 0
    this._rolloverFix = 1;
  }

  //Check is the curernt window may rollover
  var windowEnd = this._windowStart + this._windowSize - 1;
  if (!this._mayRollover){
    this._mayRollover = windowEnd - 65535 > 0;
  }

  //Check the validity of the block if the current window doesn't rollover and
  //the block is outside the valid range, it could be a duplicate (sorcerer's
  //apprendice syndrome)
  if (!this._mayRollover &&
      message.block < this._windowStart || message.block > windowEnd) return;

  //Ignore duplicates
  if (this._windowBlocksIndex[message.block]) return;

  //Insert new block
  this._windowBlocksIndex[message.block] = true;
  this._windowBlocks.push (message);

  //Update the pending packets
  if (message.data.length < this._blockSize){
    //Last packet
    this._pending = message.block - this._windowStart + 1 -
        this._windowBlocks.length;
    this._lastReceived = true;
  }else{
    this._pending--;
  }

  if (!this._pending){
    //Send ACK for the latest block
    this._windowStart += this._windowSize;
    if (this._windowStart > 65535){
      //By default rollovers to 1
      this._windowStart -= 65535 + this._rolloverFix;
    }

    //Sort the blocks
    this._sortWindow ();

    //Cancel the current timer and set it again
    this._retransmitter.reset ();
    this._retransmitter.start (this._restransmitterStartFn);

    //ACK the current window
    this._request.sendAck (
        this._windowBlocks[this._windowBlocks.length - 1].block,
        this._windowFullFn);
  }
};<|endoftext|>


<commit_before>// nodeunit

var $object = require('../src/clone.js');

module.exports = {

    clone: function(test){

        var clone = $object.clone({a:1});
            test.ok( clone.hasOwnProperty('a') );
            test.equal( Object.getPrototypeOf(clone), $object);
            test.strictEqual( Object.getOwnPropertyNames(clone).length, 1);

        clone = $object.clone({a:1}, {});
            test.ok( clone.hasOwnProperty('a') );
            test.equal( Object.getPrototypeOf(clone), $object);
            test.strictEqual( Object.getOwnPropertyNames(clone).length, 1);

        clone = $object.clone();
            test.strictEqual( Object.getOwnPropertyNames(clone).length, 0);
            test.equal( Object.getPrototypeOf(clone), $object);

        test.done();
    },

    'clone.call': function(test){
        var $proto = {a: 1};

            var clone = $object.clone.call($proto);
                test.equal( Object.getPrototypeOf(clone), $proto,
                    'check prototype');

            clone = $object.clone.call($proto, {b:2});
                test.ok( clone.hasOwnProperty('b') );

            clone = $object.clone.call($proto, {b:2}, {});
                test.ok( clone.hasOwnProperty('b') );

        test.done();
    },

    'clone.constructor': function(test){
        var constructor = $object.clone({constructor: ''}).constructor;
        var c = $object.clone({constructor: ''});
            test.ok(constructor !== c.constructor);
            test.ok(constructor !== $object.clone().constructor);
            test.equal(typeof constructor, 'function');

        test.done();
    },

    create: function(test){
        var constructorCalled = false;
        var $myType = $object.clone({
            constructor: function(){
                constructorCalled = true;
            }
        });
        var instance = $myType.create({ignored: true});
            test.ok(constructorCalled);
            test.ok(typeof instance.ignored == 'undefined');

        test.done();
    },

    describe: function(test){

        //test.expect(2);

        test.deepEqual(
            $object.describe({
                         _p: undefined,
      '(const) _unwritable': 231,
                     method: Function,
                constructor: Function
            }),{
                         _p: {value: undefined, enumerable:false},
                _unwritable: {value: 231, enumerable:false, writable: false},
                     method: {value: Function, enumerable:false},
                constructor: {value: Function, enumerable:false}
            },
            'private properties, functions, constructor should be not enumerable'
        );

        //todo

        test.done();
    },

    'can, cant': function(test){

        var $myObj = $object.clone({
            fly: function(){},
            swim: function(a,b,c){}
        });
        var myObj = $myObj.create();
            test.ok(!!   myObj.can('swim').as($myObj) );
            test.ok(!! $object.can.call(myObj, 'fly').like($myObj) );

            test.ok(!    myObj.cant('swim').as($myObj) );
            test.ok(!  $object.cant.call(myObj, 'fly').like($myObj) );

        test.done();
    },

    copy: function(test){
        var myArray = $object.copy(Array);
        myArray[0] = 11;
        myArray[1] = 22;
            test.deepEqual(myArray, [11 ,22]);

            myArray.defineProperties({test: 'T'});
                test.strictEqual(myArray.test, 'T');

        var $collection = $object.clone({items: []});
        var $users = $collection.clone({name: ''});

            // $users full prototype chain:
            //$users -> $collection -> $object -> Object.prototype -> null

            // see prototype chains produced by copy:

            var userCopy = $users.copy();
            //~$users -> $object
                test.equal(Object.getPrototypeOf(userCopy), $object);
                test.ok(userCopy.hasOwnProperty('name'));
                test.ok(userCopy.items === undefined);

            userCopy = $users.copy(Array);
            //~$users -> Array.prototype
                test.equal(Object.getPrototypeOf(userCopy), Array.prototype);
                test.ok(userCopy.hasOwnProperty('name'));
                test.ok(userCopy.items === undefined);
                test.ok(userCopy.clone === undefined);

            userCopy = $users.copy(Array, Infinity);
            //~$users -> ~$collection -> ~$object -> Array.prototype
                test.ok(userCopy.hasOwnProperty('name'));
                test.ok(userCopy.getPrototype().hasOwnProperty('items'));
                test.ok(userCopy.getPrototype().getPrototype().hasOwnProperty('clone'));
                test.ok(userCopy.getPrototype().getPrototype().getPrototype() === Array.prototype);

            userCopy = $users.copy(Array, Infinity, true);
            //~($users + $collection + $object) -> Array.prototype
                test.equal(Object.getPrototypeOf(userCopy), Array.prototype);
                test.ok(userCopy.hasOwnProperty('name'));
                test.ok(userCopy.hasOwnProperty('items'));
                test.ok(userCopy.hasOwnProperty('clone'));

        //TODO: add tests for deepCopy/deepClone

        test.done();
    },

    deepCopy: function(test){
        var obj = $object.clone({l1: {l2: {l3: null}}});
        var deepCopy = obj.deepCopy();
        test.strictEqual(deepCopy.l1.l2.l3, null);

            obj.l1.l2.l3 = 11;
                test.strictEqual(deepCopy.l1.l2.l3, null);

            deepCopy.l1.l2.l3 = 22;
                test.strictEqual(obj.l1.l2.l3, 11);

        test.done();
    },

    deepClone: function(test){
        var obj = $object.clone({l1: {l2: {l3: null}}});
        var deepClone = obj.deepClone();
            test.strictEqual(deepClone.l1.l2.l3, null);

            obj.l1.l2.l3 = 11;
                test.strictEqual(deepClone.l1.l2.l3, 11);

            deepClone.l1.l2.l3 = 22;
                test.strictEqual(obj.l1.l2.l3, 11);

        test.done();
    },

    callSuper: function(test){
        var calls = [];
        var $parent = $object.clone({
            constructor: function(arg){
                calls.push('collection');
                this.callSuper('constructor', arg);
            }
        });
        var $child = $parent.clone({
            constructor: function(arg){
                calls.push('users');
                this.callSuper('constructor', arg);
            }
        });

        var child = $child.create({setBy$objectConstructor: 11});
            test.deepEqual(calls, ['users','collection']);
            test.equal(child.setBy$objectConstructor, 11, '$object.constructor called');

        test.done();
    },

    apply: function(test){
        //methodName, args, withObj, asObj
        var asObj = {defineProperties: function(){
            this.called = true;
            return this;
        }};
        var obj = $object.apply('defineProperties',[{a:11}], Array(22,33), asObj);
            test.equal(obj.a, undefined);
            test.ok(obj.called);
            test.equal(obj[0], 22);
            test.equal(Object.getPrototypeOf(obj), Array.prototype);

        //methodName, args, withObj
        obj = $object.apply('defineProperties',[{a:11}], Array(22,33) );
            test.equal(obj.a,  11);
            test.equal(obj[0], 22);
            test.equal(Object.getPrototypeOf(obj), Array.prototype);

        //methodName, withObj
        obj = $object.apply('defineProperties', Array(22,33) );
            test.equal(obj[0], 22);
            test.equal(Object.getPrototypeOf(obj), Array.prototype);

        test.done();
    }

};
<commit_msg>add applySuper() test<commit_after>// nodeunit

var $object = require('../src/clone.js');

module.exports = {

    clone: function(test){

        var clone = $object.clone({a:1});
            test.ok( clone.hasOwnProperty('a') );
            test.equal( Object.getPrototypeOf(clone), $object);
            test.strictEqual( Object.getOwnPropertyNames(clone).length, 1);

        clone = $object.clone({a:1}, {});
            test.ok( clone.hasOwnProperty('a') );
            test.equal( Object.getPrototypeOf(clone), $object);
            test.strictEqual( Object.getOwnPropertyNames(clone).length, 1);

        clone = $object.clone();
            test.strictEqual( Object.getOwnPropertyNames(clone).length, 0);
            test.equal( Object.getPrototypeOf(clone), $object);

        test.done();
    },

    'clone.call': function(test){
        var $proto = {a: 1};

            var clone = $object.clone.call($proto);
                test.equal( Object.getPrototypeOf(clone), $proto,
                    'check prototype');

            clone = $object.clone.call($proto, {b:2});
                test.ok( clone.hasOwnProperty('b') );

            clone = $object.clone.call($proto, {b:2}, {});
                test.ok( clone.hasOwnProperty('b') );

        test.done();
    },

    'clone.constructor': function(test){
        var constructor = $object.clone({constructor: ''}).constructor;
        var c = $object.clone({constructor: ''});
            test.ok(constructor !== c.constructor);
            test.ok(constructor !== $object.clone().constructor);
            test.equal(typeof constructor, 'function');

        test.done();
    },

    create: function(test){
        var constructorCalled = false;
        var $myType = $object.clone({
            constructor: function(){
                constructorCalled = true;
            }
        });
        var instance = $myType.create({ignored: true});
            test.ok(constructorCalled);
            test.ok(typeof instance.ignored == 'undefined');

        test.done();
    },

    describe: function(test){

        //test.expect(2);

        test.deepEqual(
            $object.describe({
                         _p: undefined,
      '(const) _unwritable': 231,
                     method: Function,
                constructor: Function
            }),{
                         _p: {value: undefined, enumerable:false},
                _unwritable: {value: 231, enumerable:false, writable: false},
                     method: {value: Function, enumerable:false},
                constructor: {value: Function, enumerable:false}
            },
            'private properties, functions, constructor should be not enumerable'
        );

        //todo

        test.done();
    },

    'can, cant': function(test){

        var $myObj = $object.clone({
            fly: function(){},
            swim: function(a,b,c){}
        });
        var myObj = $myObj.create();
            test.ok(!!   myObj.can('swim').as($myObj) );
            test.ok(!! $object.can.call(myObj, 'fly').like($myObj) );

            test.ok(!    myObj.cant('swim').as($myObj) );
            test.ok(!  $object.cant.call(myObj, 'fly').like($myObj) );

        test.done();
    },

    copy: function(test){
        var myArray = $object.copy(Array);
        myArray[0] = 11;
        myArray[1] = 22;
            test.deepEqual(myArray, [11 ,22]);

            myArray.defineProperties({test: 'T'});
                test.strictEqual(myArray.test, 'T');

        var $collection = $object.clone({items: []});
        var $users = $collection.clone({name: ''});

            // $users full prototype chain:
            //$users -> $collection -> $object -> Object.prototype -> null

            // see prototype chains produced by copy:

            var userCopy = $users.copy();
            //~$users -> $object
                test.equal(Object.getPrototypeOf(userCopy), $object);
                test.ok(userCopy.hasOwnProperty('name'));
                test.ok(userCopy.items === undefined);

            userCopy = $users.copy(Array);
            //~$users -> Array.prototype
                test.equal(Object.getPrototypeOf(userCopy), Array.prototype);
                test.ok(userCopy.hasOwnProperty('name'));
                test.ok(userCopy.items === undefined);
                test.ok(userCopy.clone === undefined);

            userCopy = $users.copy(Array, Infinity);
            //~$users -> ~$collection -> ~$object -> Array.prototype
                test.ok(userCopy.hasOwnProperty('name'));
                test.ok(userCopy.getPrototype().hasOwnProperty('items'));
                test.ok(userCopy.getPrototype().getPrototype().hasOwnProperty('clone'));
                test.ok(userCopy.getPrototype().getPrototype().getPrototype() === Array.prototype);

            userCopy = $users.copy(Array, Infinity, true);
            //~($users + $collection + $object) -> Array.prototype
                test.equal(Object.getPrototypeOf(userCopy), Array.prototype);
                test.ok(userCopy.hasOwnProperty('name'));
                test.ok(userCopy.hasOwnProperty('items'));
                test.ok(userCopy.hasOwnProperty('clone'));

        //TODO: add tests for deepCopy/deepClone

        test.done();
    },

    deepCopy: function(test){
        var obj = $object.clone({l1: {l2: {l3: null}}});
        var deepCopy = obj.deepCopy();
        test.strictEqual(deepCopy.l1.l2.l3, null);

            obj.l1.l2.l3 = 11;
                test.strictEqual(deepCopy.l1.l2.l3, null);

            deepCopy.l1.l2.l3 = 22;
                test.strictEqual(obj.l1.l2.l3, 11);

        test.done();
    },

    deepClone: function(test){
        var obj = $object.clone({l1: {l2: {l3: null}}});
        var deepClone = obj.deepClone();
            test.strictEqual(deepClone.l1.l2.l3, null);

            obj.l1.l2.l3 = 11;
                test.strictEqual(deepClone.l1.l2.l3, 11);

            deepClone.l1.l2.l3 = 22;
                test.strictEqual(obj.l1.l2.l3, 11);

        test.done();
    },

    'callSuper, applySuper': function(test){
        var calls = [];
        var $parent = $object.clone({
            constructor: function(arg){
                calls.push('collection');
                this.callSuper('constructor', arg);
            }
        });
        var $child = $parent.clone({
            constructor: function(arg){
                calls.push('users');
                this.callSuper('constructor', arg);
            }
        });

        var child = $child.create({setBy$objectConstructor: 11});
            test.deepEqual(calls, ['users','collection']);
            test.equal(child.setBy$objectConstructor, 11, '$object.constructor called');

        test.done();
    },

    apply: function(test){
        //methodName, args, withObj, asObj
        var asObj = {defineProperties: function(){
            this.called = true;
            return this;
        }};
        var obj = $object.apply('defineProperties',[{a:11}], Array(22,33), asObj);
            test.equal(obj.a, undefined);
            test.ok(obj.called);
            test.equal(obj[0], 22);
            test.equal(Object.getPrototypeOf(obj), Array.prototype);

        //methodName, args, withObj
        obj = $object.apply('defineProperties',[{a:11}], Array(22,33) );
            test.equal(obj.a,  11);
            test.equal(obj[0], 22);
            test.equal(Object.getPrototypeOf(obj), Array.prototype);

        //methodName, withObj
        obj = $object.apply('defineProperties', Array(22,33) );
            test.equal(obj[0], 22);
            test.equal(Object.getPrototypeOf(obj), Array.prototype);

        test.done();
    }

};
<|endoftext|>


<commit_before>var fs = require("fs");
var path = require('path');
var brocWriter = require("broccoli-writer");
var helpers = require("broccoli-kitchen-sink-helpers");
var funnel = require('broccoli-funnel');
var swToolboxFile = require.resolve('sw-toolbox/sw-toolbox.js');
var swToolboxMapFile = require.resolve('sw-toolbox/sw-toolbox.map.json');
var toolboxLocation = 'sw-toolbox.js';
var rsvp= require('rsvp');
var BroccoliServiceWorker = function BroccoliServiceWorker(inTree, options) {
  if (!(this instanceof BroccoliServiceWorker)) {
    return new BroccoliServiceWorker(inTree, options);
  }
  this.inTree = inTree;
  options = options || {};
  if (options.skipWaiting === false) {
    this.skipWaiting = false;
  } else {
    this.skipWaiting = true;
  }
  this.cacheFirstURLs = options.cacheFirstURLs || [];
  this.cacheOnlyURLs = options.cacheOnlyURLs || [];
  this.fastestURLs = options.fastestURLs || [];
  this.debug = options.debug || false;
  this.networkFirstURLs = options.networkFirstURLs || options.dynamicCache || [];
  this.excludePaths = options.excludePaths || ['tests/*'];
  this.fallback = options.fallback || [];
  this.rootURL = (options.rootURL === false ? false : options.rootURL || '/');
  this.precacheURLs = options.precacheURLs || [];
  if (options.includeRegistration === false) {
    this.includeRegistration = false;
  } else {
    this.includeRegistration = true;
  }
  if (this.includeRegistration === true || !options.serviceWorkerFile) {
    this.serviceWorkerFile = "service-worker.js";
  } else {
    this.serviceWorkerFile = options.serviceWorkerFile;
  }
  this.swIncludeTree = options.swIncludeTree;
  this.swIncludeFiles = options.swIncludeFiles;
};

BroccoliServiceWorker.prototype = Object.create(brocWriter.prototype);
BroccoliServiceWorker.prototype.constructor = BroccoliServiceWorker;

BroccoliServiceWorker.prototype.write = function(readTree, destDir) {
  var skipWaiting = this.skipWaiting;
  var cacheFirstURLs = this.cacheFirstURLs;
  var cacheOnlyURLs = this.cacheOnlyURLs;
  var debug = this.debug;
  var networkFirstURLs = this.networkFirstURLs;
  var fallback = this.fallback;
  var rootURL = this.rootURL;
  var fastestURLs = this.fastestURLs;
  var precacheURLs = this.precacheURLs;
  var serviceWorkerFile = this.serviceWorkerFile;
  var serviceWorkerTree = funnel(this.inTree, {
    exclude: this.excludePaths
  });
  var swIncludeFiles = this.swIncludeFiles;
  var swIncludeTree = this.swIncludeTree;

  return readSwIncludeTree(readTree, this.swIncludeTree).then(function(swIncludeDir){
    return readTree(serviceWorkerTree).then(function (srcDir) {
      var lines = [];
      lines.push("importScripts('"+toolboxLocation+"');");
      lines.push("var CACHE_PREFIX = 'brocsw-v';");
      lines.push("var CACHE_VERSION = CACHE_PREFIX+'"+(new Date()).getTime()+"';");
      lines.push("toolbox.options.cache.name = CACHE_VERSION;");
      if (debug) {
        lines.push("toolbox.options.debug = true;");
      }
      lines.push("var urlsToPrefetch = [");
      if (rootURL) {
        lines.push("    '"+rootURL+"',");
      }
      getFilesRecursively(srcDir, [ "**/*" ]).forEach(function (file, idx, array) {
        lines.push(createArrayLine('    '+JSON.stringify(file), idx, array.length));
      });
      lines.push("];");
      precacheURLs.forEach(function (file, idx, array) {
        lines.push("urlsToPrefetch.push('"+file+"');");
      });
      lines.push("urlsToPrefetch.forEach(function(url) {");
      lines.push("  toolbox.router.any(url, toolbox.cacheFirst);");
      lines.push("});");
      lines.push("toolbox.precache(urlsToPrefetch);");
      setupRoutes(cacheFirstURLs, 'toolbox.cacheFirst', lines);
      setupRoutes(cacheOnlyURLs, 'toolbox.cacheOnly', lines);
      setupRoutes(fastestURLs, 'toolbox.fastest', lines);
      setupRoutes(networkFirstURLs, 'toolbox.networkFirst', lines);

      if (fallback.length) {
        fallback.forEach(function(fallback, idx, array) {
          var fallbackParts = fallback.split(' ');
          if (fallbackParts.length > 1) {
            var fallbackOptions = "{fallbackURL:'"+fallbackParts[1]+"'}";
            lines.push("toolbox.router.any('"+fallbackParts[0]+"',fallbackResponse, "+fallbackOptions+");");
          }
        });
      }
      if (swIncludeFiles && swIncludeFiles.length) {
        swIncludeFiles.forEach(function(file) {
          lines.push(fs.readFileSync(file));
        });
      }
      if (swIncludeDir) {
        getFilesRecursively(swIncludeDir, [ "**/*" ]).forEach(function (file) {
          var srcFile = path.join(swIncludeDir, file);
          lines.push(fs.readFileSync(srcFile));
        });
      }
      if (skipWaiting || debug) {
        lines.push("self.addEventListener('install', function(event) {");
         addDebugLine("'Handling install event. Resources to pre-fetch:', urlsToPrefetch", debug, lines);
        if (skipWaiting) {
          lines.push("  if (self.skipWaiting) { self.skipWaiting(); }");
        }
        lines.push("});");
      }

      lines.push(getFileContents('delete-old-caches.js'));
      if (fallback.length) {
        lines.push(getFileContents('fallback-response.js'));
      }

      lines.push(getFileContents('log-debug.js'));
      fs.writeFileSync(path.join(destDir, serviceWorkerFile), lines.join("\n"));
      fs.writeFileSync(path.join(destDir, toolboxLocation), fs.readFileSync(swToolboxFile));
      if (debug) {
        fs.writeFileSync(path.join(destDir, 'sw-toolbox.map.json'), fs.readFileSync(swToolboxMapFile));
      }
    });
  });
};

BroccoliServiceWorker.prototype.addExternalFile = function(file) {
  this.externalFiles.push(file);
};

function addDebugLine(consoleText, debug, lines) {
  if (debug) {
    lines.push("console.log("+consoleText+");");
  }
}

function createArrayLine(line, idx, arrayLength) {
  var arrayLine = line;
  if ((idx+1) < arrayLength) {
    arrayLine += ",";
  }
  return arrayLine;
}

function getFilesRecursively(dir, globPatterns) {
  try {
    return helpers.multiGlob(globPatterns, { cwd: dir }).filter(function(file){
      var srcFile = path.join(dir, file);
      var stat = fs.lstatSync(srcFile);
      return (stat.isFile()  || stat.isSymbolicLink());
    });
  } catch (ex) {
    return [];
  }
}

function getFileContents(fileName) {
  var filePath = [ __dirname, fileName].join('/');
  return fs.readFileSync(filePath);
}

function printPath(path) {
  if (path instanceof RegExp) {
    return path.toString();
  } else {
    return JSON.stringify(path);
  }
}

function setupRoutes(routeUrls, handler, lines) {
  if (routeUrls.length) {
    routeUrls.forEach(function(cacheURL, idx, array) {
      var method = 'any';
      var options;

      if (typeof cacheURL === 'object' && (cacheURL instanceof RegExp === false)) {
        options = JSON.stringify(cacheURL.options);
        if (cacheURL.method) {
          method = cacheURL.method;
        }
        cacheURL = cacheURL.route;
      }
      var line = 'toolbox.router.'+method+'('+printPath(cacheURL)+',' + handler;

      if (options) {
        line += ', ';
        line += options;
      }

      line += ');';

      lines.push(line);
    });
  }
}

function readSwIncludeTree(readTree, swIncludeTree) {
  if (swIncludeTree) {
    return readTree(swIncludeTree);
  } else {
    return rsvp.resolve();
  }
}

module.exports = BroccoliServiceWorker;
<commit_msg>fix: concat `ENV.serviceWorker.swIncludeFiles` using `\\n;`<commit_after>var fs = require("fs");
var path = require('path');
var brocWriter = require("broccoli-writer");
var helpers = require("broccoli-kitchen-sink-helpers");
var funnel = require('broccoli-funnel');
var swToolboxFile = require.resolve('sw-toolbox/sw-toolbox.js');
var swToolboxMapFile = require.resolve('sw-toolbox/sw-toolbox.map.json');
var toolboxLocation = 'sw-toolbox.js';
var rsvp= require('rsvp');
var BroccoliServiceWorker = function BroccoliServiceWorker(inTree, options) {
  if (!(this instanceof BroccoliServiceWorker)) {
    return new BroccoliServiceWorker(inTree, options);
  }
  this.inTree = inTree;
  options = options || {};
  if (options.skipWaiting === false) {
    this.skipWaiting = false;
  } else {
    this.skipWaiting = true;
  }
  this.cacheFirstURLs = options.cacheFirstURLs || [];
  this.cacheOnlyURLs = options.cacheOnlyURLs || [];
  this.fastestURLs = options.fastestURLs || [];
  this.debug = options.debug || false;
  this.networkFirstURLs = options.networkFirstURLs || options.dynamicCache || [];
  this.excludePaths = options.excludePaths || ['tests/*'];
  this.fallback = options.fallback || [];
  this.rootURL = (options.rootURL === false ? false : options.rootURL || '/');
  this.precacheURLs = options.precacheURLs || [];
  if (options.includeRegistration === false) {
    this.includeRegistration = false;
  } else {
    this.includeRegistration = true;
  }
  if (this.includeRegistration === true || !options.serviceWorkerFile) {
    this.serviceWorkerFile = "service-worker.js";
  } else {
    this.serviceWorkerFile = options.serviceWorkerFile;
  }
  this.swIncludeTree = options.swIncludeTree;
  this.swIncludeFiles = options.swIncludeFiles;
};

BroccoliServiceWorker.prototype = Object.create(brocWriter.prototype);
BroccoliServiceWorker.prototype.constructor = BroccoliServiceWorker;

BroccoliServiceWorker.prototype.write = function(readTree, destDir) {
  var skipWaiting = this.skipWaiting;
  var cacheFirstURLs = this.cacheFirstURLs;
  var cacheOnlyURLs = this.cacheOnlyURLs;
  var debug = this.debug;
  var networkFirstURLs = this.networkFirstURLs;
  var fallback = this.fallback;
  var rootURL = this.rootURL;
  var fastestURLs = this.fastestURLs;
  var precacheURLs = this.precacheURLs;
  var serviceWorkerFile = this.serviceWorkerFile;
  var serviceWorkerTree = funnel(this.inTree, {
    exclude: this.excludePaths
  });
  var swIncludeFiles = this.swIncludeFiles;
  var swIncludeTree = this.swIncludeTree;

  return readSwIncludeTree(readTree, this.swIncludeTree).then(function(swIncludeDir){
    return readTree(serviceWorkerTree).then(function (srcDir) {
      var lines = [];
      lines.push("importScripts('"+toolboxLocation+"');");
      lines.push("var CACHE_PREFIX = 'brocsw-v';");
      lines.push("var CACHE_VERSION = CACHE_PREFIX+'"+(new Date()).getTime()+"';");
      lines.push("toolbox.options.cache.name = CACHE_VERSION;");
      if (debug) {
        lines.push("toolbox.options.debug = true;");
      }
      lines.push("var urlsToPrefetch = [");
      if (rootURL) {
        lines.push("    '"+rootURL+"',");
      }
      getFilesRecursively(srcDir, [ "**/*" ]).forEach(function (file, idx, array) {
        lines.push(createArrayLine('    '+JSON.stringify(file), idx, array.length));
      });
      lines.push("];");
      precacheURLs.forEach(function (file, idx, array) {
        lines.push("urlsToPrefetch.push('"+file+"');");
      });
      lines.push("urlsToPrefetch.forEach(function(url) {");
      lines.push("  toolbox.router.any(url, toolbox.cacheFirst);");
      lines.push("});");
      lines.push("toolbox.precache(urlsToPrefetch);");
      setupRoutes(cacheFirstURLs, 'toolbox.cacheFirst', lines);
      setupRoutes(cacheOnlyURLs, 'toolbox.cacheOnly', lines);
      setupRoutes(fastestURLs, 'toolbox.fastest', lines);
      setupRoutes(networkFirstURLs, 'toolbox.networkFirst', lines);

      if (fallback.length) {
        fallback.forEach(function(fallback, idx, array) {
          var fallbackParts = fallback.split(' ');
          if (fallbackParts.length > 1) {
            var fallbackOptions = "{fallbackURL:'"+fallbackParts[1]+"'}";
            lines.push("toolbox.router.any('"+fallbackParts[0]+"',fallbackResponse, "+fallbackOptions+");");
          }
        });
      }
      if (swIncludeFiles && swIncludeFiles.length) {
        lines = lines.concat(swIncludeFiles.map(function(file) {
          return fs.readFileSync(file)
        }).join(';\n'));
      }
      if (swIncludeDir) {
        getFilesRecursively(swIncludeDir, [ "**/*" ]).forEach(function (file) {
          var srcFile = path.join(swIncludeDir, file);
          lines.push(fs.readFileSync(srcFile));
        });
      }
      if (skipWaiting || debug) {
        lines.push("self.addEventListener('install', function(event) {");
         addDebugLine("'Handling install event. Resources to pre-fetch:', urlsToPrefetch", debug, lines);
        if (skipWaiting) {
          lines.push("  if (self.skipWaiting) { self.skipWaiting(); }");
        }
        lines.push("});");
      }

      lines.push(getFileContents('delete-old-caches.js'));
      if (fallback.length) {
        lines.push(getFileContents('fallback-response.js'));
      }

      lines.push(getFileContents('log-debug.js'));
      fs.writeFileSync(path.join(destDir, serviceWorkerFile), lines.join("\n"));
      fs.writeFileSync(path.join(destDir, toolboxLocation), fs.readFileSync(swToolboxFile));
      if (debug) {
        fs.writeFileSync(path.join(destDir, 'sw-toolbox.map.json'), fs.readFileSync(swToolboxMapFile));
      }
    });
  });
};

BroccoliServiceWorker.prototype.addExternalFile = function(file) {
  this.externalFiles.push(file);
};

function addDebugLine(consoleText, debug, lines) {
  if (debug) {
    lines.push("console.log("+consoleText+");");
  }
}

function createArrayLine(line, idx, arrayLength) {
  var arrayLine = line;
  if ((idx+1) < arrayLength) {
    arrayLine += ",";
  }
  return arrayLine;
}

function getFilesRecursively(dir, globPatterns) {
  try {
    return helpers.multiGlob(globPatterns, { cwd: dir }).filter(function(file){
      var srcFile = path.join(dir, file);
      var stat = fs.lstatSync(srcFile);
      return (stat.isFile()  || stat.isSymbolicLink());
    });
  } catch (ex) {
    return [];
  }
}

function getFileContents(fileName) {
  var filePath = [ __dirname, fileName].join('/');
  return fs.readFileSync(filePath);
}

function printPath(path) {
  if (path instanceof RegExp) {
    return path.toString();
  } else {
    return JSON.stringify(path);
  }
}

function setupRoutes(routeUrls, handler, lines) {
  if (routeUrls.length) {
    routeUrls.forEach(function(cacheURL, idx, array) {
      var method = 'any';
      var options;

      if (typeof cacheURL === 'object' && (cacheURL instanceof RegExp === false)) {
        options = JSON.stringify(cacheURL.options);
        if (cacheURL.method) {
          method = cacheURL.method;
        }
        cacheURL = cacheURL.route;
      }
      var line = 'toolbox.router.'+method+'('+printPath(cacheURL)+',' + handler;

      if (options) {
        line += ', ';
        line += options;
      }

      line += ');';

      lines.push(line);
    });
  }
}

function readSwIncludeTree(readTree, swIncludeTree) {
  if (swIncludeTree) {
    return readTree(swIncludeTree);
  } else {
    return rsvp.resolve();
  }
}

module.exports = BroccoliServiceWorker;
<|endoftext|>


<commit_before>'use strict';

var brackets = require('expand-brackets');
var extglob = require('extglob');
var braces = require('braces');
var parse = require('parse-glob');
var chars = require('./chars');

/**
 * Expose `Glob`
 */

module.exports = Glob;

function Glob(pattern, options) {
  this.options = options || {};
  this.pattern = pattern;
  this.history = [];
  this.tokens = {};
  this.init(pattern);
}

Glob.prototype.init = function(pattern) {
  this.orig = pattern;
  this.negated = this.isNegated();
  this.options.track = this.options.track || false;
  this.options.dot = this.options.dot || this.options.dotfiles;
  this.options.makeRe = true;
};

/**
 * Push a change into `glob.history`. Useful
 * for debugging.
 */

Glob.prototype.track = function(msg) {
  if (this.options.track) {
    this.history.push({msg: msg, pattern: this.pattern});
  }
};

/**
 * Return true if the glob pattern has the given
 * `ch`aracter.
 *
 * @param  {String} `pattern`
 * @param  {String} `ch`
 * @return {Boolean}
 */

Glob.prototype.has = function(pattern, ch) {
  if (ch instanceof RegExp) {
    return ch.test(pattern);
  }
  return pattern.indexOf(ch) !== -1;
};

/**
 * Return true if `glob.pattern` was negated
 * with `!`. Also removes the `!` from the pattern.
 *
 * @return {Boolean}
 */

Glob.prototype.isNegated = function() {
  if (this.pattern.charCodeAt(0) === 33 /* '!' */) {
    this.pattern = this.pattern.slice(1);
    return true;
  }
  return false;
};

/**
 * Return true if the glob pattern has braces
 *
 * @param  {String} `pattern`
 * @return {Boolean}
 */

Glob.prototype.hasBraces = function(pattern) {
  return this.has((pattern || this.pattern), '{');
};

/**
 * Expand braces in the given glob pattern.
 *
 * We only need to use the [braces] lib when
 * patterns are nested.
 */

Glob.prototype.braces = function() {
  if (this.hasBraces() && this.options.nobraces !== true) {
    var a = this.pattern.match(/[\{\(\[]/g);
    var b = this.pattern.match(/[\}\)\]]/g);
    if (a && b && (a.length !== b.length)) {
      this.options.makeRe = false;
    }
    var expanded = braces(this.pattern, this.options);
    this.pattern = expanded.join('|');
  }
};

/**
 * Return true if the glob pattern has a POSIX
 * bracket expression (character class)
 *
 * @param  {String} `pattern`
 * @return {Boolean}
 */

Glob.prototype.hasBrackets = function(pattern) {
  return this.has((pattern || this.pattern), '[:');
};

/**
 * Expand bracket expressions in `glob.pattern`
 */

Glob.prototype.brackets = function() {
  if (this.hasBrackets() && this.options.nobrackets !== true) {
    this.pattern = brackets(this.pattern);
  }
};

/**
 * Return true if the glob pattern has an extglob
 * pattern.
 *
 * @param  {String} `pattern`
 * @return {Boolean}
 */

Glob.prototype.hasExtglob = function(pattern) {
  var re = /[@?!+*]\(/;
  return this.has((pattern || this.pattern), re);
};

/**
 * Expand extended globs in `glob.pattern`
 */

Glob.prototype.extglob = function() {
  if (this.hasExtglob() && this.options.noextglob !== true) {
    this.pattern = extglob(this.pattern);
  }
};

/**
 * Parse the given glob `pattern` or `glob.pattern`
 */

Glob.prototype.parse = function(pattern) {
  this.tokens = parse(pattern || this.pattern, true);
  return this.tokens;
};

/**
 * Replace `a` with `b`. Also tracks the change
 * before and after each replacement. This is
 * disabled by default, but can be enabled by
 * setting `options.track` to true.
 *
 * @param  {RegExp|String} `a`
 * @param  {String} `b`
 * @return {String}
 */

Glob.prototype.repl = function(a, b) {
  this.track('before repl: ');
  if (a && b && typeof a === 'string') {
    this.pattern = this.pattern.split(a).join(b);
  } else if (a instanceof RegExp) {
    try {
      this.pattern = this.pattern.replace(a, b);
    } catch(err) {}
  }
  this.track('after repl: ');
};

/**
 * Escape special characters in the given string.
 *
 * @param  {String} `str` Glob pattern
 * @return {String}
 */

Glob.prototype.escape = function(str) {
  this.track('before escape: ');

  var re = /["\\](['"]?[^"'\\]['"]?)/g;
  this.pattern = str.replace(re, function($0, $1) {
    var o = chars.ESC;
    var ch = o && o[$1];
    if (ch) {
      return ch;
    }
    if (/[a-z]/i.test($0)) {
      return $0.split('\\').join('');
    }
    return $0;
  });

  this.track('after escape: ');
};

/**
 * Unescape special characters in the given string.
 *
 * @param  {String} `str`
 * @return {String}
 */

Glob.prototype.unescape = function(str) {
  var re = /__([A-Z]+)_([A-Z]+)__/g;
  this.pattern = str.replace(re, function($0, $1) {
    return chars[$1][$0];
  });
};
<commit_msg>clean up, remove extglob for now<commit_after>'use strict';

var brackets = require('expand-brackets');
var braces = require('braces');
var parse = require('parse-glob');
var chars = require('./chars');

/**
 * Expose `Glob`
 */

module.exports = Glob;

function Glob(pattern, options) {
  this.options = options || {};
  this.pattern = pattern;
  this.history = [];
  this.tokens = {};
  this.init(pattern);
}

/**
 * Initialize defaults
 */

Glob.prototype.init = function(pattern) {
  this.orig = pattern;
  this.negated = this.isNegated();
  this.options.track = this.options.track || false;
  this.options.dot = this.options.dot || this.options.dotfiles;
  this.options.makeRe = true;
};

/**
 * Push a change into `glob.history`. Useful
 * for debugging.
 */

Glob.prototype.track = function(msg) {
  if (this.options.track) {
    this.history.push({msg: msg, pattern: this.pattern});
  }
};

/**
 * Return true if the glob pattern has the given
 * `ch`aracter.
 *
 * @param  {String} `pattern`
 * @param  {String} `ch`
 * @return {Boolean}
 */

Glob.prototype.has = function(pattern, ch) {
  if (ch instanceof RegExp) {
    return ch.test(pattern);
  }
  return pattern.indexOf(ch) !== -1;
};

/**
 * Return true if `glob.pattern` was negated
 * with `!`. Also removes the `!` from the pattern.
 *
 * @return {Boolean}
 */

Glob.prototype.isNegated = function() {
  if (this.pattern.charCodeAt(0) === 33 /* '!' */) {
    this.pattern = this.pattern.slice(1);
    return true;
  }
  return false;
};

/**
 * Return true if the glob pattern has braces
 *
 * @param  {String} `pattern`
 * @return {Boolean}
 */

Glob.prototype.hasBraces = function(pattern) {
  return this.has((pattern || this.pattern), '{');
};

/**
 * Expand braces in the given glob pattern.
 *
 * We only need to use the [braces] lib when
 * patterns are nested.
 */

Glob.prototype.braces = function() {
  if (this.hasBraces() && this.options.nobraces !== true) {
    var a = this.pattern.match(/[\{\(\[]/g);
    var b = this.pattern.match(/[\}\)\]]/g);
    if (a && b && (a.length !== b.length)) {
      this.options.makeRe = false;
    }
    var expanded = braces(this.pattern, this.options);
    this.pattern = expanded.join('|');
  }
};

/**
 * Return true if the glob pattern has a POSIX
 * bracket expression (character class)
 *
 * @param  {String} `pattern`
 * @return {Boolean}
 */

Glob.prototype.hasBrackets = function(pattern) {
  return this.has((pattern || this.pattern), '[:');
};

/**
 * Expand bracket expressions in `glob.pattern`
 */

Glob.prototype.brackets = function() {
  if (this.hasBrackets() && this.options.nobrackets !== true) {
    this.pattern = brackets(this.pattern);
  }
};

/**
 * Parse the given glob `pattern` or `glob.pattern`
 */

Glob.prototype.parse = function(pattern, options) {
  this.tokens = parse(pattern || this.pattern, true);
  return this.tokens;
};

/**
 * Replace `a` with `b`. Also tracks the change
 * before and after each replacement. This is
 * disabled by default, but can be enabled by
 * setting `options.track` to true.
 *
 * @param  {RegExp|String} `a`
 * @param  {String} `b`
 * @return {String}
 */

Glob.prototype.repl = function(a, b, c) {
  if (c) {
    this.track('before ' + c);
  } else {
    this.track('before');
  }
  if (a && b && typeof a === 'string') {
    this.pattern = this.pattern.split(a).join(b);
  } else if (a instanceof RegExp) {
    try {
      this.pattern = this.pattern.replace(a, b);
    } catch(err) {}
  }
  if (c) {
    this.track('after ' + c);
  } else {
    this.track('after');
  }
};

/**
 * Escape special characters in the given string.
 *
 * @param  {String} `str` Glob pattern
 * @return {String}
 */

Glob.prototype.escape = function(str) {
  this.track('before escape: ');

  var re = /["\\](['"]?[^"'\\]['"]?)/g;
  this.pattern = str.replace(re, function($0, $1) {
    var o = chars.ESC;
    var ch = o && o[$1];
    if (ch) {
      return ch;
    }
    if (/[a-z]/i.test($0)) {
      return $0.split('\\').join('');
    }
    return $0;
  });

  this.track('after escape: ');
};

/**
 * Unescape special characters in the given string.
 *
 * @param  {String} `str`
 * @return {String}
 */

Glob.prototype.unescape = function(str) {
  var re = /__([A-Z]+)_([A-Z]+)__/g;
  this.pattern = str.replace(re, function($0, $1) {
    return chars[$1][$0];
  });
};
<|endoftext|>


<commit_before>var BIP39 = require('bip39')

/**
 * @class PaymentModel
 *
 * @param {AssetModel} assetModel
 */
function PaymentModel(assetModel) {
  this.assetModel = assetModel

  this.readOnly = false
  this.recipients = []
  this.seed = null
}

/**
 * @param {string} address
 * @return {boolean}
 */
PaymentModel.prototype.checkAddress = function(address) {
  var assetdef = this.assetModel.assetdef
  var isValid = this.assetModel.wallet.checkAddress(assetdef, address)
  return isValid
}

/**
 * @param {string} amount
 * @return {boolean}
 */
PaymentModel.prototype.checkAmount = function(amount) {
  var assetdef = this.assetModel.assetdef

  var amountAvailable = assetdef.parseValue(this.assetModel.getAvailableBalance())
  var amountNeeded = assetdef.parseValue(amount)

  return amountAvailable >= amountNeeded
}

/**
 * @param {string} address Color addres or bitcoin address ?
 * @param {string} amount
 * @return {PaymentModel}
 * @throws {Error} If payment already sent
 */
PaymentModel.prototype.addRecipient = function(address, amount) {
  if (this.readOnly)
    throw new Error('payment has already been comitted')

  this.recipients.push({ address: address, amount: amount })

  return this
}

/**
 * @param {string} mnemonic
 * @param {string} password
 * @return {boolean}
 */
PaymentModel.prototype.checkMnemonic = function(mnemonic, password) {
  var seed = BIP39.mnemonicToSeedHex(mnemonic, password)
  return this.assetModel.wallet.isCurrentSeed(seed)
}

/**
 * @param {string} mnemonic
 * @param {string} password
 * @return {PaymentModel}
 * @throws {Error} If payment already sent
 */
PaymentModel.prototype.setMnemonic = function(mnemonic, password) {
  if (this.readOnly)
    throw new Error('payment has already been comitted')

  this.seed = BIP39.mnemonicToSeedHex(mnemonic, password)

  return this
}

/**
 * @callback PaymentModel~send
 * @param {?Error} error
 */

/**
 * @param {PaymentModel~send} cb
 * @return {PaymentModel}
 * @throws {Error} If payment already sent, recipients list not filled or mnemonic not set
 */
PaymentModel.prototype.send = function(cb) {
  if (this.readOnly)
    throw new Error('Payment has already been comitted')

  if (this.recipients.length === 0)
    throw new Error('Recipients list is empty')

  if (this.seed === null)
    throw new Error('Mnemonic not set')

  var assetdef = this.assetModel.assetdef

  var rawTargets = this.recipients.map(function(recipient) {
    return {
      address: this.assetModel.wallet.getBitcoinAddress(assetdef, recipient.address),
      value: assetdef.parseValue(recipient.amount)
    }
  }.bind(this))

  this.readOnly = true

  this.assetModel.wallet.sendCoins(this.seed, this.assetModel.assetdef, rawTargets, cb)

  return this
}

/**
 * @return {string}
 */
PaymentModel.prototype.getStatus = function() {
  var status = this.readOnly ? 'sent' : 'fresh'
  return status
}

module.exports = PaymentModel
<commit_msg>improved payment model callbacks<commit_after>var BIP39 = require('bip39')

/**
 * @class PaymentModel
 *
 * @param {AssetModel} assetModel
 */
function PaymentModel(assetModel) {
  this.assetModel = assetModel

  this.readOnly = false;
  this.status = null;
  this.recipients = []
  this.seed = null
}

/**
 * @param {string} address
 * @return {boolean}
 */
PaymentModel.prototype.checkAddress = function(address) {
  var assetdef = this.assetModel.assetdef
  var isValid = this.assetModel.wallet.checkAddress(assetdef, address)
  return isValid
}

/**
 * @param {string} amount
 * @return {boolean}
 */
PaymentModel.prototype.checkAmount = function(amount) {
  var assetdef = this.assetModel.assetdef

  var amountAvailable = assetdef.parseValue(this.assetModel.getAvailableBalance())
  var amountNeeded = assetdef.parseValue(amount)

  return amountAvailable >= amountNeeded
}

/**
 * @param {string} address Color addres or bitcoin address ?
 * @param {string} amount
 * @return {PaymentModel}
 * @throws {Error} If payment already sent
 */
PaymentModel.prototype.addRecipient = function(address, amount) {
  if (this.readOnly)
    throw new Error('payment has already been comitted')

  this.recipients.push({ address: address, amount: amount })

  return this
}

/**
 * @param {string} mnemonic
 * @param {string} password
 * @return {boolean}
 */
PaymentModel.prototype.checkMnemonic = function(mnemonic, password) {
  var seed = BIP39.mnemonicToSeedHex(mnemonic, password)
  return this.assetModel.wallet.isCurrentSeed(seed)
}

/**
 * @param {string} mnemonic
 * @param {string} password
 * @return {PaymentModel}
 * @throws {Error} If payment already sent
 */
PaymentModel.prototype.setMnemonic = function(mnemonic, password) {
  if (this.readOnly)
    throw new Error('payment has already been comitted')

  this.seed = BIP39.mnemonicToSeedHex(mnemonic, password)

  return this
}

/**
 * @callback PaymentModel~send
 * @param {?Error} error
 */

/**
 * @param {PaymentModel~send} cb
 * @return {PaymentModel}
 * @throws {Error} If payment already sent, recipients list not filled or mnemonic not set
 */
PaymentModel.prototype.send = function(cb) {
  var self = this;
  if (this.readOnly)
    throw new Error('Payment has already been comitted')

  if (this.recipients.length === 0)
    throw new Error('Recipients list is empty')

  if (this.seed === null)
    throw new Error('Mnemonic not set')

  var assetdef = this.assetModel.assetdef

  var rawTargets = this.recipients.map(function(recipient) {
    return {
      address: this.assetModel.wallet.getBitcoinAddress(assetdef, recipient.address),
      value: assetdef.parseValue(recipient.amount)
    }
  }.bind(this))

  this.readOnly = true;
  this.status = 'sending';

  function sendCoinsCallback(err, txid) {
      if (err) {
          console.log(err);
          self.status = 'failed';
      } else self.status = 'sent';
      self.assetModel.update();
      cb(err, txid);
  }

  this.assetModel.wallet.sendCoins(
      this.seed, this.assetModel.assetdef, rawTargets,
      sendCoinsCallback);

  return this
}

// 'fresh', 'sending', 'sent', 'failed'

/**
 * @return {string}
 */
PaymentModel.prototype.getStatus = function() {
    if (!this.readOnly) return 'fresh';
    else return this.status;
}

module.exports = PaymentModel
<|endoftext|>


<commit_before>'use strict';

/* Services */

velocityApp.factory('Account', ['$resource',
    function ($resource) {
        return $resource('app/rest/account', {}, {
        });
    }]);

velocityApp.factory('Password', ['$resource',
    function ($resource) {
        return $resource('app/rest/account/change_password', {}, {
        });
    }]);

velocityApp.factory('Sessions', ['$resource',
    function ($resource) {
        return $resource('app/rest/account/sessions/:series', {}, {
            'get': { method: 'GET', isArray: true}
        });
    }]);

velocityApp.factory('MetricsService', ['$resource',
    function ($resource) {
        return $resource('metrics/metrics', {}, {
            'get': { method: 'GET'}
        });
    }]);

velocityApp.factory('ThreadDumpService', ['$http',
    function ($http) {
        return {
            dump: function() {
                var promise = $http.get('dump').then(function(response){
                    return response.data;
                });
                return promise;
            }
        };
    }]);

velocityApp.factory('HealthCheckService', ['$rootScope', '$http',
    function ($rootScope, $http) {
        return {
            check: function() {
                var promise = $http.get('health').then(function(response){
                    return response.data;
                });
                return promise;
            }
        };
    }]);

velocityApp.factory('LogsService', ['$resource',
    function ($resource) {
        return $resource('app/rest/logs', {}, {
            'findAll': { method: 'GET', isArray: true},
            'changeLevel':  { method: 'PUT'}
        });
    }]);

velocityApp.factory('AuditsService', ['$http',
    function ($http) {
        return {
            findAll: function() {
                var promise = $http.get('app/rest/audits/all').then(function (response) {
                    return response.data;
                });
                return promise;
            },
            findByDates: function(fromDate, toDate) {
                var promise = $http.get('app/rest/audits/byDates', {params: {fromDate: fromDate, toDate: toDate}}).then(function (response) {
                    return response.data;
                });
                return promise;
            }
        }
    }]);

velocityApp.factory('Session', [
    function () {
        this.create = function (login, firstName, lastName, email, userRoles) {
            this.login = login;
            this.firstName = firstName;
            this.lastName = lastName;
            this.email = email;
            this.userRoles = userRoles;
        };
        this.invalidate = function () {
            this.login = null;
            this.firstName = null;
            this.lastName = null;
            this.email = null;
            this.roles = null;
        };
        return this;
    }]);

velocityApp.constant('USER_ROLES', {
        all: '*',
        admin: 'ROLE_ADMIN',
        user: 'ROLE_USER'
    });

velocityApp.factory('AuthenticationSharedService', ['$rootScope', '$http', 'authService', 'Session', 'Account', 'Base64Service', 'AccessToken',
    function ($rootScope, $http, authService, Session, Account, Base64Service, AccessToken) {
        return {
            login: function (param) {
                var data = "username=" + param.username + "&password=" + param.password + "&grant_type=password&scope=read%20write&client_secret=mySecretOAuthSecret&client_id=velocityapp";
                $http.post('oauth/token', data, {
                    headers: {
                        "Content-Type": "application/x-www-form-urlencoded",
                        "Accept": "application/json",
                        "Authorization": "Basic " + Base64Service.encode("velocityapp" + ':' + "mySecretOAuthSecret")
                    },
                    ignoreAuthModule: 'ignoreAuthModule'
                }).success(function (data, status, headers, config) {
                    httpHeaders.common['Authorization'] = 'Bearer ' + data.access_token;
                    AccessToken.set(data);

                    Account.get(function(data) {
                        Session.create(data.login, data.firstName, data.lastName, data.email, data.roles);
                        $rootScope.account = Session;
                        authService.loginConfirmed(data);
                    });
                }).error(function (data, status, headers, config) {
                    $rootScope.authenticationError = true;
                    Session.invalidate();
                });
            },
            valid: function (authorizedRoles) {
                httpHeaders.common['Authorization'] = 'Bearer ' + AccessToken.get();

                $http.get('protected/transparent.gif', {
                    ignoreAuthModule: 'ignoreAuthModule'
                }).success(function (data, status, headers, config) {
                    if (!Session.login || AccessToken.get() != undefined) {
                        if (AccessToken.get() == undefined || AccessToken.expired()) {
                            $rootScope.authenticated = false
                            return;
                        }
                        Account.get(function(data) {
                            Session.create(data.login, data.firstName, data.lastName, data.email, data.roles);
                            $rootScope.account = Session;

                            if (!$rootScope.isAuthorized(authorizedRoles)) {
                                event.preventDefault();
                                // user is not allowed
                                $rootScope.$broadcast("event:auth-notAuthorized");
                            }

                            $rootScope.authenticated = true;
                        });
                    }
                    $rootScope.authenticated = !!Session.login;
                }).error(function (data, status, headers, config) {
                    $rootScope.authenticated = false;
                });
            },
            isAuthorized: function (authorizedRoles) {
                if (!angular.isArray(authorizedRoles)) {
                    if (authorizedRoles == '*') {
                        return true;
                    }

                    authorizedRoles = [authorizedRoles];
                }

                var isAuthorized = false;
                angular.forEach(authorizedRoles, function(authorizedRole) {
                    var authorized = (!!Session.login &&
                        Session.userRoles.indexOf(authorizedRole) !== -1);

                    if (authorized || authorizedRole == '*') {
                        isAuthorized = true;
                    }
                });

                return isAuthorized;
            },
            logout: function () {
                $rootScope.authenticationError = false;
                $rootScope.authenticated = false;
                $rootScope.account = null;
                AccessToken.remove();

                $http.get('app/logout');
                Session.invalidate();
                httpHeaders.common['Authorization'] = null;
                authService.loginCancelled();
            }
        };
    }]);<commit_msg>typo fix<commit_after>'use strict';

/* Services */

velocityApp.factory('Account', ['$resource',
    function ($resource) {
        return $resource('app/rest/account', {}, {
        });
    }]);

velocityApp.factory('Password', ['$resource',
    function ($resource) {
        return $resource('app/rest/account/change_password', {}, {
        });
    }]);

velocityApp.factory('Sessions', ['$resource',
    function ($resource) {
        return $resource('app/rest/account/sessions/:series', {}, {
            'get': { method: 'GET', isArray: true}
        });
    }]);

velocityApp.factory('MetricsService', ['$resource',
    function ($resource) {
        return $resource('metrics/metrics', {}, {
            'get': { method: 'GET'}
        });
    }]);

velocityApp.factory('ThreadDumpService', ['$http',
    function ($http) {
        return {
            dump: function() {
                var promise = $http.get('dump').then(function(response){
                    return response.data;
                });
                return promise;
            }
        };
    }]);

velocityApp.factory('HealthCheckService', ['$rootScope', '$http',
    function ($rootScope, $http) {
        return {
            check: function() {
                var promise = $http.get('health').then(function(response){
                    return response.data;
                });
                return promise;
            }
        };
    }]);

velocityApp.factory('LogsService', ['$resource',
    function ($resource) {
        return $resource('app/rest/logs', {}, {
            'findAll': { method: 'GET', isArray: true},
            'changeLevel':  { method: 'PUT'}
        });
    }]);

velocityApp.factory('AuditsService', ['$http',
    function ($http) {
        return {
            findAll: function() {
                var promise = $http.get('app/rest/audits/all').then(function (response) {
                    return response.data;
                });
                return promise;
            },
            findByDates: function(fromDate, toDate) {
                var promise = $http.get('app/rest/audits/byDates', {params: {fromDate: fromDate, toDate: toDate}}).then(function (response) {
                    return response.data;
                });
                return promise;
            }
        }
    }]);

velocityApp.factory('Session', [
    function () {
        this.create = function (login, firstName, lastName, email, userRoles) {
            this.login = login;
            this.firstName = firstName;
            this.lastName = lastName;
            this.email = email;
            this.userRoles = userRoles;
        };
        this.invalidate = function () {
            this.login = null;
            this.firstName = null;
            this.lastName = null;
            this.email = null;
            this.userRoles = null;
        };
        return this;
    }]);

velocityApp.constant('USER_ROLES', {
        all: '*',
        admin: 'ROLE_ADMIN',
        user: 'ROLE_USER'
    });

velocityApp.factory('AuthenticationSharedService', ['$rootScope', '$http', 'authService', 'Session', 'Account', 'Base64Service', 'AccessToken',
    function ($rootScope, $http, authService, Session, Account, Base64Service, AccessToken) {
        return {
            login: function (param) {
                var data = "username=" + param.username + "&password=" + param.password + "&grant_type=password&scope=read%20write&client_secret=mySecretOAuthSecret&client_id=velocityapp";
                $http.post('oauth/token', data, {
                    headers: {
                        "Content-Type": "application/x-www-form-urlencoded",
                        "Accept": "application/json",
                        "Authorization": "Basic " + Base64Service.encode("velocityapp" + ':' + "mySecretOAuthSecret")
                    },
                    ignoreAuthModule: 'ignoreAuthModule'
                }).success(function (data, status, headers, config) {
                    httpHeaders.common['Authorization'] = 'Bearer ' + data.access_token;
                    AccessToken.set(data);

                    Account.get(function(data) {
                        Session.create(data.login, data.firstName, data.lastName, data.email, data.roles);
                        $rootScope.account = Session;
                        authService.loginConfirmed(data);
                    });
                }).error(function (data, status, headers, config) {
                    $rootScope.authenticationError = true;
                    Session.invalidate();
                });
            },
            valid: function (authorizedRoles) {
                httpHeaders.common['Authorization'] = 'Bearer ' + AccessToken.get();

                $http.get('protected/transparent.gif', {
                    ignoreAuthModule: 'ignoreAuthModule'
                }).success(function (data, status, headers, config) {
                    if (!Session.login || AccessToken.get() != undefined) {
                        if (AccessToken.get() == undefined || AccessToken.expired()) {
                            $rootScope.authenticated = false
                            return;
                        }
                        Account.get(function(data) {
                            Session.create(data.login, data.firstName, data.lastName, data.email, data.roles);
                            $rootScope.account = Session;

                            if (!$rootScope.isAuthorized(authorizedRoles)) {
                                event.preventDefault();
                                // user is not allowed
                                $rootScope.$broadcast("event:auth-notAuthorized");
                            }

                            $rootScope.authenticated = true;
                        });
                    }
                    $rootScope.authenticated = !!Session.login;
                }).error(function (data, status, headers, config) {
                    $rootScope.authenticated = false;
                });
            },
            isAuthorized: function (authorizedRoles) {
                if (!angular.isArray(authorizedRoles)) {
                    if (authorizedRoles == '*') {
                        return true;
                    }

                    authorizedRoles = [authorizedRoles];
                }

                var isAuthorized = false;
                angular.forEach(authorizedRoles, function(authorizedRole) {
                    var authorized = (!!Session.login &&
                        Session.userRoles.indexOf(authorizedRole) !== -1);

                    if (authorized || authorizedRole == '*') {
                        isAuthorized = true;
                    }
                });

                return isAuthorized;
            },
            logout: function () {
                $rootScope.authenticationError = false;
                $rootScope.authenticated = false;
                $rootScope.account = null;
                AccessToken.remove();

                $http.get('app/logout');
                Session.invalidate();
                httpHeaders.common['Authorization'] = null;
                authService.loginCancelled();
            }
        };
    }]);<|endoftext|>