<commit_before>"use strict";

const gulp = require("gulp");
const run = require("gulp-run");
const runSequence = require("run-sequence");
const del = require("del");
const path = require("path");
const fs = require("fs");

const outputDir = "./wwwroot/dist";
global.aot = true;

function getEnvOptions() {
    const options = [];
    if (global.prod) {
        options.push("--env.prod");
    }
    if (global.analyse) {
        options.push("--env.analyse");
    }
    if (global.aot) {
        options.push("--env.aot");
    }
    if (options.length > 0) {
        return " " + options.join(" ");
    } else {
        return "";
    }
}

function webpack(type) {
    return run(`webpack --config webpack.config${type ? `.${type}` : ""}.ts${getEnvOptions()}`).exec();
}

gulp.task("vendor", () => {
    let build = false;
    const vendorPath = path.join(outputDir, "vendor.js");
    const vendorExists = fs.existsSync(vendorPath);
    if (vendorExists) {
        const vendorStat = fs.statSync(vendorPath);
        const packageStat = fs.statSync("package.json");
        const vendorConfigStat = fs.statSync("webpack.config.vendor.ts");
        const commonConfigStat = fs.statSync("webpack.config.common.ts");
        if (packageStat.mtime > vendorStat.mtime) {
            build = true;
        }
        if (vendorConfigStat.mtime > vendorStat.mtime) {
            build = true;
        }
        if (commonConfigStat.mtime > vendorStat.mtime) {
            build = true;
        }
    } else {
        build = true;
    }
    if (build) {
        return webpack("vendor");
    }
});

gulp.task("vendor_force", () => {
    return webpack("vendor");
})

gulp.task("main", () => {
    return webpack()
});

gulp.task("prod_var", () => {
    global.prod = true;
})

gulp.task("analyse_var", () => {
    global.analyse = true;
})

gulp.task("clean", () => {
    del.sync(outputDir, { force: true });
});

gulp.task("test_compile", function () {
    return webpack("test");
});

gulp.task("test_run", function () {
    return run("karma start ClientApp/test/karma.conf.js").exec();
});

gulp.task("lint", () => run("npm run lint").exec());
gulp.task("lint_fix", () => run("npm run lint -- --fix").exec());
gulp.task("test", callback => runSequence("test_compile", "test_run", callback));
gulp.task("build", callback => runSequence("vendor", "main", callback));
gulp.task("analyse", callback => runSequence("analyse_var", "clean", "build", callback));
gulp.task("full", callback => runSequence("clean", "build", callback));
gulp.task("publish", callback => runSequence("prod_var", "full", callback));<commit_msg>Move test task<commit_after>"use strict";

const gulp = require("gulp");
const run = require("gulp-run");
const runSequence = require("run-sequence");
const del = require("del");
const path = require("path");
const fs = require("fs");

const outputDir = "./wwwroot/dist";
global.aot = true;

function getEnvOptions() {
    const options = [];
    if (global.prod) {
        options.push("--env.prod");
    }
    if (global.analyse) {
        options.push("--env.analyse");
    }
    if (global.aot) {
        options.push("--env.aot");
    }
    if (options.length > 0) {
        return " " + options.join(" ");
    } else {
        return "";
    }
}

function webpack(type) {
    return run(`webpack --config webpack.config${type ? `.${type}` : ""}.ts${getEnvOptions()}`).exec();
}

gulp.task("vendor", () => {
    let build = false;
    const vendorPath = path.join(outputDir, "vendor.js");
    const vendorExists = fs.existsSync(vendorPath);
    if (vendorExists) {
        const vendorStat = fs.statSync(vendorPath);
        const packageStat = fs.statSync("package.json");
        const vendorConfigStat = fs.statSync("webpack.config.vendor.ts");
        const commonConfigStat = fs.statSync("webpack.config.common.ts");
        if (packageStat.mtime > vendorStat.mtime) {
            build = true;
        }
        if (vendorConfigStat.mtime > vendorStat.mtime) {
            build = true;
        }
        if (commonConfigStat.mtime > vendorStat.mtime) {
            build = true;
        }
    } else {
        build = true;
    }
    if (build) {
        return webpack("vendor");
    }
});

gulp.task("vendor_force", () => {
    return webpack("vendor");
})

gulp.task("main", () => {
    return webpack()
});

gulp.task("prod_var", () => {
    global.prod = true;
})

gulp.task("analyse_var", () => {
    global.analyse = true;
})

gulp.task("clean", () => {
    del.sync(outputDir, { force: true });
});

gulp.task("test_compile", function () {
    return webpack("test");
});

gulp.task("test_run", function () {
    return run("karma start ClientApp/test/karma.conf.js").exec();
});

gulp.task("test", callback => runSequence("test_compile", "test_run", callback));
gulp.task("lint", () => run("npm run lint").exec());
gulp.task("lint_fix", () => run("npm run lint -- --fix").exec());
gulp.task("build", callback => runSequence("vendor", "main", callback));
gulp.task("analyse", callback => runSequence("analyse_var", "clean", "build", callback));
gulp.task("full", callback => runSequence("clean", "build", callback));
gulp.task("publish", callback => runSequence("prod_var", "full", callback));<|endoftext|>


<commit_before>"use strict";

const {strict: assert} = require("assert");

const {set_global, zrequire} = require("../zjsunit/namespace");
const {make_stub} = require("../zjsunit/stub");
const {run_test} = require("../zjsunit/test");

const util = zrequire("util");
const people = zrequire("people");
const message_store = zrequire("message_store");

const noop = function () {};

set_global("document", "document-stub");

set_global("stream_topic_history", {
    add_message: noop,
});

set_global("recent_senders", {
    process_message_for_senders: noop,
});

set_global("page_params", {
    realm_allow_message_editing: true,
    is_admin: true,
});

const denmark = {
    subscribed: false,
    name: "Denmark",
    stream_id: 20,
};

const devel = {
    subscribed: true,
    name: "Devel",
    stream_id: 21,
};

const me = {
    email: "me@example.com",
    user_id: 101,
    full_name: "Me Myself",
};

const alice = {
    email: "alice@example.com",
    user_id: 102,
    full_name: "Alice",
};

const bob = {
    email: "bob@example.com",
    user_id: 103,
    full_name: "Bob",
};

const cindy = {
    email: "cindy@example.com",
    user_id: 104,
    full_name: "Cindy",
};

const denise = {
    email: "denise@example.com",
    user_id: 105,
    full_name: "Denise ",
};

people.add_active_user(me);
people.add_active_user(alice);
people.add_active_user(bob);
people.add_active_user(cindy);
people.add_active_user(denise);

people.initialize_current_user(me.user_id);

function convert_recipients(people) {
    // Display_recipient uses `id` for user_ids.
    return people.map((p) => ({
        email: p.email,
        id: p.user_id,
        full_name: p.full_name,
    }));
}

run_test("add_message_metadata", () => {
    let message = {
        sender_email: "me@example.com",
        sender_id: me.user_id,
        type: "private",
        display_recipient: convert_recipients([me, bob, cindy]),
        flags: ["has_alert_word"],
        is_me_message: false,
        id: 2067,
    };
    message_store.set_message_booleans(message);
    message_store.add_message_metadata(message);

    assert.deepEqual(message_store.user_ids().sort(), [me.user_id, bob.user_id, cindy.user_id]);

    assert.equal(message.is_private, true);
    assert.equal(message.reply_to, "bob@example.com,cindy@example.com");
    assert.equal(message.to_user_ids, "103,104");
    assert.equal(message.display_reply_to, "Bob, Cindy");
    assert.equal(message.alerted, true);
    assert.equal(message.is_me_message, false);

    let retrieved_message = message_store.get(2067);
    assert.equal(retrieved_message, message);

    blueslip.expect("error", "message_store got non-number: 2067");
    retrieved_message = message_store.get("2067");
    assert.equal(retrieved_message, message);

    // access cached previous message, and test match subject/content
    message = {
        id: 2067,
        match_subject: "topic foo",
        match_content: "bar content",
    };
    message = message_store.add_message_metadata(message);

    assert.equal(message.reply_to, "bob@example.com,cindy@example.com");
    assert.equal(message.to_user_ids, "103,104");
    assert.equal(message.display_reply_to, "Bob, Cindy");
    assert.equal(util.get_match_topic(message), "topic foo");
    assert.equal(message.match_content, "bar content");

    message = {
        sender_email: denise.email,
        sender_id: denise.user_id,
        type: "stream",
        display_recipient: "Zoolippy",
        topic: "cool thing",
        subject: "the_subject",
        id: 2068,
    };

    message_store.set_message_booleans(message);
    message_store.add_message_metadata(message);
    assert.deepEqual(message.stream, message.display_recipient);
    assert.equal(message.reply_to, "denise@example.com");
    assert.deepEqual(message.flags, undefined);
    assert.equal(message.alerted, false);

    assert.deepEqual(message_store.user_ids().sort(), [
        me.user_id,
        bob.user_id,
        cindy.user_id,
        denise.user_id,
    ]);
});

run_test("message_booleans_parity", () => {
    // We have two code paths that update/set message booleans.
    // This test asserts that both have identical behavior for the
    // flags common between them.
    const assert_bool_match = (flags, expected_message) => {
        const set_message = {topic: "set_message_booleans", flags};
        const update_message = {topic: "update_booleans"};
        message_store.set_message_booleans(set_message);
        message_store.update_booleans(update_message, flags);
        for (const key of Object.keys(expected_message)) {
            assert.equal(
                set_message[key],
                expected_message[key],
                `'${key}' != ${expected_message[key]}`,
            );
            assert.equal(update_message[key], expected_message[key]);
        }
        assert.equal(set_message.topic, "set_message_booleans");
        assert.equal(update_message.topic, "update_booleans");
    };

    assert_bool_match(["wildcard_mentioned"], {
        mentioned: true,
        mentioned_me_directly: false,
        alerted: false,
    });

    assert_bool_match(["mentioned"], {
        mentioned: true,
        mentioned_me_directly: true,
        alerted: false,
    });

    assert_bool_match(["has_alert_word"], {
        mentioned: false,
        mentioned_me_directly: false,
        alerted: true,
    });
});

run_test("errors", () => {
    // Test a user that doesn't exist
    let message = {
        type: "private",
        display_recipient: [{id: 92714}],
    };

    blueslip.expect("error", "Unknown user_id in get_by_user_id: 92714", 2);
    blueslip.expect("error", "Unknown user id 92714", 2); // From person.js

    // Expect each to throw two blueslip errors
    // One from message_store.js, one from person.js
    const emails = message_store.get_pm_emails(message);
    assert.equal(emails, "?");

    const names = message_store.get_pm_full_names(message);
    assert.equal(names, "?");

    message = {
        type: "stream",
        display_recipient: [{}],
    };

    // This should early return and not run pm_conversation.set_partner
    let num_partner = 0;
    set_global("pm_conversation", {
        set_partner() {
            num_partner += 1;
        },
    });
    message_store.process_message_for_recent_private_messages(message);
    assert.equal(num_partner, 0);
});

