<commit_before>Object.assign(pc, function () {
    /**
     * @constructor
     * @name pc.Entity
     * @classdesc The Entity is the core primitive of a PlayCanvas game. Generally speaking an object in your game will consist of an {@link pc.Entity},
     * and a set of {@link pc.Component}s which are managed by their respective {@link pc.ComponentSystem}s. One of those components maybe a
     * {@link pc.ScriptComponent} which allows you to write custom code to attach to your Entity.
     *

     * The Entity uniquely identifies the object and also provides a transform for position and orientation
     * which it inherits from {@link pc.GraphNode} so can be added into the scene graph.
     * The Component and ComponentSystem provide the logic to give an Entity a specific type of behavior. e.g. the ability to
     * render a model or play a sound. Components are specific to an instance of an Entity and are attached (e.g. `this.entity.model`)
     * ComponentSystems allow access to all Entities and Components and are attached to the {@link pc.Application}.
     * @param {String} [name] The non-unique name of the entity, default is "Untitled".
     * @param {pc.Application} [app] The application the entity belongs to, default is the current application.
     * @example
     * var app = ... // Get the pc.Application
     *
     * var entity = new pc.Entity();
     *
     * // Add a Component to the Entity
     * entity.addComponent("camera", {
     *   fov: 45,
     *   nearClip: 1,
     *   farClip: 10000
     * });
     *
     * // Add the Entity into the scene graph
     * app.root.addChild(entity);
     *
     * // Move the entity
     * entity.translate(10, 0, 0);
     *
     * // Or translate it by setting it's position directly
     * var p = entity.getPosition();
     * entity.setPosition(p.x + 10, p.y, p.z);
     *
     * // Change the entity's rotation in local space
     * var e = entity.getLocalEulerAngles();
     * entity.setLocalEulerAngles(e.x, e.y + 90, e.z);
     *
     * // Or use rotateLocal
     * entity.rotateLocal(0, 90, 0);
     *
     * @extends pc.GraphNode
     */
    var Entity = function (name, app){
        pc.GraphNode.call(this, name);

        if (name instanceof pc.Application) app = name;
        this._batchHandle = null; // The handle for a RequestBatch, set this if you want to Component's to load their resources using a pre-existing RequestBatch.
        this.c = {}; // Component storage

        this._app = app; // store app
        if (!app) {
            this._app = pc.Application.getApplication(); // get the current application
            if (!this._app) {
                throw new Error("Couldn't find current application");
            }
        }

        this.setGuid(pc.guid.create()); // Globally Unique Identifier

        // used by component systems to speed up destruction
        this._destroying = false;

        pc.events.attach(this);
    };
    Entity.prototype = Object.create(pc.GraphNode.prototype);
    Entity.prototype.constructor = Entity;

    /**
     * @function
     * @name pc.Entity#addComponent
     * @description Create a new component and add it to the entity.
     * Use this to add functionality to the entity like rendering a model, playing sounds and so on.
     * @param {String} type The name of the component to add. Valid strings are:
     *

     *
"animation" - see {@link pc.AnimationComponent}

     *
"audiolistener" - see {@link pc.AudioListenerComponent}

     *
"camera" - see {@link pc.CameraComponent}

     *
"collision" - see {@link pc.CollisionComponent}

     *
"element" - see {@link pc.ElementComponent}

     *
"light" - see {@link pc.LightComponent}

     *
"layoutchild" - see {@link pc.LayoutChildComponent}

     *
"layoutgroup" - see {@link pc.LayoutGroupComponent}

     *
"model" - see {@link pc.ModelComponent}

     *
"particlesystem" - see {@link pc.ParticleSystemComponent}

     *
"rigidbody" - see {@link pc.RigidBodyComponent}

     *
"screen" - see {@link pc.ScreenComponent}

     *
"script" - see {@link pc.ScriptComponent}

     *
"sound" - see {@link pc.SoundComponent}

     *
"zone" - see {@link pc.ZoneComponent}

     *

     * @param {Object} data The initialization data for the specific component type. Refer to each
     * specific component's API reference page for details on valid values for this parameter.
     * @returns {pc.Component} The new Component that was attached to the entity or null if there
     * was an error.
     * @example
     * var entity = new pc.Entity();
     * entity.addComponent("light"); // Add a light component with default properties
     * entity.addComponent("camera", { // Add a camera component with some specified properties
     *   fov: 45,
     *   clearColor: new pc.Color(1,0,0),
     * });
     */
    Entity.prototype.addComponent = function (type, data) {
        var system = this._app.systems[type];
        if (!system) {
            // #ifdef DEBUG
            console.error("addComponent: System " + type + " doesn't exist");
            // #endif
            return null;
        }
        if (this.c[type]) {
            // #ifdef DEBUG
            console.warn("addComponent: Entity already has " + type + " component");
            // #endif
            return null;
        }
        return system.addComponent(this, data);
    };

    /**
     * @function
     * @name pc.Entity#removeComponent
     * @description Remove a component from the Entity.
     * @param {String} type The name of the Component type
     * @example
     * var entity = new pc.Entity();
     * entity.addComponent("light"); // add new light component
     * //...
     * entity.removeComponent("light"); // remove light component
     */
    Entity.prototype.removeComponent = function (type) {
        var system = this._app.systems[type];
        if (!system) {
            // #ifdef DEBUG
            console.error("removeComponent: System " + type + " doesn't exist");
            // #endif
            return;
        }
        if (!this.c[type]) {
            // #ifdef DEBUG
            console.warn("removeComponent: Entity doesn't have " + type + " component");
            // #endif
            return;
        }
        system.removeComponent(this);
    };

    /**
     * @private
     * @function
     * @name pc.Entity#getGuid
     * @description Get the GUID value for this Entity
     * @returns {String} The GUID of the Entity
     */
    Entity.prototype.getGuid = function () {
        return this._guid;
    };

    /**
     * @private
     * @function
     * @name pc.Entity#setGuid
     * @description Set the GUID value for this Entity.
     *
     * N.B. It is unlikely that you should need to change the GUID value of an Entity at run-time. Doing so will corrupt the graph this Entity is in.
     * @param {String} guid The GUID to assign to the Entity
     */
    Entity.prototype.setGuid = function (guid) {
        // remove current guid from entityIndex
        var index = this._app._entityIndex;
        delete index[this._guid];
        // add new guid to entityIndex
        this._guid = guid;
        index[this._guid] = this;
    };

    Entity.prototype._notifyHierarchyStateChanged = function (node, enabled) {
        var enableFirst = false;
        if (node === this && this._app._enableList.length === 0)
            enableFirst = true;

        node._beingEnabled = true;

        node._onHierarchyStateChanged(enabled);

        if (node._onHierarchyStatePostChanged)
            this._app._enableList.push(node);

        var i, len;
        var c = node._children;
        for (i = 0, len = c.length; i < len; i++) {
            if (c[i]._enabled)
                this._notifyHierarchyStateChanged(c[i], enabled);
        }

        node._beingEnabled = false;

        if (enableFirst) {
            for (i = 0, len = this._app._enableList.length; i < len; i++)
                this._app._enableList[i]._onHierarchyStatePostChanged();

            this._app._enableList.length = 0;
        }
    };

    Entity.prototype._onHierarchyStateChanged = function (enabled) {
        pc.GraphNode.prototype._onHierarchyStateChanged.call(this, enabled);

        // enable / disable all the components
        var component;
        var components = this.c;
        for (var type in components) {
            if (components.hasOwnProperty(type)) {
                component = components[type];
                if (component.enabled) {
                    if (enabled) {
                        component.onEnable();
                    } else {
                        component.onDisable();
                    }
                }
            }
        }
    };

    Entity.prototype._onHierarchyStatePostChanged = function () {
        // post enable all the components
        var components = this.c;
        for (var type in components) {
            if (components.hasOwnProperty(type))
                components[type].onPostStateChange();
        }
    };

    /**
     * @private
     * @function
     * @name pc.Entity#setRequest
     * @description Used during resource loading to ensure that child resources of Entities are tracked
     * @param {ResourceRequest} request The request being used to load this entity
     */
    Entity.prototype.setRequest = function (request) {
        this._request = request;
    };

    /**
     * @private
     * @function
     * @name pc.Entity#getRequest
     * @description Get the Request that is being used to load this Entity
     * @returns {ResourceRequest} The Request
     */
    Entity.prototype.getRequest = function () {
        return this._request;
    };

    /**
     * @function
     * @name pc.Entity#findByGuid
     * @description Find a descendant of this Entity with the GUID
     * @param {String} guid The GUID to search for.
     * @returns {pc.Entity} The Entity with the GUID or null
     */
    Entity.prototype.findByGuid = function (guid) {
        if (this._guid === guid) return this;

        var e = this._app._entityIndex[guid];
        if (e && (e === this || e.isDescendantOf(this))) {
            return e;
        }

        return null;
    };

    /**
     * @function
     * @name pc.Entity#destroy
     * @description Remove all components from the Entity and detach it from the Entity hierarchy. Then recursively destroy all ancestor Entities
     * @example
     * var firstChild = this.entity.children[0];
     * firstChild.destroy(); // delete child, all components and remove from hierarchy
     */
    Entity.prototype.destroy = function () {
        var name;

        this._destroying = true;

        // Disable all enabled components first
        for (name in this.c) {
            this.c[name].enabled = false;
        }

        // Remove all components
        for (name in this.c) {
            this.c[name].system.removeComponent(this);
        }

        // Detach from parent
        if (this._parent)
            this._parent.removeChild(this);

        var children = this._children;
        var child = children.shift();
        while (child) {
            if (child instanceof pc.Entity) {
                child.destroy();
            }

            // make sure child._parent is null because
            // we have removed it from the children array before calling
            // destroy on it
            child._parent = null;

            child = children.shift();
        }

        // fire destroy event
        this.fire('destroy', this);

        // clear all events
        if (this._callbacks)
            this._callbacks = null;

        if (this._callbackActive)
            this._callbackActive = null;

        // remove from entity index
        delete this._app._entityIndex[this._guid];

        this._destroying = false;
    };

    /**
     * @function
     * @name pc.Entity#clone
     * @description Create a deep copy of the Entity. Duplicate the full Entity hierarchy, with all Components and all descendants.
     * Note, this Entity is not in the hierarchy and must be added manually.
     * @returns {pc.Entity} A new Entity which is a deep copy of the original.
     * @example
     *   var e = this.entity.clone(); // Clone Entity
     *   this.entity.parent.addChild(e); // Add it as a sibling to the original
     */
    Entity.prototype.clone = function () {
        var duplicatedIdsMap = {};
        var c = this._cloneRecursively(duplicatedIdsMap);
        duplicatedIdsMap[this.getGuid()] = c;

        resolveDuplicatedEntityReferenceProperties(this, this, c, duplicatedIdsMap);

        return c;
    };

    Entity.prototype._cloneRecursively = function (duplicatedIdsMap) {
        var type;
        var c = new pc.Entity(this._app);
        pc.GraphNode.prototype._cloneInternal.call(this, c);

        for (type in this.c) {
            var component = this.c[type];
            component.system.cloneComponent(this, c);
        }

        var i;
        for (i = 0; i < this._children.length; i++) {
            var oldChild = this._children[i];
            if (oldChild instanceof pc.Entity) {
                var newChild = oldChild._cloneRecursively(duplicatedIdsMap);
                c.addChild(newChild);
                duplicatedIdsMap[oldChild.getGuid()] = newChild;
            }
        }

        return c;
    };

    // When an entity that has properties that contain references to other
    // entities within its subtree is duplicated, the expectation of the
    // user is likely that those properties will be updated to point to
    // the corresponding entities within the newly-created duplicate subtree.
    //
    // To handle this, we need to search for properties that refer to entities
    // within the old duplicated structure, find their newly-cloned partners
    // within the new structure, and update the references accordingly. This
    // function implements that requirement.
    function resolveDuplicatedEntityReferenceProperties(oldSubtreeRoot, oldEntity, newEntity, duplicatedIdsMap) {
        var i, len;

        if (oldEntity instanceof pc.Entity) {
            var components = oldEntity.c;

            // Handle component properties
            for (var componentName in components) {
                var component = components[componentName];
                var entityProperties = component.system.getPropertiesOfType('entity');

                for (i = 0, len = entityProperties.length; i < len; i++) {
                    var propertyDescriptor = entityProperties[i];
                    var propertyName = propertyDescriptor.name;
                    var oldEntityReferenceId = component[propertyName];
                    var entityIsWithinOldSubtree = !!oldSubtreeRoot.findByGuid(oldEntityReferenceId);

                    if (entityIsWithinOldSubtree) {
                        var newEntityReferenceId = duplicatedIdsMap[oldEntityReferenceId].getGuid();

                        if (newEntityReferenceId) {
                            newEntity.c[componentName][propertyName] = newEntityReferenceId;
                        } else {
                            console.warn('Could not find corresponding entity id when resolving duplicated entity references');
                        }
                    }
                }
            }

            // Handle entity script attributes
            if (components.script && ! newEntity._app.useLegacyScriptAttributeCloning) {
                newEntity.script.resolveDuplicatedEntityReferenceProperties(components.script, duplicatedIdsMap);
            }

            // Recurse into children. Note that we continue to pass in the same `oldSubtreeRoot`,
            // in order to correctly handle cases where a child has an entity reference
            // field that points to a parent or other ancestor that is still within the
            // duplicated subtree.
            var _old = oldEntity.children.filter(function (e) {
                return (e instanceof pc.Entity);
            });
            var _new = newEntity.children.filter(function (e) {
                return (e instanceof pc.Entity);
            });

            for (i = 0, len = _old.length; i < len; i++) {
                resolveDuplicatedEntityReferenceProperties(oldSubtreeRoot, _old[i], _new[i], duplicatedIdsMap);
            }
        }
    }

    return {
        Entity: Entity
    };
}());

