<commit_before>'use strict';
var mongoose = require('mongoose');
var ShortId = require('mongoose-shortid');
var timestamps = require('mongoose-timestamp');
var BBPromise = require('bluebird');
var Schema = mongoose.Schema;
var environments = ['live', 'test', 'dev'];
var ModuleMetricSchema = new Schema({
  schemaVersion: String,
  application: {
    type: ShortId,
    ref: 'Application',
    index: true,
    required: 'metrics must belong to an application'
  },
  lastFailure: String,
  environment: {
    type: String,
    enum: {
      values: environments,
      message: 'metrics tokens must belong to a valid environment'
    },
    required: 'metrics tokens must belong to a valid environment'
  },
  moduleName: String,
  timestampHour: Date,
  executionTime: Number,
  executions: {
    0: {
      type: Number,
      default: 0
    },
    1: {
      type: Number,
      default: 0
    },
    2: {
      type: Number,
      default: 0
    },
    3: {
      type: Number,
      default: 0
    },
    4: {
      type: Number,
      default: 0
    },
    5: {
      type: Number,
      default: 0
    },
    6: {
      type: Number,
      default: 0
    },
    7: {
      type: Number,
      default: 0
    },
    8: {
      type: Number,
      default: 0
    },
    9: {
      type: Number,
      default: 0
    },
    10: {
      type: Number,
      default: 0
    },
    11: {
      type: Number,
      default: 0
    },
    12: {
      type: Number,
      default: 0
    },
    13: {
      type: Number,
      default: 0
    },
    14: {
      type: Number,
      default: 0
    },
    15: {
      type: Number,
      default: 0
    },
    16: {
      type: Number,
      default: 0
    },
    17: {
      type: Number,
      default: 0
    },
    18: {
      type: Number,
      default: 0
    },
    19: {
      type: Number,
      default: 0
    },
    20: {
      type: Number,
      default: 0
    },
    21: {
      type: Number,
      default: 0
    },
    22: {
      type: Number,
      default: 0
    },
    23: {
      type: Number,
      default: 0
    },
    24: {
      type: Number,
      default: 0
    },
    25: {
      type: Number,
      default: 0
    },
    26: {
      type: Number,
      default: 0
    },
    27: {
      type: Number,
      default: 0
    },
    28: {
      type: Number,
      default: 0
    },
    29: {
      type: Number,
      default: 0
    },
    30: {
      type: Number,
      default: 0
    },
    31: {
      type: Number,
      default: 0
    },
    32: {
      type: Number,
      default: 0
    },
    33: {
      type: Number,
      default: 0
    },
    34: {
      type: Number,
      default: 0
    },
    35: {
      type: Number,
      default: 0
    },
    36: {
      type: Number,
      default: 0
    },
    37: {
      type: Number,
      default: 0
    },
    38: {
      type: Number,
      default: 0
    },
    39: {
      type: Number,
      default: 0
    },
    40: {
      type: Number,
      default: 0
    },
    41: {
      type: Number,
      default: 0
    },
    42: {
      type: Number,
      default: 0
    },
    43: {
      type: Number,
      default: 0
    },
    44: {
      type: Number,
      default: 0
    },
    45: {
      type: Number,
      default: 0
    },
    46: {
      type: Number,
      default: 0
    },
    47: {
      type: Number,
      default: 0
    },
    48: {
      type: Number,
      default: 0
    },
    49: {
      type: Number,
      default: 0
    },
    50: {
      type: Number,
      default: 0
    },
    51: {
      type: Number,
      default: 0
    },
    52: {
      type: Number,
      default: 0
    },
    53: {
      type: Number,
      default: 0
    },
    54: {
      type: Number,
      default: 0
    },
    55: {
      type: Number,
      default: 0
    },
    56: {
      type: Number,
      default: 0
    },
    57: {
      type: Number,
      default: 0
    },
    58: {
      type: Number,
      default: 0
    },
    59: {
      type: Number,
      default: 0
    }
  },
  timeouts: {
    0: {
      type: Number,
      default: 0
    },
    1: {
      type: Number,
      default: 0
    },
    2: {
      type: Number,
      default: 0
    },
    3: {
      type: Number,
      default: 0
    },
    4: {
      type: Number,
      default: 0
    },
    5: {
      type: Number,
      default: 0
    },
    6: {
      type: Number,
      default: 0
    },
    7: {
      type: Number,
      default: 0
    },
    8: {
      type: Number,
      default: 0
    },
    9: {
      type: Number,
      default: 0
    },
    10: {
      type: Number,
      default: 0
    },
    11: {
      type: Number,
      default: 0
    },
    12: {
      type: Number,
      default: 0
    },
    13: {
      type: Number,
      default: 0
    },
    14: {
      type: Number,
      default: 0
    },
    15: {
      type: Number,
      default: 0
    },
    16: {
      type: Number,
      default: 0
    },
    17: {
      type: Number,
      default: 0
    },
    18: {
      type: Number,
      default: 0
    },
    19: {
      type: Number,
      default: 0
    },
    20: {
      type: Number,
      default: 0
    },
    21: {
      type: Number,
      default: 0
    },
    22: {
      type: Number,
      default: 0
    },
    23: {
      type: Number,
      default: 0
    },
    24: {
      type: Number,
      default: 0
    },
    25: {
      type: Number,
      default: 0
    },
    26: {
      type: Number,
      default: 0
    },
    27: {
      type: Number,
      default: 0
    },
    28: {
      type: Number,
      default: 0
    },
    29: {
      type: Number,
      default: 0
    },
    30: {
      type: Number,
      default: 0
    },
    31: {
      type: Number,
      default: 0
    },
    32: {
      type: Number,
      default: 0
    },
    33: {
      type: Number,
      default: 0
    },
    34: {
      type: Number,
      default: 0
    },
    35: {
      type: Number,
      default: 0
    },
    36: {
      type: Number,
      default: 0
    },
    37: {
      type: Number,
      default: 0
    },
    38: {
      type: Number,
      default: 0
    },
    39: {
      type: Number,
      default: 0
    },
    40: {
      type: Number,
      default: 0
    },
    41: {
      type: Number,
      default: 0
    },
    42: {
      type: Number,
      default: 0
    },
    43: {
      type: Number,
      default: 0
    },
    44: {
      type: Number,
      default: 0
    },
    45: {
      type: Number,
      default: 0
    },
    46: {
      type: Number,
      default: 0
    },
    47: {
      type: Number,
      default: 0
    },
    48: {
      type: Number,
      default: 0
    },
    49: {
      type: Number,
      default: 0
    },
    50: {
      type: Number,
      default: 0
    },
    51: {
      type: Number,
      default: 0
    },
    52: {
      type: Number,
      default: 0
    },
    53: {
      type: Number,
      default: 0
    },
    54: {
      type: Number,
      default: 0
    },
    55: {
      type: Number,
      default: 0
    },
    56: {
      type: Number,
      default: 0
    },
    57: {
      type: Number,
      default: 0
    },
    58: {
      type: Number,
      default: 0
    },
    59: {
      type: Number,
      default: 0
    }
  },
  failures: {
    0: {
      type: Number,
      default: 0
    },
    1: {
      type: Number,
      default: 0
    },
    2: {
      type: Number,
      default: 0
    },
    3: {
      type: Number,
      default: 0
    },
    4: {
      type: Number,
      default: 0
    },
    5: {
      type: Number,
      default: 0
    },
    6: {
      type: Number,
      default: 0
    },
    7: {
      type: Number,
      default: 0
    },
    8: {
      type: Number,
      default: 0
    },
    9: {
      type: Number,
      default: 0
    },
    10: {
      type: Number,
      default: 0
    },
    11: {
      type: Number,
      default: 0
    },
    12: {
      type: Number,
      default: 0
    },
    13: {
      type: Number,
      default: 0
    },
    14: {
      type: Number,
      default: 0
    },
    15: {
      type: Number,
      default: 0
    },
    16: {
      type: Number,
      default: 0
    },
    17: {
      type: Number,
      default: 0
    },
    18: {
      type: Number,
      default: 0
    },
    19: {
      type: Number,
      default: 0
    },
    20: {
      type: Number,
      default: 0
    },
    21: {
      type: Number,
      default: 0
    },
    22: {
      type: Number,
      default: 0
    },
    23: {
      type: Number,
      default: 0
    },
    24: {
      type: Number,
      default: 0
    },
    25: {
      type: Number,
      default: 0
    },
    26: {
      type: Number,
      default: 0
    },
    27: {
      type: Number,
      default: 0
    },
    28: {
      type: Number,
      default: 0
    },
    29: {
      type: Number,
      default: 0
    },
    30: {
      type: Number,
      default: 0
    },
    31: {
      type: Number,
      default: 0
    },
    32: {
      type: Number,
      default: 0
    },
    33: {
      type: Number,
      default: 0
    },
    34: {
      type: Number,
      default: 0
    },
    35: {
      type: Number,
      default: 0
    },
    36: {
      type: Number,
      default: 0
    },
    37: {
      type: Number,
      default: 0
    },
    38: {
      type: Number,
      default: 0
    },
    39: {
      type: Number,
      default: 0
    },
    40: {
      type: Number,
      default: 0
    },
    41: {
      type: Number,
      default: 0
    },
    42: {
      type: Number,
      default: 0
    },
    43: {
      type: Number,
      default: 0
    },
    44: {
      type: Number,
      default: 0
    },
    45: {
      type: Number,
      default: 0
    },
    46: {
      type: Number,
      default: 0
    },
    47: {
      type: Number,
      default: 0
    },
    48: {
      type: Number,
      default: 0
    },
    49: {
      type: Number,
      default: 0
    },
    50: {
      type: Number,
      default: 0
    },
    51: {
      type: Number,
      default: 0
    },
    52: {
      type: Number,
      default: 0
    },
    53: {
      type: Number,
      default: 0
    },
    54: {
      type: Number,
      default: 0
    },
    55: {
      type: Number,
      default: 0
    },
    56: {
      type: Number,
      default: 0
    },
    57: {
      type: Number,
      default: 0
    },
    58: {
      type: Number,
      default: 0
    },
    59: {
      type: Number,
      default: 0
    }
  }

});

ModuleMetricSchema.plugin(timestamps);

ModuleMetricSchema.index({
  application: 1,
  environment: 1,
  timestampHour: 1
});

ModuleMetricSchema.index({
  application: 1,
  environment: 1,
  timestampHour: 1,
  moduleName: 1
});

