Commit 505cccb9 authored by Sam Clegg's avatar Sam Clegg Committed by Commit Bot

[d8] Update `new Worker` API to match the Web API

Previously we only supported strings and not filenames.  This
changes the default to filename and adds a new `type: string` which can
be passed `options` to allow for strings to be passed in test code.

See: https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker

Bug: v8:8020
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Change-Id: Ie8818885c5c5c071b6614852322cb45aeb01a647
Reviewed-on: https://chromium-review.googlesource.com/1185980
Commit-Queue: Sam Clegg <sbc@chromium.org>
Reviewed-by: 's avatarBen Smith <binji@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56056}
parent efc79717
......@@ -280,6 +280,14 @@ static Local<Value> Throw(Isolate* isolate, const char* message) {
.ToLocalChecked());
}
static Local<Value> GetValue(v8::Isolate* isolate, Local<Context> context,
Local<v8::Object> object, const char* property) {
Local<String> v8_str =
String::NewFromUtf8(isolate, property, NewStringType::kNormal)
.ToLocalChecked();
return object->Get(context, v8_str).ToLocalChecked();
}
Worker* GetWorkerFromInternalField(Isolate* isolate, Local<Object> object) {
if (object->InternalFieldCount() != 1) {
Throw(isolate, "this is not a Worker");
......@@ -397,14 +405,6 @@ class TraceConfigParser {
}
return platform::tracing::TraceRecordMode::RECORD_UNTIL_FULL;
}
static Local<Value> GetValue(v8::Isolate* isolate, Local<Context> context,
Local<v8::Object> object, const char* property) {
Local<String> v8_str =
String::NewFromUtf8(isolate, property, NewStringType::kNormal)
.ToLocalChecked();
return object->Get(context, v8_str).ToLocalChecked();
}
};
} // namespace
......@@ -1441,6 +1441,39 @@ void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
return;
}
// d8 honors `options={type: string}`, which means the first argument is
// not a filename but string of script to be run.
bool load_from_file = true;
if (args.Length() > 1 && args[1]->IsObject()) {
Local<Object> object = args[1].As<Object>();
Local<Context> context = isolate->GetCurrentContext();
Local<Value> value = GetValue(args.GetIsolate(), context, object, "type");
if (value->IsString()) {
Local<String> worker_type = value->ToString(context).ToLocalChecked();
String::Utf8Value str(isolate, worker_type);
if (strcmp("string", *str) == 0) {
load_from_file = false;
} else if (strcmp("classic", *str) == 0) {
load_from_file = true;
} else {
Throw(args.GetIsolate(), "Unsupported worker type");
return;
}
}
}
Local<Value> source;
if (load_from_file) {
String::Utf8Value filename(args.GetIsolate(), args[0]);
source = ReadFile(args.GetIsolate(), *filename);
if (source.IsEmpty()) {
Throw(args.GetIsolate(), "Error loading worker script");
return;
}
} else {
source = args[0];
}
if (!args.IsConstructCall()) {
Throw(args.GetIsolate(), "Worker must be constructed with new");
return;
......@@ -1464,7 +1497,7 @@ void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
args.Holder()->SetAlignedPointerInInternalField(0, worker);
workers_.push_back(worker);
String::Utf8Value script(args.GetIsolate(), args[0]);
String::Utf8Value script(args.GetIsolate(), source);
if (!*script) {
Throw(args.GetIsolate(), "Can't get worker script");
return;
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Verify that the Worker constrcutor by default treats its first argument
// as the filename of a script load and run.
if (this.Worker) {
var w = new Worker('test/mjsunit/d8/d8-worker-script.txt');
assertEquals("Starting worker", w.getMessage());
w.postMessage("");
assertEquals("DONE", w.getMessage());
w.terminate();
}
// Worker script used by d8-worker-script.js.
// This file is named `.txt` to prevent it being treated as a test itself.
onmessage = function(m) {
postMessage('DONE');
}
postMessage('Starting worker');
......@@ -45,7 +45,7 @@ if (this.Worker) {
Atomics.store(ta, 0, 100);
};`;
var w = new Worker(workerScript);
var w = new Worker(workerScript, {type: 'string'});
var sab = new SharedArrayBuffer(16);
var ta = new Uint32Array(sab);
......@@ -84,7 +84,7 @@ if (this.Worker) {
var id;
var workers = [];
for (id = 0; id < 4; ++id) {
workers[id] = new Worker(workerScript);
workers[id] = new Worker(workerScript, {type: 'string'});
workers[id].postMessage({sab: sab, id: id});
}
......
......@@ -27,14 +27,14 @@
if (this.Worker) {
var workerScript =
`var w = new Worker('postMessage(42)');
`var w = new Worker('postMessage(42)', {type: 'string'});
onmessage = function(parentMsg) {
w.postMessage(parentMsg);
var childMsg = w.getMessage();
postMessage(childMsg);
};`;
var w = new Worker(workerScript);
var w = new Worker(workerScript, {type: 'string'});
w.postMessage(9);
assertEquals(42, w.getMessage());
}
......@@ -97,7 +97,21 @@ if (this.Worker) {
return ab;
}
var w = new Worker(workerScript);
assertThrows(function() {
// Second arg must be 'options' object
new Worker(workerScript, 123);
});
assertThrows(function() {
new Worker('test/mjsunit/d8/d8-worker.js', {type: 'invalid'});
});
assertThrows(function() {
// worker type defaults to 'classic' which tries to load from file
new Worker(workerScript);
});
var w = new Worker(workerScript, {type: 'string'});
assertEquals("Starting worker", w.getMessage());
......@@ -156,7 +170,7 @@ if (this.Worker) {
// Make sure that the main thread doesn't block forever in getMessage() if
// the worker dies without posting a message.
var w2 = new Worker('');
var w2 = new Worker('', {type: 'string'});
var msg = w2.getMessage();
assertEquals(undefined, msg);
}
......@@ -12,7 +12,7 @@ var workerScript =
`onmessage=function(msg) {
postMessage(0);
};`;
var worker = new Worker(workerScript);
var worker = new Worker(workerScript, {type: 'string'});
var value_obj = {
valueOf: function() {worker.postMessage({sab:sab}, [sta.buffer]);
......
......@@ -133,7 +133,7 @@ if (this.Worker) {
postMessage(result);
};`;
var worker = new Worker(workerScript);
var worker = new Worker(workerScript, {type: 'string'});
worker.postMessage({sab: sab, offset: offset});
// Spin until the worker is waiting on the futex.
......@@ -143,7 +143,7 @@ if (this.Worker) {
assertEquals("ok", worker.getMessage());
worker.terminate();
var worker2 = new Worker(workerScript);
var worker2 = new Worker(workerScript, {type: 'string'});
var offset = 8;
var i32a2 = new Int32Array(sab, offset);
worker2.postMessage({sab: sab, offset: offset});
......@@ -156,7 +156,7 @@ if (this.Worker) {
// Futex should work when index and buffer views are different, but
// the real address is the same.
var worker3 = new Worker(workerScript);
var worker3 = new Worker(workerScript, {type: 'string'});
i32a2 = new Int32Array(sab, 4);
worker3.postMessage({sab: sab, offset: 8});
......@@ -205,7 +205,7 @@ if (this.Worker) {
var id;
var workers = [];
for (id = 0; id < 4; id++) {
workers[id] = new Worker(workerScript);
workers[id] = new Worker(workerScript, {type: 'string'});
workers[id].postMessage({sab: sab, id: id});
}
......
......@@ -13,7 +13,7 @@ function foo() {
return Worker.__f_0(-2147483648, __f_0);
};
var __v_9 = new Worker('');
var __v_9 = new Worker('', {type: 'string'});
__f_1 = {s: Math.s, __f_1: true};
}
}
......
......@@ -17,7 +17,7 @@ if (this.Worker) {
});
// Don't throw for real worker
var worker = new Worker('');
var worker = new Worker('', {type: 'string'});
worker.getMessage();
worker.postMessage({});
worker.terminate();
......
......@@ -4,7 +4,7 @@
if (this.Worker && this.quit) {
try {
new Function(new Worker("55"));
new Function(new Worker("55"), {type: 'string'});
} catch(err) {}
quit();
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
const worker = new Worker("onmessage = function(){}");
const worker = new Worker("onmessage = function(){}", {type: 'string'});
const buffer = new ArrayBuffer();
worker.postMessage(buffer, [buffer]);
try {
......
......@@ -8,7 +8,7 @@ if (this.Worker) {
var __v_5 = new Uint32Array(__v_1);
return __v_5;
}
var __v_6 = new Worker('onmessage = function() {}');
var __v_6 = new Worker('onmessage = function() {}', {type: 'string'});
var __v_3 = __f_0(16);
__v_6.postMessage(__v_3);
}
......@@ -5,5 +5,5 @@
// Flags: --invoke-weak-callbacks
if (this.Worker) {
var __v_6 = new Worker('');
var __v_6 = new Worker('', {type: 'string'});
}
......@@ -8,6 +8,6 @@ if (this.Worker) {
this.l = [new __f_0, new __f_0];
}
__v_6 = new __f_1;
var __v_9 = new Worker('');
var __v_9 = new Worker('', {type: 'string'});
__v_9.postMessage(__v_6);
}
......@@ -4,6 +4,6 @@
if (this.Worker) {
__v_3 = "";
var __v_6 = new Worker('');
var __v_6 = new Worker('', {type: 'string'});
__v_6.postMessage(__v_3);
}
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
if (this.Worker) {
var __v_10 = new Worker('');
var __v_10 = new Worker('', {type: 'string'});
__v_10.terminate();
__v_10.getMessage();
}
......@@ -5,5 +5,5 @@
// Flags: --no-test
if (this.Worker) {
var __v_2 = new Worker('');
var __v_2 = new Worker('', {type: 'string'});
}
......@@ -5,5 +5,5 @@
if (this.Worker) {
Function.prototype.toString = "foo";
function __f_7() {}
assertThrows(function() { var __v_5 = new Worker(__f_7.toString()); });
assertThrows(function() { var __v_5 = new Worker(__f_7.toString(), {type: 'string'}) });
}
......@@ -3,6 +3,6 @@
// found in the LICENSE file.
if (this.Worker) {
var __v_7 = new Worker('onmessage = function() {}');
var __v_7 = new Worker('onmessage = function() {}', {type: 'string'});
__v_7.postMessage("");
}
......@@ -5,6 +5,6 @@
if (this.Worker) {
var __v_5 = {};
__v_5.__defineGetter__('byteLength', function() {foo();});
var __v_8 = new Worker('onmessage = function() {};');
var __v_8 = new Worker('onmessage = function() {};', {type: 'string'});
assertThrows(function() { __v_8.postMessage(__v_5); });
}
......@@ -4,10 +4,10 @@
if (this.Worker) {
var __v_8 =
`var __v_9 = new Worker('postMessage(42)');
`var __v_9 = new Worker('postMessage(42)', {type: 'string'});
onmessage = function(parentMsg) {
__v_9.postMessage(parentMsg);
};`;
var __v_9 = new Worker(__v_8);
var __v_9 = new Worker(__v_8, {type: 'string'});
__v_9.postMessage(9);
}
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
if (this.Worker) {
var __v_7 = new Worker('onmessage = function() {};');
var __v_7 = new Worker('onmessage = function() {};', {type: 'string'});
var e;
var ab = new ArrayBuffer(2 * 1000 * 1000);
try {
......
......@@ -4,6 +4,6 @@
if (this.Worker) {
Worker.prototype = 12;
var __v_6 = new Worker('');
var __v_6 = new Worker('', {type: 'string'});
__v_6.postMessage([]);
}
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
if (this.Worker) {
var worker = new Worker("onmessage = function(){}");
var worker = new Worker("onmessage = function(){}", {type: 'string'});
var buf = new ArrayBuffer();
worker.postMessage(buf, [buf]);
}
......@@ -7,7 +7,7 @@ let workers = [];
let runningWorkers = 0;
function startWorker(script) {
let worker = new Worker(script);
let worker = new Worker(script, {type: 'string'});
worker.done = false;
worker.idx = workers.length;
workers.push(worker);
......
......@@ -7,5 +7,5 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
var builder = new WasmModuleBuilder();
let module = new WebAssembly.Module(builder.toBuffer());
var worker = new Worker('onmessage = function() {};');
var worker = new Worker('onmessage = function() {};', {type: 'string'});
worker.postMessage(module)
......@@ -9,5 +9,5 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
var builder = new WasmModuleBuilder();
let module = new WebAssembly.Module(builder.toBuffer());
var worker = new Worker('onmessage = function() {};');
var worker = new Worker('onmessage = function() {};', {type: 'string'});
worker.postMessage(module)
......@@ -31,7 +31,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
Realm.shared = { m:module, s:workerScript };
let realmScript = `
let worker = new Worker(Realm.shared.s);
let worker = new Worker(Realm.shared.s, {type: 'string'});
worker.postMessage(Realm.shared.m);
let message = worker.getMessage();
worker.terminate();
......
......@@ -10,5 +10,5 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addFunction('test', kSig_i_i).addBody([kExprUnreachable]);
let module = new WebAssembly.Module(builder.toBuffer());
var worker = new Worker('onmessage = function() {};');
var worker = new Worker('onmessage = function() {};', {type: 'string'});
worker.postMessage(module);
......@@ -60,7 +60,7 @@ let worker_onmessage = function(msg) {
}
let workerScript = "onmessage = " + worker_onmessage.toString();
let worker = new Worker(workerScript);
let worker = new Worker(workerScript, {type: 'string'});
worker.postMessage({serialized_m1, m1_bytes});
// Wait for worker to finish.
......
......@@ -150,7 +150,8 @@ function spawnWorker(module, memory, address, sequence) {
instance.exports.worker(msg.address, msg.sequence, msg.sequenceLength, msg.workerId,
msg.bitMask);
postMessage({workerId: msg.workerId});
}`
}`,
{type: 'string'}
);
workers.push(worker);
worker.postMessage({
......
......@@ -34,7 +34,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
}
}
`;
let worker = new Worker(workerScript);
let worker = new Worker(workerScript, {type: 'string'});
// Call method without using the interpreter.
var initial_interpreted = %WasmNumInterpretedCalls(instance);
......
......@@ -5,7 +5,7 @@
// Flags: --experimental-wasm-threads
(function TestPostMessageUnsharedMemory() {
let worker = new Worker('');
let worker = new Worker('', {type: 'string'});
let memory = new WebAssembly.Memory({initial: 1, maximum: 2});
assertThrows(() => worker.postMessage(memory), Error);
......@@ -39,7 +39,7 @@ let workerHelpers =
postMessage("OK");
};`;
let worker = new Worker(workerScript);
let worker = new Worker(workerScript, {type: 'string'});
let memory = new WebAssembly.Memory({initial: 1, maximum: 2, shared: true});
worker.postMessage(memory);
assertEquals("OK", worker.getMessage());
......@@ -60,7 +60,7 @@ let workerHelpers =
postMessage("OK");
};`;
let worker = new Worker(workerScript);
let worker = new Worker(workerScript, {type: 'string'});
let memory = new WebAssembly.Memory({initial: 1, maximum: 2, shared: true});
let obj = {memories: [memory, memory], buffer: memory.buffer, foo: 1};
worker.postMessage(obj);
......@@ -75,7 +75,8 @@ let workerHelpers =
postMessage("OK");
};`;
let workers = [new Worker(workerScript), new Worker(workerScript)];
let workers = [new Worker(workerScript, {type: 'string'}),
new Worker(workerScript, {type: 'string'})];
let memory = new WebAssembly.Memory({initial: 1, maximum: 2, shared: true});
for (let worker of workers) {
worker.postMessage(memory);
......
......@@ -27,7 +27,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
}
`;
let worker = new Worker(workerScript);
let worker = new Worker(workerScript, {type: 'string'});
worker.postMessage(module);
assertEquals(42, worker.getMessage());
worker.terminate();
......
......@@ -76,7 +76,7 @@ var agent = {
if (i32a === null) {
i32a = new Int32Array(new SharedArrayBuffer(256));
}
var w = new Worker(workerScript(script));
var w = new Worker(workerScript(script), {type: 'string'});
w.index = workers.length;
w.postMessage({kind: 'start', i32a: i32a, index: w.index});
workers.push(w);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment