<commit_before>'use strict'

const EventEmitter = require('events').EventEmitter
const Log          = require('ipfs-log')
const Index        = require('./Index')

const DefaultOptions = {
  Index: Index,
  maxHistory: 256
}

class Store {
  constructor(ipfs, id, dbname, options = {}) {
    this.id = id
    this.dbname = dbname
    this.events = new EventEmitter()

    let opts = Object.assign({}, DefaultOptions)
    Object.assign(opts, options)

    this.options = opts
    this._ipfs = ipfs
    this._index = new this.options.Index(this.id)
    this._oplog = new Log(this._ipfs, this.id, this.dbname, this.options)
    this._lastWrite = []
  }

  loadHistory(hash) {
    if(this._lastWrite.includes(hash))
      return Promise.resolve([])

    if(hash) this._lastWrite.push(hash)
    this.events.emit('load', this.dbname, hash)

    if(hash) {
      return Log.fromIpfsHash(this._ipfs, hash, this.options)
        .then((log) => this._oplog.join(log))
        .then((merged) => {
          this._index.updateIndex(this._oplog, merged)
          this.events.emit('history', this.dbname, merged)
        })
        .then(() => this.events.emit('ready', this.dbname))
        .then(() => this)
    } else {
      this.events.emit('ready', this.dbname)
      return Promise.resolve(this)
    }
  }

  sync(hash) {
    if(!hash || this._lastWrite.includes(hash))
      return Promise.resolve([])

    let newItems = []
    if(hash) this._lastWrite.push(hash)
    this.events.emit('sync', this.dbname)
    const startTime = new Date().getTime()
    return Log.fromIpfsHash(this._ipfs, hash, this.options)
      .then((log) => this._oplog.join(log))
      .then((merged) => newItems = merged)
      .then(() => this._index.updateIndex(this._oplog, newItems))
      .then(() => {
        newItems.reverse()
          .forEach((e) => this.events.emit('data', this.dbname, e))
      })
      .then(() => newItems)
  }

  close() {
    this.delete()
    this.events.emit('close', this.dbname)
  }

  // TODO: should make private?
  delete() {
    this._index = new this.options.Index(this.id)
    this._oplog = new Log(this._ipfs, this.id, this.dbname, this.options)
  }

  _addOperation(data) {
    let result, logHash
    if(this._oplog) {
      return this._oplog.add(data)
        .then((res) => result = res)
        .then(() => Log.getIpfsHash(this._ipfs, this._oplog))
        .then((hash) => logHash = hash)
        .then(() => this._lastWrite.push(logHash))
        .then(() => this._index.updateIndex(this._oplog, [result]))
        .then(() => this.events.emit('write', this.dbname, logHash))
        .then(() => this.events.emit('data', this.dbname, result))
        .then(() => result.hash)
    }
  }
}

module.exports = Store
<commit_msg>Fix Log creation<commit_after>'use strict'

const EventEmitter = require('events').EventEmitter
const Log          = require('ipfs-log')
const Index        = require('./Index')

const DefaultOptions = {
  Index: Index,
  maxHistory: 256
}

class Store {
  constructor(ipfs, id, dbname, options = {}) {
    this.id = id
    this.dbname = dbname
    this.events = new EventEmitter()

    let opts = Object.assign({}, DefaultOptions)
    Object.assign(opts, options)

    this.options = opts
    this._ipfs = ipfs
    this._index = new this.options.Index(this.id)
    this._oplog = new Log(this._ipfs, this.id, this.options)
    this._lastWrite = []
  }

  loadHistory(hash) {
    if(this._lastWrite.includes(hash))
      return Promise.resolve([])

    if(hash) this._lastWrite.push(hash)
    this.events.emit('load', this.dbname, hash)

    if(hash) {
      return Log.fromIpfsHash(this._ipfs, hash, this.options)
        .then((log) => this._oplog.join(log))
        .then((merged) => {
          this._index.updateIndex(this._oplog, merged)
          this.events.emit('history', this.dbname, merged)
        })
        .then(() => this.events.emit('ready', this.dbname))
        .then(() => this)
    } else {
      this.events.emit('ready', this.dbname)
      return Promise.resolve(this)
    }
  }

  sync(hash) {
    if(!hash || this._lastWrite.includes(hash))
      return Promise.resolve([])

    let newItems = []
    if(hash) this._lastWrite.push(hash)
    this.events.emit('sync', this.dbname)
    const startTime = new Date().getTime()
    return Log.fromIpfsHash(this._ipfs, hash, this.options)
      .then((log) => this._oplog.join(log))
      .then((merged) => newItems = merged)
      .then(() => this._index.updateIndex(this._oplog, newItems))
      .then(() => {
        newItems.reverse()
          .forEach((e) => this.events.emit('data', this.dbname, e))
      })
      .then(() => newItems)
  }

  close() {
    this.delete()
    this.events.emit('close', this.dbname)
  }

  // TODO: should make private?
  delete() {
    this._index = new this.options.Index(this.id)
    this._oplog = new Log(this._ipfs, this.id, this.options)
  }

  _addOperation(data) {
    let result, logHash
    if(this._oplog) {
      return this._oplog.add(data)
        .then((res) => result = res)
        .then(() => Log.getIpfsHash(this._ipfs, this._oplog))
        .then((hash) => logHash = hash)
        .then(() => this._lastWrite.push(logHash))
        .then(() => this._index.updateIndex(this._oplog, [result]))
        .then(() => this.events.emit('write', this.dbname, logHash))
        .then(() => this.events.emit('data', this.dbname, result))
        .then(() => result.hash)
    }
  }
}

module.exports = Store
<|endoftext|>


<commit_before>const P = require('bluebird');
const _ = require('lodash');
const ColumnTypeGetter = require('./sequelize-column-type-getter');
const TableConstraintsAnalyzer = require('./sequelize-table-constraints-getter');
const { DatabaseAnalyzerError } = require('../../utils/errors');
const { terminate } = require('../../utils/terminator');

let queryInterface;
let tableConstraintsAnalyzer;
let columnTypeGetter;

function isUnderscored(fields) {
  return fields.every((field) => field.nameColumn === _.snakeCase(field.nameColumn))
    && fields.some((field) => field.nameColumn.includes('_'));
}

function analyzeFields(table, config) {
  return queryInterface.describeTable(table, { schema: config.dbSchema });
}

async function analyzePrimaryKeys(schema) {
  return Object.keys(schema).filter((column) => schema[column].primaryKey);
}

async function showAllTables(databaseConnection, schema) {
  const dbDialect = databaseConnection.getDialect();

  if (['mysql', 'mariadb'].includes(dbDialect)) {
    return queryInterface.showAllTables();
  }

  let realSchema = schema;
  if (!realSchema) {
    if (dbDialect === 'mssql') {
      [{ default_schema: realSchema }] = await queryInterface.sequelize.query('SELECT SCHEMA_NAME() as default_schema', { type: queryInterface.sequelize.QueryTypes.SELECT });
    } else {
      realSchema = 'public';
    }
  }

  return queryInterface.sequelize.query(
    'SELECT table_name as table_name FROM information_schema.tables WHERE table_schema = ? AND table_type LIKE \'%TABLE\' AND table_name != \'spatial_ref_sys\'',
    { type: queryInterface.sequelize.QueryTypes.SELECT, replacements: [realSchema] },
  )
    .then((results) => results.map((table) => table.table_name));
}

function hasTimestamps(fields) {
  let hasCreatedAt = false;
  let hasUpdatedAt = false;

  fields.forEach((field) => {
    if (field.name === 'createdAt') {
      hasCreatedAt = true;
    }

    if (field.name === 'updatedAt') {
      hasUpdatedAt = true;
    }
  });

  return hasCreatedAt && hasUpdatedAt;
}

function formatAliasName(columnName) {
  const alias = _.camelCase(columnName);
  if (alias.endsWith('Id') && alias.length > 2) {
    return alias.substring(0, alias.length - 2);
  }
  if (alias.endsWith('Uuid') && alias.length > 4) {
    return alias.substring(0, alias.length - 4);
  }
  return alias;
}

// NOTICE: Look for the id column in both fields and primary keys.
function hasIdColumn(fields, primaryKeys) {
  return fields.some((field) => field.name === 'id' || field.nameColumn === 'id')
    || _.includes(primaryKeys, 'id');
}

function analyzeTable(table, config) {
  return P
    .resolve(analyzeFields(table, config))
    .then((schema) => P.all([
      schema,
      tableConstraintsAnalyzer.perform(table),
      analyzePrimaryKeys(schema),
    ]))
    .spread(async (schema, foreignKeys, primaryKeys) => {
      const fields = [];
      const references = [];

      await P.each(Object.keys(schema), async (nameColumn) => {
        const columnInfo = schema[nameColumn];
        const type = await columnTypeGetter.perform(columnInfo, nameColumn, table);
        const foreignKey = _.find(foreignKeys, { column_name: nameColumn });

        if (foreignKey
          && foreignKey.foreign_table_name
          && foreignKey.column_name
          && !columnInfo.primaryKey) {
          const reference = {
            ref: foreignKey.foreign_table_name,
            foreignKey: foreignKey.column_name,
            foreignKeyName: _.camelCase(foreignKey.column_name),
            as: formatAliasName(foreignKey.column_name),
          };

          // NOTICE: If the foreign key name and alias are the same, Sequelize will crash, we need
          //         to handle this specific scenario generating a different foreign key name.
          if (reference.foreignKeyName === reference.as) {
            reference.foreignKeyName = `${reference.foreignKeyName}Key`;
          }

          if (foreignKey.foreign_column_name !== 'id') {
            reference.targetKey = foreignKey.foreign_column_name;
          }

          references.push(reference);
        } else if (type) {
          // NOTICE: If the column is of integer type, named "id" and primary, Sequelize will
          //         handle it automatically without necessary declaration.
          if (!(nameColumn === 'id' && type === 'INTEGER' && columnInfo.primaryKey)) {
            const field = {
              name: _.camelCase(nameColumn),
              nameColumn,
              type,
              primaryKey: columnInfo.primaryKey,
              defaultValue: columnInfo.defaultValue,
            };

            fields.push(field);
          }
        }
      });

      const options = {
        underscored: isUnderscored(fields),
        timestamps: hasTimestamps(fields),
        hasIdColumn: hasIdColumn(fields, primaryKeys),
        hasPrimaryKeys: !_.isEmpty(primaryKeys),
      };

      return {
        fields,
        references,
        primaryKeys,
        options,
      };
    });
}