mongoose.model('ModuleMetric', ModuleMetricSchema);
var ModuleMetric = mongoose.model('ModuleMetric');
BBPromise.promisifyAll(ModuleMetric);
BBPromise.promisifyAll(ModuleMetric.prototype);
exports.name = 'ModuleMetric';
exports.model = ModuleMetric;
<commit_msg>add total executions<commit_after>'use strict';
var mongoose = require('mongoose');
var ShortId = require('mongoose-shortid');
var timestamps = require('mongoose-timestamp');
var BBPromise = require('bluebird');
var Schema = mongoose.Schema;
var environments = ['live', 'test', 'dev'];
var ModuleMetricSchema = new Schema({
  schemaVersion: String,
  application: {
    type: ShortId,
    ref: 'Application',
    index: true,
    required: 'metrics must belong to an application'
  },
  lastFailure: String,
  environment: {
    type: String,
    enum: {
      values: environments,
      message: 'metrics tokens must belong to a valid environment'
    },
    required: 'metrics tokens must belong to a valid environment'
  },
  moduleName: String,
  timestampHour: Date,
  executionTime: Number,
  totalExecutions: Number,
  totalFailures: Number,
  totalTimeouts: Number,
  executions: {
    0: {
      type: Number,
      default: 0
    },
    1: {
      type: Number,
      default: 0
    },
    2: {
      type: Number,
      default: 0
    },
    3: {
      type: Number,
      default: 0
    },
    4: {
      type: Number,
      default: 0
    },
    5: {
      type: Number,
      default: 0
    },
    6: {
      type: Number,
      default: 0
    },
    7: {
      type: Number,
      default: 0
    },
    8: {
      type: Number,
      default: 0
    },
    9: {
      type: Number,
      default: 0
    },
    10: {
      type: Number,
      default: 0
    },
    11: {
      type: Number,
      default: 0
    },
    12: {
      type: Number,
      default: 0
    },
    13: {
      type: Number,
      default: 0
    },
    14: {
      type: Number,
      default: 0
    },
    15: {
      type: Number,
      default: 0
    },
    16: {
      type: Number,
      default: 0
    },
    17: {
      type: Number,
      default: 0
    },
    18: {
      type: Number,
      default: 0
    },
    19: {
      type: Number,
      default: 0
    },
    20: {
      type: Number,
      default: 0
    },
    21: {
      type: Number,
      default: 0
    },
    22: {
      type: Number,
      default: 0
    },
    23: {
      type: Number,
      default: 0
    },
    24: {
      type: Number,
      default: 0
    },
    25: {
      type: Number,
      default: 0
    },
    26: {
      type: Number,
      default: 0
    },
    27: {
      type: Number,
      default: 0
    },
    28: {
      type: Number,
      default: 0
    },
    29: {
      type: Number,
      default: 0
    },
    30: {
      type: Number,
      default: 0
    },
    31: {
      type: Number,
      default: 0
    },
    32: {
      type: Number,
      default: 0
    },
    33: {
      type: Number,
      default: 0
    },
    34: {
      type: Number,
      default: 0
    },
    35: {
      type: Number,
      default: 0
    },
    36: {
      type: Number,
      default: 0
    },
    37: {
      type: Number,
      default: 0
    },
    38: {
      type: Number,
      default: 0
    },
    39: {
      type: Number,
      default: 0
    },
    40: {
      type: Number,
      default: 0
    },
    41: {
      type: Number,
      default: 0
    },
    42: {
      type: Number,
      default: 0
    },
    43: {
      type: Number,
      default: 0
    },
    44: {
      type: Number,
      default: 0
    },
    45: {
      type: Number,
      default: 0
    },
    46: {
      type: Number,
      default: 0
    },
    47: {
      type: Number,
      default: 0
    },
    48: {
      type: Number,
      default: 0
    },
    49: {
      type: Number,
      default: 0
    },
    50: {
      type: Number,
      default: 0
    },
    51: {
      type: Number,
      default: 0
    },
    52: {
      type: Number,
      default: 0
    },
    53: {
      type: Number,
      default: 0
    },
    54: {
      type: Number,
      default: 0
    },
    55: {
      type: Number,
      default: 0
    },
    56: {
      type: Number,
      default: 0
    },
    57: {
      type: Number,
      default: 0
    },
    58: {
      type: Number,
      default: 0
    },
    59: {
      type: Number,
      default: 0
    }
  },
  timeouts: {
    0: {
      type: Number,
      default: 0
    },
    1: {
      type: Number,
      default: 0
    },
    2: {
      type: Number,
      default: 0
    },
    3: {
      type: Number,
      default: 0
    },
    4: {
      type: Number,
      default: 0
    },
    5: {
      type: Number,
      default: 0
    },
    6: {
      type: Number,
      default: 0
    },
    7: {
      type: Number,
      default: 0
    },
    8: {
      type: Number,
      default: 0
    },
    9: {
      type: Number,
      default: 0
    },
    10: {
      type: Number,
      default: 0
    },
    11: {
      type: Number,
      default: 0
    },
    12: {
      type: Number,
      default: 0
    },
    13: {
      type: Number,
      default: 0
    },
    14: {
      type: Number,
      default: 0
    },
    15: {
      type: Number,
      default: 0
    },
    16: {
      type: Number,
      default: 0
    },
    17: {
      type: Number,
      default: 0
    },
    18: {
      type: Number,
      default: 0
    },
    19: {
      type: Number,
      default: 0
    },
    20: {
      type: Number,
      default: 0
    },
    21: {
      type: Number,
      default: 0
    },
    22: {
      type: Number,
      default: 0
    },
    23: {
      type: Number,
      default: 0
    },
    24: {
      type: Number,
      default: 0
    },
    25: {
      type: Number,
      default: 0
    },
    26: {
      type: Number,
      default: 0
    },
    27: {
      type: Number,
      default: 0
    },
    28: {
      type: Number,
      default: 0
    },
    29: {
      type: Number,
      default: 0
    },
    30: {
      type: Number,
      default: 0
    },
    31: {
      type: Number,
      default: 0
    },
    32: {
      type: Number,
      default: 0
    },
    33: {
      type: Number,
      default: 0
    },
    34: {
      type: Number,
      default: 0
    },
    35: {
      type: Number,
      default: 0
    },
    36: {
      type: Number,
      default: 0
    },
    37: {
      type: Number,
      default: 0
    },
    38: {
      type: Number,
      default: 0
    },
    39: {
      type: Number,
      default: 0
    },
    40: {
      type: Number,
      default: 0
    },
    41: {
      type: Number,
      default: 0
    },
    42: {
      type: Number,
      default: 0
    },
    43: {
      type: Number,
      default: 0
    },
    44: {
      type: Number,
      default: 0
    },
    45: {
      type: Number,
      default: 0
    },
    46: {
      type: Number,
      default: 0
    },
    47: {
      type: Number,
      default: 0
    },
    48: {
      type: Number,
      default: 0
    },
    49: {
      type: Number,
      default: 0
    },
    50: {
      type: Number,
      default: 0
    },
    51: {
      type: Number,
      default: 0
    },
    52: {
      type: Number,
      default: 0
    },
    53: {
      type: Number,
      default: 0
    },
    54: {
      type: Number,
      default: 0
    },
    55: {
      type: Number,
      default: 0
    },
    56: {
      type: Number,
      default: 0
    },
    57: {
      type: Number,
      default: 0
    },
    58: {
      type: Number,
      default: 0
    },
    59: {
      type: Number,
      default: 0
    }
  },
  failures: {
    0: {
      type: Number,
      default: 0
    },
    1: {
      type: Number,
      default: 0
    },
    2: {
      type: Number,
      default: 0
    },
    3: {
      type: Number,
      default: 0
    },
    4: {
      type: Number,
      default: 0
    },
    5: {
      type: Number,
      default: 0
    },
    6: {
      type: Number,
      default: 0
    },
    7: {
      type: Number,
      default: 0
    },
    8: {
      type: Number,
      default: 0
    },
    9: {
      type: Number,
      default: 0
    },
    10: {
      type: Number,
      default: 0
    },
    11: {
      type: Number,
      default: 0
    },
    12: {
      type: Number,
      default: 0
    },
    13: {
      type: Number,
      default: 0
    },
    14: {
      type: Number,
      default: 0
    },
    15: {
      type: Number,
      default: 0
    },
    16: {
      type: Number,
      default: 0
    },
    17: {
      type: Number,
      default: 0
    },
    18: {
      type: Number,
      default: 0
    },
    19: {
      type: Number,
      default: 0
    },
    20: {
      type: Number,
      default: 0
    },
    21: {
      type: Number,
      default: 0
    },
    22: {
      type: Number,
      default: 0
    },
    23: {
      type: Number,
      default: 0
    },
    24: {
      type: Number,
      default: 0
    },
    25: {
      type: Number,
      default: 0
    },
    26: {
      type: Number,
      default: 0
    },
    27: {
      type: Number,
      default: 0
    },
    28: {
      type: Number,
      default: 0
    },
    29: {
      type: Number,
      default: 0
    },
    30: {
      type: Number,
      default: 0
    },
    31: {
      type: Number,
      default: 0
    },
    32: {
      type: Number,
      default: 0
    },
    33: {
      type: Number,
      default: 0
    },
    34: {
      type: Number,
      default: 0
    },
    35: {
      type: Number,
      default: 0
    },
    36: {
      type: Number,
      default: 0
    },
    37: {
      type: Number,
      default: 0
    },
    38: {
      type: Number,
      default: 0
    },
    39: {
      type: Number,
      default: 0
    },
    40: {
      type: Number,
      default: 0
    },
    41: {
      type: Number,
      default: 0
    },
    42: {
      type: Number,
      default: 0
    },
    43: {
      type: Number,
      default: 0
    },
    44: {
      type: Number,
      default: 0
    },
    45: {
      type: Number,
      default: 0
    },
    46: {
      type: Number,
      default: 0
    },
    47: {
      type: Number,
      default: 0
    },
    48: {
      type: Number,
      default: 0
    },
    49: {
      type: Number,
      default: 0
    },
    50: {
      type: Number,
      default: 0
    },
    51: {
      type: Number,
      default: 0
    },
    52: {
      type: Number,
      default: 0
    },
    53: {
      type: Number,
      default: 0
    },
    54: {
      type: Number,
      default: 0
    },
    55: {
      type: Number,
      default: 0
    },
    56: {
      type: Number,
      default: 0
    },
    57: {
      type: Number,
      default: 0
    },
    58: {
      type: Number,
      default: 0
    },
    59: {
      type: Number,
      default: 0
    }
  }

});

ModuleMetricSchema.plugin(timestamps);

ModuleMetricSchema.index({
  application: 1,
  environment: 1,
  timestampHour: 1
});

