<commit_before>"use strict";

/** @const */
var STATE_VERSION = 3;

/** @const */
var STATE_MAGIC = 0x86768676|0;

/** @const */
var STATE_INDEX_MAGIC = 0;

/** @const */
var STATE_INDEX_VERSION = 1;

/** @const */
var STATE_INDEX_TOTAL_LEN = 2;

/** @const */
var STATE_INDEX_INFO_LEN = 3;

/** @const */
var STATE_INFO_BLOCK_START = 16;

/** @constructor */
function StateLoadError(msg)
{
    this.message = msg;
}
StateLoadError.prototype = new Error;

const CONSTRUCTOR_TABLE = {
    "Uint8Array": Uint8Array,
    "Int8Array": Int8Array,
    "Uint16Array": Uint16Array,
    "Int16Array": Int16Array,
    "Uint32Array": Uint32Array,
    "Int32Array": Int32Array,
    "Float32Array": Float32Array,
    "Float64Array": Float64Array,
};

function save_object(obj, saved_buffers)
{
    if(typeof obj !== "object" || obj === null)
    {
        dbg_assert(typeof obj !== "function");
        return obj;
    }

    if(obj instanceof Array)
    {
        return obj.map(x => save_object(x, saved_buffers));
    }

    dbg_assert(obj.constructor !== Object);

    if(obj.BYTES_PER_ELEMENT)
    {
        // Uint8Array, etc.
        var buffer = new Uint8Array(obj.buffer, obj.byteOffset, obj.length * obj.BYTES_PER_ELEMENT);

        const constructor = obj.constructor.name.replace("bound ", "");

        dbg_assert(CONSTRUCTOR_TABLE[constructor]);

        return {
            "__state_type__": constructor,
            "buffer_id": saved_buffers.push(buffer) - 1,
        };
    }

    if(DEBUG && !obj.get_state)
    {
        console.log("Object without get_state: ", obj);
    }

    var state = obj.get_state();
    var result = [];

    for(var i = 0; i < state.length; i++)
    {
        var value = state[i];

        dbg_assert(typeof value !== "function");

        result[i] = save_object(value, saved_buffers);
    }

    return result;
}

function restore_buffers(obj, buffers)
{
    if(typeof obj !== "object" || obj === null)
    {
        dbg_assert(typeof obj !== "function");
        return obj;
    }

    if(obj instanceof Array)
    {
        for(let i = 0; i < obj.length; i++)
        {
            obj[i] = restore_buffers(obj[i], buffers);
        }

        return obj;
    }

    const type = obj["__state_type__"];
    dbg_assert(type !== undefined);

    const constructor = CONSTRUCTOR_TABLE[type];
    dbg_assert(constructor, "Unkown type: " + type);

    const info = buffers.infos[obj["buffer_id"]];

    // restore large buffers by just returning a view on the state blob
    // get_state is responsible for copying the data
    if(info.length >= 1024 * 1024 && constructor === Uint8Array)
    {
        return new Uint8Array(buffers.full, info.offset, info.length);
    }
    else
    {
        var buf = buffers.full.slice(info.offset, info.offset + info.length);
        return new constructor(buf);
    }
}

CPU.prototype.save_state = function()
{
    var saved_buffers = [];
    var state = save_object(this, saved_buffers);

    var buffer_infos = [];
    var total_buffer_size = 0;

    for(var i = 0; i < saved_buffers.length; i++)
    {
        var len = saved_buffers[i].byteLength;

        buffer_infos[i] = {
            offset: total_buffer_size,
            length: len,
        };

        total_buffer_size += len;

        // align
        total_buffer_size = total_buffer_size + 3 & ~3;
    }

    var info_object = JSON.stringify({
        "buffer_infos": buffer_infos,
        "state": state,
    });

    var buffer_block_start = STATE_INFO_BLOCK_START + 2 * info_object.length;
    buffer_block_start = buffer_block_start + 3 & ~3;
    var total_size = buffer_block_start + total_buffer_size;

    //console.log("State: json_size=" + Math.ceil(buffer_block_start / 1024 / 1024) + "MB " +
    //               "buffer_size=" + Math.ceil(total_buffer_size / 1024 / 1024) + "MB");

    var result = new ArrayBuffer(total_size);

    var header_block = new Int32Array(
        result,
        0,
        STATE_INFO_BLOCK_START / 4
    );
    var info_block = new Uint16Array(
        result,
        STATE_INFO_BLOCK_START,
        info_object.length
    );
    var buffer_block = new Uint8Array(
        result,
        buffer_block_start
    );

    header_block[STATE_INDEX_MAGIC] = STATE_MAGIC;
    header_block[STATE_INDEX_VERSION] = STATE_VERSION;
    header_block[STATE_INDEX_TOTAL_LEN] = total_size;
    header_block[STATE_INDEX_INFO_LEN] = info_object.length * 2;

    for(var i = 0; i < info_object.length; i++)
    {
        info_block[i] = info_object.charCodeAt(i);
    }

    for(var i = 0; i < saved_buffers.length; i++)
    {
        var buffer = saved_buffers[i];
        dbg_assert(buffer.constructor === Uint8Array);
        buffer_block.set(buffer, buffer_infos[i].offset);
    }

    return result;
};

CPU.prototype.restore_state = function(state)
{
    var len = state.byteLength;

    if(len < STATE_INFO_BLOCK_START)
    {
        throw new StateLoadError("Invalid length: " + len);
    }

    var header_block = new Int32Array(state, 0, 4);

    if(header_block[STATE_INDEX_MAGIC] !== STATE_MAGIC)
    {
        throw new StateLoadError("Invalid header: " + h(header_block[STATE_INDEX_MAGIC] >>> 0));
    }

    if(header_block[STATE_INDEX_VERSION] !== STATE_VERSION)
    {
        throw new StateLoadError(
                "Version mismatch: dump=" + header_block[STATE_INDEX_VERSION] +
                " we=" + STATE_VERSION);
    }

    if(header_block[STATE_INDEX_TOTAL_LEN] !== len)
    {
        throw new StateLoadError(
                "Length doesn't match header: " +
                "real=" + len + " header=" + header_block[STATE_INDEX_TOTAL_LEN]);
    }

    var info_block_len = header_block[STATE_INDEX_INFO_LEN];

    if(info_block_len < 0 ||
       info_block_len + 12 >= len ||
       info_block_len % 2)
    {
        throw new StateLoadError("Invalid info block length: " + info_block_len);
    }

    var info_block_str_len = info_block_len / 2;
    var info_block_buffer = new Uint16Array(state, STATE_INFO_BLOCK_START, info_block_str_len);
    var info_block = "";

    for(var i = 0; i < info_block_str_len - 8; )
    {
        info_block += String.fromCharCode(
            info_block_buffer[i++], info_block_buffer[i++],
            info_block_buffer[i++], info_block_buffer[i++],
            info_block_buffer[i++], info_block_buffer[i++],
            info_block_buffer[i++], info_block_buffer[i++]
        );
    }

    for(; i < info_block_str_len; )
    {
        info_block += String.fromCharCode(info_block_buffer[i++]);
    }

    var info_block_obj = JSON.parse(info_block);
    var state_object = info_block_obj["state"];
    var buffer_infos = info_block_obj["buffer_infos"];
    var buffer_block_start = STATE_INFO_BLOCK_START + info_block_len;
    buffer_block_start = buffer_block_start + 3 & ~3;

    for(var i = 0; i < buffer_infos.length; i++)
    {
        buffer_infos[i].offset += buffer_block_start;
    }

    var buffers = {
        full: state,
        infos: buffer_infos,
    };

    state_object = restore_buffers(state_object, buffers);
    this.set_state(state_object);
};
<commit_msg>Use TextDecoder over manual utf16 encoding (faster + more compact)<commit_after>"use strict";

/** @const */
var STATE_VERSION = 6;

/** @const */
var STATE_MAGIC = 0x86768676|0;

/** @const */
var STATE_INDEX_MAGIC = 0;

/** @const */
var STATE_INDEX_VERSION = 1;

/** @const */
var STATE_INDEX_TOTAL_LEN = 2;

/** @const */
var STATE_INDEX_INFO_LEN = 3;

/** @const */
var STATE_INFO_BLOCK_START = 16;

/** @constructor */
function StateLoadError(msg)
{
    this.message = msg;
}
StateLoadError.prototype = new Error;

const CONSTRUCTOR_TABLE = {
    "Uint8Array": Uint8Array,
    "Int8Array": Int8Array,
    "Uint16Array": Uint16Array,
    "Int16Array": Int16Array,
    "Uint32Array": Uint32Array,
    "Int32Array": Int32Array,
    "Float32Array": Float32Array,
    "Float64Array": Float64Array,
};

function save_object(obj, saved_buffers)
{
    if(typeof obj !== "object" || obj === null)
    {
        dbg_assert(typeof obj !== "function");
        return obj;
    }

    if(obj instanceof Array)
    {
        return obj.map(x => save_object(x, saved_buffers));
    }

    if(obj.constructor === Object)
    {
        console.log(obj);
        dbg_assert(obj.constructor !== Object, "Expected non-object");
    }

    if(obj.BYTES_PER_ELEMENT)
    {
        // Uint8Array, etc.
        var buffer = new Uint8Array(obj.buffer, obj.byteOffset, obj.length * obj.BYTES_PER_ELEMENT);

        const constructor = obj.constructor.name.replace("bound ", "");

        dbg_assert(CONSTRUCTOR_TABLE[constructor]);

        return {
            "__state_type__": constructor,
            "buffer_id": saved_buffers.push(buffer) - 1,
        };
    }

    if(DEBUG && !obj.get_state)
    {
        console.log("Object without get_state: ", obj);
    }

    var state = obj.get_state();
    var result = [];

    for(var i = 0; i < state.length; i++)
    {
        var value = state[i];

        dbg_assert(typeof value !== "function");

        result[i] = save_object(value, saved_buffers);
    }

    return result;
}

function restore_buffers(obj, buffers)
{
    if(typeof obj !== "object" || obj === null)
    {
        dbg_assert(typeof obj !== "function");
        return obj;
    }

    if(obj instanceof Array)
    {
        for(let i = 0; i < obj.length; i++)
        {
            obj[i] = restore_buffers(obj[i], buffers);
        }

        return obj;
    }

    const type = obj["__state_type__"];
    dbg_assert(type !== undefined);

    const constructor = CONSTRUCTOR_TABLE[type];
    dbg_assert(constructor, "Unkown type: " + type);

    const info = buffers.infos[obj["buffer_id"]];

    // restore large buffers by just returning a view on the state blob
    // get_state is responsible for copying the data
    if(info.length >= 1024 * 1024 && constructor === Uint8Array)
    {
        return new Uint8Array(buffers.full, info.offset, info.length);
    }
    else
    {
        var buf = buffers.full.slice(info.offset, info.offset + info.length);
        return new constructor(buf);
    }
}

CPU.prototype.save_state = function()
{
    var saved_buffers = [];
    var state = save_object(this, saved_buffers);

    var buffer_infos = [];
    var total_buffer_size = 0;

    for(var i = 0; i < saved_buffers.length; i++)
    {
        var len = saved_buffers[i].byteLength;

        buffer_infos[i] = {
            offset: total_buffer_size,
            length: len,
        };

        total_buffer_size += len;

        // align
        total_buffer_size = total_buffer_size + 3 & ~3;
    }

    var info_object = JSON.stringify({
        "buffer_infos": buffer_infos,
        "state": state,
    });
    var info_block = new TextEncoder().encode(info_object);

    var buffer_block_start = STATE_INFO_BLOCK_START + info_block.length;
    buffer_block_start = buffer_block_start + 3 & ~3;
    var total_size = buffer_block_start + total_buffer_size;

    //console.log("State: json_size=" + Math.ceil(buffer_block_start / 1024 / 1024) + "MB " +
    //               "buffer_size=" + Math.ceil(total_buffer_size / 1024 / 1024) + "MB");

    var result = new ArrayBuffer(total_size);

    var header_block = new Int32Array(
        result,
        0,
        STATE_INFO_BLOCK_START / 4
    );
    new Uint8Array(result, STATE_INFO_BLOCK_START, info_block.length).set(info_block);
    var buffer_block = new Uint8Array(
        result,
        buffer_block_start
    );

    header_block[STATE_INDEX_MAGIC] = STATE_MAGIC;
    header_block[STATE_INDEX_VERSION] = STATE_VERSION;
    header_block[STATE_INDEX_TOTAL_LEN] = total_size;
    header_block[STATE_INDEX_INFO_LEN] = info_block.length;

    for(var i = 0; i < saved_buffers.length; i++)
    {
        var buffer = saved_buffers[i];
        dbg_assert(buffer.constructor === Uint8Array);
        buffer_block.set(buffer, buffer_infos[i].offset);
    }

    return result;
};