async function analyzeSequelizeTables(databaseConnection, config, allowWarning) {
  const schema = {};

  queryInterface = databaseConnection.getQueryInterface();
  tableConstraintsAnalyzer = new TableConstraintsAnalyzer(databaseConnection, config.dbSchema);
  columnTypeGetter = new ColumnTypeGetter(databaseConnection, config.dbSchema || 'public', allowWarning);

  if (config.dbSchema) {
    const schemaExists = await queryInterface.sequelize
      .query(
        'SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ?;',
        { type: queryInterface.sequelize.QueryTypes.SELECT, replacements: [config.dbSchema] },
      )
      .then((result) => !!result.length);

    if (!schemaExists) {
      const message = 'This schema does not exists.';
      return terminate(1, {
        errorCode: 'database_authentication_error',
        errorMessage: message,
        logs: [message],
      });
    }
  }

  // Build the db schema.
  await P.mapSeries(showAllTables(databaseConnection, config.dbSchema), async (table) => {
    schema[table] = await analyzeTable(table, config);
  });

  if (_.isEmpty(schema)) {
    throw new DatabaseAnalyzerError.EmptyDatabase('no tables found', {
      orm: 'sequelize',
      dialect: databaseConnection.getDialect(),
    });
  }

  return schema;
}

module.exports = analyzeSequelizeTables;
<commit_msg>[-] Technical - Code readability improvement<commit_after>const P = require('bluebird');
const _ = require('lodash');
const ColumnTypeGetter = require('./sequelize-column-type-getter');
const TableConstraintsGetter = require('./sequelize-table-constraints-getter');
const { DatabaseAnalyzerError } = require('../../utils/errors');
const { terminate } = require('../../utils/terminator');

let queryInterface;
let tableConstraintsGetter;
let columnTypeGetter;

function isUnderscored(fields) {
  return fields.every((field) => field.nameColumn === _.snakeCase(field.nameColumn))
    && fields.some((field) => field.nameColumn.includes('_'));
}

function analyzeFields(table, config) {
  return queryInterface.describeTable(table, { schema: config.dbSchema });
}

async function analyzePrimaryKeys(schema) {
  return Object.keys(schema).filter((column) => schema[column].primaryKey);
}

async function showAllTables(databaseConnection, schema) {
  const dbDialect = databaseConnection.getDialect();

  if (['mysql', 'mariadb'].includes(dbDialect)) {
    return queryInterface.showAllTables();
  }

  let realSchema = schema;
  if (!realSchema) {
    if (dbDialect === 'mssql') {
      [{ default_schema: realSchema }] = await queryInterface.sequelize.query('SELECT SCHEMA_NAME() as default_schema', { type: queryInterface.sequelize.QueryTypes.SELECT });
    } else {
      realSchema = 'public';
    }
  }

  return queryInterface.sequelize.query(
    'SELECT table_name as table_name FROM information_schema.tables WHERE table_schema = ? AND table_type LIKE \'%TABLE\' AND table_name != \'spatial_ref_sys\'',
    { type: queryInterface.sequelize.QueryTypes.SELECT, replacements: [realSchema] },
  )
    .then((results) => results.map((table) => table.table_name));
}

function hasTimestamps(fields) {
  let hasCreatedAt = false;
  let hasUpdatedAt = false;

  fields.forEach((field) => {
    if (field.name === 'createdAt') {
      hasCreatedAt = true;
    }

    if (field.name === 'updatedAt') {
      hasUpdatedAt = true;
    }
  });

  return hasCreatedAt && hasUpdatedAt;
}

function formatAliasName(columnName) {
  const alias = _.camelCase(columnName);
  if (alias.endsWith('Id') && alias.length > 2) {
    return alias.substring(0, alias.length - 2);
  }
  if (alias.endsWith('Uuid') && alias.length > 4) {
    return alias.substring(0, alias.length - 4);
  }
  return alias;
}

// NOTICE: Look for the id column in both fields and primary keys.
function hasIdColumn(fields, primaryKeys) {
  return fields.some((field) => field.name === 'id' || field.nameColumn === 'id')
    || _.includes(primaryKeys, 'id');
}

function analyzeTable(table, config) {
  return P
    .resolve(analyzeFields(table, config))
    .then((schema) => P.all([
      schema,
      tableConstraintsGetter.perform(table),
      analyzePrimaryKeys(schema),
    ]))
    .spread(async (schema, foreignKeys, primaryKeys) => {
      const fields = [];
      const references = [];

      await P.each(Object.keys(schema), async (nameColumn) => {
        const columnInfo = schema[nameColumn];
        const type = await columnTypeGetter.perform(columnInfo, nameColumn, table);
        const foreignKey = _.find(foreignKeys, { column_name: nameColumn });

        if (foreignKey
          && foreignKey.foreign_table_name
          && foreignKey.column_name
          && !columnInfo.primaryKey) {
          const reference = {
            ref: foreignKey.foreign_table_name,
            foreignKey: foreignKey.column_name,
            foreignKeyName: _.camelCase(foreignKey.column_name),
            as: formatAliasName(foreignKey.column_name),
          };

          // NOTICE: If the foreign key name and alias are the same, Sequelize will crash, we need
          //         to handle this specific scenario generating a different foreign key name.
          if (reference.foreignKeyName === reference.as) {
            reference.foreignKeyName = `${reference.foreignKeyName}Key`;
          }

          if (foreignKey.foreign_column_name !== 'id') {
            reference.targetKey = foreignKey.foreign_column_name;
          }

          references.push(reference);
        } else if (type) {
          // NOTICE: If the column is of integer type, named "id" and primary, Sequelize will
          //         handle it automatically without necessary declaration.
          if (!(nameColumn === 'id' && type === 'INTEGER' && columnInfo.primaryKey)) {
            const field = {
              name: _.camelCase(nameColumn),
              nameColumn,
              type,
              primaryKey: columnInfo.primaryKey,
              defaultValue: columnInfo.defaultValue,
            };

            fields.push(field);
          }
        }
      });

      const options = {
        underscored: isUnderscored(fields),
        timestamps: hasTimestamps(fields),
        hasIdColumn: hasIdColumn(fields, primaryKeys),
        hasPrimaryKeys: !_.isEmpty(primaryKeys),
      };

      return {
        fields,
        references,
        primaryKeys,
        options,
      };
    });
}

async function analyzeSequelizeTables(databaseConnection, config, allowWarning) {
  const schema = {};

  queryInterface = databaseConnection.getQueryInterface();
  tableConstraintsGetter = new TableConstraintsGetter(databaseConnection, config.dbSchema);
  columnTypeGetter = new ColumnTypeGetter(databaseConnection, config.dbSchema || 'public', allowWarning);

  if (config.dbSchema) {
    const schemaExists = await queryInterface.sequelize
      .query(
        'SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ?;',
        { type: queryInterface.sequelize.QueryTypes.SELECT, replacements: [config.dbSchema] },
      )
      .then((result) => !!result.length);

    if (!schemaExists) {
      const message = 'This schema does not exists.';
      return terminate(1, {
        errorCode: 'database_authentication_error',
        errorMessage: message,
        logs: [message],
      });
    }
  }

  // Build the db schema.
  await P.mapSeries(showAllTables(databaseConnection, config.dbSchema), async (table) => {
    schema[table] = await analyzeTable(table, config);
  });

  if (_.isEmpty(schema)) {
    throw new DatabaseAnalyzerError.EmptyDatabase('no tables found', {
      orm: 'sequelize',
      dialect: databaseConnection.getDialect(),
    });
  }

  return schema;
}

module.exports = analyzeSequelizeTables;
<|endoftext|>


<commit_before>/**
 * @author sunag / http://www.sunag.com.br/
 */

import { NodeBuilder } from '../core/NodeBuilder.js';
import { ColorNode } from '../inputs/ColorNode.js';
import { PositionNode } from '../accessors/PositionNode.js';
import { RawNode } from './nodes/RawNode.js';

function NodeMaterial( vertex, fragment ) {

	THREE.ShaderMaterial.call( this );

	this.vertex = vertex || new RawNode( new PositionNode( PositionNode.PROJECTION ) );
	this.fragment = fragment || new RawNode( new ColorNode( 0xFF0000 ) );

	this.updaters = [];

}

NodeMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype );
NodeMaterial.prototype.constructor = NodeMaterial;
NodeMaterial.prototype.type = "NodeMaterial";

NodeMaterial.prototype.isNodeMaterial = true;

Object.defineProperties( NodeMaterial.prototype, {

	properties: {

		get: function () {

			return this.fragment.properties;

		}

	}

} );

NodeMaterial.prototype.updateFrame = function ( frame ) {

	for ( var i = 0; i < this.updaters.length; ++ i ) {

		frame.updateNode( this.updaters[ i ] );

	}

};

NodeMaterial.prototype.onBeforeCompile = function ( shader, renderer ) {

	if ( this.needsUpdate ) {

		this.build( { renderer: renderer } );

		shader.uniforms = this.uniforms;
		shader.vertexShader = this.vertexShader;
		shader.fragmentShader = this.fragmentShader;

	}

};

NodeMaterial.prototype.build = function ( params ) {

	params = params || {};

	var builder = params.builder || new NodeBuilder();

	builder.setMaterial( this, params.renderer );
	builder.build( this.vertex, this.fragment );

	this.vertexShader = builder.getCode( 'vertex' );
	this.fragmentShader = builder.getCode( 'fragment' );

	this.defines = builder.defines;
	this.uniforms = builder.uniforms;
	this.extensions = builder.extensions;
	this.updaters = builder.updaters;

	this.fog = builder.requires.fog;
	this.lights = builder.requires.lights;

	this.transparent = builder.requires.transparent || this.blending > THREE.NormalBlending;

	this.needsUpdate = false;

	return this;

};

NodeMaterial.prototype.copy = function ( source ) {

	var uuid = this.uuid;

	for ( var name in source ) {

		this[ name ] = source[ name ];

	}

	this.uuid = uuid;

	if ( source.userData !== undefined ) {

		this.userData = JSON.parse( JSON.stringify( source.userData ) );

	}

};

NodeMaterial.prototype.toJSON = function ( meta ) {

	var isRootObject = ( meta === undefined || typeof meta === 'string' );

	if ( isRootObject ) {

		meta = {
			nodes: {}
		};

	}

	if ( meta && ! meta.materials ) meta.materials = {};

	if ( ! meta.materials[ this.uuid ] ) {

		var data = {};

		data.uuid = this.uuid;
		data.type = this.type;

		meta.materials[ data.uuid ] = data;

		if ( this.name !== "" ) data.name = this.name;

		if ( this.size !== undefined ) data.size = this.size;
		if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;

		if ( this.blending !== THREE.NormalBlending ) data.blending = this.blending;
		if ( this.flatShading === true ) data.flatShading = this.flatShading;
		if ( this.side !== THREE.FrontSide ) data.side = this.side;
		if ( this.vertexColors !== THREE.NoColors ) data.vertexColors = this.vertexColors;

		if ( this.depthFunc !== THREE.LessEqualDepth ) data.depthFunc = this.depthFunc;
		if ( this.depthTest === false ) data.depthTest = this.depthTest;
		if ( this.depthWrite === false ) data.depthWrite = this.depthWrite;

		if ( this.linewidth !== 1 ) data.linewidth = this.linewidth;
		if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
		if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
		if ( this.scale !== undefined ) data.scale = this.scale;

		if ( this.dithering === true ) data.dithering = true;

		if ( this.wireframe === true ) data.wireframe = this.wireframe;
		if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
		if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
		if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;

		if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
		if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;

		if ( this.morphTargets === true ) data.morphTargets = true;
		if ( this.skinning === true ) data.skinning = true;

		if ( this.visible === false ) data.visible = false;
		if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;

		data.fog = this.fog;
		data.lights = this.lights;

		data.vertex = this.vertex.toJSON( meta ).uuid;
		data.fragment = this.fragment.toJSON( meta ).uuid;

	}

	meta.material = this.uuid;

	return meta;

};