ModuleMetricSchema.index({
  application: 1,
  environment: 1,
  timestampHour: 1,
  moduleName: 1
});

mongoose.model('ModuleMetric', ModuleMetricSchema);
var ModuleMetric = mongoose.model('ModuleMetric');
BBPromise.promisifyAll(ModuleMetric);
BBPromise.promisifyAll(ModuleMetric.prototype);
exports.name = 'ModuleMetric';
exports.model = ModuleMetric;
<|endoftext|>


<commit_before>'use strict';

const OperationBase = require('./operation').OperationBase;
const resolveReadPreference = require('../utils').resolveReadPreference;

class CommandOperationV2 extends OperationBase {
  constructor(parent, options) {
    super(options);

    this.ns = parent.s.namespace.withCollection('$cmd');
    this.readPreference = resolveReadPreference(parent, options);
    this.readConcern = resolveReadConcern(parent, options);
    this.writeConcern = resolveWriteConcern(parent, options);

    // TODO(NODE-2056): make logger another "inheritable" property
    if (parent.s.logger) {
      this.logger = parent.s.logger;
    } else if (parent.s.db && parent.s.db.logger) {
      this.logger = parent.s.db.logger;
    }
  }

  executeCommand(server, cmd, callback) {
    if (this.logger && this.logger.isDebug()) {
      this.logger.debug(`executing command ${JSON.stringify(cmd)} against ${this.ns}`);
    }

    server.command(this.ns.toString(), cmd, this.options, (err, result) => {
      if (err) {
        callback(err, null);
        return;
      }

      // full response was requested
      if (this.options.full) {
        callback(null, result);
        return;
      }

      callback(null, result.result);
    });
  }
}

function resolveWriteConcern(parent, options) {
  return options.writeConcern || parent.writeConcern;
}

function resolveReadConcern(parent, options) {
  return options.readConcern || parent.readConcern;
}

module.exports = CommandOperationV2;
<commit_msg>feat: support explain operations in `CommandOperationV2`<commit_after>'use strict';

const OperationBase = require('./operation').OperationBase;
const resolveReadPreference = require('../utils').resolveReadPreference;

class CommandOperationV2 extends OperationBase {
  constructor(parent, options) {
    super(options);

    this.ns = parent.s.namespace.withCollection('$cmd');
    this.readPreference = resolveReadPreference(parent, this.options);
    this.readConcern = resolveReadConcern(parent, this.options);
    this.writeConcern = resolveWriteConcern(parent, this.options);
    this.explain = false;

    // TODO(NODE-2056): make logger another "inheritable" property
    if (parent.s.logger) {
      this.logger = parent.s.logger;
    } else if (parent.s.db && parent.s.db.logger) {
      this.logger = parent.s.db.logger;
    }
  }

  executeCommand(server, cmd, callback) {
    if (this.logger && this.logger.isDebug()) {
      this.logger.debug(`executing command ${JSON.stringify(cmd)} against ${this.ns}`);
    }

    let fullResponse = this.options.full;
    if (this.explain) {
      cmd = { explain: cmd };
      fullResponse = false;
    }

    server.command(this.ns.toString(), cmd, this.options, (err, result) => {
      if (err) {
        callback(err, null);
        return;
      }

      if (fullResponse) {
        callback(null, result);
        return;
      }

      callback(null, result.result);
    });
  }
}

function resolveWriteConcern(parent, options) {
  return options.writeConcern || parent.writeConcern;
}

function resolveReadConcern(parent, options) {
  return options.readConcern || parent.readConcern;
}

module.exports = CommandOperationV2;
<|endoftext|>


<commit_before>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 * Two-Pass output engine.
 *
 * (First pass) constructs contexts tree, loads everything that is needed, applies minimal bindings, applies routes (when router is loaded), etc.
 * and wait for root context stabilisation before (Second pass) applying pure string outut.
 *
 * Take a look to string-ouput engine docs.
 *
 * This is for COMPLETE isomorphism : you write your application with browser and Dom in head,
 * with complex context's structure that lazzy load datas depending on routes, environnements, (non-dom-)events, binds, etc.
 * And you output it seemlesly server side, as pure string, without worying about datas loads and initialisation sequences.
 */
var utils = require('../utils'),
	Template = require('../template'),
	Context = require('../context').Context,
	stringEngine = require('./string'),
	SOD = stringEngine.SOD;

var firstMethods = {

	// ____________________________________ WITH
	with: function(context, args, stack) {
		var path = args[0],
			template = args[1],
			ctx = new Context(typeof path === 'string' ? context.get(path) : path, context, path);
		stack.push(ctx);
		firstPass(template, ctx, stack);
	},
	//________________________________ Conditonal node rendering
	agoraView: function(context, args, stack) {
		// var channel = args[0],
		// template = args[1];
		// console.warn('agoraView has not been implemented yet for twopass engine.');
	},

	mountIf: function(context, args, stack) {
		var ok, condition = args[0],
			successTempl = args[1],
			data = { h_mountIf: true, stack: [] };
		stack.push(data);
		var exec = function(ok) {
			data.ok = ok;
			if (ok) {
				if (!data.seenSuccess)
					firstPass(successTempl, context, data.stack);
				data.seenSuccess = true;
			}
		};
		ok = condition;
		if (condition && condition.__interpolable__) {
			ok = condition.output(context);
			condition.subscribeTo(context, exec);
		} else if (typeof condition === 'function')
			ok = condition.call(this, context);
		exec(ok);
	},

	if: function(context, args, stack) {
		var condition = args[0],
			ok = condition,
			successTempl = args[1],
			failTempl = args[2];
		if (condition && condition.__interpolable__)
			ok = condition.output(context);
		else if (typeof condition === 'function')
			ok = condition.call(this, context);
		stack.push({ ok: ok, h_if: true, condition: condition });
		if (ok)
			firstPass(successTempl, context, stack);
		else if (failTempl)
			firstPass(failTempl, context, stack);
	},
	switch: function(context, args, stack) {
		var expression = args[0],
			dico = args[1],
			seen = {};

		stack.push(seen);

		function switchTempl(value) {
			value = value || 'default';
			var templ = dico[value];
			if (templ) {
				if (!seen[value]) {
					seen[value] = [];
					firstPass(templ, context, seen[value]);
				}
				seen.__currentStack = seen[value];
				seen.__current = templ;
			}
		}
		if (expression.__interpolable__) {
			expression.subscribeTo(context, function(value) {
				switchTempl(value);
			});
			switchTempl(expression.output(context));
		} else if (typeof expression === 'function')
			switchTempl(expression(context));
		else
			switchTempl(expression);
	},
	//_________________________________________ EACH
	each: function(context, args, stack) {
		var path = args[0],
			template = args[1],
			emptyTemplate = args[2],
			emptyInitialised = false,
			data = path,
			contexts = [],
			data = { contexts: contexts, emptyStack: [] };

		// store local contexts array in parent
		stack.push(data);

		var updateArray = function(value, type, path, index) {
			// on array update : produce or maintain associated local contexts array
			var ctx;
			switch (type) {
				case 'reset':
				case 'set':

					if (!value || !value.length) {
						if (emptyTemplate) {
							if (!emptyInitialised)
								firstPass(emptyTemplate, context, data.emptyStack); // traverse empty template with firstPass
							emptyInitialised = true;
						}
						return;
					}

					var j = 0;
					for (var len = value.length; j < len; ++j) // reset existing or create new ctx
					{
						if (contexts[j]) // reset existing
							contexts[j].reset(value[j]);
						else { // create new ctx
							ctx = new Context(value[j], context);
							ctx._stack = [];
							contexts.push(ctx);
							firstPass(template, ctx, ctx._stack); // traverse child template with firstPass
						}
					}
					if (j < contexts.length) // remove additional ctx that is not used any more
					{
						for (var i = j, len = contexts.length; i < len; ++i)
							contexts[i].destroy();
						contexts.splice(j);
					}
					break;
				case 'removeAt':
					contexts[index].destroy();
					contexts.splice(index, 1);
					break;
				case 'push':
					ctx = new Context(value, context);
					ctx._stack = [];
					contexts.push(ctx);
					firstPass(template, ctx, ctx._stack);
					break;
			}
		};

		if (typeof path === 'string') {
			context.subscribe(path, updateArray);
			context.subscribe(path + '.*', function(value, type, path, key) {
				// on array's item update
				var ctx = contexts[key];
				if (ctx)
					return ctx.reset(value); // update associated context
			});
			data = context.get(path);
		}
		updateArray(data, 'set');
	},
	eachTemplates: function(context, descriptor, args, stack) {
		var templates = args[0],
			handler = args[1];
		templates.forEach(function(templ) {
			firstPass(handler ? handler(templ) : templ, context, stack);
		});
	},
	//________________________________ TAGS
	tag: function(context, args, stack) {
		var name = args[0],
			template = args[1];
		if (template)
			firstPass(template, context, stack); // traverse tag template with frstPass
	},
	//_________________________________ CLIENT/SERVER
	client: function(context, args, stack) {
		if (context.env.data.isServer)
			return;
		firstPass(args[0], context, stack); // traverse client template with frstPass
	},
	server: function(context, args, stack) {
		if (!context.env.data.isServer)
			return;
		firstPass(args[0], context, stack); // traverse server template with frstPass
	},
	//_________________ CONTAINER
	container: function(context, args, stack) {
		var opt = args[0],
			template = args[1];
		firstPass(template, context, stack);
	},
	//_______________________________ SUSPEND RENDER
	suspendUntil: function(context, args, stack) {
		var xpr = args[0],
			index = args[1],
			templ = args[2],
			val = xpr.__interpolable__ ? xpr.output(context) : xpr,
			rest = new Template(templ._queue.slice(index)),
			instance,
			obj = {
				val: val,
				rest: rest,
				stack: []
			};
		stack.push(obj);
		if (val)
			firstPass(rest, context, obj.stack);
		else if (xpr.__interpolable__)
			instance = xpr.subscribeTo(context, function(value) {
				if (value) {
					obj.val = value;
					instance.destroy();
					firstPass(rest, context, obj.stack);
				}
			});
	},
	//_________________________________ local context management
	newContext: function(context, args, stack) {
		var ctx = new Context(args[0], args[1] || context);
		stack.push(ctx);
		return ctx;
	}
};