CPU.prototype.restore_state = function(state)
{
    var len = state.byteLength;

    if(len < STATE_INFO_BLOCK_START)
    {
        throw new StateLoadError("Invalid length: " + len);
    }

    var header_block = new Int32Array(state, 0, 4);

    if(header_block[STATE_INDEX_MAGIC] !== STATE_MAGIC)
    {
        throw new StateLoadError("Invalid header: " + h(header_block[STATE_INDEX_MAGIC] >>> 0));
    }

    if(header_block[STATE_INDEX_VERSION] !== STATE_VERSION)
    {
        throw new StateLoadError(
                "Version mismatch: dump=" + header_block[STATE_INDEX_VERSION] +
                " we=" + STATE_VERSION);
    }

    if(header_block[STATE_INDEX_TOTAL_LEN] !== len)
    {
        throw new StateLoadError(
                "Length doesn't match header: " +
                "real=" + len + " header=" + header_block[STATE_INDEX_TOTAL_LEN]);
    }

    var info_block_len = header_block[STATE_INDEX_INFO_LEN];

    if(info_block_len < 0 || info_block_len + 12 >= state.length)
    {
        throw new StateLoadError("Invalid info block length: " + info_block_len);
    }

    function read_info_block(info_block_buffer)
    {
        const info_block = new TextDecoder().decode(info_block_buffer);
        return JSON.parse(info_block);
    }

    const info_block_buffer = new Uint8Array(state, STATE_INFO_BLOCK_START, info_block_len);
    var info_block_obj = read_info_block(info_block_buffer);

    var state_object = info_block_obj["state"];
    var buffer_infos = info_block_obj["buffer_infos"];
    var buffer_block_start = STATE_INFO_BLOCK_START + info_block_len;
    buffer_block_start = buffer_block_start + 3 & ~3;

    for(var i = 0; i < buffer_infos.length; i++)
    {
        buffer_infos[i].offset += buffer_block_start;
    }

    var buffers = {
        full: state,
        infos: buffer_infos,
    };

    state_object = restore_buffers(state_object, buffers);
    this.set_state(state_object);
};
<|endoftext|>


<commit_before>

import { Found } from "./astravel"

var ForInStatement, FunctionDeclaration, RestElement, BinaryExpression, ArrayExpression

const ignore = Function.prototype

export default {

	// Basic methods
	go( node, state ) {
		/*
		Starts travelling through the specified AST `node` with the provided `state`.
		This method is recursively called by each node handler.
		*/
		this[ node.type ]( node, state )
	},
	find( node, state ) {
		/*
		Starts travelling through the specified AST `node` with the provided `state`.
		If it catches a `Found` instance, returns it. Otherwise, returns `undefined`.
		*/
			try {
				 this.go( node, state );
			} catch ( error ) {
				 if ( error instanceof Found )
						return error;
				 else
						throw error;
			}
	 },
	makeChild( properties = {} ) {
		/*
		Returns a custom AST traveler that inherits from `this` traveler with its own provided `properties` and the property `super` that points to the parent traveler object.
		*/
		let traveler = Object.create( this )
		traveler.super = this
		for ( let key in properties )
			traveler[ key ] = properties[ key ]
		return traveler
	},

	// JavaScript 5
	Program( node, state ) {
		let statements = node.body
		for ( let i = 0, { length } = statements; i < length; i++ )
			this.go( statements[ i ], state )
	},
	BlockStatement( node, state ) {
		let statements = node.body
		if ( statements != null )
			for ( let i = 0, { length } = statements; i < length; i++ )
				this.go( statements[ i ], state )
	},
	EmptyStatement: ignore,
	ExpressionStatement( node, state ) {
		this.go( node.expression, state )
	},
	IfStatement( node, state ) {
		this.go( node.test, state )
		this.go( node.consequent, state )
		if ( node.alternate != null )
			this.go( node.alternate, state )
	},
	LabeledStatement( node, state ) {
		this.go( node.label, state )
		this.go( node.body, state )
	},
	BreakStatement( node, state ) {
		if ( node.label )
			this.go( node.label, state )
	},
	ContinueStatement( node, state ) {
		if ( node.label )
			this.go( node.label, state )
	},
	WithStatement( node, state ) {
		this.go( node.object, state )
		this.go( node.body, state )
	},
	SwitchStatement( node, state ) {
		this.go( node.discriminant, state )
		const { cases } = node;
		for ( let i = 0, { length } = cases; i < length; i++ )
			this.go( cases[ i ], state )
	},
	SwitchCase( node, state ) {
		if ( node.test != null )
			this.go( node.test, state )
		let statements = node.consequent
		for ( let i = 0, { length } = statements; i < length; i++ )
			this.go( statements[ i ], state )
	},
	ReturnStatement( node, state ) {
		if ( node.argument )
			this.go( node.argument, state )
	},
	ThrowStatement( node, state ) {
		this.go( node.argument, state )
	},
	TryStatement( node, state ) {
		this.go( node.block, state )
		if ( node.handler != null )
			this.go( node.handler, state )
		if ( node.finalizer != null )
			this.go( node.finalizer, state )
	},
	CatchClause( node, state ) {
		this.go( node.param, state )
		this.go( node.body, state )
	},
	WhileStatement( node, state ) {
		this.go( node.test, state )
		this.go( node.body, state )
	},
	DoWhileStatement( node, state ) {
		this.go( node.body, state )
		this.go( node.test, state )
	},
	ForStatement( node, state ) {
		if ( node.init != null )
			this.go( node.init, state )
		if ( node.test != null )
			this.go( node.test, state )
		if ( node.update != null )
			this.go( node.update, state )
		this.go( node.body, state )
	},
	ForInStatement: ForInStatement = function( node, state ) {
		this.go( node.left, state )
		this.go( node.right, state )
		this.go( node.body, state )
	},
	DebuggerStatement: ignore,
	FunctionDeclaration: FunctionDeclaration = function( node, state ) {
		if ( node.id != null )
			this.go( node.id, state )
		const { params } = node
		if ( params != null && params.length !== 0 )
			for ( let i = 0, { length } = params; i < length; i++ )
				this.go( params[ i ], state )
		this.go( node.body, state )
	},
	VariableDeclaration( node, state ) {
		const { declarations } = node
		for ( let i = 0, { length } = declarations; i < length; i++ )
			this.go( declarations[ i ], state )
	},
	VariableDeclarator( node, state ) {
		this.go( node.id, state )
		if ( node.init != null )
			this.go( node.init, state )
	},
	ArrowFunctionExpression( node, state ) {
		const { params } = node
		if ( params != null && params.length !== 0 ) {
			for ( let i = 0, { length } = params; i < length; i++ ) {
				let param = params[ i ]
				this.go( param, state )
			}
		}
		this.go( node.body, state )
	},
	ThisExpression: ignore,
	ArrayExpression: ArrayExpression = function( node, state ) {
		for ( let i = 0, { elements } = node, { length } = elements; i < length; i++ ) {
			let element = elements[ i ]
			this.go( element, state )
		}
	},
	ObjectExpression( node, state ) {
		const { properties } = node, { length } = properties
		for ( let i = 0; i < length; i++ )
			this.go( properties[ i ], state )
	},
	Property( node, state ) {
		this.go( node.key, state )
		if ( !node.shorthand )
			this.go( node.value, state )
	},
	FunctionExpression: FunctionDeclaration,
	SequenceExpression( node, state ) {
		const { expressions } = node
		for ( let i = 0, { length } = expressions; i < length; i++ ) {
			let expression = expressions[ i ]
			this.go( expression, state )
		}
	},
	UnaryExpression( node, state ) {
		this.go( node.argument, state )
	},
	UpdateExpression( node, state ) {
		this.go( node.argument, state )
	},
	AssignmentExpression( node, state ) {
		this.go( node.left, state )
		this.go( node.right, state )
	},
	BinaryExpression: BinaryExpression = function( node, state ) {
		this.go( node.left, state )
		this.go( node.right, state )
	},
	LogicalExpression: BinaryExpression,
	ConditionalExpression( node, state ) {
		this.go( node.test, state )
		this.go( node.consequent, state )
		this.go( node.alternate, state )
	},
	NewExpression( node, state ) {
		this.CallExpression( node, state )
	},
	CallExpression( node, state ) {
		this.go( node.callee, state )
		const args = node[ 'arguments' ]
		for ( let i = 0, { length } = args; i < length; i++ )
			this.go( args[ i ], state )
	},
	MemberExpression( node, state ) {
		this.go( node.object, state )
		this.go( node.property, state )
	},
	Identifier: ignore,
	Literal: ignore,

	// JavaScript 6
	ForOfStatement: ForInStatement,
	ClassDeclaration( node, state ) {
		this.go( node.id, state )
		if ( node.superClass )
			this.go( node.superClass, state )
		// ClassBody
		this.BlockStatement( node.body, state )
	},
	ImportDeclaration( node, state ) {
		const { specifiers } = node, { length } = specifiers
		if ( length > 0 )
			for ( let i = 0; i < length; i++ )
				this.go( specifiers[ i ], state )
		this.go( node.source, state )
	},
	ImportNamespaceSpecifier( node, state ) {
		this.go( node.local, state )
	},
	ImportDefaultSpecifier( node, state ) {
		this.go( node.local, state )
	},
	ImportSpecifier( node, state ) {
		this.go( node.imported, state )
		this.go( node.local, state )
	},
	ExportDefaultDeclaration( node, state ) {
		this.go( node.declaration, state )
	},
	ExportNamedDeclaration( node, state ) {
		if ( node.declaration ) {
			this.go( node.declaration, state )
		} else {
			const { specifiers } = node, { length } = specifiers
			for ( let i = 0; i < length; i++ )
				this.go( specifiers[ i ], state )
			if ( node.source )
				this.go( node.source, state )
		}
	},
	ExportSpecifier( node, state ) {
		this.go( node.local, state )
		this.go( node.exported, state )
	},
	ExportAllDeclaration( node, state ) {
		this.go( node.source, state )
	},
	MethodDefinition( node, state ) {
		this.go( node.key, state )
		const { params } = node.value
		if ( params ) {
			for ( let i = 0, { length } = params; i < length; i++ )
				this.go( params[ i ], state )
		}
		this.go( node.value, state )
	},
	ClassExpression( node, state ) {
		this.ClassDeclaration( node, state )
	},
	Super: ignore,
	RestElement: RestElement = function( node, state ) {
		this.go( node.argument, state )
	},
	SpreadElement: RestElement,
	YieldExpression( node, state ) {
		if ( node.argument )
			this.go( node.argument, state )
	},
	TemplateLiteral( node, state ) {
		const { quasis, expressions } = node
		for ( let i = 0, { length } = expressions; i < length; i++ )
			this.go( expressions[ i ], state )
	},
	TaggedTemplateExpression( node, state ) {
		this.go( node.tag, state )
		this.go( node.quasi, state )
	},
	ObjectPattern( node, state ) {
		const { properties } = node, { length } = properties
		for ( let i = 0; i < length; i++ )
			this.go( properties[ i ], state )
	},
	ArrayPattern: ArrayExpression,
	AssignmentPattern( node, state ) {
		this.go( node.left, state )
		this.go( node.right, state )
	}

}

// TODO: Add JS7 nodes
<commit_msg>Added `ClassBody` node traveler<commit_after>

import { Found } from "./astravel"

var ForInStatement, FunctionDeclaration, RestElement, BinaryExpression, ArrayExpression

const ignore = Function.prototype

