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; +}