var secondMethods = {
	//_______________________________ SUSPEND RENDER
	suspendUntil: function(context, descriptor, args, stack) {
		var obj = stack.shift();
		if (obj.val)
			secondPass(obj.rest, context, descriptor, obj.stack);
	},
	//_________________________________ local context management
	newContext: function(context, descriptor, args, stack) {
		descriptor.context = stack.shift();
	},
	// ____________________________________ WITH
	with: function(context, descriptor, args, stack) {
		var path = args[0],
			template = args[1],
			ctx = stack.shift(),
			oldCtx = descriptor.context;
		descriptor.context = ctx;
		secondPass(template, ctx, descriptor, stack);
		descriptor.context = oldCtx;
	},
	//_________________________________________ EACH
	each: function(context, descriptor, args, stack) {
		var data = stack.shift(),
			template = args[1],
			emptyTemplate = args[2];
		if (!data.contexts.length) {
			if (emptyTemplate)
				secondPass(emptyTemplate, context, descriptor, data.emptyStack);
		} else
			for (var i = 0, len = data.contexts.length; i < len; ++i) {
				var sod = new SOD();
				secondPass(template, data.contexts[i], sod, data.contexts[i]._stack);
				descriptor.children += sod.children;
			}
	},
	eachTemplates: function(context, descriptor, args, stack) {
		var templates = args[0],
			handler = args[1];
		templates.forEach(function(templ) {
			secondPass(handler ? handler(templ) : templ, context, descriptor, stack);
		});
	},
	switch: function(context, descriptor, args) {
		var data = stack.shift();
		templ = data.__current;
		if (templ) {
			var sod = new SOD();
			secondPass(templ, context, sod, data.__currentStack);
			if (sod.children)
				descriptor.children += sod.children;
		}
	},
	//________________________________ Conditonal node rendering
	if: function(context, descriptor, args, stack) {
		var data = stack.shift(),
			templ = args[1],
			failTempl = args[2];
		if (data.ok)
			secondPass(templ, context, descriptor, stack);
		else if (failTempl)
			secondPass(failTempl, context, descriptor, stack);
	},
	mountIf: function(context, descriptor, args, stack) {
		var data = stack.shift(),
			successTempl = args[1];
		if (!data.ok)
			return;
		var sod = new SOD();
		secondPass(successTempl, context, sod, data.stack);
		if (sod.children)
			descriptor.children += sod.children;
	},
	//_______________ container
	container: function(context, descriptor, args, stack) {
		var opt = args[0],
			template = args[1],
			sod = new SOD();
		secondPass(template, context, sod, stack);
		if (sod.children)
			descriptor.children += sod.children;
	},
	//________________________________ TAGS
	tag: function(context, descriptor, args, stack) {
		var name = args[0],
			template = args[1],
			newDescriptor = new SOD();
		if (template)
			secondPass(template, context, newDescriptor, stack);
		utils.tagOutput(descriptor, newDescriptor, name);
	},
	//_________________________________ CLIENT/SERVER
	client: function(context, descriptor, args, stack) {
		if (context.env.data.isServer)
			return;
		secondPass(args[0], context, descriptor, stack);
	},
	server: function(context, descriptor, args, stack) {
		if (!context.env.data.isServer)
			return;
		secondPass(args[0], context, descriptor, stack);
	},
	agoraView: function(context, args, stack) {
		// var channel = args[0],
		// template = args[1];
		// console.warn('agoraView has not been implemented yet for twopass engine.');
	}
};

function firstPass(template, context, stack) {
	var queue = template._queue,
		handler = queue[0],
		newContext,
		index = 0,
		ctx,
		f;
	while (handler) {
		f = null;
		switch (handler.type) {
			case '*':
				f = firstMethods[handler.handler];
				break;
			case 'context':
			case 'firstPass':
				f = handler.handler;
				break;
			case 'custom':
				f = handler.handler.firstPass;
				break;
		}
		if (!f) {
			handler = queue[++index];
			continue;
		}
		if (f.__yTemplate__)
			firstPass(f, newContext || context, stack);
		else
			ctx = f(newContext || context, handler.args, stack);
		if (ctx && ctx.__yContext__)
			newContext = ctx;
		if (handler.suspendAfter)
			break;
		handler = queue[++index];
	}
}

function secondPass(template, context, descriptor, stack) {
	var queue = template._queue,
		handler = queue[0],
		index = 0,
		f;
	while (handler) {
		f = null;
		switch (handler.type) {
			case '*':
				f = secondMethods[handler.handler] || stringEngine[handler.handler];
				break;
			case 'string':
			case 'secondPass':
				f = handler.handler;
				break;
			case 'custom':
				f = handler.handler.secondPass;
				break;
		}
		if (!f) {
			handler = queue[++index];
			continue;
		}
		if (f.__yTemplate__)
			secondPass(f, descriptor.context || context, descriptor, stack);
		else
			f(descriptor.context || context, descriptor, handler.args, stack);
		if (handler.suspendAfter)
			break;
		handler = queue[++index];
	}
}

Template.prototype.twopass = function(context) {
	var self = this,
		stack = [];
	context = context || new Context();
	firstPass(this, context, stack); // apply first pass : construct contexts
	// wait for context stabilisation
	return context.stabilised()
		.then(function(context) {
			// then apply second pass : render to string
			var descriptor = new SOD();
			secondPass(self, context, descriptor, stack);
			return descriptor.children;
		});
};

module.exports = {
	firstMethods: firstMethods,
	secondMethods: secondMethods,
	firstPass: firstPass,
	secondPass: secondPass
};
<commit_msg>twopass engine : debug each<commit_after>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 * Two-Pass output engine.
 *
 * (First pass) constructs contexts tree, loads everything that is needed, applies minimal bindings, applies routes (when router is loaded), etc.
 * and wait for root context stabilisation before (Second pass) applying pure string outut.
 *
 * Take a look to string-ouput engine docs.
 *
 * This is for COMPLETE isomorphism : you write your application with browser and Dom in head,
 * with complex context's structure that lazzy load datas depending on routes, environnements, (non-dom-)events, binds, etc.
 * And you output it seemlesly server side, as pure string, without worying about datas loads and initialisation sequences.
 */
var utils = require('../utils'),
	Template = require('../template'),
	Context = require('../context').Context,
	stringEngine = require('./string'),
	SOD = stringEngine.SOD;

var firstMethods = {

	// ____________________________________ WITH
	with: function(context, args, stack) {
		var path = args[0],
			template = args[1],
			ctx = new Context(typeof path === 'string' ? context.get(path) : path, context, path);
		stack.push(ctx);
		firstPass(template, ctx, stack);
	},
	//________________________________ Conditonal node rendering
	agoraView: function(context, args, stack) {
		// var channel = args[0],
		// template = args[1];
		// console.warn('agoraView has not been implemented yet for twopass engine.');
	},

	mountIf: function(context, args, stack) {
		var ok, condition = args[0],
			successTempl = args[1],
			data = { h_mountIf: true, stack: [] };
		stack.push(data);
		var exec = function(ok) {
			data.ok = ok;
			if (ok) {
				if (!data.seenSuccess)
					firstPass(successTempl, context, data.stack);
				data.seenSuccess = true;
			}
		};
		ok = condition;
		if (condition && condition.__interpolable__) {
			ok = condition.output(context);
			condition.subscribeTo(context, exec);
		} else if (typeof condition === 'function')
			ok = condition.call(this, context);
		exec(ok);
	},

	if: function(context, args, stack) {
		var condition = args[0],
			ok = condition,
			successTempl = args[1],
			failTempl = args[2];
		if (condition && condition.__interpolable__)
			ok = condition.output(context);
		else if (typeof condition === 'function')
			ok = condition.call(this, context);
		stack.push({ ok: ok, h_if: true, condition: condition });
		if (ok)
			firstPass(successTempl, context, stack);
		else if (failTempl)
			firstPass(failTempl, context, stack);
	},
	switch: function(context, args, stack) {
		var expression = args[0],
			dico = args[1],
			seen = {};

		stack.push(seen);

		function switchTempl(value) {
			value = value || 'default';
			var templ = dico[value];
			if (templ) {
				if (!seen[value]) {
					seen[value] = [];
					firstPass(templ, context, seen[value]);
				}
				seen.__currentStack = seen[value];
				seen.__current = templ;
			}
		}
		if (expression.__interpolable__) {
			expression.subscribeTo(context, function(value) {
				switchTempl(value);
			});
			switchTempl(expression.output(context));
		} else if (typeof expression === 'function')
			switchTempl(expression(context));
		else
			switchTempl(expression);
	},
	//_________________________________________ EACH
	each: function(context, args, stack) {
		var path = args[0],
			template = args[1],
			emptyTemplate = args[2],
			emptyInitialised = false,
			contexts = [],
			value = path,
			data = { contexts: contexts, emptyStack: [] };

		// store local contexts array in parent
		stack.push(data);

		var updateArray = function(value, type, path, index) {
			// on array update : produce or maintain associated local contexts array
			var ctx;
			switch (type) {
				case 'reset':
				case 'set':

					if (!value || !value.length) {
						if (emptyTemplate) {
							if (!emptyInitialised)
								firstPass(emptyTemplate, context, data.emptyStack); // traverse empty template with firstPass
							emptyInitialised = true;
						}
						return;
					}

					var j = 0;
					for (var len = value.length; j < len; ++j) // reset existing or create new ctx
					{
						if (contexts[j]) // reset existing
							contexts[j].reset(value[j]);
						else { // create new ctx
							ctx = new Context(value[j], context);
							ctx._stack = [];
							contexts.push(ctx);
							firstPass(template, ctx, ctx._stack); // traverse child template with firstPass
						}
					}
					if (j < contexts.length) // remove additional ctx that is not used any more
					{
						for (var i = j, len = contexts.length; i < len; ++i)
							contexts[i].destroy();
						contexts.splice(j);
					}
					break;
				case 'removeAt':
					contexts[index].destroy();
					contexts.splice(index, 1);
					break;
				case 'push':
					ctx = new Context(value, context);
					ctx._stack = [];
					contexts.push(ctx);
					firstPass(template, ctx, ctx._stack);
					break;
			}
		};

		if (typeof path === 'string') {
			context.subscribe(path, updateArray);
			context.subscribe(path + '.*', function(value, type, path, key) {
				// on array's item update
				var ctx = contexts[key];
				if (ctx)
					return ctx.reset(value); // update associated context
			});
			value = context.get(path);
		}
		updateArray(value, 'set');
	},
	eachTemplates: function(context, descriptor, args, stack) {
		var templates = args[0],
			handler = args[1];
		templates.forEach(function(templ) {
			firstPass(handler ? handler(templ) : templ, context, stack);
		});
	},
	//________________________________ TAGS
	tag: function(context, args, stack) {
		var name = args[0],
			template = args[1];
		if (template)
			firstPass(template, context, stack); // traverse tag template with frstPass
	},
	//_________________________________ CLIENT/SERVER
	client: function(context, args, stack) {
		if (context.env.data.isServer)
			return;
		firstPass(args[0], context, stack); // traverse client template with frstPass
	},
	server: function(context, args, stack) {
		if (!context.env.data.isServer)
			return;
		firstPass(args[0], context, stack); // traverse server template with frstPass
	},
	//_________________ CONTAINER
	container: function(context, args, stack) {
		var opt = args[0],
			template = args[1];
		firstPass(template, context, stack);
	},
	//_______________________________ SUSPEND RENDER
	suspendUntil: function(context, args, stack) {
		var xpr = args[0],
			index = args[1],
			templ = args[2],
			val = xpr.__interpolable__ ? xpr.output(context) : xpr,
			rest = new Template(templ._queue.slice(index)),
			instance,
			obj = {
				val: val,
				rest: rest,
				stack: []
			};
		stack.push(obj);
		if (val)
			firstPass(rest, context, obj.stack);
		else if (xpr.__interpolable__)
			instance = xpr.subscribeTo(context, function(value) {
				if (value) {
					obj.val = value;
					instance.destroy();
					firstPass(rest, context, obj.stack);
				}
			});
	},
	//_________________________________ local context management
	newContext: function(context, args, stack) {
		var ctx = new Context(args[0], args[1] || context);
		stack.push(ctx);
		return ctx;
	}
};