/**
 * @event
 * @name pc.Entity#destroy
 * @description Fired after the entity is destroyed.
 * @param {pc.Entity} entity The entity that was destroyed.
 * @example
 * entity.on("destroy", function (e) {
 *     console.log('entity ' + e.name + ' has been destroyed');
 * });
 */
<commit_msg>[FIX] Cloned entity hierarchy now matches child order of original. (#1379)<commit_after>Object.assign(pc, function () {
    /**
     * @constructor
     * @name pc.Entity
     * @classdesc The Entity is the core primitive of a PlayCanvas game. Generally speaking an object in your game will consist of an {@link pc.Entity},
     * and a set of {@link pc.Component}s which are managed by their respective {@link pc.ComponentSystem}s. One of those components maybe a
     * {@link pc.ScriptComponent} which allows you to write custom code to attach to your Entity.
     *

     * The Entity uniquely identifies the object and also provides a transform for position and orientation
     * which it inherits from {@link pc.GraphNode} so can be added into the scene graph.
     * The Component and ComponentSystem provide the logic to give an Entity a specific type of behavior. e.g. the ability to
     * render a model or play a sound. Components are specific to an instance of an Entity and are attached (e.g. `this.entity.model`)
     * ComponentSystems allow access to all Entities and Components and are attached to the {@link pc.Application}.
     * @param {String} [name] The non-unique name of the entity, default is "Untitled".
     * @param {pc.Application} [app] The application the entity belongs to, default is the current application.
     * @example
     * var app = ... // Get the pc.Application
     *
     * var entity = new pc.Entity();
     *
     * // Add a Component to the Entity
     * entity.addComponent("camera", {
     *   fov: 45,
     *   nearClip: 1,
     *   farClip: 10000
     * });
     *
     * // Add the Entity into the scene graph
     * app.root.addChild(entity);
     *
     * // Move the entity
     * entity.translate(10, 0, 0);
     *
     * // Or translate it by setting it's position directly
     * var p = entity.getPosition();
     * entity.setPosition(p.x + 10, p.y, p.z);
     *
     * // Change the entity's rotation in local space
     * var e = entity.getLocalEulerAngles();
     * entity.setLocalEulerAngles(e.x, e.y + 90, e.z);
     *
     * // Or use rotateLocal
     * entity.rotateLocal(0, 90, 0);
     *
     * @extends pc.GraphNode
     */
    var Entity = function (name, app){
        pc.GraphNode.call(this, name);

        if (name instanceof pc.Application) app = name;
        this._batchHandle = null; // The handle for a RequestBatch, set this if you want to Component's to load their resources using a pre-existing RequestBatch.
        this.c = {}; // Component storage

        this._app = app; // store app
        if (!app) {
            this._app = pc.Application.getApplication(); // get the current application
            if (!this._app) {
                throw new Error("Couldn't find current application");
            }
        }

        this.setGuid(pc.guid.create()); // Globally Unique Identifier

        // used by component systems to speed up destruction
        this._destroying = false;

        pc.events.attach(this);
    };
    Entity.prototype = Object.create(pc.GraphNode.prototype);
    Entity.prototype.constructor = Entity;

    /**
     * @function
     * @name pc.Entity#addComponent
     * @description Create a new component and add it to the entity.
     * Use this to add functionality to the entity like rendering a model, playing sounds and so on.
     * @param {String} type The name of the component to add. Valid strings are:
     *

     *
"animation" - see {@link pc.AnimationComponent}

     *
"audiolistener" - see {@link pc.AudioListenerComponent}

     *
"camera" - see {@link pc.CameraComponent}

     *
"collision" - see {@link pc.CollisionComponent}

     *
"element" - see {@link pc.ElementComponent}

     *
"light" - see {@link pc.LightComponent}

     *
"layoutchild" - see {@link pc.LayoutChildComponent}

     *
"layoutgroup" - see {@link pc.LayoutGroupComponent}

     *
"model" - see {@link pc.ModelComponent}

     *
"particlesystem" - see {@link pc.ParticleSystemComponent}

     *
"rigidbody" - see {@link pc.RigidBodyComponent}

     *
"screen" - see {@link pc.ScreenComponent}

     *
"script" - see {@link pc.ScriptComponent}

     *
"sound" - see {@link pc.SoundComponent}

     *
"zone" - see {@link pc.ZoneComponent}

     *

     * @param {Object} data The initialization data for the specific component type. Refer to each
     * specific component's API reference page for details on valid values for this parameter.
     * @returns {pc.Component} The new Component that was attached to the entity or null if there
     * was an error.
     * @example
     * var entity = new pc.Entity();
     * entity.addComponent("light"); // Add a light component with default properties
     * entity.addComponent("camera", { // Add a camera component with some specified properties
     *   fov: 45,
     *   clearColor: new pc.Color(1,0,0),
     * });
     */
    Entity.prototype.addComponent = function (type, data) {
        var system = this._app.systems[type];
        if (!system) {
            // #ifdef DEBUG
            console.error("addComponent: System " + type + " doesn't exist");
            // #endif
            return null;
        }
        if (this.c[type]) {
            // #ifdef DEBUG
            console.warn("addComponent: Entity already has " + type + " component");
            // #endif
            return null;
        }
        return system.addComponent(this, data);
    };

    /**
     * @function
     * @name pc.Entity#removeComponent
     * @description Remove a component from the Entity.
     * @param {String} type The name of the Component type
     * @example
     * var entity = new pc.Entity();
     * entity.addComponent("light"); // add new light component
     * //...
     * entity.removeComponent("light"); // remove light component
     */
    Entity.prototype.removeComponent = function (type) {
        var system = this._app.systems[type];
        if (!system) {
            // #ifdef DEBUG
            console.error("removeComponent: System " + type + " doesn't exist");
            // #endif
            return;
        }
        if (!this.c[type]) {
            // #ifdef DEBUG
            console.warn("removeComponent: Entity doesn't have " + type + " component");
            // #endif
            return;
        }
        system.removeComponent(this);
    };

    /**
     * @private
     * @function
     * @name pc.Entity#getGuid
     * @description Get the GUID value for this Entity
     * @returns {String} The GUID of the Entity
     */
    Entity.prototype.getGuid = function () {
        return this._guid;
    };

    /**
     * @private
     * @function
     * @name pc.Entity#setGuid
     * @description Set the GUID value for this Entity.
     *
     * N.B. It is unlikely that you should need to change the GUID value of an Entity at run-time. Doing so will corrupt the graph this Entity is in.
     * @param {String} guid The GUID to assign to the Entity
     */
    Entity.prototype.setGuid = function (guid) {
        // remove current guid from entityIndex
        var index = this._app._entityIndex;
        delete index[this._guid];
        // add new guid to entityIndex
        this._guid = guid;
        index[this._guid] = this;
    };

    Entity.prototype._notifyHierarchyStateChanged = function (node, enabled) {
        var enableFirst = false;
        if (node === this && this._app._enableList.length === 0)
            enableFirst = true;

        node._beingEnabled = true;

        node._onHierarchyStateChanged(enabled);

        if (node._onHierarchyStatePostChanged)
            this._app._enableList.push(node);

        var i, len;
        var c = node._children;
        for (i = 0, len = c.length; i < len; i++) {
            if (c[i]._enabled)
                this._notifyHierarchyStateChanged(c[i], enabled);
        }

        node._beingEnabled = false;

        if (enableFirst) {
            for (i = 0, len = this._app._enableList.length; i < len; i++)
                this._app._enableList[i]._onHierarchyStatePostChanged();

            this._app._enableList.length = 0;
        }
    };

    Entity.prototype._onHierarchyStateChanged = function (enabled) {
        pc.GraphNode.prototype._onHierarchyStateChanged.call(this, enabled);

        // enable / disable all the components
        var component;
        var components = this.c;
        for (var type in components) {
            if (components.hasOwnProperty(type)) {
                component = components[type];
                if (component.enabled) {
                    if (enabled) {
                        component.onEnable();
                    } else {
                        component.onDisable();
                    }
                }
            }
        }
    };

    Entity.prototype._onHierarchyStatePostChanged = function () {
        // post enable all the components
        var components = this.c;
        for (var type in components) {
            if (components.hasOwnProperty(type))
                components[type].onPostStateChange();
        }
    };

    /**
     * @private
     * @function
     * @name pc.Entity#setRequest
     * @description Used during resource loading to ensure that child resources of Entities are tracked
     * @param {ResourceRequest} request The request being used to load this entity
     */
    Entity.prototype.setRequest = function (request) {
        this._request = request;
    };

    /**
     * @private
     * @function
     * @name pc.Entity#getRequest
     * @description Get the Request that is being used to load this Entity
     * @returns {ResourceRequest} The Request
     */
    Entity.prototype.getRequest = function () {
        return this._request;
    };

    /**
     * @function
     * @name pc.Entity#findByGuid
     * @description Find a descendant of this Entity with the GUID
     * @param {String} guid The GUID to search for.
     * @returns {pc.Entity} The Entity with the GUID or null
     */
    Entity.prototype.findByGuid = function (guid) {
        if (this._guid === guid) return this;

        var e = this._app._entityIndex[guid];
        if (e && (e === this || e.isDescendantOf(this))) {
            return e;
        }

        return null;
    };

    /**
     * @function
     * @name pc.Entity#destroy
     * @description Remove all components from the Entity and detach it from the Entity hierarchy. Then recursively destroy all ancestor Entities
     * @example
     * var firstChild = this.entity.children[0];
     * firstChild.destroy(); // delete child, all components and remove from hierarchy
     */
    Entity.prototype.destroy = function () {
        var name;

        this._destroying = true;

        // Disable all enabled components first
        for (name in this.c) {
            this.c[name].enabled = false;
        }

        // Remove all components
        for (name in this.c) {
            this.c[name].system.removeComponent(this);
        }

        // Detach from parent
        if (this._parent)
            this._parent.removeChild(this);

        var children = this._children;
        var child = children.shift();
        while (child) {
            if (child instanceof pc.Entity) {
                child.destroy();
            }

            // make sure child._parent is null because
            // we have removed it from the children array before calling
            // destroy on it
            child._parent = null;

            child = children.shift();
        }

        // fire destroy event
        this.fire('destroy', this);

        // clear all events
        if (this._callbacks)
            this._callbacks = null;

        if (this._callbackActive)
            this._callbackActive = null;

        // remove from entity index
        delete this._app._entityIndex[this._guid];

        this._destroying = false;
    };

    /**
     * @function
     * @name pc.Entity#clone
     * @description Create a deep copy of the Entity. Duplicate the full Entity hierarchy, with all Components and all descendants.
     * Note, this Entity is not in the hierarchy and must be added manually.
     * @returns {pc.Entity} A new Entity which is a deep copy of the original.
     * @example
     *   var e = this.entity.clone(); // Clone Entity
     *   this.entity.parent.addChild(e); // Add it as a sibling to the original
     */
    Entity.prototype.clone = function () {
        var duplicatedIdsMap = {};
        var clone = this._cloneRecursively(duplicatedIdsMap);
        duplicatedIdsMap[this.getGuid()] = clone;

        resolveDuplicatedEntityReferenceProperties(this, this, clone, duplicatedIdsMap);

        return clone;
    };

    Entity.prototype._cloneRecursively = function (duplicatedIdsMap) {
        var clone = new pc.Entity(this._app);
        pc.GraphNode.prototype._cloneInternal.call(this, clone);

        var i;
        for (i = 0; i < this._children.length; i++) {
            var oldChild = this._children[i];
            if (oldChild instanceof pc.Entity) {
                var newChild = oldChild._cloneRecursively(duplicatedIdsMap);
                clone.addChild(newChild);
                duplicatedIdsMap[oldChild.getGuid()] = newChild;
            }
        }

        for (var type in this.c) {
            var component = this.c[type];
            component.system.cloneComponent(this, clone);
        }

        return clone;
    };

    // When an entity that has properties that contain references to other
    // entities within its subtree is duplicated, the expectation of the
    // user is likely that those properties will be updated to point to
    // the corresponding entities within the newly-created duplicate subtree.
    //
    // To handle this, we need to search for properties that refer to entities
    // within the old duplicated structure, find their newly-cloned partners
    // within the new structure, and update the references accordingly. This
    // function implements that requirement.
    function resolveDuplicatedEntityReferenceProperties(oldSubtreeRoot, oldEntity, newEntity, duplicatedIdsMap) {
        var i, len;

        if (oldEntity instanceof pc.Entity) {
            var components = oldEntity.c;

            // Handle component properties
            for (var componentName in components) {
                var component = components[componentName];
                var entityProperties = component.system.getPropertiesOfType('entity');

                for (i = 0, len = entityProperties.length; i < len; i++) {
                    var propertyDescriptor = entityProperties[i];
                    var propertyName = propertyDescriptor.name;
                    var oldEntityReferenceId = component[propertyName];
                    var entityIsWithinOldSubtree = !!oldSubtreeRoot.findByGuid(oldEntityReferenceId);

                    if (entityIsWithinOldSubtree) {
                        var newEntityReferenceId = duplicatedIdsMap[oldEntityReferenceId].getGuid();

                        if (newEntityReferenceId) {
                            newEntity.c[componentName][propertyName] = newEntityReferenceId;
                        } else {
                            console.warn('Could not find corresponding entity id when resolving duplicated entity references');
                        }
                    }
                }
            }

            // Handle entity script attributes
            if (components.script && ! newEntity._app.useLegacyScriptAttributeCloning) {
                newEntity.script.resolveDuplicatedEntityReferenceProperties(components.script, duplicatedIdsMap);
            }

            // Recurse into children. Note that we continue to pass in the same `oldSubtreeRoot`,
            // in order to correctly handle cases where a child has an entity reference
            // field that points to a parent or other ancestor that is still within the
            // duplicated subtree.
            var _old = oldEntity.children.filter(function (e) {
                return (e instanceof pc.Entity);
            });
            var _new = newEntity.children.filter(function (e) {
                return (e instanceof pc.Entity);
            });

            for (i = 0, len = _old.length; i < len; i++) {
                resolveDuplicatedEntityReferenceProperties(oldSubtreeRoot, _old[i], _new[i], duplicatedIdsMap);
            }
        }
    }

    return {
        Entity: Entity
    };
}());

