<commit_before>var $ = require('programmatic')
var signage = require('./signage')
var composeIncrementalParser = require('./inc')
var unpackAll = require('./unpack')

var formatters = {
    blank: function (source) {
        return $('                                                          \n\
            ', source, '                                                    \n\
            // __blank__                                                    \n\
        ')
    },
    range: function (source, vars) {
        return $('                                                          \n\
            ', source, '                                                    \n\
            if (end - start < ' + vars.sentry + ') {                        \n\
                return inc.call(this, buffer, start, end, ' + vars.step + ')\n\
            }                                                               \n\
            // __blank__                                                    \n\
        ')
    },
    arrayBuffer: function (source, vars) {
        return $('                                                          \n\
            ', source, '                                                    \n\
            value = new ArrayBuffer(' + vars.field.bytes + ')               \n\
        ')
    },
    copy: function (source, vars) {
        var field = vars.field
        var little = field.endianness == 'l'
        var bytes = field.bytes
        var bite = little ? 0 : bytes - 1
        var direction = little ? 1 : -1
        var stop = little ? bytes : -1
        var index = little ? 0 : bytes - 1
        var copy = []
        while (bite != stop) {
            copy.push('value[' + index + '] = buffer[start++]')
            index += direction
            bite += direction
        }
        return $('                                                          \n\
            ', source, '                                                    \n\
            ', copy.join('\n'), '                                           \n\
        ')
    },
    toFloat: function (source, vars) {
        var bits = vars.field.bits, name = vars.field.name
        return $('                                                          \n\
            ', source, '                                                    \n\
            object.' + name +
                ' = new DataView(value).getFloat' + bits + '(0, true)       \n\
        ')
    },
    skip: function (source, vars) {
        var skip = vars.field.bytes * vars.field.repeat
        return $('                                                          \n\
            ', source, '                                                    \n\
            start += ' + skip + '                                           \n\
            // __blank__                                                    \n\
        ')
    },
    assignment: function (source, vars) {
        var field = vars.field
        var little = field.endianness == 'l'
        var bytes = field.bytes
        var bite = little ? 0 : bytes - 1
        var direction = little ? 1 : -1
        var stop = little ? bytes : -1
        var read = []
        while (bite != stop) {
            read.unshift('buffer[start++]')
            if (bite) {
                read[0] += ' * 0x' + Math.pow(256, bite).toString(16)
            }
            bite += direction
        }
        read = read.reverse().join(' + \n')
        if (field.bytes == 1) {
            var assignment = vars.assignee + ' = ' + read
        } else {
            var assignment = $('\n\
                ' + vars.assignee + ' =                                     \n\
                    ', read, '')
        }
        return $('                                                          \n\
            ', source, '                                                    \n\
            ', assignment, '                                                \n\
        ')
    },
    signage: function (source, vars) {
        return $('                                                          \n\
            ', source, '                                                    \n\
            ', signage(vars.field, 'object.' + vars.field.name), '          \n\
        ')
    },
    unpack: function (source, vars) {
        return $('                                                          \n\
            ', source, '                                                    \n\
            ', unpackAll(vars.field), '                                     \n\
        ')
    }
}

function composeParser (ranges) {
    composeIncrementalParser(ranges)

    var source = '', variables = [ 'next' ], rangeIndex = 0, source = '', step = 0

    ranges.forEach(function (range, rangeIndex) {
        if (rangeIndex) {
            source = formatters.blank(source)
        }

        source = formatters.range(source, {
            sentry: range.fixed ? range.size : 'value',
            step: step
        })

        var offset = 0
        range.pattern.forEach(function (field, index) {
            step += 2
            if (field.endianness == 'x') {
                source = formatters.skip(source, { field: field })
            } else {
                var name = 'value'

                if (field.type == 'f') {
                    variables.push('value')
                    source = formatters.arrayBuffer(source, { field: field })
                    source = formatters.copy(source, { field: field })
                    source = formatters.toFloat(source, { field: field })
                } else {
                    var vars = {
                        variable: null,
                        field: field
                    }
                    if (field.packing || field.signed || field.lengthEncoding) {
                        variables.push('value')
                        vars.assignee = 'value'
                    } else {
                        vars.assignee = 'object.' + field.name
                    }
                    source = formatters.assignment(source, vars)
                    if (field.packing) {
                        source = formatters.unpack(source, { field: field })
                    } else if (field.signed) {
                        source = formatters.signage(source, { field: field })
                    }
                }
            }
        })
    })

    var vars = variables.map(function (variable) {
        return 'var ' + variable
    }).join('\n')

    source = $('                                                            \n\
        ', vars, '                                                          \n\
        // __blank__                                                        \n\
        ', source, '                                                        \n\
        // __blank__                                                        \n\
        if (next = callback(object)) {                                      \n\
            this.parse = next                                               \n\
            return this.parse(buffer, start, end)                           \n\
        }                                                                   \n\
        // __blank__                                                        \n\
        return start                                                        \n\
    ')
    source = $('                                                            \n\
            ', composeIncrementalParser(ranges), '                          \n\
            // __blank__                                                    \n\
            return function (buffer, start, end) {                          \n\
                ', source, '                                                \n\
        }')

    return source
}

module.exports = composeParser
<commit_msg>Generate BFF parser using operations.<commit_after>var $ = require('programmatic')
var signage = require('./signage')
var composeIncrementalParser = require('./inc')
var unpackAll = require('./unpack')

var formatters = {
    blank: function (source) {
        return $('                                                          \n\
            ', source, '                                                    \n\
            // __blank__                                                    \n\
        ')
    },
    range: function (source, vars) {
        return $('                                                          \n\
            ', source, '                                                    \n\
            if (end - start < ' + vars.sentry + ') {                        \n\
                return inc.call(this, buffer, start, end, ' + vars.step + ')\n\
            }                                                               \n\
            // __blank__                                                    \n\
        ')
    },
    arrayBuffer: function (source, vars) {
        return $('                                                          \n\
            ', source, '                                                    \n\
            value = new ArrayBuffer(' + vars.field.bytes + ')               \n\
        ')
    },
    copy: function (source, vars) {
        var field = vars.field
        var little = field.endianness == 'l'
        var bytes = field.bytes
        var bite = little ? 0 : bytes - 1
        var direction = little ? 1 : -1
        var stop = little ? bytes : -1
        var index = little ? 0 : bytes - 1
        var copy = []
        while (bite != stop) {
            copy.push('value[' + index + '] = buffer[start++]')
            index += direction
            bite += direction
        }
        return $('                                                          \n\
            ', source, '                                                    \n\
            ', copy.join('\n'), '                                           \n\
        ')
    },
    toFloat: function (source, vars) {
        var bits = vars.field.bits, name = vars.field.name
        return $('                                                          \n\
            ', source, '                                                    \n\
            object.' + name +
                ' = new DataView(value).getFloat' + bits + '(0, true)       \n\
        ')
    },
    skip: function (source, vars) {
        var skip = vars.field.bytes * vars.field.repeat
        return $('                                                          \n\
            ', source, '                                                    \n\
            start += ' + skip + '                                           \n\
            // __blank__                                                    \n\
        ')
    },
    assignment: function (source, vars) {
        var field = vars.field
        var little = field.endianness == 'l'
        var bytes = field.bytes
        var bite = little ? 0 : bytes - 1
        var direction = little ? 1 : -1
        var stop = little ? bytes : -1
        var read = []
        while (bite != stop) {
            read.unshift('buffer[start++]')
            if (bite) {
                read[0] += ' * 0x' + Math.pow(256, bite).toString(16)
            }
            bite += direction
        }
        read = read.reverse().join(' + \n')
        if (field.bytes == 1) {
            var assignment = vars.assignee + ' = ' + read
        } else {
            var assignment = $('\n\
                ' + vars.assignee + ' =                                     \n\
                    ', read, '')
        }
        return $('                                                          \n\
            ', source, '                                                    \n\
            ', assignment, '                                                \n\
        ')
    },
    signage: function (source, vars) {
        return $('                                                          \n\
            ', source, '                                                    \n\
            ', signage(vars.field, 'object.' + vars.field.name), '          \n\
        ')
    },
    unpack: function (source, vars) {
        return $('                                                          \n\
            ', source, '                                                    \n\
            ', unpackAll(vars.field), '                                     \n\
        ')
    }
}

function composeParser (ranges) {
    composeIncrementalParser(ranges)

    var source = '', variables = [ 'next' ], step = 0

    var operations = []

    ranges.forEach(function (range, rangeIndex) {
        if (rangeIndex) {
            operations.push({ formatter: 'blank' })
        }

        operations.push({
            formatter: 'range',
            sentry: range.fixed ? range.size : 'value',
            step: step
        })

        var offset = 0
        range.pattern.forEach(function (field, index) {
            step += 2
            if (field.endianness == 'x') {
                operations.push({ formatter: 'skip', field: field })
            } else {
                var name = 'value'

                if (field.type == 'f') {
                    variables.push('value')
                    operations.push({ formatter: 'arrayBuffer', field: field })
                    operations.push({ formatter: 'copy', field: field })
                    operations.push({ formatter: 'toFloat', field: field })
                } else {
                    if (field.packing || field.signed || field.lengthEncoding) {
                        variables.push('value')
                        var assignee = 'value'
                    } else {
                        var assignee = 'object.' + field.name
                    }
                    operations.push({
                        formatter: 'assignment',
                        field: field,
                        assignee: assignee
                    })
                    if (field.packing) {
                        operations.push({ formatter: 'unpack', field: field })
                    } else if (field.signed) {
                        operations.push({ formatter: 'signage', field: field })
                    }
                }
            }
        })
    })

    var source = ''
    operations.forEach(function (operation) {
        source = formatters[operation.formatter](source, operation)
    })

    var vars = variables.map(function (variable) {
        return 'var ' + variable
    }).join('\n')

    source = $('                                                            \n\
        ', vars, '                                                          \n\
        // __blank__                                                        \n\
        ', source, '                                                        \n\
        // __blank__                                                        \n\
        if (next = callback(object)) {                                      \n\
            this.parse = next                                               \n\
            return this.parse(buffer, start, end)                           \n\
        }                                                                   \n\
        // __blank__                                                        \n\
        return start                                                        \n\
    ')
    source = $('                                                            \n\
            ', composeIncrementalParser(ranges), '                          \n\
            // __blank__                                                    \n\
            return function (buffer, start, end) {                          \n\
                ', source, '                                                \n\
        }')

    return source
}