export { NodeMaterial };
<commit_msg>fix needsUpdate<commit_after>/**
 * @author sunag / http://www.sunag.com.br/
 */

import { NodeBuilder } from '../core/NodeBuilder.js';
import { ColorNode } from '../inputs/ColorNode.js';
import { PositionNode } from '../accessors/PositionNode.js';
import { RawNode } from './nodes/RawNode.js';

function NodeMaterial( vertex, fragment ) {

	THREE.ShaderMaterial.call( this );

	var self = this;

	this.vertex = vertex || new RawNode( new PositionNode( PositionNode.PROJECTION ) );
	this.fragment = fragment || new RawNode( new ColorNode( 0xFF0000 ) );

	this.updaters = [];

	// it fix the programCache and share the code with others materials

	this.onBeforeCompile.toString = function() {

		return self.needsCompile;

	};

}

NodeMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype );
NodeMaterial.prototype.constructor = NodeMaterial;
NodeMaterial.prototype.type = "NodeMaterial";

NodeMaterial.prototype.isNodeMaterial = true;

Object.defineProperties( NodeMaterial.prototype, {

	properties: {

		get: function () {

			return this.fragment.properties;

		}

	},

	needsUpdate: {

		set: function ( value ) {

			this.needsCompile = value;

		},

		get: function () {

			return this.needsCompile;

		}

	}

} );

NodeMaterial.prototype.updateFrame = function ( frame ) {

	for ( var i = 0; i < this.updaters.length; ++ i ) {

		frame.updateNode( this.updaters[ i ] );

	}

};

NodeMaterial.prototype.onBeforeCompile = function ( shader, renderer ) {

	if ( this.needsUpdate ) {

		this.build( { renderer: renderer } );

		shader.uniforms = this.uniforms;
		shader.vertexShader = this.vertexShader;
		shader.fragmentShader = this.fragmentShader;

	}

};

NodeMaterial.prototype.build = function ( params ) {

	params = params || {};

	var builder = params.builder || new NodeBuilder();

	builder.setMaterial( this, params.renderer );
	builder.build( this.vertex, this.fragment );

	this.vertexShader = builder.getCode( 'vertex' );
	this.fragmentShader = builder.getCode( 'fragment' );

	this.defines = builder.defines;
	this.uniforms = builder.uniforms;
	this.extensions = builder.extensions;
	this.updaters = builder.updaters;

	this.fog = builder.requires.fog;
	this.lights = builder.requires.lights;

	this.transparent = builder.requires.transparent || this.blending > THREE.NormalBlending;

	this.needsUpdate = false;

	return this;

};

NodeMaterial.prototype.copy = function ( source ) {

	var uuid = this.uuid;

	for ( var name in source ) {

		this[ name ] = source[ name ];

	}

	this.uuid = uuid;

	if ( source.userData !== undefined ) {

		this.userData = JSON.parse( JSON.stringify( source.userData ) );

	}

};

NodeMaterial.prototype.toJSON = function ( meta ) {

	var isRootObject = ( meta === undefined || typeof meta === 'string' );

	if ( isRootObject ) {

		meta = {
			nodes: {}
		};

	}

	if ( meta && ! meta.materials ) meta.materials = {};

	if ( ! meta.materials[ this.uuid ] ) {

		var data = {};

		data.uuid = this.uuid;
		data.type = this.type;

		meta.materials[ data.uuid ] = data;

		if ( this.name !== "" ) data.name = this.name;

		if ( this.size !== undefined ) data.size = this.size;
		if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;

		if ( this.blending !== THREE.NormalBlending ) data.blending = this.blending;
		if ( this.flatShading === true ) data.flatShading = this.flatShading;
		if ( this.side !== THREE.FrontSide ) data.side = this.side;
		if ( this.vertexColors !== THREE.NoColors ) data.vertexColors = this.vertexColors;

		if ( this.depthFunc !== THREE.LessEqualDepth ) data.depthFunc = this.depthFunc;
		if ( this.depthTest === false ) data.depthTest = this.depthTest;
		if ( this.depthWrite === false ) data.depthWrite = this.depthWrite;

		if ( this.linewidth !== 1 ) data.linewidth = this.linewidth;
		if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
		if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
		if ( this.scale !== undefined ) data.scale = this.scale;

		if ( this.dithering === true ) data.dithering = true;

		if ( this.wireframe === true ) data.wireframe = this.wireframe;
		if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
		if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
		if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;

		if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
		if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;

		if ( this.morphTargets === true ) data.morphTargets = true;
		if ( this.skinning === true ) data.skinning = true;

		if ( this.visible === false ) data.visible = false;
		if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;

		data.fog = this.fog;
		data.lights = this.lights;

		data.vertex = this.vertex.toJSON( meta ).uuid;
		data.fragment = this.fragment.toJSON( meta ).uuid;

	}

	meta.material = this.uuid;

	return meta;

};

export { NodeMaterial };
<|endoftext|>


<commit_before>// This function cleans all the elements that could leak user data
// before sending to the server. It also removes any attributes that
// could have personal data so we end up with a clean dom tree.
const selectors = [
  'video',
  'input',
  'button',
  'iframe',
  'a[href=""]',
  '.accessible_elem',
  '.uiLikePagebutton',
  '.uiPopOver',
  '.uiCloseButton',
  '.uiChevronSelectorButton',
  'h5._1qbu',
  '.commentable_item'
].join(', ');

const TIMELINE_SELECTOR = '.fbUserContent, .fbUserPost, ._5pcr';
const SIDEBAR_SELECTOR = '.ego_unit';

const cleanAd = (html) => {
  let node = document.createElement("div");
  node.innerHTML = html;

  // We're not saving video ads for now, we don't need buttons, hidden forms,
  // or like links
  Array.from(node.querySelectorAll(selectors))
    .forEach((i) => i.remove());

  // remove attributes
  const killAttrs = (node) => {
    Array.from(node.attributes).forEach(attr => {
      if(attr.name !== "id" &&
         attr.name !== "class" &&
         attr.name !== "src" &&
         attr.name !== "href")
        node.removeAttribute(attr.name);
      // remove tracking get variables from links and l.facebook.com
      if(attr.name === "href") {
        try {
          let url = new URL(attr.value);
          if(url.host === 'l.facebook.com')
            url = new URL(new URLSearchParams(url.search).get("u"));
          if(url.origin && url.pathname) {
            node.setAttribute(attr.name, url.origin + url.pathname);
          } else {
            node.removeAttribute(attr.name);
          }
        } catch(e) {
          node.removeAttribute(attr.name);
        }
      }
    });
    // walk through the tree.
    Array.from(node.children).forEach(killAttrs);
  };
  Array.from(node.children).forEach(killAttrs);
  return node.innerHTML.replace(/&/g, '&');
};

const checkSponsor = (node) => {
  return Array.from(node.querySelectorAll("a")).some((a) => {
    return [
      'Sponsored',
      'Gesponsert',
      'Sponsrad',
      'Sponsorlu',
      'إعلان مُموَّل',
      'Sponsoreret',
      'Sponsorizzata'
    ].some((sponsor) => a.textContent === sponsor);
  });
};

// We have to do this because content scripts can't read window variables
const grabVariable = (fn, args)  => {
  let script = document.createElement("script");
  script.textContent = 'localStorage.setItem("pageVariable", (' + fn + ').apply(this, ' + JSON.stringify(args) + '));';
  script.setAttribute('id', 'pageVariable');
  (document.head||document.documentElement).appendChild(script);
  script.remove();
  return localStorage.getItem("pageVariable");
};

// Getting the targeting information. We're careful to cache any results so as to avoid being
// blocked by facebook.
let targetingBlocked = false;
let targetingCache = new Map();
const getTargeting = (ad) => {
  if(ad.targeting) {
    if(targetingCache.has(ad.targeting)) return {
      ...ad,
      targeting: targetingCache.get(ad.targeting)
    };
    const url = ad.targeting;
    delete ad.targeting;
    if(targetingBlocked) return ad;
    return new Promise((resolve) => {
      let req = new XMLHttpRequest();
      req.onreadystatechange = function() {
        if(req.readyState === 4) {
          try {
            const targeting = cleanAd(JSON.parse(req.response.replace('for (;;);', ''))["jsmods"]["markup"][0][1]["__html"]);
            if(!targeting) {
              return resolve(ad);
            }
            targetingCache.set(url, targeting);
            resolve({
              ...ad,
              targeting
            });
          } catch(e) {
            targetingBlocked = true;
            setTimeout(() => targetingBlocked = false, 15 * 60 * 100);
            resolve(ad);
          }
        }
      };

      // This is all built out from a close reading of facebook's code.
      let built = grabVariable((url) => {
        let parsed = new (window.require('URI'))(url);
        localStorage.setItem('url', url);
        let req = new window.AsyncRequest()
          .setURI(url)
          .setData(parsed)
          .setMethod('GET')
          .setRelativeTo(document.body)
          .setNectarModuleDataSafe(document.body)
          .setReadOnly(true);
        Object.assign(req.data, {__asyncDialog: 1});
        Object.assign(req.data, window.require('getAsyncParams')(req.method));
        req._setUserActionID();
        req.setNewSerial();
        return req.uri.addQueryData(req.data).toString();
      }, [url]);
      // AsyncRequest builds out the correct targeting url
      req.open('GET', "https://www.facebook.com" + built, true);
      req.send();
    });
  } else {
    return ad;
  }
};

// We want to minimize the impact of a user's experience using facebook, so this function tries to
// restore the state of the page when the extension clicks around.
const refocus = (cb) => {
  const focus = document.activeElement;
  cb();
  if(focus) focus.focus();
};