/**
 * @event
 * @name pc.Entity#destroy
 * @description Fired after the entity is destroyed.
 * @param {pc.Entity} entity The entity that was destroyed.
 * @example
 * entity.on("destroy", function (e) {
 *     console.log('entity ' + e.name + ' has been destroyed');
 * });
 */
<|endoftext|>


<commit_before>State = function (isTerm, transitions) {
	this.isTerm = isTerm;
	this.transitions = [];
	if(typeof transitions !== 'undefined') {
		this.transitions = this.transitions.concat(transitions);
	}
};

State.prototype.transition = function (transVal) {
	for(var index = 0; index < this.transCount(); index++) {
		if(transVal === this.transitions[index].transVal) {
			return this.transitions[index].state;
		}
	}
	return null;
};

State.prototype.addTransition = function(transVal, state) {
	this.transitions.push({
		state : state,
		transVal : transVal
	});
};

State.prototype.transCount = function() {
	return this.transitions.length;
};

Ndfa = function (regex) {
	this.startState = null;
	this.regex = regex;
};

Ndfa.prototype.generateStates = function() {
	this.startState = new State(false);

	var curState = this.startState;
	var validator = new ValidateRegex(true);

	for (var index = 0; index < this.regex.length; index++) {
		if(validator.isValid(this.regex[index])) {
			var newState = new State(false);
			curState.addTransition(this.regex[index], newState);
			curState = newState;
		}
	}
	curState.isTerm = true;
};

Ndfa.prototype.getLoopLength = function(str) {

};

Ndfa.prototype.processLoop = function(loop) {

};

Ndfa.prototype.testString = function(str) {
	var isValid = false;
	var curState = this.startState;
	for(var index = 0; index < str.length; index++) {
		var newState = curState.transition(str[index]);
		if(newState === null) {
			break;
		} else {
			curState = newState;
		}
	}
	if(curState.isTerm && newState != null) {
		isValid = true;
	}
	return isValid;
};

ValidateRegex = function(shouldDefault) {
	this.validationFuncs = [];
	if(shouldDefault) {
		this.setupDefaults();
	}
};

ValidateRegex.prototype.setupDefaults = function() {
	this.validationFuncs.push(function(char) {
		var charCast = char.charCodeAt(0);
		var diff = '9'.charCodeAt(0) - charCast;
		return 9 >= diff && diff >= 0;
	});
	this.validationFuncs.push(function(char) {
		var charCast = char.charCodeAt(0);
		var diff = 'z'.charCodeAt(0) - charCast;
		return 25 >= diff && diff >= 0;
	});
	this.validationFuncs.push(function(char) {
		var charCast = char.charCodeAt(0);
		var diff = 'Z'.charCodeAt(0) - charCast;
		return 25 >= diff && diff >= 0;
	});
	this.validationFuncs.push(function(char) {
		return char === '-' || char === '_'
			char === '.' || char === '~';
	});
};

ValidateRegex.prototype.isValid = function(char) {
	var valid = false;
	for(var index = 0; index < this.validationFuncs.length; index++) {
		valid = valid || this.validationFuncs[index](char);
	}
	return valid;
}

exports.Ndfa = Ndfa;

var x = new Ndfa('abc');
x.generateStates();
console.log(x.testString('abcza'));
<commit_msg>changed how the validator works<commit_after>State = function (isTerm, transitions) {
	this.isTerm = isTerm;
	this.transitions = [];
	if(typeof transitions !== 'undefined') {
		this.transitions = this.transitions.concat(transitions);
	}
};

State.prototype.transition = function (transVal) {
	for(var index = 0; index < this.transCount(); index++) {
		if(transVal === this.transitions[index].transVal) {
			return this.transitions[index].state;
		}
	}
	return null;
};

State.prototype.addTransition = function(transVal, state) {
	this.transitions.push({
		state : state,
		transVal : transVal
	});
};

State.prototype.transCount = function() {
	return this.transitions.length;
};

Ndfa = function (regex) {
	this.startState = null;
	this.regex = regex;
};

Ndfa.prototype.generateStates = function() {
	this.startState = new State(false);

	var curState = this.startState;

	for (var index = 0; index < this.regex.length; index++) {
		if(this.validate.isValid(this.regex[index])) {
			var newState = new State(false);
			curState.addTransition(this.regex[index], newState);
			curState = newState;
		}
	}
	curState.isTerm = true;
};

Ndfa.prototype.getLoopLength = function(str) {

};

Ndfa.prototype.processLoop = function(loop) {

};