module.exports = composeParser
<|endoftext|>


<commit_before>/*
 * Copyright 2009 The Closure Compiler Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Definitions for ECMAScript 5.
 * @see http://www.ecma-international.org/publications/files/drafts/tc39-2009-025.pdf
 * @externs
 */

/**
 * @param {Object|undefined} selfObj Specifies the object to which |this| should
 *     point when the function is run. If the value is null or undefined, it
 *     will default to the global object.
 * @param {...*} var_args Additional arguments that are partially
 *     applied to fn.
 * @return {!Function} A partially-applied form of the Function on which
 *     bind() was invoked as a method.
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
 */
Function.prototype.bind = function(selfObj, var_args) {};

/**
 * @this {String|string}
 * @return {string}
 * @nosideeffects
 * @see http://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/Trim
 */
String.prototype.trim = function() {};

/**
 * @this {String|string}
 * @return {string}
 * @nosideeffects
 * @see http://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/TrimLeft
 */
String.prototype.trimLeft = function() {};

/**
 * @this {String|string}
 * @return {string}
 * @nosideeffects
 * @see http://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/TrimRight
 */
String.prototype.trimRight = function() {};

/**
 * A object property descriptor used by Object.create, Object.defineProperty,
 * Object.defineProperties, Object.getOwnPropertyDescriptor.
 *
 * Note: not a real constructor.
 * @constructor
 */
function ObjectPropertyDescriptor() {}

/** @type {*} */
ObjectPropertyDescriptor.prototype.value;

/** @type {(function():?)|undefined} */
ObjectPropertyDescriptor.prototype.get;

/** @type {(function(?):void)|undefined} */
ObjectPropertyDescriptor.prototype.set;

/** @type {boolean|undefined} */
ObjectPropertyDescriptor.prototype.writable;

/** @type {boolean|undefined} */
ObjectPropertyDescriptor.prototype.enumerable;

/** @type {boolean|undefined} */
ObjectPropertyDescriptor.prototype.configurable;

/**
 * @param {Object} proto
 * @param {Object=} opt_properties  A map of ObjectPropertyDescriptors.
 * @return {!Object}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/create
 */
Object.create = function(proto, opt_properties) {};

/**
 * @param {!Object} obj
 * @param {string} prop
 * @param {!Object} descriptor A ObjectPropertyDescriptor.
 * @return {!Object}
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty
 */
Object.defineProperty = function(obj, prop, descriptor) {};

/**
 * @param {!Object} obj
 * @param {!Object} props A map of ObjectPropertyDescriptors.
 * @return {!Object}
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperties
 */
Object.defineProperties = function(obj, props) {};

/**
 * @param {!Object} obj
 * @param {string} prop
 * @return {!ObjectPropertyDescriptor|undefined}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor
 */
Object.getOwnPropertyDescriptor = function(obj, prop) {};

/**
 * @param {!Object} obj
 * @return {!Array<string>}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys
 */
Object.keys = function(obj) {};

/**
 * @param {!Object} obj
 * @return {!Array<string>}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames
 */
Object.getOwnPropertyNames = function(obj) {};

/**
 * @param {!Object} obj
 * @return {Object}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/GetPrototypeOf
 */
Object.getPrototypeOf = function(obj) {};

/**
 * @param {T} obj
 * @return {T}
 * @template T
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/preventExtensions
 */
Object.preventExtensions = function(obj) {};

/**
 * @param {T} obj
 * @return {T}
 * @template T
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/seal
 */
Object.seal = function(obj) {};

/**
 * @param {T} obj
 * @return {T}
 * @template T
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/freeze
 */
Object.freeze = function(obj) {};

/**
 * @param {!Object} obj
 * @return {boolean}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/isExtensible
 */
Object.isExtensible = function(obj) {};

/**
 * @param {!Object} obj
 * @return {boolean}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/isSealed
 */
Object.isSealed = function(obj) {};

/**
 * @param {!Object} obj
 * @return {boolean}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/isFrozen
 */
Object.isFrozen = function(obj) {};

/**
 * As per ECMAScript 5, 15.12.3.
 * @param {string=} opt_key The JSON key for this object.
 * @return {*} The serializable representation of this object. Note that this
 *     need not be a string. See http://goo.gl/PEUvs.
 */
Object.prototype.toJSON = function(opt_key) {};

/**
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/toISOString
 * @return {string}
 */
Date.prototype.toISOString = function() {};

/**
 * @param {*=} opt_ignoredKey
 * @return {string}
 * @override
 */
Date.prototype.toJSON = function(opt_ignoredKey) {};

/**
 * A fake type to model the JSON object.
 * @constructor
 */
function JSONType() {}

/**
 * @param {string} jsonStr The string to parse.
 * @param {(function(string, *) : *)=} opt_reviver
 * @return {*} The JSON object.
 * @throws {Error}
 * @nosideeffects
 */
JSONType.prototype.parse = function(jsonStr, opt_reviver) {};

/**
 * @param {*} jsonObj Input object.
 * @param {(Array<string>|(function(string, *) : *)|null)=} opt_replacer
 * @param {(number|string)=} opt_space
 * @return {string} JSON string which represents jsonObj.
 * @throws {Error}
 * @nosideeffects
 */
JSONType.prototype.stringify = function(jsonObj, opt_replacer, opt_space) {};

/**
 * @type {!JSONType}
 * @suppress {duplicate}
 */
var JSON;
<commit_msg>Remove nosideeffects tag from JSON.parse and JSON.stringify<commit_after>/*
 * Copyright 2009 The Closure Compiler Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Definitions for ECMAScript 5.
 * @see http://www.ecma-international.org/publications/files/drafts/tc39-2009-025.pdf
 * @externs
 */

/**
 * @param {Object|undefined} selfObj Specifies the object to which |this| should
 *     point when the function is run. If the value is null or undefined, it
 *     will default to the global object.
 * @param {...*} var_args Additional arguments that are partially
 *     applied to fn.
 * @return {!Function} A partially-applied form of the Function on which
 *     bind() was invoked as a method.
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
 */
Function.prototype.bind = function(selfObj, var_args) {};

/**
 * @this {String|string}
 * @return {string}
 * @nosideeffects
 * @see http://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/Trim
 */
String.prototype.trim = function() {};

/**
 * @this {String|string}
 * @return {string}
 * @nosideeffects
 * @see http://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/TrimLeft
 */
String.prototype.trimLeft = function() {};

/**
 * @this {String|string}
 * @return {string}
 * @nosideeffects
 * @see http://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/TrimRight
 */
String.prototype.trimRight = function() {};

/**
 * A object property descriptor used by Object.create, Object.defineProperty,
 * Object.defineProperties, Object.getOwnPropertyDescriptor.
 *
 * Note: not a real constructor.
 * @constructor
 */
function ObjectPropertyDescriptor() {}

/** @type {*} */
ObjectPropertyDescriptor.prototype.value;

/** @type {(function():?)|undefined} */
ObjectPropertyDescriptor.prototype.get;

/** @type {(function(?):void)|undefined} */
ObjectPropertyDescriptor.prototype.set;

/** @type {boolean|undefined} */
ObjectPropertyDescriptor.prototype.writable;

/** @type {boolean|undefined} */
ObjectPropertyDescriptor.prototype.enumerable;

/** @type {boolean|undefined} */
ObjectPropertyDescriptor.prototype.configurable;

/**
 * @param {Object} proto
 * @param {Object=} opt_properties  A map of ObjectPropertyDescriptors.
 * @return {!Object}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/create
 */
Object.create = function(proto, opt_properties) {};

/**
 * @param {!Object} obj
 * @param {string} prop
 * @param {!Object} descriptor A ObjectPropertyDescriptor.
 * @return {!Object}
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty
 */
Object.defineProperty = function(obj, prop, descriptor) {};

/**
 * @param {!Object} obj
 * @param {!Object} props A map of ObjectPropertyDescriptors.
 * @return {!Object}
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperties
 */
Object.defineProperties = function(obj, props) {};

/**
 * @param {!Object} obj
 * @param {string} prop
 * @return {!ObjectPropertyDescriptor|undefined}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor
 */
Object.getOwnPropertyDescriptor = function(obj, prop) {};

/**
 * @param {!Object} obj
 * @return {!Array<string>}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys
 */
Object.keys = function(obj) {};

/**
 * @param {!Object} obj
 * @return {!Array<string>}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames
 */
Object.getOwnPropertyNames = function(obj) {};

/**
 * @param {!Object} obj
 * @return {Object}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/GetPrototypeOf
 */
Object.getPrototypeOf = function(obj) {};

/**
 * @param {T} obj
 * @return {T}
 * @template T
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/preventExtensions
 */
Object.preventExtensions = function(obj) {};

/**
 * @param {T} obj
 * @return {T}
 * @template T
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/seal
 */
Object.seal = function(obj) {};

/**
 * @param {T} obj
 * @return {T}
 * @template T
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/freeze
 */
Object.freeze = function(obj) {};

/**
 * @param {!Object} obj
 * @return {boolean}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/isExtensible
 */
Object.isExtensible = function(obj) {};

/**
 * @param {!Object} obj
 * @return {boolean}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/isSealed
 */
Object.isSealed = function(obj) {};