var secondMethods = {
	//_______________________________ SUSPEND RENDER
	suspendUntil: function(context, descriptor, args, stack) {
		var obj = stack.shift();
		if (obj.val)
			secondPass(obj.rest, context, descriptor, obj.stack);
	},
	//_________________________________ local context management
	newContext: function(context, descriptor, args, stack) {
		descriptor.context = stack.shift();
	},
	// ____________________________________ WITH
	with: function(context, descriptor, args, stack) {
		var path = args[0],
			template = args[1],
			ctx = stack.shift(),
			oldCtx = descriptor.context;
		descriptor.context = ctx;
		secondPass(template, ctx, descriptor, stack);
		descriptor.context = oldCtx;
	},
	//_________________________________________ EACH
	each: function(context, descriptor, args, stack) {
		var data = stack.shift(),
			template = args[1],
			emptyTemplate = args[2];
		if (!data.contexts.length) {
			if (emptyTemplate)
				secondPass(emptyTemplate, context, descriptor, data.emptyStack);
		} else
			for (var i = 0, len = data.contexts.length; i < len; ++i) {
				var sod = new SOD();
				secondPass(template, data.contexts[i], sod, data.contexts[i]._stack);
				descriptor.children += sod.children;
			}
	},
	eachTemplates: function(context, descriptor, args, stack) {
		var templates = args[0],
			handler = args[1];
		templates.forEach(function(templ) {
			secondPass(handler ? handler(templ) : templ, context, descriptor, stack);
		});
	},
	switch: function(context, descriptor, args) {
		var data = stack.shift();
		templ = data.__current;
		if (templ) {
			var sod = new SOD();
			secondPass(templ, context, sod, data.__currentStack);
			if (sod.children)
				descriptor.children += sod.children;
		}
	},
	//________________________________ Conditonal node rendering
	if: function(context, descriptor, args, stack) {
		var data = stack.shift(),
			templ = args[1],
			failTempl = args[2];
		if (data.ok)
			secondPass(templ, context, descriptor, stack);
		else if (failTempl)
			secondPass(failTempl, context, descriptor, stack);
	},
	mountIf: function(context, descriptor, args, stack) {
		var data = stack.shift(),
			successTempl = args[1];
		if (!data.ok)
			return;
		var sod = new SOD();
		secondPass(successTempl, context, sod, data.stack);
		if (sod.children)
			descriptor.children += sod.children;
	},
	//_______________ container
	container: function(context, descriptor, args, stack) {
		var opt = args[0],
			template = args[1],
			sod = new SOD();
		secondPass(template, context, sod, stack);
		if (sod.children)
			descriptor.children += sod.children;
	},
	//________________________________ TAGS
	tag: function(context, descriptor, args, stack) {
		var name = args[0],
			template = args[1],
			newDescriptor = new SOD();
		if (template)
			secondPass(template, context, newDescriptor, stack);
		utils.tagOutput(descriptor, newDescriptor, name);
	},
	//_________________________________ CLIENT/SERVER
	client: function(context, descriptor, args, stack) {
		if (context.env.data.isServer)
			return;
		secondPass(args[0], context, descriptor, stack);
	},
	server: function(context, descriptor, args, stack) {
		if (!context.env.data.isServer)
			return;
		secondPass(args[0], context, descriptor, stack);
	},
	agoraView: function(context, args, stack) {
		// var channel = args[0],
		// template = args[1];
		// console.warn('agoraView has not been implemented yet for twopass engine.');
	}
};

function firstPass(template, context, stack) {
	var queue = template._queue,
		handler = queue[0],
		newContext,
		index = 0,
		ctx,
		f;
	while (handler) {
		f = null;
		switch (handler.type) {
			case '*':
				f = firstMethods[handler.handler];
				break;
			case 'context':
			case 'firstPass':
				f = handler.handler;
				break;
			case 'custom':
				f = handler.handler.firstPass;
				break;
		}
		if (!f) {
			handler = queue[++index];
			continue;
		}
		if (f.__yTemplate__)
			firstPass(f, newContext || context, stack);
		else
			ctx = f(newContext || context, handler.args, stack);
		if (ctx && ctx.__yContext__)
			newContext = ctx;
		if (handler.suspendAfter)
			break;
		handler = queue[++index];
	}
}

function secondPass(template, context, descriptor, stack) {
	var queue = template._queue,
		handler = queue[0],
		index = 0,
		f;
	while (handler) {
		f = null;
		switch (handler.type) {
			case '*':
				f = secondMethods[handler.handler] || stringEngine[handler.handler];
				break;
			case 'string':
			case 'secondPass':
				f = handler.handler;
				break;
			case 'custom':
				f = handler.handler.secondPass;
				break;
		}
		if (!f) {
			handler = queue[++index];
			continue;
		}
		if (f.__yTemplate__)
			secondPass(f, descriptor.context || context, descriptor, stack);
		else
			f(descriptor.context || context, descriptor, handler.args, stack);
		if (handler.suspendAfter)
			break;
		handler = queue[++index];
	}
}

Template.prototype.twopass = function(context) {
	var self = this,
		stack = [];
	context = context || new Context();
	firstPass(this, context, stack); // apply first pass : construct contexts
	// wait for context stabilisation
	return context.stabilised()
		.then(function(context) {
			// then apply second pass : render to string
			var descriptor = new SOD();
			secondPass(self, context, descriptor, stack);
			return descriptor.children;
		});
};

module.exports = {
	firstMethods: firstMethods,
	secondMethods: secondMethods,
	firstPass: firstPass,
	secondPass: secondPass
};
<|endoftext|>


<commit_before>var utils = require('../utils'),
	env = require('../env'),
	Template = require('../template'),
	Context = require('../context'),
	stringEngine = require('./string'),
	SOD = stringEngine.SOD;

var firstMethods = {
	//_________________________________ local context management
	context: function(context, args) {
		var value = args[0],
			parentPath = args[1];
		// produce local context and store it in parent
		var childContext = new Context(parentPath ? null : value, context, parentPath ? parentPath : null);
		(context.children = context.children || []).push(childContext);
		return childContext;
	},
	// ____________________________________ WITH
	with: function(context, descriptor, args) {
		var path = args[0],
			template = args[1],
			// produce local context and store it in parent
			ctx = new Context(typeof path === 'string' ? context.get(path) : path, context, path);
		(context.children = context.children || []).push(childContext);
	},
	//________________________________ Conditonal node rendering
	if: function(context, args) {
		var ok, condition = args[0],
			successTempl = args[1],
			failTempl = args[2];
		var exec = function(type, path, ok) {
			if (ok)
				firstPass(successTempl, context);
			else if (failTempl)
				firstPass(failTempl, context);
		};
		if (condition && condition.__interpolable__) {
			ok = condition.output(context);
			condition.subscribeTo(context, exec);
		} else if (typeof condition === 'function')
			ok = condition.call(this, context);
		exec('set', null, ok);
	},
	//_________________________________________ EACH
	each: function(context, args) {
		var path = args[0],
			template = args[1],
			emptyTemplate = args[2],
			emptyInitialised = false,
			data = path,
			contexts = [];

		var updateArray = function(type, path, value, index) {
			// on array update : produce or maintain associated local contexts array
			var ctx, ctxs = contexts;
			switch (type) {
				case 'reset':
				case 'set':

					if (!value.length && !emptyInitialised)
						firstPass(emptyTemplate, context); // traverse empty template with firstPass

					var j = 0;
					for (var len = value.length; j < len; ++j) // reset existing or create new ctx
					{
						if (ctxs[j]) // reset existing
							ctxs[j].reset(value[j]);
						else { // create new ctx
							ctx = new Context(value[j], this);
							ctxs.push(ctx);
							firstPass(template, ctx); // traverse child template with firstPass
						}
					}
					if (j < ctxs.length) // remove additional ctx that is not used any more
					{
						for (var i = j, len = ctxs.length; i < len; ++i)
							ctxs[i].destroy();
						ctxs.splice(j);
					}
					break;
				case 'removeAt':
					ctxs.splice(index, 1);
					break;
				case 'push':
					ctx = new Context(value, this)
					ctxs.push(ctx);
					firstPass(template, ctx);
					break;
			}
		};

		if (typeof path === 'string') {
			context.subscribe(path, updateArray);
			context.subscribe(path + '.*', function(type, path, value, key) {
				// on array's item update
				var ctx = contexts[key];
				if (ctx)
					return ctx.reset(value); // update associated context
			});
			data = context.get(path);
		}
		if (data)
			updateArray('set', path, data);
		// store local contexts array in parent
		(context.children = context.children || []).push(contexts);
	},
	//________________________________ TAGS
	tag: function(context, args) {
		var name = args[0],
			template = args[1];
		if (template)
			firstPass(template, context); // traverse tag template with frstPass
	},
	//_________________________________ CLIENT/SERVER
	client: function(context, args) {
		if (env.isServer)
			return;
		firstPass(args[0], context); // traverse client template with frstPass
	},
	server: function(context, args) {
		if (!env.isServer)
			return;
		firstPass(args[0], context); // traverse server template with frstPass
	}
};

