Update web-platform-tests to revision 3efff9b2d66aed3d8e2061205069883fd54df2be

This commit is contained in:
WPT Sync Bot 2019-04-12 21:48:49 -04:00
parent 9832feddf3
commit f80ff24202
51 changed files with 1026 additions and 868 deletions

View file

@ -192,17 +192,62 @@ function createHelperIframe(name, doBindEvents) {
doBindEvents);
}
/**
* requestVia*() functions return promises that are resolved on successful
* requests with objects of the same "type", i.e. objects that contains
* the same sets of keys that are fixed within one category of tests (e.g.
* within wpt/referrer-policy tests).
* wrapResult() (that should be defined outside this file) is used to convert
* the response bodies of subresources into the expected result objects in some
* cases, and in other cases the result objects are constructed more directly.
* TODO(https://crbug.com/906850): Clean up the semantics around this, e.g.
* use (or not use) wrapResult() consistently, unify the arguments, etc.
*/
function wrapResult(server_data) {
if (typeof(server_data) === "string") {
throw server_data;
}
return {
referrer: server_data.headers.referer,
headers: server_data.headers
}
}
// `requestVia*()` functions return promises that are resolved on successful
// requests with objects with the following keys:
// - `headers`: HTTP request headers sent to server.
// - `referrer`: Referrer.
// - `location`: The URL of the subresource.
//
// Category 1:
// `headers`: set.
// `referrer`: set via `document.referrer`.
// `location`: set via `document.location`.
// See `template/document.html.template`.
// Category 2:
// `headers`: set.
// `referrer`: set to `headers.referer` by `wrapResult()`.
// `location`: not set.
// Category 3:
// All the keys listed above are NOT set.
//
// -------------------------------- -------- --------------------------
// Function name Category Used in
// -------- ------- ---------
// referrer mixed- upgrade-
// policy content insecure-
// policy content request
// -------------------------------- -------- -------- ------- ---------
// requestViaAnchor 1 Y Y -
// requestViaArea 1 Y Y -
// requestViaAudio 3 - Y -
// requestViaDedicatedWorker 2 Y Y Y
// requestViaFetch 2 Y Y -
// requestViaForm 3 - Y -
// requestViaIframe 1 Y Y -
// requestViaImage 3 - Y -
// requestViaImageForReferrerPolicy 2 Y - -
// requestViaLinkPrefetch 3 - Y -
// requestViaLinkStylesheet 3 - Y -
// requestViaObject 3 - Y -
// requestViaPicture 3 - Y -
// requestViaScript 2 Y Y -
// requestViaSendBeacon 3 - Y -
// requestViaSharedWorker 2 Y - -
// requestViaVideo 3 - Y -
// requestViaWebSocket 3 - Y -
// requestViaWorklet 3 - Y Y
// requestViaXhr 2 Y Y -
// -------------------------------- -------- -------- ------- ---------
/**
* Creates a new iframe, binds load and error events, sets the src attribute and
@ -383,8 +428,9 @@ function requestViaFetch(url) {
function dedicatedWorkerUrlThatFetches(url) {
return `data:text/javascript,
fetch('${url}')
.then(() => postMessage(''),
() => postMessage(''));`;
.then(r => r.json())
.then(j => postMessage(j))
.catch((e) => postMessage(e.message));`;
}
function workerUrlThatImports(url) {

View file

@ -11,6 +11,7 @@
<style type="text/css">
#container {
display:flex;
align-items:flex-start;
}
input{
margin:0;padding:0;vertical-align:middle;
@ -25,4 +26,4 @@
</div>
</body>
</html>
</html>

View file

@ -0,0 +1,61 @@
<!DOCTYPE html>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='/resources/check-layout-th.js'></script>
<link rel="author" title="David Grogan" href="mailto:dgrogan@chromium.org">
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetheight">
<meta name="flags" content="" />
<meta name="assert" content="border-spacing occurring outside rows and sections is not included in their height and width" />
<style>
#theTable td {
width: 100px;
height: 100px;
background-color: green;
padding: 0px;
}
#theTable {
border-spacing: 10px;
}
.outline {
outline: 2px solid black;
}
</style>
<table id=theTable>
<tbody class="outline" data-expected-height=100>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
<tbody class="outline" data-expected-height=150>
<tr></tr>
<tr></tr>
<tr></tr>
<tr>
<td></td>
<td></td>
</tr>
<tr></tr>
<tr></tr>
</tbody>
<tbody class="outline" data-expected-height=100>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
<tfoot>
<tr style="outline: 2px dashed black" data-expected-width=210 data-expected-height=100>
<td></td>
<td></td>
</tr>
</tfoot>
</table>
<script>
checkLayout('tbody');
checkLayout('tfoot tr');
</script>

View file

@ -161,6 +161,8 @@ are:
* `dedicatedworker` (default): to be run at <code><var>x</var>.any.worker.html</code>
* `serviceworker`: to be run at <code><var>x</var>.https.any.serviceworker.html</code>
* `sharedworker`: to be run at <code><var>x</var>.any.sharedworker.html</code>
* `jsshell`: to be run in a JavaScript shell, without access to the DOM
(currently only supported in SpiderMonkey, and skipped in wptrunner)
* `default`: shorthand for the default scopes
* `worker`: shorthand for the dedicated, shared and service worker scopes

View file

@ -0,0 +1,38 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Element Timing: observe element with inline background image</title>
<body>
<style>
body {
margin: 0;
}
#target {
width: 100px;
height: 50px;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKAQMAAAC3/F3+AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABlBMVEX/AAD///9BHTQRAAAAAWJLR0QB/wIt3gAAAAtJREFUCNdjYMAHAAAeAAFuhUcyAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE5LTA0LTA1VDIwOjA4OjQxKzAyOjAwPa6EZwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxOS0wNC0wNVQyMDowODo0MSswMjowMEzzPNsAAAAASUVORK5CYII=);
}
</style>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/element-timing-helpers.js"></script>
<script>
let beforeRender = performance.now();
async_test(function (t) {
const observer = new PerformanceObserver(
t.step_func_done(function(entryList) {
assert_equals(entryList.getEntries().length, 1);
const entry = entryList.getEntries()[0];
// Only the first characters of the data URI are included in the entry.
const uriPrefix = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKAQMAAAC3/F3+AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAA';
checkElementWithoutResourceTiming(entry, uriPrefix, 'my_div', 'target',
beforeRender);
// The background image is a red square of length 10.
checkRect(entry, [0, 100, 0, 50]);
checkNaturalSize(entry, 10, 10);
})
);
observer.observe({entryTypes: ['element']});
}, 'Element with elementtiming attribute and inline background image is observable.');
</script>
<div id='target' elementtiming='my_div'></div>
</body>

View file

@ -0,0 +1,36 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Element Timing: observe inline image</title>
<body>
<style>
body {
margin: 0;
}
#inline_wee {
display: block;
}
</style>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/element-timing-helpers.js"></script>
<script>
let beforeRender = performance.now();
async_test(function (t) {
const observer = new PerformanceObserver(
t.step_func_done(function(entryList) {
assert_equals(entryList.getEntries().length, 1);
const entry = entryList.getEntries()[0];
// Only the first characters of the data URI are included in the entry.
const uriPrefix = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKAQMAAAC3/F3+AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAA';
checkElementWithoutResourceTiming(entry, uriPrefix, 'my_img', 'inline_wee',
beforeRender);
// The image is a red square of length 10.
checkRect(entry, [0, 10, 0, 10]);
checkNaturalSize(entry, 10, 10);
})
);
observer.observe({entryTypes: ['element']});
}, 'Inline image is observable via Element Timing.');
</script>
<img elementtiming='my_img' id='inline_wee' src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKAQMAAAC3/F3+AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABlBMVEX/AAD///9BHTQRAAAAAWJLR0QB/wIt3gAAAAtJREFUCNdjYMAHAAAeAAFuhUcyAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE5LTA0LTA1VDIwOjA4OjQxKzAyOjAwPa6EZwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxOS0wNC0wNVQyMDowODo0MSswMjowMEzzPNsAAAAASUVORK5CYII="/>
</body>

View file

@ -13,6 +13,19 @@ function checkElement(entry, expectedName, expectedIdentifier, expectedID, befor
assert_equals(rt_entries[0].responseEnd, entry.responseEnd);
}
function checkElementWithoutResourceTiming(entry, expectedName, expectedIdentifier,
expectedID, beforeRender) {
assert_equals(entry.entryType, 'element');
assert_equals(entry.name, expectedName);
assert_equals(entry.identifier, expectedIdentifier);
assert_equals(entry.duration, 0);
assert_equals(entry.id, expectedID);
assert_greater_than_equal(entry.startTime, beforeRender);
assert_greater_than_equal(performance.now(), entry.startTime);
// No associated resource from ResourceTiming, so the responseEnd should be 0.
assert_equals(entry.responseEnd, 0);
}
// Checks that the rect matches the desired values [left right top bottom].
function checkRect(entry, expected, description="") {
assert_equals(entry.intersectionRect.left, expected[0],

View file

@ -3,11 +3,6 @@
* @author burnik@google.com (Kristijan Burnik)
*/
function wrapResult(server_data) {
// Currently the returned value is not used in mixed-content tests.
return null;
}
/**
* MixedContentTestCase exercises all the tests for checking browser behavior
* when resources regarded as mixed-content are requested. A single run covers

View file

@ -4,11 +4,24 @@
<script src="/resources/testharnessreport.js"></script>
<script>
async_test(function(t) {
var bc = new BroadcastChannel("portal-test");
var test = "adopt-once";
var bc = new BroadcastChannel(`test-${test}`);
bc.onmessage = t.step_func_done(function(e) {
assert_equals(e.data, "passed");
bc.close();
});
window.open("resources/portals-adopt-predecessor.html");
var portalUrl = encodeURIComponent(`portal-activate-event-portal.html?test=${test}`);
window.open(`resources/portals-adopt-predecessor.html?test=${test}`);
}, "Tests that a portal can adopt its predecessor.");
async_test(function(t) {
var test = "adopt-twice";
var bc = new BroadcastChannel(`test-${test}`);
bc.onmessage = t.step_func_done(function(e) {
assert_equals(e.data, "passed");
bc.close();
});
var portalUrl = encodeURIComponent(`portal-activate-event-portal.html?test=${test}`);
window.open(`resources/portals-adopt-predecessor.html?test=${test}`);
}, "Tests that trying to adopt the predecessor twice will throw an exception.");
</script>

View file

@ -1,17 +1,28 @@
<!doctype html>
<script>
var searchParams = new URL(location).searchParams;
var test = searchParams.get("test");
var bc = new BroadcastChannel(`portal-${test}`);
window.onportalactivate = function(e) {
var portal = e.adoptPredecessor();
document.body.appendChild(portal);
if (portal instanceof HTMLPortalElement) {
var bc_adopted = new BroadcastChannel("portal-adopted");
bc_adopted.postMessage("adopted");
bc_adopted.close();
if (test == "adopt-once") {
if (portal instanceof HTMLPortalElement) {
bc.postMessage("passed");
bc.close();
}
}
if (test == "adopt-twice") {
try {
portal = e.adoptPredecessor();
} catch(e) {
bc.postMessage("passed");
bc.close();
}
}
}
var bc_loaded = new BroadcastChannel("portal-loaded");
bc_loaded.postMessage("loaded");
bc_loaded.close();
bc.postMessage("loaded");
</script>

View file

@ -1,20 +1,25 @@
<!doctype html>
<body>
<portal src="portals-adopt-predecessor-portal.html"></portal>
</body>
<script>
var bc_loaded = new BroadcastChannel("portal-loaded");
bc_loaded.onmessage = function(e) {
document.querySelector("portal").activate();
bc_loaded.close();
var searchParams = new URL(location).searchParams;
var test = searchParams.get("test");
var bc = new BroadcastChannel(`portal-${test}`);
bc.onmessage = function(e) {
switch (e.data) {
case "loaded":
document.querySelector("portal").activate();
break;
var bc_adopted = new BroadcastChannel("portal-adopted");
bc_adopted.onmessage = function(e) {
bc_adopted.close();
var bc_test = new BroadcastChannel("portal-test");
bc_test.postMessage("passed");
bc_test.close();
case "passed":
bc.close();
var bc_test = new BroadcastChannel(`test-${test}`);
bc_test.postMessage("passed");
bc_test.close();
}
}
var portal = document.createElement("portal");
portal.src = "portals-adopt-predecessor-portal.html?test=" + test;
document.body.appendChild(portal);
</script>

View file

@ -1,10 +1,3 @@
function wrapResult(server_data) {
return {
referrer: server_data.headers.referer,
headers: server_data.headers
}
}
// NOTE: This method only strips the fragment and is not in accordance to the
// recommended draft specification:
// https://w3c.github.io/webappsec/specs/referrer-policy/#null

View file

@ -1,6 +1,7 @@
from __future__ import absolute_import
import argparse
import bz2
import gzip
import json
import io
@ -9,6 +10,11 @@ from datetime import datetime, timedelta
from six.moves.urllib.request import urlopen
try:
import zstandard
except ImportError:
zstandard = None
from .vcs import Git
from . import log
@ -43,6 +49,21 @@ def merge_pr_tags(repo_root, max_count=50):
return tags
def score_name(name):
"""Score how much we like each filename, lower wins, None rejects"""
# Accept both ways of naming the manfest asset, even though
# there's no longer a reason to include the commit sha.
if name.startswith("MANIFEST-") or name.startswith("MANIFEST."):
if zstandard and name.endswith("json.zst"):
return 1
if name.endswith(".json.bz2"):
return 2
if name.endswith(".json.gz"):
return 3
return None
def github_url(tags):
for tag in tags:
url = "https://api.github.com/repos/web-platform-tests/wpt/releases/tags/%s" % tag
@ -62,13 +83,13 @@ def github_url(tags):
logger.warning("Response was not valid JSON")
return None
candidates = []
for item in release["assets"]:
# Accept both ways of naming the manfest asset, even though
# there's no longer a reason to include the commit sha.
if item["name"].startswith("MANIFEST-") and item["name"].endswith(".json.gz"):
return item["browser_download_url"]
elif item["name"] == "MANIFEST.json.gz":
return item["browser_download_url"]
score = score_name(item["name"])
if score is not None:
candidates.append((score, item["browser_download_url"]))
return [item[1] for item in sorted(candidates)]
return None
@ -79,33 +100,56 @@ def download_manifest(manifest_path, tags_func, url_func, force=False):
tags = tags_func()
url = url_func(tags)
if not url:
urls = url_func(tags)
if not urls:
logger.warning("No generated manifest found")
return False
logger.info("Downloading manifest from %s" % url)
try:
resp = urlopen(url)
except Exception:
logger.warning("Downloading pregenerated manifest failed")
return False
for url in urls:
logger.info("Downloading manifest from %s" % url)
try:
resp = urlopen(url)
except Exception:
logger.warning("Downloading pregenerated manifest failed")
continue
if resp.code != 200:
logger.warning("Downloading pregenerated manifest failed; got HTTP status %d" %
resp.code)
return False
if resp.code != 200:
logger.warning("Downloading pregenerated manifest failed; got HTTP status %d" %
resp.code)
continue
gzf = gzip.GzipFile(fileobj=io.BytesIO(resp.read()))
try:
decompressed = gzf.read()
except IOError:
logger.warning("Failed to decompress downloaded file")
if url.endswith(".zst"):
if not zstandard:
continue
try:
dctx = zstandard.ZstdDecompressor()
decompressed = dctx.decompress(resp.read())
except IOError:
logger.warning("Failed to decompress downloaded file")
continue
elif url.endswith(".bz2"):
try:
decompressed = bz2.decompress(resp.read())
except IOError:
logger.warning("Failed to decompress downloaded file")
continue
elif url.endswith(".gz"):
fileobj = io.BytesIO(resp.read())
try:
with gzip.GzipFile(fileobj=fileobj) as gzf:
decompressed = gzf.read()
except IOError:
logger.warning("Failed to decompress downloaded file")
continue
else:
logger.warning("Unknown file extension: %s" % url)
continue
break
else:
return False
try:
with open(manifest_path, "w") as f:
with open(manifest_path, "wb") as f:
f.write(decompressed)
except Exception:
logger.warning("Failed to write manifest")

View file

@ -5,8 +5,15 @@ import stat
import subprocess
from collections import deque
from six import iteritems
from .sourcefile import SourceFile
MYPY = False
if MYPY:
# MYPY is set to True when run under Mypy.
from typing import Dict, Optional
def get_tree(tests_root, manifest, manifest_path, cache_root,
working_copy=False, rebuild=False):
@ -92,13 +99,24 @@ class Git(object):
path = os.path.relpath(os.path.abspath(path), self.root)
return self.git("show", "HEAD:%s" % path)
def __iter__(self):
def hash_cache(self):
# type: () -> Dict[str, Optional[str]]
"""
A dict of rel_path -> current git object id if the working tree matches HEAD else None
"""
hash_cache = {}
cmd = ["ls-tree", "-r", "-z", "HEAD"]
local_changes = self._local_changes()
for result in self.git(*cmd).split("\0")[:-1]:
data, rel_path = result.rsplit("\t", 1)
hash = data.split(" ", 3)[2]
if rel_path in local_changes:
hash_cache[rel_path] = None if rel_path in local_changes else data.split(" ", 3)[2]
return hash_cache
def __iter__(self):
for rel_path, hash in iteritems(self.hash_cache()):
if hash is None:
contents = self._show_file(rel_path)
else:
contents = None
@ -127,6 +145,11 @@ class FileSystem(object):
self.path_filter = gitignore.PathFilter(self.root,
extras=[".git/"],
cache=self.ignore_cache)
git = Git.for_path(root, url_base, cache_path)
if git is not None:
self.hash_cache = git.hash_cache()
else:
self.hash_cache = {}
def __iter__(self):
mtime_cache = self.mtime_cache
@ -134,7 +157,8 @@ class FileSystem(object):
for filename, path_stat in filenames:
path = os.path.join(dirpath, filename)
if mtime_cache is None or mtime_cache.updated(path, path_stat):
yield SourceFile(self.root, path, self.url_base), True
hash = self.hash_cache.get(path, None)
yield SourceFile(self.root, path, self.url_base, hash), True
else:
yield path, False

View file

@ -1,6 +1,7 @@
{
"run": {"path": "run.py", "script": "run", "parser": "create_parser", "help": "Run tests in a browser",
"virtualenv": true, "install": ["requests"], "requirements": ["../wptrunner/requirements.txt"]},
"virtualenv": true, "install": ["requests", "zstandard"],
"requirements": ["../wptrunner/requirements.txt"]},
"create": {"path": "create.py", "script": "run", "parser": "get_parser", "help": "Create a new wpt test"},
"update-expectations": {"path": "update.py", "script": "update_expectations",
"parser": "create_parser_update", "help": "Update expectations files from raw logs.",

View file

@ -58,6 +58,9 @@ def get_timeout_multiplier(test_type, run_info_data, **kwargs):
return 3
elif run_info_data["os"] == "android":
return 4
# https://bugzilla.mozilla.org/show_bug.cgi?id=1538725
elif run_info_data["os"] == "win" and run_info_data["processor"] == "aarch64":
return 4
return 1

View file

@ -205,7 +205,7 @@ class ManifestItem(object):
self._data = {}
def __repr__(self):
return "<ManifestItem %s>" % (self.node.data)
return "<conditional.ManifestItem %s>" % (self.node.data)
def __str__(self):
rv = [repr(self)]

View file

@ -131,7 +131,7 @@ class ManifestItem(object):
self._data = {}
def __repr__(self):
return "<ManifestItem %s>" % (self.name)
return "<static.ManifestItem %s>" % (self.name)
def __str__(self):
rv = [repr(self)]

View file

@ -1,9 +1,3 @@
// Used by common.js.
function wrapResult(server_data) {
// Currently the returned value is not used in mixed-content tests.
return null;
}
const Host = {
SAME_ORIGIN: "same-origin",
CROSS_ORIGIN: "cross-origin",

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
function assert_Module(module) {
@ -78,7 +77,7 @@ promise_test(() => {
}, "Stray argument");
promise_test(() => {
const buffer = new Uint8Array(new WasmModuleBuilder().toBuffer());
const buffer = new WasmModuleBuilder().toBuffer();
assert_equals(buffer[0], 0);
const promise = WebAssembly.compile(buffer);
buffer[0] = 1;

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
// META: script=/wasm/jsapi/bad-imports.js

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
// META: script=/wasm/jsapi/assertions.js
// META: script=/wasm/jsapi/instanceTestFactory.js
@ -145,7 +144,7 @@ promise_test(t => {
}, "Invalid code");
promise_test(() => {
const buffer = new Uint8Array(new WasmModuleBuilder().toBuffer());
const buffer = new WasmModuleBuilder().toBuffer();
assert_equals(buffer[0], 0);
const promise = WebAssembly.instantiate(buffer);
buffer[0] = 1;

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
let emptyModuleBinary;

View file

@ -49,6 +49,22 @@ for (const type of ["i32", "f32", "f64"]) {
assert_equals(global.value, 0, "post-set value");
assert_equals(global.valueOf(), 0, "post-set valueOf");
}, `Immutable ${type} (${name})`);
test(t => {
opts.value = type;
const global = new WebAssembly.Global(opts);
assert_equals(global.value, 0, "initial value");
assert_equals(global.valueOf(), 0, "initial valueOf");
const value = {
valueOf: t.unreached_func("should not call valueOf"),
toString: t.unreached_func("should not call toString"),
};
assert_throws(new TypeError(), () => global.value = value);
assert_equals(global.value, 0, "post-set value");
assert_equals(global.valueOf(), 0, "post-set valueOf");
}, `Immutable ${type} with ToNumber side-effects (${name})`);
}
const mutableOptions = [
@ -80,6 +96,15 @@ test(() => {
assert_throws(new TypeError(), () => global.valueOf());
}, "i64 with default");
test(t => {
const argument = { "value": "i64", "mutable": true };
const global = new WebAssembly.Global(argument);
const value = {
valueOf: t.unreached_func("should not call valueOf"),
toString: t.unreached_func("should not call toString"),
};
assert_throws(new TypeError(), () => global.value = value);
}, "i64 with ToNumber side-effects");
test(() => {
const argument = { "value": "i32", "mutable": true };

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
// META: script=/wasm/jsapi/bad-imports.js

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
// META: script=/wasm/jsapi/assertions.js
// META: script=/wasm/jsapi/instanceTestFactory.js

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
let emptyModuleBinary;

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
test(() => {

View file

@ -140,7 +140,7 @@ const instanceTestFactory = [
.addBody([])
.exportFunc();
builder.setTableLength(1);
builder.setTableBounds(1);
builder.addExportOfKind("table", kExternalTable, 0);
builder.addGlobal(kWasmI32, true)

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
// META: script=/wasm/jsapi/assertions.js

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
function assert_ArrayBuffer(buffer, expected) {
@ -97,7 +96,7 @@ test(() => {
});
const builder = new WasmModuleBuilder();
builder.addExplicitSection(binary);
builder.addExplicitSection(binary.trunc_buffer());
const buffer = builder.toBuffer()
const module = new WebAssembly.Module(buffer);
@ -127,7 +126,7 @@ test(() => {
});
const builder = new WasmModuleBuilder();
builder.addExplicitSection(binary);
builder.addExplicitSection(binary.trunc_buffer());
const buffer = builder.toBuffer();
const module = new WebAssembly.Module(buffer);
@ -148,7 +147,7 @@ test(() => {
});
const builder = new WasmModuleBuilder();
builder.addExplicitSection(binary);
builder.addExplicitSection(binary.trunc_buffer());
const buffer = builder.toBuffer();
const module = new WebAssembly.Module(buffer);

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
let emptyModuleBinary;
@ -99,7 +98,7 @@ test(() => {
.addBody([])
.exportFunc();
builder.setTableLength(1);
builder.setTableBounds(1);
builder.addExportOfKind("table", kExternalTable, 0);
builder.addGlobal(kWasmI32, true)

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
function assert_ModuleImportDescriptor(import_, expected) {

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
test(() => {

View file

@ -1,5 +1,4 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
// META: script=assertions.js

View file

@ -1,384 +0,0 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-wasm
function bytes() {
var buffer = new ArrayBuffer(arguments.length);
var view = new Uint8Array(buffer);
for (var i = 0; i < arguments.length; i++) {
var val = arguments[i];
if ((typeof val) == "string") val = val.charCodeAt(0);
view[i] = val | 0;
}
return buffer;
}
// Header declaration constants
var kWasmH0 = 0;
var kWasmH1 = 0x61;
var kWasmH2 = 0x73;
var kWasmH3 = 0x6d;
var kWasmV0 = 0x1;
var kWasmV1 = 0;
var kWasmV2 = 0;
var kWasmV3 = 0;
var kHeaderSize = 8;
var kPageSize = 65536;
var kSpecMaxPages = 65535;
function bytesWithHeader() {
var buffer = new ArrayBuffer(kHeaderSize + arguments.length);
var view = new Uint8Array(buffer);
view[0] = kWasmH0;
view[1] = kWasmH1;
view[2] = kWasmH2;
view[3] = kWasmH3;
view[4] = kWasmV0;
view[5] = kWasmV1;
view[6] = kWasmV2;
view[7] = kWasmV3;
for (var i = 0; i < arguments.length; i++) {
var val = arguments[i];
if ((typeof val) == "string") val = val.charCodeAt(0);
view[kHeaderSize + i] = val | 0;
}
return buffer;
}
let kDeclNoLocals = 0;
// Section declaration constants
let kUnknownSectionCode = 0;
let kTypeSectionCode = 1; // Function signature declarations
let kImportSectionCode = 2; // Import declarations
let kFunctionSectionCode = 3; // Function declarations
let kTableSectionCode = 4; // Indirect function table and other tables
let kMemorySectionCode = 5; // Memory attributes
let kGlobalSectionCode = 6; // Global declarations
let kExportSectionCode = 7; // Exports
let kStartSectionCode = 8; // Start function declaration
let kElementSectionCode = 9; // Elements section
let kCodeSectionCode = 10; // Function code
let kDataSectionCode = 11; // Data segments
// Name section types
let kModuleNameCode = 0;
let kFunctionNamesCode = 1;
let kLocalNamesCode = 2;
let kWasmFunctionTypeForm = 0x60;
let kWasmAnyFunctionTypeForm = 0x70;
let kHasMaximumFlag = 1;
let kResizableMaximumFlag = 1;
// Function declaration flags
let kDeclFunctionName = 0x01;
let kDeclFunctionImport = 0x02;
let kDeclFunctionLocals = 0x04;
let kDeclFunctionExport = 0x08;
// Local types
let kWasmStmt = 0x40;
let kWasmI32 = 0x7f;
let kWasmI64 = 0x7e;
let kWasmF32 = 0x7d;
let kWasmF64 = 0x7c;
let kWasmS128 = 0x7b;
let kExternalFunction = 0;
let kExternalTable = 1;
let kExternalMemory = 2;
let kExternalGlobal = 3;
let kTableZero = 0;
let kMemoryZero = 0;
// Useful signatures
let kSig_i_i = makeSig([kWasmI32], [kWasmI32]);
let kSig_l_l = makeSig([kWasmI64], [kWasmI64]);
let kSig_i_l = makeSig([kWasmI64], [kWasmI32]);
let kSig_i_ii = makeSig([kWasmI32, kWasmI32], [kWasmI32]);
let kSig_i_iii = makeSig([kWasmI32, kWasmI32, kWasmI32], [kWasmI32]);
let kSig_v_iiii = makeSig([kWasmI32, kWasmI32, kWasmI32, kWasmI32], []);
let kSig_f_ff = makeSig([kWasmF32, kWasmF32], [kWasmF32]);
let kSig_d_dd = makeSig([kWasmF64, kWasmF64], [kWasmF64]);
let kSig_l_ll = makeSig([kWasmI64, kWasmI64], [kWasmI64]);
let kSig_i_dd = makeSig([kWasmF64, kWasmF64], [kWasmI32]);
let kSig_v_v = makeSig([], []);
let kSig_i_v = makeSig([], [kWasmI32]);
let kSig_l_v = makeSig([], [kWasmI64]);
let kSig_f_v = makeSig([], [kWasmF32]);
let kSig_d_v = makeSig([], [kWasmF64]);
let kSig_v_i = makeSig([kWasmI32], []);
let kSig_v_ii = makeSig([kWasmI32, kWasmI32], []);
let kSig_v_iii = makeSig([kWasmI32, kWasmI32, kWasmI32], []);
let kSig_v_l = makeSig([kWasmI64], []);
let kSig_v_d = makeSig([kWasmF64], []);
let kSig_v_dd = makeSig([kWasmF64, kWasmF64], []);
let kSig_v_ddi = makeSig([kWasmF64, kWasmF64, kWasmI32], []);
let kSig_v_f = makeSig([kWasmF32], []);
let kSig_f_f = makeSig([kWasmF32], [kWasmF32]);
let kSig_f_d = makeSig([kWasmF64], [kWasmF32]);
let kSig_d_d = makeSig([kWasmF64], [kWasmF64]);
function makeSig(params, results) {
return {params: params, results: results};
}
function makeSig_v_x(x) {
return makeSig([x], []);
}
function makeSig_v_xx(x) {
return makeSig([x, x], []);
}
function makeSig_r_v(r) {
return makeSig([], [r]);
}
function makeSig_r_x(r, x) {
return makeSig([x], [r]);
}
function makeSig_r_xx(r, x) {
return makeSig([x, x], [r]);
}
// Opcodes
let kExprUnreachable = 0x00;
let kExprNop = 0x01;
let kExprBlock = 0x02;
let kExprLoop = 0x03;
let kExprIf = 0x04;
let kExprElse = 0x05;
let kExprTry = 0x06;
let kExprCatch = 0x07;
let kExprThrow = 0x08;
let kExprEnd = 0x0b;
let kExprBr = 0x0c;
let kExprBrIf = 0x0d;
let kExprBrTable = 0x0e;
let kExprReturn = 0x0f;
let kExprCallFunction = 0x10;
let kExprCallIndirect = 0x11;
let kExprDrop = 0x1a;
let kExprSelect = 0x1b;
let kExprGetLocal = 0x20;
let kExprSetLocal = 0x21;
let kExprTeeLocal = 0x22;
let kExprGetGlobal = 0x23;
let kExprSetGlobal = 0x24;
let kExprI32Const = 0x41;
let kExprI64Const = 0x42;
let kExprF32Const = 0x43;
let kExprF64Const = 0x44;
let kExprI32LoadMem = 0x28;
let kExprI64LoadMem = 0x29;
let kExprF32LoadMem = 0x2a;
let kExprF64LoadMem = 0x2b;
let kExprI32LoadMem8S = 0x2c;
let kExprI32LoadMem8U = 0x2d;
let kExprI32LoadMem16S = 0x2e;
let kExprI32LoadMem16U = 0x2f;
let kExprI64LoadMem8S = 0x30;
let kExprI64LoadMem8U = 0x31;
let kExprI64LoadMem16S = 0x32;
let kExprI64LoadMem16U = 0x33;
let kExprI64LoadMem32S = 0x34;
let kExprI64LoadMem32U = 0x35;
let kExprI32StoreMem = 0x36;
let kExprI64StoreMem = 0x37;
let kExprF32StoreMem = 0x38;
let kExprF64StoreMem = 0x39;
let kExprI32StoreMem8 = 0x3a;
let kExprI32StoreMem16 = 0x3b;
let kExprI64StoreMem8 = 0x3c;
let kExprI64StoreMem16 = 0x3d;
let kExprI64StoreMem32 = 0x3e;
let kExprMemorySize = 0x3f;
let kExprMemoryGrow = 0x40;
let kExprI32Eqz = 0x45;
let kExprI32Eq = 0x46;
let kExprI32Ne = 0x47;
let kExprI32LtS = 0x48;
let kExprI32LtU = 0x49;
let kExprI32GtS = 0x4a;
let kExprI32GtU = 0x4b;
let kExprI32LeS = 0x4c;
let kExprI32LeU = 0x4d;
let kExprI32GeS = 0x4e;
let kExprI32GeU = 0x4f;
let kExprI64Eqz = 0x50;
let kExprI64Eq = 0x51;
let kExprI64Ne = 0x52;
let kExprI64LtS = 0x53;
let kExprI64LtU = 0x54;
let kExprI64GtS = 0x55;
let kExprI64GtU = 0x56;
let kExprI64LeS = 0x57;
let kExprI64LeU = 0x58;
let kExprI64GeS = 0x59;
let kExprI64GeU = 0x5a;
let kExprF32Eq = 0x5b;
let kExprF32Ne = 0x5c;
let kExprF32Lt = 0x5d;
let kExprF32Gt = 0x5e;
let kExprF32Le = 0x5f;
let kExprF32Ge = 0x60;
let kExprF64Eq = 0x61;
let kExprF64Ne = 0x62;
let kExprF64Lt = 0x63;
let kExprF64Gt = 0x64;
let kExprF64Le = 0x65;
let kExprF64Ge = 0x66;
let kExprI32Clz = 0x67;
let kExprI32Ctz = 0x68;
let kExprI32Popcnt = 0x69;
let kExprI32Add = 0x6a;
let kExprI32Sub = 0x6b;
let kExprI32Mul = 0x6c;
let kExprI32DivS = 0x6d;
let kExprI32DivU = 0x6e;
let kExprI32RemS = 0x6f;
let kExprI32RemU = 0x70;
let kExprI32And = 0x71;
let kExprI32Ior = 0x72;
let kExprI32Xor = 0x73;
let kExprI32Shl = 0x74;
let kExprI32ShrS = 0x75;
let kExprI32ShrU = 0x76;
let kExprI32Rol = 0x77;
let kExprI32Ror = 0x78;
let kExprI64Clz = 0x79;
let kExprI64Ctz = 0x7a;
let kExprI64Popcnt = 0x7b;
let kExprI64Add = 0x7c;
let kExprI64Sub = 0x7d;
let kExprI64Mul = 0x7e;
let kExprI64DivS = 0x7f;
let kExprI64DivU = 0x80;
let kExprI64RemS = 0x81;
let kExprI64RemU = 0x82;
let kExprI64And = 0x83;
let kExprI64Ior = 0x84;
let kExprI64Xor = 0x85;
let kExprI64Shl = 0x86;
let kExprI64ShrS = 0x87;
let kExprI64ShrU = 0x88;
let kExprI64Rol = 0x89;
let kExprI64Ror = 0x8a;
let kExprF32Abs = 0x8b;
let kExprF32Neg = 0x8c;
let kExprF32Ceil = 0x8d;
let kExprF32Floor = 0x8e;
let kExprF32Trunc = 0x8f;
let kExprF32NearestInt = 0x90;
let kExprF32Sqrt = 0x91;
let kExprF32Add = 0x92;
let kExprF32Sub = 0x93;
let kExprF32Mul = 0x94;
let kExprF32Div = 0x95;
let kExprF32Min = 0x96;
let kExprF32Max = 0x97;
let kExprF32CopySign = 0x98;
let kExprF64Abs = 0x99;
let kExprF64Neg = 0x9a;
let kExprF64Ceil = 0x9b;
let kExprF64Floor = 0x9c;
let kExprF64Trunc = 0x9d;
let kExprF64NearestInt = 0x9e;
let kExprF64Sqrt = 0x9f;
let kExprF64Add = 0xa0;
let kExprF64Sub = 0xa1;
let kExprF64Mul = 0xa2;
let kExprF64Div = 0xa3;
let kExprF64Min = 0xa4;
let kExprF64Max = 0xa5;
let kExprF64CopySign = 0xa6;
let kExprI32ConvertI64 = 0xa7;
let kExprI32SConvertF32 = 0xa8;
let kExprI32UConvertF32 = 0xa9;
let kExprI32SConvertF64 = 0xaa;
let kExprI32UConvertF64 = 0xab;
let kExprI64SConvertI32 = 0xac;
let kExprI64UConvertI32 = 0xad;
let kExprI64SConvertF32 = 0xae;
let kExprI64UConvertF32 = 0xaf;
let kExprI64SConvertF64 = 0xb0;
let kExprI64UConvertF64 = 0xb1;
let kExprF32SConvertI32 = 0xb2;
let kExprF32UConvertI32 = 0xb3;
let kExprF32SConvertI64 = 0xb4;
let kExprF32UConvertI64 = 0xb5;
let kExprF32ConvertF64 = 0xb6;
let kExprF64SConvertI32 = 0xb7;
let kExprF64UConvertI32 = 0xb8;
let kExprF64SConvertI64 = 0xb9;
let kExprF64UConvertI64 = 0xba;
let kExprF64ConvertF32 = 0xbb;
let kExprI32ReinterpretF32 = 0xbc;
let kExprI64ReinterpretF64 = 0xbd;
let kExprF32ReinterpretI32 = 0xbe;
let kExprF64ReinterpretI64 = 0xbf;
let kTrapUnreachable = 0;
let kTrapMemOutOfBounds = 1;
let kTrapDivByZero = 2;
let kTrapDivUnrepresentable = 3;
let kTrapRemByZero = 4;
let kTrapFloatUnrepresentable = 5;
let kTrapFuncInvalid = 6;
let kTrapFuncSigMismatch = 7;
let kTrapInvalidIndex = 8;
let kTrapMsgs = [
"unreachable",
"memory access out of bounds",
"divide by zero",
"divide result unrepresentable",
"remainder by zero",
"integer result unrepresentable",
"invalid function",
"function signature mismatch",
"invalid index into function table"
];
function assertTraps(trap, code) {
try {
if (typeof code === 'function') {
code();
} else {
eval(code);
}
} catch (e) {
assertEquals('object', typeof e);
assertEquals(kTrapMsgs[trap], e.message);
// Success.
return;
}
throw new MjsUnitAssertionError('Did not trap, expected: ' + kTrapMsgs[trap]);
}
function wasmI32Const(val) {
let bytes = [kExprI32Const];
for (let i = 0; i < 4; ++i) {
bytes.push(0x80 | ((val >> (7 * i)) & 0x7f));
}
bytes.push((val >> (7 * 4)) & 0x7f);
return bytes;
}
function wasmF32Const(f) {
return [kExprF32Const].concat(Array.from(new Uint8Array((new Float32Array([f])).buffer)));
}
function wasmF64Const(f) {
return [kExprF64Const].concat(Array.from(new Uint8Array((new Float64Array([f])).buffer)));
}

View file

@ -3,44 +3,401 @@
// found in the LICENSE file.
// Used for encoding f32 and double constants to bits.
let __buffer = new ArrayBuffer(8);
let byte_view = new Int8Array(__buffer);
let f32_view = new Float32Array(__buffer);
let f64_view = new Float64Array(__buffer);
let f32_view = new Float32Array(1);
let f32_bytes_view = new Uint8Array(f32_view.buffer);
let f64_view = new Float64Array(1);
let f64_bytes_view = new Uint8Array(f64_view.buffer);
// The bytes function receives one of
// - several arguments, each of which is either a number or a string of length
// 1; if it's a string, the charcode of the contained character is used.
// - a single array argument containing the actual arguments
// - a single string; the returned buffer will contain the char codes of all
// contained characters.
function bytes(...input) {
if (input.length == 1 && typeof input[0] == 'array') input = input[0];
if (input.length == 1 && typeof input[0] == 'string') {
let len = input[0].length;
let view = new Uint8Array(len);
for (let i = 0; i < len; i++) view[i] = input[0].charCodeAt(i);
return view.buffer;
}
let view = new Uint8Array(input.length);
for (let i = 0; i < input.length; i++) {
let val = input[i];
if (typeof val == 'string') {
assertEquals(1, val.length, 'string inputs must have length 1');
val = val.charCodeAt(0);
}
view[i] = val | 0;
}
return view.buffer;
}
// Header declaration constants
var kWasmH0 = 0;
var kWasmH1 = 0x61;
var kWasmH2 = 0x73;
var kWasmH3 = 0x6d;
var kWasmV0 = 0x1;
var kWasmV1 = 0;
var kWasmV2 = 0;
var kWasmV3 = 0;
var kHeaderSize = 8;
var kPageSize = 65536;
var kSpecMaxPages = 65535;
var kMaxVarInt32Size = 5;
var kMaxVarInt64Size = 10;
let kDeclNoLocals = 0;
// Section declaration constants
let kUnknownSectionCode = 0;
let kTypeSectionCode = 1; // Function signature declarations
let kImportSectionCode = 2; // Import declarations
let kFunctionSectionCode = 3; // Function declarations
let kTableSectionCode = 4; // Indirect function table and other tables
let kMemorySectionCode = 5; // Memory attributes
let kGlobalSectionCode = 6; // Global declarations
let kExportSectionCode = 7; // Exports
let kStartSectionCode = 8; // Start function declaration
let kElementSectionCode = 9; // Elements section
let kCodeSectionCode = 10; // Function code
let kDataSectionCode = 11; // Data segments
// Name section types
let kModuleNameCode = 0;
let kFunctionNamesCode = 1;
let kLocalNamesCode = 2;
let kWasmFunctionTypeForm = 0x60;
let kWasmAnyFunctionTypeForm = 0x70;
let kHasMaximumFlag = 1;
let kResizableMaximumFlag = 1;
// Function declaration flags
let kDeclFunctionName = 0x01;
let kDeclFunctionImport = 0x02;
let kDeclFunctionLocals = 0x04;
let kDeclFunctionExport = 0x08;
// Local types
let kWasmStmt = 0x40;
let kWasmI32 = 0x7f;
let kWasmI64 = 0x7e;
let kWasmF32 = 0x7d;
let kWasmF64 = 0x7c;
let kWasmS128 = 0x7b;
let kExternalFunction = 0;
let kExternalTable = 1;
let kExternalMemory = 2;
let kExternalGlobal = 3;
let kTableZero = 0;
let kMemoryZero = 0;
// Useful signatures
let kSig_i_i = makeSig([kWasmI32], [kWasmI32]);
let kSig_l_l = makeSig([kWasmI64], [kWasmI64]);
let kSig_i_l = makeSig([kWasmI64], [kWasmI32]);
let kSig_i_ii = makeSig([kWasmI32, kWasmI32], [kWasmI32]);
let kSig_i_iii = makeSig([kWasmI32, kWasmI32, kWasmI32], [kWasmI32]);
let kSig_v_iiii = makeSig([kWasmI32, kWasmI32, kWasmI32, kWasmI32], []);
let kSig_f_ff = makeSig([kWasmF32, kWasmF32], [kWasmF32]);
let kSig_d_dd = makeSig([kWasmF64, kWasmF64], [kWasmF64]);
let kSig_l_ll = makeSig([kWasmI64, kWasmI64], [kWasmI64]);
let kSig_i_dd = makeSig([kWasmF64, kWasmF64], [kWasmI32]);
let kSig_v_v = makeSig([], []);
let kSig_i_v = makeSig([], [kWasmI32]);
let kSig_l_v = makeSig([], [kWasmI64]);
let kSig_f_v = makeSig([], [kWasmF32]);
let kSig_d_v = makeSig([], [kWasmF64]);
let kSig_v_i = makeSig([kWasmI32], []);
let kSig_v_ii = makeSig([kWasmI32, kWasmI32], []);
let kSig_v_iii = makeSig([kWasmI32, kWasmI32, kWasmI32], []);
let kSig_v_l = makeSig([kWasmI64], []);
let kSig_v_d = makeSig([kWasmF64], []);
let kSig_v_dd = makeSig([kWasmF64, kWasmF64], []);
let kSig_v_ddi = makeSig([kWasmF64, kWasmF64, kWasmI32], []);
let kSig_v_f = makeSig([kWasmF32], []);
let kSig_f_f = makeSig([kWasmF32], [kWasmF32]);
let kSig_f_d = makeSig([kWasmF64], [kWasmF32]);
let kSig_d_d = makeSig([kWasmF64], [kWasmF64]);
function makeSig(params, results) {
return {params: params, results: results};
}
function makeSig_v_x(x) {
return makeSig([x], []);
}
function makeSig_v_xx(x) {
return makeSig([x, x], []);
}
function makeSig_r_v(r) {
return makeSig([], [r]);
}
function makeSig_r_x(r, x) {
return makeSig([x], [r]);
}
function makeSig_r_xx(r, x) {
return makeSig([x, x], [r]);
}
// Opcodes
let kExprUnreachable = 0x00;
let kExprNop = 0x01;
let kExprBlock = 0x02;
let kExprLoop = 0x03;
let kExprIf = 0x04;
let kExprElse = 0x05;
let kExprTry = 0x06;
let kExprCatch = 0x07;
let kExprThrow = 0x08;
let kExprEnd = 0x0b;
let kExprBr = 0x0c;
let kExprBrIf = 0x0d;
let kExprBrTable = 0x0e;
let kExprReturn = 0x0f;
let kExprCallFunction = 0x10;
let kExprCallIndirect = 0x11;
let kExprDrop = 0x1a;
let kExprSelect = 0x1b;
let kExprGetLocal = 0x20;
let kExprSetLocal = 0x21;
let kExprTeeLocal = 0x22;
let kExprGetGlobal = 0x23;
let kExprSetGlobal = 0x24;
let kExprI32LoadMem = 0x28;
let kExprI64LoadMem = 0x29;
let kExprF32LoadMem = 0x2a;
let kExprF64LoadMem = 0x2b;
let kExprI32LoadMem8S = 0x2c;
let kExprI32LoadMem8U = 0x2d;
let kExprI32LoadMem16S = 0x2e;
let kExprI32LoadMem16U = 0x2f;
let kExprI64LoadMem8S = 0x30;
let kExprI64LoadMem8U = 0x31;
let kExprI64LoadMem16S = 0x32;
let kExprI64LoadMem16U = 0x33;
let kExprI64LoadMem32S = 0x34;
let kExprI64LoadMem32U = 0x35;
let kExprI32StoreMem = 0x36;
let kExprI64StoreMem = 0x37;
let kExprF32StoreMem = 0x38;
let kExprF64StoreMem = 0x39;
let kExprI32StoreMem8 = 0x3a;
let kExprI32StoreMem16 = 0x3b;
let kExprI64StoreMem8 = 0x3c;
let kExprI64StoreMem16 = 0x3d;
let kExprI64StoreMem32 = 0x3e;
let kExprMemorySize = 0x3f;
let kExprMemoryGrow = 0x40;
let kExprI32Const = 0x41;
let kExprI64Const = 0x42;
let kExprF32Const = 0x43;
let kExprF64Const = 0x44;
let kExprI32Eqz = 0x45;
let kExprI32Eq = 0x46;
let kExprI32Ne = 0x47;
let kExprI32LtS = 0x48;
let kExprI32LtU = 0x49;
let kExprI32GtS = 0x4a;
let kExprI32GtU = 0x4b;
let kExprI32LeS = 0x4c;
let kExprI32LeU = 0x4d;
let kExprI32GeS = 0x4e;
let kExprI32GeU = 0x4f;
let kExprI64Eqz = 0x50;
let kExprI64Eq = 0x51;
let kExprI64Ne = 0x52;
let kExprI64LtS = 0x53;
let kExprI64LtU = 0x54;
let kExprI64GtS = 0x55;
let kExprI64GtU = 0x56;
let kExprI64LeS = 0x57;
let kExprI64LeU = 0x58;
let kExprI64GeS = 0x59;
let kExprI64GeU = 0x5a;
let kExprF32Eq = 0x5b;
let kExprF32Ne = 0x5c;
let kExprF32Lt = 0x5d;
let kExprF32Gt = 0x5e;
let kExprF32Le = 0x5f;
let kExprF32Ge = 0x60;
let kExprF64Eq = 0x61;
let kExprF64Ne = 0x62;
let kExprF64Lt = 0x63;
let kExprF64Gt = 0x64;
let kExprF64Le = 0x65;
let kExprF64Ge = 0x66;
let kExprI32Clz = 0x67;
let kExprI32Ctz = 0x68;
let kExprI32Popcnt = 0x69;
let kExprI32Add = 0x6a;
let kExprI32Sub = 0x6b;
let kExprI32Mul = 0x6c;
let kExprI32DivS = 0x6d;
let kExprI32DivU = 0x6e;
let kExprI32RemS = 0x6f;
let kExprI32RemU = 0x70;
let kExprI32And = 0x71;
let kExprI32Ior = 0x72;
let kExprI32Xor = 0x73;
let kExprI32Shl = 0x74;
let kExprI32ShrS = 0x75;
let kExprI32ShrU = 0x76;
let kExprI32Rol = 0x77;
let kExprI32Ror = 0x78;
let kExprI64Clz = 0x79;
let kExprI64Ctz = 0x7a;
let kExprI64Popcnt = 0x7b;
let kExprI64Add = 0x7c;
let kExprI64Sub = 0x7d;
let kExprI64Mul = 0x7e;
let kExprI64DivS = 0x7f;
let kExprI64DivU = 0x80;
let kExprI64RemS = 0x81;
let kExprI64RemU = 0x82;
let kExprI64And = 0x83;
let kExprI64Ior = 0x84;
let kExprI64Xor = 0x85;
let kExprI64Shl = 0x86;
let kExprI64ShrS = 0x87;
let kExprI64ShrU = 0x88;
let kExprI64Rol = 0x89;
let kExprI64Ror = 0x8a;
let kExprF32Abs = 0x8b;
let kExprF32Neg = 0x8c;
let kExprF32Ceil = 0x8d;
let kExprF32Floor = 0x8e;
let kExprF32Trunc = 0x8f;
let kExprF32NearestInt = 0x90;
let kExprF32Sqrt = 0x91;
let kExprF32Add = 0x92;
let kExprF32Sub = 0x93;
let kExprF32Mul = 0x94;
let kExprF32Div = 0x95;
let kExprF32Min = 0x96;
let kExprF32Max = 0x97;
let kExprF32CopySign = 0x98;
let kExprF64Abs = 0x99;
let kExprF64Neg = 0x9a;
let kExprF64Ceil = 0x9b;
let kExprF64Floor = 0x9c;
let kExprF64Trunc = 0x9d;
let kExprF64NearestInt = 0x9e;
let kExprF64Sqrt = 0x9f;
let kExprF64Add = 0xa0;
let kExprF64Sub = 0xa1;
let kExprF64Mul = 0xa2;
let kExprF64Div = 0xa3;
let kExprF64Min = 0xa4;
let kExprF64Max = 0xa5;
let kExprF64CopySign = 0xa6;
let kExprI32ConvertI64 = 0xa7;
let kExprI32SConvertF32 = 0xa8;
let kExprI32UConvertF32 = 0xa9;
let kExprI32SConvertF64 = 0xaa;
let kExprI32UConvertF64 = 0xab;
let kExprI64SConvertI32 = 0xac;
let kExprI64UConvertI32 = 0xad;
let kExprI64SConvertF32 = 0xae;
let kExprI64UConvertF32 = 0xaf;
let kExprI64SConvertF64 = 0xb0;
let kExprI64UConvertF64 = 0xb1;
let kExprF32SConvertI32 = 0xb2;
let kExprF32UConvertI32 = 0xb3;
let kExprF32SConvertI64 = 0xb4;
let kExprF32UConvertI64 = 0xb5;
let kExprF32ConvertF64 = 0xb6;
let kExprF64SConvertI32 = 0xb7;
let kExprF64UConvertI32 = 0xb8;
let kExprF64SConvertI64 = 0xb9;
let kExprF64UConvertI64 = 0xba;
let kExprF64ConvertF32 = 0xbb;
let kExprI32ReinterpretF32 = 0xbc;
let kExprI64ReinterpretF64 = 0xbd;
let kExprF32ReinterpretI32 = 0xbe;
let kExprF64ReinterpretI64 = 0xbf;
class Binary {
constructor() {
this.length = 0;
this.buffer = new Uint8Array(8192);
}
ensure_space(needed) {
if (this.buffer.length - this.length >= needed) return;
let new_capacity = this.buffer.length * 2;
while (new_capacity - this.length < needed) new_capacity *= 2;
let new_buffer = new Uint8Array(new_capacity);
new_buffer.set(this.buffer);
this.buffer = new_buffer;
}
trunc_buffer() {
return this.buffer = this.buffer.slice(0, this.length);
}
reset() {
this.length = 0;
}
class Binary extends Array {
emit_u8(val) {
this.push(val);
this.ensure_space(1);
this.buffer[this.length++] = val;
}
emit_u16(val) {
this.push(val & 0xff);
this.push((val >> 8) & 0xff);
this.ensure_space(2);
this.buffer[this.length++] = val;
this.buffer[this.length++] = val >> 8;
}
emit_u32(val) {
this.push(val & 0xff);
this.push((val >> 8) & 0xff);
this.push((val >> 16) & 0xff);
this.push((val >> 24) & 0xff);
this.ensure_space(4);
this.buffer[this.length++] = val;
this.buffer[this.length++] = val >> 8;
this.buffer[this.length++] = val >> 16;
this.buffer[this.length++] = val >> 24;
}
emit_u32v(val) {
while (true) {
emit_leb(val, max_len) {
this.ensure_space(max_len);
for (let i = 0; i < max_len; ++i) {
let v = val & 0xff;
val = val >>> 7;
if (val == 0) {
this.push(v);
break;
this.buffer[this.length++] = v;
return;
}
this.push(v | 0x80);
this.buffer[this.length++] = v | 0x80;
}
throw new Error("Leb value exceeds maximum length of " + max_len);
}
emit_u32v(val) {
this.emit_leb(val, kMaxVarInt32Size);
}
emit_u64v(val) {
this.emit_leb(val, kMaxVarInt64Size);
}
emit_bytes(data) {
for (let i = 0; i < data.length; i++) {
this.push(data[i] & 0xff);
}
this.ensure_space(data.length);
this.buffer.set(data, this.length);
this.length += data.length;
}
emit_string(string) {
@ -61,21 +418,22 @@ class Binary extends Array {
}
emit_header() {
this.push(kWasmH0, kWasmH1, kWasmH2, kWasmH3,
kWasmV0, kWasmV1, kWasmV2, kWasmV3);
this.emit_bytes([
kWasmH0, kWasmH1, kWasmH2, kWasmH3, kWasmV0, kWasmV1, kWasmV2, kWasmV3
]);
}
emit_section(section_code, content_generator) {
// Emit section name.
this.emit_u8(section_code);
// Emit the section to a temporary buffer: its full length isn't know yet.
let section = new Binary;
const section = new Binary;
content_generator(section);
// Emit section length.
this.emit_u32v(section.length);
// Copy the temporary buffer.
// Avoid spread because {section} can be huge.
for (let b of section) this.push(b);
this.emit_bytes(section.trunc_buffer());
}
}
@ -167,8 +525,9 @@ class WasmModuleBuilder {
}
addType(type) {
// TODO: canonicalize types?
this.types.push(type);
var pl = type.params.length; // should have params
var rl = type.results.length; // should have results
return this.types.length - 1;
}
@ -187,28 +546,28 @@ class WasmModuleBuilder {
return func;
}
addImport(module = "", name, type) {
addImport(module, name, type) {
let type_index = (typeof type) == "number" ? type : this.addType(type);
this.imports.push({module: module, name: name, kind: kExternalFunction,
type: type_index});
return this.num_imported_funcs++;
}
addImportedGlobal(module = "", name, type) {
addImportedGlobal(module, name, type) {
let o = {module: module, name: name, kind: kExternalGlobal, type: type,
mutable: false}
this.imports.push(o);
return this.num_imported_globals++;
}
addImportedMemory(module = "", name, initial = 0, maximum) {
addImportedMemory(module, name, initial = 0, maximum) {
let o = {module: module, name: name, kind: kExternalMemory,
initial: initial, maximum: maximum};
this.imports.push(o);
return this;
}
addImportedTable(module = "", name, initial, maximum) {
addImportedTable(module, name, initial, maximum) {
let o = {module: module, name: name, kind: kExternalTable, initial: initial,
maximum: maximum};
this.imports.push(o);
@ -263,17 +622,7 @@ class WasmModuleBuilder {
return this;
}
// TODO(ssauleau): legacy, remove this
setFunctionTableLength(length) {
return this.setTableBounds(length);
}
// TODO(ssauleau): legacy, remove this
setTableLength(min, max = undefined) {
return this.setTableBounds(min, max);
}
toArray(debug = false) {
toBuffer(debug = false) {
let binary = new Binary;
let wasm = this;
@ -394,22 +743,12 @@ class WasmModuleBuilder {
case kWasmF32:
section.emit_u8(kExprF32Const);
f32_view[0] = global.init;
section.emit_u8(byte_view[0]);
section.emit_u8(byte_view[1]);
section.emit_u8(byte_view[2]);
section.emit_u8(byte_view[3]);
section.emit_bytes(f32_bytes_view);
break;
case kWasmF64:
section.emit_u8(kExprF64Const);
f64_view[0] = global.init;
section.emit_u8(byte_view[0]);
section.emit_u8(byte_view[1]);
section.emit_u8(byte_view[2]);
section.emit_u8(byte_view[3]);
section.emit_u8(byte_view[4]);
section.emit_u8(byte_view[5]);
section.emit_u8(byte_view[6]);
section.emit_u8(byte_view[7]);
section.emit_bytes(f64_bytes_view);
break;
}
} else {
@ -443,7 +782,7 @@ class WasmModuleBuilder {
}
// Add start function section.
if (wasm.start_index != undefined) {
if (wasm.start_index !== undefined) {
if (debug) print("emitting start function @ " + binary.length);
binary.emit_section(kStartSectionCode, section => {
section.emit_u32v(wasm.start_index);
@ -480,7 +819,9 @@ class WasmModuleBuilder {
if (debug) print("emitting code @ " + binary.length);
binary.emit_section(kCodeSectionCode, section => {
section.emit_u32v(wasm.functions.length);
let header = new Binary;
for (let func of wasm.functions) {
header.reset();
// Function body length will be patched later.
let local_decls = [];
let l = func.locals;
@ -500,7 +841,6 @@ class WasmModuleBuilder {
}
}
let header = new Binary;
header.emit_u32v(local_decls.length);
for (let decl of local_decls) {
header.emit_u32v(decl.count);
@ -508,7 +848,7 @@ class WasmModuleBuilder {
}
section.emit_u32v(header.length + func.body.length);
section.emit_bytes(header);
section.emit_bytes(header.trunc_buffer());
section.emit_bytes(func.body);
}
});
@ -562,24 +902,51 @@ class WasmModuleBuilder {
});
}
return binary;
return binary.trunc_buffer();
}
toBuffer(debug = false) {
let bytes = this.toArray(debug);
let buffer = new ArrayBuffer(bytes.length);
let view = new Uint8Array(buffer);
for (let i = 0; i < bytes.length; i++) {
let val = bytes[i];
if ((typeof val) == "string") val = val.charCodeAt(0);
view[i] = val | 0;
}
return new Uint8Array(buffer);
toArray(debug = false) {
return Array.from(this.toBuffer(debug));
}
instantiate(...args) {
let module = new WebAssembly.Module(this.toBuffer());
let instance = new WebAssembly.Instance(module, ...args);
instantiate(ffi) {
let module = this.toModule();
let instance = new WebAssembly.Instance(module, ffi);
return instance;
}
asyncInstantiate(ffi) {
return WebAssembly.instantiate(this.toBuffer(), ffi)
.then(({module, instance}) => instance);
}
toModule(debug = false) {
return new WebAssembly.Module(this.toBuffer(debug));
}
}
function wasmI32Const(val) {
let bytes = [kExprI32Const];
for (let i = 0; i < 4; ++i) {
bytes.push(0x80 | ((val >> (7 * i)) & 0x7f));
}
bytes.push((val >> (7 * 4)) & 0x7f);
return bytes;
}
function wasmF32Const(f) {
f32_view[0] = f;
return [
kExprF32Const, f32_bytes_view[0], f32_bytes_view[1], f32_bytes_view[2],
f32_bytes_view[3]
];
}
function wasmF64Const(f) {
f64_view[0] = f;
return [
kExprF64Const, f64_bytes_view[0], f64_bytes_view[1], f64_bytes_view[2],
f64_bytes_view[3], f64_bytes_view[4], f64_bytes_view[5], f64_bytes_view[6],
f64_bytes_view[7]
];
}

View file

@ -1,5 +1,4 @@
// META: global=window,worker
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
for (const method of ["compileStreaming", "instantiateStreaming"]) {

View file

@ -1,5 +1,4 @@
// META: global=window,worker
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
// META: script=/wasm/jsapi/bad-imports.js

View file

@ -1,5 +1,4 @@
// META: global=window,worker
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
// META: script=/wasm/jsapi/assertions.js
// META: script=/wasm/jsapi/instanceTestFactory.js

View file

@ -1,5 +1,4 @@
// META: global=window,worker
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
let emptyModuleBinary;