export default {

	// Basic methods
	go( node, state ) {
		/*
		Starts travelling through the specified AST `node` with the provided `state`.
		This method is recursively called by each node handler.
		*/
		this[ node.type ]( node, state )
	},
	find( node, state ) {
		/*
		Starts travelling through the specified AST `node` with the provided `state`.
		If it catches a `Found` instance, returns it. Otherwise, returns `undefined`.
		*/
			try {
				 this.go( node, state );
			} catch ( error ) {
				 if ( error instanceof Found )
						return error;
				 else
						throw error;
			}
	 },
	makeChild( properties = {} ) {
		/*
		Returns a custom AST traveler that inherits from `this` traveler with its own provided `properties` and the property `super` that points to the parent traveler object.
		*/
		let traveler = Object.create( this )
		traveler.super = this
		for ( let key in properties )
			traveler[ key ] = properties[ key ]
		return traveler
	},

	// JavaScript 5
	Program( node, state ) {
		let statements = node.body
		for ( let i = 0, { length } = statements; i < length; i++ )
			this.go( statements[ i ], state )
	},
	BlockStatement( node, state ) {
		let statements = node.body
		if ( statements != null )
			for ( let i = 0, { length } = statements; i < length; i++ )
				this.go( statements[ i ], state )
	},
	EmptyStatement: ignore,
	ExpressionStatement( node, state ) {
		this.go( node.expression, state )
	},
	IfStatement( node, state ) {
		this.go( node.test, state )
		this.go( node.consequent, state )
		if ( node.alternate != null )
			this.go( node.alternate, state )
	},
	LabeledStatement( node, state ) {
		this.go( node.label, state )
		this.go( node.body, state )
	},
	BreakStatement( node, state ) {
		if ( node.label )
			this.go( node.label, state )
	},
	ContinueStatement( node, state ) {
		if ( node.label )
			this.go( node.label, state )
	},
	WithStatement( node, state ) {
		this.go( node.object, state )
		this.go( node.body, state )
	},
	SwitchStatement( node, state ) {
		this.go( node.discriminant, state )
		const { cases } = node;
		for ( let i = 0, { length } = cases; i < length; i++ )
			this.go( cases[ i ], state )
	},
	SwitchCase( node, state ) {
		if ( node.test != null )
			this.go( node.test, state )
		let statements = node.consequent
		for ( let i = 0, { length } = statements; i < length; i++ )
			this.go( statements[ i ], state )
	},
	ReturnStatement( node, state ) {
		if ( node.argument )
			this.go( node.argument, state )
	},
	ThrowStatement( node, state ) {
		this.go( node.argument, state )
	},
	TryStatement( node, state ) {
		this.go( node.block, state )
		if ( node.handler != null )
			this.go( node.handler, state )
		if ( node.finalizer != null )
			this.go( node.finalizer, state )
	},
	CatchClause( node, state ) {
		this.go( node.param, state )
		this.go( node.body, state )
	},
	WhileStatement( node, state ) {
		this.go( node.test, state )
		this.go( node.body, state )
	},
	DoWhileStatement( node, state ) {
		this.go( node.body, state )
		this.go( node.test, state )
	},
	ForStatement( node, state ) {
		if ( node.init != null )
			this.go( node.init, state )
		if ( node.test != null )
			this.go( node.test, state )
		if ( node.update != null )
			this.go( node.update, state )
		this.go( node.body, state )
	},
	ForInStatement: ForInStatement = function( node, state ) {
		this.go( node.left, state )
		this.go( node.right, state )
		this.go( node.body, state )
	},
	DebuggerStatement: ignore,
	FunctionDeclaration: FunctionDeclaration = function( node, state ) {
		if ( node.id != null )
			this.go( node.id, state )
		const { params } = node
		if ( params != null && params.length !== 0 )
			for ( let i = 0, { length } = params; i < length; i++ )
				this.go( params[ i ], state )
		this.go( node.body, state )
	},
	VariableDeclaration( node, state ) {
		const { declarations } = node
		for ( let i = 0, { length } = declarations; i < length; i++ )
			this.go( declarations[ i ], state )
	},
	VariableDeclarator( node, state ) {
		this.go( node.id, state )
		if ( node.init != null )
			this.go( node.init, state )
	},
	ArrowFunctionExpression( node, state ) {
		const { params } = node
		if ( params != null && params.length !== 0 ) {
			for ( let i = 0, { length } = params; i < length; i++ ) {
				let param = params[ i ]
				this.go( param, state )
			}
		}
		this.go( node.body, state )
	},
	ThisExpression: ignore,
	ArrayExpression: ArrayExpression = function( node, state ) {
		for ( let i = 0, { elements } = node, { length } = elements; i < length; i++ ) {
			let element = elements[ i ]
			this.go( element, state )
		}
	},
	ObjectExpression( node, state ) {
		const { properties } = node, { length } = properties
		for ( let i = 0; i < length; i++ )
			this.go( properties[ i ], state )
	},
	Property( node, state ) {
		this.go( node.key, state )
		if ( !node.shorthand )
			this.go( node.value, state )
	},
	FunctionExpression: FunctionDeclaration,
	SequenceExpression( node, state ) {
		const { expressions } = node
		for ( let i = 0, { length } = expressions; i < length; i++ ) {
			let expression = expressions[ i ]
			this.go( expression, state )
		}
	},
	UnaryExpression( node, state ) {
		this.go( node.argument, state )
	},
	UpdateExpression( node, state ) {
		this.go( node.argument, state )
	},
	AssignmentExpression( node, state ) {
		this.go( node.left, state )
		this.go( node.right, state )
	},
	BinaryExpression: BinaryExpression = function( node, state ) {
		this.go( node.left, state )
		this.go( node.right, state )
	},
	LogicalExpression: BinaryExpression,
	ConditionalExpression( node, state ) {
		this.go( node.test, state )
		this.go( node.consequent, state )
		this.go( node.alternate, state )
	},
	NewExpression( node, state ) {
		this.CallExpression( node, state )
	},
	CallExpression( node, state ) {
		this.go( node.callee, state )
		const args = node[ 'arguments' ]
		for ( let i = 0, { length } = args; i < length; i++ )
			this.go( args[ i ], state )
	},
	MemberExpression( node, state ) {
		this.go( node.object, state )
		this.go( node.property, state )
	},
	Identifier: ignore,
	Literal: ignore,

	// JavaScript 6
	ForOfStatement: ForInStatement,
	ClassDeclaration( node, state ) {
		this.go( node.id, state )
		if ( node.superClass )
			this.go( node.superClass, state )
		// ClassBody
		this.go( node.body, state )
	},
	ClassBody( node, state ) {
		const { body } = node
		for ( let i = 0, { length } = body; i < length; i++ )
			this.go( body[ i ], state )
	},
	ImportDeclaration( node, state ) {
		const { specifiers } = node, { length } = specifiers
		if ( length > 0 )
			for ( let i = 0; i < length; i++ )
				this.go( specifiers[ i ], state )
		this.go( node.source, state )
	},
	ImportNamespaceSpecifier( node, state ) {
		this.go( node.local, state )
	},
	ImportDefaultSpecifier( node, state ) {
		this.go( node.local, state )
	},
	ImportSpecifier( node, state ) {
		this.go( node.imported, state )
		this.go( node.local, state )
	},
	ExportDefaultDeclaration( node, state ) {
		this.go( node.declaration, state )
	},
	ExportNamedDeclaration( node, state ) {
		if ( node.declaration ) {
			this.go( node.declaration, state )
		} else {
			const { specifiers } = node, { length } = specifiers
			for ( let i = 0; i < length; i++ )
				this.go( specifiers[ i ], state )
			if ( node.source )
				this.go( node.source, state )
		}
	},
	ExportSpecifier( node, state ) {
		this.go( node.local, state )
		this.go( node.exported, state )
	},
	ExportAllDeclaration( node, state ) {
		this.go( node.source, state )
	},
	MethodDefinition( node, state ) {
		this.go( node.key, state )
		const { params } = node.value
		if ( params ) {
			for ( let i = 0, { length } = params; i < length; i++ )
				this.go( params[ i ], state )
		}
		this.go( node.value, state )
	},
	ClassExpression( node, state ) {
		this.ClassDeclaration( node, state )
	},
	Super: ignore,
	RestElement: RestElement = function( node, state ) {
		this.go( node.argument, state )
	},
	SpreadElement: RestElement,
	YieldExpression( node, state ) {
		if ( node.argument )
			this.go( node.argument, state )
	},
	TemplateLiteral( node, state ) {
		const { quasis, expressions } = node
		for ( let i = 0, { length } = expressions; i < length; i++ )
			this.go( expressions[ i ], state )
	},
	TaggedTemplateExpression( node, state ) {
		this.go( node.tag, state )
		this.go( node.quasi, state )
	},
	ObjectPattern( node, state ) {
		const { properties } = node, { length } = properties
		for ( let i = 0; i < length; i++ )
			this.go( properties[ i ], state )
	},
	ArrayPattern: ArrayExpression,
	AssignmentPattern( node, state ) {
		this.go( node.left, state )
		this.go( node.right, state )
	}

}

// TODO: Add JS7 nodes
<|endoftext|>


<commit_before>'use strict';

/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import $C from '../deps/collection';
import Snakeskin from '../core';
import { ws } from '../helpers/string';
import { any } from '../helpers/gcc';
import { emptyCommandParams } from '../consts/regs';

const types = {
	'acss': {
		'rel': 'alternate stylesheet',
		'type': 'text/css'
	},

	'css': {
		'rel': 'stylesheet',
		'type': 'text/css'
	}
};

const typesStr = {
	dom: {},
	string: {}
};

$C(types).forEach((el, key) => {
	$C(el).forEach((el, attr) => {
		typesStr.dom[key] = typesStr.dom[key] || '';
		typesStr.dom[key] += `__NODE__.${attr} = '${el}';`;
		typesStr.string[key] = typesStr.string[key] || '';
		typesStr.string[key] += ` ${attr}="${el}"`;
	});
});

Snakeskin.addDirective(
	'link',

	{
		block: true,
		placement: 'template',
		selfInclude: false,
		trim: {
			left: true,
			right: true
		}
	},

	function (command) {
		if (this.autoReplace) {
			this.autoReplace = false;
			this.structure.params.autoReplace = true;
		}

		if (!this.isReady()) {
			return;
		}

		if (command) {
			command = command.replace(emptyCommandParams, 'css $1');

		} else {
			command = 'css';
		}

		const
			parts = this.splitBySpace(command),
			dom = !this.domComment && this.renderMode === 'dom',
			[type] = parts;

		let str;
		if (dom) {
			str = ws`
				__NODE__ = document.createElement('link');
				${typesStr.dom[type.toLowerCase()] || ''}
				${this.wrap('__NODE__')}
				__RESULT__.push(__NODE__);
			`;

		} else {
			str = this.wrap(`'<link ${(typesStr.string[type] || this.replaceTplVars(type)).trim()}'`);
		}

		this.append(str);

		if (parts.length > 1) {
			/** @type {!Array} */
			let args = any([].slice.call(arguments));

			args[0] = parts.slice(1).join(' ');
			args[1] = args[0].length;

			Snakeskin.Directives['attr'].call(this, ...args);
			this.inline = false;
		}

		if (dom) {
			str = '__NODE__.href =';

		} else {
			str = this.wrap(`' href="'`);
		}

		this.append(str);
	},

	function () {
		if (this.structure.params.autoReplace) {
			this.autoReplace = true;
		}

		let str;
		if (!this.domComment && this.renderMode === 'dom') {
			str = ws`
				__RESULT__.pop();
				__NODE__ = null;
			`;

		} else {
			str = this.wrap(`'"${this.doctype === 'xml' ? '/' : ''}>'`);
		}

		this.append($=> str);
	}
);
<commit_msg>Added icon<commit_after>'use strict';

/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import $C from '../deps/collection';
import Snakeskin from '../core';
import { ws } from '../helpers/string';
import { any } from '../helpers/gcc';
import { emptyCommandParams } from '../consts/regs';

const types = {
	'acss': {
		'rel': 'alternate stylesheet',
		'type': 'text/css'
	},

	'css': {
		'rel': 'stylesheet',
		'type': 'text/css'
	},

	'icon': {
		'rel': 'icon',
		'type': 'image/x-icon'
	}
};

const typesStr = {
	dom: {},
	string: {}
};