// Getting the extension to show targeting information for timeline ads is hard, so we have this
// gnarly function.
let timelineCache = new Map();
const getTimelineId = (parent, ad) => {
  const control = parent.querySelector(".uiPopover");
  if(!control && control.id === "")
    return null;

  const toggle = control.querySelector("a");
  if(!toggle)
    return null;

  if(timelineCache.has(toggle.id))
    return Promise.resolve(timelineCache.get(toggle.id));

  // this is async, we have to wait until our popup shows up.
  let promise = new Promise((resolve, reject) => {
    let cb = (record, self) => {
      const layer = Array.from(document.querySelectorAll(".uiLayer"))
        .filter((a) => {
          return a.getAttribute("data-ownerid") === toggle.id;
        })[0];
      if(!layer) return null;
      const li = Array.from(layer.querySelectorAll("li"))
        .filter((it) => it.getAttribute("data-feed-option-name") === "FeedAdSeenReasonOption")[0];
      if(!li) return null;
      const endpoint = li.querySelector("a");
      if(!endpoint) return null;
      const url =  endpoint.getAttribute("ajaxify");
      refocus(() => toggle.click());
      self.disconnect();
      try {
        const resolved = {
          ...ad,
          id: new URL("https://facebook.com" + url).searchParams.get("id"),
          targeting: url
        };

        if(resolved.id) {
          timelineCache.set(toggle.id, resolved);
          resolve(resolved);
        } else {
          reject("No ad id");
        }
      } catch(e) {
        reject(e);
      }
    };

    new MutationObserver(cb).observe(document, {childList: true, subtree:true});
  }).then(getTargeting);
  refocus(() => toggle.click());
  return promise;
};

const getSidebarId = (parent, ad) => {
  const control = parent.querySelector(".uiSelectorMenuWrapper");

  //Replicating getTimelineId.
  // Since the sidebar DOM structure is slightly different we need to pull out
  // the toggle Id from the data-gt attribute. I was unable to find a dataowner-id attribute
  const toggle = parent.querySelector('a');
  const toggleData = JSON.parse(toggle.getAttribute('data-gt'));
  const toggleId = toggleData["data_to_log"]["ad_id"];
  if (!toggle && !toggleData)
    return null;

  if (sidebarCache.has(toggleId))
    return Promise.resolve(sidebarCache.get(toggleId));

  // Leaving this here becuase you'll need to test the above code works.
  // console.log(toggle, toggleData)
  let promise = new Promise((resolve, reject) => {
    let cb = (record, self) => {
      const menu = Array.from(document.querySelectorAll(".uiMenu"))

      if(!menu) return null;

      const li = Array.from(layer.querySelectorAll("li"))
        .filter((it) => it.getAttribute("data-label") === "Why am I seeing this?")[0];
      const endpoint = li.querySelector("a");
      if(!endpoint) return null;
      const url =  endpoint.getAttribute("ajaxify");
      refocus(() => toggle.click());
      self.disconnect();
      try {
        const resolved = {
          ...ad,
          id: new URL("https://facebook.com" + url).searchParams.get("id"),
          targeting: url
        };

        if(resolved.id) {
          timelineCache.set(toggleId, resolved);
          resolve(resolved);
        } else {
          reject("No ad id");
        }

      } catch(e) {
        reject(e);
      }
    };
    new MutationObserver(cb).observe(document, {childList: true, subtree:true});
  }).then(getTargeting)

  refocus(() => toggle.click());
  return promise;
}
const timeline = (node) => {
  // First we check if it is actually a sponsored post
  if(!checkSponsor(node)) return Promise.resolve(false);

  // And then we try to grab the parent container that has a hyperfeed id
  let parent = node;
  while(parent) {
    let id = parent.getAttribute("id");
    if(id && id.startsWith("hyperfeed")) break;
    parent = parent.parentElement;
  }

  // If we've walked off the top of the parent heirarchy that's an error
  if(!parent) return Promise.resolve(false);

  // Also if there's nothing to save that's an error
  if(node.children.length === 0) return Promise.resolve(false);

  // Check to see that we have the innermost fbUserContent, this cuts out like's
  // and shares.
  if(node.querySelector(TIMELINE_SELECTOR))
    node = node.querySelector(TIMELINE_SELECTOR);

  // Finally we have something to save.
  return getTimelineId(parent, {
    html: cleanAd(node.children[0].outerHTML),
    created_at: (new Date()).valueOf()
  });
};

// Sidebar ads are a bit more complicated.
const sidebar = (node) => {
  // Although first we still need to make sure we are in a sponsored box;
  let parent = node;
  while(parent) {
    if(checkSponsor(parent)) break;
    parent = parent.parentElement;
  }

  // As before it is an error if we haven't found a sponsor node.
  if(!(parent &&
       parent.classList &&
       parent.classList.contains('ego_section'))) return Promise.resolve(false);

  // Sanity check to make sure we have a salvageable id
  if(!node.hasAttribute("data-ego-fbid")) return Promise.resolve(false);

  // and we have childnodes
  if(!node.children.length === 0) return Promise.resolve(false);
  // Then we just need to sent the cleaned ad and the ego-fbid
  return getSidebarId(parent, {
    id: node.getAttribute("data-ego-fbid"),
    html: cleanAd(node.outerHTML),
    created_at: (new Date()).valueOf()
  });
};

// We are careful here to only accept a valid timeline ad or sidebar ad
const parser = function(node) {
  if(node.classList.contains("fbUserContent") ||
     node.classList.contains("fbUserPost") ||
     node.classList.contains("_5pcr")) {
    return timeline(node);
  } else if(node.classList.contains('ego_unit')) {
    return sidebar(node);
  } else {
    return Promise.resolve(false);
  }
};

module.exports = {
  parser,
  TIMELINE_SELECTOR,
  SIDEBAR_SELECTOR,
};
<commit_msg>sidebar targeting<commit_after>// This function cleans all the elements that could leak user data
// before sending to the server. It also removes any attributes that
// could have personal data so we end up with a clean dom tree.
const selectors = [
  'video',
  'input',
  'button',
  'iframe',
  'a[href=""]',
  '.accessible_elem',
  '.uiLikePagebutton',
  '.uiPopOver',
  '.uiCloseButton',
  '.uiChevronSelectorButton',
  'h5._1qbu',
  '.commentable_item'
].join(', ');

const TIMELINE_SELECTOR = '.fbUserContent, .fbUserPost, ._5pcr';
const SIDEBAR_SELECTOR = '.ego_unit';

const cleanAd = (html) => {
  let node = document.createElement("div");
  node.innerHTML = html;

  // We're not saving video ads for now, we don't need buttons, hidden forms,
  // or like links
  Array.from(node.querySelectorAll(selectors))
    .forEach((i) => i.remove());

  // remove attributes
  const killAttrs = (node) => {
    Array.from(node.attributes).forEach(attr => {
      if(attr.name !== "id" &&
         attr.name !== "class" &&
         attr.name !== "src" &&
         attr.name !== "href")
        node.removeAttribute(attr.name);
      // remove tracking get variables from links and l.facebook.com
      if(attr.name === "href") {
        try {
          let url = new URL(attr.value);
          if(url.host === 'l.facebook.com')
            url = new URL(new URLSearchParams(url.search).get("u"));
          if(url.origin && url.pathname) {
            node.setAttribute(attr.name, url.origin + url.pathname);
          } else {
            node.removeAttribute(attr.name);
          }
        } catch(e) {
          node.removeAttribute(attr.name);
        }
      }
    });
    // walk through the tree.
    Array.from(node.children).forEach(killAttrs);
  };
  Array.from(node.children).forEach(killAttrs);
  return node.innerHTML.replace(/&/g, '&');
};

const checkSponsor = (node) => {
  return Array.from(node.querySelectorAll("a")).some((a) => {
    return [
      'Sponsored',
      'Gesponsert',
      'Sponsrad',
      'Sponsorlu',
      'إعلان مُموَّل',
      'Sponsoreret',
      'Sponsorizzata'
    ].some((sponsor) => a.textContent === sponsor);
  });
};

// We have to do this because content scripts can't read window variables
const grabVariable = (fn, args)  => {
  let script = document.createElement("script");
  script.textContent = 'localStorage.setItem("pageVariable", (' + fn + ').apply(this, ' + JSON.stringify(args) + '));';
  script.setAttribute('id', 'pageVariable');
  (document.head||document.documentElement).appendChild(script);
  script.remove();
  return localStorage.getItem("pageVariable");
};

// Getting the targeting information. We're careful to cache any results so as to avoid being
// blocked by facebook.
let targetingBlocked = false;
let targetingCache = new Map();
const getTargeting = (ad) => {
  if(ad.targeting) {
    if(targetingCache.has(ad.targeting)) return {
      ...ad,
      targeting: targetingCache.get(ad.targeting)
    };
    const url = ad.targeting;
    delete ad.targeting;
    if(targetingBlocked) return ad;
    return new Promise((resolve) => {
      let req = new XMLHttpRequest();
      req.onreadystatechange = function() {
        if(req.readyState === 4) {
          try {
            const targeting = cleanAd(JSON.parse(req.response.replace('for (;;);', ''))["jsmods"]["markup"][0][1]["__html"]);
            if(!targeting) {
              return resolve(ad);
            }
            targetingCache.set(url, targeting);
            resolve({
              ...ad,
              targeting
            });
          } catch(e) {
            targetingBlocked = true;
            setTimeout(() => targetingBlocked = false, 15 * 60 * 100);
            resolve(ad);
          }
        }
      };

      // This is all built out from a close reading of facebook's code.
      let built = grabVariable((url) => {
        let parsed = new (window.require('URI'))(url);
        localStorage.setItem('url', url);
        let req = new window.AsyncRequest()
          .setURI(url)
          .setData(parsed)
          .setMethod('GET')
          .setRelativeTo(document.body)
          .setNectarModuleDataSafe(document.body)
          .setReadOnly(true);
        Object.assign(req.data, {__asyncDialog: 1});
        Object.assign(req.data, window.require('getAsyncParams')(req.method));
        req._setUserActionID();
        req.setNewSerial();
        return req.uri.addQueryData(req.data).toString();
      }, [url]);
      // AsyncRequest builds out the correct targeting url
      req.open('GET', "https://www.facebook.com" + built, true);
      req.send();
    });
  } else {
    return ad;
  }
};

// We want to minimize the impact of a user's experience using facebook, so this function tries to
// restore the state of the page when the extension clicks around.
const refocus = (cb) => {
  const focus = document.activeElement;
  cb();
  if(focus) focus.focus();
};

