Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions test-app/app/src/main/assets/app/mainpage.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ require("./tests/requireExceptionTests");
require("./tests/java-array-test");
require("./tests/field-access-test");
require("./tests/byte-buffer-test");
require("./tests/shared-array-buffer-test");
require("./tests/dex-interface-implementation");
require("./tests/testInterfaceImplementation");
require("./tests/testRuntimeImplementedAPIs");
Expand Down
2 changes: 1 addition & 1 deletion test-app/app/src/main/assets/app/shared
91 changes: 91 additions & 0 deletions test-app/app/src/main/assets/app/tests/shared-array-buffer-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
describe("Tests SharedArrayBuffer conversion", function () {
it("should pass a SharedArrayBuffer to a Java method expecting ByteBuffer", function () {
var sab = new SharedArrayBuffer(8);
var view = new Uint8Array(sab);
for (var i = 0; i < 8; i++) {
view[i] = i + 1;
}

// resolves the ByteBuffer.put(ByteBuffer) overload and copies from the
// direct buffer created over the SharedArrayBuffer's memory
var bb = java.nio.ByteBuffer.allocateDirect(8);
bb.put(sab);
bb.flip();

var roundTripped = new Uint8Array(ArrayBuffer.from(bb));
for (var i = 0; i < 8; i++) {
expect(roundTripped[i]).toBe(i + 1);
}
});

it("should respect byteOffset and length of typed array views over a SharedArrayBuffer", function () {
var sab = new SharedArrayBuffer(16);
var full = new Uint8Array(sab);
for (var i = 0; i < 16; i++) {
full[i] = i;
}

var slice = new Uint8Array(sab, 4, 8); // bytes 4..11

var bb = java.nio.ByteBuffer.allocateDirect(8);
bb.put(slice);
bb.flip();

var roundTripped = new Uint8Array(ArrayBuffer.from(bb));
for (var i = 0; i < 8; i++) {
expect(roundTripped[i]).toBe(i + 4);
}
});

it("should share memory between the SharedArrayBuffer and the Java buffer (no copy)", function () {
var sab = new SharedArrayBuffer(4);
var view = new Uint8Array(sab);
view[0] = 42;

// the holder keeps the direct ByteBuffer the runtime created over the
// SharedArrayBuffer's memory, so Java reads/writes go to the same bytes
var holder = new com.tns.tests.ByteBufferHolder();
holder.hold(sab);
expect(holder.get(0)).toBe(42);

// JS mutations after the call are visible through the Java buffer
view[0] = 99;
expect(holder.get(0)).toBe(99);

// and Java mutations are visible through the SharedArrayBuffer
holder.put(1, 77);
expect(view[1]).toBe(77);
});

it("should share a SharedArrayBuffer's memory with a worker and a Java buffer at once", function (done) {
var sab = new SharedArrayBuffer(4);
var view = new Uint8Array(sab);
view[0] = 0;

var holder = new com.tns.tests.ByteBufferHolder();
holder.hold(sab);

var worker = new Worker("../shared/Workers/EvalWorker.js");
worker.postMessage({
value: sab,
eval: "var v = new Uint8Array(value); v[0] = 42; v[3] = 99; postMessage('written');"
});
// fail fast instead of waiting for the jasmine timeout if the worker
// errors before posting back
worker.onerror = function (e) {
expect("worker error: " + e.message).toBe("");
worker.terminate();
done();
};
worker.onmessage = function (msg) {
expect(msg.data).toBe("written");
// the worker's write is visible both to this isolate and to Java
expect(view[0]).toBe(42);
expect(view[3]).toBe(99);
expect(holder.get(0)).toBe(42);
expect(holder.get(3)).toBe(99);
worker.terminate();
done();
};
Comment on lines +68 to +89

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the file explicitly
FILE="test-app/app/src/main/assets/app/tests/shared-array-buffer-test.js"
ls -la "$FILE"

# Show the relevant section around lines 50-90
nl -ba "$FILE" | sed -n '40,110p'

# Search in repo for other references to this test or similar patterns
rg -n "shared-array-buffer-test\.js|EvalWorker\.js|new Worker\\(\"\\.\\./shared/Workers/EvalWorker\.js\"\\)" -S .

# Inspect EvalWorker.js for any messaging/error behavior
WORKER="test-app/app/src/main/assets/app/tests/shared/Workers/EvalWorker.js"
ls -la "$WORKER" || true
if [ -f "$WORKER" ]; then
  nl -ba "$WORKER" | sed -n '1,220p'
fi

# Find any test harness utilities: "done", timeouts, or expect patterns
rg -n "function \\(msg\\)|onmessage|onerror|setTimeout\\(|jest\\.setTimeout|done\\(" -S test-app/app/src/main/assets/app/tests | head

Repository: NativeScript/android

Length of output: 241


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="test-app/app/src/main/assets/app/tests/shared-array-buffer-test.js"
ls -la "$FILE"
nl -ba "$FILE" | sed -n '40,110p'

rg -n "shared-array-buffer-test\\.js|EvalWorker\\.js|new Worker\\(\"\\.\\./shared/Workers/EvalWorker\\.js\"\\)" -S .

WORKER="test-app/app/src/main/assets/app/tests/shared/Workers/EvalWorker.js"
ls -la "$WORKER" || true
if [ -f "$WORKER" ]; then
  nl -ba "$WORKER" | sed -n '1,260p'
fi

rg -n "onerror|addEventListener\\(['\"]error['\"]|setTimeout\\(|jest\\.setTimeout|done\\(" -S test-app/app/src/main/assets/app/tests | head -n 80

Repository: NativeScript/android

Length of output: 241


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="test-app/app/src/main/assets/app/tests/shared-array-buffer-test.js"
ls -la "$FILE"
nl -ba "$FILE" | sed -n '40,110p'

echo "---- searching for worker error handling patterns ----"
rg -n "onerror|addEventListener\\(['\"]error['\"]|addEventListener\\(\\s*\"error\"|onmessageerror|messageerror|worker\\.onerror|worker\\.addEventListener\\(['\"]error['\"]" -S test-app/app/src/main/assets/app/tests/shared test-app/app/src/main/assets/app/tests | head -n 200 || true

echo "---- inspect EvalWorker.js ----"
WORKER="test-app/app/src/main/assets/app/tests/shared/Workers/EvalWorker.js"
ls -la "$WORKER" || true
if [ -f "$WORKER" ]; then
  nl -ba "$WORKER" | sed -n '1,260p'
fi

echo "---- search for similar tests that add onerror/timeout ----"
rg -n "new Worker\\(|postMessage\\(|terminate\\(\\);\\s*\\n\\s*done\\(|worker\\.terminate\\(\\)" -S test-app/app/src/main/assets/app/tests | head -n 200

Repository: NativeScript/android

Length of output: 241


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="test-app/app/src/main/assets/app/tests/shared-array-buffer-test.js"
WORKER="test-app/app/src/main/assets/app/tests/shared/Workers/EvalWorker.js"

echo "== file exists =="
ls -la "$FILE"

echo "== shared-array-buffer-test.js (lines 1-170) =="
awk 'NR>=1 && NR<=170 { printf "%6d %s\n", NR, $0 }' "$FILE"

echo "== shared-array-buffer-test.js (lines 40-110) =="
awk 'NR>=40 && NR<=110 { printf "%6d %s\n", NR, $0 }' "$FILE"

echo "== search for worker error handling / timeout in this test folder =="
rg -n "onerror|addEventListener\\(['\"]error['\"]\\)|onmessageerror|messageerror|setTimeout\\(|jest\\.setTimeout|timeout" \
  -S test-app/app/src/main/assets/app/tests/shared-array-buffer-test.js test-app/app/src/main/assets/app/tests/shared || true

echo "== inspect EvalWorker.js =="
if [ -f "$WORKER" ]; then
  ls -la "$WORKER"
  awk 'NR>=1 && NR<=220 { printf "%6d %s\n", NR, $0 }' "$WORKER"
else
  echo "MISSING: $WORKER"
fi

echo "== search for other shared-array-buffer tests with worker.onerror =="
rg -n "new Worker\\(|worker\\.onerror|addEventListener\\(['\"]error['\"]\\).*Worker|onmessageerror" \
  -S test-app/app/src/main/assets/app/tests || true

Repository: NativeScript/android

Length of output: 5318


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate EvalWorker.js by filename =="
fd -a -u -i "EvalWorker.js" . || true

echo "== locate any Workers/EvalWorker* =="
fd -a -u -i "*/EvalWorker.js" . || true

echo "== list directories named shared under this assets/tests =="
fd -a -u -i -t d "shared" test-app/app/src/main/assets/app/tests . || true

echo "== search for onerror handling in test-app/app/src/main/assets/app/tests =="
rg -n "worker\\.(onerror|addEventListener\\(['\"]error['\"])|onmessageerror|onerror\\s*=" \
  test-app/app/src/main/assets/app/tests -S || true

echo "== inspect referenced worker in testWebAssembly.js for error handling patterns =="
FILE2="test-app/app/src/main/assets/app/tests/testWebAssembly.js"
if [ -f "$FILE2" ]; then
  awk 'NR>=40 && NR<=120 { printf "%6d %s\n", NR, $0 }' "$FILE2"
else
  echo "Missing $FILE2"
fi

Repository: NativeScript/android

Length of output: 2324


🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -a -u -i "EvalWorker.js" . || true

Repository: NativeScript/android

Length of output: 46


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate EvalWorker.js by filename =="
fd -a -u -i "EvalWorker.js" . || true

echo "== locate any file containing 'EvalWorker' =="
rg -n "EvalWorker" -S . | head -n 50 || true

echo "== search for worker error handling patterns in assets/app/tests =="
rg -n "onerror|onmessageerror|worker\\.onerror|addEventListener\\(['\"]error['\"]\\)" \
  -S test-app/app/src/main/assets/app/tests | head -n 200 || true

echo "== inspect testWebAssembly.js around worker setup =="
FILE2="test-app/app/src/main/assets/app/tests/testWebAssembly.js"
if [ -f "$FILE2" ]; then
  awk 'NR>=45 && NR<=110 { printf "%6d %s\n", NR, $0 }' "$FILE2"
fi

Repository: NativeScript/android

Length of output: 1752


🏁 Script executed:

# no-op placeholder

Repository: NativeScript/android

Length of output: 46


Add a worker error/timeout path so this spec can’t hang.

The async test ("should share a SharedArrayBuffer's memory with a worker and a Java buffer at once") calls done() only from worker.onmessage; there’s no worker.onerror/onmessageerror handler (and EvalWorker.js isn’t present to inspect any built-in handling). If worker startup or postMessage fails before onmessage, the spec will wait for the harness timeout instead of failing immediately.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test-app/app/src/main/assets/app/tests/shared-array-buffer-test.js` around
lines 62 - 74, The test can hang because it only calls done() from
worker.onmessage; add a worker error/timeout path: attach worker.onerror and
worker.onmessageerror handlers that call done.fail(...) (or fail the test) and
terminate the worker, and implement a short watchdog timer (clear it on success)
that fails the spec and terminates the worker if no message/error arrives within
e.g. a few seconds; update the block that creates
Worker("../shared/Workers/EvalWorker.js"), worker.postMessage(...), and
worker.onmessage to also set up these handlers and the timeout so the spec
always completes on error or timeout.

});
});
24 changes: 24 additions & 0 deletions test-app/app/src/main/java/com/tns/tests/ByteBufferHolder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.tns.tests;

import java.nio.ByteBuffer;

/*
* Used by shared-array-buffer-test.js to verify that JS (Shared)ArrayBuffers
* marshal to Java as direct ByteBuffers over the same memory.
*/
public class ByteBufferHolder {
private ByteBuffer buffer;

public ByteBuffer hold(ByteBuffer buffer) {
this.buffer = buffer;
return this.buffer;
}

public byte get(int index) {
return buffer.get(index);
}

public void put(int index, byte value) {
buffer.put(index, value);
}
}
4 changes: 4 additions & 0 deletions test-app/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ add_library(
src/main/cpp/ArrayHelper.cpp
src/main/cpp/AssetExtractor.cpp
src/main/cpp/CallbackHandlers.cpp
src/main/cpp/ConcurrentQueue.cpp
src/main/cpp/Constants.cpp
src/main/cpp/DirectBuffer.cpp
src/main/cpp/FieldAccessor.cpp
Expand All @@ -112,6 +113,7 @@ add_library(
src/main/cpp/JsArgToArrayConverter.cpp
src/main/cpp/JSONObjectHelper.cpp
src/main/cpp/Logger.cpp
src/main/cpp/LooperTasks.cpp
src/main/cpp/ManualInstrumentation.cpp
src/main/cpp/MessageLoopTimer.cpp
src/main/cpp/MetadataMethodInfo.cpp
Expand All @@ -135,6 +137,8 @@ add_library(
src/main/cpp/V8GlobalHelpers.cpp
src/main/cpp/V8StringConstants.cpp
src/main/cpp/WeakRef.cpp
src/main/cpp/WorkerMessage.cpp
src/main/cpp/WorkerWrapper.cpp
src/main/cpp/Timers.cpp
src/main/cpp/com_tns_AssetExtractor.cpp
src/main/cpp/com_tns_Runtime.cpp
Expand Down
Loading