$C(types).forEach((el, key) => {
	$C(el).forEach((el, attr) => {
		typesStr.dom[key] = typesStr.dom[key] || '';
		typesStr.dom[key] += `__NODE__.${attr} = '${el}';`;
		typesStr.string[key] = typesStr.string[key] || '';
		typesStr.string[key] += ` ${attr}="${el}"`;
	});
});

Snakeskin.addDirective(
	'link',

	{
		block: true,
		placement: 'template',
		selfInclude: false,
		trim: {
			left: true,
			right: true
		}
	},

	function (command) {
		if (this.autoReplace) {
			this.autoReplace = false;
			this.structure.params.autoReplace = true;
		}

		if (!this.isReady()) {
			return;
		}

		if (command) {
			command = command.replace(emptyCommandParams, 'css $1');

		} else {
			command = 'css';
		}

		const
			parts = this.splitBySpace(command),
			dom = !this.domComment && this.renderMode === 'dom';

		const
			[type] = parts;

		let str;
		if (dom) {
			str = ws`
				__NODE__ = document.createElement('link');
				${typesStr.dom[type.toLowerCase()] || ''}
				${this.wrap('__NODE__')}
				__RESULT__.push(__NODE__);
			`;

		} else {
			str = this.wrap(`'<link ${(typesStr.string[type] || '').trim()}'`);
		}

		this.append(str);

		if (parts.length > 1) {
			/** @type {!Array} */
			let args = any([].slice.call(arguments));

			args[0] = parts.slice(1).join(' ');
			args[1] = args[0].length;

			Snakeskin.Directives['attr'].call(this, ...args);
			this.inline = false;
		}

		if (dom) {
			str = '__NODE__.href =';

		} else {
			str = this.wrap(`' href="'`);
		}

		this.append(str);
	},

	function () {
		if (this.structure.params.autoReplace) {
			this.autoReplace = true;
		}

		let str;
		if (!this.domComment && this.renderMode === 'dom') {
			str = ws`
				__RESULT__.pop();
				__NODE__ = null;
			`;

		} else {
			str = this.wrap(`'"${this.doctype === 'xml' ? '/' : ''}>'`);
		}

		this.append($=> str);
	}
);
<|endoftext|>


<commit_before>export class Test {
  bind() {
    console.log(this.myVM.subscribe('ready', () => console.log('called')));
  }
}<commit_msg>chore(linter): fixed linter error<commit_after>export class Test {
}<|endoftext|>


<commit_before>/*eslint-disable no-empty */
import warning from 'warning'

const KeyPrefix = '@@History/'
const QuotaExceededError = 'QuotaExceededError'
const SecurityError = 'SecurityError'

function createKey(key) {
  return KeyPrefix + key
}

export function saveState(key, state) {
  try {
    window.sessionStorage.setItem(createKey(key), JSON.stringify(state))
  } catch (error) {
    if (error.name === SecurityError) {
      // Blocking cookies in Safari will trigger "SecurityError: DOM Exception 18"
      // on any attempt to access window.sessionStorage.
      warning(
        false,
        '[history] Unable to save state; sessionStorage is not available due to security settings'
      )

      return
    }

    if (error.name === QuotaExceededError && window.sessionStorage.length === 0) {
      // Safari "private mode" throws "QuotaExceededError: DOM Exception 22".
      warning(
        false,
        '[history] Unable to save state; sessionStorage is not available in Safari private mode'
      )

      return
    }

    throw error
  }
}

export function readState(key) {
  let json
  try {
    json = window.sessionStorage.getItem(createKey(key))
  } catch (error) {
    if (error.name === SecurityError) {
      // Blocking cookies in Safari will trigger "SecurityError: DOM Exception 18"
      // on any attempt to access window.sessionStorage.
      warning(
        false,
        '[history] Unable to read state; sessionStorage is not available due to security settings'
      )

      return null
    }
  }

  if (json) {
    try {
      return JSON.parse(json)
    } catch (error) {
      // Ignore invalid JSON.
    }
  }

  return null
}
<commit_msg>Update comments<commit_after>/*eslint-disable no-empty */
import warning from 'warning'

const KeyPrefix = '@@History/'
const QuotaExceededError = 'QuotaExceededError'
const SecurityError = 'SecurityError'

function createKey(key) {
  return KeyPrefix + key
}

export function saveState(key, state) {
  try {
    window.sessionStorage.setItem(createKey(key), JSON.stringify(state))
  } catch (error) {
    if (error.name === SecurityError) {
      // Blocking cookies in Chrome/Firefox/Safari throws SecurityError on any
      // attempt to access window.sessionStorage.
      warning(
        false,
        '[history] Unable to save state; sessionStorage is not available due to security settings'
      )

      return
    }

    if (error.name === QuotaExceededError && window.sessionStorage.length === 0) {
      // Safari "private mode" throws QuotaExceededError.
      warning(
        false,
        '[history] Unable to save state; sessionStorage is not available in Safari private mode'
      )

      return
    }

    throw error
  }
}

export function readState(key) {
  let json
  try {
    json = window.sessionStorage.getItem(createKey(key))
  } catch (error) {
    if (error.name === SecurityError) {
      // Blocking cookies in Chrome/Firefox/Safari throws SecurityError on any
      // attempt to access window.sessionStorage.
      warning(
        false,
        '[history] Unable to read state; sessionStorage is not available due to security settings'
      )

      return null
    }
  }

  if (json) {
    try {
      return JSON.parse(json)
    } catch (error) {
      // Ignore invalid JSON.
    }
  }

  return null
}
<|endoftext|>


<commit_before>enyo.kind(
	{
		name: "App",
		fit: true,
		components: [
			{name:"bar",kind: "onyx.TabBar"},
			{
				name: 'stuff',
				content: 'empty',
				style: "border: 2px grooved black; width 600px; height: 100px; "
			}
		],

		handlers: {
			onTabChanged: "switchStuff"
		},

		create: function() {
			this.inherited(arguments);
			this.$.bar.addTab(
				{
					'caption': 'English',
					'data' : { 'msg': 'Hello World !' } // arbitrary user data
				}
			) ;
			this.$.bar.addTab(
				{
					'caption': 'Français',
					'data' : { 'msg': 'Bonjour tout le monde !' } // arbitrary user data
				}
			) ;
		},

		switchStuff: function(inSender,inEvent) {
			this.log("Tapped tab with caption "+ inEvent.caption
					 + " and message " + inEvent.data.msg );
			this.$.stuff.setContent( inEvent.data.msg);
		}
	}
);

enyo.kind(
	{
		name: "onyx.sample.TabBarSample",
		classes: "onyx onyx-sample",
		components: [
			{
				classes: "onyx-sample-divider",
				content: "Tab Bar"
			},
			{
				kind:"App"
			}

	]
});
<commit_msg>ENYO-2310: added dynamic tab bar sample<commit_after>enyo.kind(
	{
		name: "SimpleTabBar",
		fit: true,
		components: [
			{name:"bar",kind: "onyx.TabBar"},
			{
				style: "border: 2px solid grey; ",
				components: [
					{
						content: 'Only the content of this kind is changed',
						style: 'padding: 1em'
					},
					{name: 'stuff', content: 'empty', style: 'padding: 1em'}
				]
			}
		],

		handlers: {
			onTabChanged: "switchStuff"
		},

		create: function() {
			this.inherited(arguments);
			this.$.bar.addTab(
				{
					'caption': 'English',
					'data' : { 'msg': 'Hello World !' } // arbitrary user data
				}
			) ;
			this.$.bar.addTab(
				{
					'caption': 'Français',
					'data' : { 'msg': 'Bonjour tout le monde !' } // arbitrary user data
				}
			) ;
		},

		switchStuff: function(inSender,inEvent) {
			this.log("Tapped tab with caption "+ inEvent.caption
					 + " and message " + inEvent.data.msg );
			this.$.stuff.setContent( inEvent.data.msg);
		}
	}
);

enyo.kind(
	{
		name: "DynamicTabBar",
		fit: true,
		components: [
			{name:"bar",kind: "onyx.TabBar"},
			{
				style: "border: 2px solid grey; ",
				components: [
					{
						content: 'create many tabs and reduce the width of the browser',
					},
					{name: 'stuff', content: 'empty', style: 'padding: 1em'},
					{
						kind: 'onyx.Button', content: 'create tab', ontap: 'addATab',
						style: 'margin: 0.5em'
					},
					{
						kind: 'onyx.Button', content: 'kill last tab', ontap: 'killTab'
					}
				]
			}
		],

		handlers: {
			onTabChanged: "switchStuff"
		},

		number: 1,
		create: function() {
			this.inherited(arguments);
			var date = new Date();
			this.creationTime = date.getTime();
			this.addATab() ;
		},

		addATab: function(inSender,inEvent) {
			this.log("adding a tab");
			var date = new Date();
			var delta = ( date.getTime() - this.creationTime ) / 1000 ;
			this.$.bar.addTab(
				{
					'caption': 'Tab label ' + this.number++ ,
					data: { msg: "tab created after " + delta + " seconds" }
				}
			) ;
		},

		switchStuff: function(inSender,inEvent) {
			this.log("Tapped tab with caption "+ inEvent.caption
					 + " and message " + inEvent.data.msg );
			this.$.stuff.setContent( inEvent.data.msg);
		},
		killTab: function(inSender,inEvent) {
			this.log("killing tab");
			this.$.bar.removeTab({index: this.number-- - 2});
		}

	}
);

enyo.kind(
	{
		name: "onyx.sample.TabBarSample",
		classes: "onyx onyx-sample",
		components: [
			{
				classes: "onyx-sample-divider",
				content: "Simple Tab Bar"
			},
			{
				kind:"SimpleTabBar"
			},
			{
				classes: "onyx-sample-divider",
				content: "Dynamic Tab Bar",
				style: 'padding-top: 4em;'
			},
			{
				kind:"DynamicTabBar"
			}

	]
});

<|endoftext|>


<commit_before>import { assign, defaults, flatten, isFunction, partialRight, uniq, some } from "lodash";
import React from "react";
import Axis from "./axis";
import { Style, Transitions, Collection, Data, Domain, Events } from "victory-core";