// All of the menus on Facebook are asyncronously opened so we have to use a observer here to make
// sure we can grab the targeting urls
let adCache = new Map();
const parseMenu = (ad, selector, toggle, toggleId, filter) => ((resolve, reject) => {
  let cb = (record, self) => {
    const menu = Array.from(document.querySelectorAll(selector));
    if(!menu) return reject(null);
    const li = Array.from(menu.querySelectorAll("li"))
      .filter(filter)[0];
    const endpoint = li.querySelector("a");
    if(!endpoint) return reject(null);
    const url = endpoint.getAttribute("ajaxify");
    refocus(() => toggle.click());
    self.disconnect();
    try {
      const resolved = {
        ...ad,
        id: new URL("https://facebook.com" + url).searchParams.get("id"),
        targeting: url
      };

      if(resolved.id) {
        adCache.set(toggleId, resolved);
        resolve(resolved);
      } else {
        reject("No ad id");
      }
    } catch(e) {
      reject(e);
    }
  };
  new MutationObserver(cb).observe(document, {childList: true, subtree:true});
  refocus(() => toggle.click());
});

// Grab an id from a timeline ad which is hidden in a async popup.
const getTimelineId = (parent, ad) => {
  const control = parent.querySelector(".uiPopover");
  if(!control && control.id === "")
    return null;

  const toggle = control.querySelector("a");
  if(!toggle)
    return null;

  if(adCache.has(toggle.id))
    return Promise.resolve(adCache.get(toggle.id));

  // this is async, we have to wait until our popup shows up.
  let promise = new Promise(parseMenu(ad, ".uiLayer", toggle, toggle.id, (it) => (
    it.getAttribute("data-feed-option-name") === "FeedAdSeenReasonOption")
  )).then(getTargeting);
  return promise;
};

// Similar to the above -- while we could just use the data-ego-fbid from before, it makes sense to
// use the one in the encoded url in case that the dom one goes away.
const getSidebarId = (parent, ad) => {
  const control = parent.querySelector(".uiSelectorMenuWrapper");
  if(!control)
    return null;
  //Replicating getTimelineId.
  // Since the sidebar DOM structure is slightly different we need to pull out
  // the toggle Id from the data-gt attribute.
  const toggle = control.querySelector('a');
  if(!toggle)
    return null;

  const toggleData = JSON.parse(toggle.getAttribute('data-gt'));
  if(!toggleData["data_to_log"])
    return null;

  const toggleId = toggleData["data_to_log"]["ad_id"];
  if (!toggleId)
    return null;

  if (adCache.has(toggleId))
    return Promise.resolve(adCache.get(toggleId));

  // Leaving this here becuase you'll need to test the above code works.
  console.log(toggle, toggleData);
  let promise = new Promise(parseMenu(ad, ".uiMenu", toggle, toggleId, (it) => (
    it.getAttribute("data-label") === "Why am I seeing this?")
  )).then(getTargeting);

  return promise;
};

const timeline = (node) => {
  // First we check if it is actually a sponsored post
  if(!checkSponsor(node)) return Promise.resolve(false);

  // And then we try to grab the parent container that has a hyperfeed id
  let parent = node;
  while(parent) {
    let id = parent.getAttribute("id");
    if(id && id.startsWith("hyperfeed")) break;
    parent = parent.parentElement;
  }

  // If we've walked off the top of the parent heirarchy that's an error
  if(!parent) return Promise.resolve(false);

  // Also if there's nothing to save that's an error
  if(node.children.length === 0) return Promise.resolve(false);

  // Check to see that we have the innermost fbUserContent, this cuts out like's
  // and shares.
  if(node.querySelector(TIMELINE_SELECTOR))
    node = node.querySelector(TIMELINE_SELECTOR);

  // Finally we have something to save.
  return getTimelineId(parent, {
    html: cleanAd(node.children[0].outerHTML),
    created_at: (new Date()).valueOf()
  });
};

// Sidebar ads are a bit more complicated.
const sidebar = (node) => {
  // Although first we still need to make sure we are in a sponsored box;
  let parent = node;
  while(parent) {
    if(checkSponsor(parent)) break;
    parent = parent.parentElement;
  }

  // As before it is an error if we haven't found a sponsor node.
  if(!(parent &&
       parent.classList &&
       parent.classList.contains('ego_section'))) return Promise.resolve(false);

  // Sanity check to make sure we have a salvageable id
  if(!node.hasAttribute("data-ego-fbid")) return Promise.resolve(false);

  // and we have childnodes
  if(!node.children.length === 0) return Promise.resolve(false);
  // Then we just need to send the cleaned ad
  return getSidebarId(parent, {
    html: cleanAd(node.outerHTML),
    created_at: (new Date()).valueOf()
  });
};

// We are careful here to only accept a valid timeline ad or sidebar ad
const parser = function(node) {
  if(node.classList.contains("fbUserContent") ||
     node.classList.contains("fbUserPost") ||
     node.classList.contains("_5pcr")) {
    return timeline(node);
  } else if(node.classList.contains('ego_unit')) {
    return sidebar(node);
  } else {
    return Promise.resolve(false);
  }
};

module.exports = {
  parser,
  TIMELINE_SELECTOR,
  SIDEBAR_SELECTOR,
};
<|endoftext|>


<commit_before>var Promise = require('bluebird');
var google = require('googleapis');
var tables = Promise.promisifyAll(google.bigquery('v2').tables);
var tabledata = Promise.promisifyAll(google.bigquery('v2').tabledata);
var jobs = Promise.promisifyAll(google.bigquery('v2').jobs);
var uuid = require('node-uuid');
var _ = require('lodash');
var type = require('type-of');

var session = require('./session');

/**
 * Creates a new BigQuery Table of the designated properties.
 * @param {Object} props
 * @param {String} props.projectId
 * @param {String} props.datasetId
 * @param {String} props.tableId
 * @param {Object} [props.schema]
 */
function Table(props) {
  this.projectId = props.projectId;
  this.datasetId = props.datasetId;
  this.tableId = props.tableId;
  this.schema = props.schema || null;
}

/**
 * Sets the projectId property of this table.
 * @param {String} projectId
 * @return {@this}
 */
Table.prototype.setProjectId = function (projectId) {
  if (!_.isString(projectId)) {
    throw new Error('Invalid projectId argument; expected string, received ' + type(projectId));
  }

  this.projectId = projectId;
  return this;
};

/**
 * Sets the datasetId property of this table.
 * @param {String} projectId
 * @return {@this}
 */
Table.prototype.setDatasetId = function (datasetId) {
  if (!_.isString(datasetId)) {
    throw new Error('Invalid datasetId argument; expected string, received ' + type(datasetId));
  }

  this.datasetId = datasetId;
  return this;
};

/**
 * Sets the tableId property of this table.
 * @param {String} projectId
 * @return {@this}
 */
Table.prototype.setTableId = function (tableId) {
  if (!_.isString(tableId)) {
    throw new Error('Invalid tableId argument; expected string, received ' + type(tableId));
  }

  this.tableId = tableId;
  return this;
};

/**
 * Registers (creates) the table in database.
 * @param {Function} [callback]
 * @return {Promise}
 */
Table.prototype.register = function (callback) {
  var _this = this;

  return tables.insertAsync({
    projectId: this.projectId,
    datasetId: this.datasetId,
    resource: {
      kind: 'bigquery#table',
      tableReference: {
        datasetId: this.datasetId,
        projectId: this.projectId,
        tableId: this.tableId
      },
      description: this.description,
      schema: this.schema
    }
  })

    .spread(function (data) {
      return data.id;
    })

    .catch(function (err) {
      // check if table already exists
      if (err.code === 409) {
        return _this.projectId + ':' + _this.datasetId + '.' + _this.tableId;
      }

      throw err;
    })

    .nodeify(callback);
};

/**
 * Appends the specified records to table.
 * @param {Object, Array<Object>} records
 * @param {Function} [callback]
 * @return {Promise}
 */
Table.prototype.push = function (records, callback, _attempt) {
  var _this = this;

  _attempt = _attempt || 0;

  // make sure records is array
  if (!_.isArray(records)) records = _.toArray(arguments);

  // prepare records for insert
  records = records.map(function (e) {
    return {
      insertId: uuid.v4(),
      json: e
    };
  });

  return tabledata.insertAllAsync({
    projectId: this.projectId,
    datasetId: this.datasetId,
    tableId: this.tableId,
    resource: {
      rows: records
    }
  })

    .spread(function (data) {
      // check if errors exist
      if (data.insertErrors) {
        throw _.assign(new Error(), data.insertErrors[0].errors[0]);
      }

      return data;
    })

    .catch(function (err) {
      // check if session has expired
      if (err.code === 401 && _attempt === 0) {
        return session.renew()
          .then(function () {
            return _this.push(records, callback, _attempt + 1);
          });
      }
    })

    .nodeify(callback);
};

/**
 * Runs the designated SQL query and returns the results.
 * @param {String} sql
 * @param {Function} [callback]
 * @return {Promise}
 */
Table.prototype.query = function (sql, callback, _attempt) {
  var _this = this;

  _attempt = _attempt || 0;

  return jobs.queryAsync({
    projectId: this.projectId,
    resource: {
      query: sql,
      useQueryCache: true,
      defaultDataset: {
        datasetId: this.datasetId,
        projectId: this.projectId
      }
    }
  })

    .catch(function (err) {
      // check if session has expired
      if (err.code === 401 && _attempt === 0) {
        return session.renew()
          .then(function () {
            return _this.query(sql, callback, _attempt + 1);
          });
      }
    })

    .nodeify(callback);
};

module.exports = Table;
<commit_msg>Bugfix: Don't supress errors on #push<commit_after>var Promise = require('bluebird');
var google = require('googleapis');
var tables = Promise.promisifyAll(google.bigquery('v2').tables);
var tabledata = Promise.promisifyAll(google.bigquery('v2').tabledata);
var jobs = Promise.promisifyAll(google.bigquery('v2').jobs);
var uuid = require('node-uuid');
var _ = require('lodash');
var type = require('type-of');

var session = require('./session');

/**
 * Creates a new BigQuery Table of the designated properties.
 * @param {Object} props
 * @param {String} props.projectId
 * @param {String} props.datasetId
 * @param {String} props.tableId
 * @param {Object} [props.schema]
 */
function Table(props) {
  this.projectId = props.projectId;
  this.datasetId = props.datasetId;
  this.tableId = props.tableId;
  this.schema = props.schema || null;
}

/**
 * Sets the projectId property of this table.
 * @param {String} projectId
 * @return {@this}
 */
Table.prototype.setProjectId = function (projectId) {
  if (!_.isString(projectId)) {
    throw new Error('Invalid projectId argument; expected string, received ' + type(projectId));
  }

  this.projectId = projectId;
  return this;
};

/**
 * Sets the datasetId property of this table.
 * @param {String} projectId
 * @return {@this}
 */
Table.prototype.setDatasetId = function (datasetId) {
  if (!_.isString(datasetId)) {
    throw new Error('Invalid datasetId argument; expected string, received ' + type(datasetId));
  }

  this.datasetId = datasetId;
  return this;
};

/**
 * Sets the tableId property of this table.
 * @param {String} projectId
 * @return {@this}
 */