run_test("update_booleans", () => {
    const message = {};

    // First, test fields that we do actually want to update.
    message.mentioned = false;
    message.mentioned_me_directly = false;
    message.alerted = false;

    let flags = ["mentioned", "has_alert_word", "read"];
    message_store.update_booleans(message, flags);
    assert.equal(message.mentioned, true);
    assert.equal(message.mentioned_me_directly, true);
    assert.equal(message.alerted, true);

    flags = ["wildcard_mentioned", "unread"];
    message_store.update_booleans(message, flags);
    assert.equal(message.mentioned, true);
    assert.equal(message.mentioned_me_directly, false);

    flags = ["read"];
    message_store.update_booleans(message, flags);
    assert.equal(message.mentioned, false);
    assert.equal(message.mentioned_me_directly, false);
    assert.equal(message.alerted, false);

    // Make sure we don't muck with unread.
    message.unread = false;
    flags = [""];
    message_store.update_booleans(message, flags);
    assert.equal(message.unread, false);

    message.unread = true;
    flags = ["read"];
    message_store.update_booleans(message, flags);
    assert.equal(message.unread, true);
});

run_test("update_property", () => {
    const message1 = {
        type: "stream",
        sender_full_name: alice.full_name,
        sender_id: alice.user_id,
        small_avatar_url: "alice_url",
        stream_id: devel.stream_id,
        stream: devel.name,
        display_recipient: devel.name,
        id: 100,
    };
    const message2 = {
        type: "stream",
        sender_full_name: bob.full_name,
        sender_id: bob.user_id,
        small_avatar_url: "bob_url",
        stream_id: denmark.stream_id,
        stream: denmark.name,
        display_recipient: denmark.name,
        id: 101,
    };
    for (const message of [message1, message2]) {
        message_store.set_message_booleans(message);
        message_store.add_message_metadata(message);
    }

    assert.equal(message1.sender_full_name, alice.full_name);
    assert.equal(message2.sender_full_name, bob.full_name);
    message_store.update_property("sender_full_name", "Bobby", {user_id: bob.user_id});
    assert.equal(message1.sender_full_name, alice.full_name);
    assert.equal(message2.sender_full_name, "Bobby");

    assert.equal(message1.small_avatar_url, "alice_url");
    assert.equal(message2.small_avatar_url, "bob_url");
    message_store.update_property("small_avatar_url", "bobby_url", {user_id: bob.user_id});
    assert.equal(message1.small_avatar_url, "alice_url");
    assert.equal(message2.small_avatar_url, "bobby_url");

    assert.equal(message1.stream, devel.name);
    assert.equal(message1.display_recipient, devel.name);
    assert.equal(message2.stream, denmark.name);
    assert.equal(message2.display_recipient, denmark.name);
    message_store.update_property("stream_name", "Prod", {stream_id: devel.stream_id});
    assert.equal(message1.stream, "Prod");
    assert.equal(message1.display_recipient, "Prod");
    assert.equal(message2.stream, denmark.name);
    assert.equal(message2.display_recipient, denmark.name);
});

run_test("each", () => {
    message_store.each((message) => {
        assert(message.alerted !== undefined);
    });
});

run_test("message_id_change", () => {
    const message = {
        sender_email: "me@example.com",
        sender_id: me.user_id,
        type: "private",
        display_recipient: convert_recipients([me, bob, cindy]),
        flags: ["has_alert_word"],
        id: 401,
    };
    message_store.add_message_metadata(message);

    set_global("pointer", {
        furthest_read: 401,
        set_furthest_read(value) {
            this.furthest_read = value;
        },
    });

    set_global("message_list", {});
    set_global("home_msg_list", {});

    const opts = {
        old_id: 401,
        new_id: 402,
    };

    {
        const stub = make_stub();
        home_msg_list.change_message_id = stub.f;
        message_store.reify_message_id(opts);
        assert.equal(stub.num_calls, 1);
        const msg_id = stub.get_args("old", "new");
        assert.equal(msg_id.old, 401);
        assert.equal(msg_id.new, 402);
    }

    home_msg_list.view = {};
    {
        const stub = make_stub();
        home_msg_list.view.change_message_id = stub.f;
        message_store.reify_message_id(opts);
        assert.equal(stub.num_calls, 1);
        const msg_id = stub.get_args("old", "new");
        assert.equal(msg_id.old, 401);
        assert.equal(msg_id.new, 402);
    }
});

run_test("errors", () => {
    blueslip.expect("error", "message_store.get got bad value: undefined");
    message_store.get(undefined);
});
<commit_msg>node_tests: Fix misspelled pm_conversation global.<commit_after>"use strict";

const {strict: assert} = require("assert");

const {set_global, with_field, zrequire} = require("../zjsunit/namespace");
const {make_stub} = require("../zjsunit/stub");
const {run_test} = require("../zjsunit/test");

const util = zrequire("util");
const people = zrequire("people");
const pm_conversations = zrequire("pm_conversations");
const message_store = zrequire("message_store");

const noop = function () {};

set_global("document", "document-stub");

set_global("stream_topic_history", {
    add_message: noop,
});

set_global("recent_senders", {
    process_message_for_senders: noop,
});

set_global("page_params", {
    realm_allow_message_editing: true,
    is_admin: true,
});

const denmark = {
    subscribed: false,
    name: "Denmark",
    stream_id: 20,
};

const devel = {
    subscribed: true,
    name: "Devel",
    stream_id: 21,
};

const me = {
    email: "me@example.com",
    user_id: 101,
    full_name: "Me Myself",
};

const alice = {
    email: "alice@example.com",
    user_id: 102,
    full_name: "Alice",
};

const bob = {
    email: "bob@example.com",
    user_id: 103,
    full_name: "Bob",
};

const cindy = {
    email: "cindy@example.com",
    user_id: 104,
    full_name: "Cindy",
};

const denise = {
    email: "denise@example.com",
    user_id: 105,
    full_name: "Denise ",
};

people.add_active_user(me);
people.add_active_user(alice);
people.add_active_user(bob);
people.add_active_user(cindy);
people.add_active_user(denise);

people.initialize_current_user(me.user_id);

function convert_recipients(people) {
    // Display_recipient uses `id` for user_ids.
    return people.map((p) => ({
        email: p.email,
        id: p.user_id,
        full_name: p.full_name,
    }));
}

run_test("add_message_metadata", () => {
    let message = {
        sender_email: "me@example.com",
        sender_id: me.user_id,
        type: "private",
        display_recipient: convert_recipients([me, bob, cindy]),
        flags: ["has_alert_word"],
        is_me_message: false,
        id: 2067,
    };
    message_store.set_message_booleans(message);
    message_store.add_message_metadata(message);

    assert.deepEqual(message_store.user_ids().sort(), [me.user_id, bob.user_id, cindy.user_id]);

    assert.equal(message.is_private, true);
    assert.equal(message.reply_to, "bob@example.com,cindy@example.com");
    assert.equal(message.to_user_ids, "103,104");
    assert.equal(message.display_reply_to, "Bob, Cindy");
    assert.equal(message.alerted, true);
    assert.equal(message.is_me_message, false);

    let retrieved_message = message_store.get(2067);
    assert.equal(retrieved_message, message);

    blueslip.expect("error", "message_store got non-number: 2067");
    retrieved_message = message_store.get("2067");
    assert.equal(retrieved_message, message);

    // access cached previous message, and test match subject/content
    message = {
        id: 2067,
        match_subject: "topic foo",
        match_content: "bar content",
    };
    message = message_store.add_message_metadata(message);

    assert.equal(message.reply_to, "bob@example.com,cindy@example.com");
    assert.equal(message.to_user_ids, "103,104");
    assert.equal(message.display_reply_to, "Bob, Cindy");
    assert.equal(util.get_match_topic(message), "topic foo");
    assert.equal(message.match_content, "bar content");

    message = {
        sender_email: denise.email,
        sender_id: denise.user_id,
        type: "stream",
        display_recipient: "Zoolippy",
        topic: "cool thing",
        subject: "the_subject",
        id: 2068,
    };

    message_store.set_message_booleans(message);
    message_store.add_message_metadata(message);
    assert.deepEqual(message.stream, message.display_recipient);
    assert.equal(message.reply_to, "denise@example.com");
    assert.deepEqual(message.flags, undefined);
    assert.equal(message.alerted, false);

    assert.deepEqual(message_store.user_ids().sort(), [
        me.user_id,
        bob.user_id,
        cindy.user_id,
        denise.user_id,
    ]);
});

run_test("message_booleans_parity", () => {
    // We have two code paths that update/set message booleans.
    // This test asserts that both have identical behavior for the
    // flags common between them.
    const assert_bool_match = (flags, expected_message) => {
        const set_message = {topic: "set_message_booleans", flags};
        const update_message = {topic: "update_booleans"};
        message_store.set_message_booleans(set_message);
        message_store.update_booleans(update_message, flags);
        for (const key of Object.keys(expected_message)) {
            assert.equal(
                set_message[key],
                expected_message[key],
                `'${key}' != ${expected_message[key]}`,
            );
            assert.equal(update_message[key], expected_message[key]);
        }
        assert.equal(set_message.topic, "set_message_booleans");
        assert.equal(update_message.topic, "update_booleans");
    };

    assert_bool_match(["wildcard_mentioned"], {
        mentioned: true,
        mentioned_me_directly: false,
        alerted: false,
    });

    assert_bool_match(["mentioned"], {
        mentioned: true,
        mentioned_me_directly: true,
        alerted: false,
    });

    assert_bool_match(["has_alert_word"], {
        mentioned: false,
        mentioned_me_directly: false,
        alerted: true,
    });
});

run_test("errors", () => {
    // Test a user that doesn't exist
    let message = {
        type: "private",
        display_recipient: [{id: 92714}],
    };

    blueslip.expect("error", "Unknown user_id in get_by_user_id: 92714", 2);
    blueslip.expect("error", "Unknown user id 92714", 2); // From person.js

    // Expect each to throw two blueslip errors
    // One from message_store.js, one from person.js
    const emails = message_store.get_pm_emails(message);
    assert.equal(emails, "?");

    const names = message_store.get_pm_full_names(message);
    assert.equal(names, "?");

    message = {
        type: "stream",
        display_recipient: [{}],
    };

    // This should early return and not run pm_conversations.set_partner
    with_field(
        pm_conversations,
        "set_partner",
        () => assert(false),
        () => {
            message_store.process_message_for_recent_private_messages(message);
        },
    );
});

