tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit eb85973e23d6bbb248e9b91fcea86fd183c5952b
parent e4db1e137beccd337d4b8ae82e3438cdc6851356
Author: Matthew Gaudet <mgaudet@mozilla.com>
Date:   Wed,  1 Oct 2025 21:38:47 +0000

Bug 1977466 - Support adding to the front of a Fifo r=jonco

Also adds a unit test for the data structure.

Differential Revision: https://phabricator.services.mozilla.com/D257358

Diffstat:
Mjs/src/ds/Fifo.h | 7+++++++
Mjs/src/jsapi-tests/moz.build | 1+
Ajs/src/jsapi-tests/testFifo.cpp | 180+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 188 insertions(+), 0 deletions(-)

diff --git a/js/src/ds/Fifo.h b/js/src/ds/Fifo.h @@ -127,6 +127,13 @@ class Fifo { return true; } + // Construct a T in-place at the front of the queue, + // making it the next to be popped off. + template <typename... Args> + [[nodiscard]] bool emplaceFront(Args&&... args) { + return front_.emplaceBack(std::forward<Args>(args)...); + } + // Access the element at the front of the queue. T& front() { MOZ_ASSERT(!empty()); diff --git a/js/src/jsapi-tests/moz.build b/js/src/jsapi-tests/moz.build @@ -48,6 +48,7 @@ UNIFIED_SOURCES += [ "testException.cpp", "testExecuteInJSMEnvironment.cpp", "testExternalStrings.cpp", + "testFifo.cpp", "testFindSCCs.cpp", "testForceLexicalInitialization.cpp", "testForOfIterator.cpp", diff --git a/js/src/jsapi-tests/testFifo.cpp b/js/src/jsapi-tests/testFifo.cpp @@ -0,0 +1,180 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "ds/Fifo.h" + +#include "jsapi-tests/tests.h" + +// Test with primitive type (int) +BEGIN_TEST(testFifoPrimitive) { + js::Fifo<int, 0, js::SystemAllocPolicy> fifo; + + // Test initial state + CHECK(fifo.empty()); + CHECK(fifo.length() == 0); + + // Test emplaceBack + CHECK(fifo.emplaceBack(1)); + CHECK(!fifo.empty()); + CHECK(fifo.length() == 1); + CHECK(fifo.front() == 1); + + CHECK(fifo.emplaceBack(2)); + CHECK(fifo.emplaceBack(3)); + CHECK(fifo.length() == 3); + CHECK(fifo.front() == 1); + + // Test popFront + fifo.popFront(); + CHECK(fifo.length() == 2); + CHECK(fifo.front() == 2); + + // Test emplaceFront + CHECK(fifo.emplaceFront(10)); + CHECK(fifo.length() == 3); + CHECK(fifo.front() == 10); + + // Fill to 5 elements + CHECK(fifo.emplaceBack(4)); + CHECK(fifo.emplaceBack(5)); + CHECK(fifo.length() == 5); + + // Verify order by popping all + CHECK(fifo.front() == 10); + fifo.popFront(); + CHECK(fifo.front() == 2); + fifo.popFront(); + CHECK(fifo.front() == 3); + fifo.popFront(); + CHECK(fifo.front() == 4); + fifo.popFront(); + CHECK(fifo.front() == 5); + fifo.popFront(); + + CHECK(fifo.empty()); + CHECK(fifo.length() == 0); + + // Test clear + CHECK(fifo.emplaceBack(100)); + CHECK(fifo.emplaceBack(200)); + CHECK(fifo.length() == 2); + fifo.clear(); + CHECK(fifo.empty()); + CHECK(fifo.length() == 0); + + return true; +} +END_TEST(testFifoPrimitive) + +// Simple copyable class for testing +struct SimpleCopyable { + int value; + bool* destructorCalled; + + explicit SimpleCopyable(int v, bool* dc = nullptr) + : value(v), destructorCalled(dc) {} + + SimpleCopyable(const SimpleCopyable& other) = default; + SimpleCopyable& operator=(const SimpleCopyable& other) = default; + + ~SimpleCopyable() { + if (destructorCalled) { + *destructorCalled = true; + } + } +}; + +BEGIN_TEST(testFifoCopyable) { + js::Fifo<SimpleCopyable, 0, js::SystemAllocPolicy> fifo; + + // Test initial state + CHECK(fifo.empty()); + CHECK(fifo.length() == 0); + + // Test emplaceBack with constructor args + CHECK(fifo.emplaceBack(1, nullptr)); + CHECK(fifo.emplaceBack(2, nullptr)); + CHECK(fifo.length() == 2); + CHECK(fifo.front().value == 1); + + // Test emplaceFront + CHECK(fifo.emplaceFront(0, nullptr)); + CHECK(fifo.length() == 3); + CHECK(fifo.front().value == 0); + + // Pop and verify order + fifo.popFront(); + CHECK(fifo.front().value == 1); + fifo.popFront(); + CHECK(fifo.front().value == 2); + CHECK(fifo.length() == 1); + + // Test destructor is called on clear + bool destructorCalled = false; + CHECK(fifo.emplaceBack(99, &destructorCalled)); + CHECK(fifo.length() == 2); + CHECK(!destructorCalled); + + fifo.clear(); + CHECK(destructorCalled); + CHECK(fifo.empty()); + + // Test with 5 elements + CHECK(fifo.emplaceBack(10, nullptr)); + CHECK(fifo.emplaceBack(20, nullptr)); + CHECK(fifo.emplaceBack(30, nullptr)); + CHECK(fifo.emplaceFront(5, nullptr)); + CHECK(fifo.emplaceBack(40, nullptr)); + CHECK(fifo.length() == 5); + + // Verify FIFO order + CHECK(fifo.front().value == 5); + fifo.popFront(); + CHECK(fifo.front().value == 10); + fifo.popFront(); + CHECK(fifo.front().value == 20); + fifo.popFront(); + CHECK(fifo.front().value == 30); + fifo.popFront(); + CHECK(fifo.front().value == 40); + fifo.popFront(); + CHECK(fifo.empty()); + + return true; +} +END_TEST(testFifoCopyable) + +// Test mixing emplaceBack and emplaceFront operations +BEGIN_TEST(testFifoMixedOperations) { + js::Fifo<int, 0, js::SystemAllocPolicy> fifo; + + // Interleave front and back operations + CHECK(fifo.emplaceBack(3)); // Queue: [3] + CHECK(fifo.emplaceFront(1)); // Queue: [1, 3] + CHECK(fifo.emplaceBack(5)); // Queue: [1, 3, 5] + CHECK(fifo.emplaceFront(0)); // Queue: [0, 1, 3, 5] + CHECK(fifo.emplaceBack(7)); // Queue: [0, 1, 3, 5, 7] + + CHECK(fifo.length() == 5); + + // Verify order + CHECK(fifo.front() == 0); + fifo.popFront(); + CHECK(fifo.front() == 1); + fifo.popFront(); + CHECK(fifo.front() == 3); + fifo.popFront(); + CHECK(fifo.front() == 5); + fifo.popFront(); + CHECK(fifo.front() == 7); + fifo.popFront(); + + CHECK(fifo.empty()); + + return true; +} +END_TEST(testFifoMixedOperations)