var secondMethods = {
	//_________________________________ local context management
	context: function(context, descriptor) {
		if (context.children) // catch context produced in firstPass
			descriptor.context = context.children.shift();
	},
	// ____________________________________ WITH
	with: function(context, descriptor, args) {
		if (!context.children)
			return;
		var path = args[0],
			template = args[1],
			ctx = context.children.shift(); // catch context produced in firstPass
		secondPass(template, ctx, descriptor);
	},
	//_________________________________________ EACH
	each: function(context, descriptor, args) {
		if (!context.children)
			return;
		var contexts = context.children.shift(); // catch contexts array produced in firstPass
		if (contexts && contexts.length) {
			var template = args[1],
				emptyTemplate = args[2];
			if (!contexts.length)
				secondPass(emptyTemplate, context, descriptor);
			else
				for (var i = 0, len = contexts.length; i < len; ++i)
					secondPass(template, contexts[i], descriptor);
		}
	},
	//________________________________ TAGS
	tag: function(context, descriptor, args) {
		var name = args[0],
			template = args[1],
			newDescriptor = new SOD();
		if (template)
			secondPass(template, context, newDescriptor);
		utils.tagOutput(descriptor, newDescriptor, name);
	},
	//________________________________ Conditonal node rendering
	if: function(context, descriptor, args) {
		var ok, condition = args[0],
			successTempl = args[1],
			failTempl = args[2];
		if (condition && condition.__interpolable__)
			ok = condition.output(context);
		else if (type === 'function')
			ok = condition.call(this, context);
		if (ok)
			secondPass(successTempl, context, descriptor);
		else if (failTempl)
			secondPass(failTempl, context, descriptor);
	},
	//_________________________________ CLIENT/SERVER
	client: function(context, descriptor, args) {
		if (env.isServer)
			return;
		secondPass(args[0], context, descriptor);
	},
	server: function(context, descriptor, args) {
		if (!env.isServer)
			return;
		secondPass(args[0], context, descriptor);
	},
	contentSwitch: null,
	cssSwitch: null
};

function secondPass(template, context, descriptor) {
	// apply string rendering only
	descriptor = descriptor ||  new SOD();
	var handler,
		f;
	for (var i = 0, len = template._queue.length; i < len; ++i) {
		handler = template._queue[i];
		if (handler.func) {
			if (handler.firstPass)
				continue;
			else if (handler.engineBlock)
				f = handler.engineBlock.twopass.second || handler.engineBlock.string;
			else
				f = handler.func;
		} else if (secondMethods[handler.name])
			f = secondMethods[handler.name];
		else
			f = stringEngine[handler.name];

		f(descriptor.context || context, descriptor, handler.args);
	}
}

function firstPass(template, context) {
	// apply contexts construction only
	var handler,
		f,
		newContext,
		ctx;
	for (var i = 0, len = template._queue.length; i < len; ++i) {
		handler = template._queue[i];
		if (handler.func) {
			if (!handler.firstPass)
				continue;
			else if (handler.engineBlock) {
				f = handler.engineBlock.twopass.first;
				if (!f)
					continue;
			} else
				f = handler.func;
		} else if (!firstMethods[handler.name])
			continue;
		else
			f = firstMethods[handler.name];
		ctx = f(newContext || context, handler.args);
		if (ctx && ctx.__yContext__)
			newContext = ctx;
	}
}

Template.prototype.twopass = function(context) {
	context = context || new Context();
	firstPass(this, context); // apply first pass : construct contexts
	var self = this;
	// wait for context stabilisation
	return context.stabilised().then(function(context) {
		// then apply second pass : render to string
		var descriptor = new SOD();
		secondPass(self, context, descriptor);
		return descriptor.children;
	});
};

module.exports = {
	firstMethods: firstMethods,
	secondMethods: secondMethods,
	firstPass: firstPass,
	secondPass: secondPass
};
<commit_msg>finalise engineBlock management<commit_after>var utils = require('../utils'),
	env = require('../env'),
	Template = require('../template'),
	Context = require('../context'),
	stringEngine = require('./string'),
	SOD = stringEngine.SOD;

var firstMethods = {
	//_________________________________ local context management
	context: function(context, args) {
		var value = args[0],
			parentPath = args[1];
		// produce local context and store it in parent
		var childContext = new Context(parentPath ? null : value, context, parentPath ? parentPath : null);
		(context.children = context.children || []).push(childContext);
		return childContext;
	},
	// ____________________________________ WITH
	with: function(context, descriptor, args) {
		var path = args[0],
			template = args[1],
			// produce local context and store it in parent
			ctx = new Context(typeof path === 'string' ? context.get(path) : path, context, path);
		(context.children = context.children || []).push(childContext);
	},
	//________________________________ Conditonal node rendering
	if: function(context, args) {
		var ok, condition = args[0],
			successTempl = args[1],
			failTempl = args[2];
		var exec = function(type, path, ok) {
			if (ok)
				firstPass(successTempl, context);
			else if (failTempl)
				firstPass(failTempl, context);
		};
		if (condition && condition.__interpolable__) {
			ok = condition.output(context);
			condition.subscribeTo(context, exec);
		} else if (typeof condition === 'function')
			ok = condition.call(this, context);
		exec('set', null, ok);
	},
	//_________________________________________ EACH
	each: function(context, args) {
		var path = args[0],
			template = args[1],
			emptyTemplate = args[2],
			emptyInitialised = false,
			data = path,
			contexts = [];

		var updateArray = function(type, path, value, index) {
			// on array update : produce or maintain associated local contexts array
			var ctx, ctxs = contexts;
			switch (type) {
				case 'reset':
				case 'set':

					if (!value.length && !emptyInitialised)
						firstPass(emptyTemplate, context); // traverse empty template with firstPass

					var j = 0;
					for (var len = value.length; j < len; ++j) // reset existing or create new ctx
					{
						if (ctxs[j]) // reset existing
							ctxs[j].reset(value[j]);
						else { // create new ctx
							ctx = new Context(value[j], this);
							ctxs.push(ctx);
							firstPass(template, ctx); // traverse child template with firstPass
						}
					}
					if (j < ctxs.length) // remove additional ctx that is not used any more
					{
						for (var i = j, len = ctxs.length; i < len; ++i)
							ctxs[i].destroy();
						ctxs.splice(j);
					}
					break;
				case 'removeAt':
					ctxs.splice(index, 1);
					break;
				case 'push':
					ctx = new Context(value, this)
					ctxs.push(ctx);
					firstPass(template, ctx);
					break;
			}
		};

		if (typeof path === 'string') {
			context.subscribe(path, updateArray);
			context.subscribe(path + '.*', function(type, path, value, key) {
				// on array's item update
				var ctx = contexts[key];
				if (ctx)
					return ctx.reset(value); // update associated context
			});
			data = context.get(path);
		}
		if (data)
			updateArray('set', path, data);
		// store local contexts array in parent
		(context.children = context.children || []).push(contexts);
	},
	//________________________________ TAGS
	tag: function(context, args) {
		var name = args[0],
			template = args[1];
		if (template)
			firstPass(template, context); // traverse tag template with frstPass
	},
	//_________________________________ CLIENT/SERVER
	client: function(context, args) {
		if (env.isServer)
			return;
		firstPass(args[0], context); // traverse client template with frstPass
	},
	server: function(context, args) {
		if (!env.isServer)
			return;
		firstPass(args[0], context); // traverse server template with frstPass
	}
};

var secondMethods = {
	//_________________________________ local context management
	context: function(context, descriptor) {
		if (context.children) // catch context produced in firstPass
			descriptor.context = context.children.shift();
	},
	// ____________________________________ WITH
	with: function(context, descriptor, args) {
		if (!context.children)
			return;
		var path = args[0],
			template = args[1],
			ctx = context.children.shift(); // catch context produced in firstPass
		secondPass(template, ctx, descriptor);
	},
	//_________________________________________ EACH
	each: function(context, descriptor, args) {
		if (!context.children)
			return;
		var contexts = context.children.shift(); // catch contexts array produced in firstPass
		if (contexts && contexts.length) {
			var template = args[1],
				emptyTemplate = args[2];
			if (!contexts.length)
				secondPass(emptyTemplate, context, descriptor);
			else
				for (var i = 0, len = contexts.length; i < len; ++i)
					secondPass(template, contexts[i], descriptor);
		}
	},
	//________________________________ TAGS
	tag: function(context, descriptor, args) {
		var name = args[0],
			template = args[1],
			newDescriptor = new SOD();
		if (template)
			secondPass(template, context, newDescriptor);
		utils.tagOutput(descriptor, newDescriptor, name);
	},
	//________________________________ Conditonal node rendering
	if: function(context, descriptor, args) {
		var ok, condition = args[0],
			successTempl = args[1],
			failTempl = args[2];
		if (condition && condition.__interpolable__)
			ok = condition.output(context);
		else if (type === 'function')
			ok = condition.call(this, context);
		if (ok)
			secondPass(successTempl, context, descriptor);
		else if (failTempl)
			secondPass(failTempl, context, descriptor);
	},
	//_________________________________ CLIENT/SERVER
	client: function(context, descriptor, args) {
		if (env.isServer)
			return;
		secondPass(args[0], context, descriptor);
	},
	server: function(context, descriptor, args) {
		if (!env.isServer)
			return;
		secondPass(args[0], context, descriptor);
	},
	contentSwitch: null,
	cssSwitch: null
};

function secondPass(template, context, descriptor) {
	// apply string rendering only
	descriptor = descriptor ||  new SOD();
	var handler,
		f;
	for (var i = 0, len = template._queue.length; i < len; ++i) {
		handler = template._queue[i];
		if (handler.engineBlock)
			f = handler.engineBlock.twopass.second || handler.engineBlock.string;
		else if (handler.func) {
			if (handler.firstPass)
				continue;
			else
				f = handler.func;
		} else if (secondMethods[handler.name])
			f = secondMethods[handler.name];
		else
			f = stringEngine[handler.name];

		f(descriptor.context || context, descriptor, handler.args);
	}
}

function firstPass(template, context) {
	// apply contexts construction only
	var handler,
		f,
		newContext,
		ctx;
	for (var i = 0, len = template._queue.length; i < len; ++i) {
		handler = template._queue[i];
		if (handler.engineBlock) {
			f = handler.engineBlock.twopass.first;
			if (!f)
				continue;
		} else if (handler.func) {
			if (!handler.firstPass)
				continue;
			else
				f = handler.func;
		} else if (!firstMethods[handler.name])
			continue;
		else
			f = firstMethods[handler.name];
		ctx = f(newContext || context, handler.args);
		if (ctx && ctx.__yContext__)
			newContext = ctx;
	}
}