run_test("update_booleans", () => {
    const message = {};

    // First, test fields that we do actually want to update.
    message.mentioned = false;
    message.mentioned_me_directly = false;
    message.alerted = false;

    let flags = ["mentioned", "has_alert_word", "read"];
    message_store.update_booleans(message, flags);
    assert.equal(message.mentioned, true);
    assert.equal(message.mentioned_me_directly, true);
    assert.equal(message.alerted, true);

    flags = ["wildcard_mentioned", "unread"];
    message_store.update_booleans(message, flags);
    assert.equal(message.mentioned, true);
    assert.equal(message.mentioned_me_directly, false);

    flags = ["read"];
    message_store.update_booleans(message, flags);
    assert.equal(message.mentioned, false);
    assert.equal(message.mentioned_me_directly, false);
    assert.equal(message.alerted, false);

    // Make sure we don't muck with unread.
    message.unread = false;
    flags = [""];
    message_store.update_booleans(message, flags);
    assert.equal(message.unread, false);

    message.unread = true;
    flags = ["read"];
    message_store.update_booleans(message, flags);
    assert.equal(message.unread, true);
});

run_test("update_property", () => {
    const message1 = {
        type: "stream",
        sender_full_name: alice.full_name,
        sender_id: alice.user_id,
        small_avatar_url: "alice_url",
        stream_id: devel.stream_id,
        stream: devel.name,
        display_recipient: devel.name,
        id: 100,
    };
    const message2 = {
        type: "stream",
        sender_full_name: bob.full_name,
        sender_id: bob.user_id,
        small_avatar_url: "bob_url",
        stream_id: denmark.stream_id,
        stream: denmark.name,
        display_recipient: denmark.name,
        id: 101,
    };
    for (const message of [message1, message2]) {
        message_store.set_message_booleans(message);
        message_store.add_message_metadata(message);
    }

    assert.equal(message1.sender_full_name, alice.full_name);
    assert.equal(message2.sender_full_name, bob.full_name);
    message_store.update_property("sender_full_name", "Bobby", {user_id: bob.user_id});
    assert.equal(message1.sender_full_name, alice.full_name);
    assert.equal(message2.sender_full_name, "Bobby");

    assert.equal(message1.small_avatar_url, "alice_url");
    assert.equal(message2.small_avatar_url, "bob_url");
    message_store.update_property("small_avatar_url", "bobby_url", {user_id: bob.user_id});
    assert.equal(message1.small_avatar_url, "alice_url");
    assert.equal(message2.small_avatar_url, "bobby_url");

    assert.equal(message1.stream, devel.name);
    assert.equal(message1.display_recipient, devel.name);
    assert.equal(message2.stream, denmark.name);
    assert.equal(message2.display_recipient, denmark.name);
    message_store.update_property("stream_name", "Prod", {stream_id: devel.stream_id});
    assert.equal(message1.stream, "Prod");
    assert.equal(message1.display_recipient, "Prod");
    assert.equal(message2.stream, denmark.name);
    assert.equal(message2.display_recipient, denmark.name);
});

run_test("each", () => {
    message_store.each((message) => {
        assert(message.alerted !== undefined);
    });
});

run_test("message_id_change", () => {
    const message = {
        sender_email: "me@example.com",
        sender_id: me.user_id,
        type: "private",
        display_recipient: convert_recipients([me, bob, cindy]),
        flags: ["has_alert_word"],
        id: 401,
    };
    message_store.add_message_metadata(message);

    set_global("pointer", {
        furthest_read: 401,
        set_furthest_read(value) {
            this.furthest_read = value;
        },
    });

    set_global("message_list", {});
    set_global("home_msg_list", {});

    const opts = {
        old_id: 401,
        new_id: 402,
    };

    {
        const stub = make_stub();
        home_msg_list.change_message_id = stub.f;
        message_store.reify_message_id(opts);
        assert.equal(stub.num_calls, 1);
        const msg_id = stub.get_args("old", "new");
        assert.equal(msg_id.old, 401);
        assert.equal(msg_id.new, 402);
    }

    home_msg_list.view = {};
    {
        const stub = make_stub();
        home_msg_list.view.change_message_id = stub.f;
        message_store.reify_message_id(opts);
        assert.equal(stub.num_calls, 1);
        const msg_id = stub.get_args("old", "new");
        assert.equal(msg_id.old, 401);
        assert.equal(msg_id.new, 402);
    }
});

run_test("errors", () => {
    blueslip.expect("error", "message_store.get got bad value: undefined");
    message_store.get(undefined);
});
<|endoftext|>


<commit_before>import {badRequest, notFound} from 'boom'
import Joi from 'joi'
import Logger from '@modulus/logger'

import Job from '../models/job'

let logger = Logger('handlers/job')

export default {

  /////////// Job.create \\\\\\\\\\
  create: {
    validate: {
      payload: {
        employer: Joi.string().required(),
        location: {
          city: Joi.string(),
          state: Joi.string()
        },
        dates: {
          start: Joi.string().required(),
          end: Joi.string()
        },
        title: Joi.string().required(),
        tasks: Joi.array()
      }
    },
    handler: function (request, reply) {
      let {employer, location, dates, tasks, title} = request.payload

      let newJob =  {
        employer: employer,
        location: {
          city: location.city,
          state: location.state
        },
        dates: {
          start: dates.start,
          end: dates.end
        },
        title: title,
        tasks: tasks
      }

      new Job(newJob).save((err, created) => {
        if (err) {
          logger.error(`Job.create error: ${err.message}`)
          return reply(badRequest(err.message))
        }

        logger.debug(`Job.create saved ${JSON.stringify(created)}`)
        reply(created)
      })
    }
  },

  ////////// Job.get \\\\\\\\\\
  get: {
    validate: {
      params: {
        id: Joi.string().required()
      }
    },
    handler: function (request, reply) {
      Job.findOne({ id: request.params.id }, (err, job) => {
        if (err) {
          logger.error(`Job.findOne error: ${err.message}`)
          return reply(badRequest(err.message))
        }

        logger.debug(`Job.findOne found ${JSON.stringify(job)}`)
        reply(job)
      })
    }
  },

  ////////// Job.getAll \\\\\\\\\\
  getAll: {
    handler: function (request, reply) {
      Job.find({}, (err, jobs) => {
        if (err) {
          logger.error(`Job.find error: ${err.message}`)
          return reply(badRequest(err.message))
        }

        logger.debug(`Job.find found ${JSON.stringify(jobs)}`)
        reply(jobs)
      })
    }
  },

  ////////// Job.remove \\\\\\\\\\
  remove: {
    validate: {
      params: {
        id: Joi.string().required()
      }
    },
    handler: function (request, reply) {
      Job.remove({ id: request.params.id }, (err) => {
        if (err) {
          logger.error(`Job.remove error: ${err.message}`)
          return reply(badRequest(err.message))
        }

        logger.debug(`Job.remove removed ${request.params.id}`)
        reply()
      })
    }
  },

  ////////// Job.update \\\\\\\\\\
  update: {
    validate: {
      params: {
        id: Joi.string().required()
      },
      payload: {
        employer: Joi.string(),
        location: {
          city: Joi.string(),
          state: Joi.string()
        },
        dates: {
          start: Joi.string(),
          end: Joi.string()
        },
        title: Joi.string(),
        tasks: Joi.array()
      }
    },
    handler: function (request, reply) {
      let {params, payload} = request

      Job.update({ id: params.id }, payload, (err) => {
        if (err) {
          logger.error(`Job.update error: ${err.message}`)
          return reply(badRequest(err.message))
        }

        logger.debug(`Job.update updated ${params.id}`)
        reply(params.id)
      })
    }
  }
}
<commit_msg>Add `present` query parameter<commit_after>import {badRequest, notFound} from 'boom'
import Joi from 'joi'
import Logger from '@modulus/logger'

import Job from '../models/job'

let logger = Logger('handlers/job')

export default {

  /////////// Job.create \\\\\\\\\\
  create: {
    validate: {
      payload: {
        employer: Joi.string().required(),
        location: {
          city: Joi.string(),
          state: Joi.string()
        },
        dates: {
          start: Joi.string().required(),
          end: Joi.string()
        },
        title: Joi.string().required(),
        tasks: Joi.array()
      }
    },
    handler: function (request, reply) {
      let {employer, location, dates, tasks, title} = request.payload

      let newJob =  {
        employer: employer,
        location: {
          city: location.city,
          state: location.state
        },
        dates: {
          start: dates.start,
          end: dates.end
        },
        title: title,
        tasks: tasks
      }

      new Job(newJob).save((err, created) => {
        if (err) {
          logger.error(`Job.create error: ${err.message}`)
          return reply(badRequest(err.message))
        }

        logger.debug(`Job.create saved ${JSON.stringify(created)}`)
        reply(created)
      })
    }
  },

  ////////// Job.get \\\\\\\\\\
  get: {
    validate: {
      params: {
        id: Joi.string().required()
      }
    },
    handler: function (request, reply) {
      Job.findOne({ id: request.params.id }, (err, job) => {
        if (err) {
          logger.error(`Job.findOne error: ${err.message}`)
          return reply(badRequest(err.message))
        }

        logger.debug(`Job.findOne found ${JSON.stringify(job)}`)
        reply(job)
      })
    }
  },

  ////////// Job.getAll \\\\\\\\\\
  getAll: {
    validate: {
      query: {
        present: Joi.string()
      }
    },
    handler: function (request, reply) {
      let query = {}

      if (request.query && request.query.present) {
        query = { 'dates.end': 'Present' }
      }

      Job.find(query, (err, jobs) => {
        if (err) {
          logger.error(`Job.find error: ${err.message}`)
          return reply(badRequest(err.message))
        }

        logger.debug(`Job.find found ${JSON.stringify(jobs)}`)
        reply(jobs)
      })
    }
  },

  ////////// Job.remove \\\\\\\\\\
  remove: {
    validate: {
      params: {
        id: Joi.string().required()
      }
    },
    handler: function (request, reply) {
      Job.remove({ id: request.params.id }, (err) => {
        if (err) {
          logger.error(`Job.remove error: ${err.message}`)
          return reply(badRequest(err.message))
        }

        logger.debug(`Job.remove removed ${request.params.id}`)
        reply()
      })
    }
  },

  ////////// Job.update \\\\\\\\\\
  update: {
    validate: {
      params: {
        id: Joi.string().required()
      },
      payload: {
        employer: Joi.string(),
        location: {
          city: Joi.string(),
          state: Joi.string()
        },
        dates: {
          start: Joi.string(),
          end: Joi.string()
        },
        title: Joi.string(),
        tasks: Joi.array()
      }
    },
    handler: function (request, reply) {
      let {params, payload} = request

      Job.update({ id: params.id }, payload, (err) => {
        if (err) {
          logger.error(`Job.update error: ${err.message}`)
          return reply(badRequest(err.message))
        }

        logger.debug(`Job.update updated ${params.id}`)
        reply(params.id)
      })
    }
  }
}
<|endoftext|>