Table.prototype.setTableId = function (tableId) {
  if (!_.isString(tableId)) {
    throw new Error('Invalid tableId argument; expected string, received ' + type(tableId));
  }

  this.tableId = tableId;
  return this;
};

/**
 * Registers (creates) the table in database.
 * @param {Function} [callback]
 * @return {Promise}
 */
Table.prototype.register = function (callback) {
  var _this = this;

  return tables.insertAsync({
    projectId: this.projectId,
    datasetId: this.datasetId,
    resource: {
      kind: 'bigquery#table',
      tableReference: {
        datasetId: this.datasetId,
        projectId: this.projectId,
        tableId: this.tableId
      },
      description: this.description,
      schema: this.schema
    }
  })

    .spread(function (data) {
      return data.id;
    })

    .catch(function (err) {
      // check if table already exists
      if (err.code === 409) {
        return _this.projectId + ':' + _this.datasetId + '.' + _this.tableId;
      }

      throw err;
    })

    .nodeify(callback);
};

/**
 * Appends the specified records to table.
 * @param {Object, Array<Object>} records
 * @param {Function} [callback]
 * @return {Promise}
 */
Table.prototype.push = function (records, callback, _attempt) {
  var _this = this;

  _attempt = _attempt || 0;

  // make sure records is array
  if (!_.isArray(records)) records = _.toArray(arguments);

  // prepare records for insert
  records = records.map(function (e) {
    return {
      insertId: uuid.v4(),
      json: e
    };
  });

  return tabledata.insertAllAsync({
    projectId: this.projectId,
    datasetId: this.datasetId,
    tableId: this.tableId,
    resource: {
      rows: records
    }
  })

    .spread(function (data) {
      // check if errors exist
      if (data.insertErrors) {
        throw _.assign(new Error(), data.insertErrors[0].errors[0]);
      }

      return data;
    })

    .catch(function (err) {
      // check if session has expired
      if (err.code === 401 && _attempt === 0) {
        return session.renew()
          .then(function () {
            return _this.push(records, callback, _attempt + 1);
          });
      }

      throw err;
    })

    .nodeify(callback);
};

/**
 * Runs the designated SQL query and returns the results.
 * @param {String} sql
 * @param {Function} [callback]
 * @return {Promise}
 */
Table.prototype.query = function (sql, callback, _attempt) {
  var _this = this;

  _attempt = _attempt || 0;

  return jobs.queryAsync({
    projectId: this.projectId,
    resource: {
      query: sql,
      useQueryCache: true,
      defaultDataset: {
        datasetId: this.datasetId,
        projectId: this.projectId
      }
    }
  })

    .catch(function (err) {
      // check if session has expired
      if (err.code === 401 && _attempt === 0) {
        return session.renew()
          .then(function () {
            return _this.query(sql, callback, _attempt + 1);
          });
      }
    })

    .nodeify(callback);
};

module.exports = Table;
<|endoftext|>


<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 * @author Larry Battle / http://bateru.com/news
 */

var THREE = THREE || { REVISION: '52' };

self.console = self.console || {

	info: function () {},
	log: function () {},
	debug: function () {},
	warn: function () {},
	error: function () {}

};

self.Int32Array = self.Int32Array || Array;
self.Float32Array = self.Float32Array || Array;

// Shims for "startsWith", "endsWith", and "trim" for browsers where this is not yet implemented
// not sure we should have this, or at least not have it here

// http://stackoverflow.com/questions/646628/javascript-startswith
// http://stackoverflow.com/questions/498970/how-do-i-trim-a-string-in-javascript
// http://wiki.ecmascript.org/doku.php?id=harmony%3astring_extras

String.prototype.startsWith = String.prototype.startsWith || function ( str ) {

	return this.slice( 0, str.length ) === str;

};

String.prototype.endsWith = String.prototype.endsWith || function ( str ) {

	var t = String( str );
	var index = this.lastIndexOf( t );
	return ( -1 < index && index ) === (this.length - t.length);

};

String.prototype.trim = String.prototype.trim || function () {

	return this.replace( /^\s+|\s+$/g, '' );

};

// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating

// requestAnimationFrame polyfill by Erik Möller
// fixes from Paul Irish and Tino Zijdel

( function () {

	var lastTime = 0;
	var vendors = [ 'ms', 'moz', 'webkit', 'o' ];

	for ( var x = 0; x < vendors.length && !window.requestAnimationFrame; ++ x ) {

		window.requestAnimationFrame = window[ vendors[ x ] + 'RequestAnimationFrame' ];
		window.cancelAnimationFrame = window[ vendors[ x ] + 'CancelAnimationFrame' ] || window[ vendors[ x ] + 'CancelRequestAnimationFrame' ];

	}

	if ( window.requestAnimationFrame === undefined ) {

		window.requestAnimationFrame = function ( callback, element ) {

			var currTime = Date.now(), timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
			var id = window.setTimeout( function() { callback( currTime + timeToCall ); }, timeToCall );
			lastTime = currTime + timeToCall;
			return id;

		};

	}

	window.cancelAnimationFrame = window.cancelAnimationFrame || function ( id ) { window.clearTimeout( id ) };

}() );

// MATERIAL CONSTANTS

// side

THREE.FrontSide = 0;
THREE.BackSide = 1;
THREE.DoubleSide = 2;

// shading

THREE.NoShading = 0;
THREE.FlatShading = 1;
THREE.SmoothShading = 2;

// colors

THREE.NoColors = 0;
THREE.FaceColors = 1;
THREE.VertexColors = 2;

// blending modes

THREE.NoBlending = 0;
THREE.NormalBlending = 1;
THREE.AdditiveBlending = 2;
THREE.SubtractiveBlending = 3;
THREE.MultiplyBlending = 4;
THREE.CustomBlending = 5;

// custom blending equations
// (numbers start from 100 not to clash with other
//  mappings to OpenGL constants defined in Texture.js)

THREE.AddEquation = 100;
THREE.SubtractEquation = 101;
THREE.ReverseSubtractEquation = 102;

// custom blending destination factors

THREE.ZeroFactor = 200;
THREE.OneFactor = 201;
THREE.SrcColorFactor = 202;
THREE.OneMinusSrcColorFactor = 203;
THREE.SrcAlphaFactor = 204;
THREE.OneMinusSrcAlphaFactor = 205;
THREE.DstAlphaFactor = 206;
THREE.OneMinusDstAlphaFactor = 207;

// custom blending source factors

//THREE.ZeroFactor = 200;
//THREE.OneFactor = 201;
//THREE.SrcAlphaFactor = 204;
//THREE.OneMinusSrcAlphaFactor = 205;
//THREE.DstAlphaFactor = 206;
//THREE.OneMinusDstAlphaFactor = 207;
THREE.DstColorFactor = 208;
THREE.OneMinusDstColorFactor = 209;
THREE.SrcAlphaSaturateFactor = 210;

// TEXTURE CONSTANTS

THREE.MultiplyOperation = 0;
THREE.MixOperation = 1;

// Mapping modes

THREE.UVMapping = function () {};

THREE.CubeReflectionMapping = function () {};
THREE.CubeRefractionMapping = function () {};

THREE.SphericalReflectionMapping = function () {};
THREE.SphericalRefractionMapping = function () {};

// Wrapping modes

THREE.RepeatWrapping = 1000;
THREE.ClampToEdgeWrapping = 1001;
THREE.MirroredRepeatWrapping = 1002;

// Filters

THREE.NearestFilter = 1003;
THREE.NearestMipMapNearestFilter = 1004;
THREE.NearestMipMapLinearFilter = 1005;
THREE.LinearFilter = 1006;
THREE.LinearMipMapNearestFilter = 1007;
THREE.LinearMipMapLinearFilter = 1008;

// Data types

THREE.UnsignedByteType = 1009;
THREE.ByteType = 1010;
THREE.ShortType = 1011;
THREE.UnsignedShortType = 1012;
THREE.IntType = 1013;
THREE.UnsignedIntType = 1014;
THREE.FloatType = 1015;

// Pixel types

//THREE.UnsignedByteType = 1009;
THREE.UnsignedShort4444Type = 1016;
THREE.UnsignedShort5551Type = 1017;
THREE.UnsignedShort565Type = 1018;

// Pixel formats

THREE.AlphaFormat = 1019;
THREE.RGBFormat = 1020;
THREE.RGBAFormat = 1021;
THREE.LuminanceFormat = 1022;
THREE.LuminanceAlphaFormat = 1023;

// Compressed texture formats

THREE.RGB_S3TC_DXT1_Format = 2001;
THREE.RGBA_S3TC_DXT1_Format = 2002;
THREE.RGBA_S3TC_DXT3_Format = 2003;
THREE.RGBA_S3TC_DXT5_Format = 2004;

/*
// Potential future PVRTC compressed texture formats
THREE.RGB_PVRTC_4BPPV1_Format = 2100;
THREE.RGB_PVRTC_2BPPV1_Format = 2101;
THREE.RGBA_PVRTC_4BPPV1_Format = 2102;
THREE.RGBA_PVRTC_2BPPV1_Format = 2103;
*/
<commit_msg>r53dev<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 * @author Larry Battle / http://bateru.com/news
 */

var THREE = THREE || { REVISION: '53dev' };

self.console = self.console || {

	info: function () {},
	log: function () {},
	debug: function () {},
	warn: function () {},
	error: function () {}

};

self.Int32Array = self.Int32Array || Array;
self.Float32Array = self.Float32Array || Array;

// Shims for "startsWith", "endsWith", and "trim" for browsers where this is not yet implemented
// not sure we should have this, or at least not have it here

// http://stackoverflow.com/questions/646628/javascript-startswith
// http://stackoverflow.com/questions/498970/how-do-i-trim-a-string-in-javascript
// http://wiki.ecmascript.org/doku.php?id=harmony%3astring_extras

String.prototype.startsWith = String.prototype.startsWith || function ( str ) {

	return this.slice( 0, str.length ) === str;

};

String.prototype.endsWith = String.prototype.endsWith || function ( str ) {

	var t = String( str );
	var index = this.lastIndexOf( t );
	return ( -1 < index && index ) === (this.length - t.length);

};

String.prototype.trim = String.prototype.trim || function () {

	return this.replace( /^\s+|\s+$/g, '' );

};

// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating

// requestAnimationFrame polyfill by Erik Möller
// fixes from Paul Irish and Tino Zijdel

( function () {

	var lastTime = 0;
	var vendors = [ 'ms', 'moz', 'webkit', 'o' ];

	for ( var x = 0; x < vendors.length && !window.requestAnimationFrame; ++ x ) {

		window.requestAnimationFrame = window[ vendors[ x ] + 'RequestAnimationFrame' ];
		window.cancelAnimationFrame = window[ vendors[ x ] + 'CancelAnimationFrame' ] || window[ vendors[ x ] + 'CancelRequestAnimationFrame' ];

	}

	if ( window.requestAnimationFrame === undefined ) {

		window.requestAnimationFrame = function ( callback, element ) {

			var currTime = Date.now(), timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
			var id = window.setTimeout( function() { callback( currTime + timeToCall ); }, timeToCall );
			lastTime = currTime + timeToCall;
			return id;

		};

	}

	window.cancelAnimationFrame = window.cancelAnimationFrame || function ( id ) { window.clearTimeout( id ) };

}() );

