diff --git a/JS-Interpreters/ecmaref6/bindings/node-bindings.esl b/JS-Interpreters/ecmaref6/bindings/node-bindings.esl
index dc46ec0418..7d2cb4e232 100644
--- a/JS-Interpreters/ecmaref6/bindings/node-bindings.esl
+++ b/JS-Interpreters/ecmaref6/bindings/node-bindings.esl
@@ -37,8 +37,8 @@ function push_globals() {
|global| := 'undefined;
|realm|["globalThis"] := 'undefined;
|ctxStack| := stack_make();
- |ScriptJobQueue| := [];
- |PromiseJobQueue| := [];
+ |ScriptJobQueue| := queue_make();
+ |PromiseJobQueue| := queue_make();
stack_push(|globals_stack|, saved_globals);
return;
}
diff --git a/JS-Interpreters/ecmaref6/esl_sections.esl b/JS-Interpreters/ecmaref6/esl_sections.esl
index 41dd331140..1625be072f 100644
--- a/JS-Interpreters/ecmaref6/esl_sections.esl
+++ b/JS-Interpreters/ecmaref6/esl_sections.esl
@@ -1,22 +1,23 @@
/* Copyright (C) 2022-2025 formalsec programmers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-import fpath;
import os;
+import fpath;
import stack;
+import queue;
import stdlib;
import "section 6/section_6.1.esl";
diff --git a/JS-Interpreters/ecmaref6/section 8/section_8.4.esl b/JS-Interpreters/ecmaref6/section 8/section_8.4.esl
index ea7ea52594..769713587e 100644
--- a/JS-Interpreters/ecmaref6/section 8/section_8.4.esl
+++ b/JS-Interpreters/ecmaref6/section 8/section_8.4.esl
@@ -1,31 +1,31 @@
/* Copyright (C) 2022-2025 formalsec programmers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/* Called in ESL_Interpreter.esl at the start of the program's execution */
function initJobQueue() {
- |ScriptJobQueue| := [];
- |PromiseJobQueue| := [];
+ |ScriptJobQueue| := queue_make();
+ |PromiseJobQueue| := queue_make();
return;
}
function appendToJobQueue(job, queueName) {
if (queueName == "PromiseJobs")
- |PromiseJobQueue| := l_add(|PromiseJobQueue|, job);
+ enqueue(|PromiseJobQueue|, job);
else
- |ScriptJobQueue| := l_add(|ScriptJobQueue|, job);
+ enqueue(|ScriptJobQueue|, job);
return;
}
@@ -121,12 +121,10 @@ function NextJob(result) {
/* Let nextQueue be a non-empty Job Queue chosen in an implementation defined manner. If all Job Queues are
empty, the result is implementation defined. */
- if (l_len(|ScriptJobQueue|) != 0) {
- nextPending := hd |ScriptJobQueue|;
- |ScriptJobQueue| := tl |ScriptJobQueue|;
- } else if (l_len(|PromiseJobQueue|) != 0) {
- nextPending := hd |PromiseJobQueue|;
- |PromiseJobQueue| := tl |PromiseJobQueue|;
+ if (!queue_is_empty(|ScriptJobQueue|)) {
+ nextPending := dequeue(|ScriptJobQueue|);
+ } else if (!queue_is_empty(|PromiseJobQueue|)) {
+ nextPending := dequeue(|PromiseJobQueue|);
} else {
return result;
}
diff --git a/stdlib/dune b/stdlib/dune
index adb7a9450e..88ab7af4b5 100644
--- a/stdlib/dune
+++ b/stdlib/dune
@@ -2,4 +2,4 @@
(section
(site
(ecma-sl stdlib)))
- (files fpath.esl os.esl stack.esl stdlib.esl))
+ (files fpath.esl os.esl stack.esl stdlib.esl queue.esl))
diff --git a/stdlib/queue.esl b/stdlib/queue.esl
new file mode 100644
index 0000000000..65ad6a738c
--- /dev/null
+++ b/stdlib/queue.esl
@@ -0,0 +1,91 @@
+/* Copyright (C) 2022-2025 formalsec programmers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+function queue_node_make(value) {
+ return { value: value, next: null };
+}
+
+function queue_make() {
+ return { front: null, rear: null };
+}
+
+function queue_is_empty(queue) {
+ return queue.front == null;
+}
+
+function enqueue(queue, val) {
+ let new_node = queue_node_make(val);
+
+ if (queue.front == null) {
+ queue.front := new_node;
+ } else {
+ queue.rear.next := new_node;
+ }
+
+ queue.rear := new_node;
+ queue.rear.next := queue.front;
+ return;
+}
+
+function dequeue(queue) {
+ if (queue_is_empty(queue)) {
+ return null;
+ }
+
+ value := null;
+ if (queue.front == queue.rear) {
+ value := queue.front.value;
+ queue.front := null;
+ queue.rear := null;
+ } else {
+ /* FIXME: We should delete the objects we removed? */
+ tmp := queue.front;
+ value := tmp.value;
+ queue.front := queue.front.next;
+ queue.rear.next := queue.front;
+ }
+ return value;
+}
+
+function front(queue) {
+ if (queue_is_empty(queue)) {
+ return null;
+ }
+ return queue.front.value;
+}
+
+function rear(queue) {
+ if (queue_is_empty(queue)) {
+ return null;
+ }
+ return queue.rear.value;
+}
+
+function queue_iter(f, queue) {
+ if (queue_is_empty(queue)) {
+ return;
+ }
+ curr := queue.front;
+ exit := false;
+ while (!exit) {
+ {f}(curr.value);
+ curr := curr.next;
+ if (curr == queue.front) {
+ exit := true;
+ }
+ }
+ return;
+}
diff --git a/test/ecma-sl/dune b/test/ecma-sl/dune
index 6ad88c6c09..71579fd7a5 100644
--- a/test/ecma-sl/dune
+++ b/test/ecma-sl/dune
@@ -8,4 +8,5 @@
test_stdlib_fpath.esl
test_stdlib_import.esl
test_stdlib_inequality.esl
- test_stdlib_list.esl))
+ test_stdlib_list.esl
+ test_stdlib_queue.esl))
diff --git a/test/ecma-sl/test_stdlib.t b/test/ecma-sl/test_stdlib.t
index da7a7cc707..faff6a09ae 100644
--- a/test/ecma-sl/test_stdlib.t
+++ b/test/ecma-sl/test_stdlib.t
@@ -35,3 +35,5 @@ Tests list operators:
[ecma-sl] exit value: 0
$ ecma-sl interpret test_stdlib_fpath.esl --exitval
[ecma-sl] exit value: 0
+ $ ecma-sl interpret test_stdlib_queue.esl --exitval
+ [ecma-sl] exit value: 0
diff --git a/test/ecma-sl/test_stdlib_queue.esl b/test/ecma-sl/test_stdlib_queue.esl
new file mode 100644
index 0000000000..82f0def8cf
--- /dev/null
+++ b/test/ecma-sl/test_stdlib_queue.esl
@@ -0,0 +1,16 @@
+import queue;
+import stdlib;
+
+function main() {
+ let q = queue_make();
+ enqueue(q, 1);
+ enqueue(q, 2);
+ enqueue(q, 3);
+ enqueue(q, 4);
+ assert(dequeue(q) == 1);
+ assert(dequeue(q) == 2);
+ assert(dequeue(q) == 3);
+ assert(dequeue(q) == 4);
+ assert(queue_is_empty(q));
+ return 0;
+}