Template.prototype.twopass = function(context) {
	context = context || new Context();
	firstPass(this, context); // apply first pass : construct contexts
	var self = this;
	// wait for context stabilisation
	return context.stabilised().then(function(context) {
		// then apply second pass : render to string
		var descriptor = new SOD();
		secondPass(self, context, descriptor);
		return descriptor.children;
	});
};

module.exports = {
	firstMethods: firstMethods,
	secondMethods: secondMethods,
	firstPass: firstPass,
	secondPass: secondPass
};
<|endoftext|>


<commit_before>'use strict';

const pug = require('pug');
const path = require('path');
const log = require('intel').getLogger('sitespeedio.plugin.html');
const basePath = path.resolve(__dirname, 'templates');

const templateCache = {};

function getTemplate(templateName) {
  if (!templateName.endsWith('.pug')) templateName = templateName + '.pug';

  const template = templateCache[templateName];
  if (template) {
    return template;
  }

  const filename = path.resolve(basePath, templateName);
  const renderedTemplate = pug.compileFile(filename);

  templateCache[templateName] = renderedTemplate;
  return renderedTemplate;
}

module.exports = {
  renderTemplate(templateName, locals) {
    try {
      return getTemplate(templateName)(locals);
    } catch (e) {
      log.error('Could not generate %s with %j', templateName, locals);
      throw e;
    }
  },
  addTemplate(templateName, templateString) {
    const compiledTemplate = pug.compile(templateString);
    templateCache[templateName + '.pug'] = compiledTemplate;
  }
};
<commit_msg>remove logging all the options<commit_after>'use strict';

const pug = require('pug');
const path = require('path');
const log = require('intel').getLogger('sitespeedio.plugin.html');
const basePath = path.resolve(__dirname, 'templates');

const templateCache = {};

function getTemplate(templateName) {
  if (!templateName.endsWith('.pug')) templateName = templateName + '.pug';

  const template = templateCache[templateName];
  if (template) {
    return template;
  }

  const filename = path.resolve(basePath, templateName);
  const renderedTemplate = pug.compileFile(filename);

  templateCache[templateName] = renderedTemplate;
  return renderedTemplate;
}

module.exports = {
  renderTemplate(templateName, locals) {
    try {
      return getTemplate(templateName)(locals);
    } catch (e) {
      log.error('Could not generate %s', templateName);
      throw e;
    }
  },
  addTemplate(templateName, templateString) {
    const compiledTemplate = pug.compile(templateString);
    templateCache[templateName + '.pug'] = compiledTemplate;
  }
};
<|endoftext|>


<commit_before>'use strict';
var test = require('tape');
var GeometryHelper = require('../src/GeometryHelper');
var Vec3 = require('famous-math').Vec3;

test('GeometryHelper', function(t) {
    t.test('generateParametric', function(t) {

    	t.ok(
    		GeometryHelper.generateParametric instanceof Function,
    		'Should have generateParametric function'
    	);

    	var generator = function generator(u, v, pos) {
    		generator.callCount++;

		    var x = Math.sin(u) * Math.cos(v);
		    var y = Math.cos(u);
		    var z = -Math.sin(u) * Math.sin(v);

		    pos[0] = x;
		    pos[1] = y;
		    pos[2] = z;
		}
        generator.callCount = 0;

    	var detailX = 10;
    	var detailY = 10;

    	var buffers = GeometryHelper.generateParametric(detailX, detailY, generator);

    	t.equals(
    		generator.callCount,
    		(detailX + 1) * detailY,
    		'Should call generator exactly (detailX + 1) * detailY times!'
    	);

        t.end();
    });

    t.end();
});<commit_msg>tests: tests, tests and more tests<commit_after>'use strict';
var test = require('tape');
var GeometryHelper = require('../src/GeometryHelper');
var Vec3 = require('famous-math').Vec3;

test('GeometryHelper', function(t) {
    t.test('generateParametric', function(t) {

    	t.ok(
    		GeometryHelper.generateParametric instanceof Function,
    		'Should have generateParametric function'
    	);

    	var generator = function generator(u, v, pos) {
    		generator.callCount++;

		    var x = Math.sin(u) * Math.cos(v);
		    var y = Math.cos(u);
		    var z = -Math.sin(u) * Math.sin(v);

		    pos[0] = x;
		    pos[1] = y;
		    pos[2] = z;
		}
        generator.callCount = 0;

    	var detailX = 10;
    	var detailY = 10;

    	var buffers = GeometryHelper.generateParametric(detailX, detailY, generator);

    	t.equals(
    		generator.callCount,
    		(detailX + 1) * detailY,
    		'Should call generator exactly (detailX + 1) * detailY times!'
    	);

        t.end();
    });

    t.test('computeNormals', function(t) {
        var vertices = [
            -1,  1, 0,
             0, -1, 0,
             1,  1, 0
        ];
        var indices = [0, 1, 2];

        var normals = GeometryHelper.computeNormals(vertices, indices);
        t.equals(normals.length, vertices.length, 'Normals should be length of vertices');
        t.deepEquals([0, 0, 1], normals.slice(0, 3), 'Should return correct normals');
        t.deepEquals([0, 0, 1], normals.slice(3, 6), 'Should return correct normals');
        t.deepEquals([0, 0, 1], normals.slice(6, 9), 'Should return correct normals');

        t.end();
    });

    t.test('subdivide', function(t) {
        var vertices = [
            -1,  1, 0,
             0, -1, 0,
             1,  1, 0
        ];
        var indices = [0, 1, 2];
        var texCoords = [
            0.0, 0.0,
            0.5, 1.0,
            1.0, 0.0
        ];

        GeometryHelper.subdivide(indices, vertices, texCoords);

        t.equals(
            vertices.length,
            9 * 2,
            'Returned vertices should be 2X length!'
        );

        t.equals(
            indices.length,
            3 * 4,
            'Returned indices should 4X length'
        );

        var rangeX = [0, 0];
        var rangeY = [0, 0];
        var rangeZ = [0, 0];
        var vectors = [];

        for (var i = 0; i < vertices.length; i+=3) {
            vectors.push([vertices[i], vertices[i + 1], vertices[i + 2]]);
        }

        // Get ranges
        vectors.forEach(function(item, i) {
            if (item[0] < rangeX[0]) rangeX[0] = item[0];
            if (item[0] > rangeX[1]) rangeX[1] = item[0];
            if (item[1] < rangeY[0]) rangeY[0] = item[1];
            if (item[1] > rangeY[1]) rangeY[1] = item[1];
            if (item[2] < rangeZ[0]) rangeZ[0] = item[2];
            if (item[2] > rangeZ[1]) rangeZ[1] = item[2];
        });

        t.ok(!(rangeX[0] < -1), 'Returned vertices should remain with bounds of triangle');
        t.ok(!(rangeX[1] >  1), 'Returned vertices should remain with bounds of triangle');
        t.ok(!(rangeY[0] < -1), 'Returned vertices should remain with bounds of triangle');
        t.ok(!(rangeY[1] <  1), 'Returned vertices should remain with bounds of triangle');
        t.ok(!(rangeZ[0] < -1), 'Returned vertices should remain with bounds of triangle');
        t.ok(!(rangeZ[1] >  1), 'Returned vertices should remain with bounds of triangle');

        t.end();
    });

    t.test('getUniqueFaces', function(t) {
        var vertices = [
            -1,  1, 0,
             0, -1, 0,
             1,  1, 0
        ];
        var indices = [0, 1, 2];

        GeometryHelper.getUniqueFaces(vertices, indices);

        t.equals(vertices.length, 9, 'Should not duplicate vertices when no duplicate faces are found');

        var indices = [0, 1, 2, 0, 1, 2];

        GeometryHelper.getUniqueFaces(vertices, indices);

        t.equals(vertices.length, 18, 'Should duplicate vertices for duplicate faces');

        t.end();
    });

    t.test('subdivideSpheroid', function(t) {
        var vertices = [];

        vertices.push.apply(vertices, new Vec3(-1, 1, 0).normalize().toArray());
        vertices.push.apply(vertices, new Vec3( 0,-1, 0).normalize().toArray());
        vertices.push.apply(vertices, new Vec3( 1, 1, 0).normalize().toArray());

        var indices = [0, 1, 2];

        GeometryHelper.subdivideSpheroid(vertices, indices);

        var vectors = [];
        for (var i = 0; i < vertices.length; i += 3) {
            vectors.push(new Vec3(vertices[i], vertices[i + 1], vertices[i + 2]));
        }

        var allLengthOne = vectors.every(function(vec) {
            return (vec.length() > 0.98) && (vec.length() < 1.02);
        });

        t.ok(allLengthOne, "All returned vectors should be of length 1");

        t.end();
    });

    t.test('getSpheroidNormals', function(t) {
        var vertices = [
            -1,  1, 0,
             0, -1, 0,
             1,  1, 0
        ];

        var normals = GeometryHelper.getSpheroidNormals(vertices);

        var normalVectors = [];
        normalVectors.push(normals.slice(0, 3));
        normalVectors.push(normals.slice(3, 6));
        normalVectors.push(normals.slice(6, 9));

        var allNormalized = normalVectors.every(function(normal, i) {
            var vector = new Vec3(vertices[i * 3], vertices[i * 3 + 1], vertices[i * 3 + 2]).normalize();

            return (normal[0] === vector.x) && (normal[1] === vector.y) && (normal[2] === vector.z);
        });

        t.equals(normals.length, vertices.length, 'Returned normals should have same length as vertices');
        t.ok(allNormalized, "All output normals should be normalized vertices values");

        t.end();
    });

    t.test('getSpheroidUV', function(t) {

    });

    t.end();
});<|endoftext|>


<commit_before>/*
  mixin.js - Mixin in constructors in JavaScript.

  Copyright 2011, Lee Iverson <leei@sociologi.ca>.
  See LICENSE for terms.
  */

var sys = require('sys');

/**
 * Mix the {mixin} constructor into the {base} constructor.  Ensures that the
 * all properties of {mixin} are available in {ctor} both for the constructor
 * and its prototype.
 *
 * The following are guaranteed consequences of the mixin:
 * * Will not mixin the same constructor twice.
 * * More than one constructor may be mixed in to the same {base}.
 * * Invokes the function {mixin.included(base)} after the mixin, if it is defined.
 * * {new ctor(...)} will invoke the constructors of all mixed in constructors and
 *   the original constructor in reverse order of their being mixed in.
 * * Properties of the {base} constructor and all previous mixins have priority over
 *   those of the {mixin}.
 *
 * @param {Function} base  The constructor that {mixin} will be added to.
 * @param {Function} mixin The constructor that will be mixed in to {base}.
 *
 */
