<commit_before>/* eslint-disable react/forbid-prop-types */
/* eslint-disable import/prefer-default-export */
/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import React from 'react';
import { View, TouchableWithoutFeedback } from 'react-native';
import PropTypes from 'prop-types';

/**
 * TouchableWithoutFeedback doesn't have a style prop. View doesn't have an onPress
 * Prop. This hack ensures events don't propogate to the parent, styling stays consistent
 * and no feedback (i.e. gesture echo) is given to the user.
 */
const onPressNoOp = () => {};

const TouchableNoFeedback = ({ children, style, ...touchableProps }) => (
  <TouchableWithoutFeedback onPress={onPressNoOp} {...touchableProps}>
    <View style={style}>{children}</View>
  </TouchableWithoutFeedback>
);

TouchableNoFeedback.defaultProps = {
  style: null,
};

TouchableNoFeedback.propTypes = {
  children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
  style: PropTypes.object,
};

export default TouchableNoFeedback;
<commit_msg>Add correct props assignment<commit_after>/* eslint-disable react/forbid-prop-types */
/* eslint-disable import/prefer-default-export */
/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import React from 'react';
import { View, TouchableWithoutFeedback } from 'react-native';
import PropTypes from 'prop-types';

/**
 * TouchableWithoutFeedback doesn't have a style prop. View doesn't have an onPress
 * Prop. This hack ensures events don't propogate to the parent, styling stays consistent
 * and no feedback (i.e. gesture echo) is given to the user.
 */
const onPressNoOp = () => {};

const TouchableNoFeedback = ({ children, style, ...touchableProps }) => (
  <TouchableWithoutFeedback {...touchableProps} onPress={onPressNoOp}>
    <View style={style}>{children}</View>
  </TouchableWithoutFeedback>
);

TouchableNoFeedback.defaultProps = {
  style: null,
};

TouchableNoFeedback.propTypes = {
  children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
  style: PropTypes.object,
};

export default TouchableNoFeedback;
<|endoftext|>


<commit_before>//
// Vanilla javascript version of the example forground layer.
// Delete main.coffee to use vanilla JavaScript
// Or delete this file to use CoffeeScript
//

// Inherit from Layer or LayerStack.
var Example = Lysertron.Layer.extend();

// The class that is your layer needs to be assigned to module.exports in node.js style.
module.exports = Example;

// Allows shorthand property setters to be passed as uniforms to the shaders.
//
// This:
//   this.baseColor.setRGB(1,1,1);
//
// Is now equivalent to this:
//   this.uniforms.baseColor.value.setRGB(1,1,1);
//
// And now you can simply pass @uniforms to the THREE.ShaderMaterial and access
// `baseColor` as a uniform within the shader.
Example.prototype.uniformAttrs = {
  baseColor: 'c'
};

// Setup up the layer. Called for you when the layer is created.
Example.prototype.initialize = function () {

  // Sets the value for the unirformAttr declared above.
  this.baseColor = new THREE.Color(0xffffff);

  // Make a mesh that is a simple cube.
  this.mesh = new THREE.Mesh(
    new THREE.CubeGeometry(10, 10, 10),

    // Shaders are awesome. Use em!
    new THREE.ShaderMaterial({

      // @uniforms is provided by uniformAttrs above.
      uniforms: this.uniforms,

      // Load shaders from the magic `assets` object.
      vertexShader:   assets['vert.glsl'],
      fragmentShader: assets['frag.glsl']
    })
  );

  // Add the cube mesh to the layer.
  this.add(this.mesh);
};

// Called per frame, update the objects in the layer however you want.
// `elapsed` is the time in seconds since the last frame.
Example.prototype.update = function (elapsed) {

  // In this case, spin the cube on each axis at 1 radian per second.
  this.mesh.rotation.x += elapsed;
  this.mesh.rotation.y += elapsed;
  this.mesh.rotation.z += elapsed;
};

// Called on every beat of the song.  Use it to change state to show it
// reacting to the beat.
Example.prototype.onBeat = function (beat) {
  return this.baseColor.setRGB(Math.random(), Math.random(), Math.random());
};

// Called for each discernable note. Inspect the argment for details about the note.
Example.prototype.onSegment = function(segment) { };

// Called at the start of every bar. Typically 4 beats in a 4/4 time signature.
Example.prototype.onBar = function(bar) { };

// Called on each tatum. Tatums represent the lowest regular pulse train that a
// listener intuitively infers from the timing of perceived musical events (segments).
Example.prototype.onTatum = function(tatum) { };

// Called when the scene transitions and the layer should begin to die.  If you
// override this, make sure to call `super`!
Example.prototype.kill = function() { };

// Called every frame after the layer has been killed. For as long as this method
// returns `true` the layer will still be rendered. Make it return false when it's
// death animation is completed.
Example.prototype.alive = function() { };
<commit_msg>Commented out some stubs in JS example<commit_after>//
// Vanilla javascript version of the example forground layer.
// Delete main.coffee to use vanilla JavaScript
// Or delete this file to use CoffeeScript
//

// Inherit from Layer or LayerStack.
var Example = Lysertron.Layer.extend();

// The class that is your layer needs to be assigned to module.exports in node.js style.
module.exports = Example;

// Allows shorthand property setters to be passed as uniforms to the shaders.
//
// This:
//   this.baseColor.setRGB(1,1,1);
//
// Is now equivalent to this:
//   this.uniforms.baseColor.value.setRGB(1,1,1);
//
// And now you can simply pass @uniforms to the THREE.ShaderMaterial and access
// `baseColor` as a uniform within the shader.
Example.prototype.uniformAttrs = {
  baseColor: 'c'
};

// Setup up the layer. Called for you when the layer is created.
Example.prototype.initialize = function () {

  // Sets the value for the unirformAttr declared above.
  this.baseColor = new THREE.Color(0xffffff);

  // Make a mesh that is a simple cube.
  this.mesh = new THREE.Mesh(
    new THREE.CubeGeometry(10, 10, 10),

    // Shaders are awesome. Use em!
    new THREE.ShaderMaterial({

      // @uniforms is provided by uniformAttrs above.
      uniforms: this.uniforms,

      // Load shaders from the magic `assets` object.
      vertexShader:   assets['vert.glsl'],
      fragmentShader: assets['frag.glsl']
    })
  );

  // Add the cube mesh to the layer.
  this.add(this.mesh);
};

// Called per frame, update the objects in the layer however you want.
// `elapsed` is the time in seconds since the last frame.
Example.prototype.update = function (elapsed) {

  // In this case, spin the cube on each axis at 1 radian per second.
  this.mesh.rotation.x += elapsed;
  this.mesh.rotation.y += elapsed;
  this.mesh.rotation.z += elapsed;
};

// Called on every beat of the song.  Use it to change state to show it
// reacting to the beat.
Example.prototype.onBeat = function (beat) {
  return this.baseColor.setRGB(Math.random(), Math.random(), Math.random());
};

// // Called for each discernable note. Inspect the argment for details about the note.
// Example.prototype.onSegment = function(segment) { };

// // Called at the start of every bar. Typically 4 beats in a 4/4 time signature.
// Example.prototype.onBar = function(bar) { };

// // Called on each tatum. Tatums represent the lowest regular pulse train that a
// // listener intuitively infers from the timing of perceived musical events (segments).
// Example.prototype.onTatum = function(tatum) { };

// // Called when the scene transitions and the layer should begin to die.  If you
// // override this, make sure to call `super`!
// Example.prototype.kill = function() {
//   Lysertron.Layer.prototype.kill.apply(this);
// };

// // Called every frame after the layer has been killed. For as long as this method
// // returns `true` the layer will still be rendered. Make it return false when it's
// // death animation is completed.
// Example.prototype.alive = function() { };
<|endoftext|>


<commit_before>module.exports = {

    VERSION: "Default JavaScript folding player",

    bet_request: function (game_state, bet) {
        this.getPairs(game_state);
        return this.strategy1(game_state, bet);
    },

    showdown: function (game_state) {

    },

    isHigh: function (card) {
        return ['J', 'Q', 'K', 'A'].indexOf(card) == -1 ? false : true;
    },

    strategy1: function(game_state, bet) {
        var current_bet = bet;
        var our_cards = [];

        for (var p in game_state.players) {
            if (typeof game_state.players[p]['hole_cards'] != 'undefined') {
                our_cards = game_state.players[p]['hole_cards'];
            }
        }
        console.log('OUR CARDS');
        console.log(our_cards);

        console.log('COMMUNITY CARDS');
        console.log(game_state);

        if (our_cards[0]['rank'] == our_cards[1]['rank']) {
            console.log('HAS PAIR!');
            current_bet += 300;
        }

        return bet(current_bet);
    },

    getPairs: function(game_state) {
        var cards = [];
        var community_cards = game_state.community_cards;

        for (var p in game_state.players) {
            if (typeof game_state.players[p]['hole_cards'] != 'undefined') {
                cards = game_state.players[p]['hole_cards'];
            }
        }

        cards.concat(community_cards);

        console.log("PAIRS");
        console.log(cards);
        console.log(game_state.community_cards);

    }
};

<commit_msg>game state<commit_after>module.exports = {

    VERSION: "Default JavaScript folding player",

    bet_request: function (game_state, bet) {
        console.log(this.strategy1(game_state, bet));
        //this.getPairs(game_state);
        return this.strategy1(game_state, bet);
    },

    showdown: function (game_state) {

    },

    isHigh: function (card) {
        return ['J', 'Q', 'K', 'A'].indexOf(card) == -1 ? false : true;
    },

    strategy1: function(game_state, bet) {
        var current_bet = bet;
        var our_cards = [];

        for (var p in game_state.players) {
            if (typeof game_state.players[p]['hole_cards'] != 'undefined') {
                our_cards = game_state.players[p]['hole_cards'];
            }
        }
        console.log('OUR CARDS');
        console.log(our_cards);

        console.log('COMMUNITY CARDS');
        console.log(game_state);

        if (our_cards[0]['rank'] == our_cards[1]['rank']) {
            console.log('HAS PAIR!');
            current_bet += 300;
        }

        return bet(current_bet);
    },

    getPairs: function(game_state) {
        var cards = [];
        var community_cards = game_state.community_cards;

        for (var p in game_state.players) {
            if (typeof game_state.players[p]['hole_cards'] != 'undefined') {
                cards = game_state.players[p]['hole_cards'];
            }
        }

        cards.concat(community_cards);

        console.log("PAIRS");
        console.log(cards);
        console.log(game_state.community_cards);

    }
};