/**
 * @param {!Object} obj
 * @return {boolean}
 * @nosideeffects
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/isFrozen
 */
Object.isFrozen = function(obj) {};

/**
 * As per ECMAScript 5, 15.12.3.
 * @param {string=} opt_key The JSON key for this object.
 * @return {*} The serializable representation of this object. Note that this
 *     need not be a string. See http://goo.gl/PEUvs.
 */
Object.prototype.toJSON = function(opt_key) {};

/**
 * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/toISOString
 * @return {string}
 */
Date.prototype.toISOString = function() {};

/**
 * @param {*=} opt_ignoredKey
 * @return {string}
 * @override
 */
Date.prototype.toJSON = function(opt_ignoredKey) {};

/**
 * A fake type to model the JSON object.
 * @constructor
 */
function JSONType() {}

/**
 * @param {string} jsonStr The string to parse.
 * @param {(function(string, *) : *)=} opt_reviver
 * @return {*} The JSON object.
 * @throws {Error}
 */
JSONType.prototype.parse = function(jsonStr, opt_reviver) {};

/**
 * @param {*} jsonObj Input object.
 * @param {(Array<string>|(function(string, *) : *)|null)=} opt_replacer
 * @param {(number|string)=} opt_space
 * @return {string} JSON string which represents jsonObj.
 * @throws {Error}
 */
JSONType.prototype.stringify = function(jsonObj, opt_replacer, opt_space) {};

/**
 * @type {!JSONType}
 * @suppress {duplicate}
 */
var JSON;
<|endoftext|>


<commit_before>/* eslint-disable global-require */
/* eslint-disable import/no-dynamic-require */
export const languages = require('../translations/languages.json');

export const translations = languages
  .reduce((acc, lang) => ({
    ...acc,
    [lang.code]: require(`../translations/${lang.code}.json`),
  }), {});

const languageSelector = document.getElementById('language-selector');

let currentLanguage = 'en';
const setterHooks = [];

export function getTranslation(translationKey, ...args) {
  const template = translations[currentLanguage][translationKey];

  if (!args.length) return template;

  return args.reduce(
    (str, arg, index) => str.replace(new RegExp(`\\{${index}\\}`, 'g'), arg),
    template,
  );
}

/* eslint-disable no-param-reassign */
export function createTextSetter(element, translationKey, property = 'innerText') {
  if (setterHooks.some(hook => hook.element === element)) {
    throw new Error('This element already has a text setter');
  }

  const hook = {
    element, translationKey, property, args: [],
  };

  setterHooks.push(hook);

  return function setText(...args) {
    hook.args = args;
    element[property] = getTranslation(translationKey, ...args);
  };
}

export function setLanguage(language) {
  document.documentElement.classList.remove(`lang-${currentLanguage}`);
  document.documentElement.classList.add(`lang-${language}`);

  currentLanguage = language;
  languageSelector.value = language;
  chrome.storage.local.set({ language });

  setterHooks.forEach(({
    element, translationKey, property, args,
  }) => {
    element[property] = getTranslation(translationKey, ...args);
  });

  [...document.querySelectorAll('[data-t]')].forEach((element) => {
    const translationKey = element.getAttribute('data-t');
    element.innerText = translations[language][translationKey];
  });
}
<commit_msg>Fallback to English for missing translations<commit_after>/* eslint-disable global-require */
/* eslint-disable import/no-dynamic-require */
export const languages = require('../translations/languages.json');

const FALLBACK_LANGUAGE = 'en';

export const translations = languages
  .reduce((acc, lang) => ({
    ...acc,
    [lang.code]: require(`../translations/${lang.code}.json`),
  }), {});

const languageSelector = document.getElementById('language-selector');

let currentLanguage = 'en';
const setterHooks = [];

export function getTranslation(translationKey, ...args) {
  const template = translations[currentLanguage][translationKey]
    || translations[FALLBACK_LANGUAGE][translationKey];

  if (!args.length) return template;

  return args.reduce(
    (str, arg, index) => str.replace(new RegExp(`\\{${index}\\}`, 'g'), arg),
    template,
  );
}

/* eslint-disable no-param-reassign */
export function createTextSetter(element, translationKey, property = 'innerText') {
  if (setterHooks.some(hook => hook.element === element)) {
    throw new Error('This element already has a text setter');
  }

  const hook = {
    element, translationKey, property, args: [],
  };

  setterHooks.push(hook);

  return function setText(...args) {
    hook.args = args;
    element[property] = getTranslation(translationKey, ...args);
  };
}

export function setLanguage(language) {
  document.documentElement.classList.remove(`lang-${currentLanguage}`);
  document.documentElement.classList.add(`lang-${language}`);

  currentLanguage = language;
  languageSelector.value = language;
  chrome.storage.local.set({ language });

  setterHooks.forEach(({
    element, translationKey, property, args,
  }) => {
    element[property] = getTranslation(translationKey, ...args);
  });

  [...document.querySelectorAll('[data-t]')].forEach((element) => {
    const translationKey = element.getAttribute('data-t');
    element.innerText = getTranslation(translationKey);
  });
}
<|endoftext|>


<commit_before>var util = require('../util');

function square(name) {
  return name.charCodeAt(0) - 97 + (name.charCodeAt(1) - 49) * 8;
}

function squareDist(a, b) {
  var x1 = a & 7, x2 = b & 7;
  var y1 = a >> 3, y2 = b >> 3;
  return Math.max(Math.abs(x1 - x2), Math.abs(y1 - y2));
}

function isBlack(p) {
  return p === p.toLowerCase();
}

function readFen(fen) {
  var parts = fen.split(' ');
  var board = {
    pieces: {},
    turn: parts[1] === 'w',
    fmvn: parseInt(parts[5], 10) || 1
  };

  parts[0].split('/').forEach(function(row, y) {
    var x = 0;
    row.split('').forEach(function(v) {
      if (v == '~') return;
      var nb = parseInt(v, 10);
      if (nb) x += nb;
      else {
        var square = (7 - y) * 8 + x;
        board.pieces[square] = v;
        if (v === 'k' || v === 'K') board[v] = square;
        x++;
      }
    });
  });

  return board;
}

function kingMovesTo(s) {
  return [s - 1, s - 9, s - 8, s - 7, s + 1, s + 9, s + 8, s + 7].filter(function (o) {
    return o >= 0 && o < 64 && squareDist(s, o) === 1;
  });
}

function knightMovesTo(s) {
  return [s + 17, s + 15, s + 10, s + 6, s - 6, s - 10, s - 15, s - 17].filter(function (o) {
    return o >= 0 && o < 64 && squareDist(s, o) <= 2;
  });
}

var ROOK_DELTAS = [8, 1, -8, -1];
var BISHOP_DELTAS = [9, -9, 7, -7];
var QUEEN_DELTAS = ROOK_DELTAS.concat(BISHOP_DELTAS);

function slidingMovesTo(s, deltas, board) {
  var result = [];
  deltas.forEach(function (delta) {
    for (var square = s + delta;
         square >= 0 && square < 64 && squareDist(square, square - delta) === 1;
         square += delta) {
      result.push(square);
      if (board.pieces[square]) break;
    }
  });
  return result;
}

function isCheck(variant, board) {
  if (variant === 'antichess' || variant == 'racingKings') return false;

  var ksq = board.turn ? board.K : board.k;
  if (typeof ksq !== 'number') return false;

  // no check when kings are touching in atomic
  if (variant === 'atomic' && squareDist(board.k, board.K) <= 1) return false;

  var n = board.turn ? 'n' : 'N';
  var r = board.turn ? 'r' : 'R';
  var b = board.turn ? 'b' : 'B';
  var q = board.turn ? 'q' : 'Q';

  return (knightMovesTo(ksq).some(function(o) {
      return board.pieces[o] === n;
  }) || slidingMovesTo(ksq, ROOK_DELTAS, board).some(function (o) {
      return board.pieces[o] === r || board.pieces[o] === q;
  }) || slidingMovesTo(ksq, BISHOP_DELTAS, board).some(function (o) {
      return board.pieces[o] === b || board.pieces[o] === q;
  }));
}

function makeMove(variant, board, uci) {
  if (!board.turn) board.fmvn++;
  board.turn = !board.turn;

  if (uci.indexOf('@') !== -1) {
    board.pieces[square(uci.slice(2, 4))] = board.turn ? uci[0].toLowerCase() : uci[0];
    return;
  }

  var move = util.decomposeUci(uci);
  var from = square(move[0]);
  var to = square(move[1]);
  var p = board.pieces[from];
  var capture = board.pieces[to];

  if (p === 'p' || p === 'P') {
    if (uci[0] !== uci[2] && !capture) {
      // en passant
      delete board.pieces[to + (board.turn ? 8 : -8)];
      capture = true;
    }
  }

  if (p === 'k' || p === 'K') {
    // castling
    var frCastle = capture && isBlack(p) === isBlack(capture);
    if (frCastle || squareDist(from, to) > 1) {
      delete board.pieces[from];
      if (frCastle) delete board.pieces[to];
      if (to < from) {
        if (!frCastle) delete board.pieces[board.turn ? square('a8') : square('a1')];
        to = board.turn ? square('c8') : square('c1');
        board.pieces[to + 1] = board.turn ? 'r' : 'R';
      }
      else {
        if (!frCastle) delete board.pieces[board.turn ? square('h8') : square('h1')];
        to = board.turn ? square('g8') : square('g1');
        board.pieces[to - 1] = board.turn ? 'r' : 'R';
      }
      board.pieces[to] = p;
      board[p] = to;
      return;
    }
    board[p] = to;
  }

  if (move[2]) board.pieces[to] = board.turn ? move[2] : move[2].toUpperCase();
  else board.pieces[to] = p;
  delete board.pieces[from];

  // atomic explosion
  if (variant === 'atomic' && capture) {
    delete board.pieces[to];
    kingMovesTo(to).forEach(function (o) {
      if (board.pieces[o] !== 'p' && board.pieces[o] !== 'P') delete board.pieces[o];
    });
  }
}