<commit_before>/**
 * @author perezyuan.
 * @time 2017/01/18.
 *
 * 快速构建一个抽奖程序
 */

function draw(sum, number) {
    let sumArr = new Array(sum).fill().map((value, index) => index + 1);
    console.log(sumArr);
    return sumArr;
}

draw(10,2);<commit_msg>first function<commit_after>/**
 * @author perezyuan.
 * @time 2017/01/18.
 *
 * 快速构建一个抽奖程序
 */

// 问题 splice会进行10次 效率较低
function draw(sum, number = 1) {
    if (sum < number) {
        return;
    }
    let sumArr = new Array(sum).fill().map((value, index) => index + 1);
    let ret = []
    for(let i = 0; i < number; i++) {
        let num = Math.floor(Math.random() * number);
        ret.push(...sumArr.splice(num, 1));
    }
    return ret;
}

console.log(draw(10,8));<|endoftext|>


<commit_before>(function () {

  'use strict';

  angular.module('openSnap')
    .component('osCreate', {
      templateUrl: 'components/create/oscreate.html',
      controller: OsCreateController,
      bindings: {
        snippet: '<'
      }
    });

  OsCreateController.$inject = ['$mdDialog', 'OsSnippetApi', '$mdToast'];
  function OsCreateController($mdDialog, OsSnippetApi, $mdToast) {
    var $ctrl = this;

    $ctrl.$onInit = function () {
      $ctrl.editor = ace.edit('os-editor');
      $ctrl.editor.setTheme('ace/theme/eclipse');
      $ctrl.editor.getSession().setMode('ace/mode/javascript');

      $ctrl.editor.setValue(
        "/**\n* Function for controlling snake movement\n" +
        "* @param snake - The snake's cells in an array of\n" +
        "*\t\t objects containing x and y coordinates\n" +
        "* @param food - The food's cells in an object of x and y\n" +
        "* @param map - The map cells in an array of objects containing\n" +
        "*\t\t the x and y coordinates and the type of the cell\n" +
        "*\t\t 'O' for obstactle and 'T' for tile\n" +
        "* return 'UP', 'RIGHT', 'LEFT' or 'RIGHT'\n" +
        "*/\nthis.moveSnake = function(snake, food) {" +
        "\n\tvar head = snake[snake.length-1];" +
        "\n\tif (head.x > food.x) {\n\t\treturn 'LEFT';" +
        "\n\t} else if (head.x < food.x) {\n\t\treturn 'RIGHT';" +
        "\n\t} else if (head.y < food.y) {\n\t\treturn 'DOWN';" +
        "\n\t} else {\n\t\treturn 'UP';\n\t}" +
        "\n};\n", -1);
    };

    $ctrl.onRunClick = function (ev) {
      $mdDialog.show({
        controller: 'OsRunController',
        templateUrl: 'components/create/run/osrun.html',
        parent: angular.element(document.body),
        targetEvent: ev,
        clickOutsideToClose: false,
        controllerAs: '$ctrl',
        locals: {
          gameCode: $ctrl.editor.getValue()
        }
      });
    };

    $ctrl.updateSnippet = function () {
      if ($ctrl.newSnippetForm.invalid) return;
      var toastText = 'Snipped saved successfully!';
      $ctrl.snippet.code = $ctrl.editor.getValue();
      OsSnippetApi.service.save($ctrl.snippet).$promise.then(function (data) {
        $ctrl.snippet.id = data.id;
      }, function (error) {
        toastText = 'Error while saving snippet!';
      }).finally(function () {
        $mdToast.show(
          $mdToast.simple()
            .textContent(toastText)
            .position('bottom')
            .hideDelay(3000)
        );
      });
    };
  }

})();
<commit_msg>Showing the users code fixed<commit_after>(function () {

  'use strict';

  angular.module('openSnap')
    .component('osCreate', {
      templateUrl: 'components/create/oscreate.html',
      controller: OsCreateController,
      bindings: {
        snippet: '<'
      }
    });

  OsCreateController.$inject = ['$mdDialog', 'OsSnippetApi', '$mdToast'];
  function OsCreateController($mdDialog, OsSnippetApi, $mdToast) {
    var $ctrl = this;

    $ctrl.$onInit = function () {
      $ctrl.editor = ace.edit('os-editor');
      $ctrl.editor.setTheme('ace/theme/eclipse');
      $ctrl.editor.getSession().setMode('ace/mode/javascript');

      $ctrl.editor.setValue(
        "/**\n* Function for controlling snake movement\n" +
        "* @param snake - The snake's cells in an array of\n" +
        "*\t\t objects containing x and y coordinates\n" +
        "* @param food - The food's cells in an object of x and y\n" +
        "* @param map - The map cells in an array of objects containing\n" +
        "*\t\t the x and y coordinates and the type of the cell\n" +
        "*\t\t 'O' for obstactle and 'T' for tile\n" +
        "* return 'UP', 'RIGHT', 'LEFT' or 'RIGHT'\n" +
        "*/\nthis.moveSnake = function(snake, food) {" +
        "\n\tvar head = snake[snake.length-1];" +
        "\n\tif (head.x > food.x) {\n\t\treturn 'LEFT';" +
        "\n\t} else if (head.x < food.x) {\n\t\treturn 'RIGHT';" +
        "\n\t} else if (head.y < food.y) {\n\t\treturn 'DOWN';" +
        "\n\t} else {\n\t\treturn 'UP';\n\t}" +
        "\n};\n", -1);

        if (this.snippet) {
          $ctrl.editor.setValue(this.snippet.code, -1);
        }
    };

    $ctrl.onRunClick = function (ev) {
      $mdDialog.show({
        controller: 'OsRunController',
        templateUrl: 'components/create/run/osrun.html',
        parent: angular.element(document.body),
        targetEvent: ev,
        clickOutsideToClose: false,
        controllerAs: '$ctrl',
        locals: {
          gameCode: $ctrl.editor.getValue()
        }
      });
    };

    $ctrl.updateSnippet = function () {
      if ($ctrl.newSnippetForm.invalid) return;
      var toastText = 'Snippet saved successfully!';
      $ctrl.snippet.code = $ctrl.editor.getValue();
      OsSnippetApi.service.save($ctrl.snippet).$promise.then(function (data) {
        $ctrl.snippet.id = data.id;
      }, function (error) {
        toastText = 'Error while saving snippet!';
      }).finally(function () {
        $mdToast.show(
          $mdToast.simple()
            .textContent(toastText)
            .position('bottom')
            .hideDelay(3000)
        );
      });
    };
  }

})();
<|endoftext|>


<commit_before>import { Router } from 'express'
import { middleware as query } from 'querymen'
import { middleware as body } from 'bodymen'
import {<% if (passwordSignup) { %> password as passwordAuth,<% } %> master, token } from '../../services/passport'
import { index, showMe, show, create, update<% if (passwordSignup) { %>, updatePassword<% } %>, destroy } from './controller'
import { schema } from './model'
export User, { schema } from './model'

const router = new Router()
const { email<% if (passwordSignup) { %>, password<% } %>, name, picture, role } = schema.tree

/**
 * @api {get} /users Retrieve users
 * @apiName RetrieveUsers
 * @apiGroup User
 * @apiPermission admin
 * @apiParam {String} access_token User access_token.
 * @apiUse listParams
 * @apiSuccess {Object[]} users List of users.
 * @apiError {Object} 400 Some parameters may contain invalid values.
 * @apiError 401 Admin access only.
 */
router.get('/',
  token({ required: true, roles: ['admin'] }),
  query(),
  index)

/**
 * @api {get} /users/me Retrieve current user
 * @apiName RetrieveCurrentUser
 * @apiGroup User
 * @apiPermission user
 * @apiParam {String} access_token User access_token.
 * @apiSuccess {Object} user User's data.
 */
router.get('/me',
  token({ required: true }),
  showMe)

/**
 * @api {get} /users/:id Retrieve user
 * @apiName RetrieveUser
 * @apiGroup User
 * @apiPermission public
 * @apiSuccess {Object} user User's data.
 * @apiError 404 User not found.
 */
router.get('/:id',
  show)

/**
 * @api {post} /users Create user
 * @apiName CreateUser
 * @apiGroup User
 * @apiPermission master
 * @apiParam {String} access_token Master access_token.
 * @apiParam {String} email User's email.
 <%_ if (passwordSignup) { _%>
 * @apiParam {String{6..}} password User's password.
 <%_ } _%>
 * @apiParam {String} [name] User's name.
 * @apiParam {String} [picture] User's picture.
 * @apiParam {String=user,admin} [role=user] User's picture.
 * @apiSuccess (Sucess 201) {Object} user User's data.
 * @apiError {Object} 400 Some parameters may contain invalid values.
 * @apiError 401 Master access only.
 * @apiError 409 Email already registered.
 */
router.post('/',
  master(),
  body({ email<% if (passwordSignup) { %>, password<% } %>, name, picture, role }),
  create)

/**
 * @api {put} /users/:id Update user
 * @apiName UpdateUser
 * @apiGroup User
 * @apiPermission user
 * @apiParam {String} access_token User access_token.
 * @apiParam {String} [name] User's name.
 * @apiParam {String} [picture] User's picture.
 * @apiSuccess {Object} user User's data.
 * @apiError {Object} 400 Some parameters may contain invalid values.
 * @apiError 401 Current user or admin access only.
 * @apiError 404 User not found.
 */
router.put('/:id',
  token({ required: true }),
  body({ name, picture }),
  update)