Ndfa.prototype.testString = function(str) {
	var isValid = false;
	var curState = this.startState;
	for(var index = 0; index < str.length; index++) {
		var newState = curState.transition(str[index]);
		if(newState === null) {
			break;
		} else {
			curState = newState;
		}
	}
	if(curState.isTerm && newState != null) {
		isValid = true;
	}
	return isValid;
};

Ndfa.prototype.validate = (function() {
	this.validationFuncs = [
		function(char) {
		var charCast = char.charCodeAt(0);
		var diff = '9'.charCodeAt(0) - charCast;
		return 9 >= diff && diff >= 0;
		},
		function(char) {
			var charCast = char.charCodeAt(0);
			var diff = 'z'.charCodeAt(0) - charCast;
			return 25 >= diff && diff >= 0;
		},
		function(char) {
			var charCast = char.charCodeAt(0);
			var diff = 'Z'.charCodeAt(0) - charCast;
			return 25 >= diff && diff >= 0;
		},
		function(char) {
			return char === '-' || char === '_'
				char === '.' || char === '~';
		}
	];
	return {
		isValid: function(char) {
			var valid = false;
			for(var index = 0; index < validationFuncs.length; index++) {
				valid = valid || validationFuncs[index](char);
			}
			return valid;
		}
	}
})();

exports.Ndfa = Ndfa;

var x = new Ndfa('abc');
x.generateStates();
console.log(x.testString('abcc'));
<|endoftext|>


<commit_before>
function databaseWalker(node) {
    var result = {};

    result.uuid = node.UUID;

    if (node.Name) {
        result.name = node.Name;
    }

    if (node.Entry) {
        var entry = node.Entry;
        if (!Array.isArray(entry)) { entry = [entry]; }
        result.entries = entry.map(databaseWalker);
    }

    if (node.Group) {
        var group = node.Group;
        if (!Array.isArray(group)) { group = [group]; }
        result.groups = group.map(databaseWalker);
    }

    if (node.String) {
        if (Array.isArray(node.String)) {
            node.String.forEach(function (item) {
                var key = item.Key.toLowerCase();
                if (key === 'password') {
                    result[key] = item.Value._;
                } else {
                    result[key] = item.Value;
                }
            });
        } else if (node.String && typeof node.String === 'object') {
            // String is an object and not null
            // attempt at solving issue #12 - assuming that the weird thing
            // we run into, which is not a list of "String" objects, is now
            // just a "String object"
            var item = node.String;
            var key = item.Key.toLowerCase();
            if (key === 'password') {
                result[key] = item.Value._;
            } else {
                result[key] = item.Value;
            }
        }
    }

    return result;
}

module.exports = function parseRawDatabase(rawDatabase) {
    rawDatabase = rawDatabase.KeePassFile.Root.Group;
    return databaseWalker(rawDatabase);
};
<commit_msg>Revert "attempt to solve bug in #12"<commit_after>
function databaseWalker(node) {
    var result = {};

    result.uuid = node.UUID;

    if (node.Name) {
        result.name = node.Name;
    }

    if (node.Entry) {
        var entry = node.Entry;
        if (!Array.isArray(entry)) { entry = [entry]; }
        result.entries = entry.map(databaseWalker);
    }

    if (node.Group) {
        var group = node.Group;
        if (!Array.isArray(group)) { group = [group]; }
        result.groups = group.map(databaseWalker);
    }

    if (node.String) {
        node.String.forEach(function (item) {
            var key = item.Key.toLowerCase();
            if (key === 'password') {
                result[key] = item.Value._;
            } else {
                result[key] = item.Value;
            }
        });
    }

    return result;
}

module.exports = function parseRawDatabase(rawDatabase) {
    rawDatabase = rawDatabase.KeePassFile.Root.Group;
    return databaseWalker(rawDatabase);
};
<|endoftext|>


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

var request = require('wpcom-xhr-request');

/**
 * Local module dependencies.
 */

var Me = require('./lib/me');
var Site = require('./lib/site');
var Users = require('./lib/users');
var Batch = require('./lib/batch');
var debug = require('debug')('wpcom');

/**
 * XMLHttpRequest (and CORS) API access method.
 *
 * API authentication is done via an (optional) access `token`,
 * which needs to be retrieved via OAuth.
 *
 * Request Handler is optional and XHR is defined as default.
 *
 * @param {String} [token] - OAuth API access token
 * @param {Function} [reqHandler] - function Request Handler
 * @public
 */

function WPCOM(token, reqHandler) {
  if (!(this instanceof WPCOM)) {
    return new WPCOM(token, reqHandler);
  }

  // `token` is optional
  if ('function' === typeof token) {
    reqHandler = token;
    token = null;
  }

  // Set default request handler
  if (!reqHandler) {
    debug('No request handler. Adding default XHR request handler');

    this.request = function (params, fn) {
      params = params || {};
      params.authToken = token;
      return request(params, fn);
    };
  } else {
    this.request = reqHandler;
  }
}

/**
 * Get `Me` object instance
 *
 * @api public
 */

WPCOM.prototype.me = function () {
  return new Me(this);
};

/**
 * Get `Site` object instance
 *
 * @param {String} id
 * @api public
 */

WPCOM.prototype.site = function (id) {
  return new Site(id, this);
};

/**
 * Get `Users` object instance
 *
 * @api public
 */

WPCOM.prototype.users = function () {
  return new Users(this);
};

WPCOM.prototype.batch = function () {
  return new Batch(this);
};

/**
 * List Freshly Pressed Posts
 *
 * @param {Object} [query]
 * @param {Function} fn callback function
 * @api public
 */

WPCOM.prototype.freshlyPressed = function (query, fn) {
  return this.sendRequest('/freshly-pressed', query, null, fn);
};

/**
 * Request to WordPress REST API
 *
 * @param {String|Object} params
 * @param {Object} [query]
 * @param {Object} [body]
 * @param {Function} fn
 * @api private
 */

WPCOM.prototype.sendRequest = function (params, query, body, fn) {
  // `params` can be just the path (String)
  if ('string' === typeof params) {
    params = { path: params };
  }

  debug('sendRequest(%o)', params.path);

  // set `method` request param
  params.method = (params.method || 'get').toUpperCase();

  // `query` is optional
  if ('function' === typeof query) {
    fn = query;
    query = null;
  }

  // `body` is optional
  if ('function' === typeof body) {
    fn = body;
    body = null;
  }

  // pass `query` and/or `body` to request params
  if (query) {
    params.query = query;

    // Handle special query parameters
    // - `apiVersion`
    if (query.apiVersion) {
      params.apiVersion = query.apiVersion;
      delete query.apiVersion;
    }
  }

  if (body) {
    params.body = body;
  }

  // callback `fn` function is optional
  if (!fn) {
    fn = function (err) { if (err) { throw err; } };
  }

  // request method
  return this.request(params, fn);
};

/**
 * Expose `WPCOM` module
 */

module.exports = WPCOM;
<commit_msg>core: token is optional<commit_after>
/**
 * Module dependencies.
 */

var request = require('wpcom-xhr-request');

/**
 * Local module dependencies.
 */

var Me = require('./lib/me');
var Site = require('./lib/site');
var Users = require('./lib/users');
var Batch = require('./lib/batch');
var debug = require('debug')('wpcom');

/**
 * XMLHttpRequest (and CORS) API access method.
 *
 * API authentication is done via an (optional) access `token`,
 * which needs to be retrieved via OAuth.
 *
 * Request Handler is optional and XHR is defined as default.
 *
 * @param {String} [token] - OAuth API access token
 * @param {Function} [reqHandler] - function Request Handler
 * @public
 */

function WPCOM(token, reqHandler) {
  if (!(this instanceof WPCOM)) {
    return new WPCOM(token, reqHandler);
  }

  // `token` is optional
  if ('function' === typeof token) {
    reqHandler = token;
    token = null;
  }

  // Set default request handler
  if (!reqHandler) {
    debug('No request handler. Adding default XHR request handler');

    this.request = function (params, fn) {
      params = params || {};

      // token is optional
      if (token) {
        params.authToken = token;
      }

      return request(params, fn);
    };
  } else {
    this.request = reqHandler;
  }
}

/**
 * Get `Me` object instance
 *
 * @api public
 */

WPCOM.prototype.me = function () {
  return new Me(this);
};

/**
 * Get `Site` object instance
 *
 * @param {String} id
 * @api public
 */

WPCOM.prototype.site = function (id) {
  return new Site(id, this);
};

/**
 * Get `Users` object instance
 *
 * @api public
 */

WPCOM.prototype.users = function () {
  return new Users(this);
};

WPCOM.prototype.batch = function () {
  return new Batch(this);
};

/**
 * List Freshly Pressed Posts
 *
 * @param {Object} [query]
 * @param {Function} fn callback function
 * @api public
 */

WPCOM.prototype.freshlyPressed = function (query, fn) {
  return this.sendRequest('/freshly-pressed', query, null, fn);
};

/**
 * Request to WordPress REST API
 *
 * @param {String|Object} params
 * @param {Object} [query]
 * @param {Object} [body]
 * @param {Function} fn
 * @api private
 */

WPCOM.prototype.sendRequest = function (params, query, body, fn) {
  // `params` can be just the path (String)
  if ('string' === typeof params) {
    params = { path: params };
  }

  debug('sendRequest(%o)', params.path);

  // set `method` request param
  params.method = (params.method || 'get').toUpperCase();

  // `query` is optional
  if ('function' === typeof query) {
    fn = query;
    query = null;
  }

  // `body` is optional
  if ('function' === typeof body) {
    fn = body;
    body = null;
  }

  // pass `query` and/or `body` to request params
  if (query) {
    params.query = query;

    // Handle special query parameters
    // - `apiVersion`
    if (query.apiVersion) {
      params.apiVersion = query.apiVersion;
      delete query.apiVersion;
    }
  }

  if (body) {
    params.body = body;
  }

  // callback `fn` function is optional
  if (!fn) {
    fn = function (err) { if (err) { throw err; } };
  }

  // request method
  return this.request(params, fn);
};

/**
 * Expose `WPCOM` module
 */

module.exports = WPCOM;
<|endoftext|>


<commit_before>var modes = ["XML", "HTML4", "HTML5"];

module.exports = {
	decode: function(data, level){
		if(!modes[level]) level = 0;
		return module.exports["decode" + modes[level]](data);
	},
	decodeStrict: function(data, level){
		if(!modes[level]) level = 0;
		return module.exports["decode" + modes[level] + "Strict"](data);
	},
	encode: function(data, level){
		if(!modes[level]) level = 0;
		return module.exports["encode" + modes[level]](data);
	}
};