function san(board, uci) {
  if (uci.indexOf('@') !== -1) return util.fixCrazySan(uci);

  var move = util.decomposeUci(uci);
  var from = square(move[0]);
  var to = square(move[1]);
  var p = board.pieces[from];
  var d = board.pieces[to];
  var pt = board.pieces[from].toLowerCase();

  // pawn moves
  if (pt === 'p') {
    var san;
    if (uci[0] === uci[2]) san = move[1];
    else san = uci[0] + 'x' + move[1];
    if (move[2]) san += '=' + move[2].toUpperCase();
    return san;
  }

  // castling
  if (pt == 'k' && ((d && isBlack(p) === isBlack(d)) || squareDist(from, to) > 1)) {
    if (to < from) return 'O-O-O';
    else return 'O-O';
  }

  var san = pt.toUpperCase();

  // disambiguate normal moves
  var candidates = [];
  if (pt == 'k') candidates = kingMovesTo(to);
  else if (pt == 'n') candidates = knightMovesTo(to);
  else if (pt == 'r') candidates = slidingMovesTo(to, ROOK_DELTAS, board);
  else if (pt == 'b') candidates = slidingMovesTo(to, BISHOP_DELTAS, board);
  else if (pt == 'q') candidates = slidingMovesTo(to, QUEEN_DELTAS, board);

  var rank = false, file = false;
  for (var i = 0; i < candidates.length; i++) {
    if (candidates[i] === from || board.pieces[candidates[i]] !== p) continue;
    if ((from & 7) === (candidates[i] & 7)) rank = true;
    if ((from >> 3) === (candidates[i] >> 3)) file = true;
  }
  if (file) san += uci[0];
  if (rank) san += uci[1];

  // target
  if (d) san += 'x';
  san += move[1];
  return san;
}

module.exports = function(variant, fen, threat, pv, mate) {
  var board = readFen(fen);
  if (threat) board.turn = !board.turn;
  var turn = board.turn;
  var moves = pv.split(' ').slice(0, 10);

  var first = true;
  var line = moves.map(function(uci) {
    var s = '';
    if (board.turn) s = board.fmvn + '. ';
    else if (first) s = board.fmvn + '... ';
    first = false;
    s += san(board, uci);
    makeMove(variant, board, uci);
    if (isCheck(variant, board)) s += '+';
    return s;
  }).join(' ');

  if (mate) {
    var matePlies = mate * 2;
    if (mate > 0 === turn) matePlies--;
    if (moves.length >= matePlies) line = line.replace(/\+?$/, '#');
  }

  return line;
}
<commit_msg>pv2san: forgot pawn checks<commit_after>var util = require('../util');

function square(name) {
  return name.charCodeAt(0) - 97 + (name.charCodeAt(1) - 49) * 8;
}

function squareDist(a, b) {
  var x1 = a & 7, x2 = b & 7;
  var y1 = a >> 3, y2 = b >> 3;
  return Math.max(Math.abs(x1 - x2), Math.abs(y1 - y2));
}

function isBlack(p) {
  return p === p.toLowerCase();
}

function readFen(fen) {
  var parts = fen.split(' ');
  var board = {
    pieces: {},
    turn: parts[1] === 'w',
    fmvn: parseInt(parts[5], 10) || 1
  };

  parts[0].split('/').forEach(function(row, y) {
    var x = 0;
    row.split('').forEach(function(v) {
      if (v == '~') return;
      var nb = parseInt(v, 10);
      if (nb) x += nb;
      else {
        var square = (7 - y) * 8 + x;
        board.pieces[square] = v;
        if (v === 'k' || v === 'K') board[v] = square;
        x++;
      }
    });
  });

  return board;
}

function kingMovesTo(s) {
  return [s - 1, s - 9, s - 8, s - 7, s + 1, s + 9, s + 8, s + 7].filter(function (o) {
    return o >= 0 && o < 64 && squareDist(s, o) === 1;
  });
}

function knightMovesTo(s) {
  return [s + 17, s + 15, s + 10, s + 6, s - 6, s - 10, s - 15, s - 17].filter(function (o) {
    return o >= 0 && o < 64 && squareDist(s, o) <= 2;
  });
}

function pawnAttacksTo(turn, s) {
  var left = turn ? 7 : -7;
  var right = turn ? 9 : -9;
  return [s + left, s + right].filter(function (o) {
    return o >= 0 && o < 64 && squareDist(s, o) === 1;
  });
}

var ROOK_DELTAS = [8, 1, -8, -1];
var BISHOP_DELTAS = [9, -9, 7, -7];
var QUEEN_DELTAS = ROOK_DELTAS.concat(BISHOP_DELTAS);

function slidingMovesTo(s, deltas, board) {
  var result = [];
  deltas.forEach(function (delta) {
    for (var square = s + delta;
         square >= 0 && square < 64 && squareDist(square, square - delta) === 1;
         square += delta) {
      result.push(square);
      if (board.pieces[square]) break;
    }
  });
  return result;
}

function isCheck(variant, board) {
  if (variant === 'antichess' || variant == 'racingKings') return false;

  var ksq = board.turn ? board.K : board.k;
  if (typeof ksq !== 'number') return false;

  // no check when kings are touching in atomic
  if (variant === 'atomic' && squareDist(board.k, board.K) <= 1) return false;

  var p = board.turn ? 'p' : 'P';
  var n = board.turn ? 'n' : 'N';
  var r = board.turn ? 'r' : 'R';
  var b = board.turn ? 'b' : 'B';
  var q = board.turn ? 'q' : 'Q';

  return (pawnAttacksTo(board.turn, ksq).some(function(o) {
    return board.pieces[o] === p;
  }) || knightMovesTo(ksq).some(function(o) {
    return board.pieces[o] === n;
  }) || slidingMovesTo(ksq, ROOK_DELTAS, board).some(function (o) {
    return board.pieces[o] === r || board.pieces[o] === q;
  }) || slidingMovesTo(ksq, BISHOP_DELTAS, board).some(function (o) {
    return board.pieces[o] === b || board.pieces[o] === q;
  }));
}

function makeMove(variant, board, uci) {
  if (!board.turn) board.fmvn++;
  board.turn = !board.turn;

  if (uci.indexOf('@') !== -1) {
    board.pieces[square(uci.slice(2, 4))] = board.turn ? uci[0].toLowerCase() : uci[0];
    return;
  }

  var move = util.decomposeUci(uci);
  var from = square(move[0]);
  var to = square(move[1]);
  var p = board.pieces[from];
  var capture = board.pieces[to];

  if (p === 'p' || p === 'P') {
    if (uci[0] !== uci[2] && !capture) {
      // en passant
      delete board.pieces[to + (board.turn ? 8 : -8)];
      capture = true;
    }
  }

  if (p === 'k' || p === 'K') {
    // castling
    var frCastle = capture && isBlack(p) === isBlack(capture);
    if (frCastle || squareDist(from, to) > 1) {
      delete board.pieces[from];
      if (frCastle) delete board.pieces[to];
      if (to < from) {
        if (!frCastle) delete board.pieces[board.turn ? square('a8') : square('a1')];
        to = board.turn ? square('c8') : square('c1');
        board.pieces[to + 1] = board.turn ? 'r' : 'R';
      }
      else {
        if (!frCastle) delete board.pieces[board.turn ? square('h8') : square('h1')];
        to = board.turn ? square('g8') : square('g1');
        board.pieces[to - 1] = board.turn ? 'r' : 'R';
      }
      board.pieces[to] = p;
      board[p] = to;
      return;
    }
    board[p] = to;
  }

  if (move[2]) board.pieces[to] = board.turn ? move[2] : move[2].toUpperCase();
  else board.pieces[to] = p;
  delete board.pieces[from];

  // atomic explosion
  if (variant === 'atomic' && capture) {
    delete board.pieces[to];
    kingMovesTo(to).forEach(function (o) {
      if (board.pieces[o] !== 'p' && board.pieces[o] !== 'P') delete board.pieces[o];
    });
  }
}

function san(board, uci) {
  if (uci.indexOf('@') !== -1) return util.fixCrazySan(uci);

  var move = util.decomposeUci(uci);
  var from = square(move[0]);
  var to = square(move[1]);
  var p = board.pieces[from];
  var d = board.pieces[to];
  var pt = board.pieces[from].toLowerCase();

  // pawn moves
  if (pt === 'p') {
    var san;
    if (uci[0] === uci[2]) san = move[1];
    else san = uci[0] + 'x' + move[1];
    if (move[2]) san += '=' + move[2].toUpperCase();
    return san;
  }

  // castling
  if (pt == 'k' && ((d && isBlack(p) === isBlack(d)) || squareDist(from, to) > 1)) {
    if (to < from) return 'O-O-O';
    else return 'O-O';
  }

  var san = pt.toUpperCase();

  // disambiguate normal moves
  var candidates = [];
  if (pt == 'k') candidates = kingMovesTo(to);
  else if (pt == 'n') candidates = knightMovesTo(to);
  else if (pt == 'r') candidates = slidingMovesTo(to, ROOK_DELTAS, board);
  else if (pt == 'b') candidates = slidingMovesTo(to, BISHOP_DELTAS, board);
  else if (pt == 'q') candidates = slidingMovesTo(to, QUEEN_DELTAS, board);

  var rank = false, file = false;
  for (var i = 0; i < candidates.length; i++) {
    if (candidates[i] === from || board.pieces[candidates[i]] !== p) continue;
    if ((from & 7) === (candidates[i] & 7)) rank = true;
    if ((from >> 3) === (candidates[i] >> 3)) file = true;
  }
  if (file) san += uci[0];
  if (rank) san += uci[1];

  // target
  if (d) san += 'x';
  san += move[1];
  return san;
}