<%_ if (passwordSignup) {_%>
/**
 * @api {put} /users/:id/password Update password
 * @apiName UpdatePassword
 * @apiGroup User
 * @apiHeader {String} Authorization Basic authorization with email and password.
 * @apiParam {String{6..}} password User's new password.
 * @apiSuccess (Success 201) {Object} user User's data.
 * @apiError {Object} 400 Some parameters may contain invalid values.
 * @apiError 401 Current user access only.
 * @apiError 404 User not found.
 */
router.put('/:id/password',
  passwordAuth(),
  body({ password }),
  updatePassword)

<%_ } _%>
/**
 * @api {delete} /users/:id Delete user
 * @apiName DeleteUser
 * @apiGroup User
 * @apiPermission admin
 * @apiParam {String} access_token User access_token.
 * @apiSuccess (Success 204) 204 No Content.
 * @apiError 401 Admin access only.
 * @apiError 404 User not found.
 */
router.delete('/:id',
  token({ required: true, roles: ['admin'] }),
  destroy)

export default router
<commit_msg>Fixed api doc duplicate (#135)<commit_after>import { Router } from 'express'
import { middleware as query } from 'querymen'
import { middleware as body } from 'bodymen'
import {<% if (passwordSignup) { %> password as passwordAuth,<% } %> master, token } from '../../services/passport'
import { index, showMe, show, create, update<% if (passwordSignup) { %>, updatePassword<% } %>, destroy } from './controller'
import { schema } from './model'
export User, { schema } from './model'

const router = new Router()
const { email<% if (passwordSignup) { %>, password<% } %>, name, picture, role } = schema.tree

/**
 * @api {get} /users Retrieve users
 * @apiName RetrieveUsers
 * @apiGroup User
 * @apiPermission admin
 * @apiParam {String} access_token User access_token.
 * @apiUse listParams
 * @apiSuccess {Object[]} users List of users.
 * @apiError {Object} 400 Some parameters may contain invalid values.
 * @apiError 401 Admin access only.
 */
router.get('/',
  token({ required: true, roles: ['admin'] }),
  query(),
  index)

/**
 * @api {get} /users/me Retrieve current user
 * @apiName RetrieveCurrentUser
 * @apiGroup User
 * @apiPermission user
 * @apiParam {String} access_token User access_token.
 * @apiSuccess {Object} user User's data.
 */
router.get('/me',
  token({ required: true }),
  showMe)

/**
 * @api {get} /users/:id Retrieve user
 * @apiName RetrieveUser
 * @apiGroup User
 * @apiPermission public
 * @apiSuccess {Object} user User's data.
 * @apiError 404 User not found.
 */
router.get('/:id',
  show)

/**
 * @api {post} /users Create user
 * @apiName CreateUser
 * @apiGroup User
 * @apiPermission master
 * @apiParam {String} access_token Master access_token.
 * @apiParam {String} email User's email.
 <%_ if (passwordSignup) { _%>
 * @apiParam {String{6..}} password User's password.
 <%_ } _%>
 * @apiParam {String} [name] User's name.
 * @apiParam {String} [picture] User's picture.
 * @apiParam {String=user,admin} [role=user] User's role.
 * @apiSuccess (Sucess 201) {Object} user User's data.
 * @apiError {Object} 400 Some parameters may contain invalid values.
 * @apiError 401 Master access only.
 * @apiError 409 Email already registered.
 */
router.post('/',
  master(),
  body({ email<% if (passwordSignup) { %>, password<% } %>, name, picture, role }),
  create)

/**
 * @api {put} /users/:id Update user
 * @apiName UpdateUser
 * @apiGroup User
 * @apiPermission user
 * @apiParam {String} access_token User access_token.
 * @apiParam {String} [name] User's name.
 * @apiParam {String} [picture] User's picture.
 * @apiSuccess {Object} user User's data.
 * @apiError {Object} 400 Some parameters may contain invalid values.
 * @apiError 401 Current user or admin access only.
 * @apiError 404 User not found.
 */
router.put('/:id',
  token({ required: true }),
  body({ name, picture }),
  update)

<%_ if (passwordSignup) {_%>
/**
 * @api {put} /users/:id/password Update password
 * @apiName UpdatePassword
 * @apiGroup User
 * @apiHeader {String} Authorization Basic authorization with email and password.
 * @apiParam {String{6..}} password User's new password.
 * @apiSuccess (Success 201) {Object} user User's data.
 * @apiError {Object} 400 Some parameters may contain invalid values.
 * @apiError 401 Current user access only.
 * @apiError 404 User not found.
 */
router.put('/:id/password',
  passwordAuth(),
  body({ password }),
  updatePassword)

<%_ } _%>
/**
 * @api {delete} /users/:id Delete user
 * @apiName DeleteUser
 * @apiGroup User
 * @apiPermission admin
 * @apiParam {String} access_token User access_token.
 * @apiSuccess (Success 204) 204 No Content.
 * @apiError 401 Admin access only.
 * @apiError 404 User not found.
 */
router.delete('/:id',
  token({ required: true, roles: ['admin'] }),
  destroy)

export default router
<|endoftext|>


<commit_before><commit_msg>feat(MultipleProductsContainer): created<commit_after>import MultipleProducts from '../components/MultipleProducts';
import { connect } from 'react-redux';

const mapStateToProps = (state) => {
  return {
    products: state.products
  }
}

const MultipleProductsContainer = connect(
  mapStateToProps
)(MultipleProducts)

export default MultipleProductsContainer
<|endoftext|>


<commit_before>/**
 * @file Toaster component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import cloneDeep from 'lodash/cloneDeep';
import classNames from 'classnames';

import PositionPop from '../_PositionPop';
import Toast from '../_Toast';

import MsgType from '../_statics/MsgType';
import Position from '../_statics/Position';

import Util from '../_vendors/Util';

class Toaster extends Component {

    static Type = MsgType;
    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.nextKey = 0;

        this.state = {
            visible: false,
            toasts: []
        };

    }

    isPositiveSequence = (position = this.props.position) => {
        return position !== Position.BOTTOM_LEFT && position !== Position.BOTTOM && position !== Position.BOTTOM_RIGHT;
    };

    addToast = toast => {

        let toasts = this.state.toasts;

        if (this.isPositiveSequence()) {
            toasts.push({...toast, toastsId: this.nextKey++});
        } else {
            toasts.unshift({...toast, toastsId: this.nextKey++});
        }

        this.setState({
            toasts,
            visible: true
        }, () => {
            this.refs.toaster.resetPosition();
        });

    };

    removeToast = toastsId => {

        let toasts = this.state.toasts;

        toasts.splice(toasts.findIndex(item => item.toastsId === toastsId), 1);

        this.setState({
            toasts
        }, () => {
            if (toasts.length < 1) {
                this.setState({
                    visible: false
                }, () => {
                    this.refs.toaster.resetPosition();
                });
            }
        });

    };

    componentWillReceiveProps(nextProps) {

        if (nextProps.toasts && nextProps.toasts.length > 0) {

            let toasts = cloneDeep(nextProps.toasts);
            for (let i = 0, len = toasts.length; i < len; i++) {
                if (typeof toasts[i] !== 'object') {
                    toasts[i] = {
                        message: toasts[i]
                    };
                }
                toasts[i].toastsId = this.nextKey++;
            }

            if (this.isPositiveSequence()) {
                toasts = [...this.state.toasts, ...toasts];
            } else {
                toasts = [...toasts.reverse(), ...this.state.toasts];
            }

            this.setState({
                toasts,
                visible: true
            }, () => {

                this.refs.toaster.resetPosition();

                const {onToastPop} = this.props;
                onToastPop && onToastPop();

            });

        }

    }

    render() {

        const {

                className, position, duration,

                // not passing down these props
                onToastPop,

                ...restProps

            } = this.props,
            {toasts, visible} = this.state,

            toasterClassName = classNames('toaster', {
                [`toaster-${position}`]: position,
                [className]: className
            });

        return (
            <PositionPop {...restProps}
                         ref="toaster"
                         className={toasterClassName}
                         visible={visible}
                         position={position}>
                {
                    toasts && toasts.map(options =>
                        <Toast {...options}
                               key={options.toastsId}
                               duration={'duration' in options ? options.duration : duration}
                               onRequestClose={this.removeToast}/>
                    )
                }
            </PositionPop>
        );

    }

}

Toaster.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Children passed into the toaster.
     */
    toasts: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

        /**
         * The CSS class name of toast.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the toast.
         */
        style: PropTypes.object,

        /**
         * The type of toast.
         */
        type: PropTypes.oneOf(Util.enumerateValue(MsgType)),

        /**
         * The message of toast.
         */
        message: PropTypes.string,

        /**
         * The icon class name of toast.
         */
        iconCls: PropTypes.string,

        /**
         * The duration of toast.
         */
        duration: PropTypes.number

    }), PropTypes.string, PropTypes.number])),

    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * The duration of toast.
     */
    duration: PropTypes.number,

    /**
     * Callback function fired when the toaster pop.
     */
    onToastPop: PropTypes.func

};

Toaster.defaultProps = {
    position: Position.TOP,
    duration: 2500
};

export default Toaster;<commit_msg>optimize Toaster<commit_after>/**
 * @file Toaster component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import cloneDeep from 'lodash/cloneDeep';
import classNames from 'classnames';

import PositionPop from '../_PositionPop';
import Toast from '../_Toast';

import MsgType from '../_statics/MsgType';
import Position from '../_statics/Position';

import Util from '../_vendors/Util';

class Toaster extends Component {

    static Type = MsgType;
    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.nextKey = 0;

        this.state = {
            visible: false,
            toasts: []
        };

    }

    isPositiveSequence = (position = this.props.position) => {
        return position !== Position.BOTTOM_LEFT && position !== Position.BOTTOM && position !== Position.BOTTOM_RIGHT;
    };

    addToast = toast => {

        let toasts = this.state.toasts;

        if (this.isPositiveSequence()) {
            toasts.push({...toast, toastsId: this.nextKey++});
        } else {
            toasts.unshift({...toast, toastsId: this.nextKey++});
        }

        this.setState({
            toasts,
            visible: true
        }, () => {
            this.refs.toaster.resetPosition();
        });

    };

    removeToast = toastsId => {

        let {toasts} = this.state;

        if (!toasts || toasts.length < 1) {
            return;
        }

        toasts.splice(toasts.findIndex(item => item.toastsId === toastsId), 1);

        this.setState({
            toasts
        }, () => {
            if (toasts.length < 1) {
                this.setState({
                    visible: false
                }, () => {
                    this.refs.toaster.resetPosition();
                });
            }
        });

    };

    componentWillReceiveProps(nextProps) {

        if (nextProps.toasts && nextProps.toasts.length > 0) {

            let toasts = cloneDeep(nextProps.toasts);
            for (let i = 0, len = toasts.length; i < len; i++) {
                if (typeof toasts[i] !== 'object') {
                    toasts[i] = {
                        message: toasts[i]
                    };
                }
                toasts[i].toastsId = this.nextKey++;
            }

            if (this.isPositiveSequence()) {
                toasts = [...this.state.toasts, ...toasts];
            } else {
                toasts = [...toasts.reverse(), ...this.state.toasts];
            }

            this.setState({
                toasts,
                visible: true
            }, () => {

                this.refs.toaster.resetPosition();

                const {onToastPop} = this.props;
                onToastPop && onToastPop();

            });

        }

    }

    render() {

        const {

                className, position, duration,

                // not passing down these props
                onToastPop,

                ...restProps

            } = this.props,
            {toasts, visible} = this.state,

            toasterClassName = classNames('toaster', {
                [`toaster-${position}`]: position,
                [className]: className
            });

        return (
            <PositionPop {...restProps}
                         ref="toaster"
                         className={toasterClassName}
                         visible={visible}
                         position={position}>
                {
                    toasts && toasts.map(options =>
                        <Toast {...options}
                               key={options.toastsId}
                               duration={'duration' in options ? options.duration : duration}
                               onRequestClose={this.removeToast}/>
                    )
                }
            </PositionPop>
        );

    }

}

Toaster.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Children passed into the toaster.
     */
    toasts: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

        /**
         * The CSS class name of toast.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the toast.
         */
        style: PropTypes.object,

        /**
         * The type of toast.
         */
        type: PropTypes.oneOf(Util.enumerateValue(MsgType)),

        /**
         * The message of toast.
         */
        message: PropTypes.string,

        /**
         * The icon class name of toast.
         */
        iconCls: PropTypes.string,

        /**
         * The duration of toast.
         */
        duration: PropTypes.number

    }), PropTypes.string, PropTypes.number])),

    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * The duration of toast.
     */
    duration: PropTypes.number,

    /**
     * Callback function fired when the toaster pop.
     */
    onToastPop: PropTypes.func

};