// MATERIAL CONSTANTS

// side

THREE.FrontSide = 0;
THREE.BackSide = 1;
THREE.DoubleSide = 2;

// shading

THREE.NoShading = 0;
THREE.FlatShading = 1;
THREE.SmoothShading = 2;

// colors

THREE.NoColors = 0;
THREE.FaceColors = 1;
THREE.VertexColors = 2;

// blending modes

THREE.NoBlending = 0;
THREE.NormalBlending = 1;
THREE.AdditiveBlending = 2;
THREE.SubtractiveBlending = 3;
THREE.MultiplyBlending = 4;
THREE.CustomBlending = 5;

// custom blending equations
// (numbers start from 100 not to clash with other
//  mappings to OpenGL constants defined in Texture.js)

THREE.AddEquation = 100;
THREE.SubtractEquation = 101;
THREE.ReverseSubtractEquation = 102;

// custom blending destination factors

THREE.ZeroFactor = 200;
THREE.OneFactor = 201;
THREE.SrcColorFactor = 202;
THREE.OneMinusSrcColorFactor = 203;
THREE.SrcAlphaFactor = 204;
THREE.OneMinusSrcAlphaFactor = 205;
THREE.DstAlphaFactor = 206;
THREE.OneMinusDstAlphaFactor = 207;

// custom blending source factors

//THREE.ZeroFactor = 200;
//THREE.OneFactor = 201;
//THREE.SrcAlphaFactor = 204;
//THREE.OneMinusSrcAlphaFactor = 205;
//THREE.DstAlphaFactor = 206;
//THREE.OneMinusDstAlphaFactor = 207;
THREE.DstColorFactor = 208;
THREE.OneMinusDstColorFactor = 209;
THREE.SrcAlphaSaturateFactor = 210;

// TEXTURE CONSTANTS

THREE.MultiplyOperation = 0;
THREE.MixOperation = 1;

// Mapping modes

THREE.UVMapping = function () {};

THREE.CubeReflectionMapping = function () {};
THREE.CubeRefractionMapping = function () {};

THREE.SphericalReflectionMapping = function () {};
THREE.SphericalRefractionMapping = function () {};

// Wrapping modes

THREE.RepeatWrapping = 1000;
THREE.ClampToEdgeWrapping = 1001;
THREE.MirroredRepeatWrapping = 1002;

// Filters

THREE.NearestFilter = 1003;
THREE.NearestMipMapNearestFilter = 1004;
THREE.NearestMipMapLinearFilter = 1005;
THREE.LinearFilter = 1006;
THREE.LinearMipMapNearestFilter = 1007;
THREE.LinearMipMapLinearFilter = 1008;

// Data types

THREE.UnsignedByteType = 1009;
THREE.ByteType = 1010;
THREE.ShortType = 1011;
THREE.UnsignedShortType = 1012;
THREE.IntType = 1013;
THREE.UnsignedIntType = 1014;
THREE.FloatType = 1015;

// Pixel types

//THREE.UnsignedByteType = 1009;
THREE.UnsignedShort4444Type = 1016;
THREE.UnsignedShort5551Type = 1017;
THREE.UnsignedShort565Type = 1018;

// Pixel formats

THREE.AlphaFormat = 1019;
THREE.RGBFormat = 1020;
THREE.RGBAFormat = 1021;
THREE.LuminanceFormat = 1022;
THREE.LuminanceAlphaFormat = 1023;

// Compressed texture formats

THREE.RGB_S3TC_DXT1_Format = 2001;
THREE.RGBA_S3TC_DXT1_Format = 2002;
THREE.RGBA_S3TC_DXT3_Format = 2003;
THREE.RGBA_S3TC_DXT5_Format = 2004;

/*
// Potential future PVRTC compressed texture formats
THREE.RGB_PVRTC_4BPPV1_Format = 2100;
THREE.RGB_PVRTC_2BPPV1_Format = 2101;
THREE.RGBA_PVRTC_4BPPV1_Format = 2102;
THREE.RGBA_PVRTC_2BPPV1_Format = 2103;
*/
<|endoftext|>


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

var THREE = { REVISION: '70dev' };

// browserify support

if ( typeof module === 'object' ) {

	module.exports = THREE;

}

// polyfills

if ( Math.sign === undefined ) {

	Math.sign = function ( x ) {

		return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : 0;

	};

}

THREE.ConsoleErrorHandler = function() {
	console.error( arguments );
};

THREE.ConsoleWarningHandler = function() {
	console.warn( arguments );
};

THREE.ConsoleLogHandler = function() {
	console.log( arguments );
};

// set the default error handlers
THREE.error = THREE.ConsoleErrorHandler;
THREE.warning = THREE.ConsoleWarningHandler;
THREE.log = THREE.ConsoleLogHandler;

// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent.button

THREE.MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };

// GL STATE CONSTANTS

THREE.CullFaceNone = 0;
THREE.CullFaceBack = 1;
THREE.CullFaceFront = 2;
THREE.CullFaceFrontBack = 3;

THREE.FrontFaceDirectionCW = 0;
THREE.FrontFaceDirectionCCW = 1;

// SHADOWING TYPES

THREE.BasicShadowMap = 0;
THREE.PCFShadowMap = 1;
THREE.PCFSoftShadowMap = 2;

// MATERIAL CONSTANTS

// side

THREE.FrontSide = 0;
THREE.BackSide = 1;
THREE.DoubleSide = 2;

// shading

THREE.NoShading = 0;
THREE.FlatShading = 1;
THREE.SmoothShading = 2;

// colors

THREE.NoColors = 0;
THREE.FaceColors = 1;
THREE.VertexColors = 2;

// blending modes

THREE.NoBlending = 0;
THREE.NormalBlending = 1;
THREE.AdditiveBlending = 2;
THREE.SubtractiveBlending = 3;
THREE.MultiplyBlending = 4;
THREE.CustomBlending = 5;

// custom blending equations
// (numbers start from 100 not to clash with other
//  mappings to OpenGL constants defined in Texture.js)

THREE.AddEquation = 100;
THREE.SubtractEquation = 101;
THREE.ReverseSubtractEquation = 102;
THREE.MinEquation = 103;
THREE.MaxEquation = 104;

// custom blending destination factors

THREE.ZeroFactor = 200;
THREE.OneFactor = 201;
THREE.SrcColorFactor = 202;
THREE.OneMinusSrcColorFactor = 203;
THREE.SrcAlphaFactor = 204;
THREE.OneMinusSrcAlphaFactor = 205;
THREE.DstAlphaFactor = 206;
THREE.OneMinusDstAlphaFactor = 207;

// custom blending source factors

//THREE.ZeroFactor = 200;
//THREE.OneFactor = 201;
//THREE.SrcAlphaFactor = 204;
//THREE.OneMinusSrcAlphaFactor = 205;
//THREE.DstAlphaFactor = 206;
//THREE.OneMinusDstAlphaFactor = 207;
THREE.DstColorFactor = 208;
THREE.OneMinusDstColorFactor = 209;
THREE.SrcAlphaSaturateFactor = 210;

// TEXTURE CONSTANTS

THREE.MultiplyOperation = 0;
THREE.MixOperation = 1;
THREE.AddOperation = 2;

// Mapping modes

THREE.UVMapping = 300;

THREE.CubeReflectionMapping = 301;
THREE.CubeRefractionMapping = 302;

THREE.EquirectangularReflectionMapping = 303;
THREE.EquirectangularRefractionMapping = 304;

THREE.SphericalReflectionMapping = 305;

// Wrapping modes

THREE.RepeatWrapping = 1000;
THREE.ClampToEdgeWrapping = 1001;
THREE.MirroredRepeatWrapping = 1002;

// Filters

THREE.NearestFilter = 1003;
THREE.NearestMipMapNearestFilter = 1004;
THREE.NearestMipMapLinearFilter = 1005;
THREE.LinearFilter = 1006;
THREE.LinearMipMapNearestFilter = 1007;
THREE.LinearMipMapLinearFilter = 1008;

// Data types

THREE.UnsignedByteType = 1009;
THREE.ByteType = 1010;
THREE.ShortType = 1011;
THREE.UnsignedShortType = 1012;
THREE.IntType = 1013;
THREE.UnsignedIntType = 1014;
THREE.FloatType = 1015;

// Pixel types

//THREE.UnsignedByteType = 1009;
THREE.UnsignedShort4444Type = 1016;
THREE.UnsignedShort5551Type = 1017;
THREE.UnsignedShort565Type = 1018;

// Pixel formats

THREE.AlphaFormat = 1019;
THREE.RGBFormat = 1020;
THREE.RGBAFormat = 1021;
THREE.LuminanceFormat = 1022;
THREE.LuminanceAlphaFormat = 1023;
// THREE.RGBEFormat handled as THREE.RGBAFormat in shaders
THREE.RGBEFormat = THREE.RGBAFormat; //1024;

// DDS / ST3C Compressed texture formats

THREE.RGB_S3TC_DXT1_Format = 2001;
THREE.RGBA_S3TC_DXT1_Format = 2002;
THREE.RGBA_S3TC_DXT3_Format = 2003;
THREE.RGBA_S3TC_DXT5_Format = 2004;

// PVRTC compressed texture formats

THREE.RGB_PVRTC_4BPPV1_Format = 2100;
THREE.RGB_PVRTC_2BPPV1_Format = 2101;
THREE.RGBA_PVRTC_4BPPV1_Format = 2102;
THREE.RGBA_PVRTC_2BPPV1_Format = 2103;

// DEPRECATED

THREE.Projector = function () {

	THREE.error( 'THREE.Projector has been moved to /examples/js/renderers/Projector.js.' );

	this.projectVector = function ( vector, camera ) {

		THREE.warning( 'THREE.Projector: .projectVector() is now vector.project().' );
		vector.project( camera );

	};

	this.unprojectVector = function ( vector, camera ) {

		THREE.warning( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
		vector.unproject( camera );

	};

	this.pickingRay = function ( vector, camera ) {

		THREE.error( 'THREE.Projector: .pickingRay() has been removed.' );

	};

};

THREE.CanvasRenderer = function () {

	THREE.error( 'THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js' );

	this.domElement = document.createElement( 'canvas' );
	this.clear = function () {};
	this.render = function () {};
	this.setClearColor = function () {};
	this.setSize = function () {};

};
<commit_msg>simplify THREE.error/warning/log redirects to console.*<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 */

var THREE = { REVISION: '70dev' };

// browserify support

if ( typeof module === 'object' ) {

	module.exports = THREE;

}

// polyfills

if ( Math.sign === undefined ) {

	Math.sign = function ( x ) {

		return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : 0;

	};

}

// set the default log handlers
THREE.error = function() { console.error.apply( console, arguments ); }
THREE.warning = function() { console.warn.apply( console, arguments ); }
THREE.log = function() { console.log.apply( console, arguments ); }

// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent.button

THREE.MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };

// GL STATE CONSTANTS

THREE.CullFaceNone = 0;
THREE.CullFaceBack = 1;
THREE.CullFaceFront = 2;
THREE.CullFaceFrontBack = 3;

THREE.FrontFaceDirectionCW = 0;
THREE.FrontFaceDirectionCCW = 1;

// SHADOWING TYPES

THREE.BasicShadowMap = 0;
THREE.PCFShadowMap = 1;
THREE.PCFSoftShadowMap = 2;

// MATERIAL CONSTANTS

// side

THREE.FrontSide = 0;
THREE.BackSide = 1;
THREE.DoubleSide = 2;

// shading

THREE.NoShading = 0;
THREE.FlatShading = 1;
THREE.SmoothShading = 2;

// colors

THREE.NoColors = 0;
THREE.FaceColors = 1;
THREE.VertexColors = 2;

// blending modes

THREE.NoBlending = 0;
THREE.NormalBlending = 1;
THREE.AdditiveBlending = 2;
THREE.SubtractiveBlending = 3;
THREE.MultiplyBlending = 4;
THREE.CustomBlending = 5;

// custom blending equations
// (numbers start from 100 not to clash with other
//  mappings to OpenGL constants defined in Texture.js)

THREE.AddEquation = 100;
THREE.SubtractEquation = 101;
THREE.ReverseSubtractEquation = 102;
THREE.MinEquation = 103;
THREE.MaxEquation = 104;

// custom blending destination factors

THREE.ZeroFactor = 200;
THREE.OneFactor = 201;
THREE.SrcColorFactor = 202;
THREE.OneMinusSrcColorFactor = 203;
THREE.SrcAlphaFactor = 204;
THREE.OneMinusSrcAlphaFactor = 205;
THREE.DstAlphaFactor = 206;
THREE.OneMinusDstAlphaFactor = 207;

// custom blending source factors

//THREE.ZeroFactor = 200;
//THREE.OneFactor = 201;
//THREE.SrcAlphaFactor = 204;
//THREE.OneMinusSrcAlphaFactor = 205;
//THREE.DstAlphaFactor = 206;
//THREE.OneMinusDstAlphaFactor = 207;
THREE.DstColorFactor = 208;
THREE.OneMinusDstColorFactor = 209;
THREE.SrcAlphaSaturateFactor = 210;

// TEXTURE CONSTANTS

THREE.MultiplyOperation = 0;
THREE.MixOperation = 1;
THREE.AddOperation = 2;

// Mapping modes

THREE.UVMapping = 300;

THREE.CubeReflectionMapping = 301;
THREE.CubeRefractionMapping = 302;

THREE.EquirectangularReflectionMapping = 303;
THREE.EquirectangularRefractionMapping = 304;

THREE.SphericalReflectionMapping = 305;

// Wrapping modes

THREE.RepeatWrapping = 1000;
THREE.ClampToEdgeWrapping = 1001;
THREE.MirroredRepeatWrapping = 1002;

// Filters

THREE.NearestFilter = 1003;
THREE.NearestMipMapNearestFilter = 1004;
THREE.NearestMipMapLinearFilter = 1005;
THREE.LinearFilter = 1006;
THREE.LinearMipMapNearestFilter = 1007;
THREE.LinearMipMapLinearFilter = 1008;

// Data types

THREE.UnsignedByteType = 1009;
THREE.ByteType = 1010;
THREE.ShortType = 1011;
THREE.UnsignedShortType = 1012;
THREE.IntType = 1013;
THREE.UnsignedIntType = 1014;
THREE.FloatType = 1015;

// Pixel types

//THREE.UnsignedByteType = 1009;
THREE.UnsignedShort4444Type = 1016;
THREE.UnsignedShort5551Type = 1017;
THREE.UnsignedShort565Type = 1018;

// Pixel formats

THREE.AlphaFormat = 1019;
THREE.RGBFormat = 1020;
THREE.RGBAFormat = 1021;
THREE.LuminanceFormat = 1022;
THREE.LuminanceAlphaFormat = 1023;
// THREE.RGBEFormat handled as THREE.RGBAFormat in shaders
THREE.RGBEFormat = THREE.RGBAFormat; //1024;

// DDS / ST3C Compressed texture formats

THREE.RGB_S3TC_DXT1_Format = 2001;
THREE.RGBA_S3TC_DXT1_Format = 2002;
THREE.RGBA_S3TC_DXT3_Format = 2003;
THREE.RGBA_S3TC_DXT5_Format = 2004;

// PVRTC compressed texture formats

THREE.RGB_PVRTC_4BPPV1_Format = 2100;
THREE.RGB_PVRTC_2BPPV1_Format = 2101;
THREE.RGBA_PVRTC_4BPPV1_Format = 2102;
THREE.RGBA_PVRTC_2BPPV1_Format = 2103;

// DEPRECATED

THREE.Projector = function () {

	THREE.error( 'THREE.Projector has been moved to /examples/js/renderers/Projector.js.' );

	this.projectVector = function ( vector, camera ) {

		THREE.warning( 'THREE.Projector: .projectVector() is now vector.project().' );
		vector.project( camera );

	};

	this.unprojectVector = function ( vector, camera ) {

		THREE.warning( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
		vector.unproject( camera );

	};

	this.pickingRay = function ( vector, camera ) {

		THREE.error( 'THREE.Projector: .pickingRay() has been removed.' );

	};

};

THREE.CanvasRenderer = function () {

	THREE.error( 'THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js' );

	this.domElement = document.createElement( 'canvas' );
	this.clear = function () {};
	this.render = function () {};
	this.setClearColor = function () {};
	this.setSize = function () {};

};
<|endoftext|>


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

    function Audio(sounds) {
        this.sounds = sounds || {};
        this.soundBuffers = {};
        this.loadCount = 0;
        this.playingSound = false;

        try {
            window.AudioContext = window.AudioContext || window.webkitAudioContext;
            this.audioContext = new window.AudioContext();
        } catch (e) {
            window.alert('API Audio non supportée.');
        }
    }

    Audio.prototype.loadSounds = function (soundList) {

        var promises = [];
        soundList.forEach(function (element) {
            promises.push(this.loadSound(element));
        }.bind(this));
        return Promise.all(promises);
    };

    Audio.prototype.loadSound = function (sound) {

        return new Promise(function (resolve, reject) {

            if (this.soundBuffers[sound.title]) {
                resolve(sound);
            } else {
                var request = new XMLHttpRequest();
                request.open('GET', sound.url, true);
                request.responseType = 'arraybuffer';

                request.onload = function () {
                    this.audioContext.decodeAudioData(
                        request.response,
                        function (buffer) {
                            this.soundBuffers[sound.title] = buffer;
                            resolve(sound);
                        }.bind(this),
                        function (error) {
                            console.error('Fail to decodeAudioData [%s]', sound.url, error);
                            reject(sound);
                        }
                    );

                }.bind(this);

                request.onerror = function (event) {
                    reject("Erreur XMLHttpRequest ", event);
                };

                request.send();
            }

        }.bind(this));
    };

    Audio.prototype.load = function () {
        return this.loadSounds(this.sounds);
    };

    Audio.prototype.stageBgm = function () {
        return this.play(this.soundBuffers.stage, true, 0, 0);
    };

    Audio.prototype.laser = function () {
        return this.play(this.soundBuffers.laser, false);
    };

    Audio.prototype.play = function (sound, loop, loopStart, loopEnd) {
        return new Promise(function (resolve) {

            var source = this.audioContext.createBufferSource();
            source.buffer = sound;
            source.loop = loop;

            if (loop) {
                source.loopStart = loopStart;
                source.loopEnd = loopEnd;

                resolve(source);
            }

            source.onended = function () {
                if (!loop) {
                    resolve(source);
                }
            };

            source.connect(this.audioContext.destination);
            source.start(0);
        }.bind(this));
    };

    window.Audio = Audio;

})(window);
<commit_msg>feat(audio): utilisation de `Array.map` au lieu de `Array.forEach`<commit_after>(function (window) {
    'use strict';

    function Audio(sounds) {
        this.sounds = sounds || {};
        this.soundBuffers = {};
        this.loadCount = 0;
        this.playingSound = false;

        try {
            window.AudioContext = window.AudioContext || window.webkitAudioContext;
            this.audioContext = new window.AudioContext();
        } catch (e) {
            window.alert('API Audio non supportée.');
        }
    }

    Audio.prototype.loadSounds = function (soundList) {

        var promises = soundList.map(function (element) {
            return this.loadSound(element);
        }.bind(this));

        return Promise.all(promises);
    };

    Audio.prototype.loadSound = function (sound) {

        return new Promise(function (resolve, reject) {

            if (this.soundBuffers[sound.title]) {
                resolve(sound);
            } else {
                var request = new XMLHttpRequest();
                request.open('GET', sound.url, true);
                request.responseType = 'arraybuffer';

                request.onload = function () {
                    this.audioContext.decodeAudioData(
                        request.response,
                        function (buffer) {
                            this.soundBuffers[sound.title] = buffer;
                            resolve(sound);
                        }.bind(this),
                        function (error) {
                            console.error('Fail to decodeAudioData [%s]', sound.url, error);
                            reject(sound);
                        }
                    );
                }.bind(this);

                request.onerror = function (event) {
                    reject("Erreur XMLHttpRequest ", event);
                };

                request.send();
            }

        }.bind(this));
    };

    Audio.prototype.load = function () {
        return this.loadSounds(this.sounds);
    };

    Audio.prototype.stageBgm = function () {
        return this.play(this.soundBuffers.stage, true, 0, 0);
    };

    Audio.prototype.laser = function () {
        return this.play(this.soundBuffers.laser, false);
    };

    Audio.prototype.play = function (sound, loop, loopStart, loopEnd) {
        return new Promise(function (resolve) {

            var source = this.audioContext.createBufferSource();
            source.buffer = sound;
            source.loop = loop;

            if (loop) {
                source.loopStart = loopStart;
                source.loopEnd = loopEnd;

                resolve(source);
            }

            source.onended = function () {
                if (!loop) {
                    resolve(source);
                }
            };

            source.connect(this.audioContext.destination);
            source.start(0);
        }.bind(this));
    };

    window.Audio = Audio;

})(window);
<|endoftext|>