Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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