Toaster.defaultProps = {
    position: Position.TOP,
    duration: 2500
};

export default Toaster;<|endoftext|>


<commit_before>// Load in our dependencies
var assert = require('assert');
var ecmaScopes = require('ecma-scopes');
var estraverse = require('estraverse');

// Define constants
var LEXICAL_SCOPE_TYPE = 'lexical';
var BLOCK_SCOPE_TYPE = 'block';

// Define helper to check a new scope
function getScopeType(node) {
  if (node.type === 'Program') {
    // DEV: We mark `program` as `lexical` because it is easier to set/compare against
    return 'lexical';
  } else if (ecmaScopes.lexical.indexOf(node.type) !== -1) {
    return 'lexical';
  } else if (node.type === 'WithStatement') {
    return 'with';
  } else if (ecmaScopes.block.indexOf(node.type) !== -1) {
    return 'block';
  } else {
    return null;
  }
}

// TODO: Move to an object or reduce the parameters. The count is too damn high
// DEV: We specify `baseNode` because it should be where we resolve the nearest scope from which may not be an identifier
function resolveScope(baseNode, identifiers, scopeType) {
  // If we resolved identifiers
  // DEV: This assert is to make it faster for developers to debug
  assert(Array.isArray(identifiers), 'Identifier resolution for baseNode "' + baseNode.type + '" did not result in an array');

  if (identifiers.length) {
    // Walk up the nearest scopes until we find one that matches our type
    // DEV: Use `scopeTypes` since a block scope can hit `Program` which is lexical
    var scope = baseNode.nearestScope;
    var scopeTypes = scopeType === LEXICAL_SCOPE_TYPE ? [LEXICAL_SCOPE_TYPE] : [LEXICAL_SCOPE_TYPE, BLOCK_SCOPE_TYPE];
    while (scope) {
      // If the scope type matches, stop
      if (scopeTypes.indexOf(scope.type) !== -1) {
        break;
      }

      // Look at the scope's parent
      scope = scope.parent;
    }

    // Save declaration info on the scope and scope type to the identifier
    identifiers.forEach(function saveIdentifier (identifier) {
      scope.identifiers[identifier.name] = identifier;
      // TODO: We should clean up `scopeType` when `scope` is defined
      identifier.scopeType = scopeType;
    });
  }
}

// TODO: Consider breaking down ecmaVariableScope into 3 functions

// Define our variable scope function
function ecmaVariableScope(ast) {
  // Walk entire tree
  var scopeStack = [];
  var scope;
  estraverse.traverse(ast, {
    // Upon entry of a node
    enter: function (node, parent) {
      // Save the scope to our node
      // e.g. {`FunctionDeclaration.nearestScope === Program`}
      // e.g. {`Program.nearestScope === undefined`}
      node.nearestScope = scope;

      // If it is a a program, lexical scope, with statement, or block scope
      var scopeType = getScopeType(node);
      if (scopeType) {
        // Generate a new scope and push it onto our stack
        var oldScope = scope;
        scope = {
          type: scopeType,
          node: node, // reference to node of AST
          parent: oldScope, // reference to parent in scope tree
          identifiers: { // reference to Identifier nodes in AST under our scope
            // name: Identifier
          },
          children: [] // references to children in scope tree
        };
        scopeStack.push(scope);

        // If there was a parent scope, save a child reference
        if (scope.parent) {
          scope.parent.children.push(scope);
        }
      }
    },
    // Upon exiting a node
    leave: function (node, parent) {
      // If it is a program, lexical scope, with statement, or a block scope
      if (getScopeType(node)) {
        // Pop it from the stack
        scopeStack.pop();

        // Update the scope reference
        scope = scopeStack[scopeStack.length - 1];
      }
    }
  });

  // Walk entire tree
  estraverse.traverse(ast, {
    enter: function (node, parent) {
      // If the item is a variable declaration
      var identifiers;
      var scopeType;
      switch(node.type) {
        // Lexical/block scope
        // If it is a variable declaration (e.g. `var name;`, `let name;`)
        // DEV: This also covers `for/for in/for of` loops since they require a `let`
        case 'VariableDeclaration':
          // Find all of the identifiers via the declarators
          var declarators = node.declarations;
          // TODO: Consider using _.pluck
          identifiers = declarators.map(function getIdentifier (declarator) {
            return declarator.id;
          });
          // DEV: For reference, `const` is lexical
          //   if (true) { const hai = true; } console.log(hai);
          scopeType = node.kind === 'let' ? BLOCK_SCOPE_TYPE : LEXICAL_SCOPE_TYPE;
          resolveScope(node, identifiers, scopeType);
          break;

        // Lexical scopes
        // `function name(params) {}`
        case 'FunctionDeclaration':
        // `[].map(function name (params) {})`
        case 'FunctionExpression':
        // `[].map(name => 1);
        case 'ArrowFunctionExpression':
          // DEV: This covers both the function name and its parameters
          // Resolve the scope of the fn name separately from its params (different scopes)
          // DEV: Allow no name (e.g. `[].map(function () {})`
          if (node.id) {
            resolveScope(node, [node.id], LEXICAL_SCOPE_TYPE);
          }

          // Resolve scope for the fn parameters (will resolve to fn)
          if (node.params[0]) {
            resolveScope(node.params[0], node.params, LEXICAL_SCOPE_TYPE);
          }
          break;

        // Block scopes
        // `try { /* ... */ } catch (name) { /* ... */ }
        case 'CatchClause':
          resolveScope(node, [node.param], BLOCK_SCOPE_TYPE);
          break;
          // TODO: Create todo regarding `ComprehensionBlock`
      }
    }
  });

  // Walk entire tree
  estraverse.traverse(ast, {
    enter: function (node, parent) {
      // If the node is an identifier (i.e. any variable reference)
      // TODO: Verify this doesn't tag `MemberExpression's` (e.g. `log` of `console.log`)
      if (node.type === 'Identifier') {
        // Walk up the scope chain until we find our containing scope
        var scope = node.nearestScope;
        var info = {
          declared: false,
          topLevel: false,
          insideWith: false,
          type: 'undeclared'
        };
        var identifier;
        while (scope) {
          // If we are passing through a `with`, save the info
          if (scope.type === 'with') {
            info.insideWith = true;
          }

          // If it contains our variable, stop looping
          identifier = scope.identifiers[node.name];
          if (identifier !== undefined) {
            break;
          }

          // Otherwise, move to the parent scope
          scope = scope.parent;
        }

        // If we didn't find a scope or we are at the top level, mark info as top level
        if (scope === undefined || scope.node.type === 'Program') {
          info.topLevel = true;
        }

        // If we hit an identifier, save the type
        if (identifier) {
          info.type = identifier.scopeType;
        }

        // If we saw a `with`, mark `declared` as unknown
        // Attribution: https://github.com/dlsym/segmentation_fuuuu/blob/0bd35fbe215c45fda75e47c3d63df7c4be76b2c6/README.md
        // WITH(OBJ)  ________
        //         __/     /  \  FFFFFFF
        //        /   \   /__  \ FFFFFFF
        //       /  ___\  | (|  \  FFFFFF
        //       | |)  |  \__/   \  FFFUU
        //       | \ _ / ____     |  UUUU
        //       |      / VVV\_   |  UUUU
        //       |     /   ~   \  |  UUUU
        //        \   /__M_M___/  |  UUUU
        //         \_____________/   UUUU-
        if (info.insideWith === true) {
          info.declared = 'unknown';
        // Otherwise, if we didn't find a scope, marked it as undeclared
        } else if (info.type === 'undeclared') {
          info.declared = false;
        // Otherwise, mark this identifier as declared
        } else {
          info.declared = true;
        }

        // Save our info to the identifier
        node.scopeInfo = info;
        node.scope = scope;
      }
    }
  });

  // Return our marked up AST
  return ast;
}

// Export our funtion
module.exports = ecmaVariableScope;
<commit_msg>Fixed up broken test case<commit_after>// Load in our dependencies
var assert = require('assert');
var ecmaScopes = require('ecma-scopes');
var estraverse = require('estraverse');

// Define constants
var LEXICAL_SCOPE_TYPE = 'lexical';
var BLOCK_SCOPE_TYPE = 'block';

// Define helper to check a new scope
function getScopeType(node) {
  if (node.type === 'Program') {
    // DEV: We mark `program` as `lexical` because it is easier to set/compare against
    return 'lexical';
  } else if (ecmaScopes.lexical.indexOf(node.type) !== -1) {
    return 'lexical';
  } else if (node.type === 'WithStatement') {
    return 'with';
  } else if (ecmaScopes.block.indexOf(node.type) !== -1) {
    return 'block';
  } else {
    return null;
  }
}