module.exports = function(variant, fen, threat, pv, mate) {
  var board = readFen(fen);
  if (threat) board.turn = !board.turn;
  var turn = board.turn;
  var moves = pv.split(' ').slice(0, 10);

  var first = true;
  var line = moves.map(function(uci) {
    var s = '';
    if (board.turn) s = board.fmvn + '. ';
    else if (first) s = board.fmvn + '... ';
    first = false;
    s += san(board, uci);
    makeMove(variant, board, uci);
    if (isCheck(variant, board)) s += '+';
    return s;
  }).join(' ');

  if (mate) {
    var matePlies = mate * 2;
    if (mate > 0 === turn) matePlies--;
    if (moves.length >= matePlies) line = line.replace(/\+?$/, '#');
  }

  return line;
}
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var object = require('object-component');
var request = require('superagent');
var log = require('debug')('notifier-client');

/**
 * Expose `NotifierClient` constructor.
 */

module.exports = NotifierClient;

var defaults = {
  host: 'localhost',
  path: '/api/events',
  port: 80,
  protocol: 'http',
  token: null
}

/**
 * Creates a Client instance. Takes an object with options.
 *
 * @param {Object} options for configuring the client instance.
 *     - host {String} defaults to `localhost`.
 *     - port {String} defaults to '80'.
 *     - protocol {String} defautls to `http`.
 *     - path {String} api path - defaults to `/api`.
 *     - token {String} api token - defaults to `null`.
 * @return {NotifierClient} `NotifierClient` instance
 * @api public
 */

function NotifierClient (options) {
  if (!(this instanceof NotifierClient)) {
    return new NotifierClient(options);
  }

  this.options = object.merge({}, defaults);
  this.options = object.merge(this.options, options || {});
}

NotifierClient.prototype.notify = function(event) {
  if(typeof event === 'object') {
    this.event = event;
    this.send();

  } else {
    this.event.event = event;
  }

  return this;
};

NotifierClient.prototype.to = function(recipient) {
  this.event.user = recipient;
  return this;
};

NotifierClient.prototype.withData = function(data) {
  this.event.data = data;
  return this;
};

NotifierClient.prototype.send = function() {
  request
  .post(this.buildUrl())
  .set('Accept', 'application/json')
  .send(this.event)
  .end(function (err, res) {
    if (err) {
      log('Unexpected error when sending event %j', this.event);
      return;
    }

    if (res.body.error) {
      log('Error for event %j: %s', this.event, res.body.error);
      return;
    }

    // Great success!

  });
};

NotifierClient.prototype.buildUrl = function() {
  return this.options.protocol + this.options.host + ':' + this.options.port + this.options.path;
};
<commit_msg>introduce optional callback for send method<commit_after>/**
 * Module dependencies.
 */

var object = require('object-component');
var request = require('superagent');
var log = require('debug')('notifier-client');

/**
 * Expose `NotifierClient` constructor.
 */

module.exports = NotifierClient;

var defaults = {
  host: 'localhost',
  path: '/api/events',
  port: 80,
  protocol: 'http',
  token: null
};

/**
 * Creates a Client instance. Takes an object with options.
 *
 * @param {Object} options for configuring the client instance.
 *     - host {String} defaults to `localhost`.
 *     - port {String} defaults to '80'.
 *     - protocol {String} defautls to `http`.
 *     - path {String} api path - defaults to `/api`.
 *     - token {String} api token - defaults to `null`.
 * @return {NotifierClient} `NotifierClient` instance
 * @api public
 */

function NotifierClient (options) {
  if (!(this instanceof NotifierClient)) {
    return new NotifierClient(options);
  }

  this.options = object.merge({}, defaults);
  this.options = object.merge(this.options, options || {});
}

NotifierClient.prototype.notify = function(event) {
  if(typeof event === 'object') {
    this.event = event;
    this.send();

  } else {
    this.event.event = event;
  }

  return this;
};

NotifierClient.prototype.to = function(recipient) {
  this.event.user = recipient;
  return this;
};

NotifierClient.prototype.withData = function(data) {
  this.event.data = data;
  return this;
};

NotifierClient.prototype.send = function(callback) {
  callback = callback || function () {};

  request
  .post(this.buildUrl())
  .set('Accept', 'application/json')
  .send(this.event)
  .end(function (err, res) {
    if (err) {
      log('Unexpected error when sending event %j', this.event);
      return callback(err);
    }

    if (res.body.error || res.statusCode > 201) {
      log('Error for event %j: %s', this.event, res.body.error);
      return callback(res.body);
    }

    callback(null, res.body);
  });
};

NotifierClient.prototype.buildUrl = function() {
  return this.options.protocol + this.options.host + ':' + this.options.port + this.options.path;
};
<|endoftext|>


<commit_before>module.exports = {

  /**
   * Import plugin style guide rules
   * @see https://github.com/benmosher/eslint-plugin-import#rules
   */
  rules: {

    /**
     * Ensure all imports appear before other statements
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/first.md
     */
    'import/first': [ 'error', 'absolute-first' ],

    /**
     * Report repeated import of the same module in multiple places
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md
     */
    'import/no-duplicates': 'error',

    /**
     * Report namespace imports
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-namespace.md
     */
    'import/no-namespace': 'error',

    /**
     * Ensure consistent use of file extension within the import path
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md
     */
    'import/extensions': [ 'error', 'always', {
      json: 'never',
      jsx: 'never',
      js: 'never'
    }],

    /**
     * Enforce a convention in module import order
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md
     */
    'import/order': [ 'error', {
      'newlines-between': 'never',
      'groups': [
        'builtin',  // 'fs', 'path' etc.
        'external', // 'lodash', 'react' etc.
        'internal', // 'source/components/header'
        'parent',   // '../../components/footer'
        'sibling',  // './enums', './styles' etc.
        'index'     // './'
      ]
    }],

    /**
     * Enforce a newline after import statements
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/newline-after-import.md
     */
    'import/newline-after-import': 'error',

    /**
     * Prefer a default export if module exports a single name
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md
     */
    'import/prefer-default-export': 'off',

    /**
     * Limit the maximum number of dependencies a module can have
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/max-dependencies.md
     */
    'import/max-dependencies': [ 'error', {
      max: 20
    }],

    /**
     * Forbid unassigned imports
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unassigned-import.md
     */
    'import/no-unassigned-import': 'error'
  }
}
<commit_msg>Updated import rules<commit_after>module.exports = {

  /**
   * Import plugin style guide rules
   * @see https://github.com/benmosher/eslint-plugin-import#rules
   */
  rules: {

    /**
     * Ensure all imports appear before other statements
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/first.md
     */
    'import/first': [ 'error', 'absolute-first' ],

    /**
     * Forbid anonymous values as default exports
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-anonymous-default-export.md
     */
    'import/no-anonymous-default-export': 'off',

    /**
     * Report repeated import of the same module in multiple places
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md
     */
    'import/no-duplicates': 'error',

    /**
     * Report namespace imports
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-namespace.md
     */
    'import/no-namespace': 'error',

    /**
     * Ensure consistent use of file extension within the import path
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md
     */
    'import/extensions': [ 'error', 'always', {
      json: 'never',
      jsx: 'never',
      js: 'never'
    }],

    /**
     * Enforce a convention in module import order
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md
     */
    'import/order': [ 'error', {
      'newlines-between': 'never',
      'groups': [
        'builtin',  // 'fs', 'path' etc.
        'external', // 'lodash', 'react' etc.
        'internal', // 'source/components/header'
        'parent',   // '../../components/footer'
        'sibling',  // './enums', './styles' etc.
        'index'     // './'
      ]
    }],

    /**
     * Enforce a newline after import statements
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/newline-after-import.md
     */
    'import/newline-after-import': 'error',

    /**
     * Prefer a default export if module exports a single name
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md
     */
    'import/prefer-default-export': 'off',

    /**
     * Limit the maximum number of dependencies a module can have
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/max-dependencies.md
     */
    'import/max-dependencies': [ 'error', {
      max: 20
    }],

    /**
     * Forbid unassigned imports
     * @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unassigned-import.md
     */
    'import/no-unassigned-import': 'error'
  }
}
<|endoftext|>


<commit_before>// Copyright (C) 2013 - Texas Instruments, Jason Kridner
//
// This is meant to hold some private functions
// Modified by Aditya Patadia, Octal Consulting LLP
var fs = require('fs');
var winston = require('winston');
var child_process = require('child_process');
var bone = require('./bone');
var g = require('./constants');

var debug = process.env.DEBUG ? true : false;
var sysfsFiles = {};

function myRequire(packageName, onfail) {
    var y = {};
    try {
        y = require(packageName);
        y.exists = true;
    } catch(ex) {
        y.exists = false;
        if(debug) winston.debug("Optional package '" + packageName + "' not loaded");
        if(onfail) onfail();
    }
    return(y);
}

var fibers = myRequire("fibers");