export default {
  getData(props, childComponents) {
    if (props.data) {
      return Data.getData(props);
    }
    childComponents = childComponents || React.Children.toArray(props.children);
    return this.getDataFromChildren(childComponents);
  },

  getDefaultDomainPadding(props, axis, childComponents) {
    const horizontalChildren = childComponents.some((component) => {
      return component.props && component.props.horizontal;
    });
    const horizontal = props && props.horizontal || horizontalChildren.length > 0;

    const groupComponent = childComponents.filter((child) => {
      return child.type && child.type.role && child.type.role === "group";
    });

    if (groupComponent.length < 1) {
      return undefined;
    }
    const { offset, children } = groupComponent[0].props;
    const defaultDomainPadding = horizontal ?
      {y: (offset * children.length) / 2} :
      {x: (offset * children.length) / 2};
    return defaultDomainPadding[axis];
  },

  getDomain(props, axis, childComponents) {
    childComponents = childComponents || React.Children.toArray(props.children);
    const propsDomain = Domain.getDomainFromProps(props, axis);
    if (propsDomain) {
      return propsDomain;
    }
    const dataset = (props.data || props.y) && Data.getData(props);
    const dataDomain = dataset ? Domain.getDomainFromData(props, axis, dataset) : [];
    const childDomain = this.getDomainFromChildren(props, axis, childComponents);
    const min = Collection.getMinValue([...dataDomain, ...childDomain]);
    const max = Collection.getMaxValue([...dataDomain, ...childDomain]);
    const domainPadding = this.getDefaultDomainPadding(props, axis, childComponents);
    const paddedDomain = Domain.padDomain([min, max], assign({domainPadding}, props), axis);
    return Domain.cleanDomain(paddedDomain, props, axis);

  },

  setAnimationState(props, nextProps) {
    if (!props.animate) {
      return;
    }
    if (props.animate.parentState) {
      const nodesWillExit = props.animate.parentState.nodesWillExit;
      const oldProps = nodesWillExit ? props : null;
      this.setState(defaults({oldProps, nextProps}, props.animate.parentState));
    } else {
      const oldChildren = React.Children.toArray(props.children);
      const nextChildren = React.Children.toArray(nextProps.children);
      const isContinuous = (child) => {
        const check = (c) => c.type && c.type.continuous;
        return Array.isArray(child) ? some(child, check) : check(child);
      };

      const continuous = some(oldChildren, (child) => {
        return isContinuous(child) || child.props.children && isContinuous(child.props.children);
      });
      const {
        nodesWillExit,
        nodesWillEnter,
        childrenTransitions,
        nodesShouldEnter
      } = Transitions.getInitialTransitionState(oldChildren, nextChildren);

      this.setState({
        nodesWillExit,
        nodesWillEnter,
        nodesShouldEnter,
        childrenTransitions: Collection.isArrayOfArrays(childrenTransitions) ?
          childrenTransitions[0] : childrenTransitions,
        oldProps: nodesWillExit ? props : null,
        nextProps,
        continuous
      });
    }
  },

  getAllEvents(props) {
    const components = ["groupComponent", "containerComponent"];
    this.componentEvents = Events.getComponentEvents(props, components);
    if (Array.isArray(this.componentEvents)) {
      return Array.isArray(props.events) ?
        this.componentEvents.concat(...props.events) : this.componentEvents;
    }
    return props.events;
  },

  getAnimationProps(props, child, index) {
    if (!props.animate) {
      return child.props.animate;
    }
    const getFilteredState = () => {
      let childrenTransitions = this.state && this.state.childrenTransitions;
      childrenTransitions = Collection.isArrayOfArrays(childrenTransitions) ?
        childrenTransitions[index] : childrenTransitions;
      return defaults({childrenTransitions}, this.state);
    };

    let getTransitions = props.animate && props.animate.getTransitions;
    const state = getFilteredState();
    const parentState = props.animate && props.animate.parentState || state;
    if (!getTransitions) {
      const getTransitionProps = Transitions.getTransitionPropsFactory(
        props,
        state,
        (newState) => this.setState(newState)
      );
      getTransitions = partialRight(getTransitionProps, index);
    }
    return defaults({getTransitions, parentState}, props.animate, child.props.animate);
  },

  getDomainFromChildren(props, axis, childComponents) { // eslint-disable-line max-statements, complexity, max-len
    const childDomains = [];
    let childDomainsLength = 0;

    const children = childComponents
      ? childComponents.slice(0)
      : React.Children.toArray(props.children);
    let childrenLength = children.length;

    const horizontalChildren = childComponents.some((component) => {
      return component.props && component.props.horizontal;
    });
    const horizontal = props && props.horizontal || horizontalChildren.length > 0;
    const currentAxis = Axis.getCurrentAxis(axis, horizontal);

    while (childrenLength > 0) {
      const child = children[--childrenLength];

      if (child.type && isFunction(child.type.getDomain)) {
        const parentData = props.data ? Data.getData(props, axis) : undefined;
        const sharedProps = parentData ?
          assign({}, child.props, {data: parentData}) : child.props;
        const childDomain = child.props && child.type.getDomain(sharedProps, currentAxis);
        if (childDomain) {
          const childDomainLength = childDomain.length;
          for (let index = 0; index < childDomainLength; index++) {
            childDomains[childDomainsLength++] = childDomain[index];
          }
        }
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      }
    }

    const min = Collection.getMinValue(childDomains);
    const max = Collection.getMaxValue(childDomains);
    return childDomains.length === 0 ?
      [0, 1] : [min, max];
  },

  getDataFromChildren(props, childComponents) { // eslint-disable-line max-statements
    const getData = (childProps) => {
      const data = Data.getData(childProps);
      return Array.isArray(data) && data.length > 0 ? data : undefined;
    };

    // Reverse the child array to maintain correct order when looping over
    // children starting from the end of the array.
    const children = childComponents
      ? childComponents.slice(0).reverse()
      : React.Children.toArray(props.children).reverse();

    let childrenLength = children.length;

    const dataArr = [];
    let dataArrLength = 0;
    while (childrenLength > 0) {
      const child = children[--childrenLength];
      if (child.type && child.type.role === "axis") {
        dataArrLength = dataArrLength;
      } else if (child.type && child.type.role !== "axis" && isFunction(child.type.getData)) {
        dataArr[dataArrLength++] = child.type.getData(child.props);
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      } else {
        dataArr[dataArrLength++] = getData(child.props);
      }
    }

    return dataArr;
  },

  getStackedDomain(props, axis) {
    const propsDomain = Domain.getDomainFromProps(props, axis);
    if (propsDomain) {
      return propsDomain;
    }
    const { horizontal } = props;
    const ensureZero = (domain) => {
      const isDependent = (axis === "y" && !horizontal) || (axis === "x" && horizontal);
      return isDependent ?
        [Collection.getMinValue(domain, 0), Collection.getMaxValue(domain, 0)] : domain;
    };
    const datasets = this.getDataFromChildren(props);
    return ensureZero(Domain.getDomainFromGroupedData(props, axis, datasets));
  },

  getColor(calculatedProps, child, index) {
    // check for styles first
    const { style } = calculatedProps;
    let { colorScale, color } = calculatedProps;
    if (style && style.data && style.data.fill) {
      return style.data.fill;
    }
    colorScale = child.props && child.props.colorScale ? child.props.colorScale : colorScale;
    color = child.props && child.props.color ? child.props.color : color;
    if (!colorScale && !color) {
      return undefined;
    }
    const colors = Array.isArray(colorScale) ?
      colorScale : Style.getColorScale(colorScale);
    return color || colors[index % colors.length];
  },

  getChildStyle(child, index, calculatedProps) {
    const { style } = calculatedProps;
    const role = child.type && child.type.role;
    const defaultFill = role === "stack" ?
      undefined : this.getColor(calculatedProps, child, index);
    const defaultColor = role === "line" ?
      {fill: "none", stroke: defaultFill} : {fill: defaultFill};
    const childStyle = child.props.style || {};
    const dataStyle = defaults({}, childStyle.data, assign({}, style.data, defaultColor));
    const labelsStyle = defaults({}, childStyle.labels, style.labels);
    return {
      parent: style.parent,
      data: dataStyle,
      labels: labelsStyle
    };
  },

  getStringsFromCategories(childComponents, axis) { // eslint-disable-line max-statements
    const strings = [];
    let stringsLength = 0;

    const children = childComponents.slice(0).reverse();
    let childrenLength = children.length;

    while (childrenLength > 0) {
      const child = children[--childrenLength];

      if (child.props && child.props.categories) {
        const newStrings = Data.getStringsFromCategories(child.props, axis);
        const newStringsLength = newStrings.length;
        for (let index = 0; index < newStringsLength; index++) {
          strings[stringsLength++] = newStrings[index];
        }
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      }
    }

    return strings;
  },

  getStringsFromData(childComponents, axis) { // eslint-disable-line max-statements
    const strings = [];
    let stringsLength = 0;

    const children = childComponents.slice(0).reverse();
    let childrenLength = children.length;

    while (childrenLength > 0) {
      const child = children[--childrenLength];

      if (child.props && child.props.data) {
        const newStrings = Data.getStringsFromData(child.props, axis);
        const newStringsLength = newStrings.length;
        for (let index = 0; index < newStringsLength; index++) {
          strings[stringsLength++] = newStrings[index];
        }
      } else if (child.type && isFunction(child.type.getData)) {
        const data = flatten(child.type.getData(child.props));
        const attr = axis === "x" ? "xName" : "yName";
        for (let index = 0; index < data.length; index++) {
          const datum = data[index];
          if (datum[attr]) {
            strings[stringsLength++] = datum[attr];
          }
        }
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      }
    }

    return strings;
  },

  getStringsFromChildren(props, axis, childComponents) {
    childComponents = childComponents || React.Children.toArray(props.children);
    const axisComponent = Axis.getAxisComponent(childComponents, axis);
    const axisStrings = axisComponent ? Data.getStringsFromAxes(axisComponent.props, axis) : [];
    const categoryStrings = this.getStringsFromCategories(childComponents, axis);
    const dataStrings = this.getStringsFromData(childComponents, axis);
    return uniq(flatten([...categoryStrings, ...dataStrings, ...axisStrings]));
  },

  getCategories(props, axis) {
    const categories = Data.getCategories(props, axis) ||
      this.getStringsFromChildren(props, axis);
    return categories.length > 0 ? categories : undefined;
  },

  getY0(datum, index, calculatedProps) {
    if (datum.y0) {
      return datum.y0;
    }
    const { datasets } = calculatedProps;
    const y = datum._y;
    const previousDataSets = datasets.slice(0, index);
    const previousPoints = previousDataSets.reduce((prev, dataset) => {
      return prev.concat(dataset
        .filter((previousDatum) => datum._x instanceof Date
          ? previousDatum._x.getTime() === datum._x.getTime()
          : previousDatum._x === datum._x)
        .map((previousDatum) => previousDatum._y || 0)
      );
    }, []);
    const y0 = previousPoints.length && previousPoints.reduce((memo, value) => {
      const sameSign = (y < 0 && value < 0) || (y >= 0 && value >= 0);
      return sameSign ? +value + memo : memo;
    }, 0);
    return previousPoints.some((point) => point instanceof Date) ? new Date(y0) : y0;
  }
};
<commit_msg>fix horizontal default domainPadding<commit_after>import { assign, defaults, flatten, isFunction, partialRight, uniq, some } from "lodash";
import React from "react";
import Axis from "./axis";
import { Style, Transitions, Collection, Data, Domain, Events } from "victory-core";