// TODO: Move to an object or reduce the parameters. The count is too damn high
// DEV: We specify `baseNode` because it should be where we resolve the nearest scope from which may not be an identifier
function resolveScope(baseNode, identifiers, scopeType) {
  // If we resolved identifiers
  // DEV: This assert is to make it faster for developers to debug
  assert(Array.isArray(identifiers), 'Identifier resolution for baseNode "' + baseNode.type + '" did not result in an array');

  if (identifiers.length) {
    // Walk up the nearest scopes until we find one that matches our type
    // DEV: Use `scopeTypes` since a block scope can hit `Program` which is lexical
    var scope = baseNode.nearestScope;
    var scopeTypes = scopeType === LEXICAL_SCOPE_TYPE ? [LEXICAL_SCOPE_TYPE] : [LEXICAL_SCOPE_TYPE, BLOCK_SCOPE_TYPE];
    while (scope) {
      // If the scope type matches, stop
      if (scopeTypes.indexOf(scope.type) !== -1) {
        break;
      }

      // Look at the scope's parent
      scope = scope.parent;
    }

    // Save declaration info on the scope and scope type to the identifier
    identifiers.forEach(function saveIdentifier (identifier) {
      scope.identifiers[identifier.name] = identifier;
      // TODO: We should clean up `scopeType` when `scope` is defined
      identifier.scopeType = scopeType;
    });
  }
}

// TODO: Consider breaking down ecmaVariableScope into 3 functions

// Define our variable scope function
function ecmaVariableScope(ast) {
  // Walk entire tree
  var scopeStack = [];
  var scope;
  estraverse.traverse(ast, {
    // Upon entry of a node
    enter: function (node, parent) {
      // Save the scope to our node
      // e.g. {`FunctionDeclaration.nearestScope === Program`}
      // e.g. {`Program.nearestScope === undefined`}
      node.nearestScope = scope;

      // If it is a a program, lexical scope, with statement, or block scope
      var scopeType = getScopeType(node);
      if (scopeType) {
        // Generate a new scope and push it onto our stack
        var oldScope = scope;
        scope = {
          type: scopeType,
          node: node, // reference to node of AST
          parent: oldScope, // reference to parent in scope tree
          identifiers: { // reference to Identifier nodes in AST under our scope
            // name: Identifier
          },
          children: [] // references to children in scope tree
        };
        scopeStack.push(scope);

        // If there was a parent scope, save a child reference
        if (scope.parent) {
          scope.parent.children.push(scope);
        }
      }
    },
    // Upon exiting a node
    leave: function (node, parent) {
      // If it is a program, lexical scope, with statement, or a block scope
      if (getScopeType(node)) {
        // Pop it from the stack
        scopeStack.pop();

        // Update the scope reference
        scope = scopeStack[scopeStack.length - 1];
      }
    }
  });

  // Walk entire tree
  estraverse.traverse(ast, {
    enter: function (node, parent) {
      // If the item is a variable declaration
      var identifiers;
      var scopeType;
      switch(node.type) {
        // Lexical/block scope
        // If it is a variable declaration (e.g. `var name;`, `let name;`)
        // DEV: This also covers `for/for in/for of` loops since they require a `let`
        case 'VariableDeclaration':
          // Find all of the identifiers via the declarators
          var declarators = node.declarations;
          // TODO: Consider using _.pluck
          identifiers = declarators.map(function getIdentifier (declarator) {
            return declarator.id;
          });
          // DEV: For reference, `const` is lexical
          //   if (true) { const hai = true; } console.log(hai);
          scopeType = node.kind === 'let' ? BLOCK_SCOPE_TYPE : LEXICAL_SCOPE_TYPE;
          resolveScope(node, identifiers, scopeType);
          break;

        // Lexical scopes
        // `function name(params) {}`
        case 'FunctionDeclaration':
        // `[].map(function name (params) {})`
        case 'FunctionExpression':
        // `[].map(name => 1);
        case 'ArrowFunctionExpression':
          // DEV: This covers both the function name and its parameters
          // Resolve the scope of the fn name separately from its params (different scopes)
          // DEV: Allow no name (e.g. `[].map(function () {})`
          if (node.id) {
            resolveScope(node, [node.id], LEXICAL_SCOPE_TYPE);
          }

          // Resolve scope for the fn parameters (will resolve to fn)
          if (node.params[0]) {
            resolveScope(node.params[0], node.params, LEXICAL_SCOPE_TYPE);
          }
          break;

        // Block scopes
        // `try { /* ... */ } catch (name) { /* ... */ }
        case 'CatchClause':
          resolveScope(node.param, [node.param], BLOCK_SCOPE_TYPE);
          break;
          // TODO: Create todo regarding `ComprehensionBlock`
      }
    }
  });

  // Walk entire tree
  estraverse.traverse(ast, {
    enter: function (node, parent) {
      // If the node is an identifier (i.e. any variable reference)
      // TODO: Verify this doesn't tag `MemberExpression's` (e.g. `log` of `console.log`)
      if (node.type === 'Identifier') {
        // Walk up the scope chain until we find our containing scope
        var scope = node.nearestScope;
        var info = {
          declared: false,
          topLevel: false,
          insideWith: false,
          type: 'undeclared'
        };
        var identifier;
        while (scope) {
          // If we are passing through a `with`, save the info
          if (scope.type === 'with') {
            info.insideWith = true;
          }

          // If it contains our variable, stop looping
          identifier = scope.identifiers[node.name];
          if (identifier !== undefined) {
            break;
          }

          // Otherwise, move to the parent scope
          scope = scope.parent;
        }

        // If we didn't find a scope or we are at the top level, mark info as top level
        if (scope === undefined || scope.node.type === 'Program') {
          info.topLevel = true;
        }

        // If we hit an identifier, save the type
        if (identifier) {
          info.type = identifier.scopeType;
        }

        // If we saw a `with`, mark `declared` as unknown
        // Attribution: https://github.com/dlsym/segmentation_fuuuu/blob/0bd35fbe215c45fda75e47c3d63df7c4be76b2c6/README.md
        // WITH(OBJ)  ________
        //         __/     /  \  FFFFFFF
        //        /   \   /__  \ FFFFFFF
        //       /  ___\  | (|  \  FFFFFF
        //       | |)  |  \__/   \  FFFUU
        //       | \ _ / ____     |  UUUU
        //       |      / VVV\_   |  UUUU
        //       |     /   ~   \  |  UUUU
        //        \   /__M_M___/  |  UUUU
        //         \_____________/   UUUU-
        if (info.insideWith === true) {
          info.declared = 'unknown';
        // Otherwise, if we didn't find a scope, marked it as undeclared
        } else if (info.type === 'undeclared') {
          info.declared = false;
        // Otherwise, mark this identifier as declared
        } else {
          info.declared = true;
        }

        // Save our info to the identifier
        node.scopeInfo = info;
        node.scope = scope;
      }
    }
  });

  // Return our marked up AST
  return ast;
}

// Export our funtion
module.exports = ecmaVariableScope;
<|endoftext|>