module.exports = {

    require : myRequire,

    is_capemgr : function(callback) {
        return(module.exports.find_sysfsFile('capemgr', '/sys/devices', 'bone_capemgr.', callback));
    },

    is_ocp : function(callback) {
        return(module.exports.find_sysfsFile('ocp', '/sys/devices', 'ocp.', callback));
    },

    find_sysfsFile : function(name, path, prefix, callback) {
        if(typeof sysfsFiles[name] == 'undefined') {
            if(callback) {
                sysfsFiles[name] = module.exports.file_find(path, prefix, 1, onFindCapeMgr);
            } else {
                sysfsFiles[name] = module.exports.file_find(path, prefix, 1);
            }
        } else {
            if(callback) callback({path: sysfsFiles[name]});
        }

        function onFindCapeMgr(resp) {
            if(typeof resp.path == 'undefined') sysfsFiles[name] = false;
            else sysfsFiles[name] = resp.path;
            callback(resp);
        }

        return(sysfsFiles[name]);
    },

    file_exists : fs.exists,

    file_existsSync : fs.existsSync,

    file_find : function(path, prefix, attempts, callback) {
        var resp = {};
        resp.attempts = 0;
        if(typeof attempts == 'undefined') attempts = 1;

        if(callback) {
            fs.readdir(path, onReadDir);
        } else {
            while(resp.attempts < attempts) {
                try {
                    var files = fs.readdirSync(path);
                    onReadDir(null, files);
                } catch(ex) {
                    if(debug) winston.debug('Error reading ' + path);
                    return(resp.path);

                }
                if(resp.path) return(resp.path);
            }
            return(resp.path);
        }

        function onReadDir(err, files) {
            resp.attempts++;
            if(err) {
                resp.err = 'Error listing directory ' + path + ': ' + err;
                if(callback) callback(resp);
                return;
            }
            for(var j in files) {
                if(files[j].indexOf(prefix) === 0) {
                    resp.path = path + '/' + files[j];
                    if(callback) callback(resp);
                    return;
                }
            }
            if(callback) {
                if(resp.attempts >= attempts) {
                    resp.err = 'Did not find ' + prefix + ' in ' + path;
                    callback(resp);
                } else {
                    fs.readdir(path, onReadDir);
                }
            }
        }

        return(resp.path);
    },

    // Note, this just makes sure there was an attempt to load the
    // devicetree fragment, not if it was successful
    load_dt : function(name, pin, resp, callback) {
        if(debug) winston.debug('load_dt(' + [name, pin.key, JSON.stringify(resp)] + ')');
        var slotsFile;
        var lastSlots;
        var writeAttempts = 0;
        var readAttempts = 0;
        if(pin) {
            var slotRegex = new RegExp('\\d+(?=\\s*:.*,bs.*' + pin.key + ')', 'gm');
        }
        module.exports.is_capemgr(onFindCapeMgr);

        function onFindCapeMgr(x) {
            if(debug) winston.debug('onFindCapeMgr: path = ' + x.path);
            if(typeof x.path == 'undefined') {
                resp.err = "CapeMgr not found: " + x.err;
                winston.error(resp.err);
                callback(resp);
                return;
            }
            slotsFile = x.path + '/slots';
            fs.readFile(slotsFile, 'ascii', onReadSlots);
        }

        function onReadSlots(err, slots) {
            readAttempts++;
            if(err) {
                resp.err = 'Unable to read from CapeMgr slots: ' + err;
                winston.error(resp.err);
                callback(resp);
                return;
            }
            lastSlots = slots;
            var index = slots.indexOf(name);
            if(debug) winston.debug('onReadSlots: index = ' + index + ', readAttempts = ' + readAttempts);
            if(index >= 0) {
                // Fragment is already loaded
                callback(resp);
            } else if (readAttempts <= 1) {
                // Attempt to load fragment
                fs.writeFile(slotsFile, name, 'ascii', onWriteSlots);
            } else {
                resp.err = 'Error waiting for CapeMgr slot to load';
                callback(resp);
            }
        }

        function onWriteSlots(err) {
            writeAttempts++;
            if(err) {
                resp.err = 'Write to CapeMgr slots failed: ' + err;
                if(pin && writeAttempts <= 1) unloadSlot();
                else callback(resp);
                return;
            }
            fs.readFile(slotsFile, 'ascii', onReadSlots);
        }

        function unloadSlot() {
            var slot = lastSlots.match(slotRegex);
            if(slot && slot[0]) {
                if(debug) winston.debug('Attempting to unload conflicting slot ' +
                    slot[0] + ' for ' + name);
                fs.writeFile(slotsFile, '-'+slot[0], 'ascii', onUnloadSlot);
            } else {
                callback(resp);
            }
        }

        function onUnloadSlot(err) {
            if(err) {
                resp.err = "Unable to unload conflicting slot: " + err;
                callback(resp);
                return;
            }
            fs.writeFile(slotsFile, name, 'ascii', onWriteSlots);
        }
    },

    create_dt : function(pin, data, template, load, force_create, resp, callback) {
        if(debug){
            winston.debug('create_dt(' + [pin.key, data, template, load, force_create, JSON.stringify(resp)] + ')');
        }
        template = template || 'bspm';
        load = (typeof load === 'undefined') ? true : load;
        var fragment = template + '_' + pin.key + '_' + data.toString(16);
        var dtsFilename = '/lib/firmware/' + fragment + '-00A0.dts';
        var dtboFilename = '/lib/firmware/' + fragment + '-00A0.dtbo';

        if(force_create) {
            createDTS();
        } else {
            module.exports.file_exists(dtboFilename, onDTBOExistsTest);
        }

        function onDTBOExistsTest(exists) {
            if(exists) {
                onDTBOExists();
            } else {
                createDTS();
            }
        }

        function createDTS() {
            var templateFilename = require.resolve('octalbonescript').replace('index.js',
                'dts/' + template + '_template.dts');
            if(debug) winston.debug('Creating template: ' + templateFilename);
            var dts = fs.readFileSync(templateFilename, 'utf8');
            dts = dts.replace(/!PIN_KEY!/g, pin.key);
            dts = dts.replace(/!PIN_DOT_KEY!/g, pin.key.replace(/_/, '.'));
            dts = dts.replace(/!PIN_FUNCTION!/g, pin.options[data&7]);
            dts = dts.replace(/!PIN_OFFSET!/g, pin.muxRegOffset);
            dts = dts.replace(/!DATA!/g, '0x' + data.toString(16));
            if(pin.pwm) {
                dts = dts.replace(/!PWM_MODULE!/g, pin.pwm.module);
                dts = dts.replace(/!PWM_INDEX!/g, pin.pwm.index);
                dts = dts.replace(/!DUTY_CYCLE!/g, 500000);
            }
            fs.writeFile(dtsFilename, dts, 'ascii', onDTSWrite);
        }

        function onDTSWrite(err) {
            if(err) {
                resp.err = 'Error writing ' + dtsFilename + ': ' + err;
                if(debug) winston.debug(resp.err);
                callback(resp);
                return;
            }
            var command = 'dtc -O dtb -o ' + dtboFilename + ' -b 0 -@ ' + dtsFilename;
            child_process.exec(command, dtcHandler);
        }

        function dtcHandler(error, stdout, stderr) {
            if(debug) winston.debug('dtcHandler: ' +
                JSON.stringify({error:error, stdout:stdout, stderr:stderr}));
            if(!error) onDTBOExists();
        }

        function onDTBOExists() {
            if(debug) winston.debug('onDTBOExists()');
            if(load) module.exports.load_dt(fragment, pin, resp, callback);
            else callback(resp);
        }
    },

    getpin : function(pin) {
        if(typeof pin == 'object') return(pin);
        else if(typeof pin == 'string') return(bone.pins[pin]);
        else if(typeof pin == 'number') return(bone.pinIndex[pin]);
        else throw("Invalid pin: " + pin);
    },

    wrapCall : function(m, func, funcArgs, cbArgs) {
        if(!m.module.exists) {
            if(debug) winston.debug(m.name + ' support module not loaded.');
            return(function(){});
        }
        funcArgs.unshift('port');
        funcArgs.push('callback');
        var newFunction = function() {
            var args = [];
            var port = arguments[0];
            var callback = false;
            for(var i = 1; i < arguments.length; i++) {
                winston.debug('Adding argument ' + funcArgs[i] + ' to wrapper');
                if(funcArgs[i] == 'callback') {
                    callback = arguments[i];
                    var wrappedCallback = function() {
                        var cbData = {};
                        for(var j = 0; j < cbArgs.length; j++) {
                            cbData[cbArgs[j]] = arguments[j];
                        }
                        cbData.event = 'callback';
                        winston.debug('cbData = ' + JSON.stringify(cbData));
                        callback(cbData);
                    };
                    args.push(wrappedCallback);
                } else {
                    args.push(arguments[i]);
                }
            }
            if(!m.openPorts[port]) {
                if(callback) callback({'err': m.name + ' ' + port + ' not opened'});
                return(false);
            }
            winston.debug('Calling ' + m.name + '[' + port + '].' + func + '(' + args + ')');
            var x = m.openPorts[port][func].apply(
                    m.openPorts[port], args);
            if(callback) callback({'event': 'return', 'return': x});
            return(x);
        };
        newFunction.args = funcArgs;
        return(newFunction);
    },

    wrapOpen : function(m, openArgs) {
        if(!m.module.exists) {
            if(debug) winston.debug(m.name + ' support module not loaded.');
            return(function(){});
        }
        openArgs.unshift('port');
        openArgs.push('callback');
        var newFunction = function() {
            var args = {};
            for(var i = 0; i < openArgs.length; i++) {
                args[openArgs[i]] = arguments[i];
            }
            var port = args.port;
            var callback = args.callback;
            winston.debug(m.name + ' opened with ' + JSON.stringify(arguments));
            if(m.ports[port] && m.ports[port].devicetree) {
                var fragment = m.ports[port].devicetree;
                if(!module.exports.is_capemgr()) {
                    if(callback) callback({err:'Kernel does not include CapeMgr module'});
                    return(false);
                }
                if(!module.exports.load_dt(fragment)) {
                    if(callback) callback({'err': 'Devicetree overlay fragment ' +
                        fragment + ' not loaded'});
                    return(false);
                }
            }
            m.openPorts[port] = m.doOpen(args);
            if(!m.openPorts[port]) {
                if(callback) callback({'err': 'Unable to ' + m.name});
                return(false);
            }
            for(var e in m.events) {
                var addHandler = function(m, port, e) {
                    var handler = function() {
                        var myargs = arguments;
                        myargs.event = e;
                        for(var i = 0; i < arguments.length; i++) {
                            myargs[m.events[e][i]] = arguments[i];
                        }
                        callback(myargs);
                    };
                    m.openPorts[port].on(e, handler);
                };
                addHandler(m, port, e);
            }
            if(callback) callback({'event':'return', 'value':true});
            return(true);
        };
        newFunction.args = openArgs;
        return(newFunction);
    },

    pin_data : function(slew, direction, pullup, mux) {
        var pinData = 0;
        if(slew == 'slow') pinData |= 0x40;
        if(direction != g.OUTPUT) pinData |= 0x20;
        switch(pullup) {
        case 'disabled':
            pinData |= 0x08;
            break;
        case 'pullup':
            pinData |= 0x10;
            break;
        default:
            break;
        }
        pinData |= (mux & 0x07);
        return(pinData);
    },

    // Inspired by
    //   https://github.com/luciotato/waitfor/blob/master/waitfor.js
    //   https://github.com/0ctave/node-sync/blob/master/lib/sync.js
    wait_for : function(fn, myargs, result_name, no_error) {
        var fiber = fibers.current;
        var yielded = false;
        var args = [];
        var result;

        for(var i in fn.args) {
            if(fn.args[i] == 'callback') {
                args.push(myCallback);
            } else {
                args.push(myargs[i]);
            }
        }

        if(typeof fiber == 'undefined') {
            if(no_error) {
                // No callback required (fire and forget)
                fn.apply(this, args);
            } else {
                var stack = new Error().stack;
                var err = 'As of BoneScript 0.2.5, synchronous calls must be made\n' +
                    'within a fiber such as within loop() or setup():\n' + stack;
                winston.error(err);
                throw(err);
            }
        } else {
            fn.apply(this, args);
            if(!myCallback.called) {
                yielded = true;
                fibers.yield();
            }
        }

        function myCallback(x) {
            if(debug) winston.debug('Callback: ' + fn.name + ' ' + x.err);
            if(myCallback.called) return;
            if(typeof result_name == 'undefined') {
                result = x;
            } else if(typeof x[result_name] != 'undefined') {
                result = x[result_name];
            }
            if(typeof x.err != 'undefined' && x.err) {
                //var fn_name = fn.toString().substr('function '.length);
                //fn_name = fn_name.substr(0, fn_name.indexOf('('));
                if(debug) winston.debug(fn.name + ' ' + x.err);
            }
            myCallback.called = true;
            if(typeof fiber == 'undefined' && no_error) return;
            if(yielded) fiber.run();
        }

        return(result);
    }
};