export default {
  getData(props, childComponents) {
    if (props.data) {
      return Data.getData(props);
    }
    childComponents = childComponents || React.Children.toArray(props.children);
    return this.getDataFromChildren(childComponents);
  },

  getDefaultDomainPadding(props, axis, childComponents) {
    const horizontalChildren = childComponents.some((component) => {
      return component.props && component.props.horizontal;
    });
    const horizontal = props && props.horizontal || horizontalChildren;
    const groupComponent = childComponents.filter((child) => {
      return child.type && child.type.role && child.type.role === "group";
    });

    if (groupComponent.length < 1) {
      return undefined;
    }
    const { offset, children } = groupComponent[0].props;
    const defaultDomainPadding = horizontal ?
      {y: (offset * children.length) / 2} :
      {x: (offset * children.length) / 2};
    return defaultDomainPadding[axis];
  },

  getDomain(props, axis, childComponents) {
    childComponents = childComponents || React.Children.toArray(props.children);
    const propsDomain = Domain.getDomainFromProps(props, axis);
    if (propsDomain) {
      return propsDomain;
    }
    const dataset = (props.data || props.y) && Data.getData(props);
    const dataDomain = dataset ? Domain.getDomainFromData(props, axis, dataset) : [];
    const childDomain = this.getDomainFromChildren(props, axis, childComponents);
    const min = Collection.getMinValue([...dataDomain, ...childDomain]);
    const max = Collection.getMaxValue([...dataDomain, ...childDomain]);
    const domainPadding = this.getDefaultDomainPadding(props, axis, childComponents);
    const paddedDomain = Domain.padDomain([min, max], assign({domainPadding}, props), axis);
    return Domain.cleanDomain(paddedDomain, props, axis);

  },

  setAnimationState(props, nextProps) {
    if (!props.animate) {
      return;
    }
    if (props.animate.parentState) {
      const nodesWillExit = props.animate.parentState.nodesWillExit;
      const oldProps = nodesWillExit ? props : null;
      this.setState(defaults({oldProps, nextProps}, props.animate.parentState));
    } else {
      const oldChildren = React.Children.toArray(props.children);
      const nextChildren = React.Children.toArray(nextProps.children);
      const isContinuous = (child) => {
        const check = (c) => c.type && c.type.continuous;
        return Array.isArray(child) ? some(child, check) : check(child);
      };

      const continuous = some(oldChildren, (child) => {
        return isContinuous(child) || child.props.children && isContinuous(child.props.children);
      });
      const {
        nodesWillExit,
        nodesWillEnter,
        childrenTransitions,
        nodesShouldEnter
      } = Transitions.getInitialTransitionState(oldChildren, nextChildren);

      this.setState({
        nodesWillExit,
        nodesWillEnter,
        nodesShouldEnter,
        childrenTransitions: Collection.isArrayOfArrays(childrenTransitions) ?
          childrenTransitions[0] : childrenTransitions,
        oldProps: nodesWillExit ? props : null,
        nextProps,
        continuous
      });
    }
  },

  getAllEvents(props) {
    const components = ["groupComponent", "containerComponent"];
    this.componentEvents = Events.getComponentEvents(props, components);
    if (Array.isArray(this.componentEvents)) {
      return Array.isArray(props.events) ?
        this.componentEvents.concat(...props.events) : this.componentEvents;
    }
    return props.events;
  },

  getAnimationProps(props, child, index) {
    if (!props.animate) {
      return child.props.animate;
    }
    const getFilteredState = () => {
      let childrenTransitions = this.state && this.state.childrenTransitions;
      childrenTransitions = Collection.isArrayOfArrays(childrenTransitions) ?
        childrenTransitions[index] : childrenTransitions;
      return defaults({childrenTransitions}, this.state);
    };

    let getTransitions = props.animate && props.animate.getTransitions;
    const state = getFilteredState();
    const parentState = props.animate && props.animate.parentState || state;
    if (!getTransitions) {
      const getTransitionProps = Transitions.getTransitionPropsFactory(
        props,
        state,
        (newState) => this.setState(newState)
      );
      getTransitions = partialRight(getTransitionProps, index);
    }
    return defaults({getTransitions, parentState}, props.animate, child.props.animate);
  },

  getDomainFromChildren(props, axis, childComponents) { // eslint-disable-line max-statements, complexity, max-len
    const childDomains = [];
    let childDomainsLength = 0;

    const children = childComponents
      ? childComponents.slice(0)
      : React.Children.toArray(props.children);
    let childrenLength = children.length;

    const horizontalChildren = childComponents.some((component) => {
      return component.props && component.props.horizontal;
    });
    const horizontal = props && props.horizontal || horizontalChildren.length > 0;
    const currentAxis = Axis.getCurrentAxis(axis, horizontal);

    while (childrenLength > 0) {
      const child = children[--childrenLength];

      if (child.type && isFunction(child.type.getDomain)) {
        const parentData = props.data ? Data.getData(props, axis) : undefined;
        const sharedProps = parentData ?
          assign({}, child.props, {data: parentData}) : child.props;
        const childDomain = child.props && child.type.getDomain(sharedProps, currentAxis);
        if (childDomain) {
          const childDomainLength = childDomain.length;
          for (let index = 0; index < childDomainLength; index++) {
            childDomains[childDomainsLength++] = childDomain[index];
          }
        }
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      }
    }

    const min = Collection.getMinValue(childDomains);
    const max = Collection.getMaxValue(childDomains);
    return childDomains.length === 0 ?
      [0, 1] : [min, max];
  },

  getDataFromChildren(props, childComponents) { // eslint-disable-line max-statements
    const getData = (childProps) => {
      const data = Data.getData(childProps);
      return Array.isArray(data) && data.length > 0 ? data : undefined;
    };

    // Reverse the child array to maintain correct order when looping over
    // children starting from the end of the array.
    const children = childComponents
      ? childComponents.slice(0).reverse()
      : React.Children.toArray(props.children).reverse();

    let childrenLength = children.length;

    const dataArr = [];
    let dataArrLength = 0;
    while (childrenLength > 0) {
      const child = children[--childrenLength];
      if (child.type && child.type.role === "axis") {
        dataArrLength = dataArrLength;
      } else if (child.type && child.type.role !== "axis" && isFunction(child.type.getData)) {
        dataArr[dataArrLength++] = child.type.getData(child.props);
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      } else {
        dataArr[dataArrLength++] = getData(child.props);
      }
    }

    return dataArr;
  },

  getStackedDomain(props, axis) {
    const propsDomain = Domain.getDomainFromProps(props, axis);
    if (propsDomain) {
      return propsDomain;
    }
    const { horizontal } = props;
    const ensureZero = (domain) => {
      const isDependent = (axis === "y" && !horizontal) || (axis === "x" && horizontal);
      return isDependent ?
        [Collection.getMinValue(domain, 0), Collection.getMaxValue(domain, 0)] : domain;
    };
    const datasets = this.getDataFromChildren(props);
    return ensureZero(Domain.getDomainFromGroupedData(props, axis, datasets));
  },

  getColor(calculatedProps, child, index) {
    // check for styles first
    const { style } = calculatedProps;
    let { colorScale, color } = calculatedProps;
    if (style && style.data && style.data.fill) {
      return style.data.fill;
    }
    colorScale = child.props && child.props.colorScale ? child.props.colorScale : colorScale;
    color = child.props && child.props.color ? child.props.color : color;
    if (!colorScale && !color) {
      return undefined;
    }
    const colors = Array.isArray(colorScale) ?
      colorScale : Style.getColorScale(colorScale);
    return color || colors[index % colors.length];
  },

  getChildStyle(child, index, calculatedProps) {
    const { style } = calculatedProps;
    const role = child.type && child.type.role;
    const defaultFill = role === "stack" ?
      undefined : this.getColor(calculatedProps, child, index);
    const defaultColor = role === "line" ?
      {fill: "none", stroke: defaultFill} : {fill: defaultFill};
    const childStyle = child.props.style || {};
    const dataStyle = defaults({}, childStyle.data, assign({}, style.data, defaultColor));
    const labelsStyle = defaults({}, childStyle.labels, style.labels);
    return {
      parent: style.parent,
      data: dataStyle,
      labels: labelsStyle
    };
  },

  getStringsFromCategories(childComponents, axis) { // eslint-disable-line max-statements
    const strings = [];
    let stringsLength = 0;

    const children = childComponents.slice(0).reverse();
    let childrenLength = children.length;

    while (childrenLength > 0) {
      const child = children[--childrenLength];

      if (child.props && child.props.categories) {
        const newStrings = Data.getStringsFromCategories(child.props, axis);
        const newStringsLength = newStrings.length;
        for (let index = 0; index < newStringsLength; index++) {
          strings[stringsLength++] = newStrings[index];
        }
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      }
    }

    return strings;
  },

  getStringsFromData(childComponents, axis) { // eslint-disable-line max-statements
    const strings = [];
    let stringsLength = 0;

    const children = childComponents.slice(0).reverse();
    let childrenLength = children.length;

    while (childrenLength > 0) {
      const child = children[--childrenLength];

      if (child.props && child.props.data) {
        const newStrings = Data.getStringsFromData(child.props, axis);
        const newStringsLength = newStrings.length;
        for (let index = 0; index < newStringsLength; index++) {
          strings[stringsLength++] = newStrings[index];
        }
      } else if (child.type && isFunction(child.type.getData)) {
        const data = flatten(child.type.getData(child.props));
        const attr = axis === "x" ? "xName" : "yName";
        for (let index = 0; index < data.length; index++) {
          const datum = data[index];
          if (datum[attr]) {
            strings[stringsLength++] = datum[attr];
          }
        }
      } else if (child.props && child.props.children) {
        const newChildren = React.Children.toArray(child.props.children);
        const newChildrenLength = newChildren.length;
        for (let index = 0; index < newChildrenLength; index++) {
          children[childrenLength++] = newChildren[index];
        }
      }
    }

    return strings;
  },

  getStringsFromChildren(props, axis, childComponents) {
    childComponents = childComponents || React.Children.toArray(props.children);
    const axisComponent = Axis.getAxisComponent(childComponents, axis);
    const axisStrings = axisComponent ? Data.getStringsFromAxes(axisComponent.props, axis) : [];
    const categoryStrings = this.getStringsFromCategories(childComponents, axis);
    const dataStrings = this.getStringsFromData(childComponents, axis);
    return uniq(flatten([...categoryStrings, ...dataStrings, ...axisStrings]));
  },

  getCategories(props, axis) {
    const categories = Data.getCategories(props, axis) ||
      this.getStringsFromChildren(props, axis);
    return categories.length > 0 ? categories : undefined;
  },

  getY0(datum, index, calculatedProps) {
    if (datum.y0) {
      return datum.y0;
    }
    const { datasets } = calculatedProps;
    const y = datum._y;
    const previousDataSets = datasets.slice(0, index);
    const previousPoints = previousDataSets.reduce((prev, dataset) => {
      return prev.concat(dataset
        .filter((previousDatum) => datum._x instanceof Date
          ? previousDatum._x.getTime() === datum._x.getTime()
          : previousDatum._x === datum._x)
        .map((previousDatum) => previousDatum._y || 0)
      );
    }, []);
    const y0 = previousPoints.length && previousPoints.reduce((memo, value) => {
      const sameSign = (y < 0 && value < 0) || (y >= 0 && value >= 0);
      return sameSign ? +value + memo : memo;
    }, 0);
    return previousPoints.some((point) => point instanceof Date) ? new Date(y0) : y0;
  }
};
<|endoftext|>


<commit_before>// # imagesService
//      everything related to image manipulation
//
'use strict';

import * as gcs from '../util/gcs';
import * as actionCore from '../core/action-core';
import {throwStatus} from '../util/express';
import * as userCore from '../core/user-core';
import {assert} from '../validation';
import {decodeBase64Image} from '../util/base64';
import {padLeft} from '../util/string';

const gm = require('gm').subClass({ imageMagick: true });

const TARGET_FOLDER = "user_content";
const ALLOWED_MIME_TYPES = new Set(['image/jpeg', 'image/gif', 'image/png']);

function getAndValidateActionType(typeName) {
  return actionCore.getActionType(typeName)
    .then(type => {
        if (type === null) {
          throwStatus(400, `Action type ${ typeName } does not exist`);
        }

        return type;
    });
}

function getAndValidateUser(uuid) {
  return userCore.findByUuid(uuid)
    .then(user => {
      if (user === null) {
        throwStatus(400, `User with uuid ${ uuid } does not exist`);
      }

      return user;
    });
}

function uploadImage(imageName, imageFile) {
  console.log("Uploading", imageName);

  return Promise.resolve()
    .then(() => validateMimeType(imageFile.mimetype))
    .then(() => autoOrient(imageFile.buffer))
    .then(buffer => gcs.uploadImageBuffer(imageName, buffer));
};

function validateMimeType(mimetype) {
  if (ALLOWED_MIME_TYPES.has(mimetype)) {
    return Promise.resolve();
  } else {
    throw new Error(`Unsupported file type ${ mimetype } uploaded`);
  }
}

function autoOrient(imageBuffer) {
  return new Promise((resolve, reject) => {
    try {
      gm(imageBuffer)
        .autoOrient()
        .toBuffer('JPG', (error, resultBuffer) => {
          error ? reject(error) : resolve(resultBuffer);
        });
    } catch (err) {
      console.log("ERROR");
      reject(err);
    }
  });
}

function postImage(req, res) {
  const action = assert(req.body, 'action');
  const image = decodeBase64Image(req.body.imageData);
  const result = {};

  return getAndValidateActionType(action.type)
    .then(type => {
      result.type = type;

      return getAndValidateUser(action.user);
    })
    .then(user => {
      result.user = user;

      const fileName = `${ TARGET_FOLDER }/${ padLeft(user.id, 5) }-${ Date.now() }`;
      return uploadImage(fileName, image);
    })
    .then(uploadedImage => {
      return actionCore.createAction({
        team:      action.team,
        type:      action.type,
        user:      action.user,
        location:  action.location,
        imagePath: uploadedImage.imageName
      }).then(rowsInserted => undefined);
    });
};

export {
  postImage
};
<commit_msg>Support gifs in image upload<commit_after>// # imagesService
//      everything related to image manipulation
//
'use strict';

import * as gcs from '../util/gcs';
import * as actionCore from '../core/action-core';
import {throwStatus} from '../util/express';
import * as userCore from '../core/user-core';
import {assert} from '../validation';
import {decodeBase64Image} from '../util/base64';
import {padLeft} from '../util/string';
const logger = require('../util/logger')(__filename);

const gm = require('gm').subClass({ imageMagick: true });

const TARGET_FOLDER = "user_content";
const ALLOWED_MIME_TYPES = new Set(['image/jpeg', 'image/gif', 'image/png']);

function getAndValidateActionType(typeName) {
  return actionCore.getActionType(typeName)
    .then(type => {
        if (type === null) {
          throwStatus(400, `Action type ${ typeName } does not exist`);
        }

        return type;
    });
}