modes.reduce(function(prev, name){
	var obj = require("./entities/" + name.toLowerCase() + ".json");

	if(prev){
		Object.keys(prev).forEach(function(name){
			obj[name] = prev[name];
		});
	}

	module.exports["decode" + name + "Strict"] = getStrictReplacer(obj);

	if(name === "XML"){
		//there is no non-strict mode for XML
		module.exports.decodeXML = module.exports.decodeXMLStrict;
	} else {
		module.exports["decode" + name] = getReplacer(obj);
	}

	module.exports["encode" + name] = getReverse(obj);

	return obj;
}, null);

function getReplacer(obj){
	var keys = Object.keys(obj).sort();
	var re = keys.join("|").replace(/(\w+)\|\1;/g, "$1;?");

	// also match hex and char codes
	re += "|#[xX][\\da-fA-F]+;?|#\\d+;?";

	return genReplaceFunc(
		new RegExp("&(?:" + re + ")", "g"),
		function func(name){
			if(name.charAt(1) === "#"){
				if(name.charAt(2).toLowerCase() === "x"){
					return String.fromCharCode(parseInt(name.substr(3), 16));
				}
				return String.fromCharCode(parseInt(name.substr(2), 10));
			}
			return obj[name.substr(1)];
		}
	);
}

function getStrictReplacer(obj){
	var keys = Object.keys(obj).sort().filter(RegExp.prototype.test, /;$/);
	var re = keys.map(function(name){
		return name.slice(0, -1); //remove trailing semicolon
	}).join("|");

	// also match hex and char codes
	re += "|#[xX][\\da-fA-F]+|#\\d+";

	var expr = new RegExp("&(?:" + re + ");", "g");

	return genReplaceFunc(expr, func);

	function func(name){
			if(name.charAt(1) === "#"){
				if(name.charAt(2).toLowerCase() === "x"){
					return String.fromCharCode(parseInt(name.substr(3), 16));
				}
				return String.fromCharCode(parseInt(name.substr(2), 10));
			}
			return obj[name.substr(1)];
		}
}

var re_nonASCII = /[^\0-\x7F]/g,
    re_astralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;

function nonUTF8Replacer(c){
	return "&#x" + c.charCodeAt(0).toString(16).toUpperCase() + ";";
}

function astralReplacer(c){
	// http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
	var high = c.charCodeAt(0);
	var low  = c.charCodeAt(1);
	var codePoint = (high - 0xD800) * 0x400 + low - 0xDC00 + 0x10000;
	return "&#x" + codePoint.toString(16).toUpperCase() + ";";
}

function getReverse(obj){
	var reverse = Object.keys(obj).filter(function(name){
		//prefer identifiers with a semicolon
		return name.substr(-1) === ";" || obj[name + ";"] !== obj[name];
	}).reduce(function(reverse, name){
		reverse[obj[name]] = name;
		return reverse;
	}, {});

	var regex = new RegExp("\\" + Object.keys(reverse).sort().join("|\\"), "g");
	function func(name){
		return "&" + reverse[name];
	}

	return function(data){
		return data
				.replace(regex, func)
				.replace(re_astralSymbols, astralReplacer)
				.replace(re_nonASCII, nonUTF8Replacer);
	};
}

function genReplaceFunc(regex, func){
	return function(data){
		return data.replace(regex, func);
	};
}
<commit_msg>convert all values to strings<commit_after>var modes = ["XML", "HTML4", "HTML5"];

module.exports = {
	decode: function(data, level){
		if(!modes[level]) level = 0;
		return module.exports["decode" + modes[level]](data);
	},
	decodeStrict: function(data, level){
		if(!modes[level]) level = 0;
		return module.exports["decode" + modes[level] + "Strict"](data);
	},
	encode: function(data, level){
		if(!modes[level]) level = 0;
		return module.exports["encode" + modes[level]](data);
	}
};

modes.reduce(function(prev, name){
	var obj = require("./entities/" + name.toLowerCase() + ".json");

	if(prev){
		Object.keys(prev).forEach(function(name){
			obj[name] = prev[name];
		});
	}

	module.exports["decode" + name + "Strict"] = getStrictReplacer(obj);

	if(name === "XML"){
		//there is no non-strict mode for XML
		module.exports.decodeXML = module.exports.decodeXMLStrict;
	} else {
		module.exports["decode" + name] = getReplacer(obj);
	}

	module.exports["encode" + name] = getReverse(obj);

	return obj;
}, null);

function getReplacer(obj){
	var keys = Object.keys(obj).sort();
	var re = keys.join("|").replace(/(\w+)\|\1;/g, "$1;?");

	// also match hex and char codes
	re += "|#[xX][\\da-fA-F]+;?|#\\d+;?";

	return genReplaceFunc(
		new RegExp("&(?:" + re + ")", "g"),
		function func(name){
			if(name.charAt(1) === "#"){
				if(name.charAt(2).toLowerCase() === "x"){
					return String.fromCharCode(parseInt(name.substr(3), 16));
				}
				return String.fromCharCode(parseInt(name.substr(2), 10));
			}
			return obj[name.substr(1)];
		}
	);
}

function getStrictReplacer(obj){
	var keys = Object.keys(obj).sort().filter(RegExp.prototype.test, /;$/);
	var re = keys.map(function(name){
		return name.slice(0, -1); //remove trailing semicolon
	}).join("|");

	// also match hex and char codes
	re += "|#[xX][\\da-fA-F]+|#\\d+";

	var expr = new RegExp("&(?:" + re + ");", "g");

	return genReplaceFunc(expr, func);

	function func(name){
			if(name.charAt(1) === "#"){
				if(name.charAt(2).toLowerCase() === "x"){
					return String.fromCharCode(parseInt(name.substr(3), 16));
				}
				return String.fromCharCode(parseInt(name.substr(2), 10));
			}
			return obj[name.substr(1)];
		}
}

var re_nonASCII = /[^\0-\x7F]/g,
    re_astralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;

function nonUTF8Replacer(c){
	return "&#x" + c.charCodeAt(0).toString(16).toUpperCase() + ";";
}

function astralReplacer(c){
	// http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
	var high = c.charCodeAt(0);
	var low  = c.charCodeAt(1);
	var codePoint = (high - 0xD800) * 0x400 + low - 0xDC00 + 0x10000;
	return "&#x" + codePoint.toString(16).toUpperCase() + ";";
}

function getReverse(obj){
	var reverse = Object.keys(obj).filter(function(name){
		//prefer identifiers with a semicolon
		return name.substr(-1) === ";" || obj[name + ";"] !== obj[name];
	}).reduce(function(reverse, name){
		reverse[obj[name]] = name;
		return reverse;
	}, {});

	var regex = new RegExp("\\" + Object.keys(reverse).sort().join("|\\"), "g");
	function func(name){
		return "&" + reverse[name];
	}

	return function(data){
		return (data + "")
				.replace(regex, func)
				.replace(re_astralSymbols, astralReplacer)
				.replace(re_nonASCII, nonUTF8Replacer);
	};
}

function genReplaceFunc(regex, func){
	return function(data){
		return (data + "")
				.replace(regex, func);
	};
}
<|endoftext|>


<commit_before>var Node = {
  child: require('child_process'),
  fs: require('fs'),
  os: require('os'),
  path: require('path'),
  process: process
};