<commit_msg>bug fix<commit_after>// Copyright (C) 2013 - Texas Instruments, Jason Kridner
//
// This is meant to hold some private functions
// Modified by Aditya Patadia, Octal Consulting LLP
var fs = require('fs');
var winston = require('winston');
var child_process = require('child_process');
var bone = require('./bone');
var g = require('./constants');

var debug = process.env.DEBUG ? true : false;
var sysfsFiles = {};

function myRequire(packageName, onfail) {
    var y = {};
    try {
        y = require(packageName);
        y.exists = true;
    } catch(ex) {
        y.exists = false;
        if(debug) winston.debug("Optional package '" + packageName + "' not loaded");
        if(onfail) onfail();
    }
    return(y);
}

var fibers = myRequire("fibers");

module.exports = {

    require : myRequire,

    is_capemgr : function(callback) {
        return(module.exports.find_sysfsFile('capemgr', '/sys/devices', 'bone_capemgr.', callback));
    },

    is_ocp : function(callback) {
        return(module.exports.find_sysfsFile('ocp', '/sys/devices', 'ocp.', callback));
    },

    find_sysfsFile : function(name, path, prefix, callback) {
        if(typeof sysfsFiles[name] == 'undefined') {
            if(callback) {
                sysfsFiles[name] = module.exports.file_find(path, prefix, 1, onFindCapeMgr);
            } else {
                sysfsFiles[name] = module.exports.file_find(path, prefix, 1);
            }
        } else {
            if(callback) callback({path: sysfsFiles[name]});
        }

        function onFindCapeMgr(resp) {
            if(typeof resp.path == 'undefined') sysfsFiles[name] = false;
            else sysfsFiles[name] = resp.path;
            callback(resp);
        }

        return(sysfsFiles[name]);
    },

    file_exists : fs.exists,

    file_existsSync : fs.existsSync,

    file_find : function(path, prefix, attempts, callback) {
        var resp = {};
        resp.attempts = 0;
        if(typeof attempts == 'undefined') attempts = 1;

        if(callback) {
            fs.readdir(path, onReadDir);
        } else {
            while(resp.attempts < attempts) {
                try {
                    var files = fs.readdirSync(path);
                    onReadDir(null, files);
                } catch(ex) {
                    if(debug) winston.debug('Error reading ' + path);
                    return(resp.path);

                }
                if(resp.path) return(resp.path);
            }
            return(resp.path);
        }

        function onReadDir(err, files) {
            resp.attempts++;
            if(err) {
                resp.err = 'Error listing directory ' + path + ': ' + err;
                if(callback) callback(resp);
                return;
            }
            for(var j in files) {
                if(files[j].indexOf(prefix) === 0) {
                    resp.path = path + '/' + files[j];
                    if(callback) callback(resp);
                    return;
                }
            }
            if(callback) {
                if(resp.attempts >= attempts) {
                    resp.err = 'Did not find ' + prefix + ' in ' + path;
                    callback(resp);
                } else {
                    fs.readdir(path, onReadDir);
                }
            }
        }

        return(resp.path);
    },

    // Note, this just makes sure there was an attempt to load the
    // devicetree fragment, not if it was successful
    load_dt : function(name, pin, resp, callback) {
        if(debug) winston.debug('load_dt(' + [name, JSON.stringify(resp)] + ')');
        var slotsFile;
        var lastSlots;
        var writeAttempts = 0;
        var readAttempts = 0;
        if(pin) {
            var slotRegex = new RegExp('\\d+(?=\\s*:.*,bs.*' + pin.key + ')', 'gm');
        }
        module.exports.is_capemgr(onFindCapeMgr);

        function onFindCapeMgr(x) {
            if(debug) winston.debug('onFindCapeMgr: path = ' + x.path);
            if(typeof x.path == 'undefined') {
                resp.err = "CapeMgr not found: " + x.err;
                winston.error(resp.err);
                callback(resp);
                return;
            }
            slotsFile = x.path + '/slots';
            fs.readFile(slotsFile, 'ascii', onReadSlots);
        }

        function onReadSlots(err, slots) {
            readAttempts++;
            if(err) {
                resp.err = 'Unable to read from CapeMgr slots: ' + err;
                winston.error(resp.err);
                callback(resp);
                return;
            }
            lastSlots = slots;
            var index = slots.indexOf(name);
            if(debug) winston.debug('onReadSlots: index = ' + index + ', readAttempts = ' + readAttempts);
            if(index >= 0) {
                // Fragment is already loaded
                callback(resp);
            } else if (readAttempts <= 1) {
                // Attempt to load fragment
                fs.writeFile(slotsFile, name, 'ascii', onWriteSlots);
            } else {
                resp.err = 'Error waiting for CapeMgr slot to load';
                callback(resp);
            }
        }

        function onWriteSlots(err) {
            writeAttempts++;
            if(err) {
                resp.err = 'Write to CapeMgr slots failed: ' + err;
                if(pin && writeAttempts <= 1) unloadSlot();
                else callback(resp);
                return;
            }
            fs.readFile(slotsFile, 'ascii', onReadSlots);
        }

        function unloadSlot() {
            var slot = lastSlots.match(slotRegex);
            if(slot && slot[0]) {
                if(debug) winston.debug('Attempting to unload conflicting slot ' +
                    slot[0] + ' for ' + name);
                fs.writeFile(slotsFile, '-'+slot[0], 'ascii', onUnloadSlot);
            } else {
                callback(resp);
            }
        }

        function onUnloadSlot(err) {
            if(err) {
                resp.err = "Unable to unload conflicting slot: " + err;
                callback(resp);
                return;
            }
            fs.writeFile(slotsFile, name, 'ascii', onWriteSlots);
        }
    },

    create_dt : function(pin, data, template, load, force_create, resp, callback) {
        if(debug){
            winston.debug('create_dt(' + [pin.key, data, template, load, force_create, JSON.stringify(resp)] + ')');
        }
        template = template || 'bspm';
        load = (typeof load === 'undefined') ? true : load;
        var fragment = template + '_' + pin.key + '_' + data.toString(16);
        var dtsFilename = '/lib/firmware/' + fragment + '-00A0.dts';
        var dtboFilename = '/lib/firmware/' + fragment + '-00A0.dtbo';

        if(force_create) {
            createDTS();
        } else {
            module.exports.file_exists(dtboFilename, onDTBOExistsTest);
        }

        function onDTBOExistsTest(exists) {
            if(exists) {
                onDTBOExists();
            } else {
                createDTS();
            }
        }

        function createDTS() {
            var templateFilename = require.resolve('octalbonescript').replace('index.js',
                'dts/' + template + '_template.dts');
            if(debug) winston.debug('Creating template: ' + templateFilename);
            var dts = fs.readFileSync(templateFilename, 'utf8');
            dts = dts.replace(/!PIN_KEY!/g, pin.key);
            dts = dts.replace(/!PIN_DOT_KEY!/g, pin.key.replace(/_/, '.'));
            dts = dts.replace(/!PIN_FUNCTION!/g, pin.options[data&7]);
            dts = dts.replace(/!PIN_OFFSET!/g, pin.muxRegOffset);
            dts = dts.replace(/!DATA!/g, '0x' + data.toString(16));
            if(pin.pwm) {
                dts = dts.replace(/!PWM_MODULE!/g, pin.pwm.module);
                dts = dts.replace(/!PWM_INDEX!/g, pin.pwm.index);
                dts = dts.replace(/!DUTY_CYCLE!/g, 500000);
            }
            fs.writeFile(dtsFilename, dts, 'ascii', onDTSWrite);
        }

        function onDTSWrite(err) {
            if(err) {
                resp.err = 'Error writing ' + dtsFilename + ': ' + err;
                if(debug) winston.debug(resp.err);
                callback(resp);
                return;
            }
            var command = 'dtc -O dtb -o ' + dtboFilename + ' -b 0 -@ ' + dtsFilename;
            child_process.exec(command, dtcHandler);
        }

        function dtcHandler(error, stdout, stderr) {
            if(debug) winston.debug('dtcHandler: ' +
                JSON.stringify({error:error, stdout:stdout, stderr:stderr}));
            if(!error) onDTBOExists();
        }

        function onDTBOExists() {
            if(debug) winston.debug('onDTBOExists()');
            if(load) module.exports.load_dt(fragment, pin, resp, callback);
            else callback(resp);
        }
    },

    getpin : function(pin) {
        if(typeof pin == 'object') return(pin);
        else if(typeof pin == 'string') return(bone.pins[pin]);
        else if(typeof pin == 'number') return(bone.pinIndex[pin]);
        else throw("Invalid pin: " + pin);
    },

    wrapCall : function(m, func, funcArgs, cbArgs) {
        if(!m.module.exists) {
            if(debug) winston.debug(m.name + ' support module not loaded.');
            return(function(){});
        }
        funcArgs.unshift('port');
        funcArgs.push('callback');
        var newFunction = function() {
            var args = [];
            var port = arguments[0];
            var callback = false;
            for(var i = 1; i < arguments.length; i++) {
                winston.debug('Adding argument ' + funcArgs[i] + ' to wrapper');
                if(funcArgs[i] == 'callback') {
                    callback = arguments[i];
                    var wrappedCallback = function() {
                        var cbData = {};
                        for(var j = 0; j < cbArgs.length; j++) {
                            cbData[cbArgs[j]] = arguments[j];
                        }
                        cbData.event = 'callback';
                        winston.debug('cbData = ' + JSON.stringify(cbData));
                        callback(cbData);
                    };
                    args.push(wrappedCallback);
                } else {
                    args.push(arguments[i]);
                }
            }
            if(!m.openPorts[port]) {
                if(callback) callback({'err': m.name + ' ' + port + ' not opened'});
                return(false);
            }
            winston.debug('Calling ' + m.name + '[' + port + '].' + func + '(' + args + ')');
            var x = m.openPorts[port][func].apply(
                    m.openPorts[port], args);
            if(callback) callback({'event': 'return', 'return': x});
            return(x);
        };
        newFunction.args = funcArgs;
        return(newFunction);
    },

    wrapOpen : function(m, openArgs) {
        if(!m.module.exists) {
            if(debug) winston.debug(m.name + ' support module not loaded.');
            return(function(){});
        }
        openArgs.unshift('port');
        openArgs.push('callback');
        var newFunction = function() {
            var args = {};
            for(var i = 0; i < openArgs.length; i++) {
                args[openArgs[i]] = arguments[i];
            }
            var port = args.port;
            var callback = args.callback;
            winston.debug(m.name + ' opened with ' + JSON.stringify(arguments));
            if(m.ports[port] && m.ports[port].devicetree) {
                var fragment = m.ports[port].devicetree;
                if(!module.exports.is_capemgr()) {
                    if(callback) callback({err:'Kernel does not include CapeMgr module'});
                    return(false);
                }
                if(!module.exports.load_dt(fragment)) {
                    if(callback) callback({'err': 'Devicetree overlay fragment ' +
                        fragment + ' not loaded'});
                    return(false);
                }
            }
            m.openPorts[port] = m.doOpen(args);
            if(!m.openPorts[port]) {
                if(callback) callback({'err': 'Unable to ' + m.name});
                return(false);
            }
            for(var e in m.events) {
                var addHandler = function(m, port, e) {
                    var handler = function() {
                        var myargs = arguments;
                        myargs.event = e;
                        for(var i = 0; i < arguments.length; i++) {
                            myargs[m.events[e][i]] = arguments[i];
                        }
                        callback(myargs);
                    };
                    m.openPorts[port].on(e, handler);
                };
                addHandler(m, port, e);
            }
            if(callback) callback({'event':'return', 'value':true});
            return(true);
        };
        newFunction.args = openArgs;
        return(newFunction);
    },

    pin_data : function(slew, direction, pullup, mux) {
        var pinData = 0;
        if(slew == 'slow') pinData |= 0x40;
        if(direction != g.OUTPUT) pinData |= 0x20;
        switch(pullup) {
        case 'disabled':
            pinData |= 0x08;
            break;
        case 'pullup':
            pinData |= 0x10;
            break;
        default:
            break;
        }
        pinData |= (mux & 0x07);
        return(pinData);
    },

    // Inspired by
    //   https://github.com/luciotato/waitfor/blob/master/waitfor.js
    //   https://github.com/0ctave/node-sync/blob/master/lib/sync.js
    wait_for : function(fn, myargs, result_name, no_error) {
        var fiber = fibers.current;
        var yielded = false;
        var args = [];
        var result;

        for(var i in fn.args) {
            if(fn.args[i] == 'callback') {
                args.push(myCallback);
            } else {
                args.push(myargs[i]);
            }
        }

        if(typeof fiber == 'undefined') {
            if(no_error) {
                // No callback required (fire and forget)
                fn.apply(this, args);
            } else {
                var stack = new Error().stack;
                var err = 'As of BoneScript 0.2.5, synchronous calls must be made\n' +
                    'within a fiber such as within loop() or setup():\n' + stack;
                winston.error(err);
                throw(err);
            }
        } else {
            fn.apply(this, args);
            if(!myCallback.called) {
                yielded = true;
                fibers.yield();
            }
        }

        function myCallback(x) {
            if(debug) winston.debug('Callback: ' + fn.name + ' ' + x.err);
            if(myCallback.called) return;
            if(typeof result_name == 'undefined') {
                result = x;
            } else if(typeof x[result_name] != 'undefined') {
                result = x[result_name];
            }
            if(typeof x.err != 'undefined' && x.err) {
                //var fn_name = fn.toString().substr('function '.length);
                //fn_name = fn_name.substr(0, fn_name.indexOf('('));
                if(debug) winston.debug(fn.name + ' ' + x.err);
            }
            myCallback.called = true;
            if(typeof fiber == 'undefined' && no_error) return;
            if(yielded) fiber.run();
        }

        return(result);
    }
};