function getAndValidateUser(uuid) {
  return userCore.findByUuid(uuid)
    .then(user => {
      if (user === null) {
        throwStatus(400, `User with uuid ${ uuid } does not exist`);
      }

      return user;
    });
}

function uploadImage(imageName, imageFile) {
  logger.info("Uploading", imageName);

  return Promise.resolve()
    .then(() => validateMimeType(imageFile.mimetype))
    .then(() => {
      if (imageFile.mimetype === 'image/gif') {
        return imageFile.buffer;
      } else {
        return autoOrient(imageFile.buffer);
      }
    })
    .then(buffer => gcs.uploadImageBuffer(imageName, buffer));
};

function validateMimeType(mimetype) {
  if (ALLOWED_MIME_TYPES.has(mimetype)) {
    return Promise.resolve();
  } else {
    throw new Error(`Unsupported file type ${ mimetype } uploaded`);
  }
}

function autoOrient(imageBuffer) {
  return new Promise((resolve, reject) => {
    try {
      gm(imageBuffer)
        .autoOrient()
        .toBuffer('JPG', (error, resultBuffer) => {
          error ? reject(error) : resolve(resultBuffer);
        });
    } catch (err) {
      logger.error('Error in auto-orient:', err);
      logger.error(err.stack);
      reject(err);
    }
  });
}

function postImage(req, res) {
  const action = assert(req.body, 'action');
  const image = decodeBase64Image(req.body.imageData);
  const result = {};

  return getAndValidateActionType(action.type)
    .then(type => {
      result.type = type;

      return getAndValidateUser(action.user);
    })
    .then(user => {
      result.user = user;

      const fileName = `${ TARGET_FOLDER }/${ padLeft(user.id, 5) }-${ Date.now() }`;
      return uploadImage(fileName, image);
    })
    .then(uploadedImage => {
      return actionCore.createAction({
        team:      action.team,
        type:      action.type,
        user:      action.user,
        location:  action.location,
        imagePath: uploadedImage.imageName
      }).then(rowsInserted => undefined);
    });
};

export {
  postImage
};
<|endoftext|>


<commit_before>'use strict';