<commit_before>
;(function(exports, undefined) {

  function invokeListeners(val) {
    if (val && val._listeners) {
      if(val._ttl) {
        for (var k = 0, l = val._listeners.length; k < l; k++) {
          val._listeners[k].apply(this, args);
          val._ttl -= 1;
        }
        return true;
      }
    }
  }

  exports.EventEmitter2 = function EventEmitter2(conf) {
    if(conf) {
      if(conf.delimiter === '*') {
        throw new Error('The event can not be delimited by the "*" (wild-card) character.')
      }
    }
    this._delimiter = conf ? conf.delimiter : '/';
    this._events = {};
  };

  EventEmitter2.prototype.addListener = function(event, listener, ttl) {

    var name, ns = this._events;

    // Signal that a new listener is being added.
    this.emit('newListener', event, listener);

    // the name has a delimiter
    if(~event.indexOf(this._delimiter)) {

      //split the name into an array
      name = event.split(this._delimiter);

      // continue to build out additional namespaces and attach the listener to them
      for(var i = 0, l = name.length; i < l; i++) {

        // get the namespace
        ns = ns[name[i]] || (ns[name[i]] = {});

        // if this is a wild card or the completed ns, add the event
        if(i === name.length) {
          ns._listeners ? ns._listeners.push(listener) : ns._listeners = [listener];
          ns._ttl = ttl;
        }
      }
    }

    // if the name does not have a delimiter
    else {

      // get a handle to the event
      var e = ns[event] || (ns[event] = {});

      e._listeners ? e._listeners.push(listener) : e._listeners = [listener];
      e._ttl = ttl;
    }

  };

  EventEmitter2.prototype.on = EventEmitter2.prototype.addListener;

  EventEmitter2.prototype.once = function() {
    this.addListener(arguments, 1);
  };

  EventEmitter2.prototype.emit = function(event) {

    // get all the args except the event, make it a real array
    var args = [].slice.call(arguments).slice(1);

    // if there is a delimiter in the event name
    if(~event.indexOf(this._delimiter)) {

      //split the name into an array
      name = event.split(this._delimiter);

      var explore = [this._events],
          invoked = false;

      for (var i = 0; i < name.length; i++) {
        //
        // Iterate over the parts of the potentially namespaced
        // event.
        //
        //     emit('foo/*/bazz') ==> ['foo', '*', 'bazz']
        //
        var part = name[i], newSets = [], removeAt = [];

        for (var j = 0; j < explore.length; j++) {
          //
          // Iterative "unkown" set exploration: Iterate over each "unknown"
          // set of objects in the events tree. If a wildcard is discovered,
          // append that object to the unknown set and continue exploration.
          //
          var ns = explore[j];

          if (i === name.length - 1) {
            //
            // Then if we are at the end of the iteration
            // invoke all of the listeners, if not, continue
            // iterating deeper in the object
            //
            if (part === '*') {
              for (var key in ns) {
                //
                // Remark: This could cause some collisions for `_listeners`, and `_ttl`.
                //
                invokeListeners(ns[key]);
              }
              invoked = true;
            }
            else {
              if (invokeListeners(ns[part])) {
                invoked = true;
              }

              if (invokeListeners(ns['*'])) {
                invoked = true;
              }
            }
          }
          else {
            if (part !== '*') {
              if (!ns[part] && !ns['*']) {
                //
                // If it's not a wild card and there isn't a wild
                // card stored and the exact key isn't at the
                // next step of the events object, break out
                // of the loop and end evaluation.
                //
                continue;
              }

              if (ns[part]) {
                //
                // If it's not a wild card, but there is an exact
                // match for this part of the namespaced event.
                //
                if (ns['*']) {
                  newSets.push(ns['*']);
                }

                explore[j] = explore[j][part];
              }
              else if (ns['*']) {
                //
                // If the part of the namespaced event is not a wildcard,
                // but the set we are currently exploring has a wildcard
                // at this level, nest deeper for that particular set.
                //
                explore[j] = explore[j]['*'];

                if (invokeListeners(ns['*'])) {
                  invoked = true;
                }
              }
            }
            else {
              //
              // Otherwise, this part of the namespaced event is a 'wildcard',
              // in which case, we iterate over the keys of the current set,
              // and add those objects to the set to be added to the "unknown" set
              // after this level of exploration has completed.
              //
              for (var key in ns) {
                if (ns.hasOwnProperty(key)) {
                  newSets.push(ns[key]);
                }
              }

              if (invokeListeners(ns['*'])) {
                invoked = true;
              }

              removeAt.push(j);
            }
          }
        }

        for (var j = 0; j < removeAt.length; j++) {
          //
          // Remove stale sets that are no longer of interest.
          //
          explore.splice(j, 1);
        }

        if (newSets.length) {
          //
          // If this level of exploration has yielded any new sets
          // to be explored, then concatenate those sets to the "unknown" sets.
          //
          explore = explore.concat(newSets);
        }
      }

      return invoked;
    }

    // if the name does not have a delimiter
    else {

      if (!this._events[event]) {
        return false;
      }

      // get a handle to the listeners
      var listeners = this._events[event]._listeners || null;

      if (!listeners) {
        return false;
      }

      // fire off each of them
      for(var i = 0, l = listeners.length; i < l; i++) {
        listeners[i].apply(this, args);
      }
    }
  }

  EventEmitter2.prototype.removeListener = function(event) {
    this.listeners(event, true);
  };
  EventEmitter2.prototype.removeAllListeners = function() {
    for(var event in this._events) {
      this.listeners(event, null, true);
    }
  };

  EventEmitter2.prototype.listeners = function(event, listener, removeAllListeners) {

    var listeners = []; // the array of listeners to return.

    // if there is a delimiter in the event name
    if(~event.indexOf(this._delimiter)) {

      //split the name into an array
      name = event.split(this._delimiter);

      // continue to build out additional namespaces and attach the listener to them
      for (var i = 0; i < name.length; i++) {

        // get the namespace
        ns = ns[name[i]] || (ns[name[i]] = {});

        //
        // if this is a wild card or the completed ns, remove the event,
        // also reset the times to live and the time to die.
        //
        if(ns._listeners) {

          //
          // if there is only one argument to this method, we are just
          // looking to see what listeners exist and then report on that.
          //
          if(arguments.length === 1) {
            listeners.push(ns._listeners);
          } else {

            //
            // if we have some arguments, we're considering deleteing some
            // or possibly all of the listeners associated with an event.
            //
            if(removeAllListeners) {
              ns = null;
            }
            else {
              for (var i = 0; i < ns._listeners.length; i++) {
                if(ns._listeners[i] === listener) {
                  ns = null;
                }
              }
            }
          }
        }
      }
    }
    else {

      //
      // this is a simple event, no need to deconstruct the name,
      // lets just kill any listeners associated with it.
      //
      var e = this._events[event];

      if(!removeEvents) {
        listeners.push(ns._listeners);
      }
      else {
        if(removeAllListeners) {
          e = null;
        }
        else {
          for (var i = 0; i < e._listeners.length; i++) {
            if(e._listeners[i] === listener) {
              e = null;
            }
          }
        }
      }
    }

    return listeners;
  };

}((typeof exports === 'undefined') ? window : exports));
<commit_msg>[lib] typo<commit_after>
;(function(exports, undefined) {

  function invokeListeners(val, args) {
    if (val && val._listeners) {
      if(val._ttl) {
        for (var k = 0, l = val._listeners.length; k < l; k++) {
          val._listeners[k].apply(this, args);
          val._ttl -= 1;
        }
        return true;
      }
    }
  }

  exports.EventEmitter2 = function EventEmitter2(conf) {
    if(conf) {
      if(conf.delimiter === '*') {
        throw new Error('The event can not be delimited by the "*" (wild-card) character.')
      }
    }
    this._delimiter = conf ? conf.delimiter : '/';
    this._events = {};
  };

  EventEmitter2.prototype.addListener = function(event, listener, ttl) {

    var name, ns = this._events;

    // Signal that a new listener is being added.
    this.emit('newListener', event, listener);

    // the name has a delimiter
    if(~event.indexOf(this._delimiter)) {

      //split the name into an array
      name = event.split(this._delimiter);

      // continue to build out additional namespaces and attach the listener to them
      for(var i = 0, l = name.length; i < l; i++) {

        // get the namespace
        ns = ns[name[i]] || (ns[name[i]] = {});

        // if this is a wild card or the completed ns, add the event
        if(i === name.length) {
          ns._listeners ? ns._listeners.push(listener) : ns._listeners = [listener];
          ns._ttl = ttl;
        }
      }
    }

    // if the name does not have a delimiter
    else {

      // get a handle to the event
      var e = ns[event] || (ns[event] = {});

      e._listeners ? e._listeners.push(listener) : e._listeners = [listener];
      e._ttl = ttl;
    }

  };

  EventEmitter2.prototype.on = EventEmitter2.prototype.addListener;

  EventEmitter2.prototype.once = function() {
    this.addListener(arguments, 1);
  };

  EventEmitter2.prototype.emit = function(event) {

    // get all the args except the event, make it a real array
    var args = [].slice.call(arguments).slice(1);

    // if there is a delimiter in the event name
    if(~event.indexOf(this._delimiter)) {

      //split the name into an array
      name = event.split(this._delimiter);

      var explore = [this._events],
          invoked = false;

      for (var i = 0; i < name.length; i++) {
        //
        // Iterate over the parts of the potentially namespaced
        // event.
        //
        //     emit('foo/*/bazz') ==> ['foo', '*', 'bazz']
        //
        var part = name[i], newSets = [], removeAt = [];

        for (var j = 0; j < explore.length; j++) {
          //
          // Iterative "unkown" set exploration: Iterate over each "unknown"
          // set of objects in the events tree. If a wildcard is discovered,
          // append that object to the unknown set and continue exploration.
          //
          var ns = explore[j];

          if (i === name.length - 1) {
            //
            // Then if we are at the end of the iteration
            // invoke all of the listeners, if not, continue
            // iterating deeper in the object
            //
            if (part === '*') {
              for (var key in ns) {
                //
                // Remark: This could cause some collisions for `_listeners`, and `_ttl`.
                //
                invokeListeners(ns[key], args);
              }
              invoked = true;
            }
            else {
              if (invokeListeners(ns[part], args)) {
                invoked = true;
              }

              if (invokeListeners(ns['*'], args)) {
                invoked = true;
              }
            }
          }
          else {
            if (part !== '*') {
              if (!ns[part] && !ns['*']) {
                //
                // If it's not a wild card and there isn't a wild
                // card stored and the exact key isn't at the
                // next step of the events object, break out
                // of the loop and end evaluation.
                //
                continue;
              }

              if (ns[part]) {
                //
                // If it's not a wild card, but there is an exact
                // match for this part of the namespaced event.
                //
                if (ns['*']) {
                  newSets.push(ns['*']);
                }

                explore[j] = explore[j][part];
              }
              else if (ns['*']) {
                //
                // If the part of the namespaced event is not a wildcard,
                // but the set we are currently exploring has a wildcard
                // at this level, nest deeper for that particular set.
                //
                explore[j] = explore[j]['*'];

                if (invokeListeners(ns['*'], args)) {
                  invoked = true;
                }
              }
            }
            else {
              //
              // Otherwise, this part of the namespaced event is a 'wildcard',
              // in which case, we iterate over the keys of the current set,
              // and add those objects to the set to be added to the "unknown" set
              // after this level of exploration has completed.
              //
              for (var key in ns) {
                if (ns.hasOwnProperty(key)) {
                  newSets.push(ns[key]);
                }
              }

              if (invokeListeners(ns['*'], args)) {
                invoked = true;
              }

              removeAt.push(j);
            }
          }
        }

        for (var j = 0; j < removeAt.length; j++) {
          //
          // Remove stale sets that are no longer of interest.
          //
          explore.splice(j, 1);
        }

        if (newSets.length) {
          //
          // If this level of exploration has yielded any new sets
          // to be explored, then concatenate those sets to the "unknown" sets.
          //
          explore = explore.concat(newSets);
        }
      }

      return invoked;
    }

    // if the name does not have a delimiter
    else {

      if (!this._events[event]) {
        return false;
      }

      // get a handle to the listeners
      var listeners = this._events[event]._listeners || null;

      if (!listeners) {
        return false;
      }

      // fire off each of them
      for(var i = 0, l = listeners.length; i < l; i++) {
        listeners[i].apply(this, args);
      }
    }
  }

  EventEmitter2.prototype.removeListener = function(event) {
    this.listeners(event, true);
  };
  EventEmitter2.prototype.removeAllListeners = function() {
    for(var event in this._events) {
      this.listeners(event, null, true);
    }
  };

  EventEmitter2.prototype.listeners = function(event, listener, removeAllListeners) {

    var listeners = []; // the array of listeners to return.

    // if there is a delimiter in the event name
    if(~event.indexOf(this._delimiter)) {

      //split the name into an array
      name = event.split(this._delimiter);

      // continue to build out additional namespaces and attach the listener to them
      for (var i = 0; i < name.length; i++) {

        // get the namespace
        ns = ns[name[i]] || (ns[name[i]] = {});

        //
        // if this is a wild card or the completed ns, remove the event,
        // also reset the times to live and the time to die.
        //
        if(ns._listeners) {

          //
          // if there is only one argument to this method, we are just
          // looking to see what listeners exist and then report on that.
          //
          if(arguments.length === 1) {
            listeners.push(ns._listeners);
          } else {

            //
            // if we have some arguments, we're considering deleteing some
            // or possibly all of the listeners associated with an event.
            //
            if(removeAllListeners) {
              ns = null;
            }
            else {
              for (var i = 0; i < ns._listeners.length; i++) {
                if(ns._listeners[i] === listener) {
                  ns = null;
                }
              }
            }
          }
        }
      }
    }
    else {

      //
      // this is a simple event, no need to deconstruct the name,
      // lets just kill any listeners associated with it.
      //
      var e = this._events[event];

      if(!removeEvents) {
        listeners.push(ns._listeners);
      }
      else {
        if(removeAllListeners) {
          e = null;
        }
        else {
          for (var i = 0; i < e._listeners.length; i++) {
            if(e._listeners[i] === listener) {
              e = null;
            }
          }
        }
      }
    }

    return listeners;
  };

}((typeof exports === 'undefined') ? window : exports));
<|endoftext|>