function mixin(base, mixin) {
  var ctor = base;
  if (base.constructors) {
    // Don't mixin the same constructor twice.
    for (var i in base.constructors) {
      if (base.constructors[i] === mixin)
        return base;
    }
    // Remember this new one.
    base.constructors.unshift(mixin);
  } else {
    // Remember all mixed in classes
    base.constructors = [mixin, base];
    // Create a function with the same name, that calls both functions...
    ctor = base.prototype.constructor = mixin_constructor(base.name, base);
    ctor.__proto__ = base;
  }

  // Inject the mixin prototype at the top of the chain
  ctor.prototype = insert_proto(base.prototype, mixin.prototype);
  //inspect_protos(ctor.prototype, "ctor.prototype");

  insert_proto(ctor.__proto__, mixin);
  //inspect_protos(ctor, "ctor");

  // Inform mixin that it has been included
  if (mixin.hasOwnProperty('included')) {
    var incl = mixin.included.call(mixin, ctor);
    if (incl) { ctor = incl; }
  }

  return ctor;
}

function mixin_constructor(name, ctor) {
  var str = "function __ctor() { var c = ctor.constructors; for (var i in c) { c[i].apply(this, arguments); } }";
  eval(str.replace(/__ctor/, name));
  return eval(name);
}

function insert_proto(base, mixin) {
  //inspect_protos(base,  "inserting: base ");
  //inspect_protos(mixin, "inserting: mixin");
  var copy = copyInto({}, mixin);
  copy.__mixed_in = true;
  // Find
  for (var p = base, prev = base; p.__mixed_in; prev = p, p = p.__proto__) {}
  if (p == base) { p.__mixed_in = true; } // Mark this as mixed in
  //inspect_protos(copy, "inserting: copy");
  copy.__proto__ = prev.__proto__;
  prev.__proto__ = copy;
  //inspect_protos(base, "inserted: base");
  return base;
}

function copyInto(copy, obj) {
  var names = Object.getOwnPropertyNames(obj);
  for (var i in names) {
    var p = names[i];
    if (p !== 'prototype') {
      var descr = Object.getOwnPropertyDescriptor(obj, p);
      //console.log("obj." + p + " = " + sys.inspect(descr));
      Object.defineProperty(copy, p, descr);
    }
  }
  return copy;
}
mixin.copyInto = copyInto;

function inspect_protos(obj, name) {
  console.log(name + " = " + sys.inspect(obj));
  var i = 0;
  while (obj.__proto__) {
    obj = obj.__proto__;
    console.log("  __proto__[" + i + "] = " + sys.inspect(obj));
    ++i;
  }
}

/**
 * Alias a property that is already defined for this Object. Moves the existing
 * property definition on {obj[method]} to {method}_without_{suffix} and
 * assigns {f} to both {method}_with_{suffix} and {method}.
 *
 * For example, the following code will override the "save" method of the
 * {ctor.prototype} with {my_save} and make the old version available as
 * {save_without_timestamp}.
 *
 *     Mixin.included = function(ctor) {
 *       mixin.alias(ctor.prototype, "save", "timestamp", my_save);
 *     }
 *
 * @param {Object} obj    The target object.
 * @param {String} method The base method name.
 * @param {String} suffix A suffix that will be added to the method name(s).
 * @param {Function} f    The function to use to override the method.
 * @api public
 */
function alias(obj, method, suffix, f) {
  if (obj[method + "_without_" + suffix]) {
    throw(method + "_without_" + suffix + " already defined.");
  }

  var was = obj[method];
  obj[method + "_without_" + suffix] = was;
  obj[method + "_with_" + suffix] = obj[method] = f;
}

mixin.alias = alias;

module.exports = mixin;
<commit_msg>Convert to use util instead of sys<commit_after>/*
  mixin.js - Mixin in constructors in JavaScript.

  Copyright 2011, Lee Iverson <leei@sociologi.ca>.
  See LICENSE for terms.
  */

var util = require('util');

/**
 * Mix the {mixin} constructor into the {base} constructor.  Ensures that the
 * all properties of {mixin} are available in {ctor} both for the constructor
 * and its prototype.
 *
 * The following are guaranteed consequences of the mixin:
 * * Will not mixin the same constructor twice.
 * * More than one constructor may be mixed in to the same {base}.
 * * Invokes the function {mixin.included(base)} after the mixin, if it is defined.
 * * {new ctor(...)} will invoke the constructors of all mixed in constructors and
 *   the original constructor in reverse order of their being mixed in.
 * * Properties of the {base} constructor and all previous mixins have priority over
 *   those of the {mixin}.
 *
 * @param {Function} base  The constructor that {mixin} will be added to.
 * @param {Function} mixin The constructor that will be mixed in to {base}.
 *
 */
function mixin(base, mixin) {
  var ctor = base;
  if (base.constructors) {
    // Don't mixin the same constructor twice.
    for (var i in base.constructors) {
      if (base.constructors[i] === mixin)
        return base;
    }
    // Remember this new one.
    base.constructors.unshift(mixin);
  } else {
    // Remember all mixed in classes
    base.constructors = [mixin, base];
    // Create a function with the same name, that calls both functions...
    ctor = base.prototype.constructor = mixin_constructor(base.name, base);
    ctor.__proto__ = base;
  }

  // Inject the mixin prototype at the top of the chain
  ctor.prototype = insert_proto(base.prototype, mixin.prototype);
  //inspect_protos(ctor.prototype, "ctor.prototype");

  insert_proto(ctor.__proto__, mixin);
  //inspect_protos(ctor, "ctor");

  // Inform mixin that it has been included
  if (mixin.hasOwnProperty('included')) {
    var incl = mixin.included.call(mixin, ctor);
    if (incl) { ctor = incl; }
  }

  return ctor;
}

function mixin_constructor(name, ctor) {
  var str = "function __ctor() { var c = ctor.constructors; for (var i in c) { c[i].apply(this, arguments); } }";
  eval(str.replace(/__ctor/, name));
  return eval(name);
}

function insert_proto(base, mixin) {
  //inspect_protos(base,  "inserting: base ");
  //inspect_protos(mixin, "inserting: mixin");
  var copy = copyInto({}, mixin);
  copy.__mixed_in = true;
  // Find
  for (var p = base, prev = base; p.__mixed_in; prev = p, p = p.__proto__) {}
  if (p == base) { p.__mixed_in = true; } // Mark this as mixed in
  //inspect_protos(copy, "inserting: copy");
  copy.__proto__ = prev.__proto__;
  prev.__proto__ = copy;
  //inspect_protos(base, "inserted: base");
  return base;
}

function copyInto(copy, obj) {
  var names = Object.getOwnPropertyNames(obj);
  for (var i in names) {
    var p = names[i];
    if (p !== 'prototype') {
      var descr = Object.getOwnPropertyDescriptor(obj, p);
      //console.log("obj." + p + " = " + util.inspect(descr));
      Object.defineProperty(copy, p, descr);
    }
  }
  return copy;
}
mixin.copyInto = copyInto;

function inspect_protos(obj, name) {
  console.log(name + " = " + util.inspect(obj));
  var i = 0;
  while (obj.__proto__) {
    obj = obj.__proto__;
    console.log("  __proto__[" + i + "] = " + util.inspect(obj));
    ++i;
  }
}

/**
 * Alias a property that is already defined for this Object. Moves the existing
 * property definition on {obj[method]} to {method}_without_{suffix} and
 * assigns {f} to both {method}_with_{suffix} and {method}.
 *
 * For example, the following code will override the "save" method of the
 * {ctor.prototype} with {my_save} and make the old version available as
 * {save_without_timestamp}.
 *
 *     Mixin.included = function(ctor) {
 *       mixin.alias(ctor.prototype, "save", "timestamp", my_save);
 *     }
 *
 * @param {Object} obj    The target object.
 * @param {String} method The base method name.
 * @param {String} suffix A suffix that will be added to the method name(s).
 * @param {Function} f    The function to use to override the method.
 * @api public
 */
function alias(obj, method, suffix, f) {
  if (obj[method + "_without_" + suffix]) {
    throw(method + "_without_" + suffix + " already defined.");
  }

  var was = obj[method];
  obj[method + "_without_" + suffix] = was;
  obj[method + "_with_" + suffix] = obj[method] = f;
}

mixin.alias = alias;

module.exports = mixin;
<|endoftext|>


<commit_before>'use strict';

var findOpenPort = require('find-open-port');
var Bluebird = require('bluebird');

exports.name = 'proxy';

function getProxyOptions(config) {
  function buildOptionsFromPort(port) {
    var appPort = config.get('app.port');
    var proxyModule = require.resolve('./child');
    var commandPort = 4446;

    config.set('proxy.targetUrl', 'http://127.0.0.1:' + port);
    config.set('proxy.commandUrl', 'http://127.0.0.1:' + commandPort);

    return {
      dependsOn: config.get('launch', false) ? [ 'application' ] : [],
      command: process.execPath,
      commandArgs: [
        proxyModule,
        '' + appPort,
        '' + port,
        '' + commandPort,
      ],
      port: port,
      verifyTimeout: config.get('proxy.timeout', 6000),
    };
  }

  var port = config.get('proxy.port', 0);

  if (port === 0) {
    return findOpenPort().then(buildOptionsFromPort);
  }
  return Bluebird.resolve(port).then(buildOptionsFromPort);
}
exports.getOptions = getProxyOptions;
<commit_msg>Default proxy port to 4445<commit_after>'use strict';

var findOpenPort = require('find-open-port');
var Bluebird = require('bluebird');

exports.name = 'proxy';

function getProxyOptions(config) {
  function buildOptionsFromPort(port) {
    var appPort = config.get('app.port');
    var proxyModule = require.resolve('./child');
    var commandPort = 4446;

    config.set('proxy.targetUrl', 'http://127.0.0.1:' + port);
    config.set('proxy.commandUrl', 'http://127.0.0.1:' + commandPort);

    return {
      dependsOn: config.get('launch', false) ? [ 'application' ] : [],
      command: process.execPath,
      commandArgs: [
        proxyModule,
        '' + appPort,
        '' + port,
        '' + commandPort,
      ],
      port: port,
      verifyTimeout: config.get('proxy.timeout', 6000),
    };
  }

  // Defaulting to 4445 for backward compatibility
  var port = config.get('proxy.port', 4445);

  if (port === 0) {
    return findOpenPort().then(buildOptionsFromPort);
  }
  return Bluebird.resolve(port).then(buildOptionsFromPort);
}
exports.getOptions = getProxyOptions;
<|endoftext|>