module.exports = {
  plugins: [
    'react',
  ],
  parserOptions: {
    ecmaVersion: 2017,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  rules: {
    // Enable original eslint rules
    'jsx-quotes': 'error',

    // React rules
    'react/display-name': 'off',
    'react/forbid-component-props': 'off',
    'react/forbid-elements': 'off',
    'react/forbid-prop-types': 'error',
    'react/forbid-foreign-prop-types': 'error',
    'react/no-array-index-key': 'error',
    'react/no-children-prop': 'error',
    'react/no-danger': 'error',
    'react/no-danger-with-children': 'error',
    'react/no-deprecated': 'error',
    'react/no-did-mount-set-state': 'off',
    'react/no-did-update-set-state': 'off',
    'react/no-direct-mutation-state': 'error',
    'react/no-find-dom-node': 'error',
    'react/no-is-mounted': 'error',
    'react/no-multi-comp': ['error', {ignoreStateless: true}],
    'react/no-render-return-value': 'error',
    'react/no-set-state': 'off',
    'react/no-string-refs': 'error',
    'react/no-unescaped-entities': 'error',
    'react/no-unknown-property': 'error',
    'react/no-unused-prop-types': 'error',
    'react/prefer-es6-class': 'error',
    'react/prefer-stateless-function': 'error',
    'react/prop-types': 'error',
    'react/react-in-jsx-scope': 'error',
    'react/require-default-props': 'error',
    'react/require-optimization': 'off',
    'react/require-render-return': 'error',
    'react/self-closing-comp': 'error',
    'react/sort-comp': 'error',
    'react/sort-prop-types': 'off',
    'react/style-prop-object': 'error',
    'react/void-dom-elements-no-children': 'error',

    // JSX-specific rules
    'react/jsx-boolean-value': 'error',
    'react/jsx-closing-bracket-location': 'error',
    'react/jsx-curly-spacing': 'error',
    'react/jsx-equals-spacing': 'error',
    'react/jsx-filename-extension': ['error', {extensions: ['.js', '.jsx']}],
    'react/jsx-first-prop-new-line': ['error', 'multiline'],
    'react/jsx-handler-names': 'error',
    'react/jsx-indent': ['error', 2],
    'react/jsx-indent-props': ['error', 2],
    'react/jsx-key': 'error',
    'react/jsx-max-props-per-line': ['error', {maximum: 2}],
    'react/jsx-no-bind': ['error', {allowArrowFunctions: true}],
    'react/jsx-no-comment-textnodes': 'error',
    'react/jsx-no-duplicate-props': ['error', {ignoreCase: true}],
    'react/jsx-no-literals': 'off',
    'react/jsx-no-target-blank': 'error',
    'react/jsx-no-undef': 'error',
    'react/jsx-pascal-case': 'error',
    'react/jsx-sort-props': 'off',
    'react/jsx-space-before-closing': 'error',
    'react/jsx-tag-spacing': 'error',
    'react/jsx-uses-react': 'error',
    'react/jsx-uses-vars': 'error',
    'react/jsx-wrap-multilines': 'error',
  },
};
<commit_msg>Enable `react/jsx-sort-props` rule<commit_after>'use strict';

module.exports = {
  plugins: [
    'react',
  ],
  parserOptions: {
    ecmaVersion: 2017,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  rules: {
    // Enable original eslint rules
    'jsx-quotes': 'error',

    // React rules
    'react/display-name': 'off',
    'react/forbid-component-props': 'off',
    'react/forbid-elements': 'off',
    'react/forbid-prop-types': 'error',
    'react/forbid-foreign-prop-types': 'error',
    'react/no-array-index-key': 'error',
    'react/no-children-prop': 'error',
    'react/no-danger': 'error',
    'react/no-danger-with-children': 'error',
    'react/no-deprecated': 'error',
    'react/no-did-mount-set-state': 'off',
    'react/no-did-update-set-state': 'off',
    'react/no-direct-mutation-state': 'error',
    'react/no-find-dom-node': 'error',
    'react/no-is-mounted': 'error',
    'react/no-multi-comp': ['error', {ignoreStateless: true}],
    'react/no-render-return-value': 'error',
    'react/no-set-state': 'off',
    'react/no-string-refs': 'error',
    'react/no-unescaped-entities': 'error',
    'react/no-unknown-property': 'error',
    'react/no-unused-prop-types': 'error',
    'react/prefer-es6-class': 'error',
    'react/prefer-stateless-function': 'error',
    'react/prop-types': 'error',
    'react/react-in-jsx-scope': 'error',
    'react/require-default-props': 'error',
    'react/require-optimization': 'off',
    'react/require-render-return': 'error',
    'react/self-closing-comp': 'error',
    'react/sort-comp': 'error',
    'react/sort-prop-types': 'off',
    'react/style-prop-object': 'error',
    'react/void-dom-elements-no-children': 'error',

    // JSX-specific rules
    'react/jsx-boolean-value': 'error',
    'react/jsx-closing-bracket-location': 'error',
    'react/jsx-curly-spacing': 'error',
    'react/jsx-equals-spacing': 'error',
    'react/jsx-filename-extension': ['error', {extensions: ['.js', '.jsx']}],
    'react/jsx-first-prop-new-line': ['error', 'multiline'],
    'react/jsx-handler-names': 'error',
    'react/jsx-indent': ['error', 2],
    'react/jsx-indent-props': ['error', 2],
    'react/jsx-key': 'error',
    'react/jsx-max-props-per-line': ['error', {maximum: 2}],
    'react/jsx-no-bind': ['error', {allowArrowFunctions: true}],
    'react/jsx-no-comment-textnodes': 'error',
    'react/jsx-no-duplicate-props': ['error', {ignoreCase: true}],
    'react/jsx-no-literals': 'off',
    'react/jsx-no-target-blank': 'error',
    'react/jsx-no-undef': 'error',
    'react/jsx-pascal-case': 'error',
    'react/jsx-sort-props': [
      'error',
      {
        callbacksLast: true,
        shorthandLast: true,
      },
    ],
    'react/jsx-space-before-closing': 'error',
    'react/jsx-tag-spacing': 'error',
    'react/jsx-uses-react': 'error',
    'react/jsx-uses-vars': 'error',
    'react/jsx-wrap-multilines': 'error',
  },
};
<|endoftext|>


<commit_before>'use strict';

const exec = require('child_process').exec;
const fs = require('fs-extra');
const path = require('path');

const excludesDir = 'node_modules/fepper/excludes';

var confFile = 'conf.yml';
var confFileSrc = path.resolve(excludesDir, confFile);
if (fs.existsSync(confFileSrc)) {
  fs.copySync(confFileSrc, confFile);
}

var plConfFile = 'patternlab-config.json';
var plConfFileSrc = path.resolve(excludesDir, plConfFile);
if (fs.existsSync(plConfFileSrc)) {
  fs.copySync(plConfFileSrc, plConfFile);
}

var prefFile = 'pref.yml';
var prefFileSrc = path.resolve(excludesDir, prefFile);
if (fs.existsSync(prefFileSrc)) {
  fs.copySync(prefFileSrc, prefFile);
}

var binGulp = path.resolve('node_modules', '.bin', 'gulp');
exec(`${binGulp} --gulpfile node_modules/fepper/tasker.js install`, (err, stdout, stderr) => {
  if (err) {
    throw err;
  }

  fs.writeFileSync('install.log', stdout);
  if (stderr) {

    /* eslint-disable no-console */
    console.log(stderr);

    /* eslint-enable no-console */
    fs.appendFileSync('install.log', stderr);
  }
});
<commit_msg>fixing install.js to write when file doesn't exist<commit_after>'use strict';

const exec = require('child_process').exec;
const fs = require('fs-extra');
const path = require('path');

const excludesDir = 'node_modules/fepper/excludes';

var confFile = 'conf.yml';
var confFileSrc = path.resolve(excludesDir, confFile);
if (!fs.existsSync(confFileSrc)) {
  fs.copySync(confFileSrc, confFile);
}

var plConfFile = 'patternlab-config.json';
var plConfFileSrc = path.resolve(excludesDir, plConfFile);
if (!fs.existsSync(plConfFileSrc)) {
  fs.copySync(plConfFileSrc, plConfFile);
}

var prefFile = 'pref.yml';
var prefFileSrc = path.resolve(excludesDir, prefFile);
if (!fs.existsSync(prefFileSrc)) {
  fs.copySync(prefFileSrc, prefFile);
}

var binGulp = path.resolve('node_modules', '.bin', 'gulp');
exec(`${binGulp} --gulpfile node_modules/fepper/tasker.js install`, (err, stdout, stderr) => {
  if (err) {
    throw err;
  }

  fs.writeFileSync('install.log', stdout);
  if (stderr) {

    /* eslint-disable no-console */
    console.log(stderr);

    /* eslint-enable no-console */
    fs.appendFileSync('install.log', stderr);
  }
});
<|endoftext|>


<commit_before>import { update } from "./renderer"

const tuple = {
	data: null,
	key: null,
	parentKey: null
}

function Proxy(key, func) {
	this.key = key
	this.func = func
}

class Store
{
	constructor()
	{
		this.data = {}
		this.watchers = {}
		this.proxies = []
	}

	set(key, value, force)
	{
		this.dispatch({
			action: "SET",
			key,
			value,
			force
		})
	}

	add(key, value)
	{
		this.dispatch({
			action: "ADD",
			key,
			value
		})
	}

	remove(key, value)
	{
		this.dispatch({
			action: "REMOVE",
			key
		})
	}

	create(key, value)
	{
		this.dispatch({
			action: "CREATE",
			key,
			value
		})
	}

	dispatch(data)
	{
		if(this.globalProxy) {
			this.globalProxy(data)
		}
		else {
			this.handle(data)
		}

		for(let n = 0; n < this.proxies.length; n++) {
			const proxy = this.proxies[n]
			if(data.key.indexOf(proxy.key) === 0) {
				proxy.func(data)
			}
		}
	}

	performSet(payload)
	{
		if(!this.getData(payload.key, payload.force)) { return }

		if(!tuple.key)
		{
			this.data = payload.value

			for(let key in this.watchers)
			{
				const value = this.get(key)

				const emitPayload = {
					action: "SET",
					key: key,
					value: value
				}
				this.emit(emitPayload)
			}
		}
		else
		{
			tuple.data[tuple.key] = payload.value
			this.emit(payload)

			if(tuple.parentKey)
			{
				const emitPayload = {
					action: payload.action,
					key: tuple.parentKey,
					value: tuple.data,
					changedKey: tuple.key,
					changedValue: payload.value
				}
				this.emit(emitPayload)
			}
		}
	}

	performAdd(payload)
	{
		if(!this.getData(payload.key)) { return }

		let array = tuple.data[tuple.key]
		if(!array) {
			array = [ payload.value ]
			tuple.data[tuple.key] = array
		}
		else if(!Array.isArray(array)) {
			console.warn("(store) Data at key '${payload.key}' is not an Array")
			return
		}
		else {
			array.push(payload.value)
		}

		const emitPayload = {
			action: payload.action,
			key: tuple.key,
			value: array
		}
		this.emit(emitPayload)
	}

	performRemove(payload)
	{
		if(!this.getData(payload.key)) { return }

		const data = tuple.data
		if(Array.isArray(data)) {
			data.splice(parseInt(tuple.key), 1)
		}
		else {
			delete data[tuple.key]
		}

		this.emit(payload)

		const emitPayload = {
			action: payload.action,
			key: tuple.parentKey,
			value: data,
			changedKey: tuple.key
		}
		this.emit(emitPayload)
	}

	performCreate(payload)
	{
		if(!this.getData(payload.key, true)) { return }

		if(!tuple.data[tuple.key]) {
			tuple.data[tuple.key] = payload.value
		}
	}

	handle(data)
	{
		switch(data.action) {
			case "SET":
				this.performSet(data)
				break
			case "ADD":
				this.performAdd(data)
				break
			case "REMOVE":
				this.performRemove(data)
				break
			case "CREATE":
				this.performCreate(data)
				break
		}
	}

	watch(key, element)
	{
		const buffer = this.watchers[key]
		if(!buffer) {
			this.watchers[key] = [ element ]
		}
		else {
			buffer.push(element)
		}
	}

	unwatch(key, element)
	{
		const buffer = this.watchers[key]
		if(!buffer) { return }

		for(let n = 0; n < buffer.length; n++)
		{
			if(buffer[n] === element) {
				buffer[n] = buffer[buffer.length - 1]
				buffer.pop()
				break
			}
		}

		if(buffer.length === 0) {
			delete this.watchers[key]
		}
	}

	emit(payload)
	{
		const buffer = this.watchers[payload.key]
		if(!buffer) { return }

		for(let n = 0; n < buffer.length; n++) {
			buffer[n](payload)
		}
	}

	get(key)
	{
		if(!key)
		{
			if(key === undefined) {
				return ""
			}

			return this.data
		}

		const buffer = key.split(".")
		let data = this.data

		for(let n = 0; n < buffer.length; n++)
		{
			const id = buffer[n]
			if(id === "@") {
				return buffer[n - 1]
			}
			else {
				data = data[id]
			}

			if(data === undefined) {
				return null
			}
		}

		return data
	}

	getData(key, force)
	{
		if(!key) {
			tuple.data = this.data
			tuple.key = null
			tuple.parentKey = null
			return tuple
		}

		const buffer = key.split(".")
		let data = this.data

		const num = buffer.length - 1;
		if(num === 0)
		{
			tuple.data = data
			tuple.key = buffer[0]
			tuple.parentKey = null
		}
		else
		{
			for(let n = 0; n < num; n++)
			{
				const newData = data[buffer[n]]
				if(!newData)
				{
					if(!force) {
						console.warn(`(store.getData) No data available with key: [${buffer[n]}] in address: [${key}]`)
						return null
					}
					else
					{
						for(; n < num; n++) {
							const newDict = {}
							data[buffer[n]] = newDict
							data = newDict
						}
						break
					}

				}

				data = newData
			}

			tuple.data = data
			tuple.key = buffer[num]
			tuple.parentKey = key.slice(0, key.lastIndexOf("."))
		}

		return tuple
	}

	addProxy(key, func)
	{
		if(key === "")
		{
			if(this.globalProxy) {
				console.warn("(wabi.proxy) There is already global proxy declared")
				return
			}

			this.globalProxy = func
		}
		else
		{
			for(let n = 0; n < this.proxies.length; n++) {
				const proxy = this.proxies[n]
				if(proxy.key === key && proxy.func === func) {
					console.warn("(wabi.proxy) There is already a proxy declared with key:", key)
					return
				}
			}

			const proxy = new Proxy(key, func)
			this.proxies.push(proxy)
		}
	}

	removeProxy(key, func)
	{
		if(key === "")
		{
			if(this.globalProxy !== func) {
				console.warn("(wabi.proxy) Global proxy functions don`t match")
				return
			}

			this.globalProxy = null
		}
		else
		{
			for(let n = 0; n < this.proxies.length; n++) {
				const proxy = this.proxies[n]
				if(proxy.key === key && proxy.func === func) {
					this.proxies[n] = this.proxies[this.proxies.length - 1]
					this.proxies.pop()
					return
				}
			}
		}
	}

	toJSON() {
		return this.data
	}
}

const store = new Store()

const lastSegment = function(str)
{
	const index = str.lastIndexOf(".")
	if(index === -1) { return null }

	return str.slice(index + 1)
}

export {
	store, lastSegment
}
<commit_msg>Change store path separator from "." to "/"<commit_after>import { update } from "./renderer"

const tuple = {
	data: null,
	key: null,
	parentKey: null
}

function Proxy(key, func) {
	this.key = key
	this.func = func
}

class Store
{
	constructor()
	{
		this.data = {}
		this.watchers = {}
		this.proxies = []
	}

	set(key, value, force)
	{
		this.dispatch({
			action: "SET",
			key,
			value,
			force
		})
	}

	add(key, value)
	{
		this.dispatch({
			action: "ADD",
			key,
			value
		})
	}

	remove(key, value)
	{
		this.dispatch({
			action: "REMOVE",
			key
		})
	}

	create(key, value)
	{
		this.dispatch({
			action: "CREATE",
			key,
			value
		})
	}

	dispatch(data)
	{
		if(this.globalProxy) {
			this.globalProxy(data)
		}
		else {
			this.handle(data)
		}

		for(let n = 0; n < this.proxies.length; n++) {
			const proxy = this.proxies[n]
			if(data.key.indexOf(proxy.key) === 0) {
				proxy.func(data)
			}
		}
	}

	performSet(payload)
	{
		if(!this.getData(payload.key, payload.force)) { return }

		if(!tuple.key)
		{
			this.data = payload.value

			for(let key in this.watchers)
			{
				const value = this.get(key)

				const emitPayload = {
					action: "SET",
					key: key,
					value: value
				}
				this.emit(emitPayload)
			}
		}
		else
		{
			tuple.data[tuple.key] = payload.value
			this.emit(payload)

			if(tuple.parentKey)
			{
				const emitPayload = {
					action: payload.action,
					key: tuple.parentKey,
					value: tuple.data,
					changedKey: tuple.key,
					changedValue: payload.value
				}
				this.emit(emitPayload)
			}
		}
	}

	performAdd(payload)
	{
		if(!this.getData(payload.key)) { return }

		let array = tuple.data[tuple.key]
		if(!array) {
			array = [ payload.value ]
			tuple.data[tuple.key] = array
		}
		else if(!Array.isArray(array)) {
			console.warn("(store) Data at key '${payload.key}' is not an Array")
			return
		}
		else {
			array.push(payload.value)
		}

		const emitPayload = {
			action: payload.action,
			key: tuple.key,
			value: array
		}
		this.emit(emitPayload)
	}

	performRemove(payload)
	{
		if(!this.getData(payload.key)) { return }

		const data = tuple.data
		if(Array.isArray(data)) {
			data.splice(parseInt(tuple.key), 1)
		}
		else {
			delete data[tuple.key]
		}

		this.emit(payload)

		const emitPayload = {
			action: payload.action,
			key: tuple.parentKey,
			value: data,
			changedKey: tuple.key
		}
		this.emit(emitPayload)
	}

	performCreate(payload)
	{
		if(!this.getData(payload.key, true)) { return }

		if(!tuple.data[tuple.key]) {
			tuple.data[tuple.key] = payload.value
		}
	}

	handle(data)
	{
		switch(data.action) {
			case "SET":
				this.performSet(data)
				break
			case "ADD":
				this.performAdd(data)
				break
			case "REMOVE":
				this.performRemove(data)
				break
			case "CREATE":
				this.performCreate(data)
				break
		}
	}

	watch(key, element)
	{
        const buffer = this.watchers[key]
        if(!buffer) {
            this.watchers[key] = [ element ]
        }
        else {
            buffer.push(element)
        }
	}

	unwatch(key, element)
	{
		const buffer = this.watchers[key]
		if(!buffer) { return }

		for(let n = 0; n < buffer.length; n++)
		{
			if(buffer[n] === element) {
				buffer[n] = buffer[buffer.length - 1]
				buffer.pop()
				break
			}
		}

		if(buffer.length === 0) {
			delete this.watchers[key]
		}
	}

	emit(payload)
	{
		const buffer = this.watchers[payload.key]
		if(!buffer) { return }

		for(let n = 0; n < buffer.length; n++) {
			buffer[n](payload)
		}
	}

	get(key)
	{
		if(!key)
		{
			if(key === undefined) {
				return ""
			}

			return this.data
		}

		const buffer = key.split("/")
		let data = this.data

		for(let n = 0; n < buffer.length; n++)
		{
			const id = buffer[n]
			if(id === "@") {
				return buffer[n - 1]
			}
			else {
				data = data[id]
			}

			if(data === undefined) {
				return null
			}
		}

		return data
	}

	getData(key, force)
	{
		if(!key) {
			tuple.data = this.data
			tuple.key = null
			tuple.parentKey = null
			return tuple
		}

		const buffer = key.split("/")
		let data = this.data

		const num = buffer.length - 1;
		if(num === 0)
		{
			tuple.data = data
			tuple.key = buffer[0]
			tuple.parentKey = null
		}
		else
		{
			for(let n = 0; n < num; n++)
			{
				const newData = data[buffer[n]]
				if(!newData)
				{
					if(!force) {
						console.warn(`(store.getData) No data available with key: [${buffer[n]}] in address: [${key}]`)
						return null
					}
					else
					{
						for(; n < num; n++) {
							const newDict = {}
							data[buffer[n]] = newDict
							data = newDict
						}
						break
					}

				}

				data = newData
			}

			tuple.data = data
			tuple.key = buffer[num]
			tuple.parentKey = key.slice(0, key.lastIndexOf("/"))
		}

		return tuple
	}

	addProxy(key, func)
	{
		if(key === "")
		{
			if(this.globalProxy) {
				console.warn("(wabi.proxy) There is already global proxy declared")
				return
			}

			this.globalProxy = func
		}
		else
		{
			for(let n = 0; n < this.proxies.length; n++) {
				const proxy = this.proxies[n]
				if(proxy.key === key && proxy.func === func) {
					console.warn("(wabi.proxy) There is already a proxy declared with key:", key)
					return
				}
			}

			const proxy = new Proxy(key, func)
			this.proxies.push(proxy)
		}
	}

	removeProxy(key, func)
	{
		if(key === "")
		{
			if(this.globalProxy !== func) {
				console.warn("(wabi.proxy) Global proxy functions don`t match")
				return
			}

			this.globalProxy = null
		}
		else
		{
			for(let n = 0; n < this.proxies.length; n++) {
				const proxy = this.proxies[n]
				if(proxy.key === key && proxy.func === func) {
					this.proxies[n] = this.proxies[this.proxies.length - 1]
					this.proxies.pop()
					return
				}
			}
		}
	}

	toJSON() {
		return this.data
	}
}

const store = new Store()

const lastSegment = function(str)
{
	const index = str.lastIndexOf("/")
	if(index === -1) { return null }

	return str.slice(index + 1)
}

export {
	store, lastSegment
}
<|endoftext|>


<commit_before><commit_msg>transparencia modificada<commit_after><|endoftext|>