function escapeDoubleQuotes(string) {
  return string.replace(/"/g, '\\"');
}

function validName(string) {
  return /^[a-z0-9 ]+$/i.test(string) && string.trim().length > 0;
}

var Sudo = function(command, end) {
  if (Node.process.platform === 'darwin') return Sudo.Mac(command, end);
  end('Platform not yet supported.');
  // TO DO: Add support for linux.
};

Sudo.name = undefined;

Sudo.Mac = function(command, end, count) {
  if (count === undefined) count = 0;
  if (count >= 2) return end(new Error('Permission denied after several password prompts.'));
  if (/^sudo/i.test(command)) return end(new Error('Command should not contain "sudo".'));
  // Run sudo in non-interactive mode (-n).
  Node.child.exec('sudo -n ' + command,
    function(error, stdout, stderr) {
      if (error) return end(error);
      if (stderr !== 'sudo: a password is required\n') {
        if (/^sudo:/i.test(stderr)) return end(stderr);
        end(error, stdout, stderr);
      } else {
        Sudo.Mac.prompt(
          function(error) {
            if (error) return end(error);
            Sudo.Mac(command, end, ++count); // Cannot use ++ suffix here.
          }
        );
      }
    }
  );
};

Sudo.Mac.prompt = function(end) {
  var self = this;
  var title = Sudo.name || Node.process.title;
  if (!validName(title)) return end(new Error('Please use sudo.setName(string) to set your app name (process.title contains invalid characters).'));
  var temp = Node.os.tmpdir();
  if (!temp) return end(new Error('Requires os.tmpdir() to be defined.'));
  if (!Node.process.env.USER) return end(new Error('Requires env[\'USER\'] to be defined.'));
  if (self.prompting) {
    // Already waiting for user to enter password...
    // We expect that Sudo.exec may be called multiple times.
    // If a prompt is already pending, then we wait for the result of the prompt
    // and do not trigger another permission request dialog.
    self.prompting.push(end);
  } else {
    // Prompting user for password...
    self.prompting = [end];
    var finish = function(error) {
      var callbacks = self.prompting;
      self.prompting = false;
      for (var index = 0, length = callbacks.length; index < length; index++) {
        callbacks[index](error);
      }
    };
    // We copy osascript to a new tmp location using the title of this process as the basename.
    // We can then use this new binary to change the sudo timestamp, and OS X will use
    // the title of this process when asking the user for permission.
    Node.child.exec('which osascript',
      function(error, stdout, stderr) {
        if (error) return finish(error);
        var source = stdout.trim();
        var target = Node.path.join(temp, title);
        Node.fs.readFile(source,
          function(error, buffer) {
            if (error) return finish(error);
            Node.fs.writeFile(target, buffer,
              function(error) {
                if (error) return finish(error);
                Node.fs.chmod(target, 0755,
                  function(error) {
                    if (error) return finish(error);
                    // Set the sudo timestamp for our user:
                    var command = '"' + escapeDoubleQuotes(target) + '" -e \'do shell script "mkdir -p /var/db/sudo/$USER; touch /var/db/sudo/$USER" with administrator privileges\'';
                    Node.child.exec(command,
                      function(error, stdout, stderr) {
                        if (/user canceled/i.test(error)) error = new Error('User did not grant permission.');
                        if (error) return finish(error);
                        Node.fs.unlink(target, finish);
                      }
                    );
                  }
                );
              }
            );
          }
        );
      }
    );
  }
};

Sudo.Mac.prompting = false;

exports.exec = Sudo;

exports.touch = function(end) {
  Sudo('echo noop',
    function(error) {
      if (error) return end(error);
      end();
    }
  );
};

exports.setName = function(string) {
  if (!validName(string)) throw new Error('Name must be alphanumeric only (spaces are allowed).');
  Sudo.name = string;
};
<commit_msg>Fix setName<commit_after>var Node = {
  child: require('child_process'),
  fs: require('fs'),
  os: require('os'),
  path: require('path'),
  process: process
};

function escapeDoubleQuotes(string) {
  return string.replace(/"/g, '\\"');
}

function validName(string) {
  return /^[a-z0-9 ]+$/i.test(string) && string.trim().length > 0;
}

var Name = undefined;

var Sudo = function(command, end) {
  if (Node.process.platform === 'darwin') return Sudo.Mac(command, end);
  end('Platform not yet supported.');
  // TO DO: Add support for linux.
};

Sudo.Mac = function(command, end, count) {
  if (count === undefined) count = 0;
  if (count >= 2) return end(new Error('Permission denied after several password prompts.'));
  if (/^sudo/i.test(command)) return end(new Error('Command should not contain "sudo".'));
  // Run sudo in non-interactive mode (-n).
  Node.child.exec('sudo -n ' + command,
    function(error, stdout, stderr) {
      if (error) return end(error);
      if (stderr !== 'sudo: a password is required\n') {
        if (/^sudo:/i.test(stderr)) return end(stderr);
        end(error, stdout, stderr);
      } else {
        Sudo.Mac.prompt(
          function(error) {
            if (error) return end(error);
            Sudo.Mac(command, end, ++count); // Cannot use ++ suffix here.
          }
        );
      }
    }
  );
};

Sudo.Mac.prompt = function(end) {
  var self = this;
  var title = Name || Node.process.title;
  if (!validName(title)) return end(new Error('Please use sudo.setName(string) to set your app name (process.title contains invalid characters).'));
  var temp = Node.os.tmpdir();
  if (!temp) return end(new Error('Requires os.tmpdir() to be defined.'));
  if (!Node.process.env.USER) return end(new Error('Requires env[\'USER\'] to be defined.'));
  if (self.prompting) {
    // Already waiting for user to enter password...
    // We expect that Sudo.exec may be called multiple times.
    // If a prompt is already pending, then we wait for the result of the prompt
    // and do not trigger another permission request dialog.
    self.prompting.push(end);
  } else {
    // Prompting user for password...
    self.prompting = [end];
    var finish = function(error) {
      var callbacks = self.prompting;
      self.prompting = false;
      for (var index = 0, length = callbacks.length; index < length; index++) {
        callbacks[index](error);
      }
    };
    // We copy osascript to a new tmp location using the title of this process as the basename.
    // We can then use this new binary to change the sudo timestamp, and OS X will use
    // the title of this process when asking the user for permission.
    Node.child.exec('which osascript',
      function(error, stdout, stderr) {
        if (error) return finish(error);
        var source = stdout.trim();
        var target = Node.path.join(temp, title);
        Node.fs.readFile(source,
          function(error, buffer) {
            if (error) return finish(error);
            Node.fs.writeFile(target, buffer,
              function(error) {
                if (error) return finish(error);
                Node.fs.chmod(target, 0755,
                  function(error) {
                    if (error) return finish(error);
                    // Set the sudo timestamp for our user:
                    var command = '"' + escapeDoubleQuotes(target) + '" -e \'do shell script "mkdir -p /var/db/sudo/$USER; touch /var/db/sudo/$USER" with administrator privileges\'';
                    Node.child.exec(command,
                      function(error, stdout, stderr) {
                        if (/user canceled/i.test(error)) error = new Error('User did not grant permission.');
                        if (error) return finish(error);
                        Node.fs.unlink(target, finish);
                      }
                    );
                  }
                );
              }
            );
          }
        );
      }
    );
  }
};

Sudo.Mac.prompting = false;

exports.exec = Sudo;

exports.touch = function(end) {
  Sudo('echo noop',
    function(error) {
      if (error) return end(error);
      end();
    }
  );
};

exports.setName = function(string) {
  if (!validName(string)) throw new Error('Name must be alphanumeric only (spaces are allowed).');
  Name = string;
};
<|endoftext|>


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

var Command = require('./util/command'),
    project = require('./util/project'),
    platforms = require('./util/platform'),
    cordova = require('cordova-lib').cordova,

    util = require('util');

/**
 * localization of human readable log messages
 * eventual migration to its own module
 */
var PG_STR = {
    'msgdet' : ['detecting', 'SDK environment...'],
    'useenv' : ['using the', 'environment']
};

/*!
 * Command setup.
 */

module.exports = {
    create: function(phonegap) {
        return new InstallCommand(phonegap);
    }
};

function InstallCommand(phonegap) {
    return Command.apply(this, arguments);
}

util.inherits(InstallCommand, Command);

/**
 * Installs an App.
 *
 * Automatically detects if local SDK exists.
 *  - true: install application using the local system.
 *  - false: install the application using remote service.
 *
 * Options:
 *
 *   - `options` {Object}
 *     - `platforms` {Array} is a list of platforms (limited to 1).
 *   - [`callback`] {Function} is triggered after completion.
 *     - `e` {Error} is null unless there is an error.
 *
 * Returns:
 *
 *   {PhoneGap} for chaining.
 */

InstallCommand.prototype.run = function(options, callback) {
    // require options
    if (!options) throw new Error('requires option parameter');
    if (!options.platforms) throw new Error('requires option.platforms parameter');

    // optional callback
    callback = callback || function() {};

    // run app
    this.execute(options, callback);

    return this.phonegap;
};

/*!
 * Execute.
 */

InstallCommand.prototype.execute = function(options, callback) {
    var self = this,
        platform = platforms.names(options.platforms)[0];

    // change to project directory and delegate errors
    if (!project.cd({ emitter: self.phonegap, callback: callback })) return;

    // detect the platform support
    self.phonegap.emit('log', PG_STR.msgdet[0], platform.human, PG_STR.msgdet[1]);
    cordova.platform.supports('.', platform.local).then(function() {
        // invoke local or remote build
        var env = 'local';
        self.phonegap.emit('log', PG_STR.useenv[0], env, PG_STR.useenv[1]);
        self.phonegap[env].install(options, callback);
    }, function(e) {
        var env = 'remote';
        self.phonegap.emit('log', PG_STR.useenv[0], env, PG_STR.useenv[1]);
        self.phonegap[env].install(options, callback);
    });

};
<commit_msg>[#418] install updated to use cordova platform instead of deprecated supports function<commit_after>/*!
 * Module dependencies.
 */

var Command = require('./util/command'),
    project = require('./util/project'),
    platforms = require('./util/platform'),
    cordova = require('cordova-lib').cordova,

    util = require('util');

/**
 * localization of human readable log messages
 * eventual migration to its own module
 */
var PG_STR = {
    'msgdet' : ['detecting', 'SDK environment...'],
    'useenv' : ['using the', 'environment']
};

/*!
 * Command setup.
 */

module.exports = {
    create: function(phonegap) {
        return new InstallCommand(phonegap);
    }
};

function InstallCommand(phonegap) {
    return Command.apply(this, arguments);
}

util.inherits(InstallCommand, Command);

/**
 * Installs an App.
 *
 * Automatically detects if local SDK exists.
 *  - true: install application using the local system.
 *  - false: install the application using remote service.
 *
 * Options:
 *
 *   - `options` {Object}
 *     - `platforms` {Array} is a list of platforms (limited to 1).
 *   - [`callback`] {Function} is triggered after completion.
 *     - `e` {Error} is null unless there is an error.
 *
 * Returns:
 *
 *   {PhoneGap} for chaining.
 */

InstallCommand.prototype.run = function(options, callback) {
    // require options
    if (!options) throw new Error('requires option parameter');
    if (!options.platforms) throw new Error('requires option.platforms parameter');

    // optional callback
    callback = callback || function() {};

    // run app
    this.execute(options, callback);

    return this.phonegap;
};

/*!
 * Execute.
 */

InstallCommand.prototype.execute = function(options, callback) {
    var self = this,
        platform = platforms.names(options.platforms)[0];

    // change to project directory and delegate errors
    if (!project.cd({ emitter: self.phonegap, callback: callback })) return;

    // detect the platform support
    self.phonegap.emit('log', PG_STR.msgdet[0], platform.human, PG_STR.msgdet[1]);

    try {
        // will throw if element in options.platform isn't recognized
        cordova.platform('', options.platform, null)
        // invoke local build
        var env = 'local';
        self.phonegap.emit('log', PG_STR.useenv[0], env, PG_STR.useenv[1]);
        self.phonegap[env].install(options, callback);
    } catch (e) {
        // invoke remote build
        var env = 'remote';
        self.phonegap.emit('log', PG_STR.useenv[0], env, PG_STR.useenv[1]);
        self.phonegap[env].install(options, callback);
    }
};
<|endoftext|>


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

try {
  var EventEmitter = require('events').EventEmitter;
} catch (err) {
  var Emitter = require('emitter');
}

/**
 * Noop.
 */

function noop(){}

/**
 * Expose `Batch`.
 */

module.exports = Batch;

/**
 * Create a new Batch.
 */

function Batch() {
  if (!(this instanceof Batch)) return new Batch;
  this.fns = [];
  this.concurrency(Infinity);
  this.throws(true);
  for (var i = 0, len = arguments.length; i < len; ++i) {
    this.push(arguments[i]);
  }
}

/**
 * Inherit from `EventEmitter.prototype`.
 */

if (EventEmitter) {
  Batch.prototype.__proto__ = EventEmitter.prototype;
} else {
  Emitter(Batch.prototype);
}

/**
 * Set concurrency to `n`.
 *
 * @param {Number} n
 * @return {Batch}
 * @api public
 */

Batch.prototype.concurrency = function(n){
  this.n = n;
  return this;
};

/**
 * Queue a function.
 *
 * @param {Function} fn
 * @return {Batch}
 * @api public
 */

Batch.prototype.push = function(fn){
  this.fns.push(fn);
  return this;
};

/**
 * Set wether Batch will or will not throw up.
 *
 * @param  {Boolean} throws
 * @return {Batch}
 * @api public
 */
Batch.prototype.throws = function(throws) {
  this.e = !!throws;
  return this;
};

/**
 * Execute all queued functions in parallel,
 * executing `cb(err, results)`.
 *
 * @param {Function} cb
 * @return {Batch}
 * @api public
 */

Batch.prototype.end = function(cb){
  var self = this
    , total = this.fns.length
    , pending = total
    , results = []
    , errors = []
    , cb = cb || noop
    , fns = this.fns
    , max = this.n
    , throws = this.e
    , index = 0
    , done;

  // empty
  if (!fns.length) return cb(null, results);

  // process
  function next() {
    var i = index++;
    var fn = fns[i];
    if (!fn) return;
    var start = new Date;

    try {
      fn(callback);
    } catch (err) {
      callback(err);
    }

    function callback(err, res){
      if (done) return;
      if (err && throws) return done = true, cb(err);
      var complete = total - pending + 1;
      var end = new Date;

      results[i] = res;
      errors[i] = err;

      self.emit('progress', {
        index: i,
        value: res,
        error: err,
        pending: pending,
        total: total,
        complete: complete,
        percent: complete / total * 100 | 0,
        start: start,
        end: end,
        duration: end - start
      });

      if (--pending) next();
      else if(!throws) cb(errors, results);
      else cb(null, results);
    }
  }

  // concurrency
  for (var i = 0; i < fns.length; i++) {
    if (i == max) break;
    next();
  }

  return this;
};
<commit_msg>Fix compatibility with component v1<commit_after>/**
 * Module dependencies.
 */

try {
  var EventEmitter = require('events').EventEmitter;
  if (!EventEmitter) throw new Error();
} catch (err) {
  var Emitter = require('emitter');
}

/**
 * Noop.
 */

function noop(){}

/**
 * Expose `Batch`.
 */

module.exports = Batch;

/**
 * Create a new Batch.
 */

function Batch() {
  if (!(this instanceof Batch)) return new Batch;
  this.fns = [];
  this.concurrency(Infinity);
  this.throws(true);
  for (var i = 0, len = arguments.length; i < len; ++i) {
    this.push(arguments[i]);
  }
}

/**
 * Inherit from `EventEmitter.prototype`.
 */

if (EventEmitter) {
  Batch.prototype.__proto__ = EventEmitter.prototype;
} else {
  Emitter(Batch.prototype);
}

/**
 * Set concurrency to `n`.
 *
 * @param {Number} n
 * @return {Batch}
 * @api public
 */

Batch.prototype.concurrency = function(n){
  this.n = n;
  return this;
};

/**
 * Queue a function.
 *
 * @param {Function} fn
 * @return {Batch}
 * @api public
 */

Batch.prototype.push = function(fn){
  this.fns.push(fn);
  return this;
};

/**
 * Set wether Batch will or will not throw up.
 *
 * @param  {Boolean} throws
 * @return {Batch}
 * @api public
 */
Batch.prototype.throws = function(throws) {
  this.e = !!throws;
  return this;
};

/**
 * Execute all queued functions in parallel,
 * executing `cb(err, results)`.
 *
 * @param {Function} cb
 * @return {Batch}
 * @api public
 */

Batch.prototype.end = function(cb){
  var self = this
    , total = this.fns.length
    , pending = total
    , results = []
    , errors = []
    , cb = cb || noop
    , fns = this.fns
    , max = this.n
    , throws = this.e
    , index = 0
    , done;

  // empty
  if (!fns.length) return cb(null, results);

  // process
  function next() {
    var i = index++;
    var fn = fns[i];
    if (!fn) return;
    var start = new Date;

    try {
      fn(callback);
    } catch (err) {
      callback(err);
    }

    function callback(err, res){
      if (done) return;
      if (err && throws) return done = true, cb(err);
      var complete = total - pending + 1;
      var end = new Date;

      results[i] = res;
      errors[i] = err;

      self.emit('progress', {
        index: i,
        value: res,
        error: err,
        pending: pending,
        total: total,
        complete: complete,
        percent: complete / total * 100 | 0,
        start: start,
        end: end,
        duration: end - start
      });

      if (--pending) next();
      else if(!throws) cb(errors, results);
      else cb(null, results);
    }
  }

  // concurrency
  for (var i = 0; i < fns.length; i++) {
    if (i == max) break;
    next();
  }

  return this;
};
<|endoftext|>


<commit_before>var halCache = {};

module.exports = (server, options) => {
  options = options || {};
  options.prefix = options.prefix || "";
  options.makeObjects = options.makeObjects || false;

  var getHAL = require('./getHAL.js')(server, options);
  var makeAddLink = require('./addLink.js')(server, options);

  // override json formatter
  // add HAL data to body and then invoke normal json formatter
  var _formatJSON = server.formatters["application/json"];
  var halFormatter = (request, response, body, cb) => {
    body._links = request.hal;
    return _formatJSON(request, response, body, cb);
  }
  server.acceptable.push('application/hal+json');
  server.formatters["application/hal+json"] = halFormatter;
  if (options.overrideJSON) {
    server.formatters["application/json"] = halFormatter;
  }

  // fires on every request
  // renders the HAL data and puts it in cache if not present already
  return (request, response, next) => {
    var method = request.method;
    var url = request.url;

    if (!halCache[url]) {
      halCache[url] = getHAL(url);
    }
    // clone the cached object
    // the developer can add custom links, and if we pass this object by reference
    // this will (accidentally) get into the cache
    if (options.makeObjects) {
      Object.assign(request.hal, halCache[url]);
    } else {
      request.hal = halCache[url].slice(0);
    }
    response.addLink = makeAddLink(request.hal, response);
    next();
  }
}
<commit_msg>changed to named functions in main file<commit_after>var halCache = {};

module.exports = function restifyJSONHalInit(server, options) {
  options = options || {};
  options.prefix = options.prefix || "";
  options.makeObjects = options.makeObjects || false;

  var getHAL = require('./getHAL.js')(server, options);
  var makeAddLink = require('./addLink.js')(server, options);

  // override json formatter
  // add HAL data to body and then invoke normal json formatter
  var _formatJSON = server.formatters["application/json"];
  var halFormatter = function restifyJSONHalFormatter(request, response, body, cb) {
    body._links = request.hal;
    return _formatJSON(request, response, body, cb);
  }
  server.acceptable.push('application/hal+json');
  server.formatters["application/hal+json"] = halFormatter;
  if (options.overrideJSON) {
    server.formatters["application/json"] = halFormatter;
  }

  // fires on every request
  // renders the HAL data and puts it in cache if not present already
  return function restifyJSONHal(request, response, next) {
    var method = request.method;
    var url = request.url;

    if (!halCache[url]) {
      halCache[url] = getHAL(url);
    }
    // clone the cached object
    // the developer can add custom links, and if we pass this object by reference
    // this will (accidentally) get into the cache
    if (options.makeObjects) {
      Object.assign(request.hal, halCache[url]);
    } else {
      request.hal = halCache[url].slice(0);
    }
    response.addLink = makeAddLink(request.hal, response);
    next();
  }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

(function() {

    var fs = require('fs');
    var path = require('path');
    var resolve = require('resolve');

    var File = require('vinyl'); // The module file to be checked.

    var deps = {}; // The dependency tree being resolved.
    var checked = []; // List of modules already checked.
    var toCheck = []; // List of modules to parse next.

    var opts = {
        parseRequires: true, // Naively parses source for require statements.
        indexCoreModules: false, //Whether to index core modules or skip them.
        indexPackageJSONDeps: true, // Indexes dependencies in pacakge.json
        indexPackageJSONOptDeps: true, // Indexes optional dependencies in pacakge.json
        indexPac: true, // Indexes dependencies in pacakge.json
        indexRequiresByName: true, // Indexes parsed dependencies required by name.
        indexRequiresByPath: false, // Indexes parsed dependencies required by path.
        recursePackageJSONDeps: true, // Recurse through package.json dependencies.
        recursePackageJSONOptDeps: true, // Recurse through package.json optional dependencies.
        recurseRequiresByPath: true, // Recurse through parsed dependencies required by path.
        verbose: false, // Print logging info.
        limit: 1000000, // Maximum number of modules checked recursively.
                        // Setting this to `1` stops the recursion at checking only the given module's dependencies.
                        // But this isn't really a recursion counter, as all dependencies beyond the first level count towards the limit individually.
        offsetPath: __dirname // All resolved modules are made relative to this path.
    };

    // Actual logic for parsing files.
    var checkByFile = function(file) {

        // Check for the "recursion" limit.
        if (opts.limit >= 0) {
            opts.limit--;
        }
        else {
            throw "Recursion limit reached.";
        }

        var basedir = path.resolve(path.dirname(file.path));

        // Parse package.json.
        if ( opts.indexPackageJSONDeps || opts.indexPackageJSONOptDeps || opts.recursePackageJSONDeps || opts.recursePackageJSONOptDeps ) {
            require('closest-package').sync(basedir, function(json, filename) {

                if ( opts.indexPackageJSONDeps || opts.recursePackageJSONDeps ) {
                    for (var moduleName in json.dependencies) {

                        // Resolve module path.
                        var modulePathLocal = resolve.sync(moduleName, {
                            basedir: basedir
                        });
                        // Make path absolute.
                        var modulePathAbsolute = path.resolve(modulePathLocal);

                        // Add resolution to output.
                        if (opts.indexPackageJSONDeps) {
                            if (typeof deps[basedir] !== typeof {}) deps[basedir] = {};
                            deps[basedir][moduleName] = path.relative(opts.offsetPath, modulePathAbsolute);
                            if (opts.verbose) console.log("Indexed package.json dependency `" + moduleName + "`.");
                        }

                        // Add dependency to be checked recursively.
                        if (opts.recursePackageJSONDeps) {
                            toCheck.push(modulePathAbsolute);
                        }

                    }
                }

                if ( opts.indexPackageJSONOptDeps || opts.recursePackageJSONOptDeps ) {
                    for (var moduleName in json.optionalDependencies) {

                        // Resolve module path.
                        var modulePathLocal = resolve.sync(moduleName, {
                            basedir: basedir
                        });
                        // Make path absolute.
                        var modulePathAbsolute = path.resolve(modulePathLocal);

                        // Add resolution to output.
                        if (opts.indexPackageJSONOptDeps) {
                            if (typeof deps[basedir] !== typeof {}) deps[basedir] = {};
                            deps[basedir][moduleName] = path.relative(opts.offsetPath, modulePathAbsolute);
                            if (opts.verbose) console.log("Indexed package.json optional dependency `" + moduleName + "`.");
                        }

                        // Add dependency to be checked recursively.
                        if (opts.recursePackageJSONOptDeps) {
                            toCheck.push(modulePathAbsolute);
                        }

                    }
                }

                return true; //NOTE: Because this is a filtering function and the lookup would onlt stop at true. And we do want the very closest one.
            });
        }

        // Parse file body for requires.

        if (opts.parseRequires) {

            var input = file.contents.toString('utf-8');

            var regex = /\brequire\(([^\)]*)\)/g;

            var matchObject;
            while (matchObject = regex.exec(input)) {

                var fullMatch = matchObject[0];
                var match = matchObject[1];

                try {

                    // Evaluate and "clean" module name.
                    var moduleName = eval(match);

                    if (resolve.isCore(moduleName)) {
                        if (opts.indexCoreModules) {
                            // Make path absolute.
                            if (typeof deps[basedir] !== typeof {}) deps[basedir] = {};
                            deps[basedir][moduleName] = moduleName;
                            if (opts.verbose) console.log("Indexed core module `" + moduleName + "`.");
                        } else {
                            // Throw a fit if module is core to Node.
                            throw "Core modules do not run in the browser!";
                        }
                    }
                    else {

                        // Else continue.
                        // Check if module was required by path.
                        var requiredByPath = /^(?:\.{0,2})\//.test(moduleName);

                        // Check whether to parse path'd modules.
                        if (!opts.recurseRequiresByPath && requiredByPath) {
                            throw "Will not parse modules required by path.";
                        }

                        // Resolve module.
                        var modulePathLocal = resolve.sync(moduleName, {
                            basedir: basedir
                        });
                        // Make path absolute.
                        var modulePathAbsolute = path.resolve(modulePathLocal);

                        // Add resolution to index of module wasn't required in path form.
                        if (opts.indexRequiresByName && (opts.indexRequiresByPath || !requiredByPath)) {
                            if (path.resolve(file.path) != modulePathAbsolute) {
                                if (typeof deps[basedir] !== typeof {}) deps[basedir] = {};
                                deps[basedir][moduleName] = path.relative(opts.offsetPath, modulePathAbsolute);
                                if (opts.verbose) console.log("Indexed required module `" + moduleName + "`.");
                            }
                        }
                        else {
                            if (opts.verbose) console.log("Did not index required module `" + moduleName + "`.");
                        }

                        // Add dependency to be checked recursively.
                        if (toCheck.indexOf(modulePathAbsolute) <= -1) {
                            toCheck.push(modulePathAbsolute);
                            if (opts.verbose) console.log("Will not parse path dependency " + moduleName + "`.");
                        }

                    }

                }
                catch (e) {
                    console.error("Could not resolve `" + match + "`: " + (e.toString()));
                }

            }

        }

        var modulePathAbsolute = toCheck.shift();
        while (modulePathAbsolute) {
            checkByModule(modulePathAbsolute);
            modulePathAbsolute = toCheck.shift();
        }

    };

    // Shortcut for checking by filepath or module name.
    var checkByModule = function(name) {

        // Resolve absolute module path.
        var filePathAbsolute = path.resolve(resolve.sync(name, {
            basedir: __dirname
        }));

        // Check if absolute filepath has not already been checked.
        if (checked.indexOf(filePathAbsolute) <= -1) {
            // Add absolute filepath to checked list.
            checked.push(filePathAbsolute);
            // Parse for dependencies.
            checkByFile(new File({
                cwd: process.cwd(),
                base: path.dirname(filePathAbsolute),
                path: filePathAbsolute,
                contents: fs.readFileSync(filePathAbsolute)
            }));
        }

        // Verbose log for files checked for requires.
        if (opts.verbose) {
            console.log("Parsing dependency `" + name + "`.");
        }

        // Return the resolution map.
        return deps;

    };

    // Exports.
    checkByModule.opts = opts;
    checkByModule.checkByFile = checkByFile;
    module.exports = checkByModule;

    // Run from command-line.
    if (require.main === module) {
        var args = require('yargs').argv._;
        for (var i = 0; i < args.length; i++) {
            var infile = args[i];
            console.log(checkByModule(infile));
        }
    }

}).call(this);<commit_msg>Implemented passing opts into the API.<commit_after>#!/usr/bin/env node

(function() {

    var fs = require('fs');
    var path = require('path');
    var resolve = require('resolve');

    var File = require('vinyl'); // The module file to be checked.

    var deps = {}; // The dependency tree being resolved.
    var checked = []; // List of modules already checked.
    var toCheck = []; // List of modules to parse next.

    var defaultOpts = {
        parseRequires: true, // Naively parses source for require statements.
        indexCoreModules: false, //Whether to index core modules or skip them.
        indexPackageJSONDeps: true, // Indexes dependencies in pacakge.json
        indexPackageJSONOptDeps: true, // Indexes optional dependencies in pacakge.json
        indexPac: true, // Indexes dependencies in pacakge.json
        indexRequiresByName: true, // Indexes parsed dependencies required by name.
        indexRequiresByPath: false, // Indexes parsed dependencies required by path.
        recursePackageJSONDeps: true, // Recurse through package.json dependencies.
        recursePackageJSONOptDeps: true, // Recurse through package.json optional dependencies.
        recurseRequiresByPath: true, // Recurse through parsed dependencies required by path.
        verbose: false, // Print logging info.
        limit: 1000000, // Maximum number of modules checked recursively.
                        // Setting this to `1` stops the recursion at checking only the given module's dependencies.
                        // But this isn't really a recursion counter, as all dependencies beyond the first level count towards the limit individually.
        offsetPath: __dirname // All resolved modules are made relative to this path.
    };

    // Parse opts.
    var parseOpts = function(opts) {
        var o = {};
        for ( var key in defaultOpts ) {
            if ( typeof opts === typeof {} && opts[key] !== undefined ) {
                o[key] = opts[key];
            } else {
                o[key] = defaultOpts[key];
            }
        }
        return o;
    ;}

    // Actual logic for parsing files.
    var checkByFile = function( file, opts ) {

        // Parse opts.
        var opts = parseOpts(opts);

        // Check for the "recursion" limit.
        if (opts.limit >= 0) {
            opts.limit--;
        }
        else {
            throw "Recursion limit reached.";
        }

        var basedir = path.resolve(path.dirname(file.path));

        // Parse package.json.
        if ( opts.indexPackageJSONDeps || opts.indexPackageJSONOptDeps || opts.recursePackageJSONDeps || opts.recursePackageJSONOptDeps ) {
            require('closest-package').sync(basedir, function(json, filename) {

                if ( opts.indexPackageJSONDeps || opts.recursePackageJSONDeps ) {
                    for (var moduleName in json.dependencies) {

                        // Resolve module path.
                        var modulePathLocal = resolve.sync(moduleName, {
                            basedir: basedir
                        });
                        // Make path absolute.
                        var modulePathAbsolute = path.resolve(modulePathLocal);

                        // Add resolution to output.
                        if (opts.indexPackageJSONDeps) {
                            if (typeof deps[basedir] !== typeof {}) deps[basedir] = {};
                            deps[basedir][moduleName] = path.relative(opts.offsetPath, modulePathAbsolute);
                            if (opts.verbose) console.log("Indexed package.json dependency `" + moduleName + "`.");
                        }

                        // Add dependency to be checked recursively.
                        if (opts.recursePackageJSONDeps) {
                            toCheck.push(modulePathAbsolute);
                        }

                    }
                }

                if ( opts.indexPackageJSONOptDeps || opts.recursePackageJSONOptDeps ) {
                    for (var moduleName in json.optionalDependencies) {

                        // Resolve module path.
                        var modulePathLocal = resolve.sync(moduleName, {
                            basedir: basedir
                        });
                        // Make path absolute.
                        var modulePathAbsolute = path.resolve(modulePathLocal);

                        // Add resolution to output.
                        if (opts.indexPackageJSONOptDeps) {
                            if (typeof deps[basedir] !== typeof {}) deps[basedir] = {};
                            deps[basedir][moduleName] = path.relative(opts.offsetPath, modulePathAbsolute);
                            if (opts.verbose) console.log("Indexed package.json optional dependency `" + moduleName + "`.");
                        }

                        // Add dependency to be checked recursively.
                        if (opts.recursePackageJSONOptDeps) {
                            toCheck.push(modulePathAbsolute);
                        }

                    }
                }

                return true; //NOTE: Because this is a filtering function and the lookup would onlt stop at true. And we do want the very closest one.
            });
        }

        // Parse file body for requires.

        if (opts.parseRequires) {

            var input = file.contents.toString('utf-8');

            var regex = /\brequire\(([^\)]*)\)/g;

            var matchObject;
            while (matchObject = regex.exec(input)) {

                var fullMatch = matchObject[0];
                var match = matchObject[1];

                try {

                    // Evaluate and "clean" module name.
                    var moduleName = eval(match);

                    if (resolve.isCore(moduleName)) {
                        if (opts.indexCoreModules) {
                            // Make path absolute.
                            if (typeof deps[basedir] !== typeof {}) deps[basedir] = {};
                            deps[basedir][moduleName] = moduleName;
                            if (opts.verbose) console.log("Indexed core module `" + moduleName + "`.");
                        } else {
                            // Throw a fit if module is core to Node.
                            throw "Core modules do not run in the browser!";
                        }
                    }
                    else {

                        // Else continue.
                        // Check if module was required by path.
                        var requiredByPath = /^(?:\.{0,2})\//.test(moduleName);

                        // Check whether to parse path'd modules.
                        if (!opts.recurseRequiresByPath && requiredByPath) {
                            throw "Will not parse modules required by path.";
                        }

                        // Resolve module.
                        var modulePathLocal = resolve.sync(moduleName, {
                            basedir: basedir
                        });
                        // Make path absolute.
                        var modulePathAbsolute = path.resolve(modulePathLocal);

                        // Add resolution to index of module wasn't required in path form.
                        if (opts.indexRequiresByName && (opts.indexRequiresByPath || !requiredByPath)) {
                            if (path.resolve(file.path) != modulePathAbsolute) {
                                if (typeof deps[basedir] !== typeof {}) deps[basedir] = {};
                                deps[basedir][moduleName] = path.relative(opts.offsetPath, modulePathAbsolute);
                                if (opts.verbose) console.log("Indexed required module `" + moduleName + "`.");
                            }
                        }
                        else {
                            if (opts.verbose) console.log("Did not index required module `" + moduleName + "`.");
                        }

                        // Add dependency to be checked recursively.
                        if (toCheck.indexOf(modulePathAbsolute) <= -1) {
                            toCheck.push(modulePathAbsolute);
                            if (opts.verbose) console.log("Will not parse path dependency " + moduleName + "`.");
                        }

                    }

                }
                catch (e) {
                    console.error("Could not resolve `" + match + "`: " + (e.toString()));
                }

            }

        }

        var modulePathAbsolute = toCheck.shift();
        while (modulePathAbsolute) {
            checkByModule( modulePathAbsolute, opts );
            modulePathAbsolute = toCheck.shift();
        }

    };

    // Shortcut for checking by filepath or module name.
    var checkByModule = function( name, opts ) {

        // Parse opts.
        var opts = parseOpts(opts);

        // Resolve absolute module path.
        var filePathAbsolute = path.resolve(resolve.sync(name, {
            basedir: __dirname
        }));

        // Check if absolute filepath has not already been checked.
        if (checked.indexOf(filePathAbsolute) <= -1) {
            // Add absolute filepath to checked list.
            checked.push(filePathAbsolute);
            // Parse for dependencies.
            checkByFile(new File({
                cwd: process.cwd(),
                base: path.dirname(filePathAbsolute),
                path: filePathAbsolute,
                contents: fs.readFileSync(filePathAbsolute)
            }), opts);
        }

        // Verbose log for files checked for requires.
        if (opts.verbose) {
            console.log("Parsing dependency `" + name + "`.");
        }

        // Return the resolution map.
        return deps;

    };

    // Exports.
    checkByModule.defaultOpts = defaultOpts;
    checkByModule.checkByFile = checkByFile;
    module.exports = checkByModule;

    // Run from command-line.
    if (require.main === module) {
        var opts;
        var args = require('yargs').argv._;
        for (var i = 0; i < args.length; i++) {
            var infile = args[i];
            console.log(checkByModule( infile, opts ));
        }
    }

}).call(this);<|endoftext|>