<|endoftext|>


<commit_before>(function( $, undefined ) {
    $.KBWidget({
        name: "KBaseBambiRunResultCard",
        parent: "kbaseWidget",
        version: "1.0.0",

        options: {
            bambi_run_result_id: null,
            workspace_id: null,
            loadingImage: "assets/img/ajax-loader.gif",
            title: "BAMBI Run Result Overview",
            isInCard: false,
            width: 450
        },

//        workspaceURL: "https://kbase.us/services/workspace",
        newWorkspaceServiceUrl: "http://140.221.84.209:7058/",

        init: function(options) {
            this._super(options);
            if (this.options.bambi_run_result_id === null) {
                //throw an error
                return;
            }

            this.$messagePane = $("
")
                                .addClass("kbwidget-message-pane")
                                .addClass("kbwidget-hide-message");
            this.$elem.append(this.$messagePane);

//            this.workspaceClient = new workspaceService(this.workspaceURL);
            this.workspaceClient = new Workspace(this.newWorkspaceServiceUrl, { 'token' : this.options.auth, 'user_id' : this.options.userId});

            return this.render();
        },

        render: function(options) {
            this.showMessage("");

            /**
             * Fields to show:
             * ID
             * Timestamp
             * Number of motifs
             */
            var self = this;
            this.workspaceClient.get_objects([{workspace: this.options.workspace_id, name: this.options.bambi_run_result_id}],
            		    	function(data){
					self.collection = data;
					var d = new Date(parseInt(self.collection.data.timestamp));
					var creationMonth = d.getMonth()+1;
					self.$elem.append("
BAMBI Run Info
");
			        self.$elem.append($("
").
					append($("
").addClass("kbgo-table")
					    .append($("
").append("ID	" + self.collection.data.id + "	"))
					    .append($("
").append("Created: 	" + creationMonth +"/"+ d.getDate() +"/"+ d.getFullYear() +" "+ d.getHours() +":"+ d.getMinutes() +":"+ d.getSeconds() + "	"))
						.append($("
").append("Number of motifs	" + self.collection.data.motifs.length + "	"))
					));
					self.$elem.append("
View motifs
");

					var $dropdown = $("<select />");
					for (var motif in self.collection.data.motifs) {
						$dropdown.append("<option id='" + motif + "'>"+ self.collection.data.motifs[motif].description + "</option>");
					}
					self.$elem.append($dropdown);
					self.$elem.append($("<button class='btn btn-default'>Show Motif</button>")
	                	.on("click",
	                    	function(event) {
								$(self.$elem.selector + " > select option:selected").each(function() {
    //                      	console.log(event);
								self.trigger("showBambiMotif", { motif: self.collection.data.motifs[$(this).attr("id")], event: event });
	                        });
	                    })
	                );

					self.$elem.append($("").append("
<button class='btn btn-default'>Show BAMBI run parameters</button>")
	                	.on("click",
	                    	function(event) {
								self.trigger("showBambiRunParameters", { collection: self.collection, event: event });
	                    })
	                );

					self.$elem.append($("").append("
<button class='btn btn-default'>Show BAMBI raw output</button>")
	                	.on("click",
	                    	function(event) {
								self.trigger("showBambiRawOutput", { raw_output: self.collection.data.raw_output, event: event });
	                    })
	                );

                        },

			    function(data) {
                                $('.loader-table').remove();
                                self.$elem.append('
[Error] ' + data.error.message + '
');
                                return;
                            }
		    );
            this.hideMessage();
            return this;

        },

        getData: function() {
            return {
                type: "BambiRunResult",
                id: this.options.bambi_run_result_id,
                workspace: this.options.workspace_id,
                title: "BAMBI Run Result Overview"
            };
        },

        showMessage: function(message) {
            var span = $("").append(message);

            this.$messagePane.append(span);
            this.$messagePane.removeClass("kbwidget-hide-message");
        },

        hideMessage: function() {
            this.$messagePane.addClass("kbwidget-hide-message");
            this.$messagePane.empty();
        },

        rpcError: function(error) {
            console.log("An error occurred: " + error);
        }

    });
})( jQuery );
<commit_msg>fixed bug in Bambi landing page<commit_after>(function( $, undefined ) {
    $.KBWidget({
        name: "KBaseBambiRunResultCard",
        parent: "kbaseWidget",
        version: "1.0.0",

        options: {
            bambi_run_result_id: null,
            workspace_id: null,
            loadingImage: "assets/img/ajax-loader.gif",
            title: "BAMBI Run Result Overview",
            isInCard: false,
            width: 450
        },

//        workspaceURL: "https://kbase.us/services/workspace",
        newWorkspaceServiceUrl: "http://140.221.84.209:7058/",

        init: function(options) {
            this._super(options);
            if (this.options.bambi_run_result_id === null) {
                //throw an error
                return;
            }

            this.$messagePane = $("
")
                                .addClass("kbwidget-message-pane")
                                .addClass("kbwidget-hide-message");
            this.$elem.append(this.$messagePane);

//            this.workspaceClient = new workspaceService(this.workspaceURL);
            this.workspaceClient = new Workspace(this.newWorkspaceServiceUrl, { 'token' : this.options.auth, 'user_id' : this.options.userId});

            return this.render();
        },

        render: function(options) {
            this.showMessage("");

            /**
             * Fields to show:
             * ID
             * Timestamp
             * Number of motifs
             */
            var self = this;
            this.workspaceClient.get_objects([{workspace: this.options.workspace_id, name: this.options.bambi_run_result_id}],
            		    	function(data){
					self.collection = data[0];
					var d = new Date(parseInt(self.collection.data.timestamp));
					var creationMonth = d.getMonth()+1;
					self.$elem.append("
BAMBI Run Info
");
			        self.$elem.append($("
").
					append($("
").addClass("kbgo-table")
					    .append($("
").append("ID	" + self.collection.data.id + "	"))
					    .append($("
").append("Created: 	" + creationMonth +"/"+ d.getDate() +"/"+ d.getFullYear() +" "+ d.getHours() +":"+ d.getMinutes() +":"+ d.getSeconds() + "	"))
						.append($("
").append("Number of motifs	" + self.collection.data.motifs.length + "	"))
					));
					self.$elem.append("
View motifs
");

					var $dropdown = $("<select />");
					for (var motif in self.collection.data.motifs) {
						$dropdown.append("<option id='" + motif + "'>"+ self.collection.data.motifs[motif].description + "</option>");
					}
					self.$elem.append($dropdown);
					self.$elem.append($("<button class='btn btn-default'>Show Motif</button>")
	                	.on("click",
	                    	function(event) {
								$(self.$elem.selector + " > select option:selected").each(function() {
    //                      	console.log(event);
								self.trigger("showBambiMotif", { motif: self.collection.data.motifs[$(this).attr("id")], event: event });
	                        });
	                    })
	                );

					self.$elem.append($("").append("
<button class='btn btn-default'>Show BAMBI run parameters</button>")
	                	.on("click",
	                    	function(event) {
								self.trigger("showBambiRunParameters", { collection: self.collection, event: event });
	                    })
	                );

					self.$elem.append($("").append("
<button class='btn btn-default'>Show BAMBI raw output</button>")
	                	.on("click",
	                    	function(event) {
								self.trigger("showBambiRawOutput", { raw_output: self.collection.data.raw_output, event: event });
	                    })
	                );

                        },

			    function(data) {
                                $('.loader-table').remove();
                                self.$elem.append('
[Error] ' + data.error.message + '
');
                                return;
                            }
		    );
            this.hideMessage();
            return this;

        },

        getData: function() {
            return {
                type: "BambiRunResult",
                id: this.options.bambi_run_result_id,
                workspace: this.options.workspace_id,
                title: "BAMBI Run Result Overview"
            };
        },

        showMessage: function(message) {
            var span = $("").append(message);

            this.$messagePane.append(span);
            this.$messagePane.removeClass("kbwidget-hide-message");
        },

        hideMessage: function() {
            this.$messagePane.addClass("kbwidget-hide-message");
            this.$messagePane.empty();
        },

        rpcError: function(error) {
            console.log("An error occurred: " + error);
        }

    });
})( jQuery );
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose');
var errorHandler = require('./errors.server.controller');
var Vocablist = mongoose.model('Vocablist');
var _ = require('lodash');
var Vocab = mongoose.model('Vocab');
var updateVocabHelper = require('../helpers/updateVocab');

function saveVocablistPromise(vocablist) {
  return new Promise(function(resolve, error) {
    vocablist.save(function(err) {
      if (err) {
        error(err);
      } else {
        resolve(vocablist);
      }
    });
  });
}

function populateVocablist(vocablist) {
  return new Promise(function(resolve, error) {
    vocablist.populate('vocab', function(err) {
      if (err) {
        error(err);
      } else {
        resolve(vocablist);
      }
    });
  });
}

function removeNullFromArray(array) {
  for (var i = 0; i < array.length; i++) {
    if (!array[i]) {
      array.splice(i, 1);
    }
  }
}

/**
 * Create a Vocablist
 */
exports.create = function(req, res) {
  var vocabs = req.body.vocab;
  updateVocabHelper.createVocabs(req.user, vocabs).
    then(function(vocabDocs) {
      var vocablist = req.body;
      vocablist.vocab = vocabDocs;
      vocablist.user = req.user;
      return Vocablist.create(vocablist);
    }).
    then(function(vocablist) {
      res.jsonp(vocablist);
      return;
    }).
    catch(function(err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    });
};

/**
 * Show the current Vocablist
 */
exports.read = function(req, res) {
  req.vocablist.populate('vocab', function(err) {
    if (err) {
      return res.status(400).send(new Error('Failed to load Vocablist ' + req.vocablist._id));
    } else {
      res.jsonp(req.vocablist);
    }
  });
};

/**
 * Update a Vocablist
 */
exports.update = function(req, res) {
  var vocablist = req.vocablist;
  vocablist = _.extend(vocablist , req.body);
  updateVocabHelper.findAndUpdateVocabs(req.body.vocab).
    then(function(vocabs) {
      removeNullFromArray(vocabs);
      vocablist.vocab = vocabs;
      return saveVocablistPromise(vocablist);
    }).
    then(populateVocablist).
    then(function(vocablist) {
      res.jsonp(vocablist);
    }).
    catch(
      function(err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      }
    );
};

function deleteVocabs(vocablist) {
  var ids = [];
  for (var i = 0; i < vocablist.vocab.length; i++) {
    ids.push(vocablist.vocab[i]);
  }
  return Vocab.remove({_id: {$in: ids}});
}

/**
 * Delete an Vocablist
 */
exports.delete = function(req, res) {
  var vocablist = req.vocablist;
  deleteVocabs(vocablist).then(function() {
    return vocablist.remove();
  }).then(function() {
    res.jsonp(vocablist);
  }).catch(function(err) {
    return res.status(400).send({
      message: errorHandler.getErrorMessage(err)
    });
  });
};

function getAllVocablists(user) {
  var query = user ? {user: user._id} : {};
  return Vocablist.find(query).sort('-created').populate('vocab').exec();
}

/**
 * List of Vocablists
 */
exports.list = function(req, res) {
  var query = req.user ? {user: req.user._id} : {};
  getAllVocablists(req.user)
    .then(function(vocablists) {
      res.jsonp(vocablists);
    })
    .catch(function(err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    });
};

function stripVocab(vocab) {
  return {
    word: vocab.word,
    translation: vocab.translation,
    timesTested: vocab.timesTested,
    timesCorrect: vocab.timesCorrect,
    lastTested: vocab.lastTested
  };
}

function stripVocablist(vocablist) {
  for (var i = 0; i < vocablist.vocab.length; i++) {
    vocablist.vocab[i] = stripVocab(vocablist.vocab[i]);
  }
  return {
    vocab: vocablist.vocab,
    name: vocablist.name,
    category: vocablist.category,
    created: vocablist.created,
    chapter: vocablist.chapter
  };
}

exports.download = function(req, res, next) {
  populateVocablist(req.vocablist).then(function(vocablist) {
    var stripped = stripVocablist(vocablist);
    res.set('Content-Type', 'application/force-download');
    res.set('Content-Disposition', 'attachment; filename=\"' + vocablist.name + '.json' + '\"');
    res.send(stripped);
  });
};

exports.downloadAll = function(req, res, next) {
  getAllVocablists(req.user)
    .then(function(vocablists) {
      for (var i = 0; i < vocablists.length; i++) {
        vocablists[i] = stripVocablist(vocablists[i]);
      }
      res.set('Content-Type', 'application/force-download');
      res.set('Content-Disposition', 'attachment; filename=\"allVocablists.json\"');
      res.send(vocablists);
    })
    .catch(function(err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    });
};

/**
 * Vocablist middleware
 */
exports.vocablistByID = function(req, res, next, id) {
  Vocablist.findById(id).exec(function(err, vocablist) {
    if (err) {
      return next(err);
    }
    if (!vocablist) {
      return next(new Error('Failed to load Vocablist ' + id));
    }
    req.vocablist = vocablist;
    next();
  });
};

/**
 * Vocablist authorization middleware
 */
exports.hasAuthorization = function(req, res, next) {
  if (req.vocablist.user.toString() !== req.user._id.toString()) {
    return res.status(403).send('User is not authorized');
  }
  next();
};
<commit_msg>Adds a mostMistaken function<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose');
var errorHandler = require('./errors.server.controller');
var Vocablist = mongoose.model('Vocablist');
var _ = require('lodash');
var Vocab = mongoose.model('Vocab');
var updateVocabHelper = require('../helpers/updateVocab');

function saveVocablistPromise(vocablist) {
  return new Promise(function(resolve, error) {
    vocablist.save(function(err) {
      if (err) {
        error(err);
      } else {
        resolve(vocablist);
      }
    });
  });
}

function populateVocablist(vocablist) {
  return new Promise(function(resolve, error) {
    vocablist.populate('vocab', function(err) {
      if (err) {
        error(err);
      } else {
        resolve(vocablist);
      }
    });
  });
}

function removeNullFromArray(array) {
  for (var i = 0; i < array.length; i++) {
    if (!array[i]) {
      array.splice(i, 1);
    }
  }
}

/**
 * Create a Vocablist
 */
exports.create = function(req, res) {
  var vocabs = req.body.vocab;
  updateVocabHelper.createVocabs(req.user, vocabs).
    then(function(vocabDocs) {
      var vocablist = req.body;
      vocablist.vocab = vocabDocs;
      vocablist.user = req.user;
      return Vocablist.create(vocablist);
    }).
    then(function(vocablist) {
      res.jsonp(vocablist);
      return;
    }).
    catch(function(err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    });
};

/**
 * Show the current Vocablist
 */
exports.read = function(req, res) {
  req.vocablist.populate('vocab', function(err) {
    if (err) {
      return res.status(400).send(new Error('Failed to load Vocablist ' + req.vocablist._id));
    } else {
      res.jsonp(req.vocablist);
    }
  });
};

/**
 * Update a Vocablist
 */
exports.update = function(req, res) {
  var vocablist = req.vocablist;
  vocablist = _.extend(vocablist , req.body);
  updateVocabHelper.findAndUpdateVocabs(req.body.vocab).
    then(function(vocabs) {
      removeNullFromArray(vocabs);
      vocablist.vocab = vocabs;
      return saveVocablistPromise(vocablist);
    }).
    then(populateVocablist).
    then(function(vocablist) {
      res.jsonp(vocablist);
    }).
    catch(
      function(err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      }
    );
};

function deleteVocabs(vocablist) {
  var ids = [];
  for (var i = 0; i < vocablist.vocab.length; i++) {
    ids.push(vocablist.vocab[i]);
  }
  return Vocab.remove({_id: {$in: ids}});
}

/**
 * Delete an Vocablist
 */
exports.delete = function(req, res) {
  var vocablist = req.vocablist;
  deleteVocabs(vocablist).then(function() {
    return vocablist.remove();
  }).then(function() {
    res.jsonp(vocablist);
  }).catch(function(err) {
    return res.status(400).send({
      message: errorHandler.getErrorMessage(err)
    });
  });
};

function getAllVocablists(user) {
  var query = user ? {user: user._id} : {};
  return Vocablist.find(query).sort('-created').populate('vocab').exec();
}

/**
 * List of Vocablists
 */
exports.list = function(req, res) {
  var query = req.user ? {user: req.user._id} : {};
  getAllVocablists(req.user)
    .then(function(vocablists) {
      res.jsonp(vocablists);
    })
    .catch(function(err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    });
};

function stripVocab(vocab) {
  return {
    word: vocab.word,
    translation: vocab.translation,
    timesTested: vocab.timesTested,
    timesCorrect: vocab.timesCorrect,
    lastTested: vocab.lastTested
  };
}

function stripVocablist(vocablist) {
  for (var i = 0; i < vocablist.vocab.length; i++) {
    vocablist.vocab[i] = stripVocab(vocablist.vocab[i]);
  }
  return {
    vocab: vocablist.vocab,
    name: vocablist.name,
    category: vocablist.category,
    created: vocablist.created,
    chapter: vocablist.chapter
  };
}

exports.download = function(req, res, next) {
  populateVocablist(req.vocablist).then(function(vocablist) {
    var stripped = stripVocablist(vocablist);
    res.set('Content-Type', 'application/force-download');
    res.set('Content-Disposition', 'attachment; filename=\"' + vocablist.name + '.json' + '\"');
    res.send(stripped);
  });
};

exports.downloadAll = function(req, res, next) {
  getAllVocablists(req.user)
    .then(function(vocablists) {
      for (var i = 0; i < vocablists.length; i++) {
        vocablists[i] = stripVocablist(vocablists[i]);
      }
      res.set('Content-Type', 'application/force-download');
      res.set('Content-Disposition', 'attachment; filename=\"allVocablists.json\"');
      res.send(vocablists);
    })
    .catch(function(err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    });
};

/**
 * Vocablist middleware
 */
exports.vocablistByID = function(req, res, next, id) {
  Vocablist.findById(id).exec(function(err, vocablist) {
    if (err) {
      return next(err);
    }
    if (!vocablist) {
      return next(new Error('Failed to load Vocablist ' + id));
    }
    req.vocablist = vocablist;
    next();
  });
};

/**
 * Vocablist authorization middleware
 */
exports.hasAuthorization = function(req, res, next) {
  if (req.vocablist.user.toString() !== req.user._id.toString()) {
    return res.status(403).send('User is not authorized');
  }
  next();
};

exports.mostMistaken = function(req, res, next) {
  Vocab.find({user: req.user._id}).
    where('timesTested').gt(0).
    limit(20).
    then(function(vocabs) {
      vocabs.sort(function(vocab1, vocab2) {
        return (vocab1.timesCorrect / vocab1.timesTested) -
        (vocab2.timesCorrect / vocab2.timesTested);
      });
      res.jsonp({vocab: vocabs});
    }).
    catch(function(err) {
      res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    });
};
<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');

const test = require('tape');
const nock = require('nock');
const install = require('../lib/install.js');

test('should follow redirects', (t) => {
  // Dummy tar.gz data, contains a blank directory.
  const targz = 'H4sICPr8u1oCA3kudGFyANPTZ6A5MDAwMDc1VQDTZhAaCGA0hGNobGRqZm5uZmxupGBgaGhiZsKgYMpAB1BaXJJYBHRKYk5pcioedeUZqak5+D2J5CkFhlEwCkbBKBjkAAAyG1ofAAYAAA==';

  // Mock an HTTP redirect
  const n = nock('https://mapbox-node-pre-gyp-public-testing-bucket.s3.us-east-1.amazonaws.com')
    .get(/\/node-pre-gyp\/node-pre-gyp-test-app1\/v0.1.0\/Release\/node-v\d+-\S+.tar.gz/)
    .reply(302, '', {
      'Location': 'https://mapbox-node-pre-gyp-public-testing-bucket.s3.us-east-1.amazonaws.com/otherapp.tar.gz'
    })
    .get('/otherapp.tar.gz')
    .reply(200, Buffer.from(targz, 'base64'));

  const opts = {
    opts: {
      'build-from-source': false,
      'update-binary': true
    }
  };

  process.chdir('test/app1');

  // commands no longer read package.json so it must be passed to them.
  opts.package_json = JSON.parse(fs.readFileSync('./package.json'));

  install(opts, [], (err) => {
    t.ifError(err); // Worked fine
    t.ok(n.isDone()); // All mocks consumed
    t.end();
  });

});

<commit_msg>fix fetch test<commit_after>'use strict';

const fs = require('fs');

const test = require('tape');
const { mockS3Http } = require('../lib/node-pre-gyp.js');
const nock = require('nock');
const install = require('../lib/install.js');

test.onFinish(() => {
  mockS3Http('on');
});

test('should follow redirects', (t) => {
  // clear existing mocks
  const was = mockS3Http('off');

  // Dummy tar.gz data, contains a blank directory.
  const targz = 'H4sICPr8u1oCA3kudGFyANPTZ6A5MDAwMDc1VQDTZhAaCGA0hGNobGRqZm5uZmxupGBgaGhiZsKgYMpAB1BaXJJYBHRKYk5pcioedeUZqak5+D2J5CkFhlEwCkbBKBjkAAAyG1ofAAYAAA==';
  // Mock an HTTP redirect
  const scope = nock('https://mapbox-node-pre-gyp-public-testing-bucket.s3.us-east-1.amazonaws.com')
    // .get(/\/node-pre-gyp\/node-pre-gyp-test-app1\/v0.1.0\/Release\/node-v\d+-\S+.tar.gz/)
    .get(() => true)
    .reply(302, '', {
      'Location': 'https://mapbox-node-pre-gyp-public-testing-bucket.s3.us-east-1.amazonaws.com/otherapp.tar.gz'
    })
    .get('/otherapp.tar.gz')
    .reply(200, Buffer.from(targz, 'base64'));

  const opts = {
    opts: {
      'build-from-source': false,
      'update-binary': true
    }
  };

  process.chdir('test/app1');

  // commands no longer read package.json so it must be passed to them.
  opts.package_json = JSON.parse(fs.readFileSync('./package.json'));

  console.log('mockS3Http was', was, 'is', mockS3Http('get'));

  install(opts, [], (err) => {
    t.ifError(err); // Worked fine
    t.ok(scope.isDone()); // All mocks consumed
    t.end();
  });

});

<|endoftext|>


<commit_before> // monkey patching
 String.prototype.endsWith = function(suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

var libsw = new LibSpaceWalk();

// ==== Logging Data ====
var logData = [];
var filteredData = [];

var showState = {
	show: 'show',
	hide: 'hide',
	faded: 'faded'
}
var showTrace = showState.show;
var showDebug = showState.show;
var showInfo = showState.show;
var showWarn = showState.show;
var showError = showState.show;
var showFatal = showState.show;

function nextShowState(state) {
	if (state === showState.show)
		return showState.faded;
	else if (state == showState.faded)
		return showState.hide;
	else
		return showState.show;
}

libsw.onMessage = function(data) {
	if (data.type === 'log') {
		addLog(data.payload);
		d3.select('#lineCounter')
			.text(logData.length);
	}
}

libsw.onSessionStarted = function() {

	// post new session
	d3.select('#log').append('div')
		.attr('class', 'sessionMarker')
		.text('new session started...');
}

function addLog(datum) {
	logData.push(datum);
	d3.select('#lineCounter')
		.text(logData.length);

	d3.select('#log').selectAll('div.logEntry')
		.data(logData)
			.enter().append('div')
				.attr('class', function(d) { return 'logEntry ' + d.level; })
				.html(function(d) { return d.message; })
				.style('opacity', function(d) {
					if (((showTrace === showState.faded) && d.level === 'trace') ||
						((showDebug === showState.faded) && d.level === 'debug') ||
						((showInfo === showState.faded) && d.level === 'info') ||
						((showWarn === showState.faded) && d.level === 'warn') ||
						((showError === showState.faded) && d.level === 'error') ||
						((showFatal === showState.faded) && d.level === 'fatal')) {
						return '0.5';
					} else
						return '1';
				})
				.style('display', function(d) {
					if (((showTrace === showState.hide) && d.level === 'trace') ||
						((showDebug === showState.hide) && d.level === 'debug') ||
						((showInfo === showState.hide) && d.level === 'info') ||
						((showWarn === showState.hide) && d.level === 'warn') ||
						((showError === showState.hide) && d.level === 'error') ||
						((showFatal === showState.hide) && d.level === 'fatal')) {
						return 'none';
					} else
						return 'block';
				})
}

function toggleCube(state, name, cls) {
	if (state === showState.show) {
		d3.select(name)
			.transition()
				.duration(200)
				.style('opacity', 1);

		d3.selectAll('div.log div.' + cls)
			.style('opacity', 1)
			.style('display', 'block');
	}
	else if (state === showState.faded) {
		d3.select(name)
			.transition()
				.duration(200)
				.style('opacity', 0.5);

		d3.selectAll('div.log div.' + cls)
			.style('opacity', 0.5)
			.style('display', 'block');
	}

	else if (state === showState.hide) {
		d3.select(name)
			.transition()
				.duration(200)
				.style('opacity', 0.1);

		d3.selectAll('div.log div.' + cls)
			.style('opacity', 0.1)
			.style('display', 'none');
	}
}

function init() {

	$('#toggleTrace').click(function() {
		showTrace = nextShowState(showTrace);
		toggleCube(showTrace, '#toggleTrace', 'trace');
	});

	$('#toggleInfo').click(function() {
		showInfo = nextShowState(showInfo);
		toggleCube(showInfo, '#toggleInfo', 'info');
	});

	$('#toggleDebug').click(function() {
		showDebug = nextShowState(showDebug);
		toggleCube(showDebug, '#toggleDebug', 'debug');
	});

	$('#toggleWarn').click(function() {
		showWarn = nextShowState(showWarn);
		toggleCube(showWarn, '#toggleWarn', 'warn');
	});

	$('#toggleError').click(function() {
		showError = nextShowState(showError);
		toggleCube(showError, '#toggleError', 'error');
	});

	$('#toggleFatal').click(function() {
		showFatal = nextShowState(showFatal);
		toggleCube(showFatal, '#toggleFatal', 'fatal');
	});

	var clearLog = function() {
		logData = [];
		d3.select('#lineCounter')
			.text('--');

		d3.selectAll('div.log div')
			.remove();
	}
	$('#clearLog').click(clearLog);

	var clearScalar = function() {
		scalarData = [];

		d3.selectAll('div.scalar div')
			.remove();

		d3.select('#scalar').append('div')
			.attr('id', 'scalar-session-' + sessionID)
	}
	$('#clearScalar').click(clearScalar);
}

var readyStateCheckInterval = setInterval(function() {
	   if (document.readyState === "complete") {
		   init();
		   clearInterval(readyStateCheckInterval);
	   }
}, 10);

// ================================= util ================================
function round(value, decimals) {
	decimals = decimals || 0;
	var v = value * Math.pow(10, decimals);
	return Math.round(v) / Math.pow(10, decimals);
}

function last(arr) {
	return arr[arr.length-1];
}<commit_msg>updated to spec<commit_after> // monkey patching
 String.prototype.endsWith = function(suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

var libsw = new LibSpaceWalk();

// ==== Logging Data ====
var logData = [];
var filteredData = [];

var showState = {
	show: 'show',
	hide: 'hide',
	faded: 'faded'
}
var showTrace = showState.show;
var showDebug = showState.show;
var showInfo = showState.show;
var showWarn = showState.show;
var showError = showState.show;
var showFatal = showState.show;

function nextShowState(state) {
	if (state === showState.show)
		return showState.faded;
	else if (state == showState.faded)
		return showState.hide;
	else
		return showState.show;
}

libsw.onMessage = function(data) {
	if (data.type === 'core.simpleLog.message') {
		addLog(data.payload);
		d3.select('#lineCounter')
			.text(logData.length);
	}
}

libsw.onSessionStarted = function() {

	// post new session
	d3.select('#log').append('div')
		.attr('class', 'sessionMarker')
		.text('new session started...');
}

function addLog(datum) {
	logData.push(datum);
	d3.select('#lineCounter')
		.text(logData.length);

	d3.select('#log').selectAll('div.logEntry')
		.data(logData)
			.enter().append('div')
				.attr('class', function(d) { return 'logEntry ' + d.level; })
				.html(function(d) { return d.message; })
				.style('opacity', function(d) {
					if (((showTrace === showState.faded) && d.level === 'trace') ||
						((showDebug === showState.faded) && d.level === 'debug') ||
						((showInfo === showState.faded) && d.level === 'info') ||
						((showWarn === showState.faded) && d.level === 'warn') ||
						((showError === showState.faded) && d.level === 'error') ||
						((showFatal === showState.faded) && d.level === 'fatal')) {
						return '0.5';
					} else
						return '1';
				})
				.style('display', function(d) {
					if (((showTrace === showState.hide) && d.level === 'trace') ||
						((showDebug === showState.hide) && d.level === 'debug') ||
						((showInfo === showState.hide) && d.level === 'info') ||
						((showWarn === showState.hide) && d.level === 'warn') ||
						((showError === showState.hide) && d.level === 'error') ||
						((showFatal === showState.hide) && d.level === 'fatal')) {
						return 'none';
					} else
						return 'block';
				})
}

function toggleCube(state, name, cls) {
	if (state === showState.show) {
		d3.select(name)
			.transition()
				.duration(200)
				.style('opacity', 1);

		d3.selectAll('div.log div.' + cls)
			.style('opacity', 1)
			.style('display', 'block');
	}
	else if (state === showState.faded) {
		d3.select(name)
			.transition()
				.duration(200)
				.style('opacity', 0.5);

		d3.selectAll('div.log div.' + cls)
			.style('opacity', 0.5)
			.style('display', 'block');
	}

	else if (state === showState.hide) {
		d3.select(name)
			.transition()
				.duration(200)
				.style('opacity', 0.1);

		d3.selectAll('div.log div.' + cls)
			.style('opacity', 0.1)
			.style('display', 'none');
	}
}

function init() {

	$('#toggleTrace').click(function() {
		showTrace = nextShowState(showTrace);
		toggleCube(showTrace, '#toggleTrace', 'trace');
	});

	$('#toggleInfo').click(function() {
		showInfo = nextShowState(showInfo);
		toggleCube(showInfo, '#toggleInfo', 'info');
	});

	$('#toggleDebug').click(function() {
		showDebug = nextShowState(showDebug);
		toggleCube(showDebug, '#toggleDebug', 'debug');
	});

	$('#toggleWarn').click(function() {
		showWarn = nextShowState(showWarn);
		toggleCube(showWarn, '#toggleWarn', 'warn');
	});

	$('#toggleError').click(function() {
		showError = nextShowState(showError);
		toggleCube(showError, '#toggleError', 'error');
	});

	$('#toggleFatal').click(function() {
		showFatal = nextShowState(showFatal);
		toggleCube(showFatal, '#toggleFatal', 'fatal');
	});

	var clearLog = function() {
		logData = [];
		d3.select('#lineCounter')
			.text('--');

		d3.selectAll('div.log div')
			.remove();
	}
	$('#clearLog').click(clearLog);

	var clearScalar = function() {
		scalarData = [];

		d3.selectAll('div.scalar div')
			.remove();

		d3.select('#scalar').append('div')
			.attr('id', 'scalar-session-' + sessionID)
	}
	$('#clearScalar').click(clearScalar);
}

var readyStateCheckInterval = setInterval(function() {
	   if (document.readyState === "complete") {
		   init();
		   clearInterval(readyStateCheckInterval);
	   }
}, 10);

// ================================= util ================================
function round(value, decimals) {
	decimals = decimals || 0;
	var v = value * Math.pow(10, decimals);
	return Math.round(v) / Math.pow(10, decimals);
}

function last(arr) {
	return arr[arr.length-1];
}<|endoftext|>


<commit_before>import assert from 'assert';

import _ from 'mori';

import Store from '../src/stores/store';
import Dispatcher from '../src/lib/dispatcher';
import atom from '../src/state/atom';

let initial = {

    items: _.sortedSet(

        _.hashMap('name', 'Item #1', 'selected', false),
        _.hashMap('name', 'Item #2', 'selected', false),
        _.hashMap('name', 'Item #3', 'selected', false),
        _.hashMap('name', 'Item #4', 'selected', false)
    )
};

let state = _.toClj(initial),
    newState = _.hashMap('name', 'Item #1', 'selected', false);

describe('Flux', () => {

    describe('Data flow', () => {

        it('atom should update', () => {

            atom.silentSwap(state);
            atom.addChangeListener(() => assert.ok(_.equals(atom.getState(), newState)));

            Dispatcher.register('UPDATE', payload => atom.swap(payload));
            Dispatcher.dispatch('UPDATE', newState);
        });
    });
});
<commit_msg>remove unused store<commit_after>import assert from 'assert';

import _ from 'mori';

import Dispatcher from '../src/lib/dispatcher';
import atom from '../src/state/atom';

let initial = {

    items: _.sortedSet(

        _.hashMap('name', 'Item #1', 'selected', false),
        _.hashMap('name', 'Item #2', 'selected', false),
        _.hashMap('name', 'Item #3', 'selected', false),
        _.hashMap('name', 'Item #4', 'selected', false)
    )
};

let state = _.toClj(initial),
    newState = _.hashMap('name', 'Item #1', 'selected', false);

describe('Flux', () => {

    describe('Data flow', () => {

        it('atom should update', () => {

            atom.silentSwap(state);
            atom.addChangeListener(() => assert.ok(_.equals(atom.getState(), newState)));

            Dispatcher.register('UPDATE', payload => atom.swap(payload));
            Dispatcher.dispatch('UPDATE', newState);
        });
    });
});
<|endoftext|>


<commit_before>// Private

var HandlerGroup = function HandlerGroup (successCb, failureCb) {
  this.successCb = (typeof successCb === 'function') ? successCb : null;
  this.failureCb = (typeof failureCb === 'function') ? failureCb : null;
  this.forwarder = new Deferral();
};

var $Promise = function $Promise () {
  this.state = 'pending';
  this.handlers = [];
  this.schedule = function schedule (fn) {
    schedule.fns = schedule.fns || [];
    if (fn) schedule.fns.push(fn);
    else setImmediate(function(){
      var newIndex = schedule.fns.length;
      schedule.fns.forEach(function(fn){ fn(); });
      schedule.fns = schedule.fns.slice(newIndex);
    });
  };
};

$Promise.prototype.then = function then (successCb, failureCb) {
  var newGroup = new HandlerGroup(successCb, failureCb);
  this.handlers.push(newGroup);
  this.tryHandlers();
  return newGroup.forwarder.promise;
};

$Promise.prototype.tryHandlers = function tryHandlers () {
  var group, handler, bubble, output;
  if (this.state === 'pending') return;
  while (this.handlers.length) {
    group = this.handlers.shift();
    handler = (this.state === 'resolved') ? group.successCb : group.failureCb;
    if (!handler) {
      bubble = (this.state === 'resolved') ? 'resolve' : 'reject';
      group.forwarder[bubble](this.value);
    } else {
      this.schedule(executes(handler, this.value, group.forwarder));
    }
  }
  this.schedule();
};

function executes (handler, value, forwarder) {
  return function executing () {
    try {
      output = handler(value);
      if (output === forwarder.promise) {
        var er = new TypeError('cannot forward the promise returned by .then');
        forwarder.reject(er);
      } else if (output instanceof $Promise) {
        output.then(
          function(value) { forwarder.resolve(value); },
          function(error) { forwarder.reject(error); }
        );
      } else forwarder.resolve(output);
    } catch (err) {
      forwarder.reject(err);
    }
  };
}

var Deferral = function Deferral () {
  this.promise = new $Promise();
  this.resolve = this.resolve.bind(this);
  this.reject  = this.reject.bind(this);
};

Deferral.prototype.resolve = function resolve (value) {
  if (this.promise.state !== 'pending') return;
  this.promise.state = 'resolved';
  this.promise.value = value;
  this.promise.tryHandlers();
  return this.promise;
};

Deferral.prototype.reject = function reject (reason) {
  if (this.promise.state !== 'pending') return;
  this.promise.state = 'rejected';
  this.promise.value = reason;
  this.promise.tryHandlers();
  return this.promise;
};

// Public

// Library & ES6-style constructor
var Pledge = function Pledge (handOff) {
  var deferral = this.defer();
  handOff( deferral.resolve, deferral.reject );
  return deferral.promise;
};

// Deferral-style factory
Pledge.defer = function defer () {
  return new Deferral();
};

// Utility methods
Pledge.resolved = function resolved (value) {
  return new Deferral().resolve(value);
};

Pledge.rejected = function rejected (reason) {
  return new Deferral().reject(reason);
};

// It's alive!
module.exports = Pledge;
<commit_msg>passing all specs<commit_after>'use strict';
//===== Private =====

// helpers for more readable code
function invoke (fns) { fns.forEach(function (fn) { fn(); }); }
function isFunction (maybe) { return typeof maybe === 'function'; }
function isObjectOrFunction (maybe) {
  return maybe && (typeof maybe).match(/function|object/);
}

// ancillary promise handler group constructor
function ChainLink (onFulfilled, onRejected) {
  this.onFulfilled = isFunction(onFulfilled) ? onFulfilled : null;
  this.onRejected = isFunction(onRejected) ? onRejected : null;
  this.downstream = new Deferral();
}

// making sure only platform code is on the stack before running handlers
function Schedule () {
  var fns = [];
  this.add = fns.push.bind(fns);
  this.run = function() { setImmediate(function(){ invoke(fns); }); };
}

//----- Promise class -----

function $Promise () {
  this.state = 'pending';
  this.chains = [];
}

$Promise.prototype.then = function then (onFulfilled, onRejected) {
  var newChain = new ChainLink(onFulfilled, onRejected);
  this.chains.push(newChain);
  this.tryHandlers();
  return newChain.downstream.promise;
};

$Promise.prototype.tryHandlers = function tryHandlers () {
  if (this.state === 'pending') return;
  var chain, handler, schedule = new Schedule();
  while (this.chains.length) {
    chain = this.chains.shift();
    handler = this.state === 'resolved' ? chain.onFulfilled : chain.onRejected;
    if (handler) schedule.add(executes(handler, this.value, chain.downstream));
    else if (this.state === 'resolved') chain.downstream.resolve(this.value);
    else if (this.state === 'rejected') chain.downstream.reject(this.value);
  }
  schedule.run();
};

function executes (handler, value, downstream) {
  return function executing () {
    try {
      var x = handler(value);
      promiseResolutionProcedure(downstream, x);
    } catch (err) { downstream.reject(err); }
  };
}

function promiseResolutionProcedure (downstream, x) { // 2.3
  var promise = downstream.promise,
      resolve = downstream.resolve.bind(downstream),
      reject = downstream.reject.bind(downstream);
  if (promise === x) { // 2.3.1
    reject( new TypeError('handlers must not return current chain') );
  } else if ( x instanceof $Promise ) { // 2.3.2
    x.then( promiseResolutionProcedure.bind(downstream), reject );
  } else if ( isObjectOrFunction(x) ) { // 2.3.3
    try {
      var then = x.then; // 2.3.3.1
      if ( isFunction(then) ) { // 2.3.3.3
        var ran = 0; // 2.3.3.3.3
        try {
          then.call(
            x,
            function resolvePromise (y) {
              if (!ran++) promiseResolutionProcedure(downstream, y); // 2.3.3.3.1
            },
            function rejectPromise (y) { if (!ran++) reject(y); } // 2.3.3.3.2
          );
        } catch (errCallingThen) { if (!ran) reject(errCallingThen); } // 2.3.3.3.4
      } else resolve(x); // 2.3.3.4
    } catch (errAccessingThen) { reject(errAccessingThen); } // 2.3.3.2
  } else { // 2.3.4
    resolve(x);
  }
}

//----- Deferral class -----

function Deferral () {
  this.promise = new $Promise();
  this.resolve = this.resolve.bind(this);
  this.reject = this.reject.bind(this);
}

Deferral.prototype.settle = function settle (state, value) {
  if (this.promise.state === 'pending' && state.match(/resolved|rejected/) ) {
    this.promise.state = state;
    this.promise.value = value;
    this.promise.tryHandlers();
  }
  return this.promise;
};

Deferral.prototype.resolve = function resolve (value) {
  return this.settle('resolved', value);
};

Deferral.prototype.reject = function reject (reason) {
  return this.settle('rejected', reason);
};

//===== Public =====

// Library namespace & ES6-style constructor wrapper
function Pledge (executor) {
  if (!isFunction(executor)) throw new TypeError('Pledge takes a function');
  var deferral = Pledge.defer();
  executor( deferral.resolve.bind(deferral), deferral.reject.bind(deferral) );
  return deferral.promise;
}

// Deferral factory function
Pledge.defer = function defer () {
  return new Deferral();
};

//----- Library methods -----

// returns a new promise resolved with `value`
Pledge.resolved = function resolved (value) {
  return new Deferral().resolve(value);
};

// returns a new promise rejected with `reason`
Pledge.rejected = function rejected (reason) {
  return new Deferral().reject(reason);
};

// It's alive!
module.exports = Pledge;
<|endoftext|>


<commit_before>module.exports = {

  'Editor drag&drop should trigger URL update' : function (browser) {
    browser
      .resizeWindow(640,360)
      .page.looper()
      .uri('#index=3&v=nJBxKT7EGKI&v=_7gWDO8SgW4&i=cJjBEQP&v=vnncm3MbMLs&v=3Hv1DElPXV0&v=PLb57RNlqJc&v=S0COlNTizwo&v=phrRu6lACcE&v=FGs57y4nA_Y&v=U8-rNMPTnyg&v=XCzdTxRBDW8&v=wY-kAnvOY80&v=QaLFAlUp1U8&v=4bnb8ti0JGU&v=uxp54wEhQi8&v=RyZU9ptzy68&v=vCVN5pLXoo4&v=jA8inmHhx8c&v=GINpKSkZawk&v=qk2_IY9w4Og&v=_G04b2sZvSM&v=rLrtEyisDMU&quality=small&editor')
      .waitForLoadedId('cJjBEQP')
      .waitForElementVisible('#editor .highlighted')
      .assert.editorHighlightUri('i=cJjBEQP')
      .assert.uriEquals('#index=3&v=nJBxKT7EGKI&v=_7gWDO8SgW4&i=cJjBEQP&v=vnncm3MbMLs&v=3Hv1DElPXV0&v=PLb57RNlqJc&v=S0COlNTizwo&v=phrRu6lACcE&v=FGs57y4nA_Y&v=U8-rNMPTnyg&v=XCzdTxRBDW8&v=wY-kAnvOY80&v=QaLFAlUp1U8&v=4bnb8ti0JGU&v=uxp54wEhQi8&v=RyZU9ptzy68&v=vCVN5pLXoo4&v=jA8inmHhx8c&v=GINpKSkZawk&v=qk2_IY9w4Og&v=_G04b2sZvSM&v=rLrtEyisDMU&quality=small&editor')
      .moveToElement('#editor .highlighted',3,3)
      .mouseButtonDown('left')
      .moveToElement('#editor table', 10, 3)
      .mouseButtonUp('left')
      .waitForLoadedId('_7gWDO8SgW4')
      .assert.uriEquals('#i=cJjBEQP&v=nJBxKT7EGKI&v=_7gWDO8SgW4&v=vnncm3MbMLs&v=3Hv1DElPXV0&v=PLb57RNlqJc&v=S0COlNTizwo&v=phrRu6lACcE&v=FGs57y4nA_Y&v=U8-rNMPTnyg&v=XCzdTxRBDW8&v=wY-kAnvOY80&v=QaLFAlUp1U8&v=4bnb8ti0JGU&v=uxp54wEhQi8&v=RyZU9ptzy68&v=vCVN5pLXoo4&v=jA8inmHhx8c&v=GINpKSkZawk&v=qk2_IY9w4Og&v=_G04b2sZvSM&v=rLrtEyisDMU&editor&index=3&quality=small')
      .waitForElementVisible('#editor .highlighted')
      .assert.editorHighlightUri('v=_7gWDO8SgW4')
      .end();
  },

};
<commit_msg>Skip editor test on TravisCI<commit_after>module.exports = {

  'Editor drag&drop should trigger URL update' : function (browser) {
    if (browser.globals.skipOnTravis) return;
    browser
      .resizeWindow(640,360)
      .page.looper()
      .uri('#index=3&v=nJBxKT7EGKI&v=_7gWDO8SgW4&i=cJjBEQP&v=vnncm3MbMLs&v=3Hv1DElPXV0&v=PLb57RNlqJc&v=S0COlNTizwo&v=phrRu6lACcE&v=FGs57y4nA_Y&v=U8-rNMPTnyg&v=XCzdTxRBDW8&v=wY-kAnvOY80&v=QaLFAlUp1U8&v=4bnb8ti0JGU&v=uxp54wEhQi8&v=RyZU9ptzy68&v=vCVN5pLXoo4&v=jA8inmHhx8c&v=GINpKSkZawk&v=qk2_IY9w4Og&v=_G04b2sZvSM&v=rLrtEyisDMU&quality=small&editor')
      .waitForLoadedId('cJjBEQP')
      .waitForElementVisible('#editor .highlighted')
      .assert.editorHighlightUri('i=cJjBEQP')
      .assert.uriEquals('#index=3&v=nJBxKT7EGKI&v=_7gWDO8SgW4&i=cJjBEQP&v=vnncm3MbMLs&v=3Hv1DElPXV0&v=PLb57RNlqJc&v=S0COlNTizwo&v=phrRu6lACcE&v=FGs57y4nA_Y&v=U8-rNMPTnyg&v=XCzdTxRBDW8&v=wY-kAnvOY80&v=QaLFAlUp1U8&v=4bnb8ti0JGU&v=uxp54wEhQi8&v=RyZU9ptzy68&v=vCVN5pLXoo4&v=jA8inmHhx8c&v=GINpKSkZawk&v=qk2_IY9w4Og&v=_G04b2sZvSM&v=rLrtEyisDMU&quality=small&editor')
      .moveToElement('#editor .highlighted',3,3)
      .mouseButtonDown('left')
      .moveToElement('#editor table', 10, 3)
      .mouseButtonUp('left')
      .waitForLoadedId('_7gWDO8SgW4')
      .assert.uriEquals('#i=cJjBEQP&v=nJBxKT7EGKI&v=_7gWDO8SgW4&v=vnncm3MbMLs&v=3Hv1DElPXV0&v=PLb57RNlqJc&v=S0COlNTizwo&v=phrRu6lACcE&v=FGs57y4nA_Y&v=U8-rNMPTnyg&v=XCzdTxRBDW8&v=wY-kAnvOY80&v=QaLFAlUp1U8&v=4bnb8ti0JGU&v=uxp54wEhQi8&v=RyZU9ptzy68&v=vCVN5pLXoo4&v=jA8inmHhx8c&v=GINpKSkZawk&v=qk2_IY9w4Og&v=_G04b2sZvSM&v=rLrtEyisDMU&editor&index=3&quality=small')
      .waitForElementVisible('#editor .highlighted')
      .assert.editorHighlightUri('v=_7gWDO8SgW4')
      .end();
  },

};
<|endoftext|>


<commit_before>var expect = require('chai').expect;

var hooks = require('../src/hooks');

describe('hooks.js', function () {

	beforeEach(function () {
		var self = this;
	});

	afterEach(function () {
		var self = this;
	});

	it('Expect hooks.mount to not throw error when called', function () {
		var self = this;

		var fn = function () {
			var testFunction = function () {
			};
			testFunction = hooks.mount(testFunction);
		};

		expect(fn).to.not.throw(Error);
	});

	it('Expect hooks.hookify to not throw error when called', function () {
		var self = this;

		var fn = function () {
			var testObject = {
				testFunction: function () {
				},
				testSecondFunction: function () {
				},
			};
			hooks.hookify(testObject);
		};

		expect(fn).to.not.throw(Error);
	});

	it('Expect pre,post,before,after to not throw error when called on mounted function', function () {
		var self = this;

		var fn = function () {
			var testFunction = function () {
			};

			testFunction = hooks.mount(testFunction);

			testFunction.pre(function(){});
			testFunction.post(function(){});
			testFunction.before(function(){});
			testFunction.after(function(){});
		};

		expect(fn).to.not.throw(Error);
	});

	it('Expect pre,post,before,after to not throw error when called on hookified object', function () {
		var self = this;

		var fn = function () {
			var testObject = {
				testFunction: function () {
				},
				testSecondFunction: function () {
				},
			};

			hooks.hookify(testObject);

			testObject.pre('(.*)', function(){});
			testObject.post('(.*)', function(){});
			testObject.before('(.*)', function(){});
			testObject.after('(.*)', function(){});
		};

		expect(fn).to.not.throw(Error);
	});

	it('Expect pre,post,before,after to be functions mounted to chosen function', function () {
		var self = this;

		var testFunction = function () {
		};

		testFunction = hooks.mount(testFunction);

		expect(testFunction.pre).to.be.a('function');
		expect(testFunction.post).to.be.a('function');
		expect(testFunction.before).to.be.a('function');
		expect(testFunction.after).to.be.a('function');
	});

	it('Expect output to be sum of pre, basic and post function', function () {
		var self = this;

		var output = '';

		var testFunction = function () {
			output += ' center ';
		};

		testFunction = hooks.mount(testFunction);

		testFunction.pre(function(){
			output += 'before';
		});

		testFunction.post(function(){
			output += 'after';
		});

		testFunction();

		expect(output).to.be.equal('before center after');
	});

	it('Expect output to be converted to upper case by post hook', function () {
		var self = this;

		var testFunction = function () {
			return 'Anna';
		};

		testFunction = hooks.mount(testFunction);

		testFunction.post(function(args, meta, result){
			return result.toUpperCase();
		});

		var output = testFunction();

		expect(output).to.be.equal('ANNA');
	});

	it('Expect output to not to be overwritten by post hook if undefined returned', function () {
		var self = this;

		var testFunction = function () {
			return 'Anna';
		};

		testFunction = hooks.mount(testFunction);

		testFunction.post(function(args, meta, result){
			return undefined;
		});

		var output = testFunction();

		expect(output).to.be.equal('Anna');
	});

	it('Expect output to be overwritten by post hook if null returned', function () {
		var self = this;

		var testFunction = function () {
			return 'Anna';
		};

		testFunction = hooks.mount(testFunction);

		testFunction.post(function(args, meta, result){
			return null;
		});

		var output = testFunction();

		expect(output).to.be.equal(null);
	});

	it('Expect output to be correctly overwritten by post hooks where some of them modify output and some of them don\'t', function () {
		var self = this;

		var testFunction = function () {
			return 'Anna';
		};

		testFunction = hooks.mount(testFunction);

		testFunction.post(function(args, meta, result){
			return '@' + result;
		});

		testFunction.post(function(args, meta, result){
			return undefined;
		});

		testFunction.post(function(args, meta, result){
			return result.toUpperCase();
		});

		testFunction.post(function(args, meta, result){
		});

		var output = testFunction();

		expect(output).to.be.equal('@ANNA');
	});

	it('Expect output to not be modified by hooks after clean function was called', function () {
		var self = this;

		var testFunction = function () {
			return 'Anna';
		};

		testFunction = hooks.mount(testFunction);

		testFunction.post(function(args, meta, result){
			return result.toUpperCase();
		});

		testFunction.clean();

		var output = testFunction();

		expect(output).to.be.equal('Anna');
	});

});<commit_msg>Added new tests<commit_after>var expect = require('chai').expect;

var hooks = require('../src/hooks');

describe('hooks.js', function () {

	beforeEach(function () {
		var self = this;
	});

	afterEach(function () {
		var self = this;
	});

	it('Expect hooks.mount to not throw error when called', function () {
		var self = this;

		var fn = function () {
			var testFunction = function () {
			};
			testFunction = hooks.mount(testFunction);
		};

		expect(fn).to.not.throw(Error);
	});

	it('Expect hooks.hookify to not throw error when called', function () {
		var self = this;

		var fn = function () {
			var testObject = {
				testFunction: function () {
				},
				testSecondFunction: function () {
				},
			};
			hooks.hookify(testObject);
		};

		expect(fn).to.not.throw(Error);
	});

	it('Expect pre,post,before,after to not throw error when called on mounted function', function () {
		var self = this;

		var fn = function () {
			var testFunction = function () {
			};

			testFunction = hooks.mount(testFunction);

			testFunction.pre(function(){});
			testFunction.post(function(){});
			testFunction.before(function(){});
			testFunction.after(function(){});
		};

		expect(fn).to.not.throw(Error);
	});

	it('Expect pre,post,before,after to not throw error when called on hookified object', function () {
		var self = this;

		var fn = function () {
			var testObject = {
				testFunction: function () {
				},
				testSecondFunction: function () {
				},
			};

			hooks.hookify(testObject);

			testObject.pre('(.*)', function(){});
			testObject.post('(.*)', function(){});
			testObject.before('(.*)', function(){});
			testObject.after('(.*)', function(){});
		};

		expect(fn).to.not.throw(Error);
	});

	it('Expect pre,post,before,after to be functions mounted to chosen function', function () {
		var self = this;

		var testFunction = function () {
		};

		testFunction = hooks.mount(testFunction);

		expect(testFunction.pre).to.be.a('function');
		expect(testFunction.post).to.be.a('function');
		expect(testFunction.before).to.be.a('function');
		expect(testFunction.after).to.be.a('function');
	});

	it('Expect output to be sum of pre, basic and post function', function () {
		var self = this;

		var output = '';

		var testFunction = function () {
			output += ' center ';
		};

		testFunction = hooks.mount(testFunction);

		testFunction.pre(function(){
			output += 'before';
		});

		testFunction.post(function(){
			output += 'after';
		});

		testFunction();

		expect(output).to.be.equal('before center after');
	});

	it('Expect output to be converted to upper case by post hook', function () {
		var self = this;

		var testFunction = function () {
			return 'Anna';
		};

		testFunction = hooks.mount(testFunction);

		testFunction.post(function(args, meta, result){
			return result.toUpperCase();
		});

		var output = testFunction();

		expect(output).to.be.equal('ANNA');
	});

	it('Expect output to not be overwritten by post hook if undefined returned', function () {
		var self = this;

		var testFunction = function () {
			return 'Anna';
		};

		testFunction = hooks.mount(testFunction);

		testFunction.post(function(args, meta, result){
			return undefined;
		});

		var output = testFunction();

		expect(output).to.be.equal('Anna');
	});

	it('Expect output to be overwritten by post hook if null returned', function () {
		var self = this;

		var testFunction = function () {
			return 'Anna';
		};

		testFunction = hooks.mount(testFunction);

		testFunction.post(function(args, meta, result){
			return null;
		});

		var output = testFunction();

		expect(output).to.be.equal(null);
	});

	it('Expect output to be correctly overwritten by post hooks where some of them modify output and some of them don\'t', function () {
		var self = this;

		var testFunction = function () {
			return 'Anna';
		};

		testFunction = hooks.mount(testFunction);

		testFunction.post(function(args, meta, result){
			return '@' + result;
		});

		testFunction.post(function(args, meta, result){
			return undefined;
		});

		testFunction.post(function(args, meta, result){
			return result.toUpperCase();
		});

		testFunction.post(function(args, meta, result){
		});

		var output = testFunction();

		expect(output).to.be.equal('@ANNA');
	});

	it('Expect output to not be modified by hooks after clean function was called', function () {
		var self = this;

		var testFunction = function () {
			return 'Anna';
		};

		testFunction = hooks.mount(testFunction);

		testFunction.post(function(args, meta, result){
			return result.toUpperCase();
		});

		testFunction.clean();

		var output = testFunction();

		expect(output).to.be.equal('Anna');
	});

});<|endoftext|>


<commit_before>const { spawn } = require('child_process')

module.exports = {
  onPreBuild({ utils: { status: { show } } }) {
    spawn('sleep', ['60'], { detached: true })
    show({ summary: 'Test' })
  }
}
<commit_msg>Revert "Revert "Revert "Revert "Revert "Try child process"""""<commit_after>module.exports = {
  onPreBuild({ utils: { status: { show } } }) {
    show({ summary: 'Test' })
  }
}
<|endoftext|>


<commit_before>function onFormSubmit() {
  'use strict';

  let filterService = document.getElementById('service').value;
  if (filterService.startsWith('0x')) {
    filterService = parseInt(filterService, 16);
  }

  log('Requesting Bluetooth Device...');
  navigator.bluetooth.requestDevice({filters:[{services:[ filterService ]}]})
  .then(device => {
    log('> Device Name:   ' + device.name);
    log('> Device Id:     ' + device.id);
    log('> Device Paired: ' + device.paired);
    log('> Device Class:  ' + device.deviceClass);
    log('> Device UUIDs:  ' + device.uuids.join('\n' + ' '.repeat(21)));
  })
  .catch(error => {
    log('Argh! ' + error);
  });
}
<commit_msg>Fixed formatting nit in bluetooth device-info sample<commit_after>function onFormSubmit() {
  'use strict';

  let filterService = document.getElementById('service').value;
  if (filterService.startsWith('0x')) {
    filterService = parseInt(filterService, 16);
  }

  log('Requesting Bluetooth Device...');
  navigator.bluetooth.requestDevice({filters:[{services:[ filterService ]}]})
  .then(device => {
    log('> Device Name:   ' + device.name);
    log('> Device Id:     ' + device.id);
    log('> Device Paired: ' + device.paired);
    log('> Device Class:  ' + device.deviceClass);
    log('> Device UUIDs:  ' + device.uuids.join('\n' + ' '.repeat(17)));
  })
  .catch(error => {
    log('Argh! ' + error);
  });
}
<|endoftext|>


<commit_before>/*global WeakMap*/
import { arr, string } from "lively.lang";

function newKeyIn(obj, base = "_") {
  var i = 1, key;
  do {
    key = base + "-" + i++;
  } while (key in obj);
  return key;
}

function signalBindings(morph, name, value) {
  // optimized lively.bindings.signal
  var conns = morph.attributeConnections;
  if (!conns) return
  conns = conns.slice();
  for (var i = 0; i < conns.length; i++)
    if (conns[i].sourceAttrName === name)
      conns[i].update(value)
}

function informMorph(changeManager, change, morph) {
  try {
    morph.onChange(change);
    signalBindings(morph, "change", change);
    var owner = morph.owner;
    while (owner) {
      owner.onSubmorphChange(change, morph);
      owner = owner.owner;
    }
  } catch (err) {
    console.error(`Error in informMorph: ${err.stack}`)
  }
}

function informListeners(changeManager, change) {
  try {
    if (changeManager.changeListeners.length)
      changeManager.changeListeners.forEach(listener => listener(change));
  } catch (err) {
    console.error(`Error in informListeners: ${err.stack}`)
  }
}

class Change {
  constructor(target) {
    this.target = target;
    this.group = null;
  }
  get type() { return "abstract change" }
  apply() { throw new Error("Not yet implemented"); }
  reverseApply() { throw new Error("Not yet implemented"); }
}

export class GroupChange extends Change {
  constructor(target) {
    this.target = target;
    this.changes = [];
  }

  consumesChanges() { return true }

  addChange(c) {
    this.changes.push(c);
    c.group = this;
  }

  apply() {
    this.changes.slice().forEach(change => change.apply());
    return this;
  }

  reverseApply() {
    this.changes.slice().reverse().forEach(change => change.reverseApply());
    return this;
  }
}

export class ValueChange extends Change {

  get type() { return "setter" }

  constructor(target, prop, value, meta) {
    this.target = target;
    this.prop = prop;
    this.value = value;
    this.prevValue = null;
    this.meta = meta;
  }

  apply() {
    var {target, prop, value} = this;
    target[prop] = value;
  }

  reverseApply() {
    var {target, prop, prevValue} = this;
    target[prop] = prevValue;
  }
}

export class MethodCallChange extends GroupChange {

  get type() { return "method-call" }

  constructor(target, selector, args, undo) {
    this.changes = [];
    this.target = target;
    this.selector = selector;
    this.args = args;
    this.undo = undo;
  }

  apply() {
    var {target, selector, args} = this;
    target[selector].apply(target, args);
  }

  reverseApply() {
    if (!this.undo) return;
    if (typeof this.undo === "function") this.undo();
    else {
      var {target, selector, args} = this.undo;
      target[selector].apply(target, args);
    }
  }

}

export class ChangeManager {

  constructor() {
    this.reset();
  }

  reset() {
    this.changes = [];
    this.revision = 0;

    this.changeListeners = [];
    this.changeRecordersPerMorph = new WeakMap();
    this.changeRecorders = {};

    this.changeGroupStack = [];
  }

  changesFor(morph) { return this.changes.filter(c => c.target === morph); }

  apply(change) { change.apply(); }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // interface for adding changes, used by morphs

  addValueChange(morph, prop, value, meta) {
    var change = new ValueChange(morph, prop, value, meta);
    return this._record(morph, change);
  }

  addMethodCallChangeDoing(spec, morph, doFn) {
    var {target, selector, args, undo} = spec;
    if (!undo) undo = () => console.warn(`No undo recorded for ${target}.${selector}`);
    var change = new MethodCallChange(target, selector, args, undo);
    morph.groupChangesWhile(change, doFn);
    return change;
  }

  _record(morph, change) {
    // FIXME
    if (change.hasOwnProperty("value")) {
      change.prevValue = morph._currentState[change.prop];
      morph._currentState[change.prop] = change.value;
    }

    morph.makeDirty();

    var grouping = arr.last(this.changeGroupStack);
    if (grouping && grouping.consumesChanges()) {
      grouping.addChange(change);
    } else {
      this.changes.push(change);
      morph._rev = ++this.revision;
      informListeners(this, change)
    }
    informMorph(this, change, morph);

    return change;
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // group changes

  groupChangesWhile(targetMorph, groupChange = new GroupChange(targetMorph), whileFn) {
    this.changeGroupStack.push(groupChange);
    try {
      whileFn();
      arr.remove(this.changeGroupStack, groupChange);
      return this._record(targetMorph, groupChange);
    } catch (err) {
      arr.remove(this.changeGroupStack, groupChange);
      throw err;
    }
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // listen for changes / record changes

  recordChangesWhile(whileFn, optFilter) {
    var from = this.changes.length;
    whileFn();
    var changes = this.changes.slice(from, this.changes.length);
    return optFilter ? changes.filter(optFilter) : changes;
  }

  addChangeListener(listenFn) { arr.pushIfNotIncluded(this.changeListeners, listenFn); }
  removeChangeListener(listenFn) { arr.remove(this.changeListeners, listenFn); }

  recordChangesStart(optFilter, optName = "") {
    // change recorder is a change listener that is identified by id

    // Recorder object to be used to record specific changes when they occur,
    // based on change listeners
    var id = newKeyIn(this.changeRecorders, optName + "__change_recorder_" + Date.now()),
        listener = optFilter ?
          change => optFilter(change) && recorder.changes.push(change) :
          change => recorder.changes.push(change),
        recorder = this.changeRecorders[id] = {id, filter: optFilter, changes: [], listener};

    this.addChangeListener(listener);

    return recorder;
  }

  recordChangesStop(id) {
    if (!(id in this.changeRecorders)) return [];
    var {changes, listener} = this.changeRecorders[id];
    delete this.changeRecorders[id];
    this.removeChangeListener(listener);
    return changes;
  }

  recordChangesStartForMorph(morph, optFilter) {
    var recorder = this.recordChangesStart(optFilter, morph.id);

    // store recorder alongside morph for easy lookup and
    // to make it easy to just start / stop recordings
    // without having to manage listener storage and its lifetime

    var perMorph = this.changeRecordersPerMorph.get(morph);
    if (!perMorph) {
      perMorph = [];
      this.changeRecordersPerMorph.set(morph, perMorph);
    }
    perMorph.push(recorder.id);

    return recorder;
  }

  recordChangesStopForMorph(morph, optId) {
    var perMorph = this.changeRecordersPerMorph.get(morph);
    if (!perMorph || !perMorph.length) {
      console.warn(`Cannot endMorphChangeRecorder for morph ${morph}: recorder not found`)
      return [];
    }

    var id = optId;
    if (!optId) id = perMorph.pop();
    else arr.remove(perMorph, id);

    return this.recordChangesStop(id);
  }

}
<commit_msg>changes: signal property changes like "extent", "fill", etc<commit_after>/*global WeakMap*/
import { arr, string } from "lively.lang";

function newKeyIn(obj, base = "_") {
  var i = 1, key;
  do {
    key = base + "-" + i++;
  } while (key in obj);
  return key;
}

function signalBindings(morph, name, change) {
  // optimized lively.bindings.signal
  var conns = morph.attributeConnections;
  if (!conns) return
  conns = conns.slice();
  for (var i = 0; i < conns.length; i++) {
    if (conns[i].sourceAttrName === name)
      conns[i].update(change);
    if (change.prop && conns[i].sourceAttrName === change.prop)
      conns[i].update(change.value);
  }
}

function informMorph(changeManager, change, morph) {
  try {
    morph.onChange(change);
    signalBindings(morph, "change", change);
    var owner = morph.owner;
    while (owner) {
      owner.onSubmorphChange(change, morph);
      owner = owner.owner;
    }
  } catch (err) {
    console.error(`Error in informMorph: ${err.stack}`)
  }
}

function informListeners(changeManager, change) {
  try {
    if (changeManager.changeListeners.length)
      changeManager.changeListeners.forEach(listener => listener(change));
  } catch (err) {
    console.error(`Error in informListeners: ${err.stack}`)
  }
}

class Change {
  constructor(target) {
    this.target = target;
    this.group = null;
  }
  get type() { return "abstract change" }
  apply() { throw new Error("Not yet implemented"); }
  reverseApply() { throw new Error("Not yet implemented"); }
}

export class GroupChange extends Change {
  constructor(target) {
    this.target = target;
    this.changes = [];
  }

  consumesChanges() { return true }

  addChange(c) {
    this.changes.push(c);
    c.group = this;
  }

  apply() {
    this.changes.slice().forEach(change => change.apply());
    return this;
  }

  reverseApply() {
    this.changes.slice().reverse().forEach(change => change.reverseApply());
    return this;
  }
}

export class ValueChange extends Change {

  get type() { return "setter" }

  constructor(target, prop, value, meta) {
    this.target = target;
    this.prop = prop;
    this.value = value;
    this.prevValue = null;
    this.meta = meta;
  }

  apply() {
    var {target, prop, value} = this;
    target[prop] = value;
  }

  reverseApply() {
    var {target, prop, prevValue} = this;
    target[prop] = prevValue;
  }
}

export class MethodCallChange extends GroupChange {

  get type() { return "method-call" }

  constructor(target, selector, args, undo) {
    this.changes = [];
    this.target = target;
    this.selector = selector;
    this.args = args;
    this.undo = undo;
  }

  apply() {
    var {target, selector, args} = this;
    target[selector].apply(target, args);
  }

  reverseApply() {
    if (!this.undo) return;
    if (typeof this.undo === "function") this.undo();
    else {
      var {target, selector, args} = this.undo;
      target[selector].apply(target, args);
    }
  }

}

export class ChangeManager {

  constructor() {
    this.reset();
  }

  reset() {
    this.changes = [];
    this.revision = 0;

    this.changeListeners = [];
    this.changeRecordersPerMorph = new WeakMap();
    this.changeRecorders = {};

    this.changeGroupStack = [];
  }

  changesFor(morph) { return this.changes.filter(c => c.target === morph); }

  apply(change) { change.apply(); }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // interface for adding changes, used by morphs

  addValueChange(morph, prop, value, meta) {
    var change = new ValueChange(morph, prop, value, meta);
    return this._record(morph, change);
  }

  addMethodCallChangeDoing(spec, morph, doFn) {
    var {target, selector, args, undo} = spec;
    if (!undo) undo = () => console.warn(`No undo recorded for ${target}.${selector}`);
    var change = new MethodCallChange(target, selector, args, undo);
    morph.groupChangesWhile(change, doFn);
    return change;
  }

  _record(morph, change) {
    // FIXME
    if (change.hasOwnProperty("value")) {
      change.prevValue = morph._currentState[change.prop];
      morph._currentState[change.prop] = change.value;
    }

    morph.makeDirty();

    var grouping = arr.last(this.changeGroupStack);
    if (grouping && grouping.consumesChanges()) {
      grouping.addChange(change);
    } else {
      this.changes.push(change);
      morph._rev = ++this.revision;
      informListeners(this, change)
    }
    informMorph(this, change, morph);

    return change;
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // group changes

  groupChangesWhile(targetMorph, groupChange = new GroupChange(targetMorph), whileFn) {
    this.changeGroupStack.push(groupChange);
    try {
      whileFn();
      arr.remove(this.changeGroupStack, groupChange);
      return this._record(targetMorph, groupChange);
    } catch (err) {
      arr.remove(this.changeGroupStack, groupChange);
      throw err;
    }
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // listen for changes / record changes

  recordChangesWhile(whileFn, optFilter) {
    var from = this.changes.length;
    whileFn();
    var changes = this.changes.slice(from, this.changes.length);
    return optFilter ? changes.filter(optFilter) : changes;
  }

  addChangeListener(listenFn) { arr.pushIfNotIncluded(this.changeListeners, listenFn); }
  removeChangeListener(listenFn) { arr.remove(this.changeListeners, listenFn); }

  recordChangesStart(optFilter, optName = "") {
    // change recorder is a change listener that is identified by id

    // Recorder object to be used to record specific changes when they occur,
    // based on change listeners
    var id = newKeyIn(this.changeRecorders, optName + "__change_recorder_" + Date.now()),
        listener = optFilter ?
          change => optFilter(change) && recorder.changes.push(change) :
          change => recorder.changes.push(change),
        recorder = this.changeRecorders[id] = {id, filter: optFilter, changes: [], listener};

    this.addChangeListener(listener);

    return recorder;
  }

  recordChangesStop(id) {
    if (!(id in this.changeRecorders)) return [];
    var {changes, listener} = this.changeRecorders[id];
    delete this.changeRecorders[id];
    this.removeChangeListener(listener);
    return changes;
  }

  recordChangesStartForMorph(morph, optFilter) {
    var recorder = this.recordChangesStart(optFilter, morph.id);

    // store recorder alongside morph for easy lookup and
    // to make it easy to just start / stop recordings
    // without having to manage listener storage and its lifetime

    var perMorph = this.changeRecordersPerMorph.get(morph);
    if (!perMorph) {
      perMorph = [];
      this.changeRecordersPerMorph.set(morph, perMorph);
    }
    perMorph.push(recorder.id);

    return recorder;
  }

  recordChangesStopForMorph(morph, optId) {
    var perMorph = this.changeRecordersPerMorph.get(morph);
    if (!perMorph || !perMorph.length) {
      console.warn(`Cannot endMorphChangeRecorder for morph ${morph}: recorder not found`)
      return [];
    }

    var id = optId;
    if (!optId) id = perMorph.pop();
    else arr.remove(perMorph, id);

    return this.recordChangesStop(id);
  }

}
<|endoftext|>