<|endoftext|>


<commit_before>var XDemo = undefined;
(function() {

  var updatePreview = function(preview, source) {
    preview.document.open();
    preview.document.write(source);
    preview.document.close();
  };

  var localDoc = document.currentScript.ownerDocument;
  var proto = Object.create(HTMLElement.prototype);

  Object.defineProperty(proto, "src", { get: function() { return src; }, set: function(newSrc) { src = newSrc; this.load(); } });

  proto.createdCallback = function() {
    this._root = this.createShadowRoot();
    var tplContent = localDoc.querySelector("template").content;
    this._root.appendChild(tplContent.cloneNode(true));

    var self    = this,
    previewElem = self._root.getElementById("preview");

    self.source = self._root.getElementById("source");
    self.preview = (previewElem.contentWindow) ? previewElem.contentWindow :
                     (previewElem.contentDocument.document) ? previewElem.contentDocument.document : previewElem.contentDocument;

    self.source.addEventListener("keyup", function(e) { e.stopPropagation(); return false });

    this.load = function() {
      if(!self.src) throw new Error("Can't load without a source");

      var xhr = new XMLHttpRequest();
      xhr.onload = function() {
        self.source.value = this.responseText;
        updatePreview(self.preview, self.source.value);
      }
      xhr.open("get", self.src);
      xhr.send();
    }
  };

  proto.attachedCallback = function() {
    var self = this;

    self.source.addEventListener("blur", function() {
      updatePreview(self.preview, this.value);
    });

    this.src = this.attributes.getNamedItem("src").value;
  };

  XDemo = document.registerElement("x-demo", { prototype: proto });
}());
<commit_msg>Support for webkitCreateShadowRoot<commit_after>var XDemo = undefined;
(function() {

  var updatePreview = function(preview, source) {
    preview.document.open();
    preview.document.write(source);
    preview.document.close();
  };

  var localDoc = document.currentScript.ownerDocument;
  var proto = Object.create(HTMLElement.prototype);

  Object.defineProperty(proto, "src", { get: function() { return src; }, set: function(newSrc) { src = newSrc; this.load(); } });

  proto.createdCallback = function() {
    if(this.createShadowRoot) {
      this._root = this.createShadowRoot();
    } else {
      this._root = this.webkitCreateShadowRoot();
    }

    var tplContent = localDoc.querySelector("template").content;
    this._root.appendChild(tplContent.cloneNode(true));

    var self    = this,
    previewElem = self._root.getElementById("preview");

    self.source = self._root.getElementById("source");
    self.preview = (previewElem.contentWindow) ? previewElem.contentWindow :
                     (previewElem.contentDocument.document) ? previewElem.contentDocument.document : previewElem.contentDocument;

    self.source.addEventListener("keyup", function(e) { e.stopPropagation(); return false });

    this.load = function() {
      if(!self.src) throw new Error("Can't load without a source");

      var xhr = new XMLHttpRequest();
      xhr.onload = function() {
        self.source.value = this.responseText;
        updatePreview(self.preview, self.source.value);
      }
      xhr.open("get", self.src);
      xhr.send();
    }
  };

  proto.attachedCallback = function() {
    var self = this;

    self.source.addEventListener("blur", function() {
      updatePreview(self.preview, this.value);
    });

    this.src = this.attributes.getNamedItem("src").value;
  };

  XDemo = document.registerElement("x-demo", { prototype: proto });
}());
<|endoftext|>