mirror of
https://github.com/tauri-apps/verso.git
synced 2026-01-31 00:55:21 +01:00
feat: flatpak support (#91)
* Add flatpak manifest Known issues: - MOZJS_ARCHIVE need to link manually - Mozangle build failed due to stddef.h missing - script build failed due to missing WebIDL python module * Fix mozangle and script build errors * Update README.md * Update gitignore * Add libmozjs archive * Import more granular servo crates * Fix running error in flatpak * Enable surfman features on Windows * Enable mozangle features instead * build(flatpak): add verso desktop file --------- Co-authored-by: Wu Yuwei <Wu Yu Wei> Co-authored-by: Jason Tsai <jason@pews.dev>
This commit is contained in:
committed by
GitHub
parent
74addf188b
commit
a5bdd6a104
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1 +1,2 @@
|
||||
resources/* linguist-vendored
|
||||
third_party/* linguist-vendored
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,3 +3,6 @@ Cargo.lock
|
||||
.DS_Store
|
||||
.vscode/
|
||||
resources/
|
||||
.flatpak-builder/
|
||||
libmozjs*
|
||||
cargo-sources.json
|
||||
|
||||
184
Cargo.lock
generated
184
Cargo.lock
generated
@@ -425,10 +425,7 @@ source = "git+https://github.com/servo/servo.git?rev=ed8def2#ed8def28960fd64fa0d
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"bluetooth_traits",
|
||||
"blurdroid",
|
||||
"blurmac",
|
||||
"blurmock",
|
||||
"blurz",
|
||||
"embedder_traits",
|
||||
"ipc-channel",
|
||||
"log",
|
||||
@@ -448,21 +445,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blurdroid"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b23557dd27704797128f9db2816416bef20dad62d4a9768714eeb65f07d296"
|
||||
|
||||
[[package]]
|
||||
name = "blurmac"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/servo/servo.git?rev=ed8def2#ed8def28960fd64fa0d00bd67731d594c1042747"
|
||||
dependencies = [
|
||||
"log",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blurmock"
|
||||
version = "0.1.3"
|
||||
@@ -472,16 +454,6 @@ dependencies = [
|
||||
"hex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blurz"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6dae8337ff67fe8ead29a28a0115605753e6a5205d4b6017e9f42f198c3c50a"
|
||||
dependencies = [
|
||||
"dbus",
|
||||
"hex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brotli"
|
||||
version = "3.5.0"
|
||||
@@ -816,43 +788,6 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compositing"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/servo.git?rev=ed8def2#ed8def28960fd64fa0d00bd67731d594c1042747"
|
||||
dependencies = [
|
||||
"base",
|
||||
"canvas",
|
||||
"compositing_traits",
|
||||
"crossbeam-channel",
|
||||
"embedder_traits",
|
||||
"euclid",
|
||||
"fnv",
|
||||
"fonts",
|
||||
"fonts_traits",
|
||||
"gleam",
|
||||
"image 0.24.9",
|
||||
"ipc-channel",
|
||||
"keyboard-types",
|
||||
"libc",
|
||||
"log",
|
||||
"net_traits",
|
||||
"pixels",
|
||||
"profile_traits",
|
||||
"script_traits",
|
||||
"servo-media",
|
||||
"servo_config",
|
||||
"servo_geometry",
|
||||
"servo_url",
|
||||
"style_traits",
|
||||
"time 0.1.45",
|
||||
"toml",
|
||||
"webrender",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
"webxr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compositing_traits"
|
||||
version = "0.0.1"
|
||||
@@ -1212,16 +1147,6 @@ dependencies = [
|
||||
"matches",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dbus"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48b5f0f36f1eebe901b0e6bee369a77ed3396334bf3f09abd46454a576f71819"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libdbus-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deny_public_fields"
|
||||
version = "0.0.1"
|
||||
@@ -2823,15 +2748,6 @@ version = "0.2.155"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "libdbus-sys"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72"
|
||||
dependencies = [
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libflate"
|
||||
version = "0.1.27"
|
||||
@@ -2871,62 +2787,6 @@ dependencies = [
|
||||
"redox_syscall 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libservo"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/servo.git?rev=ed8def2#ed8def28960fd64fa0d00bd67731d594c1042747"
|
||||
dependencies = [
|
||||
"background_hang_monitor",
|
||||
"base",
|
||||
"bluetooth",
|
||||
"bluetooth_traits",
|
||||
"canvas",
|
||||
"canvas_traits",
|
||||
"cfg-if",
|
||||
"compositing",
|
||||
"compositing_traits",
|
||||
"constellation",
|
||||
"crossbeam-channel",
|
||||
"devtools",
|
||||
"devtools_traits",
|
||||
"embedder_traits",
|
||||
"env_logger",
|
||||
"euclid",
|
||||
"fonts",
|
||||
"fonts_traits",
|
||||
"gaol",
|
||||
"gleam",
|
||||
"ipc-channel",
|
||||
"keyboard-types",
|
||||
"layout_thread_2020",
|
||||
"log",
|
||||
"media",
|
||||
"mozangle",
|
||||
"net",
|
||||
"net_traits",
|
||||
"profile",
|
||||
"profile_traits",
|
||||
"script",
|
||||
"script_layout_interface",
|
||||
"script_traits",
|
||||
"servo-media",
|
||||
"servo-media-dummy",
|
||||
"servo_config",
|
||||
"servo_geometry",
|
||||
"servo_url",
|
||||
"sparkle",
|
||||
"style",
|
||||
"style_traits",
|
||||
"surfman",
|
||||
"webdriver_server",
|
||||
"webgpu",
|
||||
"webrender",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
"webxr",
|
||||
"webxr-api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.1.18"
|
||||
@@ -3693,12 +3553,6 @@ dependencies = [
|
||||
"ttf-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "4.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.3"
|
||||
@@ -5562,15 +5416,6 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.6"
|
||||
@@ -5821,29 +5666,54 @@ name = "verso"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"arboard",
|
||||
"base",
|
||||
"block",
|
||||
"bluetooth",
|
||||
"bluetooth_traits",
|
||||
"canvas",
|
||||
"cargo-packager-resource-resolver",
|
||||
"cfg_aliases 0.2.1",
|
||||
"cocoa 0.25.0",
|
||||
"compositing_traits",
|
||||
"constellation",
|
||||
"core-graphics 0.23.2",
|
||||
"crossbeam-channel",
|
||||
"devtools",
|
||||
"embedder_traits",
|
||||
"env_logger",
|
||||
"euclid",
|
||||
"fonts",
|
||||
"getopts",
|
||||
"gleam",
|
||||
"ipc-channel",
|
||||
"libservo",
|
||||
"keyboard-types",
|
||||
"layout_thread_2020",
|
||||
"log",
|
||||
"media",
|
||||
"mozangle",
|
||||
"net",
|
||||
"objc",
|
||||
"objc_id",
|
||||
"owo-colors",
|
||||
"profile",
|
||||
"profile_traits",
|
||||
"raw-window-handle 0.5.2",
|
||||
"script",
|
||||
"script_traits",
|
||||
"servo-media",
|
||||
"servo-media-dummy",
|
||||
"servo_config",
|
||||
"servo_geometry",
|
||||
"servo_url",
|
||||
"sparkle",
|
||||
"style",
|
||||
"style_traits",
|
||||
"surfman",
|
||||
"thiserror",
|
||||
"webdriver_server",
|
||||
"webgpu",
|
||||
"webrender",
|
||||
"webrender_api",
|
||||
"webrender_traits",
|
||||
"webxr",
|
||||
"winit",
|
||||
]
|
||||
|
||||
67
Cargo.toml
67
Cargo.toml
@@ -40,41 +40,66 @@ targets = [
|
||||
[features]
|
||||
default = []
|
||||
packager = ["dep:cargo-packager-resource-resolver"]
|
||||
flatpak = []
|
||||
|
||||
[build-dependencies]
|
||||
cfg_aliases = "0.2"
|
||||
|
||||
[dependencies]
|
||||
owo-colors = "4.0"
|
||||
log = "0.4"
|
||||
thiserror = "1.0"
|
||||
raw-window-handle = { version = "0.5", features = ["std"] }
|
||||
arboard = "3.4.0"
|
||||
# Servo
|
||||
libservo = { git = "https://github.com/servo/servo.git", rev = "ed8def2", features = ["max_log_level", "native-bluetooth", "webdriver"] }
|
||||
compositing_traits = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
webdriver_server = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
webrender = { git = "https://github.com/servo/webrender", branch = "0.64", features = ["capture"] }
|
||||
sparkle = "0.1.26"
|
||||
webxr = { git = "https://github.com/servo/webxr", features = ["headless"] }
|
||||
crossbeam-channel = "0.5"
|
||||
env_logger = "0.10"
|
||||
euclid = "0.22"
|
||||
getopts = "0.2.17"
|
||||
gleam = "0.15"
|
||||
ipc-channel = "0.18"
|
||||
keyboard-types = "0.7"
|
||||
log = "0.4"
|
||||
raw-window-handle = { version = "0.5", features = ["std"] }
|
||||
sparkle = "0.1.26"
|
||||
surfman = { version = "0.9", features = ["chains", "sm-raw-window-handle"] }
|
||||
thiserror = "1.0"
|
||||
winit = { version = "0.29", features = ["rwh_05"] }
|
||||
# Servo repo crates
|
||||
# libservo = { git = "https://github.com/servo/servo.git", rev = "ed8def2", features = ["max_log_level", "native-bluetooth", "webdriver"] }
|
||||
base = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
bluetooth = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
bluetooth_traits = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
canvas = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
compositing_traits = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
constellation = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
devtools = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
embedder_traits = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
fonts = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
layout_thread_2020 = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
media = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
net = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
profile = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
profile_traits = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
script = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
script_traits = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
servo_config = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
servo_geometry = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
servo_url = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
webdriver_server = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
webrender_traits = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
webgpu = { git = "https://github.com/servo/servo.git", rev = "ed8def2" }
|
||||
# Servo org crates
|
||||
servo-media = { git = "https://github.com/servo/media" }
|
||||
servo-media-dummy = { git = "https://github.com/servo/media" }
|
||||
# Servo Compositor
|
||||
ipc-channel = "0.18"
|
||||
# Servo
|
||||
crossbeam-channel = "0.5"
|
||||
getopts = "0.2.17"
|
||||
surfman = { version = "0.9", features = ["chains", "sm-raw-window-handle"] }
|
||||
winit = { version = "0.29", features = ["rwh_05"] }
|
||||
style = { git = "https://github.com/servo/stylo", branch = "2024-07-16", features = ["servo"] }
|
||||
style_traits = { git = "https://github.com/servo/stylo", branch = "2024-07-16", features = ["servo"] }
|
||||
webrender = { git = "https://github.com/servo/webrender", branch = "0.64", features = ["capture"] }
|
||||
webrender_api = { git = "https://github.com/servo/webrender", branch = "0.64" }
|
||||
webxr = { git = "https://github.com/servo/webxr", features = ["headless"] }
|
||||
# Packager feature
|
||||
cargo-packager-resource-resolver = { version = "0.1.1", features = [
|
||||
"auto-detect-format",
|
||||
], optional = true }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
libservo = { git = "https://github.com/servo/servo.git", rev = "ed8def2", features = [
|
||||
"no-wgl",
|
||||
] }
|
||||
surfman = { version = "0.9", features = ["sm-angle-default"] }
|
||||
mozangle = { version = "0.5.1", features = ["egl", "build_dlls"] }
|
||||
|
||||
[target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies]
|
||||
block = "0.1"
|
||||
|
||||
44
README.md
44
README.md
@@ -48,9 +48,33 @@ cargo run
|
||||
|
||||
### Linux
|
||||
|
||||
#### Flatpak
|
||||
|
||||
For unified environment setup and package experience, we choose Flatpak to build the project from the start.
|
||||
Please follow [Flatpack Setup](https://flatpak.org/setup/) page to install Flakpak based on your distribution.
|
||||
|
||||
- Install flatpak runtimes and extensions:
|
||||
|
||||
```sh
|
||||
flatpak install flathub org.freedesktop.Platform//23.08
|
||||
flatpak install flathub org.freedesktop.Sdk//23.08
|
||||
flatpak install flathub org.freedesktop.Sdk.Extension.rust-stable//23.08
|
||||
flatpak install flathub org.freedesktop.Sdk.Extension.llvm18//23.08
|
||||
```
|
||||
|
||||
- Generate manifests and build:
|
||||
// TODO Exporting to a repository instead
|
||||
|
||||
```sh
|
||||
python3 ./flatpak-cargo-generator.py ./Cargo.lock -o cargo-sources.json
|
||||
flatpak-builder --user --install --force-clean target org.versotile.verso.yml
|
||||
flatpak run org.versotile.verso
|
||||
```
|
||||
|
||||
#### Nix
|
||||
|
||||
We also support building Verso in nix shell. But we don't bundle it in nix at the moment.
|
||||
|
||||
- For NixOS:
|
||||
|
||||
```sh
|
||||
@@ -63,24 +87,8 @@ nix-shell shell.nix --run 'cargo r'
|
||||
nix-shell shell.nix --run 'nixGL cargo r'
|
||||
```
|
||||
|
||||
#### Debian-based Distributions
|
||||
|
||||
```sh
|
||||
sudo apt install build-essential python3-pip ccache clang cmake curl \
|
||||
g++ git gperf libdbus-1-dev libfreetype6-dev libgl1-mesa-dri \
|
||||
libgles2-mesa-dev libglib2.0-dev libgstreamer-plugins-base1.0-dev \
|
||||
gstreamer1.0-plugins-good libgstreamer-plugins-good1.0-dev \
|
||||
gstreamer1.0-plugins-bad libgstreamer-plugins-bad1.0-dev \
|
||||
gstreamer1.0-plugins-ugly gstreamer1.0-plugins-base \
|
||||
libgstreamer-plugins-base1.0-dev gstreamer1.0-libav \
|
||||
libgstrtspserver-1.0-dev gstreamer1.0-tools libges-1.0-dev \
|
||||
libharfbuzz-dev liblzma-dev libunwind-dev libunwind-dev libvulkan1 \
|
||||
libx11-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev \
|
||||
libxmu-dev libxmu6 libegl1-mesa-dev llvm-dev m4 xorg-dev \
|
||||
python3-mako
|
||||
```
|
||||
|
||||
For others, please follow the instructions in [Servo book](https://book.servo.org/hacking/setting-up-your-environment.html#tools-for-linux) to bootstrap first.
|
||||
If you prefer to build the project without any sandbox, please follow the instructions in [Servo book](https://book.servo.org/hacking/setting-up-your-environment.html#tools-for-linux) to bootstrap.
|
||||
But please understand we don't triage any build issue without flatpak or nix setup.
|
||||
|
||||
## Nightly Release
|
||||
|
||||
|
||||
438
flatpak-cargo-generator.py
Normal file
438
flatpak-cargo-generator.py
Normal file
@@ -0,0 +1,438 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
__license__ = 'MIT'
|
||||
import json
|
||||
from urllib.parse import urlparse, ParseResult, parse_qs
|
||||
import os
|
||||
import contextlib
|
||||
import copy
|
||||
import glob
|
||||
import subprocess
|
||||
import argparse
|
||||
import logging
|
||||
import hashlib
|
||||
import asyncio
|
||||
from typing import Any, Dict, List, NamedTuple, Optional, Tuple, TypedDict
|
||||
|
||||
import aiohttp
|
||||
import toml
|
||||
|
||||
CRATES_IO = 'https://static.crates.io/crates'
|
||||
CARGO_HOME = 'cargo'
|
||||
CARGO_CRATES = f'{CARGO_HOME}/vendor'
|
||||
VENDORED_SOURCES = 'vendored-sources'
|
||||
GIT_CACHE = 'flatpak-cargo/git'
|
||||
COMMIT_LEN = 7
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def workdir(path: str):
|
||||
oldpath = os.getcwd()
|
||||
os.chdir(path)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
os.chdir(oldpath)
|
||||
|
||||
|
||||
def canonical_url(url: str) -> ParseResult:
|
||||
'Converts a string to a Cargo Canonical URL, as per https://github.com/rust-lang/cargo/blob/35c55a93200c84a4de4627f1770f76a8ad268a39/src/cargo/util/canonical_url.rs#L19'
|
||||
# Hrm. The upstream cargo does not replace those URLs, but if we don't then it doesn't work too well :(
|
||||
url = url.replace('git+https://', 'https://')
|
||||
u = urlparse(url)
|
||||
# It seems cargo drops query and fragment
|
||||
u = ParseResult(u.scheme, u.netloc, u.path, '', '', '')
|
||||
u = u._replace(path = u.path.rstrip('/'))
|
||||
|
||||
if u.netloc == 'github.com':
|
||||
u = u._replace(scheme = 'https')
|
||||
u = u._replace(path = u.path.lower())
|
||||
|
||||
if u.path.endswith('.git'):
|
||||
u = u._replace(path = u.path[:-len('.git')])
|
||||
|
||||
return u
|
||||
|
||||
|
||||
def get_git_tarball(repo_url: str, commit: str) -> str:
|
||||
url = canonical_url(repo_url)
|
||||
path = url.path.split('/')[1:]
|
||||
|
||||
assert len(path) == 2
|
||||
owner = path[0]
|
||||
if path[1].endswith('.git'):
|
||||
repo = path[1].replace('.git', '')
|
||||
else:
|
||||
repo = path[1]
|
||||
if url.hostname == 'github.com':
|
||||
return f'https://codeload.{url.hostname}/{owner}/{repo}/tar.gz/{commit}'
|
||||
elif url.hostname.split('.')[0] == 'gitlab': # type: ignore
|
||||
return f'https://{url.hostname}/{owner}/{repo}/-/archive/{commit}/{repo}-{commit}.tar.gz'
|
||||
elif url.hostname == 'bitbucket.org':
|
||||
return f'https://{url.hostname}/{owner}/{repo}/get/{commit}.tar.gz'
|
||||
else:
|
||||
raise ValueError(f'Don\'t know how to get tarball for {repo_url}')
|
||||
|
||||
|
||||
async def get_remote_sha256(url: str) -> str:
|
||||
logging.info(f"started sha256({url})")
|
||||
sha256 = hashlib.sha256()
|
||||
async with aiohttp.ClientSession(raise_for_status=True) as http_session:
|
||||
async with http_session.get(url) as response:
|
||||
while True:
|
||||
data = await response.content.read(4096)
|
||||
if not data:
|
||||
break
|
||||
sha256.update(data)
|
||||
logging.info(f"done sha256({url})")
|
||||
return sha256.hexdigest()
|
||||
|
||||
|
||||
_TomlType = Dict[str, Any]
|
||||
|
||||
|
||||
def load_toml(tomlfile: str = 'Cargo.lock') -> _TomlType:
|
||||
with open(tomlfile, 'r') as f:
|
||||
toml_data = toml.load(f)
|
||||
return toml_data
|
||||
|
||||
|
||||
def git_repo_name(git_url: str, commit: str) -> str:
|
||||
name = canonical_url(git_url).path.split('/')[-1]
|
||||
return f'{name}-{commit[:COMMIT_LEN]}'
|
||||
|
||||
|
||||
def fetch_git_repo(git_url: str, commit: str) -> str:
|
||||
repo_dir = git_url.replace('://', '_').replace('/', '_')
|
||||
cache_dir = os.environ.get('XDG_CACHE_HOME', os.path.expanduser('~/.cache'))
|
||||
clone_dir = os.path.join(cache_dir, 'flatpak-cargo', repo_dir)
|
||||
if not os.path.isdir(os.path.join(clone_dir, '.git')):
|
||||
subprocess.run(['git', 'clone', '--depth=1', git_url, clone_dir], check=True)
|
||||
rev_parse_proc = subprocess.run(['git', 'rev-parse', 'HEAD'], cwd=clone_dir, check=True,
|
||||
stdout=subprocess.PIPE)
|
||||
head = rev_parse_proc.stdout.decode().strip()
|
||||
if head[:COMMIT_LEN] != commit[:COMMIT_LEN]:
|
||||
subprocess.run(['git', 'fetch', 'origin', commit], cwd=clone_dir, check=True)
|
||||
subprocess.run(['git', 'checkout', commit], cwd=clone_dir, check=True)
|
||||
|
||||
# Get the submodules as they might contain dependencies. This is a noop if
|
||||
# there are no submodules in the repository
|
||||
subprocess.run(['git', 'submodule', 'update', '--init', '--recursive'], cwd=clone_dir, check=True)
|
||||
|
||||
return clone_dir
|
||||
|
||||
def update_workspace_keys(pkg, workspace):
|
||||
for key, item in pkg.items():
|
||||
# There cannot be a 'workspace' key if the item is not a dict.
|
||||
if not isinstance(item, dict):
|
||||
continue;
|
||||
|
||||
# Recurse for keys under target.cfg(..)
|
||||
if key == 'target':
|
||||
for target in item.values():
|
||||
update_workspace_keys(target, workspace)
|
||||
continue;
|
||||
# dev-dependencies and build-dependencies should reference root dependencies table from workspace
|
||||
elif key == 'dev-dependencies' or key == 'build-dependencies':
|
||||
update_workspace_keys(item, workspace.get('dependencies', None))
|
||||
continue;
|
||||
|
||||
if not workspace or not key in workspace:
|
||||
continue;
|
||||
|
||||
workspace_item = workspace[key]
|
||||
|
||||
if 'workspace' in item:
|
||||
if isinstance(workspace_item, dict):
|
||||
del item['workspace']
|
||||
|
||||
for dep_key, workspace_value in workspace_item.items():
|
||||
# features are additive
|
||||
if dep_key == 'features' and 'features' in item:
|
||||
item['features'] += workspace_value
|
||||
else:
|
||||
item[dep_key] = workspace_value
|
||||
elif len(item) > 1:
|
||||
del item['workspace']
|
||||
item.update({ 'version': workspace_item })
|
||||
else:
|
||||
pkg[key] = workspace_item
|
||||
else:
|
||||
update_workspace_keys(item, workspace_item)
|
||||
|
||||
class _GitPackage(NamedTuple):
|
||||
path: str
|
||||
package: _TomlType
|
||||
workspace: Optional[_TomlType]
|
||||
|
||||
@property
|
||||
def normalized(self) -> _TomlType:
|
||||
package = copy.deepcopy(self.package)
|
||||
if self.workspace is None:
|
||||
return package
|
||||
|
||||
update_workspace_keys(package, self.workspace)
|
||||
|
||||
return package
|
||||
|
||||
_GitPackagesType = Dict[str, _GitPackage]
|
||||
|
||||
|
||||
async def get_git_repo_packages(git_url: str, commit: str) -> _GitPackagesType:
|
||||
logging.info('Loading packages from %s', git_url)
|
||||
git_repo_dir = fetch_git_repo(git_url, commit)
|
||||
packages: _GitPackagesType = {}
|
||||
|
||||
def get_cargo_toml_packages(root_dir: str, workspace: Optional[_TomlType] = None):
|
||||
assert not os.path.isabs(root_dir) and os.path.isdir(root_dir)
|
||||
|
||||
with workdir(root_dir):
|
||||
if os.path.exists('Cargo.toml'):
|
||||
cargo_toml = load_toml('Cargo.toml')
|
||||
workspace = cargo_toml.get('workspace') or workspace
|
||||
|
||||
if 'package' in cargo_toml:
|
||||
packages[cargo_toml['package']['name']] = _GitPackage(
|
||||
path=os.path.normpath(root_dir),
|
||||
package=cargo_toml,
|
||||
workspace=workspace
|
||||
)
|
||||
for child in os.scandir(root_dir):
|
||||
if child.is_dir():
|
||||
# the workspace can be referenced by any subdirectory
|
||||
get_cargo_toml_packages(child.path, workspace)
|
||||
|
||||
with workdir(git_repo_dir):
|
||||
get_cargo_toml_packages('.')
|
||||
|
||||
assert packages, f"No packages found in {git_repo_dir}"
|
||||
logging.debug(
|
||||
'Packages in %s:\n%s',
|
||||
git_url,
|
||||
json.dumps(
|
||||
{k: v.path for k, v in packages.items()},
|
||||
indent=4,
|
||||
),
|
||||
)
|
||||
return packages
|
||||
|
||||
|
||||
_FlatpakSourceType = Dict[str, Any]
|
||||
|
||||
|
||||
async def get_git_repo_sources(
|
||||
url: str,
|
||||
commit: str,
|
||||
tarball: bool = False,
|
||||
) -> List[_FlatpakSourceType]:
|
||||
name = git_repo_name(url, commit)
|
||||
if tarball:
|
||||
tarball_url = get_git_tarball(url, commit)
|
||||
git_repo_sources = [{
|
||||
'type': 'archive',
|
||||
'archive-type': 'tar-gzip',
|
||||
'url': tarball_url,
|
||||
'sha256': await get_remote_sha256(tarball_url),
|
||||
'dest': f'{GIT_CACHE}/{name}',
|
||||
}]
|
||||
else:
|
||||
git_repo_sources = [{
|
||||
'type': 'git',
|
||||
'url': url,
|
||||
'commit': commit,
|
||||
'dest': f'{GIT_CACHE}/{name}',
|
||||
}]
|
||||
return git_repo_sources
|
||||
|
||||
|
||||
_GitRepo = TypedDict('_GitRepo', {'lock': asyncio.Lock, 'commits': Dict[str, _GitPackagesType]})
|
||||
_GitReposType = Dict[str, _GitRepo]
|
||||
_VendorEntryType = Dict[str, Dict[str, str]]
|
||||
|
||||
|
||||
async def get_git_package_sources(
|
||||
package: _TomlType,
|
||||
git_repos: _GitReposType,
|
||||
) -> Tuple[List[_FlatpakSourceType], _VendorEntryType]:
|
||||
name = package['name']
|
||||
source = package['source']
|
||||
commit = urlparse(source).fragment
|
||||
assert commit, 'The commit needs to be indicated in the fragement part'
|
||||
canonical = canonical_url(source)
|
||||
repo_url = canonical.geturl()
|
||||
|
||||
git_repo = git_repos.setdefault(repo_url, {
|
||||
'commits': {},
|
||||
'lock': asyncio.Lock(),
|
||||
})
|
||||
async with git_repo['lock']:
|
||||
if commit not in git_repo['commits']:
|
||||
git_repo['commits'][commit] = await get_git_repo_packages(repo_url, commit)
|
||||
|
||||
cargo_vendored_entry: _VendorEntryType = {
|
||||
repo_url: {
|
||||
'git': repo_url,
|
||||
'replace-with': VENDORED_SOURCES,
|
||||
}
|
||||
}
|
||||
rev = parse_qs(urlparse(source).query).get('rev')
|
||||
tag = parse_qs(urlparse(source).query).get('tag')
|
||||
branch = parse_qs(urlparse(source).query).get('branch')
|
||||
if rev:
|
||||
assert len(rev) == 1
|
||||
cargo_vendored_entry[repo_url]['rev'] = rev[0]
|
||||
elif tag:
|
||||
assert len(tag) == 1
|
||||
cargo_vendored_entry[repo_url]['tag'] = tag[0]
|
||||
elif branch:
|
||||
assert len(branch) == 1
|
||||
cargo_vendored_entry[repo_url]['branch'] = branch[0]
|
||||
|
||||
logging.info("Adding package %s from %s", name, repo_url)
|
||||
git_pkg = git_repo['commits'][commit][name]
|
||||
pkg_repo_dir = os.path.join(GIT_CACHE, git_repo_name(repo_url, commit), git_pkg.path)
|
||||
git_sources: List[_FlatpakSourceType] = [
|
||||
{
|
||||
'type': 'shell',
|
||||
'commands': [
|
||||
f'cp -r --reflink=auto "{pkg_repo_dir}" "{CARGO_CRATES}/{name}"'
|
||||
],
|
||||
},
|
||||
{
|
||||
'type': 'inline',
|
||||
'contents': toml.dumps(git_pkg.normalized),
|
||||
'dest': f'{CARGO_CRATES}/{name}', #-{version}',
|
||||
'dest-filename': 'Cargo.toml',
|
||||
},
|
||||
{
|
||||
'type': 'inline',
|
||||
'contents': json.dumps({'package': None, 'files': {}}),
|
||||
'dest': f'{CARGO_CRATES}/{name}', #-{version}',
|
||||
'dest-filename': '.cargo-checksum.json',
|
||||
}
|
||||
]
|
||||
|
||||
return (git_sources, cargo_vendored_entry)
|
||||
|
||||
|
||||
async def get_package_sources(
|
||||
package: _TomlType,
|
||||
cargo_lock: _TomlType,
|
||||
git_repos: _GitReposType,
|
||||
) -> Optional[Tuple[List[_FlatpakSourceType], _VendorEntryType]]:
|
||||
metadata = cargo_lock.get('metadata')
|
||||
name = package['name']
|
||||
version = package['version']
|
||||
|
||||
if 'source' not in package:
|
||||
logging.debug('%s has no source', name)
|
||||
return None
|
||||
source = package['source']
|
||||
|
||||
if source.startswith('git+'):
|
||||
return await get_git_package_sources(package, git_repos)
|
||||
|
||||
key = f'checksum {name} {version} ({source})'
|
||||
if metadata is not None and key in metadata:
|
||||
checksum = metadata[key]
|
||||
elif 'checksum' in package:
|
||||
checksum = package['checksum']
|
||||
else:
|
||||
logging.warning(f'{name} doesn\'t have checksum')
|
||||
return None
|
||||
crate_sources = [
|
||||
{
|
||||
'type': 'archive',
|
||||
'archive-type': 'tar-gzip',
|
||||
'url': f'{CRATES_IO}/{name}/{name}-{version}.crate',
|
||||
'sha256': checksum,
|
||||
'dest': f'{CARGO_CRATES}/{name}-{version}',
|
||||
},
|
||||
{
|
||||
'type': 'inline',
|
||||
'contents': json.dumps({'package': checksum, 'files': {}}),
|
||||
'dest': f'{CARGO_CRATES}/{name}-{version}',
|
||||
'dest-filename': '.cargo-checksum.json',
|
||||
},
|
||||
]
|
||||
return (crate_sources, {'crates-io': {'replace-with': VENDORED_SOURCES}})
|
||||
|
||||
|
||||
async def generate_sources(
|
||||
cargo_lock: _TomlType,
|
||||
git_tarballs: bool = False,
|
||||
) -> List[_FlatpakSourceType]:
|
||||
# {
|
||||
# "git-repo-url": {
|
||||
# "lock": asyncio.Lock(),
|
||||
# "commits": {
|
||||
# "commit-hash": {
|
||||
# "package-name": "./relative/package/path"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
git_repos: _GitReposType = {}
|
||||
sources: List[_FlatpakSourceType] = []
|
||||
package_sources = []
|
||||
cargo_vendored_sources = {
|
||||
VENDORED_SOURCES: {'directory': f'{CARGO_CRATES}'},
|
||||
}
|
||||
|
||||
pkg_coros = [get_package_sources(p, cargo_lock, git_repos) for p in cargo_lock['package']]
|
||||
for pkg in await asyncio.gather(*pkg_coros):
|
||||
if pkg is None:
|
||||
continue
|
||||
else:
|
||||
pkg_sources, cargo_vendored_entry = pkg
|
||||
package_sources.extend(pkg_sources)
|
||||
cargo_vendored_sources.update(cargo_vendored_entry)
|
||||
|
||||
logging.debug('Adding collected git repos:\n%s', json.dumps(list(git_repos), indent=4))
|
||||
git_repo_coros = []
|
||||
for git_url, git_repo in git_repos.items():
|
||||
for git_commit in git_repo['commits']:
|
||||
git_repo_coros.append(get_git_repo_sources(git_url, git_commit, git_tarballs))
|
||||
sources.extend(sum(await asyncio.gather(*git_repo_coros), []))
|
||||
|
||||
sources.extend(package_sources)
|
||||
|
||||
logging.debug('Vendored sources:\n%s', json.dumps(cargo_vendored_sources, indent=4))
|
||||
sources.append({
|
||||
'type': 'inline',
|
||||
'contents': toml.dumps({
|
||||
'source': cargo_vendored_sources,
|
||||
}),
|
||||
'dest': CARGO_HOME,
|
||||
'dest-filename': 'config'
|
||||
})
|
||||
return sources
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('cargo_lock', help='Path to the Cargo.lock file')
|
||||
parser.add_argument('-o', '--output', required=False, help='Where to write generated sources')
|
||||
parser.add_argument('-t', '--git-tarballs', action='store_true', help='Download git repos as tarballs')
|
||||
parser.add_argument('-d', '--debug', action='store_true')
|
||||
args = parser.parse_args()
|
||||
if args.output is not None:
|
||||
outfile = args.output
|
||||
else:
|
||||
outfile = 'generated-sources.json'
|
||||
if args.debug:
|
||||
loglevel = logging.DEBUG
|
||||
else:
|
||||
loglevel = logging.INFO
|
||||
logging.basicConfig(level=loglevel)
|
||||
|
||||
generated_sources = asyncio.run(generate_sources(load_toml(args.cargo_lock),
|
||||
git_tarballs=args.git_tarballs))
|
||||
with open(outfile, 'w') as out:
|
||||
json.dump(generated_sources, out, indent=4, sort_keys=False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
||||
9
org.versotile.verso.desktop
Normal file
9
org.versotile.verso.desktop
Normal file
@@ -0,0 +1,9 @@
|
||||
[Desktop Entry]
|
||||
Name=Verso
|
||||
StartupWMClass=verso
|
||||
Comment=A web browser that plays old world blues to build new world hope.
|
||||
GenericName=Web Browser
|
||||
Type=Application
|
||||
Categories=Network
|
||||
Icon=org.versotile.verso
|
||||
Exec=verso
|
||||
54
org.versotile.verso.yml
Normal file
54
org.versotile.verso.yml
Normal file
@@ -0,0 +1,54 @@
|
||||
id: org.versotile.verso
|
||||
runtime: org.freedesktop.Platform
|
||||
runtime-version: '23.08'
|
||||
sdk: org.freedesktop.Sdk
|
||||
sdk-extensions:
|
||||
- org.freedesktop.Sdk.Extension.rust-stable
|
||||
- org.freedesktop.Sdk.Extension.llvm18
|
||||
finish-args:
|
||||
- --share=ipc
|
||||
- --socket=fallback-x11
|
||||
- --socket=wayland
|
||||
- --socket=pulseaudio
|
||||
- --socket=system-bus
|
||||
- --socket=session-bus
|
||||
- --share=network
|
||||
- --device=dri
|
||||
- --filesystem=home
|
||||
build-options:
|
||||
append-path: /usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm18/bin
|
||||
prepend-ld-library-path: /usr/lib/sdk/llvm18/lib
|
||||
env:
|
||||
CARGO_HOME: /run/build/verso/cargo
|
||||
MOZJS_ARCHIVE: /run/build/verso/libmozjs-x86_64-unknown-linux-gnu.tar.gz
|
||||
command: verso
|
||||
modules:
|
||||
- name: verso
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
# Install pyhton packages required by script crates
|
||||
- pip3 install --prefix=/app --no-deps ./third_party/ply
|
||||
- pip3 install --prefix=/app --no-deps ./third_party/WebIDL/
|
||||
# Desktop file
|
||||
- install -d /app/share/applications
|
||||
- install -Dm755 ./org.versotile.verso.desktop /app/share/applications/${FLATPAK_ID}.desktop
|
||||
- install -Dm644 ./icons/icon256x256.png /app/share/icons/hicolor/256x256/apps/${FLATPAK_ID}.png
|
||||
# Build Verso release profile
|
||||
- cargo --offline fetch --manifest-path Cargo.toml
|
||||
- cargo --offline build --release --features flatpak
|
||||
# Install Verso
|
||||
- install -Dm755 ./target/release/verso -t /app/bin/
|
||||
- mkdir /app/resources
|
||||
- cp -r ./resources/* /app/resources
|
||||
sources:
|
||||
- cargo-sources.json
|
||||
- type: dir
|
||||
path: .
|
||||
- type: file
|
||||
# Update the link whenever mozjs-sys is updated
|
||||
url: https://github.com/servo/mozjs/releases/download/mozjs-sys-v0.115.13-2/libmozjs-x86_64-unknown-linux-gnu.tar.gz
|
||||
sha256: 1df591ce943a5294cf709a3850a9ed19b6e809d582fabc9dc094f109ef576e55
|
||||
only-arches:
|
||||
- x86_64
|
||||
|
||||
|
||||
@@ -3,45 +3,44 @@ use std::ffi::c_void;
|
||||
use std::rc::Rc;
|
||||
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
||||
|
||||
use base::id::{PipelineId, TopLevelBrowsingContextId};
|
||||
use base::{Epoch, WebRenderEpochToU16};
|
||||
use compositing_traits::{
|
||||
CompositionPipeline, CompositorMsg, CompositorProxy, CompositorReceiver, ConstellationMsg,
|
||||
ForwardedToCompositorMsg, SendableFrameTree,
|
||||
};
|
||||
use crossbeam_channel::Sender;
|
||||
use embedder_traits::Cursor;
|
||||
use euclid::{Point2D, Scale, Transform3D, Vector2D};
|
||||
use gleam::gl;
|
||||
use ipc_channel::ipc;
|
||||
use log::{debug, error, trace, warn};
|
||||
use servo::base::id::{PipelineId, TopLevelBrowsingContextId};
|
||||
use servo::base::{Epoch, WebRenderEpochToU16};
|
||||
use servo::embedder_traits::Cursor;
|
||||
use servo::euclid::{Point2D, Scale, Transform3D, Vector2D};
|
||||
use servo::profile_traits::time::{self as profile_time, profile, ProfilerCategory};
|
||||
use servo::profile_traits::{mem, time};
|
||||
use servo::script_traits::CompositorEvent::{
|
||||
MouseButtonEvent, MouseMoveEvent, TouchEvent, WheelEvent,
|
||||
};
|
||||
use servo::script_traits::{
|
||||
use profile_traits::time::{self as profile_time, profile, ProfilerCategory};
|
||||
use profile_traits::{mem, time};
|
||||
use script_traits::CompositorEvent::{MouseButtonEvent, MouseMoveEvent, TouchEvent, WheelEvent};
|
||||
use script_traits::{
|
||||
AnimationState, AnimationTickType, ConstellationControlMsg, MouseButton, MouseEventType,
|
||||
ScrollState, TouchEventType, TouchId, WheelDelta, WindowSizeData, WindowSizeType,
|
||||
};
|
||||
use servo::servo_geometry::DeviceIndependentPixel;
|
||||
use servo::style_traits::{CSSPixel, DevicePixel, PinchZoomFactor};
|
||||
use servo::webrender_api::units::{
|
||||
use servo_geometry::DeviceIndependentPixel;
|
||||
use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor};
|
||||
use webrender::{RenderApi, Transaction};
|
||||
use webrender_api::units::{
|
||||
DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePoint, LayoutPoint, LayoutRect, LayoutSize,
|
||||
LayoutVector2D, WorldPoint,
|
||||
};
|
||||
use servo::webrender_api::{
|
||||
use webrender_api::{
|
||||
BuiltDisplayList, DirtyRect, DisplayListPayload, DocumentId, Epoch as WebRenderEpoch,
|
||||
ExternalScrollId, FontInstanceOptions, HitTestFlags, PipelineId as WebRenderPipelineId,
|
||||
PropertyBinding, ReferenceFrameKind, RenderReasons, SampledScrollOffset, ScrollLocation,
|
||||
SpaceAndClipInfo, SpatialId, SpatialTreeItemKey, TransformStyle,
|
||||
};
|
||||
use servo::webrender_traits::display_list::{HitTestInfo, ScrollTree};
|
||||
use servo::webrender_traits::{
|
||||
use webrender_traits::display_list::{HitTestInfo, ScrollTree};
|
||||
use webrender_traits::{
|
||||
CanvasToCompositorMsg, CompositorHitTestResult, FontToCompositorMsg, ImageUpdate,
|
||||
NetToCompositorMsg, RenderingContext, ScriptToCompositorMsg, SerializedImageUpdate,
|
||||
UntrustedNodeAddress,
|
||||
};
|
||||
use webrender::{RenderApi, Transaction};
|
||||
|
||||
use crate::touch::{TouchAction, TouchHandler};
|
||||
use crate::webview::WebView;
|
||||
@@ -68,7 +67,7 @@ pub struct InitialCompositorState {
|
||||
/// Servo's rendering context
|
||||
pub rendering_context: RenderingContext,
|
||||
/// Webrender GL handle
|
||||
pub webrender_gl: Rc<dyn servo::gl::Gl>,
|
||||
pub webrender_gl: Rc<dyn gl::Gl>,
|
||||
/// WebXR registry
|
||||
pub webxr_main_thread: webxr::MainThreadRegistry,
|
||||
}
|
||||
@@ -168,7 +167,7 @@ pub struct IOCompositor {
|
||||
rendering_context: RenderingContext,
|
||||
|
||||
/// The GL bindings for webrender
|
||||
webrender_gl: Rc<dyn servo::gl::Gl>,
|
||||
webrender_gl: Rc<dyn gl::Gl>,
|
||||
|
||||
/// Some XR devices want to run on the main thread.
|
||||
pub webxr_main_thread: webxr::MainThreadRegistry,
|
||||
@@ -1924,7 +1923,7 @@ impl IOCompositor {
|
||||
.map(|info| info.framebuffer_object)
|
||||
.unwrap_or(0);
|
||||
self.webrender_gl
|
||||
.bind_framebuffer(servo::gl::FRAMEBUFFER, framebuffer_object);
|
||||
.bind_framebuffer(gl::FRAMEBUFFER, framebuffer_object);
|
||||
self.assert_gl_framebuffer_complete();
|
||||
|
||||
profile(
|
||||
@@ -2026,7 +2025,7 @@ impl IOCompositor {
|
||||
self.assert_gl_framebuffer_complete();
|
||||
|
||||
// Set the viewport background based on prefs.
|
||||
let color = servo::config::pref!(shell.background_color.rgba);
|
||||
let color = servo_config::pref!(shell.background_color.rgba);
|
||||
gl.clear_color(
|
||||
color[0] as f32,
|
||||
color[1] as f32,
|
||||
@@ -2051,9 +2050,9 @@ impl IOCompositor {
|
||||
rect.size().width,
|
||||
rect.size().height,
|
||||
);
|
||||
gl.enable(servo::gl::SCISSOR_TEST);
|
||||
gl.clear(servo::gl::COLOR_BUFFER_BIT);
|
||||
gl.disable(servo::gl::SCISSOR_TEST);
|
||||
gl.enable(gl::SCISSOR_TEST);
|
||||
gl.clear(gl::COLOR_BUFFER_BIT);
|
||||
gl.disable(gl::SCISSOR_TEST);
|
||||
}
|
||||
|
||||
self.assert_gl_framebuffer_complete();
|
||||
@@ -2061,7 +2060,7 @@ impl IOCompositor {
|
||||
|
||||
#[track_caller]
|
||||
fn assert_no_gl_error(&self) {
|
||||
debug_assert_eq!(self.webrender_gl.get_error(), servo::gl::NO_ERROR);
|
||||
debug_assert_eq!(self.webrender_gl.get_error(), gl::NO_ERROR);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
@@ -2069,10 +2068,9 @@ impl IOCompositor {
|
||||
debug_assert_eq!(
|
||||
(
|
||||
self.webrender_gl.get_error(),
|
||||
self.webrender_gl
|
||||
.check_frame_buffer_status(servo::gl::FRAMEBUFFER)
|
||||
self.webrender_gl.check_frame_buffer_status(gl::FRAMEBUFFER)
|
||||
),
|
||||
(servo::gl::NO_ERROR, servo::gl::FRAMEBUFFER_COMPLETE)
|
||||
(gl::NO_ERROR, gl::FRAMEBUFFER_COMPLETE)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
use servo::{
|
||||
config::opts::{default_opts, set_options, Opts},
|
||||
embedder_traits::resources::{self, Resource, ResourceReaderMethods},
|
||||
};
|
||||
use embedder_traits::resources::{self, Resource, ResourceReaderMethods};
|
||||
use servo_config::opts::{default_opts, set_options, Opts};
|
||||
|
||||
/// Configuration of Verso instance.
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -32,21 +30,6 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Returns the path to the resources directory.
|
||||
pub fn resources_dir_path() -> Option<std::path::PathBuf> {
|
||||
#[cfg(feature = "packager")]
|
||||
let root_dir = {
|
||||
use cargo_packager_resource_resolver::{current_format, resources_dir};
|
||||
current_format().and_then(|format| resources_dir(format))
|
||||
};
|
||||
#[cfg(not(feature = "packager"))]
|
||||
let root_dir = std::env::current_dir();
|
||||
|
||||
root_dir.ok().map(|dir| dir.join("resources"))
|
||||
}
|
||||
}
|
||||
|
||||
struct ResourceReader(PathBuf);
|
||||
|
||||
impl ResourceReaderMethods for ResourceReader {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use keyboard_types::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers};
|
||||
use log::info;
|
||||
use servo::keyboard_types::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers};
|
||||
use winit::event::{ElementState, KeyEvent};
|
||||
use winit::keyboard::{Key as LogicalKey, KeyCode, ModifiersState, NamedKey, PhysicalKey};
|
||||
|
||||
|
||||
@@ -67,7 +67,12 @@ fn resources_dir_path() -> Option<std::path::PathBuf> {
|
||||
use cargo_packager_resource_resolver::{current_format, resources_dir};
|
||||
current_format().and_then(|format| resources_dir(format))
|
||||
};
|
||||
#[cfg(not(feature = "packager"))]
|
||||
#[cfg(feature = "flatpak")]
|
||||
let root_dir = {
|
||||
use std::str::FromStr;
|
||||
std::path::PathBuf::from_str("/app")
|
||||
};
|
||||
#[cfg(not(any(feature = "packager", feature = "flatpak")))]
|
||||
let root_dir = std::env::current_dir();
|
||||
|
||||
root_dir.ok().map(|dir| dir.join("resources"))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use euclid::{Point2D, Scale, Vector2D};
|
||||
use log::warn;
|
||||
use servo::euclid::{Point2D, Scale, Vector2D};
|
||||
use servo::script_traits::{EventResult, TouchId};
|
||||
use servo::style_traits::DevicePixel;
|
||||
use script_traits::{EventResult, TouchId};
|
||||
use webrender_api::units::DevicePixel;
|
||||
|
||||
use self::TouchState::*;
|
||||
|
||||
|
||||
60
src/verso.rs
60
src/verso.rs
@@ -5,40 +5,38 @@ use std::{
|
||||
};
|
||||
|
||||
use arboard::Clipboard;
|
||||
use bluetooth::BluetoothThreadFactory;
|
||||
use bluetooth_traits::BluetoothRequest;
|
||||
use canvas::{
|
||||
canvas_paint_thread::{self, CanvasPaintThread},
|
||||
WebGLComm,
|
||||
};
|
||||
use compositing_traits::{
|
||||
CompositorMsg, CompositorProxy, CompositorReceiver, ConstellationMsg, ForwardedToCompositorMsg,
|
||||
};
|
||||
use constellation::{Constellation, FromCompositorLogger, InitialConstellationState};
|
||||
use crossbeam_channel::{unbounded, Sender};
|
||||
use devtools;
|
||||
use embedder_traits::{EmbedderProxy, EmbedderReceiver, EventLoopWaker};
|
||||
use euclid::Scale;
|
||||
use fonts::FontCacheThread;
|
||||
use gleam::gl;
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use layout_thread_2020;
|
||||
use log::{Log, Metadata, Record};
|
||||
use servo::{
|
||||
bluetooth::BluetoothThreadFactory,
|
||||
bluetooth_traits::BluetoothRequest,
|
||||
canvas::{
|
||||
canvas_paint_thread::{self, CanvasPaintThread},
|
||||
WebGLComm,
|
||||
},
|
||||
config::{opts, pref},
|
||||
constellation::{Constellation, FromCompositorLogger, InitialConstellationState},
|
||||
devtools,
|
||||
embedder_traits::{EmbedderProxy, EmbedderReceiver, EventLoopWaker},
|
||||
euclid::Scale,
|
||||
fonts::FontCacheThread,
|
||||
gl,
|
||||
ipc_channel::ipc::{self, IpcSender},
|
||||
layout_thread_2020,
|
||||
media::{GlApi, GlContext, NativeDisplay, WindowGLContext},
|
||||
net::resource_thread,
|
||||
profile,
|
||||
script::{self, JSEngineSetup},
|
||||
script_traits::WindowSizeData,
|
||||
style,
|
||||
url::ServoUrl,
|
||||
webgpu,
|
||||
webrender_api::*,
|
||||
webrender_traits::*,
|
||||
};
|
||||
use media::{GlApi, GlContext, NativeDisplay, WindowGLContext};
|
||||
use net::resource_thread;
|
||||
use profile;
|
||||
use script::{self, JSEngineSetup};
|
||||
use script_traits::WindowSizeData;
|
||||
use servo_config::{opts, pref};
|
||||
use servo_url::ServoUrl;
|
||||
use style;
|
||||
use surfman::GLApi;
|
||||
use webgpu;
|
||||
use webrender::{create_webrender_instance, ShaderPrecacheFlags, WebRenderOptions};
|
||||
use webrender_api::*;
|
||||
use webrender_traits::*;
|
||||
use winit::{
|
||||
event::{Event, StartCause},
|
||||
event_loop::EventLoopProxy,
|
||||
@@ -61,7 +59,8 @@ pub struct Verso {
|
||||
/// and deinitialization of the JS Engine. Multiprocess Servo instances have their
|
||||
/// own instance that exists in the content process instead.
|
||||
_js_engine_setup: Option<JSEngineSetup>,
|
||||
clipboard: Clipboard,
|
||||
/// FIXME: It's None on wayland in Flatpak. Find a way to support this.
|
||||
clipboard: Option<Clipboard>,
|
||||
resource_dir: PathBuf,
|
||||
}
|
||||
|
||||
@@ -363,8 +362,7 @@ impl Verso {
|
||||
constellation_sender,
|
||||
embedder_receiver,
|
||||
_js_engine_setup: js_engine_setup,
|
||||
clipboard: Clipboard::new()
|
||||
.expect("Clipboard isn't supported in this platform or desktop environment."),
|
||||
clipboard: Clipboard::new().ok(),
|
||||
resource_dir,
|
||||
};
|
||||
|
||||
@@ -435,7 +433,7 @@ impl Verso {
|
||||
top_level_browsing_context,
|
||||
msg,
|
||||
&self.constellation_sender,
|
||||
&mut self.clipboard,
|
||||
self.clipboard.as_mut(),
|
||||
);
|
||||
}
|
||||
ShutdownState::FinishedShuttingDown => {
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
use arboard::Clipboard;
|
||||
use base::id::{PipelineId, PipelineNamespace, PipelineNamespaceId, WebViewId};
|
||||
use compositing_traits::ConstellationMsg;
|
||||
use crossbeam_channel::Sender;
|
||||
use servo::{
|
||||
base::id::{PipelineId, PipelineNamespace, PipelineNamespaceId, WebViewId},
|
||||
embedder_traits::{CompositorEventVariant, EmbedderMsg, PromptDefinition},
|
||||
script_traits::TraversalDirection,
|
||||
url::ServoUrl,
|
||||
webrender_api::units::DeviceIntRect,
|
||||
TopLevelBrowsingContextId,
|
||||
};
|
||||
use embedder_traits::{CompositorEventVariant, EmbedderMsg, PromptDefinition};
|
||||
use script_traits::TraversalDirection;
|
||||
use servo_url::ServoUrl;
|
||||
use webrender_api::units::DeviceIntRect;
|
||||
|
||||
use crate::{verso::send_to_constellation, window::Window};
|
||||
|
||||
@@ -47,7 +44,7 @@ impl WebView {
|
||||
pub fn new_panel(rect: DeviceIntRect) -> Self {
|
||||
// Reserving a namespace to create TopLevelBrowsingContextId.
|
||||
PipelineNamespace::install(PipelineNamespaceId(0));
|
||||
let id = TopLevelBrowsingContextId::new();
|
||||
let id = WebViewId::new();
|
||||
Self {
|
||||
webview_id: id,
|
||||
pipeline_id: None,
|
||||
@@ -63,7 +60,7 @@ impl Window {
|
||||
webview_id: WebViewId,
|
||||
message: EmbedderMsg,
|
||||
sender: &Sender<ConstellationMsg>,
|
||||
clipboard: &mut Clipboard,
|
||||
clipboard: Option<&mut Clipboard>,
|
||||
) {
|
||||
log::trace!("Verso WebView {webview_id:?} is handling Embedder message: {message:?}",);
|
||||
match message {
|
||||
@@ -83,13 +80,17 @@ impl Window {
|
||||
send_to_constellation(sender, ConstellationMsg::AllowNavigationResponse(id, true));
|
||||
}
|
||||
EmbedderMsg::GetClipboardContents(sender) => {
|
||||
let contents = clipboard.get_text().unwrap_or_else(|e| {
|
||||
log::warn!(
|
||||
"Verso WebView {webview_id:?} failed to get clipboard content: {}",
|
||||
e
|
||||
);
|
||||
String::new()
|
||||
});
|
||||
let contents = clipboard
|
||||
.map(|c| {
|
||||
c.get_text().unwrap_or_else(|e| {
|
||||
log::warn!(
|
||||
"Verso WebView {webview_id:?} failed to get clipboard content: {}",
|
||||
e
|
||||
);
|
||||
String::new()
|
||||
})
|
||||
})
|
||||
.unwrap_or_default();
|
||||
if let Err(e) = sender.send(contents) {
|
||||
log::warn!(
|
||||
"Verso WebView {webview_id:?} failed to send clipboard content: {}",
|
||||
@@ -98,12 +99,14 @@ impl Window {
|
||||
}
|
||||
}
|
||||
EmbedderMsg::SetClipboardContents(text) => {
|
||||
if let Err(e) = clipboard.set_text(text) {
|
||||
log::warn!(
|
||||
"Verso WebView {webview_id:?} failed to set clipboard contents: {}",
|
||||
e
|
||||
);
|
||||
}
|
||||
clipboard.map(|c| {
|
||||
if let Err(e) = c.set_text(text) {
|
||||
log::warn!(
|
||||
"Verso WebView {webview_id:?} failed to set clipboard contents: {}",
|
||||
e
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
EmbedderMsg::EventDelivered(event) => {
|
||||
if let CompositorEventVariant::MouseButtonEvent = event {
|
||||
@@ -122,7 +125,7 @@ impl Window {
|
||||
panel_id: WebViewId,
|
||||
message: EmbedderMsg,
|
||||
sender: &Sender<ConstellationMsg>,
|
||||
clipboard: &mut Clipboard,
|
||||
clipboard: Option<&mut Clipboard>,
|
||||
) {
|
||||
log::trace!("Verso Panel {panel_id:?} is handling Embedder message: {message:?}",);
|
||||
match message {
|
||||
@@ -138,7 +141,7 @@ impl Window {
|
||||
self.window.request_redraw();
|
||||
// let demo_url = ServoUrl::parse("https://demo.versotile.org").unwrap();
|
||||
let demo_url = ServoUrl::parse("https://keyboard-test.space").unwrap();
|
||||
let demo_id = TopLevelBrowsingContextId::new();
|
||||
let demo_id = WebViewId::new();
|
||||
send_to_constellation(sender, ConstellationMsg::NewWebView(demo_url, demo_id));
|
||||
}
|
||||
EmbedderMsg::AllowNavigationRequest(id, _url) => {
|
||||
@@ -203,18 +206,24 @@ impl Window {
|
||||
}
|
||||
}
|
||||
EmbedderMsg::GetClipboardContents(sender) => {
|
||||
let contents = clipboard.get_text().unwrap_or_else(|e| {
|
||||
log::warn!("Verso Panel failed to get clipboard content: {}", e);
|
||||
String::new()
|
||||
});
|
||||
let contents = clipboard
|
||||
.map(|c| {
|
||||
c.get_text().unwrap_or_else(|e| {
|
||||
log::warn!("Verso Panel failed to get clipboard content: {}", e);
|
||||
String::new()
|
||||
})
|
||||
})
|
||||
.unwrap_or_default();
|
||||
if let Err(e) = sender.send(contents) {
|
||||
log::warn!("Verso Panel failed to send clipboard content: {}", e);
|
||||
}
|
||||
}
|
||||
EmbedderMsg::SetClipboardContents(text) => {
|
||||
if let Err(e) = clipboard.set_text(text) {
|
||||
log::warn!("Verso Panel failed to set clipboard contents: {}", e);
|
||||
}
|
||||
clipboard.map(|c| {
|
||||
if let Err(e) = c.set_text(text) {
|
||||
log::warn!("Verso Panel failed to set clipboard contents: {}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
e => {
|
||||
log::warn!("Verso Panel isn't supporting this message yet: {e:?}")
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
use std::cell::Cell;
|
||||
|
||||
use base::id::{PipelineId, WebViewId};
|
||||
use compositing_traits::ConstellationMsg;
|
||||
use crossbeam_channel::Sender;
|
||||
use embedder_traits::{Cursor, EmbedderMsg};
|
||||
use euclid::{Point2D, Size2D};
|
||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
||||
use servo::webrender_api::units::DeviceIntSize;
|
||||
use servo::{
|
||||
base::id::{PipelineId, WebViewId},
|
||||
embedder_traits::{Cursor, EmbedderMsg},
|
||||
euclid::{Point2D, Size2D},
|
||||
script_traits::{TouchEventType, WheelDelta, WheelMode},
|
||||
style_traits::DevicePixel,
|
||||
webrender_api::{
|
||||
units::{DeviceIntPoint, DeviceIntRect, DevicePoint, LayoutVector2D},
|
||||
ScrollLocation,
|
||||
},
|
||||
webrender_traits::RenderingContext,
|
||||
TopLevelBrowsingContextId,
|
||||
};
|
||||
use script_traits::{TouchEventType, WheelDelta, WheelMode};
|
||||
use surfman::{Connection, SurfaceType};
|
||||
use webrender_api::{
|
||||
units::{
|
||||
DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixel, DevicePoint, LayoutVector2D,
|
||||
},
|
||||
ScrollLocation,
|
||||
};
|
||||
use webrender_traits::RenderingContext;
|
||||
use winit::{
|
||||
dpi::PhysicalPosition,
|
||||
event::{ElementState, TouchPhase, WindowEvent},
|
||||
@@ -102,10 +99,10 @@ impl Window {
|
||||
compositor.on_mouse_window_move_event_class(cursor);
|
||||
}
|
||||
WindowEvent::MouseInput { state, button, .. } => {
|
||||
let button: servo::script_traits::MouseButton = match button {
|
||||
winit::event::MouseButton::Left => servo::script_traits::MouseButton::Left,
|
||||
winit::event::MouseButton::Right => servo::script_traits::MouseButton::Right,
|
||||
winit::event::MouseButton::Middle => servo::script_traits::MouseButton::Middle,
|
||||
let button: script_traits::MouseButton = match button {
|
||||
winit::event::MouseButton::Left => script_traits::MouseButton::Left,
|
||||
winit::event::MouseButton::Right => script_traits::MouseButton::Right,
|
||||
winit::event::MouseButton::Middle => script_traits::MouseButton::Middle,
|
||||
_ => {
|
||||
log::warn!(
|
||||
"Verso Window isn't supporting this mouse button yet: {button:?}"
|
||||
@@ -197,10 +194,10 @@ impl Window {
|
||||
/// Handle servo messages.
|
||||
pub fn handle_servo_message(
|
||||
&mut self,
|
||||
webview_id: Option<TopLevelBrowsingContextId>,
|
||||
webview_id: Option<WebViewId>,
|
||||
message: EmbedderMsg,
|
||||
sender: &Sender<ConstellationMsg>,
|
||||
clipboard: &mut Clipboard,
|
||||
clipboard: Option<&mut Clipboard>,
|
||||
) {
|
||||
match webview_id {
|
||||
// // Handle message in Verso Panel
|
||||
|
||||
1
third_party/WebIDL/README
vendored
Normal file
1
third_party/WebIDL/README
vendored
Normal file
@@ -0,0 +1 @@
|
||||
A WebIDL parser written in Python to be used in Mozilla.
|
||||
1
third_party/WebIDL/UPSTREAM
vendored
Normal file
1
third_party/WebIDL/UPSTREAM
vendored
Normal file
@@ -0,0 +1 @@
|
||||
http://dev.w3.org/cvsweb/~checkout~/2006/webapi/WebIDL/Overview.html?rev=1.409;content-type=text%2Fhtml%3b+charset=utf-8
|
||||
9529
third_party/WebIDL/WebIDL.py
vendored
Normal file
9529
third_party/WebIDL/WebIDL.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3
third_party/WebIDL/__init__.py
vendored
Normal file
3
third_party/WebIDL/__init__.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
__version__ = '1.0'
|
||||
__all__ = ['WebIDL']
|
||||
|
||||
BIN
third_party/WebIDL/__pycache__/WebIDL.cpython-310.pyc
vendored
Normal file
BIN
third_party/WebIDL/__pycache__/WebIDL.cpython-310.pyc
vendored
Normal file
Binary file not shown.
10
third_party/WebIDL/abstract.patch
vendored
Normal file
10
third_party/WebIDL/abstract.patch
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
--- WebIDL.py
|
||||
+++ WebIDL.py
|
||||
@@ -1987,6 +1987,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
||||
or identifier == "RunConstructorInCallerCompartment"
|
||||
or identifier == "WantsEventListenerHooks"
|
||||
or identifier == "Serializable"
|
||||
+ or identifier == "Abstract"
|
||||
):
|
||||
# Known extended attributes that do not take values
|
||||
if not attr.noArguments():
|
||||
49
third_party/WebIDL/builtin-array.patch
vendored
Normal file
49
third_party/WebIDL/builtin-array.patch
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
--- WebIDL.py
|
||||
+++ WebIDL.py
|
||||
@@ -2549,6 +2549,17 @@ class IDLType(IDLObject):
|
||||
"object",
|
||||
# Funny stuff
|
||||
"interface",
|
||||
+ "int8array",
|
||||
+ "uint8array",
|
||||
+ "int16array",
|
||||
+ "uint16array",
|
||||
+ "int32array",
|
||||
+ "uint32array",
|
||||
+ "float32array",
|
||||
+ "float64array",
|
||||
+ "arrayBuffer",
|
||||
+ "arrayBufferView",
|
||||
+ "uint8clampedarray",
|
||||
"dictionary",
|
||||
"enum",
|
||||
"callback",
|
||||
@@ -3842,17 +3853,17 @@ class IDLBuiltinType(IDLType):
|
||||
Types.utf8string: IDLType.Tags.utf8string,
|
||||
Types.jsstring: IDLType.Tags.jsstring,
|
||||
Types.object: IDLType.Tags.object,
|
||||
- Types.ArrayBuffer: IDLType.Tags.interface,
|
||||
- Types.ArrayBufferView: IDLType.Tags.interface,
|
||||
- Types.Int8Array: IDLType.Tags.interface,
|
||||
- Types.Uint8Array: IDLType.Tags.interface,
|
||||
- Types.Uint8ClampedArray: IDLType.Tags.interface,
|
||||
- Types.Int16Array: IDLType.Tags.interface,
|
||||
- Types.Uint16Array: IDLType.Tags.interface,
|
||||
- Types.Int32Array: IDLType.Tags.interface,
|
||||
- Types.Uint32Array: IDLType.Tags.interface,
|
||||
- Types.Float32Array: IDLType.Tags.interface,
|
||||
- Types.Float64Array: IDLType.Tags.interface,
|
||||
+ Types.ArrayBuffer: IDLType.Tags.arrayBuffer,
|
||||
+ Types.ArrayBufferView: IDLType.Tags.arrayBufferView,
|
||||
+ Types.Int8Array: IDLType.Tags.int8array,
|
||||
+ Types.Uint8Array: IDLType.Tags.uint8array,
|
||||
+ Types.Uint8ClampedArray: IDLType.Tags.uint8clampedarray,
|
||||
+ Types.Int16Array: IDLType.Tags.int16array,
|
||||
+ Types.Uint16Array: IDLType.Tags.uint16array,
|
||||
+ Types.Int32Array: IDLType.Tags.int32array,
|
||||
+ Types.Uint32Array: IDLType.Tags.uint32array,
|
||||
+ Types.Float32Array: IDLType.Tags.float32array,
|
||||
+ Types.Float64Array: IDLType.Tags.float64array,
|
||||
Types.ReadableStream: IDLType.Tags.interface,
|
||||
}
|
||||
|
||||
20
third_party/WebIDL/callback-location.patch
vendored
Normal file
20
third_party/WebIDL/callback-location.patch
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
--- WebIDL.py
|
||||
+++ WebIDL.py
|
||||
@@ -2283,7 +2283,7 @@ class IDLUnresolvedType(IDLType):
|
||||
return typedefType.complete(scope).withExtendedAttributes(self.extraTypeAttributes)
|
||||
elif obj.isCallback() and not obj.isInterface():
|
||||
assert self.name.name == obj.identifier.name
|
||||
- return IDLCallbackType(self.location, obj)
|
||||
+ return IDLCallbackType(obj.location, obj)
|
||||
|
||||
name = self.name.resolve(scope, None)
|
||||
return IDLWrapperType(self.location, obj)
|
||||
@@ -6854,7 +6854,7 @@ class Parser(Tokenizer):
|
||||
type = IDLTypedefType(self.getLocation(p, 1), obj.innerType,
|
||||
obj.identifier.name)
|
||||
elif obj.isCallback() and not obj.isInterface():
|
||||
- type = IDLCallbackType(self.getLocation(p, 1), obj)
|
||||
+ type = IDLCallbackType(obj.location, obj)
|
||||
else:
|
||||
type = IDLWrapperType(self.getLocation(p, 1), p[1])
|
||||
p[0] = self.handleNullable(type, p[2])
|
||||
10
third_party/WebIDL/debug.patch
vendored
Normal file
10
third_party/WebIDL/debug.patch
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
--- WebIDL.py
|
||||
+++ WebIDL.py
|
||||
@@ -8827,6 +8827,7 @@ class Parser(Tokenizer):
|
||||
module=self,
|
||||
outputdir=outputdir,
|
||||
errorlog=logger,
|
||||
+ debug=False,
|
||||
write_tables=False,
|
||||
# Pickling the grammar is a speedup in
|
||||
# some cases (older Python?) but a
|
||||
11
third_party/WebIDL/ext-attribute-no-value-error.patch
vendored
Normal file
11
third_party/WebIDL/ext-attribute-no-value-error.patch
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
--- WebIDL.py
|
||||
+++ WebIDL.py
|
||||
@@ -3490,7 +3490,7 @@ class IDLBuiltinType(IDLType):
|
||||
[self.location, attribute.location])
|
||||
assert not self.nullable()
|
||||
if not attribute.hasValue():
|
||||
- raise WebIDLError("[TreatNullAs] must take an identifier argument"
|
||||
+ raise WebIDLError("[TreatNullAs] must take an identifier argument",
|
||||
[attribute.location])
|
||||
value = attribute.value()
|
||||
if value != 'EmptyString':
|
||||
10
third_party/WebIDL/inline.patch
vendored
Normal file
10
third_party/WebIDL/inline.patch
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
--- WebIDL.py
|
||||
+++ WebIDL.py
|
||||
@@ -1988,6 +1988,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
||||
or identifier == "WantsEventListenerHooks"
|
||||
or identifier == "Serializable"
|
||||
or identifier == "Abstract"
|
||||
+ or identifier == "Inline"
|
||||
):
|
||||
# Known extended attributes that do not take values
|
||||
if not attr.noArguments():
|
||||
72
third_party/WebIDL/like-as-iterable.patch
vendored
Normal file
72
third_party/WebIDL/like-as-iterable.patch
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
diff --git a/third_party/WebIDL/WebIDL.py b/third_party/WebIDL/WebIDL.py
|
||||
index 2366e3f702..e1d973f5fe 100644
|
||||
--- a/third_party/WebIDL/WebIDL.py
|
||||
+++ b/third_party/WebIDL/WebIDL.py
|
||||
@@ -9022,6 +9022,67 @@ class Parser(Tokenizer):
|
||||
itr_iface.asyncIterableInterface = iface
|
||||
self._productions.append(itr_iface)
|
||||
iterable.iteratorType = IDLWrapperType(iface.location, itr_iface)
|
||||
+ if not iterable:
|
||||
+ # We haven't run finish() on the interface yet, so we don't know
|
||||
+ # whether our interface is maplike/setlike/iterable or not. This
|
||||
+ # means we have to loop through the members to see if we have an
|
||||
+ # iterable member.
|
||||
+ for m in iface.members:
|
||||
+ if isinstance(m, IDLMaplikeOrSetlike):
|
||||
+ iterable = m
|
||||
+ break
|
||||
+ if iterable and (iterable.isSetlike() or iterable.isMaplike()):
|
||||
+
|
||||
+ def simpleExtendedAttr(str):
|
||||
+ return IDLExtendedAttribute(iface.location, (str,))
|
||||
+
|
||||
+ if isinstance(iterable, IDLAsyncIterable):
|
||||
+ nextReturnType = IDLPromiseType(
|
||||
+ iterable.location, BuiltinTypes[IDLBuiltinType.Types.any]
|
||||
+ )
|
||||
+ else:
|
||||
+ nextReturnType = BuiltinTypes[IDLBuiltinType.Types.object]
|
||||
+ nextMethod = IDLMethod(
|
||||
+ iterable.location,
|
||||
+ IDLUnresolvedIdentifier(iterable.location, "next"),
|
||||
+ nextReturnType,
|
||||
+ [],
|
||||
+ )
|
||||
+ nextMethod.addExtendedAttributes([simpleExtendedAttr("Throws")])
|
||||
+
|
||||
+ methods = [nextMethod]
|
||||
+
|
||||
+ if iterable.isSetlike():
|
||||
+ itr_suffix = "Setlike"
|
||||
+ else:
|
||||
+ itr_suffix = "Maplike"
|
||||
+ itr_ident = IDLUnresolvedIdentifier(
|
||||
+ iface.location, iface.identifier.name + itr_suffix
|
||||
+ )
|
||||
+ classNameOverride = iface.identifier.name + " " + itr_suffix
|
||||
+ itr_iface = IDLInterface(
|
||||
+ iface.location,
|
||||
+ self.globalScope(),
|
||||
+ itr_ident,
|
||||
+ None,
|
||||
+ methods,
|
||||
+ isKnownNonPartial=True,
|
||||
+ classNameOverride=classNameOverride,
|
||||
+ )
|
||||
+ itr_iface.addExtendedAttributes(
|
||||
+ [simpleExtendedAttr("LegacyNoInterfaceObject")]
|
||||
+ )
|
||||
+ # Make sure the exposure set for the iterator interface is the
|
||||
+ # same as the exposure set for the iterable interface, because
|
||||
+ # we're going to generate methods on the iterable that return
|
||||
+ # instances of the iterator.
|
||||
+ itr_iface._exposureGlobalNames = set(iface._exposureGlobalNames)
|
||||
+ # Always append generated iterable interfaces after the
|
||||
+ # interface they're a member of, otherwise nativeType generation
|
||||
+ # won't work correctly.
|
||||
+ itr_iface.iterableInterface = iface
|
||||
+ self._productions.append(itr_iface)
|
||||
+ iterable.iteratorType = IDLWrapperType(iface.location, itr_iface)
|
||||
|
||||
# Make sure we finish IDLIncludesStatements before we finish the
|
||||
# IDLInterfaces.
|
||||
162
third_party/WebIDL/readable-stream.patch
vendored
Normal file
162
third_party/WebIDL/readable-stream.patch
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
--- WebIDL.py
|
||||
+++ WebIDL.py
|
||||
@@ -2498,6 +2498,9 @@ class IDLType(IDLObject):
|
||||
def isRecord(self):
|
||||
return False
|
||||
|
||||
+ def isReadableStream(self):
|
||||
+ return False
|
||||
+
|
||||
def isArrayBuffer(self):
|
||||
return False
|
||||
|
||||
@@ -2526,7 +2529,7 @@ class IDLType(IDLObject):
|
||||
def isSpiderMonkeyInterface(self):
|
||||
"""Returns a boolean indicating whether this type is an 'interface'
|
||||
type that is implemented in SpiderMonkey."""
|
||||
- return self.isInterface() and self.isBufferSource()
|
||||
+ return self.isInterface() and (self.isBufferSource() or self.isReadableStream())
|
||||
|
||||
def isAny(self):
|
||||
return self.tag() == IDLType.Tags.any
|
||||
@@ -2743,6 +2746,9 @@ class IDLNullableType(IDLParametrizedType):
|
||||
def isRecord(self):
|
||||
return self.inner.isRecord()
|
||||
|
||||
+ def isReadableStream(self):
|
||||
+ return self.inner.isReadableStream()
|
||||
+
|
||||
def isArrayBuffer(self):
|
||||
return self.inner.isArrayBuffer()
|
||||
|
||||
@@ -3252,6 +3258,9 @@ class IDLTypedefType(IDLType):
|
||||
def isRecord(self):
|
||||
return self.inner.isRecord()
|
||||
|
||||
+ def isReadableStream(self):
|
||||
+ return self.inner.isReadableStream()
|
||||
+
|
||||
def isDictionary(self):
|
||||
return self.inner.isDictionary()
|
||||
|
||||
@@ -3597,6 +3606,7 @@ class IDLBuiltinType(IDLType):
|
||||
"Uint32Array",
|
||||
"Float32Array",
|
||||
"Float64Array",
|
||||
+ "ReadableStream",
|
||||
)
|
||||
|
||||
TagLookup = {
|
||||
@@ -3632,6 +3642,7 @@ class IDLBuiltinType(IDLType):
|
||||
Types.Uint32Array: IDLType.Tags.interface,
|
||||
Types.Float32Array: IDLType.Tags.interface,
|
||||
Types.Float64Array: IDLType.Tags.interface,
|
||||
+ Types.ReadableStream: IDLType.Tags.interface,
|
||||
}
|
||||
|
||||
PrettyNames = {
|
||||
@@ -3667,6 +3678,7 @@ class IDLBuiltinType(IDLType):
|
||||
Types.Uint32Array: "Uint32Array",
|
||||
Types.Float32Array: "Float32Array",
|
||||
Types.Float64Array: "Float64Array",
|
||||
+ Types.ReadableStream: "ReadableStream",
|
||||
}
|
||||
|
||||
def __init__(
|
||||
@@ -3830,11 +3842,19 @@ class IDLBuiltinType(IDLType):
|
||||
and self._typeTag <= IDLBuiltinType.Types.Float64Array
|
||||
)
|
||||
|
||||
+ def isReadableStream(self):
|
||||
+ return self._typeTag == IDLBuiltinType.Types.ReadableStream
|
||||
+
|
||||
def isInterface(self):
|
||||
# TypedArray things are interface types per the TypedArray spec,
|
||||
# but we handle them as builtins because SpiderMonkey implements
|
||||
# all of it internally.
|
||||
- return self.isArrayBuffer() or self.isArrayBufferView() or self.isTypedArray()
|
||||
+ return (
|
||||
+ self.isArrayBuffer()
|
||||
+ or self.isArrayBufferView()
|
||||
+ or self.isTypedArray()
|
||||
+ or self.isReadableStream()
|
||||
+ )
|
||||
|
||||
def isNonCallbackInterface(self):
|
||||
# All the interfaces we can be are non-callback
|
||||
@@ -3928,6 +3948,7 @@ class IDLBuiltinType(IDLType):
|
||||
# ArrayBuffer is distinguishable from everything
|
||||
# that's not an ArrayBuffer or a callback interface
|
||||
(self.isArrayBuffer() and not other.isArrayBuffer())
|
||||
+ or (self.isReadableStream() and not other.isReadableStream())
|
||||
or
|
||||
# ArrayBufferView is distinguishable from everything
|
||||
# that's not an ArrayBufferView or typed array.
|
||||
@@ -4134,6 +4155,11 @@ BuiltinTypes = {
|
||||
"Float64Array",
|
||||
IDLBuiltinType.Types.Float64Array,
|
||||
),
|
||||
+ IDLBuiltinType.Types.ReadableStream: IDLBuiltinType(
|
||||
+ BuiltinLocation("<builtin type>"),
|
||||
+ "ReadableStream",
|
||||
+ IDLBuiltinType.Types.ReadableStream,
|
||||
+ ),
|
||||
}
|
||||
|
||||
|
||||
@@ -6883,6 +6909,9 @@ class Tokenizer(object):
|
||||
def t_IDENTIFIER(self, t):
|
||||
r"[_-]?[A-Za-z][0-9A-Z_a-z-]*"
|
||||
t.type = self.keywords.get(t.value, "IDENTIFIER")
|
||||
+ # If Builtin readable streams are disabled, mark ReadableStream as an identifier.
|
||||
+ if t.type == "READABLESTREAM" and not self._use_builtin_readable_streams:
|
||||
+ t.type = "IDENTIFIER"
|
||||
return t
|
||||
|
||||
def t_STRING(self, t):
|
||||
@@ -6973,6 +7002,7 @@ class Tokenizer(object):
|
||||
"setlike": "SETLIKE",
|
||||
"iterable": "ITERABLE",
|
||||
"namespace": "NAMESPACE",
|
||||
+ "ReadableStream": "READABLESTREAM",
|
||||
"constructor": "CONSTRUCTOR",
|
||||
"symbol": "SYMBOL",
|
||||
"async": "ASYNC",
|
||||
@@ -6993,7 +7023,8 @@ class Tokenizer(object):
|
||||
],
|
||||
)
|
||||
|
||||
- def __init__(self, outputdir, lexer=None):
|
||||
+ def __init__(self, outputdir, lexer=None, use_builtin_readable_streams=True):
|
||||
+ self._use_builtin_readable_streams = use_builtin_readable_streams
|
||||
if lexer:
|
||||
self.lexer = lexer
|
||||
else:
|
||||
@@ -8482,6 +8513,7 @@ class Parser(Tokenizer):
|
||||
"""
|
||||
DistinguishableType : PrimitiveType Null
|
||||
| ARRAYBUFFER Null
|
||||
+ | READABLESTREAM Null
|
||||
| OBJECT Null
|
||||
| UNDEFINED Null
|
||||
"""
|
||||
@@ -8489,6 +8521,8 @@ class Parser(Tokenizer):
|
||||
type = BuiltinTypes[IDLBuiltinType.Types.object]
|
||||
elif p[1] == "ArrayBuffer":
|
||||
type = BuiltinTypes[IDLBuiltinType.Types.ArrayBuffer]
|
||||
+ elif p[1] == "ReadableStream":
|
||||
+ type = BuiltinTypes[IDLBuiltinType.Types.ReadableStream]
|
||||
elif p[1] == "undefined":
|
||||
type = BuiltinTypes[IDLBuiltinType.Types.undefined]
|
||||
else:
|
||||
@@ -8827,8 +8861,8 @@ class Parser(Tokenizer):
|
||||
[Location(self.lexer, p.lineno, p.lexpos, self._filename)],
|
||||
)
|
||||
|
||||
- def __init__(self, outputdir="", lexer=None):
|
||||
- Tokenizer.__init__(self, outputdir, lexer)
|
||||
+ def __init__(self, outputdir="", lexer=None, use_builtin_readable_stream=True):
|
||||
+ Tokenizer.__init__(self, outputdir, lexer, use_builtin_readable_stream)
|
||||
|
||||
logger = SqueakyCleanLogger()
|
||||
try:
|
||||
79
third_party/WebIDL/runtests.py
vendored
Normal file
79
third_party/WebIDL/runtests.py
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
import os, sys
|
||||
import glob
|
||||
import optparse
|
||||
import traceback
|
||||
import WebIDL
|
||||
|
||||
class TestHarness(object):
|
||||
def __init__(self, test, verbose):
|
||||
self.test = test
|
||||
self.verbose = verbose
|
||||
self.printed_intro = False
|
||||
|
||||
def start(self):
|
||||
if self.verbose:
|
||||
self.maybe_print_intro()
|
||||
|
||||
def finish(self):
|
||||
if self.verbose or self.printed_intro:
|
||||
print("Finished test %s" % self.test)
|
||||
|
||||
def maybe_print_intro(self):
|
||||
if not self.printed_intro:
|
||||
print("Starting test %s" % self.test)
|
||||
self.printed_intro = True
|
||||
|
||||
def test_pass(self, msg):
|
||||
if self.verbose:
|
||||
print("TEST-PASS | %s" % msg)
|
||||
|
||||
def test_fail(self, msg):
|
||||
self.maybe_print_intro()
|
||||
print("TEST-UNEXPECTED-FAIL | %s" % msg)
|
||||
|
||||
def ok(self, condition, msg):
|
||||
if condition:
|
||||
self.test_pass(msg)
|
||||
else:
|
||||
self.test_fail(msg)
|
||||
|
||||
def check(self, a, b, msg):
|
||||
if a == b:
|
||||
self.test_pass(msg)
|
||||
else:
|
||||
self.test_fail(msg)
|
||||
print("\tGot %s expected %s" % (a, b))
|
||||
|
||||
def run_tests(tests, verbose):
|
||||
testdir = os.path.join(os.path.dirname(__file__), 'tests')
|
||||
if not tests:
|
||||
tests = glob.iglob(os.path.join(testdir, "*.py"))
|
||||
sys.path.append(testdir)
|
||||
|
||||
for test in tests:
|
||||
(testpath, ext) = os.path.splitext(os.path.basename(test))
|
||||
_test = __import__(testpath, globals(), locals(), ['WebIDLTest'])
|
||||
|
||||
harness = TestHarness(test, verbose)
|
||||
harness.start()
|
||||
try:
|
||||
_test.WebIDLTest.__call__(WebIDL.Parser(), harness)
|
||||
except Exception as ex:
|
||||
print("TEST-UNEXPECTED-FAIL | Unhandled exception in test %s: %s" % (testpath, ex))
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
harness.finish()
|
||||
|
||||
if __name__ == '__main__':
|
||||
usage = """%prog [OPTIONS] [TESTS]
|
||||
Where TESTS are relative to the tests directory."""
|
||||
parser = optparse.OptionParser(usage=usage)
|
||||
parser.add_option('-q', '--quiet', action='store_false', dest='verbose', default=True,
|
||||
help="Don't print passing tests.")
|
||||
options, tests = parser.parse_args()
|
||||
|
||||
run_tests(tests, verbose=options.verbose)
|
||||
13
third_party/WebIDL/setup.py
vendored
Normal file
13
third_party/WebIDL/setup.py
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
try:
|
||||
from setuptools import setup
|
||||
except ImportError:
|
||||
from distutils.core import setup
|
||||
|
||||
setup(name = "WebIDL",
|
||||
description="A WebIDL parser written in Python to be used in Mozilla.",
|
||||
version = "1.0.0",
|
||||
packages = ['.'],
|
||||
classifiers = [
|
||||
'Programming Language :: Python :: 3',
|
||||
]
|
||||
)
|
||||
19
third_party/WebIDL/tests/test_any_null.py
vendored
Normal file
19
third_party/WebIDL/tests/test_any_null.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface DoubleNull {
|
||||
attribute any? foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
19
third_party/WebIDL/tests/test_argument_identifier_conflicts.py
vendored
Normal file
19
third_party/WebIDL/tests/test_argument_identifier_conflicts.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface ArgumentIdentifierConflict {
|
||||
undefined foo(boolean arg1, boolean arg1);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
22
third_party/WebIDL/tests/test_argument_keywords.py
vendored
Normal file
22
third_party/WebIDL/tests/test_argument_keywords.py
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo {
|
||||
undefined foo(object constructor);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 1, "Should have an interface")
|
||||
iface = results[0]
|
||||
harness.check(len(iface.members), 1, "Should have an operation")
|
||||
operation = iface.members[0]
|
||||
harness.check(len(operation.signatures()), 1, "Should have one signature")
|
||||
(retval, args) = operation.signatures()[0]
|
||||
harness.check(len(args), 1, "Should have an argument")
|
||||
harness.check(
|
||||
args[0].identifier.name,
|
||||
"constructor",
|
||||
"Should have an identifier named 'constructor'",
|
||||
)
|
||||
19
third_party/WebIDL/tests/test_argument_novoid.py
vendored
Normal file
19
third_party/WebIDL/tests/test_argument_novoid.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface VoidArgument1 {
|
||||
void foo(void arg2);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
95
third_party/WebIDL/tests/test_arraybuffer.py
vendored
Normal file
95
third_party/WebIDL/tests/test_arraybuffer.py
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestArrayBuffer {
|
||||
attribute ArrayBuffer bufferAttr;
|
||||
undefined bufferMethod(ArrayBuffer arg1, ArrayBuffer? arg2, sequence<ArrayBuffer> arg3);
|
||||
|
||||
attribute ArrayBufferView viewAttr;
|
||||
undefined viewMethod(ArrayBufferView arg1, ArrayBufferView? arg2, sequence<ArrayBufferView> arg3);
|
||||
|
||||
attribute Int8Array int8ArrayAttr;
|
||||
undefined int8ArrayMethod(Int8Array arg1, Int8Array? arg2, sequence<Int8Array> arg3);
|
||||
|
||||
attribute Uint8Array uint8ArrayAttr;
|
||||
undefined uint8ArrayMethod(Uint8Array arg1, Uint8Array? arg2, sequence<Uint8Array> arg3);
|
||||
|
||||
attribute Uint8ClampedArray uint8ClampedArrayAttr;
|
||||
undefined uint8ClampedArrayMethod(Uint8ClampedArray arg1, Uint8ClampedArray? arg2, sequence<Uint8ClampedArray> arg3);
|
||||
|
||||
attribute Int16Array int16ArrayAttr;
|
||||
undefined int16ArrayMethod(Int16Array arg1, Int16Array? arg2, sequence<Int16Array> arg3);
|
||||
|
||||
attribute Uint16Array uint16ArrayAttr;
|
||||
undefined uint16ArrayMethod(Uint16Array arg1, Uint16Array? arg2, sequence<Uint16Array> arg3);
|
||||
|
||||
attribute Int32Array int32ArrayAttr;
|
||||
undefined int32ArrayMethod(Int32Array arg1, Int32Array? arg2, sequence<Int32Array> arg3);
|
||||
|
||||
attribute Uint32Array uint32ArrayAttr;
|
||||
undefined uint32ArrayMethod(Uint32Array arg1, Uint32Array? arg2, sequence<Uint32Array> arg3);
|
||||
|
||||
attribute Float32Array float32ArrayAttr;
|
||||
undefined float32ArrayMethod(Float32Array arg1, Float32Array? arg2, sequence<Float32Array> arg3);
|
||||
|
||||
attribute Float64Array float64ArrayAttr;
|
||||
undefined float64ArrayMethod(Float64Array arg1, Float64Array? arg2, sequence<Float64Array> arg3);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
iface = results[0]
|
||||
|
||||
harness.ok(True, "TestArrayBuffer interface parsed without error")
|
||||
harness.check(len(iface.members), 22, "Interface should have twenty two members")
|
||||
|
||||
members = iface.members
|
||||
|
||||
def checkStuff(attr, method, t):
|
||||
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Expect an IDLAttribute")
|
||||
harness.ok(isinstance(method, WebIDL.IDLMethod), "Expect an IDLMethod")
|
||||
|
||||
harness.check(str(attr.type), t, "Expect an ArrayBuffer type")
|
||||
harness.ok(attr.type.isSpiderMonkeyInterface(), "Should test as a js interface")
|
||||
|
||||
(retType, arguments) = method.signatures()[0]
|
||||
harness.ok(retType.isUndefined(), "Should have an undefined return type")
|
||||
harness.check(len(arguments), 3, "Expect 3 arguments")
|
||||
|
||||
harness.check(str(arguments[0].type), t, "Expect an ArrayBuffer type")
|
||||
harness.ok(
|
||||
arguments[0].type.isSpiderMonkeyInterface(), "Should test as a js interface"
|
||||
)
|
||||
|
||||
harness.check(
|
||||
str(arguments[1].type), t + "OrNull", "Expect an ArrayBuffer type"
|
||||
)
|
||||
harness.ok(
|
||||
arguments[1].type.inner.isSpiderMonkeyInterface(),
|
||||
"Should test as a js interface",
|
||||
)
|
||||
|
||||
harness.check(
|
||||
str(arguments[2].type), t + "Sequence", "Expect an ArrayBuffer type"
|
||||
)
|
||||
harness.ok(
|
||||
arguments[2].type.inner.isSpiderMonkeyInterface(),
|
||||
"Should test as a js interface",
|
||||
)
|
||||
|
||||
checkStuff(members[0], members[1], "ArrayBuffer")
|
||||
checkStuff(members[2], members[3], "ArrayBufferView")
|
||||
checkStuff(members[4], members[5], "Int8Array")
|
||||
checkStuff(members[6], members[7], "Uint8Array")
|
||||
checkStuff(members[8], members[9], "Uint8ClampedArray")
|
||||
checkStuff(members[10], members[11], "Int16Array")
|
||||
checkStuff(members[12], members[13], "Uint16Array")
|
||||
checkStuff(members[14], members[15], "Int32Array")
|
||||
checkStuff(members[16], members[17], "Uint32Array")
|
||||
checkStuff(members[18], members[19], "Float32Array")
|
||||
checkStuff(members[20], members[21], "Float64Array")
|
||||
199
third_party/WebIDL/tests/test_attr.py
vendored
Normal file
199
third_party/WebIDL/tests/test_attr.py
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
testData = [
|
||||
("::TestAttr%s::b", "b", "Byte%s", False),
|
||||
("::TestAttr%s::rb", "rb", "Byte%s", True),
|
||||
("::TestAttr%s::o", "o", "Octet%s", False),
|
||||
("::TestAttr%s::ro", "ro", "Octet%s", True),
|
||||
("::TestAttr%s::s", "s", "Short%s", False),
|
||||
("::TestAttr%s::rs", "rs", "Short%s", True),
|
||||
("::TestAttr%s::us", "us", "UnsignedShort%s", False),
|
||||
("::TestAttr%s::rus", "rus", "UnsignedShort%s", True),
|
||||
("::TestAttr%s::l", "l", "Long%s", False),
|
||||
("::TestAttr%s::rl", "rl", "Long%s", True),
|
||||
("::TestAttr%s::ul", "ul", "UnsignedLong%s", False),
|
||||
("::TestAttr%s::rul", "rul", "UnsignedLong%s", True),
|
||||
("::TestAttr%s::ll", "ll", "LongLong%s", False),
|
||||
("::TestAttr%s::rll", "rll", "LongLong%s", True),
|
||||
("::TestAttr%s::ull", "ull", "UnsignedLongLong%s", False),
|
||||
("::TestAttr%s::rull", "rull", "UnsignedLongLong%s", True),
|
||||
("::TestAttr%s::str", "str", "String%s", False),
|
||||
("::TestAttr%s::rstr", "rstr", "String%s", True),
|
||||
("::TestAttr%s::obj", "obj", "Object%s", False),
|
||||
("::TestAttr%s::robj", "robj", "Object%s", True),
|
||||
("::TestAttr%s::object", "object", "Object%s", False),
|
||||
("::TestAttr%s::f", "f", "Float%s", False),
|
||||
("::TestAttr%s::rf", "rf", "Float%s", True),
|
||||
]
|
||||
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestAttr {
|
||||
attribute byte b;
|
||||
readonly attribute byte rb;
|
||||
attribute octet o;
|
||||
readonly attribute octet ro;
|
||||
attribute short s;
|
||||
readonly attribute short rs;
|
||||
attribute unsigned short us;
|
||||
readonly attribute unsigned short rus;
|
||||
attribute long l;
|
||||
readonly attribute long rl;
|
||||
attribute unsigned long ul;
|
||||
readonly attribute unsigned long rul;
|
||||
attribute long long ll;
|
||||
readonly attribute long long rll;
|
||||
attribute unsigned long long ull;
|
||||
readonly attribute unsigned long long rull;
|
||||
attribute DOMString str;
|
||||
readonly attribute DOMString rstr;
|
||||
attribute object obj;
|
||||
readonly attribute object robj;
|
||||
attribute object _object;
|
||||
attribute float f;
|
||||
readonly attribute float rf;
|
||||
};
|
||||
|
||||
interface TestAttrNullable {
|
||||
attribute byte? b;
|
||||
readonly attribute byte? rb;
|
||||
attribute octet? o;
|
||||
readonly attribute octet? ro;
|
||||
attribute short? s;
|
||||
readonly attribute short? rs;
|
||||
attribute unsigned short? us;
|
||||
readonly attribute unsigned short? rus;
|
||||
attribute long? l;
|
||||
readonly attribute long? rl;
|
||||
attribute unsigned long? ul;
|
||||
readonly attribute unsigned long? rul;
|
||||
attribute long long? ll;
|
||||
readonly attribute long long? rll;
|
||||
attribute unsigned long long? ull;
|
||||
readonly attribute unsigned long long? rull;
|
||||
attribute DOMString? str;
|
||||
readonly attribute DOMString? rstr;
|
||||
attribute object? obj;
|
||||
readonly attribute object? robj;
|
||||
attribute object? _object;
|
||||
attribute float? f;
|
||||
readonly attribute float? rf;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
def checkAttr(attr, QName, name, type, readonly):
|
||||
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
|
||||
harness.ok(attr.isAttr(), "Attr is an Attr")
|
||||
harness.ok(not attr.isMethod(), "Attr is not an method")
|
||||
harness.ok(not attr.isConst(), "Attr is not a const")
|
||||
harness.check(attr.identifier.QName(), QName, "Attr has the right QName")
|
||||
harness.check(attr.identifier.name, name, "Attr has the right name")
|
||||
harness.check(str(attr.type), type, "Attr has the right type")
|
||||
harness.check(attr.readonly, readonly, "Attr's readonly state is correct")
|
||||
|
||||
harness.ok(True, "TestAttr interface parsed without error.")
|
||||
harness.check(len(results), 2, "Should be two productions.")
|
||||
iface = results[0]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
harness.check(
|
||||
iface.identifier.QName(), "::TestAttr", "Interface has the right QName"
|
||||
)
|
||||
harness.check(iface.identifier.name, "TestAttr", "Interface has the right name")
|
||||
harness.check(
|
||||
len(iface.members), len(testData), "Expect %s members" % len(testData)
|
||||
)
|
||||
|
||||
attrs = iface.members
|
||||
|
||||
for i in range(len(attrs)):
|
||||
data = testData[i]
|
||||
attr = attrs[i]
|
||||
(QName, name, type, readonly) = data
|
||||
checkAttr(attr, QName % "", name, type % "", readonly)
|
||||
|
||||
iface = results[1]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
harness.check(
|
||||
iface.identifier.QName(), "::TestAttrNullable", "Interface has the right QName"
|
||||
)
|
||||
harness.check(
|
||||
iface.identifier.name, "TestAttrNullable", "Interface has the right name"
|
||||
)
|
||||
harness.check(
|
||||
len(iface.members), len(testData), "Expect %s members" % len(testData)
|
||||
)
|
||||
|
||||
attrs = iface.members
|
||||
|
||||
for i in range(len(attrs)):
|
||||
data = testData[i]
|
||||
attr = attrs[i]
|
||||
(QName, name, type, readonly) = data
|
||||
checkAttr(attr, QName % "Nullable", name, type % "OrNull", readonly)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[SetterThrows] readonly attribute boolean foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow [SetterThrows] on readonly attributes")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[Throw] readonly attribute boolean foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should spell [Throws] correctly")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[SameObject] readonly attribute boolean foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "Should not allow [SameObject] on attributes not of interface type"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[SameObject] readonly attribute A foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(not threw, "Should allow [SameObject] on attributes of interface type")
|
||||
80
third_party/WebIDL/tests/test_attr_sequence_type.py
vendored
Normal file
80
third_party/WebIDL/tests/test_attr_sequence_type.py
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface AttrSequenceType {
|
||||
attribute sequence<object> foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Attribute type must not be a sequence type")
|
||||
|
||||
parser.reset()
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface AttrUnionWithSequenceType {
|
||||
attribute (sequence<object> or DOMString) foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Attribute type must not be a union with a sequence member type")
|
||||
|
||||
parser.reset()
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface AttrNullableUnionWithSequenceType {
|
||||
attribute (sequence<object>? or DOMString) foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Attribute type must not be a union with a nullable sequence " "member type",
|
||||
)
|
||||
|
||||
parser.reset()
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"\n"
|
||||
" interface AttrUnionWithUnionWithSequenceType {\n"
|
||||
" attribute ((sequence<object> or DOMString) or "
|
||||
"AttrUnionWithUnionWithSequenceType) foo;\n"
|
||||
" };\n"
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Attribute type must not be a union type with a union member "
|
||||
"type that has a sequence member type",
|
||||
)
|
||||
570
third_party/WebIDL/tests/test_attributes_on_types.py
vendored
Normal file
570
third_party/WebIDL/tests/test_attributes_on_types.py
vendored
Normal file
@@ -0,0 +1,570 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
# Basic functionality
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef [EnforceRange] long Foo;
|
||||
typedef [Clamp] long Bar;
|
||||
typedef [LegacyNullToEmptyString] DOMString Baz;
|
||||
dictionary A {
|
||||
required [EnforceRange] long a;
|
||||
required [Clamp] long b;
|
||||
[ChromeOnly, EnforceRange] long c;
|
||||
Foo d;
|
||||
};
|
||||
interface B {
|
||||
attribute Foo typedefFoo;
|
||||
attribute [EnforceRange] long foo;
|
||||
attribute [Clamp] long bar;
|
||||
attribute [LegacyNullToEmptyString] DOMString baz;
|
||||
undefined method([EnforceRange] long foo, [Clamp] long bar,
|
||||
[LegacyNullToEmptyString] DOMString baz);
|
||||
undefined method2(optional [EnforceRange] long foo, optional [Clamp] long bar,
|
||||
optional [LegacyNullToEmptyString] DOMString baz);
|
||||
undefined method3(optional [LegacyNullToEmptyString] UTF8String foo = "");
|
||||
};
|
||||
interface C {
|
||||
attribute [EnforceRange] long? foo;
|
||||
attribute [Clamp] long? bar;
|
||||
undefined method([EnforceRange] long? foo, [Clamp] long? bar);
|
||||
undefined method2(optional [EnforceRange] long? foo, optional [Clamp] long? bar);
|
||||
};
|
||||
interface Setlike {
|
||||
setlike<[Clamp] long>;
|
||||
};
|
||||
interface Maplike {
|
||||
maplike<[Clamp] long, [EnforceRange] long>;
|
||||
};
|
||||
interface Iterable {
|
||||
iterable<[Clamp] long, [EnforceRange] long>;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(not threw, "Should not have thrown on parsing normal")
|
||||
if not threw:
|
||||
harness.check(
|
||||
results[0].innerType.hasEnforceRange(), True, "Foo is [EnforceRange]"
|
||||
)
|
||||
harness.check(results[1].innerType.hasClamp(), True, "Bar is [Clamp]")
|
||||
harness.check(
|
||||
results[2].innerType.legacyNullToEmptyString,
|
||||
True,
|
||||
"Baz is [LegacyNullToEmptyString]",
|
||||
)
|
||||
A = results[3]
|
||||
harness.check(
|
||||
A.members[0].type.hasEnforceRange(), True, "A.a is [EnforceRange]"
|
||||
)
|
||||
harness.check(A.members[1].type.hasClamp(), True, "A.b is [Clamp]")
|
||||
harness.check(
|
||||
A.members[2].type.hasEnforceRange(), True, "A.c is [EnforceRange]"
|
||||
)
|
||||
harness.check(
|
||||
A.members[3].type.hasEnforceRange(), True, "A.d is [EnforceRange]"
|
||||
)
|
||||
B = results[4]
|
||||
harness.check(
|
||||
B.members[0].type.hasEnforceRange(), True, "B.typedefFoo is [EnforceRange]"
|
||||
)
|
||||
harness.check(
|
||||
B.members[1].type.hasEnforceRange(), True, "B.foo is [EnforceRange]"
|
||||
)
|
||||
harness.check(B.members[2].type.hasClamp(), True, "B.bar is [Clamp]")
|
||||
harness.check(
|
||||
B.members[3].type.legacyNullToEmptyString,
|
||||
True,
|
||||
"B.baz is [LegacyNullToEmptyString]",
|
||||
)
|
||||
method = B.members[4].signatures()[0][1]
|
||||
harness.check(
|
||||
method[0].type.hasEnforceRange(),
|
||||
True,
|
||||
"foo argument of method is [EnforceRange]",
|
||||
)
|
||||
harness.check(
|
||||
method[1].type.hasClamp(), True, "bar argument of method is [Clamp]"
|
||||
)
|
||||
harness.check(
|
||||
method[2].type.legacyNullToEmptyString,
|
||||
True,
|
||||
"baz argument of method is [LegacyNullToEmptyString]",
|
||||
)
|
||||
method2 = B.members[5].signatures()[0][1]
|
||||
harness.check(
|
||||
method2[0].type.hasEnforceRange(),
|
||||
True,
|
||||
"foo argument of method2 is [EnforceRange]",
|
||||
)
|
||||
harness.check(
|
||||
method2[1].type.hasClamp(), True, "bar argument of method2 is [Clamp]"
|
||||
)
|
||||
harness.check(
|
||||
method2[2].type.legacyNullToEmptyString,
|
||||
True,
|
||||
"baz argument of method2 is [LegacyNullToEmptyString]",
|
||||
)
|
||||
|
||||
method3 = B.members[6].signatures()[0][1]
|
||||
harness.check(
|
||||
method3[0].type.legacyNullToEmptyString,
|
||||
True,
|
||||
"bar argument of method2 is [LegacyNullToEmptyString]",
|
||||
)
|
||||
harness.check(
|
||||
method3[0].defaultValue.type.isUTF8String(),
|
||||
True,
|
||||
"default value of bar argument of method2 is correctly coerced to UTF8String",
|
||||
)
|
||||
|
||||
C = results[5]
|
||||
harness.ok(C.members[0].type.nullable(), "C.foo is nullable")
|
||||
harness.ok(C.members[0].type.hasEnforceRange(), "C.foo has [EnforceRange]")
|
||||
harness.ok(C.members[1].type.nullable(), "C.bar is nullable")
|
||||
harness.ok(C.members[1].type.hasClamp(), "C.bar has [Clamp]")
|
||||
method = C.members[2].signatures()[0][1]
|
||||
harness.ok(method[0].type.nullable(), "foo argument of method is nullable")
|
||||
harness.ok(
|
||||
method[0].type.hasEnforceRange(),
|
||||
"foo argument of method has [EnforceRange]",
|
||||
)
|
||||
harness.ok(method[1].type.nullable(), "bar argument of method is nullable")
|
||||
harness.ok(method[1].type.hasClamp(), "bar argument of method has [Clamp]")
|
||||
method2 = C.members[3].signatures()[0][1]
|
||||
harness.ok(method2[0].type.nullable(), "foo argument of method2 is nullable")
|
||||
harness.ok(
|
||||
method2[0].type.hasEnforceRange(),
|
||||
"foo argument of method2 has [EnforceRange]",
|
||||
)
|
||||
harness.ok(method2[1].type.nullable(), "bar argument of method2 is nullable")
|
||||
harness.ok(method2[1].type.hasClamp(), "bar argument of method2 has [Clamp]")
|
||||
|
||||
# Test [AllowShared]
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef [AllowShared] ArrayBufferView Foo;
|
||||
dictionary A {
|
||||
required [AllowShared] ArrayBufferView a;
|
||||
[ChromeOnly, AllowShared] ArrayBufferView b;
|
||||
Foo c;
|
||||
};
|
||||
interface B {
|
||||
attribute Foo typedefFoo;
|
||||
attribute [AllowShared] ArrayBufferView foo;
|
||||
undefined method([AllowShared] ArrayBufferView foo);
|
||||
undefined method2(optional [AllowShared] ArrayBufferView foo);
|
||||
};
|
||||
interface C {
|
||||
attribute [AllowShared] ArrayBufferView? foo;
|
||||
undefined method([AllowShared] ArrayBufferView? foo);
|
||||
undefined method2(optional [AllowShared] ArrayBufferView? foo);
|
||||
};
|
||||
interface Setlike {
|
||||
setlike<[AllowShared] ArrayBufferView>;
|
||||
};
|
||||
interface Maplike {
|
||||
maplike<[Clamp] long, [AllowShared] ArrayBufferView>;
|
||||
};
|
||||
interface Iterable {
|
||||
iterable<[Clamp] long, [AllowShared] ArrayBufferView>;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(not threw, "Should not have thrown on parsing normal")
|
||||
if not threw:
|
||||
harness.ok(results[0].innerType.hasAllowShared(), "Foo is [AllowShared]")
|
||||
A = results[1]
|
||||
harness.ok(A.members[0].type.hasAllowShared(), "A.a is [AllowShared]")
|
||||
harness.ok(A.members[1].type.hasAllowShared(), "A.b is [AllowShared]")
|
||||
harness.ok(A.members[2].type.hasAllowShared(), "A.c is [AllowShared]")
|
||||
B = results[2]
|
||||
harness.ok(B.members[0].type.hasAllowShared(), "B.typedefFoo is [AllowShared]")
|
||||
harness.ok(B.members[1].type.hasAllowShared(), "B.foo is [AllowShared]")
|
||||
method = B.members[2].signatures()[0][1]
|
||||
harness.ok(
|
||||
method[0].type.hasAllowShared(), "foo argument of method is [AllowShared]"
|
||||
)
|
||||
method2 = B.members[3].signatures()[0][1]
|
||||
harness.ok(
|
||||
method2[0].type.hasAllowShared(), "foo argument of method2 is [AllowShared]"
|
||||
)
|
||||
C = results[3]
|
||||
harness.ok(C.members[0].type.nullable(), "C.foo is nullable")
|
||||
harness.ok(C.members[0].type.hasAllowShared(), "C.foo is [AllowShared]")
|
||||
method = C.members[1].signatures()[0][1]
|
||||
harness.ok(method[0].type.nullable(), "foo argument of method is nullable")
|
||||
harness.ok(
|
||||
method[0].type.hasAllowShared(), "foo argument of method is [AllowShared]"
|
||||
)
|
||||
method2 = C.members[2].signatures()[0][1]
|
||||
harness.ok(method2[0].type.nullable(), "foo argument of method2 is nullable")
|
||||
harness.ok(
|
||||
method2[0].type.hasAllowShared(), "foo argument of method2 is [AllowShared]"
|
||||
)
|
||||
|
||||
ATTRIBUTES = [
|
||||
("[Clamp]", "long"),
|
||||
("[EnforceRange]", "long"),
|
||||
("[LegacyNullToEmptyString]", "DOMString"),
|
||||
("[AllowShared]", "ArrayBufferView"),
|
||||
]
|
||||
TEMPLATES = [
|
||||
(
|
||||
"required dictionary members",
|
||||
"""
|
||||
dictionary Foo {
|
||||
%s required %s foo;
|
||||
};
|
||||
""",
|
||||
),
|
||||
(
|
||||
"optional arguments",
|
||||
"""
|
||||
interface Foo {
|
||||
undefined foo(%s optional %s foo);
|
||||
};
|
||||
""",
|
||||
),
|
||||
(
|
||||
"typedefs",
|
||||
"""
|
||||
%s typedef %s foo;
|
||||
""",
|
||||
),
|
||||
(
|
||||
"attributes",
|
||||
"""
|
||||
interface Foo {
|
||||
%s attribute %s foo;
|
||||
};
|
||||
""",
|
||||
),
|
||||
(
|
||||
"readonly attributes",
|
||||
"""
|
||||
interface Foo {
|
||||
readonly attribute %s %s foo;
|
||||
};
|
||||
""",
|
||||
),
|
||||
(
|
||||
"readonly unresolved attributes",
|
||||
"""
|
||||
interface Foo {
|
||||
readonly attribute Bar baz;
|
||||
};
|
||||
typedef %s %s Bar;
|
||||
""",
|
||||
),
|
||||
(
|
||||
"method",
|
||||
"""
|
||||
interface Foo {
|
||||
%s %s foo();
|
||||
};
|
||||
""",
|
||||
),
|
||||
(
|
||||
"interface",
|
||||
"""
|
||||
%s
|
||||
interface Foo {
|
||||
attribute %s foo;
|
||||
};
|
||||
""",
|
||||
),
|
||||
(
|
||||
"partial interface",
|
||||
"""
|
||||
interface Foo {
|
||||
undefined foo();
|
||||
};
|
||||
%s
|
||||
partial interface Foo {
|
||||
attribute %s bar;
|
||||
};
|
||||
""",
|
||||
),
|
||||
(
|
||||
"interface mixin",
|
||||
"""
|
||||
%s
|
||||
interface mixin Foo {
|
||||
attribute %s foo;
|
||||
};
|
||||
""",
|
||||
),
|
||||
(
|
||||
"namespace",
|
||||
"""
|
||||
%s
|
||||
namespace Foo {
|
||||
attribute %s foo;
|
||||
};
|
||||
""",
|
||||
),
|
||||
(
|
||||
"partial namespace",
|
||||
"""
|
||||
namespace Foo {
|
||||
undefined foo();
|
||||
};
|
||||
%s
|
||||
partial namespace Foo {
|
||||
attribute %s bar;
|
||||
};
|
||||
""",
|
||||
),
|
||||
(
|
||||
"dictionary",
|
||||
"""
|
||||
%s
|
||||
dictionary Foo {
|
||||
%s foo;
|
||||
};
|
||||
""",
|
||||
),
|
||||
]
|
||||
|
||||
for name, template in TEMPLATES:
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(template % ("", "long"))
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(not threw, "Template for %s parses without attributes" % name)
|
||||
for attribute, type in ATTRIBUTES:
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(template % (attribute, type))
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow %s on %s" % (attribute, name))
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef [Clamp, EnforceRange] long Foo;
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange]")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef [EnforceRange, Clamp] long Foo;
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange]")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef [Clamp] long Foo;
|
||||
typedef [EnforceRange] Foo bar;
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange] via typedefs")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef [EnforceRange] long Foo;
|
||||
typedef [Clamp] Foo bar;
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange] via typedefs")
|
||||
|
||||
TYPES = [
|
||||
"DOMString",
|
||||
"unrestricted float",
|
||||
"float",
|
||||
"unrestricted double",
|
||||
"double",
|
||||
]
|
||||
|
||||
for type in TYPES:
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef [Clamp] %s Foo;
|
||||
"""
|
||||
% type
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow [Clamp] on %s" % type)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef [EnforceRange] %s Foo;
|
||||
"""
|
||||
% type
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow [EnforceRange] on %s" % type)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef [LegacyNullToEmptyString] long Foo;
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow [LegacyNullToEmptyString] on long")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef [LegacyNullToEmptyString] JSString Foo;
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow [LegacyNullToEmptyString] on JSString")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef [LegacyNullToEmptyString] DOMString? Foo;
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw, "Should not allow [LegacyNullToEmptyString] on nullable DOMString"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef [AllowShared] DOMString Foo;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "[AllowShared] only allowed on buffer source types")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef [AllowShared=something] ArrayBufferView Foo;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "[AllowShared] must take no arguments")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo {
|
||||
undefined foo([Clamp] Bar arg);
|
||||
};
|
||||
typedef long Bar;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(not threw, "Should allow type attributes on unresolved types")
|
||||
harness.check(
|
||||
results[0].members[0].signatures()[0][1][0].type.hasClamp(),
|
||||
True,
|
||||
"Unresolved types with type attributes should correctly resolve with attributes",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo {
|
||||
undefined foo(Bar arg);
|
||||
};
|
||||
typedef [Clamp] long Bar;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(not threw, "Should allow type attributes on typedefs")
|
||||
harness.check(
|
||||
results[0].members[0].signatures()[0][1][0].type.hasClamp(),
|
||||
True,
|
||||
"Unresolved types that resolve to typedefs with attributes should correctly resolve with "
|
||||
"attributes",
|
||||
)
|
||||
11
third_party/WebIDL/tests/test_builtin_filename.py
vendored
Normal file
11
third_party/WebIDL/tests/test_builtin_filename.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface Test {
|
||||
attribute long b;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
attr = parser.finish()[0].members[0]
|
||||
harness.check(attr.type.filename, "<builtin>", "Filename on builtin type")
|
||||
59
third_party/WebIDL/tests/test_builtins.py
vendored
Normal file
59
third_party/WebIDL/tests/test_builtins.py
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestBuiltins {
|
||||
attribute boolean b;
|
||||
attribute byte s8;
|
||||
attribute octet u8;
|
||||
attribute short s16;
|
||||
attribute unsigned short u16;
|
||||
attribute long s32;
|
||||
attribute unsigned long u32;
|
||||
attribute long long s64;
|
||||
attribute unsigned long long u64;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestBuiltins interface parsed without error.")
|
||||
harness.check(len(results), 1, "Should be one production")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
iface = results[0]
|
||||
harness.check(
|
||||
iface.identifier.QName(), "::TestBuiltins", "Interface has the right QName"
|
||||
)
|
||||
harness.check(iface.identifier.name, "TestBuiltins", "Interface has the right name")
|
||||
harness.check(iface.parent, None, "Interface has no parent")
|
||||
|
||||
members = iface.members
|
||||
harness.check(len(members), 9, "Should be one production")
|
||||
|
||||
names = ["b", "s8", "u8", "s16", "u16", "s32", "u32", "s64", "u64", "ts"]
|
||||
types = [
|
||||
"Boolean",
|
||||
"Byte",
|
||||
"Octet",
|
||||
"Short",
|
||||
"UnsignedShort",
|
||||
"Long",
|
||||
"UnsignedLong",
|
||||
"LongLong",
|
||||
"UnsignedLongLong",
|
||||
"UnsignedLongLong",
|
||||
]
|
||||
for i in range(9):
|
||||
attr = members[i]
|
||||
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
|
||||
harness.check(
|
||||
attr.identifier.QName(),
|
||||
"::TestBuiltins::" + names[i],
|
||||
"Attr has correct QName",
|
||||
)
|
||||
harness.check(attr.identifier.name, names[i], "Attr has correct name")
|
||||
harness.check(str(attr.type), types[i], "Attr type is the correct name")
|
||||
harness.ok(attr.type.isPrimitive(), "Should be a primitive type")
|
||||
125
third_party/WebIDL/tests/test_bytestring.py
vendored
Normal file
125
third_party/WebIDL/tests/test_bytestring.py
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestByteString {
|
||||
attribute ByteString bs;
|
||||
attribute DOMString ds;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestByteString interface parsed without error.")
|
||||
|
||||
harness.check(len(results), 1, "Should be one production")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
iface = results[0]
|
||||
harness.check(
|
||||
iface.identifier.QName(), "::TestByteString", "Interface has the right QName"
|
||||
)
|
||||
harness.check(
|
||||
iface.identifier.name, "TestByteString", "Interface has the right name"
|
||||
)
|
||||
harness.check(iface.parent, None, "Interface has no parent")
|
||||
|
||||
members = iface.members
|
||||
harness.check(len(members), 2, "Should be two productions")
|
||||
|
||||
attr = members[0]
|
||||
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
|
||||
harness.check(
|
||||
attr.identifier.QName(), "::TestByteString::bs", "Attr has correct QName"
|
||||
)
|
||||
harness.check(attr.identifier.name, "bs", "Attr has correct name")
|
||||
harness.check(str(attr.type), "ByteString", "Attr type is the correct name")
|
||||
harness.ok(attr.type.isByteString(), "Should be ByteString type")
|
||||
harness.ok(attr.type.isString(), "Should be String collective type")
|
||||
harness.ok(not attr.type.isDOMString(), "Should be not be DOMString type")
|
||||
|
||||
# now check we haven't broken DOMStrings in the process.
|
||||
attr = members[1]
|
||||
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
|
||||
harness.check(
|
||||
attr.identifier.QName(), "::TestByteString::ds", "Attr has correct QName"
|
||||
)
|
||||
harness.check(attr.identifier.name, "ds", "Attr has correct name")
|
||||
harness.check(str(attr.type), "String", "Attr type is the correct name")
|
||||
harness.ok(attr.type.isDOMString(), "Should be DOMString type")
|
||||
harness.ok(attr.type.isString(), "Should be String collective type")
|
||||
harness.ok(not attr.type.isByteString(), "Should be not be ByteString type")
|
||||
|
||||
# Cannot represent constant ByteString in IDL.
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface ConstByteString {
|
||||
const ByteString foo = "hello"
|
||||
};
|
||||
"""
|
||||
)
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "Should have thrown a WebIDL error for ByteString default in interface"
|
||||
)
|
||||
|
||||
# Can have optional ByteStrings with default values
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface OptionalByteString {
|
||||
undefined passByteString(optional ByteString arg = "hello");
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError as e:
|
||||
harness.ok(
|
||||
False,
|
||||
"Should not have thrown a WebIDL error for ByteString "
|
||||
"default in dictionary. " + str(e),
|
||||
)
|
||||
|
||||
# Can have a default ByteString value in a dictionary
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary OptionalByteStringDict {
|
||||
ByteString item = "some string";
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError as e:
|
||||
harness.ok(
|
||||
False,
|
||||
"Should not have thrown a WebIDL error for ByteString "
|
||||
"default in dictionary. " + str(e),
|
||||
)
|
||||
|
||||
# Don't allow control characters in ByteString literals
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary OptionalByteStringDict2 {
|
||||
ByteString item = "\x03";
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should have thrown a WebIDL error for invalid ByteString "
|
||||
"default in dictionary",
|
||||
)
|
||||
42
third_party/WebIDL/tests/test_callback.py
vendored
Normal file
42
third_party/WebIDL/tests/test_callback.py
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestCallback {
|
||||
attribute CallbackType? listener;
|
||||
};
|
||||
|
||||
callback CallbackType = boolean (unsigned long arg);
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestCallback interface parsed without error.")
|
||||
harness.check(len(results), 2, "Should be two productions.")
|
||||
iface = results[0]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
harness.check(
|
||||
iface.identifier.QName(), "::TestCallback", "Interface has the right QName"
|
||||
)
|
||||
harness.check(iface.identifier.name, "TestCallback", "Interface has the right name")
|
||||
harness.check(len(iface.members), 1, "Expect %s members" % 1)
|
||||
|
||||
attr = iface.members[0]
|
||||
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
|
||||
harness.ok(attr.isAttr(), "Should be an attribute")
|
||||
harness.ok(not attr.isMethod(), "Attr is not an method")
|
||||
harness.ok(not attr.isConst(), "Attr is not a const")
|
||||
harness.check(
|
||||
attr.identifier.QName(), "::TestCallback::listener", "Attr has the right QName"
|
||||
)
|
||||
harness.check(attr.identifier.name, "listener", "Attr has the right name")
|
||||
t = attr.type
|
||||
harness.ok(not isinstance(t, WebIDL.IDLWrapperType), "Attr has the right type")
|
||||
harness.ok(isinstance(t, WebIDL.IDLNullableType), "Attr has the right type")
|
||||
harness.ok(t.isCallback(), "Attr has the right type")
|
||||
|
||||
callback = results[1]
|
||||
harness.ok(not callback.isConstructor(), "callback is not constructor")
|
||||
84
third_party/WebIDL/tests/test_callback_constructor.py
vendored
Normal file
84
third_party/WebIDL/tests/test_callback_constructor.py
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestCallbackConstructor {
|
||||
attribute CallbackConstructorType? constructorAttribute;
|
||||
};
|
||||
|
||||
callback constructor CallbackConstructorType = TestCallbackConstructor (unsigned long arg);
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestCallbackConstructor interface parsed without error.")
|
||||
harness.check(len(results), 2, "Should be two productions.")
|
||||
iface = results[0]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
harness.check(
|
||||
iface.identifier.QName(),
|
||||
"::TestCallbackConstructor",
|
||||
"Interface has the right QName",
|
||||
)
|
||||
harness.check(
|
||||
iface.identifier.name, "TestCallbackConstructor", "Interface has the right name"
|
||||
)
|
||||
harness.check(len(iface.members), 1, "Expect %s members" % 1)
|
||||
|
||||
attr = iface.members[0]
|
||||
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
|
||||
harness.ok(attr.isAttr(), "Should be an attribute")
|
||||
harness.ok(not attr.isMethod(), "Attr is not an method")
|
||||
harness.ok(not attr.isConst(), "Attr is not a const")
|
||||
harness.check(
|
||||
attr.identifier.QName(),
|
||||
"::TestCallbackConstructor::constructorAttribute",
|
||||
"Attr has the right QName",
|
||||
)
|
||||
harness.check(
|
||||
attr.identifier.name, "constructorAttribute", "Attr has the right name"
|
||||
)
|
||||
t = attr.type
|
||||
harness.ok(not isinstance(t, WebIDL.IDLWrapperType), "Attr has the right type")
|
||||
harness.ok(isinstance(t, WebIDL.IDLNullableType), "Attr has the right type")
|
||||
harness.ok(t.isCallback(), "Attr has the right type")
|
||||
|
||||
callback = results[1]
|
||||
harness.ok(callback.isConstructor(), "Callback is constructor")
|
||||
|
||||
parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[LegacyTreatNonObjectAsNull]
|
||||
callback constructor CallbackConstructorType = object ();
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw, "Should throw on LegacyTreatNonObjectAsNull callback constructors"
|
||||
)
|
||||
|
||||
parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[MOZ_CAN_RUN_SCRIPT_BOUNDARY]
|
||||
callback constructor CallbackConstructorType = object ();
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw, "Should not permit MOZ_CAN_RUN_SCRIPT_BOUNDARY callback constructors"
|
||||
)
|
||||
106
third_party/WebIDL/tests/test_callback_interface.py
vendored
Normal file
106
third_party/WebIDL/tests/test_callback_interface.py
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
callback interface TestCallbackInterface {
|
||||
attribute boolean bool;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
iface = results[0]
|
||||
|
||||
harness.ok(iface.isCallback(), "Interface should be a callback")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestInterface {
|
||||
};
|
||||
callback interface TestCallbackInterface : TestInterface {
|
||||
attribute boolean bool;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow non-callback parent of callback interface")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestInterface : TestCallbackInterface {
|
||||
};
|
||||
callback interface TestCallbackInterface {
|
||||
attribute boolean bool;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow callback parent of non-callback interface")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
callback interface TestCallbackInterface1 {
|
||||
undefined foo();
|
||||
};
|
||||
callback interface TestCallbackInterface2 {
|
||||
undefined foo(DOMString arg);
|
||||
undefined foo(TestCallbackInterface1 arg);
|
||||
};
|
||||
callback interface TestCallbackInterface3 {
|
||||
undefined foo(DOMString arg);
|
||||
undefined foo(TestCallbackInterface1 arg);
|
||||
static undefined bar();
|
||||
};
|
||||
callback interface TestCallbackInterface4 {
|
||||
undefined foo(DOMString arg);
|
||||
undefined foo(TestCallbackInterface1 arg);
|
||||
static undefined bar();
|
||||
const long baz = 5;
|
||||
};
|
||||
callback interface TestCallbackInterface5 {
|
||||
static attribute boolean bool;
|
||||
undefined foo();
|
||||
};
|
||||
callback interface TestCallbackInterface6 {
|
||||
undefined foo(DOMString arg);
|
||||
undefined foo(TestCallbackInterface1 arg);
|
||||
undefined bar();
|
||||
};
|
||||
callback interface TestCallbackInterface7 {
|
||||
static attribute boolean bool;
|
||||
};
|
||||
callback interface TestCallbackInterface8 {
|
||||
attribute boolean bool;
|
||||
};
|
||||
callback interface TestCallbackInterface9 : TestCallbackInterface1 {
|
||||
undefined foo();
|
||||
};
|
||||
callback interface TestCallbackInterface10 : TestCallbackInterface1 {
|
||||
undefined bar();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
for i, iface in enumerate(results):
|
||||
harness.check(
|
||||
iface.isSingleOperationInterface(),
|
||||
i < 4,
|
||||
"Interface %s should be a single operation interface"
|
||||
% iface.identifier.name,
|
||||
)
|
||||
160
third_party/WebIDL/tests/test_cereactions.py
vendored
Normal file
160
third_party/WebIDL/tests/test_cereactions.py
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo {
|
||||
[CEReactions(DOMString a)] undefined foo(boolean arg2);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for [CEReactions] with an argument")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo {
|
||||
[CEReactions(DOMString b)] readonly attribute boolean bar;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for [CEReactions] with an argument")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo {
|
||||
[CEReactions] attribute boolean bar;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except Exception as e:
|
||||
harness.ok(
|
||||
False,
|
||||
"Shouldn't have thrown for [CEReactions] used on writable attribute. %s"
|
||||
% e,
|
||||
)
|
||||
threw = True
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo {
|
||||
[CEReactions] undefined foo(boolean arg2);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except Exception as e:
|
||||
harness.ok(
|
||||
False,
|
||||
"Shouldn't have thrown for [CEReactions] used on regular operations. %s"
|
||||
% e,
|
||||
)
|
||||
threw = True
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo {
|
||||
[CEReactions] readonly attribute boolean A;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw, "Should have thrown for [CEReactions] used on a readonly attribute"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[CEReactions]
|
||||
interface Foo {
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for [CEReactions] used on a interface")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo {
|
||||
[CEReactions] getter any(DOMString name);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for [CEReactions] used on a named getter")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo {
|
||||
[CEReactions] legacycaller double compute(double x);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for [CEReactions] used on a legacycaller")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo {
|
||||
[CEReactions] stringifier DOMString ();
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for [CEReactions] used on a stringifier")
|
||||
128
third_party/WebIDL/tests/test_conditional_dictionary_member.py
vendored
Normal file
128
third_party/WebIDL/tests/test_conditional_dictionary_member.py
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Dict {
|
||||
any foo;
|
||||
[ChromeOnly] any bar;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 1, "Should have a dictionary")
|
||||
members = results[0].members
|
||||
harness.check(len(members), 2, "Should have two members")
|
||||
# Note that members are ordered lexicographically, so "bar" comes
|
||||
# before "foo".
|
||||
harness.ok(
|
||||
members[0].getExtendedAttribute("ChromeOnly"), "First member is not ChromeOnly"
|
||||
)
|
||||
harness.ok(
|
||||
not members[1].getExtendedAttribute("ChromeOnly"), "Second member is ChromeOnly"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Dict {
|
||||
any foo;
|
||||
any bar;
|
||||
};
|
||||
|
||||
interface Iface {
|
||||
[Constant, Cached] readonly attribute Dict dict;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 2, "Should have a dictionary and an interface")
|
||||
|
||||
parser = parser.reset()
|
||||
exception = None
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Dict {
|
||||
any foo;
|
||||
[ChromeOnly] any bar;
|
||||
};
|
||||
|
||||
interface Iface {
|
||||
[Constant, Cached] readonly attribute Dict dict;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except Exception as e:
|
||||
exception = e
|
||||
|
||||
harness.ok(exception, "Should have thrown.")
|
||||
harness.check(
|
||||
exception.message,
|
||||
"[Cached] and [StoreInSlot] must not be used on an attribute "
|
||||
"whose type contains a [ChromeOnly] dictionary member",
|
||||
"Should have thrown the right exception",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
exception = None
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary ParentDict {
|
||||
[ChromeOnly] any bar;
|
||||
};
|
||||
|
||||
dictionary Dict : ParentDict {
|
||||
any foo;
|
||||
};
|
||||
|
||||
interface Iface {
|
||||
[Constant, Cached] readonly attribute Dict dict;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except Exception as e:
|
||||
exception = e
|
||||
|
||||
harness.ok(exception, "Should have thrown (2).")
|
||||
harness.check(
|
||||
exception.message,
|
||||
"[Cached] and [StoreInSlot] must not be used on an attribute "
|
||||
"whose type contains a [ChromeOnly] dictionary member",
|
||||
"Should have thrown the right exception (2)",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
exception = None
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary GrandParentDict {
|
||||
[ChromeOnly] any baz;
|
||||
};
|
||||
|
||||
dictionary ParentDict : GrandParentDict {
|
||||
any bar;
|
||||
};
|
||||
|
||||
dictionary Dict : ParentDict {
|
||||
any foo;
|
||||
};
|
||||
|
||||
interface Iface {
|
||||
[Constant, Cached] readonly attribute Dict dict;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except Exception as e:
|
||||
exception = e
|
||||
|
||||
harness.ok(exception, "Should have thrown (3).")
|
||||
harness.check(
|
||||
exception.message,
|
||||
"[Cached] and [StoreInSlot] must not be used on an attribute "
|
||||
"whose type contains a [ChromeOnly] dictionary member",
|
||||
"Should have thrown the right exception (3)",
|
||||
)
|
||||
96
third_party/WebIDL/tests/test_const.py
vendored
Normal file
96
third_party/WebIDL/tests/test_const.py
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
import WebIDL
|
||||
|
||||
expected = [
|
||||
("::TestConsts::zero", "zero", "Byte", 0),
|
||||
("::TestConsts::b", "b", "Byte", -1),
|
||||
("::TestConsts::o", "o", "Octet", 2),
|
||||
("::TestConsts::s", "s", "Short", -3),
|
||||
("::TestConsts::us", "us", "UnsignedShort", 4),
|
||||
("::TestConsts::l", "l", "Long", -5),
|
||||
("::TestConsts::ul", "ul", "UnsignedLong", 6),
|
||||
("::TestConsts::ull", "ull", "UnsignedLongLong", 7),
|
||||
("::TestConsts::ll", "ll", "LongLong", -8),
|
||||
("::TestConsts::t", "t", "Boolean", True),
|
||||
("::TestConsts::f", "f", "Boolean", False),
|
||||
("::TestConsts::fl", "fl", "Float", 0.2),
|
||||
("::TestConsts::db", "db", "Double", 0.2),
|
||||
("::TestConsts::ufl", "ufl", "UnrestrictedFloat", 0.2),
|
||||
("::TestConsts::udb", "udb", "UnrestrictedDouble", 0.2),
|
||||
("::TestConsts::fli", "fli", "Float", 2),
|
||||
("::TestConsts::dbi", "dbi", "Double", 2),
|
||||
("::TestConsts::ufli", "ufli", "UnrestrictedFloat", 2),
|
||||
("::TestConsts::udbi", "udbi", "UnrestrictedDouble", 2),
|
||||
]
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestConsts {
|
||||
const byte zero = 0;
|
||||
const byte b = -1;
|
||||
const octet o = 2;
|
||||
const short s = -3;
|
||||
const unsigned short us = 0x4;
|
||||
const long l = -0X5;
|
||||
const unsigned long ul = 6;
|
||||
const unsigned long long ull = 7;
|
||||
const long long ll = -010;
|
||||
const boolean t = true;
|
||||
const boolean f = false;
|
||||
const float fl = 0.2;
|
||||
const double db = 0.2;
|
||||
const unrestricted float ufl = 0.2;
|
||||
const unrestricted double udb = 0.2;
|
||||
const float fli = 2;
|
||||
const double dbi = 2;
|
||||
const unrestricted float ufli = 2;
|
||||
const unrestricted double udbi = 2;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestConsts interface parsed without error.")
|
||||
harness.check(len(results), 1, "Should be one production.")
|
||||
iface = results[0]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
harness.check(
|
||||
iface.identifier.QName(), "::TestConsts", "Interface has the right QName"
|
||||
)
|
||||
harness.check(iface.identifier.name, "TestConsts", "Interface has the right name")
|
||||
harness.check(
|
||||
len(iface.members), len(expected), "Expect %s members" % len(expected)
|
||||
)
|
||||
|
||||
for const, (QName, name, type, value) in zip(iface.members, expected):
|
||||
harness.ok(isinstance(const, WebIDL.IDLConst), "Should be an IDLConst")
|
||||
harness.ok(const.isConst(), "Const is a const")
|
||||
harness.ok(not const.isAttr(), "Const is not an attr")
|
||||
harness.ok(not const.isMethod(), "Const is not a method")
|
||||
harness.check(const.identifier.QName(), QName, "Const has the right QName")
|
||||
harness.check(const.identifier.name, name, "Const has the right name")
|
||||
harness.check(str(const.type), type, "Const has the right type")
|
||||
harness.ok(const.type.isPrimitive(), "All consts should be primitive")
|
||||
harness.check(
|
||||
str(const.value.type),
|
||||
str(const.type),
|
||||
"Const's value has the same type as the type",
|
||||
)
|
||||
harness.check(const.value.value, value, "Const value has the right value.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestConsts {
|
||||
const boolean? zero = 0;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Nullable types are not allowed for consts.")
|
||||
596
third_party/WebIDL/tests/test_constructor.py
vendored
Normal file
596
third_party/WebIDL/tests/test_constructor.py
vendored
Normal file
@@ -0,0 +1,596 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
def checkArgument(argument, QName, name, type, optional, variadic):
|
||||
harness.ok(isinstance(argument, WebIDL.IDLArgument), "Should be an IDLArgument")
|
||||
harness.check(
|
||||
argument.identifier.QName(), QName, "Argument has the right QName"
|
||||
)
|
||||
harness.check(argument.identifier.name, name, "Argument has the right name")
|
||||
harness.check(str(argument.type), type, "Argument has the right return type")
|
||||
harness.check(
|
||||
argument.optional, optional, "Argument has the right optional value"
|
||||
)
|
||||
harness.check(
|
||||
argument.variadic, variadic, "Argument has the right variadic value"
|
||||
)
|
||||
|
||||
def checkMethod(
|
||||
method,
|
||||
QName,
|
||||
name,
|
||||
signatures,
|
||||
static=True,
|
||||
getter=False,
|
||||
setter=False,
|
||||
deleter=False,
|
||||
legacycaller=False,
|
||||
stringifier=False,
|
||||
chromeOnly=False,
|
||||
htmlConstructor=False,
|
||||
secureContext=False,
|
||||
pref=None,
|
||||
func=None,
|
||||
):
|
||||
harness.ok(isinstance(method, WebIDL.IDLMethod), "Should be an IDLMethod")
|
||||
harness.ok(method.isMethod(), "Method is a method")
|
||||
harness.ok(not method.isAttr(), "Method is not an attr")
|
||||
harness.ok(not method.isConst(), "Method is not a const")
|
||||
harness.check(method.identifier.QName(), QName, "Method has the right QName")
|
||||
harness.check(method.identifier.name, name, "Method has the right name")
|
||||
harness.check(method.isStatic(), static, "Method has the correct static value")
|
||||
harness.check(method.isGetter(), getter, "Method has the correct getter value")
|
||||
harness.check(method.isSetter(), setter, "Method has the correct setter value")
|
||||
harness.check(
|
||||
method.isDeleter(), deleter, "Method has the correct deleter value"
|
||||
)
|
||||
harness.check(
|
||||
method.isLegacycaller(),
|
||||
legacycaller,
|
||||
"Method has the correct legacycaller value",
|
||||
)
|
||||
harness.check(
|
||||
method.isStringifier(),
|
||||
stringifier,
|
||||
"Method has the correct stringifier value",
|
||||
)
|
||||
harness.check(
|
||||
method.getExtendedAttribute("ChromeOnly") is not None,
|
||||
chromeOnly,
|
||||
"Method has the correct value for ChromeOnly",
|
||||
)
|
||||
harness.check(
|
||||
method.isHTMLConstructor(),
|
||||
htmlConstructor,
|
||||
"Method has the correct htmlConstructor value",
|
||||
)
|
||||
harness.check(
|
||||
len(method.signatures()),
|
||||
len(signatures),
|
||||
"Method has the correct number of signatures",
|
||||
)
|
||||
harness.check(
|
||||
method.getExtendedAttribute("Pref"),
|
||||
pref,
|
||||
"Method has the correct pref value",
|
||||
)
|
||||
harness.check(
|
||||
method.getExtendedAttribute("Func"),
|
||||
func,
|
||||
"Method has the correct func value",
|
||||
)
|
||||
harness.check(
|
||||
method.getExtendedAttribute("SecureContext") is not None,
|
||||
secureContext,
|
||||
"Method has the correct SecureContext value",
|
||||
)
|
||||
|
||||
sigpairs = zip(method.signatures(), signatures)
|
||||
for gotSignature, expectedSignature in sigpairs:
|
||||
(gotRetType, gotArgs) = gotSignature
|
||||
(expectedRetType, expectedArgs) = expectedSignature
|
||||
|
||||
harness.check(
|
||||
str(gotRetType), expectedRetType, "Method has the expected return type."
|
||||
)
|
||||
|
||||
for i in range(0, len(gotArgs)):
|
||||
(QName, name, type, optional, variadic) = expectedArgs[i]
|
||||
checkArgument(gotArgs[i], QName, name, type, optional, variadic)
|
||||
|
||||
def checkResults(results):
|
||||
harness.check(len(results), 3, "Should be three productions")
|
||||
harness.ok(
|
||||
isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface"
|
||||
)
|
||||
harness.ok(
|
||||
isinstance(results[1], WebIDL.IDLInterface), "Should be an IDLInterface"
|
||||
)
|
||||
harness.ok(
|
||||
isinstance(results[2], WebIDL.IDLInterface), "Should be an IDLInterface"
|
||||
)
|
||||
|
||||
checkMethod(
|
||||
results[0].ctor(),
|
||||
"::TestConstructorNoArgs::constructor",
|
||||
"constructor",
|
||||
[("TestConstructorNoArgs (Wrapper)", [])],
|
||||
)
|
||||
harness.check(
|
||||
len(results[0].members), 0, "TestConstructorNoArgs should not have members"
|
||||
)
|
||||
checkMethod(
|
||||
results[1].ctor(),
|
||||
"::TestConstructorWithArgs::constructor",
|
||||
"constructor",
|
||||
[
|
||||
(
|
||||
"TestConstructorWithArgs (Wrapper)",
|
||||
[
|
||||
(
|
||||
"::TestConstructorWithArgs::constructor::name",
|
||||
"name",
|
||||
"String",
|
||||
False,
|
||||
False,
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
harness.check(
|
||||
len(results[1].members),
|
||||
0,
|
||||
"TestConstructorWithArgs should not have members",
|
||||
)
|
||||
checkMethod(
|
||||
results[2].ctor(),
|
||||
"::TestConstructorOverloads::constructor",
|
||||
"constructor",
|
||||
[
|
||||
(
|
||||
"TestConstructorOverloads (Wrapper)",
|
||||
[
|
||||
(
|
||||
"::TestConstructorOverloads::constructor::foo",
|
||||
"foo",
|
||||
"Object",
|
||||
False,
|
||||
False,
|
||||
)
|
||||
],
|
||||
),
|
||||
(
|
||||
"TestConstructorOverloads (Wrapper)",
|
||||
[
|
||||
(
|
||||
"::TestConstructorOverloads::constructor::bar",
|
||||
"bar",
|
||||
"Boolean",
|
||||
False,
|
||||
False,
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
harness.check(
|
||||
len(results[2].members),
|
||||
0,
|
||||
"TestConstructorOverloads should not have members",
|
||||
)
|
||||
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestConstructorNoArgs {
|
||||
constructor();
|
||||
};
|
||||
|
||||
interface TestConstructorWithArgs {
|
||||
constructor(DOMString name);
|
||||
};
|
||||
|
||||
interface TestConstructorOverloads {
|
||||
constructor(object foo);
|
||||
constructor(boolean bar);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
checkResults(results)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestPrefConstructor {
|
||||
[Pref="dom.webidl.test1"] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 1, "Should be one production")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
|
||||
checkMethod(
|
||||
results[0].ctor(),
|
||||
"::TestPrefConstructor::constructor",
|
||||
"constructor",
|
||||
[("TestPrefConstructor (Wrapper)", [])],
|
||||
pref=["dom.webidl.test1"],
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestChromeOnlyConstructor {
|
||||
[ChromeOnly] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 1, "Should be one production")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
|
||||
checkMethod(
|
||||
results[0].ctor(),
|
||||
"::TestChromeOnlyConstructor::constructor",
|
||||
"constructor",
|
||||
[("TestChromeOnlyConstructor (Wrapper)", [])],
|
||||
chromeOnly=True,
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestSCConstructor {
|
||||
[SecureContext] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 1, "Should be one production")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
|
||||
checkMethod(
|
||||
results[0].ctor(),
|
||||
"::TestSCConstructor::constructor",
|
||||
"constructor",
|
||||
[("TestSCConstructor (Wrapper)", [])],
|
||||
secureContext=True,
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestFuncConstructor {
|
||||
[Func="IsNotUAWidget"] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 1, "Should be one production")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
|
||||
checkMethod(
|
||||
results[0].ctor(),
|
||||
"::TestFuncConstructor::constructor",
|
||||
"constructor",
|
||||
[("TestFuncConstructor (Wrapper)", [])],
|
||||
func=["IsNotUAWidget"],
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
(
|
||||
"\n"
|
||||
" interface TestPrefChromeOnlySCFuncConstructor {\n"
|
||||
' [ChromeOnly, Pref="dom.webidl.test1", SecureContext, '
|
||||
'Func="IsNotUAWidget"]\n'
|
||||
" constructor();\n"
|
||||
" };\n"
|
||||
)
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 1, "Should be one production")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
|
||||
checkMethod(
|
||||
results[0].ctor(),
|
||||
"::TestPrefChromeOnlySCFuncConstructor::constructor",
|
||||
"constructor",
|
||||
[("TestPrefChromeOnlySCFuncConstructor (Wrapper)", [])],
|
||||
func=["IsNotUAWidget"],
|
||||
pref=["dom.webidl.test1"],
|
||||
chromeOnly=True,
|
||||
secureContext=True,
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestHTMLConstructor {
|
||||
[HTMLConstructor] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 1, "Should be one production")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
|
||||
checkMethod(
|
||||
results[0].ctor(),
|
||||
"::TestHTMLConstructor::constructor",
|
||||
"constructor",
|
||||
[("TestHTMLConstructor (Wrapper)", [])],
|
||||
htmlConstructor=True,
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestChromeOnlyConstructor {
|
||||
constructor()
|
||||
[ChromeOnly] constructor(DOMString a);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Can't have both a constructor and a ChromeOnly constructor")
|
||||
|
||||
# Test HTMLConstructor with argument
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestHTMLConstructorWithArgs {
|
||||
[HTMLConstructor] constructor(DOMString a);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "HTMLConstructor should take no argument")
|
||||
|
||||
# Test HTMLConstructor on a callback interface
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
callback interface TestHTMLConstructorOnCallbackInterface {
|
||||
[HTMLConstructor] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "HTMLConstructor can't be used on a callback interface")
|
||||
|
||||
# Test HTMLConstructor and constructor operation
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestHTMLConstructorAndConstructor {
|
||||
constructor();
|
||||
[HTMLConstructor] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Can't have both a constructor and a HTMLConstructor")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestHTMLConstructorAndConstructor {
|
||||
[Throws]
|
||||
constructor();
|
||||
[HTMLConstructor] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Can't have both a throwing constructor and a HTMLConstructor")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestHTMLConstructorAndConstructor {
|
||||
constructor(DOMString a);
|
||||
[HTMLConstructor] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Can't have both a HTMLConstructor and a constructor operation")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestHTMLConstructorAndConstructor {
|
||||
[Throws]
|
||||
constructor(DOMString a);
|
||||
[HTMLConstructor] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Can't have both a HTMLConstructor and a throwing constructor " "operation",
|
||||
)
|
||||
|
||||
# Test HTMLConstructor and [ChromeOnly] constructor operation
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestHTMLConstructorAndConstructor {
|
||||
[ChromeOnly]
|
||||
constructor();
|
||||
[HTMLConstructor] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Can't have both a ChromeOnly constructor and a HTMLConstructor")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestHTMLConstructorAndConstructor {
|
||||
[Throws, ChromeOnly]
|
||||
constructor();
|
||||
[HTMLConstructor] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Can't have both a throwing chromeonly constructor and a " "HTMLConstructor",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestHTMLConstructorAndConstructor {
|
||||
[ChromeOnly]
|
||||
constructor(DOMString a);
|
||||
[HTMLConstructor] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Can't have both a HTMLConstructor and a chromeonly constructor " "operation",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestHTMLConstructorAndConstructor {
|
||||
[Throws, ChromeOnly]
|
||||
constructor(DOMString a);
|
||||
[HTMLConstructor] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Can't have both a HTMLConstructor and a throwing chromeonly "
|
||||
"constructor operation",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[LegacyNoInterfaceObject]
|
||||
interface InterfaceWithoutInterfaceObject {
|
||||
constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Can't have a constructor operation on a [LegacyNoInterfaceObject] "
|
||||
"interface",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface InterfaceWithPartial {
|
||||
};
|
||||
|
||||
partial interface InterfaceWithPartial {
|
||||
constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Can't have a constructor operation on a partial interface")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface InterfaceWithMixin {
|
||||
};
|
||||
|
||||
interface mixin Mixin {
|
||||
constructor();
|
||||
};
|
||||
|
||||
InterfaceWithMixin includes Mixin
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Can't have a constructor operation on a mixin")
|
||||
72
third_party/WebIDL/tests/test_constructor_global.py
vendored
Normal file
72
third_party/WebIDL/tests/test_constructor_global.py
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=TestConstructorGlobal, Exposed=TestConstructorGlobal]
|
||||
interface TestConstructorGlobal {
|
||||
constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=TestLegacyFactoryFunctionGlobal, Exposed=TestLegacyFactoryFunctionGlobal,
|
||||
LegacyFactoryFunction=FooBar]
|
||||
interface TestLegacyFactoryFunctionGlobal {
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[LegacyFactoryFunction=FooBar, Global=TestLegacyFactoryFunctionGlobal,
|
||||
Exposed=TestLegacyFactoryFunctionGlobal]
|
||||
interface TestLegacyFactoryFunctionGlobal {
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=TestHTMLConstructorGlobal, Exposed=TestHTMLConstructorGlobal]
|
||||
interface TestHTMLConstructorGlobal {
|
||||
[HTMLConstructor] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
50
third_party/WebIDL/tests/test_constructor_no_interface_object.py
vendored
Normal file
50
third_party/WebIDL/tests/test_constructor_no_interface_object.py
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[LegacyNoInterfaceObject]
|
||||
interface TestConstructorLegacyNoInterfaceObject {
|
||||
constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
|
||||
parser.parse(
|
||||
"""
|
||||
[LegacyNoInterfaceObject, LegacyFactoryFunction=FooBar]
|
||||
interface TestLegacyFactoryFunctionLegacyNoInterfaceObject {
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
# Test HTMLConstructor and LegacyNoInterfaceObject
|
||||
parser = parser.reset()
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[LegacyNoInterfaceObject]
|
||||
interface TestHTMLConstructorLegacyNoInterfaceObject {
|
||||
[HTMLConstructor] constructor();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
17
third_party/WebIDL/tests/test_deduplicate.py
vendored
Normal file
17
third_party/WebIDL/tests/test_deduplicate.py
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo;
|
||||
interface Bar;
|
||||
interface Foo;
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
# There should be no duplicate interfaces in the result.
|
||||
expectedNames = sorted(["Foo", "Bar"])
|
||||
actualNames = sorted(map(lambda iface: iface.identifier.name, results))
|
||||
harness.check(
|
||||
actualNames, expectedNames, "Parser shouldn't output duplicate names."
|
||||
)
|
||||
878
third_party/WebIDL/tests/test_dictionary.py
vendored
Normal file
878
third_party/WebIDL/tests/test_dictionary.py
vendored
Normal file
@@ -0,0 +1,878 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Dict2 : Dict1 {
|
||||
long child = 5;
|
||||
Dict1 aaandAnother;
|
||||
};
|
||||
dictionary Dict1 {
|
||||
long parent;
|
||||
double otherParent;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
|
||||
dict1 = results[1]
|
||||
dict2 = results[0]
|
||||
|
||||
harness.check(len(dict1.members), 2, "Dict1 has two members")
|
||||
harness.check(len(dict2.members), 2, "Dict2 has four members")
|
||||
|
||||
harness.check(
|
||||
dict1.members[0].identifier.name, "otherParent", "'o' comes before 'p'"
|
||||
)
|
||||
harness.check(
|
||||
dict1.members[1].identifier.name, "parent", "'o' really comes before 'p'"
|
||||
)
|
||||
harness.check(
|
||||
dict2.members[0].identifier.name, "aaandAnother", "'a' comes before 'c'"
|
||||
)
|
||||
harness.check(
|
||||
dict2.members[1].identifier.name, "child", "'a' really comes before 'c'"
|
||||
)
|
||||
|
||||
# Test partial dictionary.
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
long c;
|
||||
long g;
|
||||
};
|
||||
partial dictionary A {
|
||||
long h;
|
||||
long d;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
|
||||
dict1 = results[0]
|
||||
harness.check(len(dict1.members), 4, "Dict1 has four members")
|
||||
harness.check(dict1.members[0].identifier.name, "c", "c should be first")
|
||||
harness.check(dict1.members[1].identifier.name, "d", "d should come after c")
|
||||
harness.check(dict1.members[2].identifier.name, "g", "g should come after d")
|
||||
harness.check(dict1.members[3].identifier.name, "h", "h should be last")
|
||||
|
||||
# Now reset our parser
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Dict {
|
||||
long prop = 5;
|
||||
long prop;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow name duplication in a dictionary")
|
||||
|
||||
# Test no name duplication across normal and partial dictionary.
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
long prop = 5;
|
||||
};
|
||||
partial dictionary A {
|
||||
long prop;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw, "Should not allow name duplication across normal and partial dictionary"
|
||||
)
|
||||
|
||||
# Now reset our parser again
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Dict1 : Dict2 {
|
||||
long prop = 5;
|
||||
};
|
||||
dictionary Dict2 : Dict3 {
|
||||
long prop2;
|
||||
};
|
||||
dictionary Dict3 {
|
||||
double prop;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw, "Should not allow name duplication in a dictionary and " "its ancestor"
|
||||
)
|
||||
|
||||
# More reset
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Iface {};
|
||||
dictionary Dict : Iface {
|
||||
long prop;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow non-dictionary parents for dictionaries")
|
||||
|
||||
# Even more reset
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A : B {};
|
||||
dictionary B : A {};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow cycles in dictionary inheritance chains")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
[LegacyNullToEmptyString] DOMString foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw, "Should not allow [LegacyNullToEmptyString] on dictionary members"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(A arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Trailing dictionary arg must be optional")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(optional A arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Trailing dictionary arg must have a default value")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo((A or DOMString) arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Trailing union arg containing a dictionary must be optional")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(optional (A or DOMString) arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw, "Trailing union arg containing a dictionary must have a default value"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(A arg1, optional long arg2);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Dictionary arg followed by optional arg must be optional")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(optional A arg1, optional long arg2);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Dictionary arg followed by optional arg must have default value")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(A arg1, optional long arg2, long arg3);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
not threw,
|
||||
"Dictionary arg followed by non-optional arg doesn't have to be optional",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo((A or DOMString) arg1, optional long arg2);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Union arg containing dictionary followed by optional arg must " "be optional",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(optional (A or DOMString) arg1, optional long arg2);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Union arg containing dictionary followed by optional arg must "
|
||||
"have a default value",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(A arg1, long arg2);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
harness.ok(True, "Dictionary arg followed by required arg can be required")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(optional A? arg1 = {});
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except Exception as x:
|
||||
threw = x
|
||||
|
||||
harness.ok(threw, "Optional dictionary arg must not be nullable")
|
||||
harness.ok(
|
||||
"nullable" in str(threw),
|
||||
"Must have the expected exception for optional nullable dictionary arg",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
required long x;
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(A? arg1);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except Exception as x:
|
||||
threw = x
|
||||
|
||||
harness.ok(threw, "Required dictionary arg must not be nullable")
|
||||
harness.ok(
|
||||
"nullable" in str(threw),
|
||||
"Must have the expected exception for required nullable " "dictionary arg",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(optional (A or long)? arg1 = {});
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except Exception as x:
|
||||
threw = x
|
||||
|
||||
harness.ok(threw, "Dictionary arg must not be in an optional nullable union")
|
||||
harness.ok(
|
||||
"nullable" in str(threw),
|
||||
"Must have the expected exception for optional nullable union "
|
||||
"arg containing dictionary",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
required long x;
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo((A or long)? arg1);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except Exception as x:
|
||||
threw = x
|
||||
|
||||
harness.ok(threw, "Dictionary arg must not be in a required nullable union")
|
||||
harness.ok(
|
||||
"nullable" in str(threw),
|
||||
"Must have the expected exception for required nullable union "
|
||||
"arg containing dictionary",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(sequence<A?> arg1);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(not threw, "Nullable union should be allowed in a sequence argument")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(optional (A or long?) arg1);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Dictionary must not be in a union with a nullable type")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(optional (long? or A) arg1);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "A nullable type must not be in a union with a dictionary")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
A? doFoo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
harness.ok(True, "Dictionary return value can be nullable")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(optional A arg = {});
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
harness.ok(True, "Dictionary arg should actually parse")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(optional (A or DOMString) arg = {});
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
harness.ok(True, "Union arg containing a dictionary should actually parse")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
undefined doFoo(optional (A or DOMString) arg = "abc");
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
harness.ok(
|
||||
True,
|
||||
"Union arg containing a dictionary with string default should actually parse",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
Foo foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Member type must not be its Dictionary.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo3 : Foo {
|
||||
short d;
|
||||
};
|
||||
|
||||
dictionary Foo2 : Foo3 {
|
||||
boolean c;
|
||||
};
|
||||
|
||||
dictionary Foo1 : Foo2 {
|
||||
long a;
|
||||
};
|
||||
|
||||
dictionary Foo {
|
||||
Foo1 b;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Member type must not be a Dictionary that " "inherits from its Dictionary.",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
(Foo or DOMString)[]? b;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Member type must not be a Nullable type "
|
||||
"whose inner type includes its Dictionary.",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
(DOMString or Foo) b;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Member type must not be a Union type, one of "
|
||||
"whose member types includes its Dictionary.",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
sequence<sequence<sequence<Foo>>> c;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Member type must not be a Sequence type "
|
||||
"whose element type includes its Dictionary.",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
(DOMString or Foo)[] d;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Member type must not be an Array type "
|
||||
"whose element type includes its Dictionary.",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
Foo1 b;
|
||||
};
|
||||
|
||||
dictionary Foo3 {
|
||||
Foo d;
|
||||
};
|
||||
|
||||
dictionary Foo2 : Foo3 {
|
||||
short c;
|
||||
};
|
||||
|
||||
dictionary Foo1 : Foo2 {
|
||||
long a;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Member type must not be a Dictionary, one of whose "
|
||||
"members or inherited members has a type that includes "
|
||||
"its Dictionary.",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
};
|
||||
|
||||
dictionary Bar {
|
||||
Foo? d;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Member type must not be a nullable dictionary")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
unrestricted float urFloat = 0;
|
||||
unrestricted float urFloat2 = 1.1;
|
||||
unrestricted float urFloat3 = -1.1;
|
||||
unrestricted float? urFloat4 = null;
|
||||
unrestricted float infUrFloat = Infinity;
|
||||
unrestricted float negativeInfUrFloat = -Infinity;
|
||||
unrestricted float nanUrFloat = NaN;
|
||||
|
||||
unrestricted double urDouble = 0;
|
||||
unrestricted double urDouble2 = 1.1;
|
||||
unrestricted double urDouble3 = -1.1;
|
||||
unrestricted double? urDouble4 = null;
|
||||
unrestricted double infUrDouble = Infinity;
|
||||
unrestricted double negativeInfUrDouble = -Infinity;
|
||||
unrestricted double nanUrDouble = NaN;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
harness.ok(True, "Parsing default values for unrestricted types succeeded.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
double f = Infinity;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Only unrestricted values can be initialized to Infinity")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
double f = -Infinity;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Only unrestricted values can be initialized to -Infinity")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
double f = NaN;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Only unrestricted values can be initialized to NaN")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
float f = Infinity;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Only unrestricted values can be initialized to Infinity")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
float f = -Infinity;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Only unrestricted values can be initialized to -Infinity")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
float f = NaN;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Only unrestricted values can be initialized to NaN")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo {
|
||||
long module;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(not threw, "Should be able to use 'module' as a dictionary member name")
|
||||
465
third_party/WebIDL/tests/test_distinguishability.py
vendored
Normal file
465
third_party/WebIDL/tests/test_distinguishability.py
vendored
Normal file
@@ -0,0 +1,465 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def firstArgType(method):
|
||||
return method.signatures()[0][1][0].type
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
// Give our dictionary a required member so we don't need to
|
||||
// mess with optional and default values.
|
||||
dictionary Dict {
|
||||
required long member;
|
||||
};
|
||||
callback interface Foo {
|
||||
};
|
||||
interface Bar {
|
||||
// Bit of a pain to get things that have dictionary types
|
||||
undefined passDict(Dict arg);
|
||||
undefined passFoo(Foo arg);
|
||||
undefined passNullableUnion((object? or DOMString) arg);
|
||||
undefined passNullable(Foo? arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
|
||||
iface = results[2]
|
||||
harness.ok(iface.isInterface(), "Should have interface")
|
||||
dictMethod = iface.members[0]
|
||||
ifaceMethod = iface.members[1]
|
||||
nullableUnionMethod = iface.members[2]
|
||||
nullableIfaceMethod = iface.members[3]
|
||||
|
||||
dictType = firstArgType(dictMethod)
|
||||
ifaceType = firstArgType(ifaceMethod)
|
||||
|
||||
harness.ok(dictType.isDictionary(), "Should have dictionary type")
|
||||
harness.ok(ifaceType.isInterface(), "Should have interface type")
|
||||
harness.ok(ifaceType.isCallbackInterface(), "Should have callback interface type")
|
||||
|
||||
harness.ok(
|
||||
not dictType.isDistinguishableFrom(ifaceType),
|
||||
"Dictionary not distinguishable from callback interface",
|
||||
)
|
||||
harness.ok(
|
||||
not ifaceType.isDistinguishableFrom(dictType),
|
||||
"Callback interface not distinguishable from dictionary",
|
||||
)
|
||||
|
||||
nullableUnionType = firstArgType(nullableUnionMethod)
|
||||
nullableIfaceType = firstArgType(nullableIfaceMethod)
|
||||
|
||||
harness.ok(nullableUnionType.isUnion(), "Should have union type")
|
||||
harness.ok(nullableIfaceType.isInterface(), "Should have interface type")
|
||||
harness.ok(nullableIfaceType.nullable(), "Should have nullable type")
|
||||
|
||||
harness.ok(
|
||||
not nullableUnionType.isDistinguishableFrom(nullableIfaceType),
|
||||
"Nullable type not distinguishable from union with nullable " "member type",
|
||||
)
|
||||
harness.ok(
|
||||
not nullableIfaceType.isDistinguishableFrom(nullableUnionType),
|
||||
"Union with nullable member type not distinguishable from " "nullable type",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestIface {
|
||||
undefined passKid(Kid arg);
|
||||
undefined passParent(Parent arg);
|
||||
undefined passGrandparent(Grandparent arg);
|
||||
undefined passUnrelated1(Unrelated1 arg);
|
||||
undefined passUnrelated2(Unrelated2 arg);
|
||||
undefined passArrayBuffer(ArrayBuffer arg);
|
||||
undefined passArrayBuffer(ArrayBufferView arg);
|
||||
};
|
||||
|
||||
interface Kid : Parent {};
|
||||
interface Parent : Grandparent {};
|
||||
interface Grandparent {};
|
||||
interface Unrelated1 {};
|
||||
interface Unrelated2 {};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
|
||||
iface = results[0]
|
||||
harness.ok(iface.isInterface(), "Should have interface")
|
||||
argTypes = [firstArgType(method) for method in iface.members]
|
||||
unrelatedTypes = [firstArgType(method) for method in iface.members[-3:]]
|
||||
|
||||
for type1 in argTypes:
|
||||
for type2 in argTypes:
|
||||
distinguishable = type1 is not type2 and (
|
||||
type1 in unrelatedTypes or type2 in unrelatedTypes
|
||||
)
|
||||
|
||||
harness.check(
|
||||
type1.isDistinguishableFrom(type2),
|
||||
distinguishable,
|
||||
"Type %s should %sbe distinguishable from type %s"
|
||||
% (type1, "" if distinguishable else "not ", type2),
|
||||
)
|
||||
harness.check(
|
||||
type2.isDistinguishableFrom(type1),
|
||||
distinguishable,
|
||||
"Type %s should %sbe distinguishable from type %s"
|
||||
% (type2, "" if distinguishable else "not ", type1),
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface Dummy {};
|
||||
interface TestIface {
|
||||
undefined method(long arg1, TestIface arg2);
|
||||
undefined method(long arg1, long arg2);
|
||||
undefined method(long arg1, Dummy arg2);
|
||||
undefined method(DOMString arg1, DOMString arg2, DOMString arg3);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results[1].members), 1, "Should look like we have one method")
|
||||
harness.check(
|
||||
len(results[1].members[0].signatures()), 4, "Should have four signatures"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Dummy {};
|
||||
interface TestIface {
|
||||
undefined method(long arg1, TestIface arg2);
|
||||
undefined method(long arg1, long arg2);
|
||||
undefined method(any arg1, Dummy arg2);
|
||||
undefined method(DOMString arg1, DOMString arg2, DOMString arg3);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should throw when args before the distinguishing arg are not "
|
||||
"all the same type",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Dummy {};
|
||||
interface TestIface {
|
||||
undefined method(long arg1, TestIface arg2);
|
||||
undefined method(long arg1, long arg2);
|
||||
undefined method(any arg1, DOMString arg2);
|
||||
undefined method(DOMString arg1, DOMString arg2, DOMString arg3);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should throw when there is no distinguishing index")
|
||||
|
||||
# Now let's test our whole distinguishability table
|
||||
argTypes = [
|
||||
"long",
|
||||
"short",
|
||||
"long?",
|
||||
"short?",
|
||||
"boolean",
|
||||
"boolean?",
|
||||
"undefined",
|
||||
"undefined?",
|
||||
"DOMString",
|
||||
"ByteString",
|
||||
"UTF8String",
|
||||
"Enum",
|
||||
"Enum2",
|
||||
"Interface",
|
||||
"Interface?",
|
||||
"AncestorInterface",
|
||||
"UnrelatedInterface",
|
||||
"CallbackInterface",
|
||||
"CallbackInterface?",
|
||||
"CallbackInterface2",
|
||||
"object",
|
||||
"Callback",
|
||||
"Callback2",
|
||||
"Dict",
|
||||
"Dict2",
|
||||
"sequence<long>",
|
||||
"sequence<short>",
|
||||
"record<DOMString, object>",
|
||||
"record<USVString, Dict>",
|
||||
"record<ByteString, long>",
|
||||
"record<UTF8String, long>",
|
||||
"any",
|
||||
"Promise<any>",
|
||||
"Promise<any>?",
|
||||
"USVString",
|
||||
"JSString",
|
||||
"ArrayBuffer",
|
||||
"ArrayBufferView",
|
||||
"Uint8Array",
|
||||
"Uint16Array",
|
||||
"(long or Callback)",
|
||||
"(long or Dict)",
|
||||
]
|
||||
|
||||
# Try to categorize things a bit to keep list lengths down
|
||||
def allBut(list1, list2):
|
||||
return [
|
||||
a
|
||||
for a in list1
|
||||
if a not in list2
|
||||
and (a != "any" and a != "Promise<any>" and a != "Promise<any>?")
|
||||
]
|
||||
|
||||
unionsWithCallback = ["(long or Callback)"]
|
||||
unionsNoCallback = ["(long or Dict)"]
|
||||
unions = unionsWithCallback + unionsNoCallback
|
||||
numerics = ["long", "short", "long?", "short?"]
|
||||
booleans = ["boolean", "boolean?"]
|
||||
undefineds = ["undefined", "undefined?"]
|
||||
primitives = numerics + booleans
|
||||
nonNumerics = allBut(argTypes, numerics + unions)
|
||||
nonBooleans = allBut(argTypes, booleans)
|
||||
strings = [
|
||||
"DOMString",
|
||||
"ByteString",
|
||||
"Enum",
|
||||
"Enum2",
|
||||
"USVString",
|
||||
"JSString",
|
||||
"UTF8String",
|
||||
]
|
||||
nonStrings = allBut(argTypes, strings)
|
||||
nonObjects = undefineds + primitives + strings
|
||||
bufferSourceTypes = ["ArrayBuffer", "ArrayBufferView", "Uint8Array", "Uint16Array"]
|
||||
interfaces = [
|
||||
"Interface",
|
||||
"Interface?",
|
||||
"AncestorInterface",
|
||||
"UnrelatedInterface",
|
||||
] + bufferSourceTypes
|
||||
nullables = [
|
||||
"long?",
|
||||
"short?",
|
||||
"boolean?",
|
||||
"undefined?",
|
||||
"Interface?",
|
||||
"CallbackInterface?",
|
||||
"Dict",
|
||||
"Dict2",
|
||||
"Date?",
|
||||
"any",
|
||||
"Promise<any>?",
|
||||
] + unionsNoCallback
|
||||
sequences = ["sequence<long>", "sequence<short>"]
|
||||
nonUserObjects = nonObjects + interfaces + sequences
|
||||
otherObjects = allBut(argTypes, nonUserObjects + ["object"])
|
||||
notRelatedInterfaces = (
|
||||
nonObjects
|
||||
+ ["UnrelatedInterface"]
|
||||
+ otherObjects
|
||||
+ sequences
|
||||
+ bufferSourceTypes
|
||||
)
|
||||
records = [
|
||||
"record<DOMString, object>",
|
||||
"record<USVString, Dict>",
|
||||
"record<ByteString, long>",
|
||||
"record<UTF8String, long>",
|
||||
] # JSString not supported in records
|
||||
dicts = ["Dict", "Dict2"]
|
||||
callbacks = ["Callback", "Callback2"]
|
||||
callbackInterfaces = [
|
||||
"CallbackInterface",
|
||||
"CallbackInterface?",
|
||||
"CallbackInterface2",
|
||||
]
|
||||
dictionaryLike = dicts + callbackInterfaces + records + unionsNoCallback
|
||||
|
||||
# Build a representation of the distinguishability table as a dict
|
||||
# of dicts, holding True values where needed, holes elsewhere.
|
||||
data = dict()
|
||||
for type in argTypes:
|
||||
data[type] = dict()
|
||||
|
||||
def setDistinguishable(type, types):
|
||||
for other in types:
|
||||
data[type][other] = True
|
||||
|
||||
setDistinguishable("long", nonNumerics)
|
||||
setDistinguishable("short", nonNumerics)
|
||||
setDistinguishable("long?", allBut(nonNumerics, nullables))
|
||||
setDistinguishable("short?", allBut(nonNumerics, nullables))
|
||||
setDistinguishable("boolean", nonBooleans)
|
||||
setDistinguishable("boolean?", allBut(nonBooleans, nullables))
|
||||
setDistinguishable("undefined", allBut(argTypes, undefineds + dictionaryLike))
|
||||
setDistinguishable(
|
||||
"undefined?", allBut(argTypes, undefineds + dictionaryLike + nullables)
|
||||
)
|
||||
setDistinguishable("DOMString", nonStrings)
|
||||
setDistinguishable("ByteString", nonStrings)
|
||||
setDistinguishable("UTF8String", nonStrings)
|
||||
setDistinguishable("USVString", nonStrings)
|
||||
setDistinguishable("JSString", nonStrings)
|
||||
setDistinguishable("Enum", nonStrings)
|
||||
setDistinguishable("Enum2", nonStrings)
|
||||
setDistinguishable("Interface", notRelatedInterfaces)
|
||||
setDistinguishable("Interface?", allBut(notRelatedInterfaces, nullables))
|
||||
setDistinguishable("AncestorInterface", notRelatedInterfaces)
|
||||
setDistinguishable(
|
||||
"UnrelatedInterface", allBut(argTypes, ["object", "UnrelatedInterface"])
|
||||
)
|
||||
setDistinguishable(
|
||||
"CallbackInterface",
|
||||
allBut(nonUserObjects + callbacks + unionsWithCallback, undefineds),
|
||||
)
|
||||
setDistinguishable(
|
||||
"CallbackInterface?",
|
||||
allBut(nonUserObjects + callbacks + unionsWithCallback, nullables + undefineds),
|
||||
)
|
||||
setDistinguishable(
|
||||
"CallbackInterface2",
|
||||
allBut(nonUserObjects + callbacks + unionsWithCallback, undefineds),
|
||||
)
|
||||
setDistinguishable("object", nonObjects)
|
||||
setDistinguishable(
|
||||
"Callback",
|
||||
nonUserObjects + unionsNoCallback + dicts + records + callbackInterfaces,
|
||||
)
|
||||
setDistinguishable(
|
||||
"Callback2",
|
||||
nonUserObjects + unionsNoCallback + dicts + records + callbackInterfaces,
|
||||
)
|
||||
setDistinguishable(
|
||||
"Dict",
|
||||
allBut(nonUserObjects + unionsWithCallback + callbacks, nullables + undefineds),
|
||||
)
|
||||
setDistinguishable(
|
||||
"Dict2",
|
||||
allBut(nonUserObjects + unionsWithCallback + callbacks, nullables + undefineds),
|
||||
)
|
||||
setDistinguishable(
|
||||
"sequence<long>",
|
||||
allBut(argTypes, sequences + ["object"]),
|
||||
)
|
||||
setDistinguishable(
|
||||
"sequence<short>",
|
||||
allBut(argTypes, sequences + ["object"]),
|
||||
)
|
||||
setDistinguishable(
|
||||
"record<DOMString, object>",
|
||||
allBut(nonUserObjects + unionsWithCallback + callbacks, undefineds),
|
||||
)
|
||||
setDistinguishable(
|
||||
"record<USVString, Dict>",
|
||||
allBut(nonUserObjects + unionsWithCallback + callbacks, undefineds),
|
||||
)
|
||||
# JSString not supported in records
|
||||
setDistinguishable(
|
||||
"record<ByteString, long>",
|
||||
allBut(nonUserObjects + unionsWithCallback + callbacks, undefineds),
|
||||
)
|
||||
setDistinguishable(
|
||||
"record<UTF8String, long>",
|
||||
allBut(nonUserObjects + unionsWithCallback + callbacks, undefineds),
|
||||
)
|
||||
setDistinguishable("any", [])
|
||||
setDistinguishable("Promise<any>", [])
|
||||
setDistinguishable("Promise<any>?", [])
|
||||
setDistinguishable("ArrayBuffer", allBut(argTypes, ["ArrayBuffer", "object"]))
|
||||
setDistinguishable(
|
||||
"ArrayBufferView",
|
||||
allBut(argTypes, ["ArrayBufferView", "Uint8Array", "Uint16Array", "object"]),
|
||||
)
|
||||
setDistinguishable(
|
||||
"Uint8Array", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "object"])
|
||||
)
|
||||
setDistinguishable(
|
||||
"Uint16Array", allBut(argTypes, ["ArrayBufferView", "Uint16Array", "object"])
|
||||
)
|
||||
setDistinguishable(
|
||||
"(long or Callback)",
|
||||
allBut(nonUserObjects + dicts + records + callbackInterfaces, numerics),
|
||||
)
|
||||
setDistinguishable(
|
||||
"(long or Dict)",
|
||||
allBut(nonUserObjects + callbacks, numerics + nullables + undefineds),
|
||||
)
|
||||
|
||||
def areDistinguishable(type1, type2):
|
||||
return data[type1].get(type2, False)
|
||||
|
||||
def checkDistinguishability(parser, type1, type2):
|
||||
idlTemplate = """
|
||||
enum Enum { "a", "b" };
|
||||
enum Enum2 { "c", "d" };
|
||||
interface Interface : AncestorInterface {};
|
||||
interface AncestorInterface {};
|
||||
interface UnrelatedInterface {};
|
||||
callback interface CallbackInterface {};
|
||||
callback interface CallbackInterface2 {};
|
||||
callback Callback = any();
|
||||
callback Callback2 = long(short arg);
|
||||
[LegacyTreatNonObjectAsNull] callback LegacyCallback1 = any();
|
||||
// Give our dictionaries required members so we don't need to
|
||||
// mess with optional and default values.
|
||||
dictionary Dict { required long member; };
|
||||
dictionary Dict2 { required long member; };
|
||||
interface TestInterface {%s
|
||||
};
|
||||
"""
|
||||
if type1 in undefineds or type2 in undefineds:
|
||||
methods = """
|
||||
(%s or %s) myMethod();""" % (
|
||||
type1,
|
||||
type2,
|
||||
)
|
||||
else:
|
||||
methodTemplate = """
|
||||
undefined myMethod(%s arg);"""
|
||||
methods = (methodTemplate % type1) + (methodTemplate % type2)
|
||||
idl = idlTemplate % methods
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(idl)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
if areDistinguishable(type1, type2):
|
||||
harness.ok(
|
||||
not threw,
|
||||
"Should not throw for '%s' and '%s' because they are distinguishable"
|
||||
% (type1, type2),
|
||||
)
|
||||
else:
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should throw for '%s' and '%s' because they are not distinguishable"
|
||||
% (type1, type2),
|
||||
)
|
||||
|
||||
# Enumerate over everything in both orders, since order matters in
|
||||
# terms of our implementation of distinguishability checks
|
||||
for type1 in argTypes:
|
||||
for type2 in argTypes:
|
||||
checkDistinguishability(parser, type1, type2)
|
||||
19
third_party/WebIDL/tests/test_double_null.py
vendored
Normal file
19
third_party/WebIDL/tests/test_double_null.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface DoubleNull {
|
||||
attribute byte?? foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
67
third_party/WebIDL/tests/test_duplicate_qualifiers.py
vendored
Normal file
67
third_party/WebIDL/tests/test_duplicate_qualifiers.py
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface DuplicateQualifiers1 {
|
||||
getter getter byte foo(unsigned long index);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface DuplicateQualifiers2 {
|
||||
setter setter byte foo(unsigned long index, byte value);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface DuplicateQualifiers4 {
|
||||
deleter deleter byte foo(unsigned long index);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface DuplicateQualifiers5 {
|
||||
getter deleter getter byte foo(unsigned long index);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
17
third_party/WebIDL/tests/test_empty_enum.py
vendored
Normal file
17
third_party/WebIDL/tests/test_empty_enum.py
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
enum TestEmptyEnum {
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
harness.ok(False, "Should have thrown!")
|
||||
except WebIDL.WebIDLError:
|
||||
harness.ok(True, "Parsing TestEmptyEnum enum should fail")
|
||||
|
||||
parser.finish()
|
||||
54
third_party/WebIDL/tests/test_empty_sequence_default_value.py
vendored
Normal file
54
third_party/WebIDL/tests/test_empty_sequence_default_value.py
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface X {
|
||||
const sequence<long> foo = [];
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Constant cannot have [] as a default value")
|
||||
|
||||
parser = parser.reset()
|
||||
|
||||
parser.parse(
|
||||
"""
|
||||
interface X {
|
||||
undefined foo(optional sequence<long> arg = []);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(
|
||||
isinstance(
|
||||
results[0].members[0].signatures()[0][1][0].defaultValue,
|
||||
WebIDL.IDLEmptySequenceValue,
|
||||
),
|
||||
"Should have IDLEmptySequenceValue as default value of argument",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary X {
|
||||
sequence<long> foo = [];
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(
|
||||
isinstance(results[0].members[0].defaultValue, WebIDL.IDLEmptySequenceValue),
|
||||
"Should have IDLEmptySequenceValue as default value of " "dictionary member",
|
||||
)
|
||||
107
third_party/WebIDL/tests/test_enum.py
vendored
Normal file
107
third_party/WebIDL/tests/test_enum.py
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
enum TestEnum {
|
||||
"",
|
||||
"foo",
|
||||
"bar"
|
||||
};
|
||||
|
||||
interface TestEnumInterface {
|
||||
TestEnum doFoo(boolean arg);
|
||||
readonly attribute TestEnum foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestEnumInterfaces interface parsed without error.")
|
||||
harness.check(len(results), 2, "Should be one production")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLEnum), "Should be an IDLEnum")
|
||||
harness.ok(isinstance(results[1], WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
|
||||
enum = results[0]
|
||||
harness.check(enum.identifier.QName(), "::TestEnum", "Enum has the right QName")
|
||||
harness.check(enum.identifier.name, "TestEnum", "Enum has the right name")
|
||||
harness.check(enum.values(), ["", "foo", "bar"], "Enum has the right values")
|
||||
|
||||
iface = results[1]
|
||||
|
||||
harness.check(
|
||||
iface.identifier.QName(), "::TestEnumInterface", "Interface has the right QName"
|
||||
)
|
||||
harness.check(
|
||||
iface.identifier.name, "TestEnumInterface", "Interface has the right name"
|
||||
)
|
||||
harness.check(iface.parent, None, "Interface has no parent")
|
||||
|
||||
members = iface.members
|
||||
harness.check(len(members), 2, "Should be one production")
|
||||
harness.ok(isinstance(members[0], WebIDL.IDLMethod), "Should be an IDLMethod")
|
||||
method = members[0]
|
||||
harness.check(
|
||||
method.identifier.QName(),
|
||||
"::TestEnumInterface::doFoo",
|
||||
"Method has correct QName",
|
||||
)
|
||||
harness.check(method.identifier.name, "doFoo", "Method has correct name")
|
||||
|
||||
signatures = method.signatures()
|
||||
harness.check(len(signatures), 1, "Expect one signature")
|
||||
|
||||
(returnType, arguments) = signatures[0]
|
||||
harness.check(
|
||||
str(returnType), "TestEnum (Wrapper)", "Method type is the correct name"
|
||||
)
|
||||
harness.check(len(arguments), 1, "Method has the right number of arguments")
|
||||
arg = arguments[0]
|
||||
harness.ok(isinstance(arg, WebIDL.IDLArgument), "Should be an IDLArgument")
|
||||
harness.check(str(arg.type), "Boolean", "Argument has the right type")
|
||||
|
||||
attr = members[1]
|
||||
harness.check(
|
||||
attr.identifier.QName(), "::TestEnumInterface::foo", "Attr has correct QName"
|
||||
)
|
||||
harness.check(attr.identifier.name, "foo", "Attr has correct name")
|
||||
|
||||
harness.check(str(attr.type), "TestEnum (Wrapper)", "Attr type is the correct name")
|
||||
|
||||
# Now reset our parser
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
enum Enum {
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
};
|
||||
interface TestInterface {
|
||||
undefined foo(optional Enum e = "d");
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow a bogus default value for an enum")
|
||||
|
||||
# Now reset our parser
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
enum Enum {
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 1, "Should allow trailing comma in enum")
|
||||
16
third_party/WebIDL/tests/test_enum_duplicate_values.py
vendored
Normal file
16
third_party/WebIDL/tests/test_enum_duplicate_values.py
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
enum TestEnumDuplicateValue {
|
||||
"",
|
||||
""
|
||||
};
|
||||
"""
|
||||
)
|
||||
harness.ok(False, "Should have thrown!")
|
||||
except WebIDL.WebIDLError:
|
||||
harness.ok(True, "Enum TestEnumDuplicateValue should throw")
|
||||
24
third_party/WebIDL/tests/test_error_colno.py
vendored
Normal file
24
third_party/WebIDL/tests/test_error_colno.py
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
# Check that error messages put the '^' in the right place.
|
||||
|
||||
threw = False
|
||||
input = "interface ?"
|
||||
try:
|
||||
parser.parse(input)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError as e:
|
||||
threw = True
|
||||
lines = str(e).split("\n")
|
||||
|
||||
harness.check(len(lines), 3, "Expected number of lines in error message")
|
||||
harness.check(lines[1], input, "Second line shows error")
|
||||
harness.check(
|
||||
lines[2],
|
||||
" " * (len(input) - 1) + "^",
|
||||
"Correct column pointer in error message",
|
||||
)
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
38
third_party/WebIDL/tests/test_error_lineno.py
vendored
Normal file
38
third_party/WebIDL/tests/test_error_lineno.py
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
# Check that error messages put the '^' in the right place.
|
||||
|
||||
threw = False
|
||||
input = """\
|
||||
// This is a comment.
|
||||
interface Foo {
|
||||
};
|
||||
|
||||
/* This is also a comment. */
|
||||
interface ?"""
|
||||
try:
|
||||
parser.parse(input)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError as e:
|
||||
threw = True
|
||||
lines = str(e).split("\n")
|
||||
|
||||
harness.check(len(lines), 3, "Expected number of lines in error message")
|
||||
harness.ok(
|
||||
lines[0].endswith("line 6:10"),
|
||||
'First line of error should end with "line 6:10", but was "%s".' % lines[0],
|
||||
)
|
||||
harness.check(
|
||||
lines[1],
|
||||
"interface ?",
|
||||
"Second line of error message is the line which caused the error.",
|
||||
)
|
||||
harness.check(
|
||||
lines[2],
|
||||
" " * (len("interface ?") - 1) + "^",
|
||||
"Correct column pointer in error message.",
|
||||
)
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
383
third_party/WebIDL/tests/test_exposed_extended_attribute.py
vendored
Normal file
383
third_party/WebIDL/tests/test_exposed_extended_attribute.py
vendored
Normal file
@@ -0,0 +1,383 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, Exposed=Foo] interface Foo {};
|
||||
[Global=(Bar, Bar1,Bar2), Exposed=Bar] interface Bar {};
|
||||
[Global=(Baz, Baz2), Exposed=Baz] interface Baz {};
|
||||
|
||||
[Exposed=(Foo,Bar1)]
|
||||
interface Iface {
|
||||
undefined method1();
|
||||
|
||||
[Exposed=Bar1]
|
||||
readonly attribute any attr;
|
||||
};
|
||||
|
||||
[Exposed=Foo]
|
||||
partial interface Iface {
|
||||
undefined method2();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.check(len(results), 5, "Should know about five things")
|
||||
iface = results[3]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should have an interface here")
|
||||
members = iface.members
|
||||
harness.check(len(members), 3, "Should have three members")
|
||||
|
||||
harness.ok(
|
||||
members[0].exposureSet == set(["Foo", "Bar"]),
|
||||
"method1 should have the right exposure set",
|
||||
)
|
||||
harness.ok(
|
||||
members[0]._exposureGlobalNames == set(["Foo", "Bar1"]),
|
||||
"method1 should have the right exposure global names",
|
||||
)
|
||||
|
||||
harness.ok(
|
||||
members[1].exposureSet == set(["Bar"]),
|
||||
"attr should have the right exposure set",
|
||||
)
|
||||
harness.ok(
|
||||
members[1]._exposureGlobalNames == set(["Bar1"]),
|
||||
"attr should have the right exposure global names",
|
||||
)
|
||||
|
||||
harness.ok(
|
||||
members[2].exposureSet == set(["Foo"]),
|
||||
"method2 should have the right exposure set",
|
||||
)
|
||||
harness.ok(
|
||||
members[2]._exposureGlobalNames == set(["Foo"]),
|
||||
"method2 should have the right exposure global names",
|
||||
)
|
||||
|
||||
harness.ok(
|
||||
iface.exposureSet == set(["Foo", "Bar"]),
|
||||
"Iface should have the right exposure set",
|
||||
)
|
||||
harness.ok(
|
||||
iface._exposureGlobalNames == set(["Foo", "Bar1"]),
|
||||
"Iface should have the right exposure global names",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, Exposed=Foo] interface Foo {};
|
||||
[Global=(Bar, Bar1, Bar2), Exposed=Bar] interface Bar {};
|
||||
[Global=(Baz, Baz2), Exposed=Baz] interface Baz {};
|
||||
|
||||
[Exposed=Foo]
|
||||
interface Iface2 {
|
||||
undefined method3();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
|
||||
harness.check(len(results), 4, "Should know about four things")
|
||||
iface = results[3]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should have an interface here")
|
||||
members = iface.members
|
||||
harness.check(len(members), 1, "Should have one member")
|
||||
|
||||
harness.ok(
|
||||
members[0].exposureSet == set(["Foo"]),
|
||||
"method3 should have the right exposure set",
|
||||
)
|
||||
harness.ok(
|
||||
members[0]._exposureGlobalNames == set(["Foo"]),
|
||||
"method3 should have the right exposure global names",
|
||||
)
|
||||
|
||||
harness.ok(
|
||||
iface.exposureSet == set(["Foo"]), "Iface2 should have the right exposure set"
|
||||
)
|
||||
harness.ok(
|
||||
iface._exposureGlobalNames == set(["Foo"]),
|
||||
"Iface2 should have the right exposure global names",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, Exposed=Foo] interface Foo {};
|
||||
[Global=(Bar, Bar1, Bar2), Exposed=Bar] interface Bar {};
|
||||
[Global=(Baz, Baz2), Exposed=Baz] interface Baz {};
|
||||
|
||||
[Exposed=Foo]
|
||||
interface Iface3 {
|
||||
undefined method4();
|
||||
};
|
||||
|
||||
[Exposed=(Foo,Bar1)]
|
||||
interface mixin Mixin {
|
||||
undefined method5();
|
||||
};
|
||||
|
||||
Iface3 includes Mixin;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 6, "Should know about six things")
|
||||
iface = results[3]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should have an interface here")
|
||||
members = iface.members
|
||||
harness.check(len(members), 2, "Should have two members")
|
||||
|
||||
harness.ok(
|
||||
members[0].exposureSet == set(["Foo"]),
|
||||
"method4 should have the right exposure set",
|
||||
)
|
||||
harness.ok(
|
||||
members[0]._exposureGlobalNames == set(["Foo"]),
|
||||
"method4 should have the right exposure global names",
|
||||
)
|
||||
|
||||
harness.ok(
|
||||
members[1].exposureSet == set(["Foo", "Bar"]),
|
||||
"method5 should have the right exposure set",
|
||||
)
|
||||
harness.ok(
|
||||
members[1]._exposureGlobalNames == set(["Foo", "Bar1"]),
|
||||
"method5 should have the right exposure global names",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Exposed=Foo]
|
||||
interface Bar {
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown on invalid Exposed value on interface.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Bar {
|
||||
[Exposed=Foo]
|
||||
readonly attribute bool attr;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown on invalid Exposed value on attribute.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Bar {
|
||||
[Exposed=Foo]
|
||||
undefined operation();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown on invalid Exposed value on operation.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Bar {
|
||||
[Exposed=Foo]
|
||||
const long constant = 5;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown on invalid Exposed value on constant.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, Exposed=Foo] interface Foo {};
|
||||
[Global=Bar, Exposed=Bar] interface Bar {};
|
||||
|
||||
[Exposed=Foo]
|
||||
interface Baz {
|
||||
[Exposed=Bar]
|
||||
undefined method();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw, "Should have thrown on member exposed where its interface is not."
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, Exposed=Foo] interface Foo {};
|
||||
[Global=Bar, Exposed=Bar] interface Bar {};
|
||||
|
||||
[Exposed=Foo]
|
||||
interface Baz {
|
||||
undefined method();
|
||||
};
|
||||
|
||||
[Exposed=Bar]
|
||||
interface mixin Mixin {
|
||||
undefined otherMethod();
|
||||
};
|
||||
|
||||
Baz includes Mixin;
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.check(len(results), 5, "Should know about five things")
|
||||
iface = results[2]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should have an interface here")
|
||||
members = iface.members
|
||||
harness.check(len(members), 2, "Should have two members")
|
||||
|
||||
harness.ok(
|
||||
members[0].exposureSet == set(["Foo"]),
|
||||
"method should have the right exposure set",
|
||||
)
|
||||
harness.ok(
|
||||
members[0]._exposureGlobalNames == set(["Foo"]),
|
||||
"method should have the right exposure global names",
|
||||
)
|
||||
|
||||
harness.ok(
|
||||
members[1].exposureSet == set(["Bar"]),
|
||||
"otherMethod should have the right exposure set",
|
||||
)
|
||||
harness.ok(
|
||||
members[1]._exposureGlobalNames == set(["Bar"]),
|
||||
"otherMethod should have the right exposure global names",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, Exposed=Foo] interface Foo {};
|
||||
[Global=Bar, Exposed=Bar] interface Bar {};
|
||||
|
||||
[Exposed=*]
|
||||
interface Baz {
|
||||
undefined methodWild();
|
||||
};
|
||||
|
||||
[Exposed=Bar]
|
||||
interface mixin Mixin {
|
||||
undefined methodNotWild();
|
||||
};
|
||||
|
||||
Baz includes Mixin;
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.check(len(results), 5, "Should know about five things")
|
||||
iface = results[2]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should have an interface here")
|
||||
members = iface.members
|
||||
harness.check(len(members), 2, "Should have two members")
|
||||
|
||||
harness.ok(
|
||||
members[0].exposureSet == set(["Foo", "Bar"]),
|
||||
"methodWild should have the right exposure set",
|
||||
)
|
||||
harness.ok(
|
||||
members[0]._exposureGlobalNames == set(["Foo", "Bar"]),
|
||||
"methodWild should have the right exposure global names",
|
||||
)
|
||||
|
||||
harness.ok(
|
||||
members[1].exposureSet == set(["Bar"]),
|
||||
"methodNotWild should have the right exposure set",
|
||||
)
|
||||
harness.ok(
|
||||
members[1]._exposureGlobalNames == set(["Bar"]),
|
||||
"methodNotWild should have the right exposure global names",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, Exposed=Foo] interface Foo {};
|
||||
[Global=Bar, Exposed=Bar] interface Bar {};
|
||||
|
||||
[Exposed=Foo]
|
||||
interface Baz {
|
||||
[Exposed=*]
|
||||
undefined method();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw, "Should have thrown on member exposed where its interface is not."
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, Exposed=Foo] interface Foo {};
|
||||
[Global=Bar, Exposed=Bar] interface Bar {};
|
||||
|
||||
[Exposed=(Foo,*)]
|
||||
interface Baz {
|
||||
undefined method();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown on a wildcard in an identifier list.")
|
||||
131
third_party/WebIDL/tests/test_extended_attributes.py
vendored
Normal file
131
third_party/WebIDL/tests/test_extended_attributes.py
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
[LegacyNoInterfaceObject]
|
||||
interface TestExtendedAttr {
|
||||
[LegacyUnforgeable] readonly attribute byte b;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
[Pref="foo.bar",Pref=flop]
|
||||
interface TestExtendedAttr {
|
||||
[Pref="foo.bar"] attribute byte b;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestLegacyLenientThis {
|
||||
[LegacyLenientThis] attribute byte b;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
harness.ok(
|
||||
results[0].members[0].hasLegacyLenientThis(), "Should have a lenient this"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestLegacyLenientThis2 {
|
||||
[LegacyLenientThis=something] attribute byte b;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "[LegacyLenientThis] must take no arguments")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestClamp {
|
||||
undefined testClamp([Clamp] long foo);
|
||||
undefined testNotClamp(long foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
# Pull out the first argument out of the arglist of the first (and
|
||||
# only) signature.
|
||||
harness.ok(
|
||||
results[0].members[0].signatures()[0][1][0].type.hasClamp(), "Should be clamped"
|
||||
)
|
||||
harness.ok(
|
||||
not results[0].members[1].signatures()[0][1][0].type.hasClamp(),
|
||||
"Should not be clamped",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestClamp2 {
|
||||
undefined testClamp([Clamp=something] long foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "[Clamp] must take no arguments")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestEnforceRange {
|
||||
undefined testEnforceRange([EnforceRange] long foo);
|
||||
undefined testNotEnforceRange(long foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
# Pull out the first argument out of the arglist of the first (and
|
||||
# only) signature.
|
||||
harness.ok(
|
||||
results[0].members[0].signatures()[0][1][0].type.hasEnforceRange(),
|
||||
"Should be enforceRange",
|
||||
)
|
||||
harness.ok(
|
||||
not results[0].members[1].signatures()[0][1][0].type.hasEnforceRange(),
|
||||
"Should not be enforceRange",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestEnforceRange2 {
|
||||
undefined testEnforceRange([EnforceRange=something] long foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "[EnforceRange] must take no arguments")
|
||||
145
third_party/WebIDL/tests/test_float_types.py
vendored
Normal file
145
third_party/WebIDL/tests/test_float_types.py
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
typedef float myFloat;
|
||||
typedef unrestricted float myUnrestrictedFloat;
|
||||
interface FloatTypes {
|
||||
attribute float f;
|
||||
attribute unrestricted float uf;
|
||||
attribute double d;
|
||||
attribute unrestricted double ud;
|
||||
[LenientFloat]
|
||||
attribute float lf;
|
||||
[LenientFloat]
|
||||
attribute double ld;
|
||||
|
||||
undefined m1(float arg1, double arg2, float? arg3, double? arg4,
|
||||
myFloat arg5, unrestricted float arg6,
|
||||
unrestricted double arg7, unrestricted float? arg8,
|
||||
unrestricted double? arg9, myUnrestrictedFloat arg10);
|
||||
[LenientFloat]
|
||||
undefined m2(float arg1, double arg2, float? arg3, double? arg4,
|
||||
myFloat arg5, unrestricted float arg6,
|
||||
unrestricted double arg7, unrestricted float? arg8,
|
||||
unrestricted double? arg9, myUnrestrictedFloat arg10);
|
||||
[LenientFloat]
|
||||
undefined m3(float arg);
|
||||
[LenientFloat]
|
||||
undefined m4(double arg);
|
||||
[LenientFloat]
|
||||
undefined m5((float or FloatTypes) arg);
|
||||
[LenientFloat]
|
||||
undefined m6(sequence<float> arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.check(len(results), 3, "Should be two typedefs and one interface.")
|
||||
iface = results[2]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
types = [a.type for a in iface.members if a.isAttr()]
|
||||
harness.ok(types[0].isFloat(), "'float' is a float")
|
||||
harness.ok(not types[0].isUnrestricted(), "'float' is not unrestricted")
|
||||
harness.ok(types[1].isFloat(), "'unrestricted float' is a float")
|
||||
harness.ok(types[1].isUnrestricted(), "'unrestricted float' is unrestricted")
|
||||
harness.ok(types[2].isFloat(), "'double' is a float")
|
||||
harness.ok(not types[2].isUnrestricted(), "'double' is not unrestricted")
|
||||
harness.ok(types[3].isFloat(), "'unrestricted double' is a float")
|
||||
harness.ok(types[3].isUnrestricted(), "'unrestricted double' is unrestricted")
|
||||
|
||||
method = iface.members[6]
|
||||
harness.ok(isinstance(method, WebIDL.IDLMethod), "Should be an IDLMethod")
|
||||
argtypes = [a.type for a in method.signatures()[0][1]]
|
||||
for idx, type in enumerate(argtypes):
|
||||
harness.ok(type.isFloat(), "Type %d should be float" % idx)
|
||||
harness.check(
|
||||
type.isUnrestricted(),
|
||||
idx >= 5,
|
||||
"Type %d should %sbe unrestricted" % (idx, "" if idx >= 4 else "not "),
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface FloatTypes {
|
||||
[LenientFloat]
|
||||
long m(float arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "[LenientFloat] only allowed on methods returning undefined")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface FloatTypes {
|
||||
[LenientFloat]
|
||||
undefined m(unrestricted float arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "[LenientFloat] only allowed on methods with unrestricted float args"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface FloatTypes {
|
||||
[LenientFloat]
|
||||
undefined m(sequence<unrestricted float> arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "[LenientFloat] only allowed on methods with unrestricted float args (2)"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface FloatTypes {
|
||||
[LenientFloat]
|
||||
undefined m((unrestricted float or FloatTypes) arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "[LenientFloat] only allowed on methods with unrestricted float args (3)"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface FloatTypes {
|
||||
[LenientFloat]
|
||||
readonly attribute float foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "[LenientFloat] only allowed on writable attributes")
|
||||
15
third_party/WebIDL/tests/test_forward_decl.py
vendored
Normal file
15
third_party/WebIDL/tests/test_forward_decl.py
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface ForwardDeclared;
|
||||
interface ForwardDeclared;
|
||||
|
||||
interface TestForwardDecl {
|
||||
attribute ForwardDeclared foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
|
||||
harness.ok(True, "TestForwardDeclared interface parsed without error.")
|
||||
151
third_party/WebIDL/tests/test_global_extended_attr.py
vendored
Normal file
151
third_party/WebIDL/tests/test_global_extended_attr.py
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, Exposed=Foo]
|
||||
interface Foo : Bar {
|
||||
getter any(DOMString name);
|
||||
};
|
||||
[Exposed=Foo]
|
||||
interface Bar {};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(
|
||||
results[0].isOnGlobalProtoChain(),
|
||||
"[Global] interface should be on global's proto chain",
|
||||
)
|
||||
harness.ok(
|
||||
results[1].isOnGlobalProtoChain(),
|
||||
"[Global] interface should be on global's proto chain",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, Exposed=Foo]
|
||||
interface Foo {
|
||||
getter any(DOMString name);
|
||||
setter undefined(DOMString name, any arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should have thrown for [Global] used on an interface with a " "named setter",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, Exposed=Foo]
|
||||
interface Foo {
|
||||
getter any(DOMString name);
|
||||
deleter undefined(DOMString name);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should have thrown for [Global] used on an interface with a " "named deleter",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, LegacyOverrideBuiltIns, Exposed=Foo]
|
||||
interface Foo {
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should have thrown for [Global] used on an interface with a "
|
||||
"[LegacyOverrideBuiltIns]",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, Exposed=Foo]
|
||||
interface Foo : Bar {
|
||||
};
|
||||
[LegacyOverrideBuiltIns, Exposed=Foo]
|
||||
interface Bar {
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should have thrown for [Global] used on an interface with an "
|
||||
"[LegacyOverrideBuiltIns] ancestor",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Foo, Exposed=Foo]
|
||||
interface Foo {
|
||||
};
|
||||
[Exposed=Foo]
|
||||
interface Bar : Foo {
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should have thrown for [Global] used on an interface with a " "descendant",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global, Exposed=Foo]
|
||||
interface Foo {
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should have thrown for [Global] without a right hand side value",
|
||||
)
|
||||
45
third_party/WebIDL/tests/test_identifier_conflict.py
vendored
Normal file
45
third_party/WebIDL/tests/test_identifier_conflict.py
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
enum Foo { "a" };
|
||||
interface Foo;
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
harness.ok(False, "Should fail to parse")
|
||||
except Exception as e:
|
||||
harness.ok(
|
||||
"Name collision" in str(e), "Should have name collision for interface"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Foo { long x; };
|
||||
enum Foo { "a" };
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
harness.ok(False, "Should fail to parse")
|
||||
except Exception as e:
|
||||
harness.ok(
|
||||
"Name collision" in str(e), "Should have name collision for dictionary"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
enum Foo { "a" };
|
||||
enum Foo { "b" };
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
harness.ok(False, "Should fail to parse")
|
||||
except Exception as e:
|
||||
harness.ok(
|
||||
"Multiple unresolvable definitions" in str(e),
|
||||
"Should have name collision for dictionary",
|
||||
)
|
||||
18
third_party/WebIDL/tests/test_incomplete_parent.py
vendored
Normal file
18
third_party/WebIDL/tests/test_incomplete_parent.py
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestIncompleteParent : NotYetDefined {
|
||||
undefined foo();
|
||||
};
|
||||
|
||||
interface NotYetDefined : EvenHigherOnTheChain {
|
||||
};
|
||||
|
||||
interface EvenHigherOnTheChain {
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
|
||||
harness.ok(True, "TestIncompleteParent interface parsed without error.")
|
||||
61
third_party/WebIDL/tests/test_incomplete_types.py
vendored
Normal file
61
third_party/WebIDL/tests/test_incomplete_types.py
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestIncompleteTypes {
|
||||
attribute FooInterface attr1;
|
||||
|
||||
FooInterface method1(FooInterface arg);
|
||||
};
|
||||
|
||||
interface FooInterface {
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestIncompleteTypes interface parsed without error.")
|
||||
harness.check(len(results), 2, "Should be two productions.")
|
||||
iface = results[0]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
harness.check(
|
||||
iface.identifier.QName(),
|
||||
"::TestIncompleteTypes",
|
||||
"Interface has the right QName",
|
||||
)
|
||||
harness.check(
|
||||
iface.identifier.name, "TestIncompleteTypes", "Interface has the right name"
|
||||
)
|
||||
harness.check(len(iface.members), 2, "Expect 2 members")
|
||||
|
||||
attr = iface.members[0]
|
||||
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
|
||||
method = iface.members[1]
|
||||
harness.ok(isinstance(method, WebIDL.IDLMethod), "Should be an IDLMethod")
|
||||
|
||||
harness.check(
|
||||
attr.identifier.QName(),
|
||||
"::TestIncompleteTypes::attr1",
|
||||
"Attribute has the right QName",
|
||||
)
|
||||
harness.check(
|
||||
attr.type.name, "FooInterface", "Previously unresolved type has the right name"
|
||||
)
|
||||
|
||||
harness.check(
|
||||
method.identifier.QName(),
|
||||
"::TestIncompleteTypes::method1",
|
||||
"Attribute has the right QName",
|
||||
)
|
||||
(returnType, args) = method.signatures()[0]
|
||||
harness.check(
|
||||
returnType.name, "FooInterface", "Previously unresolved type has the right name"
|
||||
)
|
||||
harness.check(
|
||||
args[0].type.name,
|
||||
"FooInterface",
|
||||
"Previously unresolved type has the right name",
|
||||
)
|
||||
459
third_party/WebIDL/tests/test_interface.py
vendored
Normal file
459
third_party/WebIDL/tests/test_interface.py
vendored
Normal file
@@ -0,0 +1,459 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("interface Foo { };")
|
||||
results = parser.finish()
|
||||
harness.ok(True, "Empty interface parsed without error.")
|
||||
harness.check(len(results), 1, "Should be one production")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
iface = results[0]
|
||||
harness.check(iface.identifier.QName(), "::Foo", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "Foo", "Interface has the right name")
|
||||
harness.check(iface.parent, None, "Interface has no parent")
|
||||
|
||||
parser.parse("interface Bar : Foo { };")
|
||||
results = parser.finish()
|
||||
harness.ok(True, "Empty interface parsed without error.")
|
||||
harness.check(len(results), 2, "Should be two productions")
|
||||
harness.ok(isinstance(results[1], WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
iface = results[1]
|
||||
harness.check(iface.identifier.QName(), "::Bar", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "Bar", "Interface has the right name")
|
||||
harness.ok(isinstance(iface.parent, WebIDL.IDLInterface), "Interface has a parent")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface QNameBase {
|
||||
attribute long foo;
|
||||
};
|
||||
|
||||
interface QNameDerived : QNameBase {
|
||||
attribute long long foo;
|
||||
attribute byte bar;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 2, "Should be two productions")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
harness.ok(isinstance(results[1], WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
harness.check(results[1].parent, results[0], "Inheritance chain is right")
|
||||
harness.check(len(results[0].members), 1, "Expect 1 productions")
|
||||
harness.check(len(results[1].members), 2, "Expect 2 productions")
|
||||
base = results[0]
|
||||
derived = results[1]
|
||||
harness.check(
|
||||
base.members[0].identifier.QName(),
|
||||
"::QNameBase::foo",
|
||||
"Member has the right QName",
|
||||
)
|
||||
harness.check(
|
||||
derived.members[0].identifier.QName(),
|
||||
"::QNameDerived::foo",
|
||||
"Member has the right QName",
|
||||
)
|
||||
harness.check(
|
||||
derived.members[1].identifier.QName(),
|
||||
"::QNameDerived::bar",
|
||||
"Member has the right QName",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A : B {};
|
||||
interface B : A {};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow cycles in interface inheritance chains")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A : C {};
|
||||
interface C : B {};
|
||||
interface B : A {};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw, "Should not allow indirect cycles in interface inheritance chains"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A;
|
||||
interface B : A {};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should not allow inheriting from an interface that is only forward declared",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
constructor();
|
||||
constructor(long arg);
|
||||
readonly attribute boolean x;
|
||||
undefined foo();
|
||||
};
|
||||
partial interface A {
|
||||
readonly attribute boolean y;
|
||||
undefined foo(long arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 2, "Should have two results with partial interface")
|
||||
iface = results[0]
|
||||
harness.check(
|
||||
len(iface.members), 3, "Should have three members with partial interface"
|
||||
)
|
||||
harness.check(
|
||||
iface.members[0].identifier.name,
|
||||
"x",
|
||||
"First member should be x with partial interface",
|
||||
)
|
||||
harness.check(
|
||||
iface.members[1].identifier.name,
|
||||
"foo",
|
||||
"Second member should be foo with partial interface",
|
||||
)
|
||||
harness.check(
|
||||
len(iface.members[1].signatures()),
|
||||
2,
|
||||
"Should have two foo signatures with partial interface",
|
||||
)
|
||||
harness.check(
|
||||
iface.members[2].identifier.name,
|
||||
"y",
|
||||
"Third member should be y with partial interface",
|
||||
)
|
||||
harness.check(
|
||||
len(iface.ctor().signatures()),
|
||||
2,
|
||||
"Should have two constructors with partial interface",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
partial interface A {
|
||||
readonly attribute boolean y;
|
||||
undefined foo(long arg);
|
||||
};
|
||||
interface A {
|
||||
constructor();
|
||||
constructor(long arg);
|
||||
readonly attribute boolean x;
|
||||
undefined foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(
|
||||
len(results), 2, "Should have two results with reversed partial interface"
|
||||
)
|
||||
iface = results[1]
|
||||
harness.check(
|
||||
len(iface.members),
|
||||
3,
|
||||
"Should have three members with reversed partial interface",
|
||||
)
|
||||
harness.check(
|
||||
iface.members[0].identifier.name,
|
||||
"x",
|
||||
"First member should be x with reversed partial interface",
|
||||
)
|
||||
harness.check(
|
||||
iface.members[1].identifier.name,
|
||||
"foo",
|
||||
"Second member should be foo with reversed partial interface",
|
||||
)
|
||||
harness.check(
|
||||
len(iface.members[1].signatures()),
|
||||
2,
|
||||
"Should have two foo signatures with reversed partial interface",
|
||||
)
|
||||
harness.check(
|
||||
iface.members[2].identifier.name,
|
||||
"y",
|
||||
"Third member should be y with reversed partial interface",
|
||||
)
|
||||
harness.check(
|
||||
len(iface.ctor().signatures()),
|
||||
2,
|
||||
"Should have two constructors with reversed partial interface",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
readonly attribute boolean x;
|
||||
};
|
||||
interface A {
|
||||
readonly attribute boolean y;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow two non-partial interfaces with the same name")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
partial interface A {
|
||||
readonly attribute boolean x;
|
||||
};
|
||||
partial interface A {
|
||||
readonly attribute boolean y;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Must have a non-partial interface for a given name")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
boolean x;
|
||||
};
|
||||
partial interface A {
|
||||
readonly attribute boolean y;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should not allow a name collision between partial interface "
|
||||
"and other object",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
boolean x;
|
||||
};
|
||||
interface A {
|
||||
readonly attribute boolean y;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "Should not allow a name collision between interface " "and other object"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
boolean x;
|
||||
};
|
||||
interface A;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should not allow a name collision between external interface "
|
||||
"and other object",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
readonly attribute boolean x;
|
||||
};
|
||||
interface A;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should not allow a name collision between external interface " "and interface",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface A;
|
||||
interface A;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.ok(
|
||||
len(results) == 1 and isinstance(results[0], WebIDL.IDLExternalInterface),
|
||||
"Should allow name collisions between external interface " "declarations",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[SomeRandomAnnotation]
|
||||
interface A {
|
||||
readonly attribute boolean y;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow unknown extended attributes on interfaces")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Window, Exposed=Window] interface Window {};
|
||||
[Exposed=Window, LegacyWindowAlias=A]
|
||||
interface B {};
|
||||
[Exposed=Window, LegacyWindowAlias=(C, D)]
|
||||
interface E {};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(
|
||||
results[1].legacyWindowAliases, ["A"], "Should support a single identifier"
|
||||
)
|
||||
harness.check(
|
||||
results[2].legacyWindowAliases, ["C", "D"], "Should support an identifier list"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[LegacyWindowAlias]
|
||||
interface A {};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow [LegacyWindowAlias] with no value")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Exposed=Worker, LegacyWindowAlias=B]
|
||||
interface A {};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow [LegacyWindowAlias] without Window exposure")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Window, Exposed=Window] interface Window {};
|
||||
[Exposed=Window]
|
||||
interface A {};
|
||||
[Exposed=Window, LegacyWindowAlias=A]
|
||||
interface B {};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "Should not allow [LegacyWindowAlias] to conflict with other identifiers"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Window, Exposed=Window] interface Window {};
|
||||
[Exposed=Window, LegacyWindowAlias=A]
|
||||
interface B {};
|
||||
[Exposed=Window]
|
||||
interface A {};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "Should not allow [LegacyWindowAlias] to conflict with other identifiers"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Window, Exposed=Window] interface Window {};
|
||||
[Exposed=Window, LegacyWindowAlias=A]
|
||||
interface B {};
|
||||
[Exposed=Window, LegacyWindowAlias=A]
|
||||
interface C {};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "Should not allow [LegacyWindowAlias] to conflict with other identifiers"
|
||||
)
|
||||
20
third_party/WebIDL/tests/test_interface_const_identifier_conflicts.py
vendored
Normal file
20
third_party/WebIDL/tests/test_interface_const_identifier_conflicts.py
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface IdentifierConflict {
|
||||
const byte thing1 = 1;
|
||||
const unsigned long thing1 = 1;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
171
third_party/WebIDL/tests/test_interface_identifier_conflicts_across_members.py
vendored
Normal file
171
third_party/WebIDL/tests/test_interface_identifier_conflicts_across_members.py
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface IdentifierConflictAcrossMembers1 {
|
||||
const byte thing1 = 1;
|
||||
readonly attribute long thing1;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers1.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface IdentifierConflictAcrossMembers2 {
|
||||
readonly attribute long thing1;
|
||||
const byte thing1 = 1;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers2.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface IdentifierConflictAcrossMembers3 {
|
||||
getter boolean thing1(DOMString name);
|
||||
readonly attribute long thing1;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers3.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface IdentifierConflictAcrossMembers4 {
|
||||
const byte thing1 = 1;
|
||||
long thing1();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers4.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface IdentifierConflictAcrossMembers5 {
|
||||
static long thing1();
|
||||
undefined thing1();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
not threw, "Should not have thrown for IdentifierConflictAcrossMembers5."
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin IdentifierConflictAcrossMembers6Mixin {
|
||||
undefined thing1();
|
||||
};
|
||||
interface IdentifierConflictAcrossMembers6 {
|
||||
static long thing1();
|
||||
};
|
||||
IdentifierConflictAcrossMembers6 includes IdentifierConflictAcrossMembers6Mixin;
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
not threw, "Should not have thrown for IdentifierConflictAcrossMembers6."
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface IdentifierConflictAcrossMembers7 {
|
||||
const byte thing1 = 1;
|
||||
static readonly attribute long thing1;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers7.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface IdentifierConflictAcrossMembers8 {
|
||||
readonly attribute long thing1 = 1;
|
||||
static readonly attribute long thing1;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers8.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface IdentifierConflictAcrossMembers9 {
|
||||
void thing1();
|
||||
static readonly attribute long thing1;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers9.")
|
||||
935
third_party/WebIDL/tests/test_interface_maplikesetlikeiterable.py
vendored
Normal file
935
third_party/WebIDL/tests/test_interface_maplikesetlikeiterable.py
vendored
Normal file
@@ -0,0 +1,935 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
def shouldPass(prefix, iface, expectedMembers, numProductions=1):
|
||||
p = parser.reset()
|
||||
p.parse(iface)
|
||||
results = p.finish()
|
||||
harness.check(
|
||||
len(results),
|
||||
numProductions,
|
||||
"%s - Should have production count %d" % (prefix, numProductions),
|
||||
)
|
||||
harness.ok(
|
||||
isinstance(results[0], WebIDL.IDLInterface),
|
||||
"%s - Should be an IDLInterface" % (prefix),
|
||||
)
|
||||
# Make a copy, since we plan to modify it
|
||||
expectedMembers = list(expectedMembers)
|
||||
for m in results[0].members:
|
||||
name = m.identifier.name
|
||||
if m.isMethod() and m.isStatic():
|
||||
# None of the expected members are static methods, so ignore those.
|
||||
harness.ok(True, "%s - %s - Should be a %s" % (prefix, name, type(m)))
|
||||
elif (name, type(m)) in expectedMembers:
|
||||
harness.ok(True, "%s - %s - Should be a %s" % (prefix, name, type(m)))
|
||||
expectedMembers.remove((name, type(m)))
|
||||
else:
|
||||
harness.ok(
|
||||
False,
|
||||
"%s - %s - Unknown symbol of type %s" % (prefix, name, type(m)),
|
||||
)
|
||||
# A bit of a hoop because we can't generate the error string if we pass
|
||||
if len(expectedMembers) == 0:
|
||||
harness.ok(True, "Found all the members")
|
||||
else:
|
||||
harness.ok(
|
||||
False,
|
||||
"Expected member not found: %s of type %s"
|
||||
% (expectedMembers[0][0], expectedMembers[0][1]),
|
||||
)
|
||||
return results
|
||||
|
||||
def shouldFail(prefix, iface):
|
||||
try:
|
||||
p = parser.reset()
|
||||
p.parse(iface)
|
||||
p.finish()
|
||||
harness.ok(False, prefix + " - Interface passed when should've failed")
|
||||
except WebIDL.WebIDLError:
|
||||
harness.ok(True, prefix + " - Interface failed as expected")
|
||||
except Exception as e:
|
||||
harness.ok(
|
||||
False,
|
||||
prefix
|
||||
+ " - Interface failed but not as a WebIDLError exception: %s" % e,
|
||||
)
|
||||
|
||||
iterableMembers = [
|
||||
(x, WebIDL.IDLMethod) for x in ["entries", "keys", "values", "forEach"]
|
||||
]
|
||||
setROMembers = (
|
||||
[(x, WebIDL.IDLMethod) for x in ["has"]]
|
||||
+ [("__setlike", WebIDL.IDLMaplikeOrSetlike)]
|
||||
+ iterableMembers
|
||||
)
|
||||
setROMembers.extend([("size", WebIDL.IDLAttribute)])
|
||||
setRWMembers = [
|
||||
(x, WebIDL.IDLMethod) for x in ["add", "clear", "delete"]
|
||||
] + setROMembers
|
||||
mapROMembers = (
|
||||
[(x, WebIDL.IDLMethod) for x in ["get", "has"]]
|
||||
+ [("__maplike", WebIDL.IDLMaplikeOrSetlike)]
|
||||
+ iterableMembers
|
||||
)
|
||||
mapROMembers.extend([("size", WebIDL.IDLAttribute)])
|
||||
mapRWMembers = [
|
||||
(x, WebIDL.IDLMethod) for x in ["set", "clear", "delete"]
|
||||
] + mapROMembers
|
||||
|
||||
# OK, now that we've used iterableMembers to set up the above, append
|
||||
# __iterable to it for the iterable<> case.
|
||||
iterableMembers.append(("__iterable", WebIDL.IDLIterable))
|
||||
|
||||
asyncIterableMembers = [
|
||||
(x, WebIDL.IDLMethod) for x in ["entries", "keys", "values"]
|
||||
]
|
||||
asyncIterableMembers.append(("__iterable", WebIDL.IDLAsyncIterable))
|
||||
|
||||
valueIterableMembers = [("__iterable", WebIDL.IDLIterable)]
|
||||
valueIterableMembers.append(("__indexedgetter", WebIDL.IDLMethod))
|
||||
valueIterableMembers.append(("length", WebIDL.IDLAttribute))
|
||||
|
||||
valueAsyncIterableMembers = [("__iterable", WebIDL.IDLAsyncIterable)]
|
||||
valueAsyncIterableMembers.append(("values", WebIDL.IDLMethod))
|
||||
|
||||
disallowedIterableNames = [
|
||||
("keys", WebIDL.IDLMethod),
|
||||
("entries", WebIDL.IDLMethod),
|
||||
("values", WebIDL.IDLMethod),
|
||||
]
|
||||
disallowedMemberNames = [
|
||||
("forEach", WebIDL.IDLMethod),
|
||||
("has", WebIDL.IDLMethod),
|
||||
("size", WebIDL.IDLAttribute),
|
||||
] + disallowedIterableNames
|
||||
mapDisallowedMemberNames = [("get", WebIDL.IDLMethod)] + disallowedMemberNames
|
||||
disallowedNonMethodNames = [
|
||||
("clear", WebIDL.IDLMethod),
|
||||
("delete", WebIDL.IDLMethod),
|
||||
]
|
||||
mapDisallowedNonMethodNames = [("set", WebIDL.IDLMethod)] + disallowedNonMethodNames
|
||||
setDisallowedNonMethodNames = [("add", WebIDL.IDLMethod)] + disallowedNonMethodNames
|
||||
unrelatedMembers = [
|
||||
("unrelatedAttribute", WebIDL.IDLAttribute),
|
||||
("unrelatedMethod", WebIDL.IDLMethod),
|
||||
]
|
||||
|
||||
#
|
||||
# Simple Usage Tests
|
||||
#
|
||||
|
||||
shouldPass(
|
||||
"Iterable (key only)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
iterable<long>;
|
||||
readonly attribute unsigned long length;
|
||||
getter long(unsigned long index);
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
valueIterableMembers + unrelatedMembers,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Iterable (key only) inheriting from parent",
|
||||
"""
|
||||
interface Foo1 : Foo2 {
|
||||
iterable<long>;
|
||||
readonly attribute unsigned long length;
|
||||
getter long(unsigned long index);
|
||||
};
|
||||
interface Foo2 {
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
valueIterableMembers,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Iterable (key and value)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
iterable<long, long>;
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
iterableMembers + unrelatedMembers,
|
||||
# numProductions == 2 because of the generated iterator iface,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Iterable (key and value) inheriting from parent",
|
||||
"""
|
||||
interface Foo1 : Foo2 {
|
||||
iterable<long, long>;
|
||||
};
|
||||
interface Foo2 {
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
iterableMembers,
|
||||
# numProductions == 3 because of the generated iterator iface,
|
||||
numProductions=3,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Async iterable (key only)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long>;
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
valueAsyncIterableMembers + unrelatedMembers,
|
||||
# numProductions == 2 because of the generated iterator iface,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Async iterable (key only) inheriting from parent",
|
||||
"""
|
||||
interface Foo1 : Foo2 {
|
||||
async iterable<long>;
|
||||
};
|
||||
interface Foo2 {
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
valueAsyncIterableMembers,
|
||||
# numProductions == 3 because of the generated iterator iface,
|
||||
numProductions=3,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Async iterable with argument (key only)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long>(optional long foo);
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
valueAsyncIterableMembers + unrelatedMembers,
|
||||
# numProductions == 2 because of the generated iterator iface,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Async iterable (key and value)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long, long>;
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
asyncIterableMembers + unrelatedMembers,
|
||||
# numProductions == 2 because of the generated iterator iface,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Async iterable (key and value) inheriting from parent",
|
||||
"""
|
||||
interface Foo1 : Foo2 {
|
||||
async iterable<long, long>;
|
||||
};
|
||||
interface Foo2 {
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
asyncIterableMembers,
|
||||
# numProductions == 3 because of the generated iterator iface,
|
||||
numProductions=3,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Async iterable with argument (key and value)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long, long>(optional long foo);
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
asyncIterableMembers + unrelatedMembers,
|
||||
# numProductions == 2 because of the generated iterator iface,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Maplike (readwrite)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
mapRWMembers + unrelatedMembers,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Maplike (readwrite) inheriting from parent",
|
||||
"""
|
||||
interface Foo1 : Foo2 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface Foo2 {
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
mapRWMembers,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Maplike (readwrite)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
mapRWMembers + unrelatedMembers,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Maplike (readwrite) inheriting from parent",
|
||||
"""
|
||||
interface Foo1 : Foo2 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface Foo2 {
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
mapRWMembers,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Maplike (readonly)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
readonly maplike<long, long>;
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
mapROMembers + unrelatedMembers,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Maplike (readonly) inheriting from parent",
|
||||
"""
|
||||
interface Foo1 : Foo2 {
|
||||
readonly maplike<long, long>;
|
||||
};
|
||||
interface Foo2 {
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
mapROMembers,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Setlike (readwrite)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
setlike<long>;
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
setRWMembers + unrelatedMembers,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Setlike (readwrite) inheriting from parent",
|
||||
"""
|
||||
interface Foo1 : Foo2 {
|
||||
setlike<long>;
|
||||
};
|
||||
interface Foo2 {
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
setRWMembers,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Setlike (readonly)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
readonly setlike<long>;
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
setROMembers + unrelatedMembers,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Setlike (readonly) inheriting from parent",
|
||||
"""
|
||||
interface Foo1 : Foo2 {
|
||||
readonly setlike<long>;
|
||||
};
|
||||
interface Foo2 {
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
setROMembers,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Inheritance of maplike/setlike",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
};
|
||||
""",
|
||||
mapRWMembers,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"JS Implemented maplike interface",
|
||||
"""
|
||||
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
|
||||
interface Foo1 {
|
||||
constructor();
|
||||
setlike<long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"JS Implemented maplike interface",
|
||||
"""
|
||||
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
|
||||
interface Foo1 {
|
||||
constructor();
|
||||
maplike<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
#
|
||||
# Multiple maplike/setlike tests
|
||||
#
|
||||
|
||||
shouldFail(
|
||||
"Two maplike/setlikes on same interface",
|
||||
"""
|
||||
interface Foo1 {
|
||||
setlike<long>;
|
||||
maplike<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Two iterable/setlikes on same interface",
|
||||
"""
|
||||
interface Foo1 {
|
||||
iterable<long>;
|
||||
maplike<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Two iterables on same interface",
|
||||
"""
|
||||
interface Foo1 {
|
||||
iterable<long>;
|
||||
iterable<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Two iterables on same interface",
|
||||
"""
|
||||
interface Foo1 {
|
||||
iterable<long>;
|
||||
async iterable<long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Two iterables on same interface",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long>;
|
||||
async iterable<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Async iterable with non-optional arguments",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long>(long foo);
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Async iterable with non-optional arguments",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long>(optional long foo, long bar);
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Async iterable with non-optional arguments",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long, long>(long foo);
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Two maplike/setlikes in partials",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
partial interface Foo1 {
|
||||
setlike<long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Conflicting maplike/setlikes across inheritance",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
setlike<long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Conflicting maplike/iterable across inheritance",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
iterable<long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Conflicting maplike/setlikes across multistep inheritance",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
};
|
||||
interface Foo3 : Foo2 {
|
||||
setlike<long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
#
|
||||
# Member name collision tests
|
||||
#
|
||||
|
||||
def testConflictingMembers(
|
||||
likeMember, conflict, expectedMembers, methodPasses, numProductions=1
|
||||
):
|
||||
"""
|
||||
Tests for maplike/setlike member generation against conflicting member
|
||||
names. If methodPasses is True, this means we expect the interface to
|
||||
pass in the case of method shadowing, and expectedMembers should be the
|
||||
list of interface members to check against on the passing interface.
|
||||
|
||||
"""
|
||||
(conflictName, conflictType) = conflict
|
||||
if methodPasses:
|
||||
shouldPass(
|
||||
"Conflicting method: %s and %s" % (likeMember, conflictName),
|
||||
"""
|
||||
interface Foo1 {
|
||||
%s;
|
||||
[Throws]
|
||||
undefined %s(long test1, double test2, double test3);
|
||||
};
|
||||
"""
|
||||
% (likeMember, conflictName),
|
||||
expectedMembers,
|
||||
)
|
||||
else:
|
||||
shouldFail(
|
||||
"Conflicting method: %s and %s" % (likeMember, conflictName),
|
||||
"""
|
||||
interface Foo1 {
|
||||
%s;
|
||||
[Throws]
|
||||
undefined %s(long test1, double test2, double test3);
|
||||
};
|
||||
"""
|
||||
% (likeMember, conflictName),
|
||||
)
|
||||
# Inherited conflicting methods should ALWAYS fail
|
||||
shouldFail(
|
||||
"Conflicting inherited method: %s and %s" % (likeMember, conflictName),
|
||||
"""
|
||||
interface Foo1 {
|
||||
undefined %s(long test1, double test2, double test3);
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
%s;
|
||||
};
|
||||
"""
|
||||
% (conflictName, likeMember),
|
||||
)
|
||||
if conflictType == WebIDL.IDLAttribute:
|
||||
shouldFail(
|
||||
"Conflicting static method: %s and %s" % (likeMember, conflictName),
|
||||
"""
|
||||
interface Foo1 {
|
||||
%s;
|
||||
static undefined %s(long test1, double test2, double test3);
|
||||
};
|
||||
"""
|
||||
% (likeMember, conflictName),
|
||||
)
|
||||
else:
|
||||
shouldPass(
|
||||
"Conflicting static method: %s and %s" % (likeMember, conflictName),
|
||||
"""
|
||||
interface Foo1 {
|
||||
%s;
|
||||
static undefined %s(long test1, double test2, double test3);
|
||||
};
|
||||
"""
|
||||
% (likeMember, conflictName),
|
||||
expectedMembers,
|
||||
numProductions=numProductions,
|
||||
)
|
||||
shouldFail(
|
||||
"Conflicting attribute: %s and %s" % (likeMember, conflictName),
|
||||
"""
|
||||
interface Foo1 {
|
||||
%s
|
||||
attribute double %s;
|
||||
};
|
||||
"""
|
||||
% (likeMember, conflictName),
|
||||
)
|
||||
shouldFail(
|
||||
"Conflicting const: %s and %s" % (likeMember, conflictName),
|
||||
"""
|
||||
interface Foo1 {
|
||||
%s;
|
||||
const double %s = 0;
|
||||
};
|
||||
"""
|
||||
% (likeMember, conflictName),
|
||||
)
|
||||
shouldFail(
|
||||
"Conflicting static attribute: %s and %s" % (likeMember, conflictName),
|
||||
"""
|
||||
interface Foo1 {
|
||||
%s;
|
||||
static attribute long %s;
|
||||
};
|
||||
"""
|
||||
% (likeMember, conflictName),
|
||||
)
|
||||
|
||||
for member in disallowedIterableNames:
|
||||
testConflictingMembers(
|
||||
"iterable<long, long>", member, iterableMembers, False, numProductions=2
|
||||
)
|
||||
for member in mapDisallowedMemberNames:
|
||||
testConflictingMembers("maplike<long, long>", member, mapRWMembers, False)
|
||||
for member in disallowedMemberNames:
|
||||
testConflictingMembers("setlike<long>", member, setRWMembers, False)
|
||||
for member in mapDisallowedNonMethodNames:
|
||||
testConflictingMembers("maplike<long, long>", member, mapRWMembers, True)
|
||||
for member in setDisallowedNonMethodNames:
|
||||
testConflictingMembers("setlike<long>", member, setRWMembers, True)
|
||||
|
||||
shouldPass(
|
||||
"Inheritance of maplike/setlike with child member collision",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
undefined entries();
|
||||
};
|
||||
""",
|
||||
mapRWMembers,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Inheritance of multi-level maplike/setlike with child member collision",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
};
|
||||
interface Foo3 : Foo2 {
|
||||
undefined entries();
|
||||
};
|
||||
""",
|
||||
mapRWMembers,
|
||||
numProductions=3,
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Maplike interface with mixin member collision",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface mixin Foo2 {
|
||||
undefined entries();
|
||||
};
|
||||
Foo1 includes Foo2;
|
||||
""",
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Inherited Maplike interface with consequential interface member collision",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface mixin Foo2 {
|
||||
undefined entries();
|
||||
};
|
||||
interface Foo3 : Foo1 {
|
||||
};
|
||||
Foo3 includes Foo2;
|
||||
""",
|
||||
mapRWMembers,
|
||||
numProductions=4,
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Inheritance of name collision with child maplike/setlike",
|
||||
"""
|
||||
interface Foo1 {
|
||||
undefined entries();
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Inheritance of multi-level name collision with child maplike/setlike",
|
||||
"""
|
||||
interface Foo1 {
|
||||
undefined entries();
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
};
|
||||
interface Foo3 : Foo2 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Inheritance of attribute collision with parent maplike/setlike",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
attribute double size;
|
||||
};
|
||||
""",
|
||||
mapRWMembers,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Inheritance of multi-level attribute collision with parent maplike/setlike",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
};
|
||||
interface Foo3 : Foo2 {
|
||||
attribute double size;
|
||||
};
|
||||
""",
|
||||
mapRWMembers,
|
||||
numProductions=3,
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Inheritance of attribute collision with child maplike/setlike",
|
||||
"""
|
||||
interface Foo1 {
|
||||
attribute double size;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Inheritance of multi-level attribute collision with child maplike/setlike",
|
||||
"""
|
||||
interface Foo1 {
|
||||
attribute double size;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
};
|
||||
interface Foo3 : Foo2 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Inheritance of attribute/rw function collision with child maplike/setlike",
|
||||
"""
|
||||
interface Foo1 {
|
||||
attribute double set;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Inheritance of const/rw function collision with child maplike/setlike",
|
||||
"""
|
||||
interface Foo1 {
|
||||
const double set = 0;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Inheritance of rw function with same name in child maplike/setlike",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
undefined clear();
|
||||
};
|
||||
""",
|
||||
mapRWMembers,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Inheritance of unforgeable attribute collision with child maplike/setlike",
|
||||
"""
|
||||
interface Foo1 {
|
||||
[LegacyUnforgeable]
|
||||
attribute double size;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Inheritance of multi-level unforgeable attribute collision with child maplike/setlike",
|
||||
"""
|
||||
interface Foo1 {
|
||||
[LegacyUnforgeable]
|
||||
attribute double size;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
};
|
||||
interface Foo3 : Foo2 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Interface with readonly allowable overrides",
|
||||
"""
|
||||
interface Foo1 {
|
||||
readonly setlike<long>;
|
||||
readonly attribute boolean clear;
|
||||
};
|
||||
""",
|
||||
setROMembers + [("clear", WebIDL.IDLAttribute)],
|
||||
)
|
||||
|
||||
r = shouldPass(
|
||||
"Check proper override of clear/delete/set",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
long clear(long a, long b, double c, double d);
|
||||
long set(long a, long b, double c, double d);
|
||||
long delete(long a, long b, double c, double d);
|
||||
};
|
||||
""",
|
||||
mapRWMembers,
|
||||
)
|
||||
|
||||
for m in r[0].members:
|
||||
if m.identifier.name in ["clear", "set", "delete"]:
|
||||
harness.ok(m.isMethod(), "%s should be a method" % m.identifier.name)
|
||||
harness.check(
|
||||
m.maxArgCount, 4, "%s should have 4 arguments" % m.identifier.name
|
||||
)
|
||||
harness.ok(
|
||||
not m.isMaplikeOrSetlikeOrIterableMethod(),
|
||||
"%s should not be a maplike/setlike function" % m.identifier.name,
|
||||
)
|
||||
534
third_party/WebIDL/tests/test_interfacemixin.py
vendored
Normal file
534
third_party/WebIDL/tests/test_interfacemixin.py
vendored
Normal file
@@ -0,0 +1,534 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("interface mixin Foo { };")
|
||||
results = parser.finish()
|
||||
harness.ok(True, "Empty interface mixin parsed without error.")
|
||||
harness.check(len(results), 1, "Should be one production")
|
||||
harness.ok(
|
||||
isinstance(results[0], WebIDL.IDLInterfaceMixin),
|
||||
"Should be an IDLInterfaceMixin",
|
||||
)
|
||||
mixin = results[0]
|
||||
harness.check(
|
||||
mixin.identifier.QName(), "::Foo", "Interface mixin has the right QName"
|
||||
)
|
||||
harness.check(mixin.identifier.name, "Foo", "Interface mixin has the right name")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin QNameBase {
|
||||
const long foo = 3;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 1, "Should be one productions")
|
||||
harness.ok(
|
||||
isinstance(results[0], WebIDL.IDLInterfaceMixin),
|
||||
"Should be an IDLInterfaceMixin",
|
||||
)
|
||||
harness.check(len(results[0].members), 1, "Expect 1 productions")
|
||||
mixin = results[0]
|
||||
harness.check(
|
||||
mixin.members[0].identifier.QName(),
|
||||
"::QNameBase::foo",
|
||||
"Member has the right QName",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin A {
|
||||
readonly attribute boolean x;
|
||||
undefined foo();
|
||||
};
|
||||
partial interface mixin A {
|
||||
readonly attribute boolean y;
|
||||
undefined foo(long arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(
|
||||
len(results), 2, "Should have two results with partial interface mixin"
|
||||
)
|
||||
mixin = results[0]
|
||||
harness.check(
|
||||
len(mixin.members), 3, "Should have three members with partial interface mixin"
|
||||
)
|
||||
harness.check(
|
||||
mixin.members[0].identifier.name,
|
||||
"x",
|
||||
"First member should be x with partial interface mixin",
|
||||
)
|
||||
harness.check(
|
||||
mixin.members[1].identifier.name,
|
||||
"foo",
|
||||
"Second member should be foo with partial interface mixin",
|
||||
)
|
||||
harness.check(
|
||||
len(mixin.members[1].signatures()),
|
||||
2,
|
||||
"Should have two foo signatures with partial interface mixin",
|
||||
)
|
||||
harness.check(
|
||||
mixin.members[2].identifier.name,
|
||||
"y",
|
||||
"Third member should be y with partial interface mixin",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
partial interface mixin A {
|
||||
readonly attribute boolean y;
|
||||
undefined foo(long arg);
|
||||
};
|
||||
interface mixin A {
|
||||
readonly attribute boolean x;
|
||||
undefined foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(
|
||||
len(results), 2, "Should have two results with reversed partial interface mixin"
|
||||
)
|
||||
mixin = results[1]
|
||||
harness.check(
|
||||
len(mixin.members),
|
||||
3,
|
||||
"Should have three members with reversed partial interface mixin",
|
||||
)
|
||||
harness.check(
|
||||
mixin.members[0].identifier.name,
|
||||
"x",
|
||||
"First member should be x with reversed partial interface mixin",
|
||||
)
|
||||
harness.check(
|
||||
mixin.members[1].identifier.name,
|
||||
"foo",
|
||||
"Second member should be foo with reversed partial interface mixin",
|
||||
)
|
||||
harness.check(
|
||||
len(mixin.members[1].signatures()),
|
||||
2,
|
||||
"Should have two foo signatures with reversed partial interface mixin",
|
||||
)
|
||||
harness.check(
|
||||
mixin.members[2].identifier.name,
|
||||
"y",
|
||||
"Third member should be y with reversed partial interface mixin",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface Interface {};
|
||||
interface mixin Mixin {
|
||||
attribute short x;
|
||||
};
|
||||
Interface includes Mixin;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
iface = results[0]
|
||||
harness.check(len(iface.members), 1, "Should merge members from mixins")
|
||||
harness.check(
|
||||
iface.members[0].identifier.name, "x", "Should merge members from mixins"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin A {
|
||||
readonly attribute boolean x;
|
||||
};
|
||||
interface mixin A {
|
||||
readonly attribute boolean y;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "Should not allow two non-partial interface mixins with the same name"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
partial interface mixin A {
|
||||
readonly attribute boolean x;
|
||||
};
|
||||
partial interface mixin A {
|
||||
readonly attribute boolean y;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Must have a non-partial interface mixin for a given name")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
boolean x;
|
||||
};
|
||||
partial interface mixin A {
|
||||
readonly attribute boolean y;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should not allow a name collision between partial interface "
|
||||
"mixin and other object",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary A {
|
||||
boolean x;
|
||||
};
|
||||
interface mixin A {
|
||||
readonly attribute boolean y;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should not allow a name collision between interface mixin " "and other object",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin A {
|
||||
readonly attribute boolean x;
|
||||
};
|
||||
interface A;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should not allow a name collision between external interface "
|
||||
"and interface mixin",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[SomeRandomAnnotation]
|
||||
interface mixin A {
|
||||
readonly attribute boolean y;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "Should not allow unknown extended attributes on interface mixins"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin A {
|
||||
getter double (DOMString propertyName);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow getters on interface mixins")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin A {
|
||||
setter undefined (DOMString propertyName, double propertyValue);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow setters on interface mixins")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin A {
|
||||
deleter undefined (DOMString propertyName);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow deleters on interface mixins")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin A {
|
||||
legacycaller double compute(double x);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow legacycallers on interface mixins")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin A {
|
||||
inherit attribute x;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow inherited attribute on interface mixins")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Interface {};
|
||||
interface NotMixin {
|
||||
attribute short x;
|
||||
};
|
||||
Interface includes NotMixin;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should fail if the right side does not point an interface mixin")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin NotInterface {};
|
||||
interface mixin Mixin {
|
||||
attribute short x;
|
||||
};
|
||||
NotInterface includes Mixin;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should fail if the left side does not point an interface")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin Mixin {
|
||||
iterable<DOMString>;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should fail if an interface mixin includes iterable")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin Mixin {
|
||||
setlike<DOMString>;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should fail if an interface mixin includes setlike")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface mixin Mixin {
|
||||
maplike<DOMString, DOMString>;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should fail if an interface mixin includes maplike")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Interface {
|
||||
attribute short attr;
|
||||
};
|
||||
interface mixin Mixin {
|
||||
attribute short attr;
|
||||
};
|
||||
Interface includes Mixin;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "Should fail if the included mixin interface has duplicated member"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Interface {};
|
||||
interface mixin Mixin1 {
|
||||
attribute short attr;
|
||||
};
|
||||
interface mixin Mixin2 {
|
||||
attribute short attr;
|
||||
};
|
||||
Interface includes Mixin1;
|
||||
Interface includes Mixin2;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "Should fail if the included mixin interfaces have duplicated member"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Window, Exposed=Window] interface Window {};
|
||||
[Global=Worker, Exposed=Worker] interface Worker {};
|
||||
[Exposed=Window]
|
||||
interface Base {};
|
||||
interface mixin Mixin {
|
||||
Base returnSelf();
|
||||
};
|
||||
Base includes Mixin;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
base = results[2]
|
||||
attr = base.members[0]
|
||||
harness.check(
|
||||
attr.exposureSet,
|
||||
set(["Window"]),
|
||||
"Should expose on globals where the base interfaces are exposed",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Window, Exposed=Window] interface Window {};
|
||||
[Global=Worker, Exposed=Worker] interface Worker {};
|
||||
[Exposed=Window]
|
||||
interface Base {};
|
||||
[Exposed=Window]
|
||||
interface mixin Mixin {
|
||||
attribute short a;
|
||||
};
|
||||
Base includes Mixin;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
base = results[2]
|
||||
attr = base.members[0]
|
||||
harness.check(
|
||||
attr.exposureSet, set(["Window"]), "Should follow [Exposed] on interface mixin"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
[Global=Window, Exposed=Window] interface Window {};
|
||||
[Global=Worker, Exposed=Worker] interface Worker {};
|
||||
[Exposed=Window]
|
||||
interface Base1 {};
|
||||
[Exposed=Worker]
|
||||
interface Base2 {};
|
||||
interface mixin Mixin {
|
||||
attribute short a;
|
||||
};
|
||||
Base1 includes Mixin;
|
||||
Base2 includes Mixin;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
base = results[2]
|
||||
attr = base.members[0]
|
||||
harness.check(
|
||||
attr.exposureSet,
|
||||
set(["Window", "Worker"]),
|
||||
"Should expose on all globals where including interfaces are " "exposed",
|
||||
)
|
||||
base = results[3]
|
||||
attr = base.members[0]
|
||||
harness.check(
|
||||
attr.exposureSet,
|
||||
set(["Window", "Worker"]),
|
||||
"Should expose on all globals where including interfaces are " "exposed",
|
||||
)
|
||||
11
third_party/WebIDL/tests/test_legacyTreatNonObjectAsNull.py
vendored
Normal file
11
third_party/WebIDL/tests/test_legacyTreatNonObjectAsNull.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
[LegacyTreatNonObjectAsNull] callback Function = any(any... arguments);
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
callback = results[0]
|
||||
harness.check(callback._treatNonObjectAsNull, True, "Got the expected value")
|
||||
86
third_party/WebIDL/tests/test_lenientSetter.py
vendored
Normal file
86
third_party/WebIDL/tests/test_lenientSetter.py
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import WebIDL
|
||||
|
||||
|
||||
def should_throw(parser, harness, message, code):
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(code)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown: %s" % message)
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
# The [LegacyLenientSetter] extended attribute MUST take no arguments.
|
||||
should_throw(
|
||||
parser,
|
||||
harness,
|
||||
"no arguments",
|
||||
"""
|
||||
interface I {
|
||||
[LegacyLenientSetter=X] readonly attribute long A;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
# An attribute with the [LegacyLenientSetter] extended attribute MUST NOT
|
||||
# also be declared with the [PutForwards] extended attribute.
|
||||
should_throw(
|
||||
parser,
|
||||
harness,
|
||||
"PutForwards",
|
||||
"""
|
||||
interface I {
|
||||
[PutForwards=B, LegacyLenientSetter] readonly attribute J A;
|
||||
};
|
||||
interface J {
|
||||
attribute long B;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
# An attribute with the [LegacyLenientSetter] extended attribute MUST NOT
|
||||
# also be declared with the [Replaceable] extended attribute.
|
||||
should_throw(
|
||||
parser,
|
||||
harness,
|
||||
"Replaceable",
|
||||
"""
|
||||
interface I {
|
||||
[Replaceable, LegacyLenientSetter] readonly attribute J A;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
# The [LegacyLenientSetter] extended attribute MUST NOT be used on an
|
||||
# attribute that is not read only.
|
||||
should_throw(
|
||||
parser,
|
||||
harness,
|
||||
"writable attribute",
|
||||
"""
|
||||
interface I {
|
||||
[LegacyLenientSetter] attribute long A;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
# The [LegacyLenientSetter] extended attribute MUST NOT be used on a
|
||||
# static attribute.
|
||||
should_throw(
|
||||
parser,
|
||||
harness,
|
||||
"static attribute",
|
||||
"""
|
||||
interface I {
|
||||
[LegacyLenientSetter] static readonly attribute long A;
|
||||
};
|
||||
""",
|
||||
)
|
||||
430
third_party/WebIDL/tests/test_method.py
vendored
Normal file
430
third_party/WebIDL/tests/test_method.py
vendored
Normal file
@@ -0,0 +1,430 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestMethods {
|
||||
undefined basic();
|
||||
static undefined basicStatic();
|
||||
undefined basicWithSimpleArgs(boolean arg1, byte arg2, unsigned long arg3);
|
||||
boolean basicBoolean();
|
||||
static boolean basicStaticBoolean();
|
||||
boolean basicBooleanWithSimpleArgs(boolean arg1, byte arg2, unsigned long arg3);
|
||||
undefined optionalArg(optional byte? arg1, optional sequence<byte> arg2);
|
||||
undefined variadicArg(byte?... arg1);
|
||||
object getObject();
|
||||
undefined setObject(object arg1);
|
||||
undefined setAny(any arg1);
|
||||
float doFloats(float arg1);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestMethods interface parsed without error.")
|
||||
harness.check(len(results), 1, "Should be one production.")
|
||||
iface = results[0]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
harness.check(
|
||||
iface.identifier.QName(), "::TestMethods", "Interface has the right QName"
|
||||
)
|
||||
harness.check(iface.identifier.name, "TestMethods", "Interface has the right name")
|
||||
harness.check(len(iface.members), 12, "Expect 12 members")
|
||||
|
||||
methods = iface.members
|
||||
|
||||
def checkArgument(argument, QName, name, type, optional, variadic):
|
||||
harness.ok(isinstance(argument, WebIDL.IDLArgument), "Should be an IDLArgument")
|
||||
harness.check(
|
||||
argument.identifier.QName(), QName, "Argument has the right QName"
|
||||
)
|
||||
harness.check(argument.identifier.name, name, "Argument has the right name")
|
||||
harness.check(str(argument.type), type, "Argument has the right return type")
|
||||
harness.check(
|
||||
argument.optional, optional, "Argument has the right optional value"
|
||||
)
|
||||
harness.check(
|
||||
argument.variadic, variadic, "Argument has the right variadic value"
|
||||
)
|
||||
|
||||
def checkMethod(
|
||||
method,
|
||||
QName,
|
||||
name,
|
||||
signatures,
|
||||
static=False,
|
||||
getter=False,
|
||||
setter=False,
|
||||
deleter=False,
|
||||
legacycaller=False,
|
||||
stringifier=False,
|
||||
):
|
||||
harness.ok(isinstance(method, WebIDL.IDLMethod), "Should be an IDLMethod")
|
||||
harness.ok(method.isMethod(), "Method is a method")
|
||||
harness.ok(not method.isAttr(), "Method is not an attr")
|
||||
harness.ok(not method.isConst(), "Method is not a const")
|
||||
harness.check(method.identifier.QName(), QName, "Method has the right QName")
|
||||
harness.check(method.identifier.name, name, "Method has the right name")
|
||||
harness.check(method.isStatic(), static, "Method has the correct static value")
|
||||
harness.check(method.isGetter(), getter, "Method has the correct getter value")
|
||||
harness.check(method.isSetter(), setter, "Method has the correct setter value")
|
||||
harness.check(
|
||||
method.isDeleter(), deleter, "Method has the correct deleter value"
|
||||
)
|
||||
harness.check(
|
||||
method.isLegacycaller(),
|
||||
legacycaller,
|
||||
"Method has the correct legacycaller value",
|
||||
)
|
||||
harness.check(
|
||||
method.isStringifier(),
|
||||
stringifier,
|
||||
"Method has the correct stringifier value",
|
||||
)
|
||||
harness.check(
|
||||
len(method.signatures()),
|
||||
len(signatures),
|
||||
"Method has the correct number of signatures",
|
||||
)
|
||||
|
||||
sigpairs = zip(method.signatures(), signatures)
|
||||
for gotSignature, expectedSignature in sigpairs:
|
||||
(gotRetType, gotArgs) = gotSignature
|
||||
(expectedRetType, expectedArgs) = expectedSignature
|
||||
|
||||
harness.check(
|
||||
str(gotRetType), expectedRetType, "Method has the expected return type."
|
||||
)
|
||||
|
||||
for i in range(0, len(gotArgs)):
|
||||
(QName, name, type, optional, variadic) = expectedArgs[i]
|
||||
checkArgument(gotArgs[i], QName, name, type, optional, variadic)
|
||||
|
||||
checkMethod(methods[0], "::TestMethods::basic", "basic", [("Undefined", [])])
|
||||
checkMethod(
|
||||
methods[1],
|
||||
"::TestMethods::basicStatic",
|
||||
"basicStatic",
|
||||
[("Undefined", [])],
|
||||
static=True,
|
||||
)
|
||||
checkMethod(
|
||||
methods[2],
|
||||
"::TestMethods::basicWithSimpleArgs",
|
||||
"basicWithSimpleArgs",
|
||||
[
|
||||
(
|
||||
"Undefined",
|
||||
[
|
||||
(
|
||||
"::TestMethods::basicWithSimpleArgs::arg1",
|
||||
"arg1",
|
||||
"Boolean",
|
||||
False,
|
||||
False,
|
||||
),
|
||||
(
|
||||
"::TestMethods::basicWithSimpleArgs::arg2",
|
||||
"arg2",
|
||||
"Byte",
|
||||
False,
|
||||
False,
|
||||
),
|
||||
(
|
||||
"::TestMethods::basicWithSimpleArgs::arg3",
|
||||
"arg3",
|
||||
"UnsignedLong",
|
||||
False,
|
||||
False,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
checkMethod(
|
||||
methods[3], "::TestMethods::basicBoolean", "basicBoolean", [("Boolean", [])]
|
||||
)
|
||||
checkMethod(
|
||||
methods[4],
|
||||
"::TestMethods::basicStaticBoolean",
|
||||
"basicStaticBoolean",
|
||||
[("Boolean", [])],
|
||||
static=True,
|
||||
)
|
||||
checkMethod(
|
||||
methods[5],
|
||||
"::TestMethods::basicBooleanWithSimpleArgs",
|
||||
"basicBooleanWithSimpleArgs",
|
||||
[
|
||||
(
|
||||
"Boolean",
|
||||
[
|
||||
(
|
||||
"::TestMethods::basicBooleanWithSimpleArgs::arg1",
|
||||
"arg1",
|
||||
"Boolean",
|
||||
False,
|
||||
False,
|
||||
),
|
||||
(
|
||||
"::TestMethods::basicBooleanWithSimpleArgs::arg2",
|
||||
"arg2",
|
||||
"Byte",
|
||||
False,
|
||||
False,
|
||||
),
|
||||
(
|
||||
"::TestMethods::basicBooleanWithSimpleArgs::arg3",
|
||||
"arg3",
|
||||
"UnsignedLong",
|
||||
False,
|
||||
False,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
checkMethod(
|
||||
methods[6],
|
||||
"::TestMethods::optionalArg",
|
||||
"optionalArg",
|
||||
[
|
||||
(
|
||||
"Undefined",
|
||||
[
|
||||
(
|
||||
"::TestMethods::optionalArg::arg1",
|
||||
"arg1",
|
||||
"ByteOrNull",
|
||||
True,
|
||||
False,
|
||||
),
|
||||
(
|
||||
"::TestMethods::optionalArg::arg2",
|
||||
"arg2",
|
||||
"ByteSequence",
|
||||
True,
|
||||
False,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
checkMethod(
|
||||
methods[7],
|
||||
"::TestMethods::variadicArg",
|
||||
"variadicArg",
|
||||
[
|
||||
(
|
||||
"Undefined",
|
||||
[
|
||||
(
|
||||
"::TestMethods::variadicArg::arg1",
|
||||
"arg1",
|
||||
"ByteOrNull",
|
||||
True,
|
||||
True,
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
checkMethod(methods[8], "::TestMethods::getObject", "getObject", [("Object", [])])
|
||||
checkMethod(
|
||||
methods[9],
|
||||
"::TestMethods::setObject",
|
||||
"setObject",
|
||||
[
|
||||
(
|
||||
"Undefined",
|
||||
[("::TestMethods::setObject::arg1", "arg1", "Object", False, False)],
|
||||
)
|
||||
],
|
||||
)
|
||||
checkMethod(
|
||||
methods[10],
|
||||
"::TestMethods::setAny",
|
||||
"setAny",
|
||||
[("Undefined", [("::TestMethods::setAny::arg1", "arg1", "Any", False, False)])],
|
||||
)
|
||||
checkMethod(
|
||||
methods[11],
|
||||
"::TestMethods::doFloats",
|
||||
"doFloats",
|
||||
[("Float", [("::TestMethods::doFloats::arg1", "arg1", "Float", False, False)])],
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
undefined foo(optional float bar = 1);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(not threw, "Should allow integer to float type corecion")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[GetterThrows] undefined foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow [GetterThrows] on methods")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[SetterThrows] undefined foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow [SetterThrows] on methods")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[Throw] undefined foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should spell [Throws] correctly on methods")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
undefined __noSuchMethod__();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow __noSuchMethod__ methods")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[Throws, LenientFloat]
|
||||
undefined foo(float myFloat);
|
||||
[Throws]
|
||||
undefined foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(not threw, "Should allow LenientFloat to be only in a specific overload")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[Throws]
|
||||
undefined foo();
|
||||
[Throws, LenientFloat]
|
||||
undefined foo(float myFloat);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
iface = results[0]
|
||||
methods = iface.members
|
||||
lenientFloat = methods[0].getExtendedAttribute("LenientFloat")
|
||||
harness.ok(
|
||||
lenientFloat is not None,
|
||||
"LenientFloat in overloads must be added to the method",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[Throws, LenientFloat]
|
||||
undefined foo(float myFloat);
|
||||
[Throws]
|
||||
undefined foo(float myFloat, float yourFloat);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should prevent overloads from getting different restricted float behavior",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[Throws]
|
||||
undefined foo(float myFloat, float yourFloat);
|
||||
[Throws, LenientFloat]
|
||||
undefined foo(float myFloat);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should prevent overloads from getting different restricted float behavior (2)",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[Throws, LenientFloat]
|
||||
undefined foo(float myFloat);
|
||||
[Throws, LenientFloat]
|
||||
undefined foo(short myShort);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should prevent overloads from getting redundant [LenientFloat]")
|
||||
235
third_party/WebIDL/tests/test_namespace.py
vendored
Normal file
235
third_party/WebIDL/tests/test_namespace.py
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
namespace MyNamespace {
|
||||
attribute any foo;
|
||||
any bar();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 1, "Should have a thing.")
|
||||
harness.ok(results[0].isNamespace(), "Our thing should be a namespace")
|
||||
harness.check(len(results[0].members), 2, "Should have two things in our namespace")
|
||||
harness.ok(results[0].members[0].isAttr(), "First member is attribute")
|
||||
harness.ok(results[0].members[0].isStatic(), "Attribute should be static")
|
||||
harness.ok(results[0].members[1].isMethod(), "Second member is method")
|
||||
harness.ok(results[0].members[1].isStatic(), "Operation should be static")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
namespace MyNamespace {
|
||||
attribute any foo;
|
||||
};
|
||||
partial namespace MyNamespace {
|
||||
any bar();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 2, "Should have things.")
|
||||
harness.ok(results[0].isNamespace(), "Our thing should be a namespace")
|
||||
harness.check(len(results[0].members), 2, "Should have two things in our namespace")
|
||||
harness.ok(results[0].members[0].isAttr(), "First member is attribute")
|
||||
harness.ok(results[0].members[0].isStatic(), "Attribute should be static")
|
||||
harness.ok(results[0].members[1].isMethod(), "Second member is method")
|
||||
harness.ok(results[0].members[1].isStatic(), "Operation should be static")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
partial namespace MyNamespace {
|
||||
any bar();
|
||||
};
|
||||
namespace MyNamespace {
|
||||
attribute any foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 2, "Should have things.")
|
||||
harness.ok(results[1].isNamespace(), "Our thing should be a namespace")
|
||||
harness.check(len(results[1].members), 2, "Should have two things in our namespace")
|
||||
harness.ok(results[1].members[0].isAttr(), "First member is attribute")
|
||||
harness.ok(results[1].members[0].isStatic(), "Attribute should be static")
|
||||
harness.ok(results[1].members[1].isMethod(), "Second member is method")
|
||||
harness.ok(results[1].members[1].isStatic(), "Operation should be static")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
namespace MyNamespace {
|
||||
static attribute any foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
namespace MyNamespace {
|
||||
static any bar();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
namespace MyNamespace {
|
||||
any bar();
|
||||
};
|
||||
|
||||
interface MyNamespace {
|
||||
any baz();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface MyNamespace {
|
||||
any baz();
|
||||
};
|
||||
|
||||
namespace MyNamespace {
|
||||
any bar();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
namespace MyNamespace {
|
||||
any baz();
|
||||
};
|
||||
|
||||
namespace MyNamespace {
|
||||
any bar();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
partial namespace MyNamespace {
|
||||
any baz();
|
||||
};
|
||||
|
||||
interface MyNamespace {
|
||||
any bar();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
namespace MyNamespace {
|
||||
any bar();
|
||||
};
|
||||
|
||||
partial interface MyNamespace {
|
||||
any baz();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
partial interface MyNamespace {
|
||||
any baz();
|
||||
};
|
||||
|
||||
namespace MyNamespace {
|
||||
any bar();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface MyNamespace {
|
||||
any bar();
|
||||
};
|
||||
|
||||
partial namespace MyNamespace {
|
||||
any baz();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
76
third_party/WebIDL/tests/test_newobject.py
vendored
Normal file
76
third_party/WebIDL/tests/test_newobject.py
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
# Import the WebIDL module, so we can do isinstance checks and whatnot
|
||||
def WebIDLTest(parser, harness):
|
||||
# Basic functionality
|
||||
parser.parse(
|
||||
"""
|
||||
interface Iface {
|
||||
[NewObject] readonly attribute Iface attr;
|
||||
[NewObject] Iface method();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.ok(results, "Should not have thrown on basic [NewObject] usage")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Iface {
|
||||
[Pure, NewObject] readonly attribute Iface attr;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "[NewObject] attributes must depend on something")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Iface {
|
||||
[Pure, NewObject] Iface method();
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "[NewObject] methods must depend on something")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Iface {
|
||||
[Cached, NewObject, Affects=Nothing] readonly attribute Iface attr;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "[NewObject] attributes must not be [Cached]")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Iface {
|
||||
[StoreInSlot, NewObject, Affects=Nothing] readonly attribute Iface attr;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "[NewObject] attributes must not be [StoreInSlot]")
|
||||
145
third_party/WebIDL/tests/test_nullable_equivalency.py
vendored
Normal file
145
third_party/WebIDL/tests/test_nullable_equivalency.py
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestNullableEquivalency1 {
|
||||
attribute long a;
|
||||
attribute long? b;
|
||||
};
|
||||
|
||||
interface TestNullableEquivalency2 {
|
||||
attribute ArrayBuffer a;
|
||||
attribute ArrayBuffer? b;
|
||||
};
|
||||
|
||||
/* Can't have dictionary-valued attributes, so can't test that here */
|
||||
|
||||
enum TestNullableEquivalency4Enum {
|
||||
"Foo",
|
||||
"Bar"
|
||||
};
|
||||
|
||||
interface TestNullableEquivalency4 {
|
||||
attribute TestNullableEquivalency4Enum a;
|
||||
attribute TestNullableEquivalency4Enum? b;
|
||||
};
|
||||
|
||||
interface TestNullableEquivalency5 {
|
||||
attribute TestNullableEquivalency4 a;
|
||||
attribute TestNullableEquivalency4? b;
|
||||
};
|
||||
|
||||
interface TestNullableEquivalency6 {
|
||||
attribute boolean a;
|
||||
attribute boolean? b;
|
||||
};
|
||||
|
||||
interface TestNullableEquivalency7 {
|
||||
attribute DOMString a;
|
||||
attribute DOMString? b;
|
||||
};
|
||||
|
||||
interface TestNullableEquivalency8 {
|
||||
attribute float a;
|
||||
attribute float? b;
|
||||
};
|
||||
|
||||
interface TestNullableEquivalency9 {
|
||||
attribute double a;
|
||||
attribute double? b;
|
||||
};
|
||||
|
||||
interface TestNullableEquivalency10 {
|
||||
attribute object a;
|
||||
attribute object? b;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
for decl in parser.finish():
|
||||
if decl.isInterface():
|
||||
checkEquivalent(decl, harness)
|
||||
|
||||
|
||||
def checkEquivalent(iface, harness):
|
||||
type1 = iface.members[0].type
|
||||
type2 = iface.members[1].type
|
||||
|
||||
harness.check(type1.nullable(), False, "attr1 should not be nullable")
|
||||
harness.check(type2.nullable(), True, "attr2 should be nullable")
|
||||
|
||||
# We don't know about type1, but type2, the nullable type, definitely
|
||||
# shouldn't be builtin.
|
||||
harness.check(type2.builtin, False, "attr2 should not be builtin")
|
||||
|
||||
# Ensure that all attributes of type2 match those in type1, except for:
|
||||
# - names on an ignore list,
|
||||
# - names beginning with '_',
|
||||
# - functions which throw when called with no args, and
|
||||
# - class-level non-callables ("static variables").
|
||||
#
|
||||
# Yes, this is an ugly, fragile hack. But it finds bugs...
|
||||
for attr in dir(type1):
|
||||
if (
|
||||
attr.startswith("_")
|
||||
or attr
|
||||
in [
|
||||
"nullable",
|
||||
"builtin",
|
||||
"filename",
|
||||
"location",
|
||||
"inner",
|
||||
"QName",
|
||||
"getDeps",
|
||||
"name",
|
||||
"prettyName",
|
||||
]
|
||||
or (hasattr(type(type1), attr) and not callable(getattr(type1, attr)))
|
||||
):
|
||||
continue
|
||||
|
||||
a1 = getattr(type1, attr)
|
||||
|
||||
if callable(a1):
|
||||
try:
|
||||
v1 = a1()
|
||||
except AssertionError:
|
||||
# Various methods assert that they're called on objects of
|
||||
# the right type, skip them if the assert fails.
|
||||
continue
|
||||
except TypeError:
|
||||
# a1 requires positional arguments, so skip this attribute.
|
||||
continue
|
||||
|
||||
try:
|
||||
a2 = getattr(type2, attr)
|
||||
except WebIDL.WebIDLError:
|
||||
harness.ok(
|
||||
False,
|
||||
"Missing %s attribute on type %s in %s" % (attr, type2, iface),
|
||||
)
|
||||
continue
|
||||
|
||||
if not callable(a2):
|
||||
harness.ok(
|
||||
False,
|
||||
"%s attribute on type %s in %s wasn't callable"
|
||||
% (attr, type2, iface),
|
||||
)
|
||||
continue
|
||||
|
||||
v2 = a2()
|
||||
harness.check(v2, v1, "%s method return value" % attr)
|
||||
else:
|
||||
try:
|
||||
a2 = getattr(type2, attr)
|
||||
except WebIDL.WebIDLError:
|
||||
harness.ok(
|
||||
False,
|
||||
"Missing %s attribute on type %s in %s" % (attr, type2, iface),
|
||||
)
|
||||
continue
|
||||
|
||||
harness.check(a2, a1, "%s attribute should match" % attr)
|
||||
19
third_party/WebIDL/tests/test_nullable_void.py
vendored
Normal file
19
third_party/WebIDL/tests/test_nullable_void.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface NullableVoid {
|
||||
void? foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
287
third_party/WebIDL/tests/test_observableArray.py
vendored
Normal file
287
third_party/WebIDL/tests/test_observableArray.py
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
# Test dictionary as inner type
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
dictionary A {
|
||||
boolean member;
|
||||
};
|
||||
interface B {
|
||||
attribute ObservableArray<A> foo;
|
||||
};
|
||||
""",
|
||||
"use dictionary as inner type",
|
||||
)
|
||||
|
||||
# Test sequence as inner type
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
attribute ObservableArray<sequence<boolean>> foo;
|
||||
};
|
||||
""",
|
||||
"use sequence as inner type",
|
||||
)
|
||||
|
||||
# Test sequence<dictionary> as inner type
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
dictionary A {
|
||||
boolean member;
|
||||
};
|
||||
interface B {
|
||||
attribute ObservableArray<sequence<A>> foo;
|
||||
};
|
||||
""",
|
||||
"use sequence<dictionary> as inner type",
|
||||
)
|
||||
|
||||
# Test record as inner type
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
attribute ObservableArray<record<DOMString, boolean>> foo;
|
||||
};
|
||||
""",
|
||||
"use record as inner type",
|
||||
)
|
||||
|
||||
# Test record<dictionary> as inner type
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
dictionary A {
|
||||
boolean member;
|
||||
};
|
||||
interface B {
|
||||
attribute ObservableArray<record<DOMString, A>> foo;
|
||||
};
|
||||
""",
|
||||
"use record<dictionary> as inner type",
|
||||
)
|
||||
|
||||
# Test observable array as inner type
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
attribute ObservableArray<ObservableArray<boolean>> foo;
|
||||
};
|
||||
""",
|
||||
"use ObservableArray as inner type",
|
||||
)
|
||||
|
||||
# Test nullable attribute
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
attribute ObservableArray<boolean>? foo;
|
||||
};
|
||||
""",
|
||||
"nullable",
|
||||
)
|
||||
|
||||
# Test sequence
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
undefined foo(sequence<ObservableArray<boolean>> foo);
|
||||
};
|
||||
""",
|
||||
"used in sequence",
|
||||
)
|
||||
|
||||
# Test record
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
undefined foo(record<DOMString, ObservableArray<boolean>> foo);
|
||||
};
|
||||
""",
|
||||
"used in record",
|
||||
)
|
||||
|
||||
# Test promise
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
Promise<ObservableArray<boolean>> foo();
|
||||
};
|
||||
""",
|
||||
"used in promise",
|
||||
)
|
||||
|
||||
# Test union
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
attribute (DOMString or ObservableArray<boolean>>) foo;
|
||||
};
|
||||
""",
|
||||
"used in union",
|
||||
)
|
||||
|
||||
# Test dictionary member
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
dictionary A {
|
||||
ObservableArray<boolean> foo;
|
||||
};
|
||||
""",
|
||||
"used on dictionary member type",
|
||||
)
|
||||
|
||||
# Test argument
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
undefined foo(ObservableArray<boolean> foo);
|
||||
};
|
||||
""",
|
||||
"used on argument",
|
||||
)
|
||||
|
||||
# Test static attribute
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
static attribute ObservableArray<boolean> foo;
|
||||
};
|
||||
""",
|
||||
"used on static attribute type",
|
||||
)
|
||||
|
||||
# Test iterable
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
iterable<ObservableArray<boolean>>;
|
||||
};
|
||||
""",
|
||||
"used in iterable",
|
||||
)
|
||||
|
||||
# Test maplike
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
maplike<long, ObservableArray<boolean>>;
|
||||
};
|
||||
""",
|
||||
"used in maplike",
|
||||
)
|
||||
|
||||
# Test setlike
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
setlike<ObservableArray<boolean>>;
|
||||
};
|
||||
""",
|
||||
"used in setlike",
|
||||
)
|
||||
|
||||
# Test JS implemented interface
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
[JSImplementation="@mozilla.org/dom/test-interface-js;1"]
|
||||
interface A {
|
||||
readonly attribute ObservableArray<boolean> foo;
|
||||
};
|
||||
""",
|
||||
"used in JS implemented interface",
|
||||
)
|
||||
|
||||
# Test namespace
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
namespace A {
|
||||
readonly attribute ObservableArray<boolean> foo;
|
||||
};
|
||||
""",
|
||||
"used in namespaces",
|
||||
)
|
||||
|
||||
# Test [Cached] extended attribute
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
[Cached, Pure]
|
||||
readonly attribute ObservableArray<boolean> foo;
|
||||
};
|
||||
""",
|
||||
"have Cached extended attribute",
|
||||
)
|
||||
|
||||
# Test [StoreInSlot] extended attribute
|
||||
harness.should_throw(
|
||||
parser,
|
||||
"""
|
||||
interface A {
|
||||
[StoreInSlot, Pure]
|
||||
readonly attribute ObservableArray<boolean> foo;
|
||||
};
|
||||
""",
|
||||
"have StoreInSlot extended attribute",
|
||||
)
|
||||
|
||||
# Test regular attribute
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
readonly attribute ObservableArray<boolean> foo;
|
||||
attribute ObservableArray<[Clamp] octet> bar;
|
||||
attribute ObservableArray<long?> baz;
|
||||
attribute ObservableArray<(boolean or long)> qux;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
A = results[0]
|
||||
foo = A.members[0]
|
||||
harness.ok(foo.readonly, "A.foo is readonly attribute")
|
||||
harness.ok(foo.type.isObservableArray(), "A.foo is ObservableArray type")
|
||||
harness.check(
|
||||
foo.slotIndices[A.identifier.name], 0, "A.foo should be stored in slot"
|
||||
)
|
||||
bar = A.members[1]
|
||||
harness.ok(bar.type.isObservableArray(), "A.bar is ObservableArray type")
|
||||
harness.check(
|
||||
bar.slotIndices[A.identifier.name], 1, "A.bar should be stored in slot"
|
||||
)
|
||||
harness.ok(bar.type.inner.hasClamp(), "A.bar's inner type should be clamped")
|
||||
baz = A.members[2]
|
||||
harness.ok(baz.type.isObservableArray(), "A.baz is ObservableArray type")
|
||||
harness.check(
|
||||
baz.slotIndices[A.identifier.name], 2, "A.baz should be stored in slot"
|
||||
)
|
||||
harness.ok(baz.type.inner.nullable(), "A.baz's inner type should be nullable")
|
||||
qux = A.members[3]
|
||||
harness.ok(qux.type.isObservableArray(), "A.qux is ObservableArray type")
|
||||
harness.check(
|
||||
qux.slotIndices[A.identifier.name], 3, "A.qux should be stored in slot"
|
||||
)
|
||||
harness.ok(qux.type.inner.isUnion(), "A.qux's inner type should be union")
|
||||
38
third_party/WebIDL/tests/test_optional_constraints.py
vendored
Normal file
38
third_party/WebIDL/tests/test_optional_constraints.py
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface OptionalConstraints1 {
|
||||
undefined foo(optional byte arg1, byte arg2);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
not threw,
|
||||
"Should not have thrown on non-optional argument following "
|
||||
"optional argument.",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface OptionalConstraints2 {
|
||||
undefined foo(optional byte arg1 = 1, optional byte arg2 = 2,
|
||||
optional byte arg3, optional byte arg4 = 4,
|
||||
optional byte arg5, optional byte arg6 = 9);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
args = results[0].members[0].signatures()[0][1]
|
||||
harness.check(len(args), 6, "Should have 6 arguments")
|
||||
harness.check(args[5].defaultValue.value, 9, "Should have correct default value")
|
||||
74
third_party/WebIDL/tests/test_overload.py
vendored
Normal file
74
third_party/WebIDL/tests/test_overload.py
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestOverloads {
|
||||
undefined basic();
|
||||
undefined basic(long arg1);
|
||||
boolean abitharder(TestOverloads foo);
|
||||
boolean abitharder(boolean foo);
|
||||
undefined abitharder(ArrayBuffer? foo);
|
||||
undefined withVariadics(long... numbers);
|
||||
undefined withVariadics(TestOverloads iface);
|
||||
undefined withVariadics(long num, TestOverloads iface);
|
||||
undefined optionalTest();
|
||||
undefined optionalTest(optional long num1, long num2);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestOverloads interface parsed without error.")
|
||||
harness.check(len(results), 1, "Should be one production.")
|
||||
iface = results[0]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should be an IDLInterface")
|
||||
harness.check(
|
||||
iface.identifier.QName(), "::TestOverloads", "Interface has the right QName"
|
||||
)
|
||||
harness.check(
|
||||
iface.identifier.name, "TestOverloads", "Interface has the right name"
|
||||
)
|
||||
harness.check(len(iface.members), 4, "Expect %s members" % 4)
|
||||
|
||||
member = iface.members[0]
|
||||
harness.check(
|
||||
member.identifier.QName(),
|
||||
"::TestOverloads::basic",
|
||||
"Method has the right QName",
|
||||
)
|
||||
harness.check(member.identifier.name, "basic", "Method has the right name")
|
||||
harness.check(member.hasOverloads(), True, "Method has overloads")
|
||||
|
||||
signatures = member.signatures()
|
||||
harness.check(len(signatures), 2, "Method should have 2 signatures")
|
||||
|
||||
(retval, argumentSet) = signatures[0]
|
||||
|
||||
harness.check(str(retval), "Undefined", "Expect an undefined retval")
|
||||
harness.check(len(argumentSet), 0, "Expect an empty argument set")
|
||||
|
||||
(retval, argumentSet) = signatures[1]
|
||||
harness.check(str(retval), "Undefined", "Expect an undefined retval")
|
||||
harness.check(len(argumentSet), 1, "Expect an argument set with one argument")
|
||||
|
||||
argument = argumentSet[0]
|
||||
harness.ok(isinstance(argument, WebIDL.IDLArgument), "Should be an IDLArgument")
|
||||
harness.check(
|
||||
argument.identifier.QName(),
|
||||
"::TestOverloads::basic::arg1",
|
||||
"Argument has the right QName",
|
||||
)
|
||||
harness.check(argument.identifier.name, "arg1", "Argument has the right name")
|
||||
harness.check(str(argument.type), "Long", "Argument has the right type")
|
||||
|
||||
member = iface.members[3]
|
||||
harness.check(
|
||||
len(member.overloadsForArgCount(0)), 1, "Only one overload for no args"
|
||||
)
|
||||
harness.check(len(member.overloadsForArgCount(1)), 0, "No overloads for one arg")
|
||||
harness.check(
|
||||
len(member.overloadsForArgCount(2)), 1, "Only one overload for two args"
|
||||
)
|
||||
180
third_party/WebIDL/tests/test_promise.py
vendored
Normal file
180
third_party/WebIDL/tests/test_promise.py
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
legacycaller Promise<any> foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow Promise return values for legacycaller.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
Promise<any> foo();
|
||||
long foo(long arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should not allow overloads which have both Promise and "
|
||||
"non-Promise return types.",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
long foo(long arg);
|
||||
Promise<any> foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should not allow overloads which have both Promise and "
|
||||
"non-Promise return types.",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
Promise<any>? foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow nullable Promise return values.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
undefined foo(Promise<any>? arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow nullable Promise arguments.")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
Promise<any> foo();
|
||||
Promise<any> foo(long arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
|
||||
harness.ok(
|
||||
True, "Should allow overloads which only have Promise and return " "types."
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
attribute Promise<any> attr;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow writable Promise-typed attributes.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[LegacyLenientSetter] readonly attribute Promise<any> attr;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "Should not allow [LegacyLenientSetter] Promise-typed attributes."
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[PutForwards=bar] readonly attribute Promise<any> attr;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow [PutForwards] Promise-typed attributes.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[Replaceable] readonly attribute Promise<any> attr;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow [Replaceable] Promise-typed attributes.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface A {
|
||||
[SameObject] readonly attribute Promise<any> attr;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow [SameObject] Promise-typed attributes.")
|
||||
110
third_party/WebIDL/tests/test_prototype_ident.py
vendored
Normal file
110
third_party/WebIDL/tests/test_prototype_ident.py
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestIface {
|
||||
static attribute boolean prototype;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "The identifier of a static attribute must not be 'prototype'")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestIface {
|
||||
static boolean prototype();
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "The identifier of a static operation must not be 'prototype'")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestIface {
|
||||
const boolean prototype = true;
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "The identifier of a constant must not be 'prototype'")
|
||||
|
||||
# Make sure that we can parse non-static attributes with 'prototype' as identifier.
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestIface {
|
||||
attribute boolean prototype;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
|
||||
testIface = results[0]
|
||||
harness.check(
|
||||
testIface.members[0].isStatic(), False, "Attribute should not be static"
|
||||
)
|
||||
harness.check(
|
||||
testIface.members[0].identifier.name,
|
||||
"prototype",
|
||||
"Attribute identifier should be 'prototype'",
|
||||
)
|
||||
|
||||
# Make sure that we can parse non-static operations with 'prototype' as identifier.
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestIface {
|
||||
boolean prototype();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
|
||||
testIface = results[0]
|
||||
harness.check(
|
||||
testIface.members[0].isStatic(), False, "Operation should not be static"
|
||||
)
|
||||
harness.check(
|
||||
testIface.members[0].identifier.name,
|
||||
"prototype",
|
||||
"Operation identifier should be 'prototype'",
|
||||
)
|
||||
|
||||
# Make sure that we can parse dictionary members with 'prototype' as identifier.
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary TestDict {
|
||||
boolean prototype;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
|
||||
testDict = results[0]
|
||||
harness.check(
|
||||
testDict.members[0].identifier.name,
|
||||
"prototype",
|
||||
"Dictionary member should be 'prototype'",
|
||||
)
|
||||
122
third_party/WebIDL/tests/test_putForwards.py
vendored
Normal file
122
third_party/WebIDL/tests/test_putForwards.py
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface I {
|
||||
[PutForwards=B] readonly attribute long A;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface I {
|
||||
[PutForwards=B] readonly attribute J A;
|
||||
};
|
||||
interface J {
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface I {
|
||||
[PutForwards=B] attribute J A;
|
||||
};
|
||||
interface J {
|
||||
attribute long B;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface I {
|
||||
[PutForwards=B] static readonly attribute J A;
|
||||
};
|
||||
interface J {
|
||||
attribute long B;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
callback interface I {
|
||||
[PutForwards=B] readonly attribute J A;
|
||||
};
|
||||
interface J {
|
||||
attribute long B;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface I {
|
||||
[PutForwards=C] readonly attribute J A;
|
||||
[PutForwards=C] readonly attribute J B;
|
||||
};
|
||||
interface J {
|
||||
[PutForwards=D] readonly attribute K C;
|
||||
};
|
||||
interface K {
|
||||
[PutForwards=A] readonly attribute I D;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
61
third_party/WebIDL/tests/test_record.py
vendored
Normal file
61
third_party/WebIDL/tests/test_record.py
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Dict {};
|
||||
interface RecordArg {
|
||||
undefined foo(record<DOMString, Dict> arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.check(len(results), 2, "Should know about two things")
|
||||
harness.ok(
|
||||
isinstance(results[1], WebIDL.IDLInterface), "Should have an interface here"
|
||||
)
|
||||
members = results[1].members
|
||||
harness.check(len(members), 1, "Should have one member")
|
||||
harness.ok(members[0].isMethod(), "Should have method")
|
||||
signature = members[0].signatures()[0]
|
||||
args = signature[1]
|
||||
harness.check(len(args), 1, "Should have one arg")
|
||||
harness.ok(args[0].type.isRecord(), "Should have a record type here")
|
||||
harness.ok(args[0].type.inner.isDictionary(), "Should have a dictionary inner type")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface RecordUndefinedArg {
|
||||
undefined foo(record<DOMString, undefined> arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "Should have thrown because record can't have undefined as value type."
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
dictionary Dict {
|
||||
record<DOMString, Dict> val;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should have thrown on dictionary containing itself via record.")
|
||||
86
third_party/WebIDL/tests/test_replaceable.py
vendored
Normal file
86
third_party/WebIDL/tests/test_replaceable.py
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import WebIDL
|
||||
|
||||
|
||||
def should_throw(parser, harness, message, code):
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(code)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown: %s" % message)
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
# The [Replaceable] extended attribute MUST take no arguments.
|
||||
should_throw(
|
||||
parser,
|
||||
harness,
|
||||
"no arguments",
|
||||
"""
|
||||
interface I {
|
||||
[Replaceable=X] readonly attribute long A;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
# An attribute with the [Replaceable] extended attribute MUST NOT also be
|
||||
# declared with the [PutForwards] extended attribute.
|
||||
should_throw(
|
||||
parser,
|
||||
harness,
|
||||
"PutForwards",
|
||||
"""
|
||||
interface I {
|
||||
[PutForwards=B, Replaceable] readonly attribute J A;
|
||||
};
|
||||
interface J {
|
||||
attribute long B;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
# The [Replaceable] extended attribute MUST NOT be used on an attribute
|
||||
# that is not read only.
|
||||
should_throw(
|
||||
parser,
|
||||
harness,
|
||||
"writable attribute",
|
||||
"""
|
||||
interface I {
|
||||
[Replaceable] attribute long A;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
# The [Replaceable] extended attribute MUST NOT be used on a static
|
||||
# attribute.
|
||||
should_throw(
|
||||
parser,
|
||||
harness,
|
||||
"static attribute",
|
||||
"""
|
||||
interface I {
|
||||
[Replaceable] static readonly attribute long A;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
# The [Replaceable] extended attribute MUST NOT be used on an attribute
|
||||
# declared on a callback interface.
|
||||
should_throw(
|
||||
parser,
|
||||
harness,
|
||||
"callback interface",
|
||||
"""
|
||||
callback interface I {
|
||||
[Replaceable] readonly attribute long A;
|
||||
};
|
||||
""",
|
||||
)
|
||||
7
third_party/WebIDL/tests/test_sanity.py
vendored
Normal file
7
third_party/WebIDL/tests/test_sanity.py
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("")
|
||||
parser.finish()
|
||||
harness.ok(True, "Parsing nothing doesn't throw.")
|
||||
parser.parse("interface Foo {};")
|
||||
parser.finish()
|
||||
harness.ok(True, "Parsing a silly interface doesn't throw.")
|
||||
541
third_party/WebIDL/tests/test_securecontext_extended_attribute.py
vendored
Normal file
541
third_party/WebIDL/tests/test_securecontext_extended_attribute.py
vendored
Normal file
@@ -0,0 +1,541 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
[SecureContext]
|
||||
interface TestSecureContextOnInterface {
|
||||
const octet TEST_CONSTANT = 0;
|
||||
readonly attribute byte testAttribute;
|
||||
undefined testMethod(byte foo);
|
||||
};
|
||||
partial interface TestSecureContextOnInterface {
|
||||
const octet TEST_CONSTANT_2 = 0;
|
||||
readonly attribute byte testAttribute2;
|
||||
undefined testMethod2(byte foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(
|
||||
len(results[0].members),
|
||||
6,
|
||||
"TestSecureContextOnInterface should have six members",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].getExtendedAttribute("SecureContext"),
|
||||
"Interface should have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[0].getExtendedAttribute("SecureContext"),
|
||||
"[SecureContext] should propagate from interface to constant members",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[1].getExtendedAttribute("SecureContext"),
|
||||
"[SecureContext] should propagate from interface to attribute members",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[2].getExtendedAttribute("SecureContext"),
|
||||
"[SecureContext] should propagate from interface to method members",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[3].getExtendedAttribute("SecureContext"),
|
||||
(
|
||||
"[SecureContext] should propagate from interface to "
|
||||
"constant members from partial interface"
|
||||
),
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[4].getExtendedAttribute("SecureContext"),
|
||||
(
|
||||
"[SecureContext] should propagate from interface to "
|
||||
"attribute members from partial interface"
|
||||
),
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[5].getExtendedAttribute("SecureContext"),
|
||||
"[SecureContext] should propagate from interface to method members from partial interface",
|
||||
)
|
||||
|
||||
# Same thing, but with the partial interface specified first:
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
partial interface TestSecureContextOnInterfaceAfterPartialInterface {
|
||||
const octet TEST_CONSTANT_2 = 0;
|
||||
readonly attribute byte testAttribute2;
|
||||
undefined testMethod2(byte foo);
|
||||
};
|
||||
[SecureContext]
|
||||
interface TestSecureContextOnInterfaceAfterPartialInterface {
|
||||
const octet TEST_CONSTANT = 0;
|
||||
readonly attribute byte testAttribute;
|
||||
undefined testMethod(byte foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(
|
||||
len(results[1].members),
|
||||
6,
|
||||
"TestSecureContextOnInterfaceAfterPartialInterface should have six members",
|
||||
)
|
||||
harness.ok(
|
||||
results[1].getExtendedAttribute("SecureContext"),
|
||||
"Interface should have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[1].members[0].getExtendedAttribute("SecureContext"),
|
||||
"[SecureContext] should propagate from interface to constant members",
|
||||
)
|
||||
harness.ok(
|
||||
results[1].members[1].getExtendedAttribute("SecureContext"),
|
||||
"[SecureContext] should propagate from interface to attribute members",
|
||||
)
|
||||
harness.ok(
|
||||
results[1].members[2].getExtendedAttribute("SecureContext"),
|
||||
"[SecureContext] should propagate from interface to method members",
|
||||
)
|
||||
harness.ok(
|
||||
results[1].members[3].getExtendedAttribute("SecureContext"),
|
||||
(
|
||||
"[SecureContext] should propagate from interface to constant members from "
|
||||
"partial interface"
|
||||
),
|
||||
)
|
||||
harness.ok(
|
||||
results[1].members[4].getExtendedAttribute("SecureContext"),
|
||||
(
|
||||
"[SecureContext] should propagate from interface to attribute members from "
|
||||
"partial interface"
|
||||
),
|
||||
)
|
||||
harness.ok(
|
||||
results[1].members[5].getExtendedAttribute("SecureContext"),
|
||||
(
|
||||
"[SecureContext] should propagate from interface to method members from partial "
|
||||
"interface"
|
||||
),
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestSecureContextOnPartialInterface {
|
||||
const octet TEST_CONSTANT = 0;
|
||||
readonly attribute byte testAttribute;
|
||||
undefined testMethod(byte foo);
|
||||
};
|
||||
[SecureContext]
|
||||
partial interface TestSecureContextOnPartialInterface {
|
||||
const octet TEST_CONSTANT_2 = 0;
|
||||
readonly attribute byte testAttribute2;
|
||||
undefined testMethod2(byte foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(
|
||||
len(results[0].members),
|
||||
6,
|
||||
"TestSecureContextOnPartialInterface should have six members",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].getExtendedAttribute("SecureContext") is None,
|
||||
"[SecureContext] should not propagate from a partial interface to the interface",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[0].getExtendedAttribute("SecureContext") is None,
|
||||
(
|
||||
"[SecureContext] should not propagate from a partial interface to the interface's "
|
||||
"constant members"
|
||||
),
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[1].getExtendedAttribute("SecureContext") is None,
|
||||
(
|
||||
"[SecureContext] should not propagate from a partial interface to the interface's "
|
||||
"attribute members"
|
||||
),
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[2].getExtendedAttribute("SecureContext") is None,
|
||||
(
|
||||
"[SecureContext] should not propagate from a partial interface to the interface's "
|
||||
"method members"
|
||||
),
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[3].getExtendedAttribute("SecureContext"),
|
||||
"Constant members from [SecureContext] partial interface should be [SecureContext]",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[4].getExtendedAttribute("SecureContext"),
|
||||
"Attribute members from [SecureContext] partial interface should be [SecureContext]",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[5].getExtendedAttribute("SecureContext"),
|
||||
"Method members from [SecureContext] partial interface should be [SecureContext]",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestSecureContextOnInterfaceMembers {
|
||||
const octet TEST_NON_SECURE_CONSTANT_1 = 0;
|
||||
[SecureContext]
|
||||
const octet TEST_SECURE_CONSTANT = 1;
|
||||
const octet TEST_NON_SECURE_CONSTANT_2 = 2;
|
||||
readonly attribute byte testNonSecureAttribute1;
|
||||
[SecureContext]
|
||||
readonly attribute byte testSecureAttribute;
|
||||
readonly attribute byte testNonSecureAttribute2;
|
||||
undefined testNonSecureMethod1(byte foo);
|
||||
[SecureContext]
|
||||
undefined testSecureMethod(byte foo);
|
||||
undefined testNonSecureMethod2(byte foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(
|
||||
len(results[0].members),
|
||||
9,
|
||||
"TestSecureContextOnInterfaceMembers should have nine members",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].getExtendedAttribute("SecureContext") is None,
|
||||
"[SecureContext] on members should not propagate up to the interface",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[0].getExtendedAttribute("SecureContext") is None,
|
||||
"Constant should not have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[1].getExtendedAttribute("SecureContext"),
|
||||
"Constant should have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[2].getExtendedAttribute("SecureContext") is None,
|
||||
"Constant should not have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[3].getExtendedAttribute("SecureContext") is None,
|
||||
"Attribute should not have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[4].getExtendedAttribute("SecureContext"),
|
||||
"Attribute should have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[5].getExtendedAttribute("SecureContext") is None,
|
||||
"Attribute should not have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[6].getExtendedAttribute("SecureContext") is None,
|
||||
"Method should not have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[7].getExtendedAttribute("SecureContext"),
|
||||
"Method should have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[8].getExtendedAttribute("SecureContext") is None,
|
||||
"Method should not have [SecureContext] extended attribute",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestSecureContextOnPartialInterfaceMembers {
|
||||
};
|
||||
partial interface TestSecureContextOnPartialInterfaceMembers {
|
||||
const octet TEST_NON_SECURE_CONSTANT_1 = 0;
|
||||
[SecureContext]
|
||||
const octet TEST_SECURE_CONSTANT = 1;
|
||||
const octet TEST_NON_SECURE_CONSTANT_2 = 2;
|
||||
readonly attribute byte testNonSecureAttribute1;
|
||||
[SecureContext]
|
||||
readonly attribute byte testSecureAttribute;
|
||||
readonly attribute byte testNonSecureAttribute2;
|
||||
undefined testNonSecureMethod1(byte foo);
|
||||
[SecureContext]
|
||||
undefined testSecureMethod(byte foo);
|
||||
undefined testNonSecureMethod2(byte foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(
|
||||
len(results[0].members),
|
||||
9,
|
||||
"TestSecureContextOnPartialInterfaceMembers should have nine members",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[0].getExtendedAttribute("SecureContext") is None,
|
||||
"Constant from partial interface should not have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[1].getExtendedAttribute("SecureContext"),
|
||||
"Constant from partial interface should have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[2].getExtendedAttribute("SecureContext") is None,
|
||||
"Constant from partial interface should not have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[3].getExtendedAttribute("SecureContext") is None,
|
||||
"Attribute from partial interface should not have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[4].getExtendedAttribute("SecureContext"),
|
||||
"Attribute from partial interface should have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[5].getExtendedAttribute("SecureContext") is None,
|
||||
"Attribute from partial interface should not have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[6].getExtendedAttribute("SecureContext") is None,
|
||||
"Method from partial interface should not have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[7].getExtendedAttribute("SecureContext"),
|
||||
"Method from partial interface should have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[8].getExtendedAttribute("SecureContext") is None,
|
||||
"Method from partial interface should not have [SecureContext] extended attribute",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[SecureContext=something]
|
||||
interface TestSecureContextTakesNoValue1 {
|
||||
const octet TEST_SECURE_CONSTANT = 0;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "[SecureContext] must take no arguments (testing on interface)")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestSecureContextForOverloads1 {
|
||||
[SecureContext]
|
||||
undefined testSecureMethod(byte foo);
|
||||
};
|
||||
partial interface TestSecureContextForOverloads1 {
|
||||
undefined testSecureMethod(byte foo, byte bar);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
(
|
||||
"If [SecureContext] appears on an overloaded operation, then it MUST appear on all "
|
||||
"overloads"
|
||||
),
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestSecureContextForOverloads2 {
|
||||
[SecureContext]
|
||||
undefined testSecureMethod(byte foo);
|
||||
};
|
||||
partial interface TestSecureContextForOverloads2 {
|
||||
[SecureContext]
|
||||
undefined testSecureMethod(byte foo, byte bar);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
not threw,
|
||||
"[SecureContext] can appear on an overloaded operation if it appears on all overloads",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[SecureContext]
|
||||
interface TestSecureContextOnInterfaceAndMember {
|
||||
[SecureContext]
|
||||
undefined testSecureMethod(byte foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw, "[SecureContext] must not appear on an interface and interface member"
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestSecureContextOnPartialInterfaceAndMember {
|
||||
};
|
||||
[SecureContext]
|
||||
partial interface TestSecureContextOnPartialInterfaceAndMember {
|
||||
[SecureContext]
|
||||
undefined testSecureMethod(byte foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
(
|
||||
"[SecureContext] must not appear on a partial interface and one of the partial "
|
||||
"interface's member's"
|
||||
),
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[SecureContext]
|
||||
interface TestSecureContextOnInterfaceAndPartialInterfaceMember {
|
||||
};
|
||||
partial interface TestSecureContextOnInterfaceAndPartialInterfaceMember {
|
||||
[SecureContext]
|
||||
undefined testSecureMethod(byte foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
(
|
||||
"[SecureContext] must not appear on an interface and one of its partial interface's "
|
||||
"member's"
|
||||
),
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[SecureContext]
|
||||
interface TestSecureContextOnInheritedInterface {
|
||||
};
|
||||
interface TestSecureContextNotOnInheritingInterface : TestSecureContextOnInheritedInterface {
|
||||
undefined testSecureMethod(byte foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
(
|
||||
"[SecureContext] must appear on interfaces that inherit from another [SecureContext] "
|
||||
"interface"
|
||||
),
|
||||
)
|
||||
|
||||
# Test 'includes'.
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
[SecureContext]
|
||||
interface TestSecureContextInterfaceThatIncludesNonSecureContextMixin {
|
||||
const octet TEST_CONSTANT = 0;
|
||||
};
|
||||
interface mixin TestNonSecureContextMixin {
|
||||
const octet TEST_CONSTANT_2 = 0;
|
||||
readonly attribute byte testAttribute2;
|
||||
undefined testMethod2(byte foo);
|
||||
};
|
||||
TestSecureContextInterfaceThatIncludesNonSecureContextMixin includes TestNonSecureContextMixin;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(
|
||||
len(results[0].members),
|
||||
4,
|
||||
(
|
||||
"TestSecureContextInterfaceThatImplementsNonSecureContextInterface should have four "
|
||||
"members"
|
||||
),
|
||||
)
|
||||
harness.ok(
|
||||
results[0].getExtendedAttribute("SecureContext"),
|
||||
"Interface should have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[0].getExtendedAttribute("SecureContext"),
|
||||
(
|
||||
"[SecureContext] should propagate from interface to constant members even when other "
|
||||
"members are copied from a non-[SecureContext] interface"
|
||||
),
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[1].getExtendedAttribute("SecureContext") is None,
|
||||
"Constants copied from non-[SecureContext] mixin should not be [SecureContext]",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[2].getExtendedAttribute("SecureContext") is None,
|
||||
"Attributes copied from non-[SecureContext] mixin should not be [SecureContext]",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[3].getExtendedAttribute("SecureContext") is None,
|
||||
"Methods copied from non-[SecureContext] mixin should not be [SecureContext]",
|
||||
)
|
||||
|
||||
# Test SecureContext and LegacyNoInterfaceObject
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
[LegacyNoInterfaceObject, SecureContext]
|
||||
interface TestSecureContextLegacyNoInterfaceObject {
|
||||
undefined testSecureMethod(byte foo);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.check(
|
||||
len(results[0].members),
|
||||
1,
|
||||
"TestSecureContextLegacyNoInterfaceObject should have only one member",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].getExtendedAttribute("SecureContext"),
|
||||
"Interface should have [SecureContext] extended attribute",
|
||||
)
|
||||
harness.ok(
|
||||
results[0].members[0].getExtendedAttribute("SecureContext"),
|
||||
"Interface member should have [SecureContext] extended attribute",
|
||||
)
|
||||
259
third_party/WebIDL/tests/test_special_method_signature_mismatch.py
vendored
Normal file
259
third_party/WebIDL/tests/test_special_method_signature_mismatch.py
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch1 {
|
||||
getter long long foo(long index);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch2 {
|
||||
getter undefined foo(unsigned long index);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch3 {
|
||||
getter boolean foo(unsigned long index, boolean extraArg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch4 {
|
||||
getter boolean foo(unsigned long... index);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch5 {
|
||||
getter boolean foo(optional unsigned long index);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch6 {
|
||||
getter boolean foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch7 {
|
||||
deleter long long foo(long index);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch9 {
|
||||
deleter boolean foo(unsigned long index, boolean extraArg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch10 {
|
||||
deleter boolean foo(unsigned long... index);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch11 {
|
||||
deleter boolean foo(optional unsigned long index);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch12 {
|
||||
deleter boolean foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch13 {
|
||||
setter long long foo(long index, long long value);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch15 {
|
||||
setter boolean foo(unsigned long index, boolean value, long long extraArg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch16 {
|
||||
setter boolean foo(unsigned long index, boolean... value);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch17 {
|
||||
setter boolean foo(unsigned long index, optional boolean value);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodSignatureMismatch18 {
|
||||
setter boolean foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
117
third_party/WebIDL/tests/test_special_methods.py
vendored
Normal file
117
third_party/WebIDL/tests/test_special_methods.py
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethods {
|
||||
getter long long (unsigned long index);
|
||||
setter long long (unsigned long index, long long value);
|
||||
getter boolean (DOMString name);
|
||||
setter boolean (DOMString name, boolean value);
|
||||
deleter boolean (DOMString name);
|
||||
readonly attribute unsigned long length;
|
||||
};
|
||||
|
||||
interface SpecialMethodsCombination {
|
||||
getter deleter boolean (DOMString name);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
def checkMethod(
|
||||
method,
|
||||
QName,
|
||||
name,
|
||||
static=False,
|
||||
getter=False,
|
||||
setter=False,
|
||||
deleter=False,
|
||||
legacycaller=False,
|
||||
stringifier=False,
|
||||
):
|
||||
harness.ok(isinstance(method, WebIDL.IDLMethod), "Should be an IDLMethod")
|
||||
harness.check(method.identifier.QName(), QName, "Method has the right QName")
|
||||
harness.check(method.identifier.name, name, "Method has the right name")
|
||||
harness.check(method.isStatic(), static, "Method has the correct static value")
|
||||
harness.check(method.isGetter(), getter, "Method has the correct getter value")
|
||||
harness.check(method.isSetter(), setter, "Method has the correct setter value")
|
||||
harness.check(
|
||||
method.isDeleter(), deleter, "Method has the correct deleter value"
|
||||
)
|
||||
harness.check(
|
||||
method.isLegacycaller(),
|
||||
legacycaller,
|
||||
"Method has the correct legacycaller value",
|
||||
)
|
||||
harness.check(
|
||||
method.isStringifier(),
|
||||
stringifier,
|
||||
"Method has the correct stringifier value",
|
||||
)
|
||||
|
||||
harness.check(len(results), 2, "Expect 2 interfaces")
|
||||
|
||||
iface = results[0]
|
||||
harness.check(len(iface.members), 6, "Expect 6 members")
|
||||
|
||||
checkMethod(
|
||||
iface.members[0],
|
||||
"::SpecialMethods::__indexedgetter",
|
||||
"__indexedgetter",
|
||||
getter=True,
|
||||
)
|
||||
checkMethod(
|
||||
iface.members[1],
|
||||
"::SpecialMethods::__indexedsetter",
|
||||
"__indexedsetter",
|
||||
setter=True,
|
||||
)
|
||||
checkMethod(
|
||||
iface.members[2],
|
||||
"::SpecialMethods::__namedgetter",
|
||||
"__namedgetter",
|
||||
getter=True,
|
||||
)
|
||||
checkMethod(
|
||||
iface.members[3],
|
||||
"::SpecialMethods::__namedsetter",
|
||||
"__namedsetter",
|
||||
setter=True,
|
||||
)
|
||||
checkMethod(
|
||||
iface.members[4],
|
||||
"::SpecialMethods::__nameddeleter",
|
||||
"__nameddeleter",
|
||||
deleter=True,
|
||||
)
|
||||
|
||||
iface = results[1]
|
||||
harness.check(len(iface.members), 1, "Expect 1 member")
|
||||
|
||||
checkMethod(
|
||||
iface.members[0],
|
||||
"::SpecialMethodsCombination::__namedgetterdeleter",
|
||||
"__namedgetterdeleter",
|
||||
getter=True,
|
||||
deleter=True,
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface IndexedDeleter {
|
||||
deleter undefined(unsigned long index);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "There are no indexed deleters")
|
||||
54
third_party/WebIDL/tests/test_special_methods_uniqueness.py
vendored
Normal file
54
third_party/WebIDL/tests/test_special_methods_uniqueness.py
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodUniqueness1 {
|
||||
getter deleter boolean (DOMString name);
|
||||
getter boolean (DOMString name);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodUniqueness1 {
|
||||
deleter boolean (DOMString name);
|
||||
getter deleter boolean (DOMString name);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface SpecialMethodUniqueness1 {
|
||||
setter boolean (DOMString name);
|
||||
setter boolean (DOMString name);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
196
third_party/WebIDL/tests/test_stringifier.py
vendored
Normal file
196
third_party/WebIDL/tests/test_stringifier.py
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestStringifier {
|
||||
stringifier;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(
|
||||
isinstance(results[0].members[0], WebIDL.IDLMethod),
|
||||
"Stringifer should be method",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestStringifier {
|
||||
stringifier;
|
||||
stringifier;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow two 'stringifier;'")
|
||||
|
||||
parser = parser.reset()
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestStringifier {
|
||||
stringifier;
|
||||
stringifier DOMString foo();
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow a 'stringifier;' and a 'stringifier()'")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestStringifier {
|
||||
stringifier attribute DOMString foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.ok(
|
||||
isinstance(results[0].members[0], WebIDL.IDLAttribute),
|
||||
"Stringifier attribute should be an attribute",
|
||||
)
|
||||
stringifier = results[0].members[1]
|
||||
harness.ok(
|
||||
isinstance(stringifier, WebIDL.IDLMethod),
|
||||
"Stringifier attribute should insert a method",
|
||||
)
|
||||
harness.ok(stringifier.isStringifier(), "Inserted method should be a stringifier")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestStringifier {};
|
||||
interface mixin TestStringifierMixin {
|
||||
stringifier attribute DOMString foo;
|
||||
};
|
||||
TestStringifier includes TestStringifierMixin;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
harness.ok(
|
||||
isinstance(results[0].members[0], WebIDL.IDLAttribute),
|
||||
"Stringifier attribute should be an attribute",
|
||||
)
|
||||
stringifier = results[0].members[1]
|
||||
harness.ok(
|
||||
isinstance(stringifier, WebIDL.IDLMethod),
|
||||
"Stringifier attribute should insert a method",
|
||||
)
|
||||
harness.ok(stringifier.isStringifier(), "Inserted method should be a stringifier")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestStringifier {
|
||||
stringifier attribute USVString foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
stringifier = results[0].members[1]
|
||||
harness.ok(
|
||||
stringifier.signatures()[0][0].isUSVString(),
|
||||
"Stringifier attributes should allow USVString",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestStringifier {
|
||||
[Throws, NeedsSubjectPrincipal]
|
||||
stringifier attribute USVString foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
stringifier = results[0].members[1]
|
||||
harness.ok(
|
||||
stringifier.getExtendedAttribute("Throws"),
|
||||
"Stringifier attributes should support [Throws]",
|
||||
)
|
||||
harness.ok(
|
||||
stringifier.getExtendedAttribute("NeedsSubjectPrincipal"),
|
||||
"Stringifier attributes should support [NeedsSubjectPrincipal]",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestStringifier {
|
||||
stringifier attribute UTF8String foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
stringifier = results[0].members[1]
|
||||
harness.ok(
|
||||
stringifier.signatures()[0][0].isUTF8String(),
|
||||
"Stringifier attributes should allow UTF8String",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestStringifier {
|
||||
stringifier attribute ByteString foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow ByteString")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestStringifier {
|
||||
stringifier;
|
||||
stringifier attribute DOMString foo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow a 'stringifier;' and a stringifier attribute")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface TestStringifier {
|
||||
stringifier attribute DOMString foo;
|
||||
stringifier attribute DOMString bar;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should not allow multiple stringifier attributes")
|
||||
312
third_party/WebIDL/tests/test_toJSON.py
vendored
Normal file
312
third_party/WebIDL/tests/test_toJSON.py
vendored
Normal file
@@ -0,0 +1,312 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Test {
|
||||
object toJSON();
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(not threw, "Should allow a toJSON method.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Test {
|
||||
object toJSON(object arg);
|
||||
object toJSON(long arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow overloads of a toJSON method.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Test {
|
||||
object toJSON(object arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow a toJSON method with arguments.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Test {
|
||||
long toJSON();
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(not threw, "Should allow a toJSON method with 'long' as return type.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Test {
|
||||
[Default] object toJSON();
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
not threw, "Should allow a default toJSON method with 'object' as return type."
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Test {
|
||||
[Default] long toJSON();
|
||||
};
|
||||
"""
|
||||
)
|
||||
parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should not allow a default toJSON method with non-'object' as return type.",
|
||||
)
|
||||
|
||||
JsonTypes = [
|
||||
"byte",
|
||||
"octet",
|
||||
"short",
|
||||
"unsigned short",
|
||||
"long",
|
||||
"unsigned long",
|
||||
"long long",
|
||||
"unsigned long long",
|
||||
"float",
|
||||
"unrestricted float",
|
||||
"double",
|
||||
"unrestricted double",
|
||||
"boolean",
|
||||
"DOMString",
|
||||
"ByteString",
|
||||
"UTF8String",
|
||||
"USVString",
|
||||
"Enum",
|
||||
"InterfaceWithToJSON",
|
||||
"object",
|
||||
]
|
||||
|
||||
nonJsonTypes = [
|
||||
"InterfaceWithoutToJSON",
|
||||
"any",
|
||||
"Int8Array",
|
||||
"Int16Array",
|
||||
"Int32Array",
|
||||
"Uint8Array",
|
||||
"Uint16Array",
|
||||
"Uint32Array",
|
||||
"Uint8ClampedArray",
|
||||
"Float32Array",
|
||||
"Float64Array",
|
||||
"ArrayBuffer",
|
||||
]
|
||||
|
||||
def doTest(testIDL, shouldThrow, description):
|
||||
p = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
p.parse(
|
||||
testIDL
|
||||
+ """
|
||||
enum Enum { "a", "b", "c" };
|
||||
interface InterfaceWithToJSON { long toJSON(); };
|
||||
interface InterfaceWithoutToJSON {};
|
||||
"""
|
||||
)
|
||||
p.finish()
|
||||
except Exception as x:
|
||||
threw = True
|
||||
harness.ok(x.message == "toJSON method has non-JSON return type", x)
|
||||
harness.check(threw, shouldThrow, description)
|
||||
|
||||
for type in JsonTypes:
|
||||
doTest(
|
||||
"interface Test { %s toJSON(); };" % type,
|
||||
False,
|
||||
"%s should be a JSON type" % type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface Test { sequence<%s> toJSON(); };" % type,
|
||||
False,
|
||||
"sequence<%s> should be a JSON type" % type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"dictionary Foo { %s foo; }; " "interface Test { Foo toJSON(); }; " % type,
|
||||
False,
|
||||
"dictionary containing only JSON type (%s) should be a JSON type" % type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"dictionary Foo { %s foo; }; dictionary Bar : Foo { }; "
|
||||
"interface Test { Bar toJSON(); }; " % type,
|
||||
False,
|
||||
"dictionary whose ancestors only contain JSON types should be a JSON type",
|
||||
)
|
||||
|
||||
doTest(
|
||||
"dictionary Foo { any foo; }; dictionary Bar : Foo { %s bar; };"
|
||||
"interface Test { Bar toJSON(); };" % type,
|
||||
True,
|
||||
"dictionary whose ancestors contain non-JSON types should not be a JSON type",
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface Test { record<DOMString, %s> toJSON(); };" % type,
|
||||
False,
|
||||
"record<DOMString, %s> should be a JSON type" % type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface Test { record<ByteString, %s> toJSON(); };" % type,
|
||||
False,
|
||||
"record<ByteString, %s> should be a JSON type" % type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface Test { record<UTF8String, %s> toJSON(); };" % type,
|
||||
False,
|
||||
"record<UTF8String, %s> should be a JSON type" % type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface Test { record<USVString, %s> toJSON(); };" % type,
|
||||
False,
|
||||
"record<USVString, %s> should be a JSON type" % type,
|
||||
)
|
||||
|
||||
otherUnionType = "Foo" if type != "object" else "long"
|
||||
doTest(
|
||||
"interface Foo { object toJSON(); };"
|
||||
"interface Test { (%s or %s) toJSON(); };" % (otherUnionType, type),
|
||||
False,
|
||||
"union containing only JSON types (%s or %s) should be a JSON type"
|
||||
% (otherUnionType, type),
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface test { %s? toJSON(); };" % type,
|
||||
False,
|
||||
"Nullable type (%s) should be a JSON type" % type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface Foo : InterfaceWithoutToJSON { %s toJSON(); };"
|
||||
"interface Test { Foo toJSON(); };" % type,
|
||||
False,
|
||||
"interface with toJSON should be a JSON type",
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface Foo : InterfaceWithToJSON { };" "interface Test { Foo toJSON(); };",
|
||||
False,
|
||||
"inherited interface with toJSON should be a JSON type",
|
||||
)
|
||||
|
||||
for type in nonJsonTypes:
|
||||
doTest(
|
||||
"interface Test { %s toJSON(); };" % type,
|
||||
True,
|
||||
"%s should not be a JSON type" % type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface Test { sequence<%s> toJSON(); };" % type,
|
||||
True,
|
||||
"sequence<%s> should not be a JSON type" % type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"dictionary Foo { %s foo; }; " "interface Test { Foo toJSON(); }; " % type,
|
||||
True,
|
||||
"Dictionary containing a non-JSON type (%s) should not be a JSON type"
|
||||
% type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"dictionary Foo { %s foo; }; dictionary Bar : Foo { }; "
|
||||
"interface Test { Bar toJSON(); }; " % type,
|
||||
True,
|
||||
"dictionary whose ancestors only contain non-JSON types should not be a JSON type",
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface Test { record<DOMString, %s> toJSON(); };" % type,
|
||||
True,
|
||||
"record<DOMString, %s> should not be a JSON type" % type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface Test { record<ByteString, %s> toJSON(); };" % type,
|
||||
True,
|
||||
"record<ByteString, %s> should not be a JSON type" % type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface Test { record<USVString, %s> toJSON(); };" % type,
|
||||
True,
|
||||
"record<USVString, %s> should not be a JSON type" % type,
|
||||
)
|
||||
|
||||
if type != "any":
|
||||
doTest(
|
||||
"interface Foo { object toJSON(); }; "
|
||||
"interface Test { (Foo or %s) toJSON(); };" % type,
|
||||
True,
|
||||
"union containing a non-JSON type (%s) should not be a JSON type"
|
||||
% type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface test { %s? toJSON(); };" % type,
|
||||
True,
|
||||
"Nullable type (%s) should not be a JSON type" % type,
|
||||
)
|
||||
|
||||
doTest(
|
||||
"dictionary Foo { long foo; any bar; };" "interface Test { Foo toJSON(); };",
|
||||
True,
|
||||
"dictionary containing a non-JSON type should not be a JSON type",
|
||||
)
|
||||
|
||||
doTest(
|
||||
"interface Foo : InterfaceWithoutToJSON { }; "
|
||||
"interface Test { Foo toJSON(); };",
|
||||
True,
|
||||
"interface without toJSON should not be a JSON type",
|
||||
)
|
||||
80
third_party/WebIDL/tests/test_treatNonCallableAsNull.py
vendored
Normal file
80
third_party/WebIDL/tests/test_treatNonCallableAsNull.py
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
[TreatNonCallableAsNull] callback Function = any(any... arguments);
|
||||
|
||||
interface TestTreatNonCallableAsNull1 {
|
||||
attribute Function? onfoo;
|
||||
attribute Function onbar;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
iface = results[1]
|
||||
attr = iface.members[0]
|
||||
harness.check(attr.type.treatNonCallableAsNull(), True, "Got the expected value")
|
||||
attr = iface.members[1]
|
||||
harness.check(attr.type.treatNonCallableAsNull(), False, "Got the expected value")
|
||||
|
||||
parser = parser.reset()
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
callback Function = any(any... arguments);
|
||||
|
||||
interface TestTreatNonCallableAsNull2 {
|
||||
[TreatNonCallableAsNull] attribute Function onfoo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
callback Function = any(any... arguments);
|
||||
|
||||
[TreatNonCallableAsNull]
|
||||
interface TestTreatNonCallableAsNull3 {
|
||||
attribute Function onfoo;
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
[TreatNonCallableAsNull, LegacyTreatNonObjectAsNull]
|
||||
callback Function = any(any... arguments);
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
97
third_party/WebIDL/tests/test_typedef.py
vendored
Normal file
97
third_party/WebIDL/tests/test_typedef.py
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
import WebIDL
|
||||
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse(
|
||||
"""
|
||||
typedef long mylong;
|
||||
typedef long? mynullablelong;
|
||||
interface Foo {
|
||||
const mylong X = 5;
|
||||
undefined foo(optional mynullablelong arg = 7);
|
||||
undefined bar(optional mynullablelong arg = null);
|
||||
undefined baz(mylong arg);
|
||||
};
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.check(
|
||||
results[2].members[1].signatures()[0][1][0].type.name,
|
||||
"LongOrNull",
|
||||
"Should expand typedefs",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef long? mynullablelong;
|
||||
interface Foo {
|
||||
undefined foo(mynullablelong? Y);
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown on nullable inside nullable arg.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef long? mynullablelong;
|
||||
interface Foo {
|
||||
const mynullablelong? X = 5;
|
||||
};
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown on nullable inside nullable const.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo {
|
||||
const mynullablelong? X = 5;
|
||||
};
|
||||
typedef long? mynullablelong;
|
||||
"""
|
||||
)
|
||||
results = parser.finish()
|
||||
except WebIDL.WebIDLError:
|
||||
threw = True
|
||||
|
||||
harness.ok(
|
||||
threw,
|
||||
"Should have thrown on nullable inside nullable const typedef "
|
||||
"after interface.",
|
||||
)
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse(
|
||||
"""
|
||||
interface Foo {
|
||||
const mylong X = 5;
|
||||
};
|
||||
typedef long mylong;
|
||||
"""
|
||||
)
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.check(
|
||||
results[0].members[0].type.name,
|
||||
"Long",
|
||||
"Should expand typedefs that come before interface",
|
||||
)
|
||||
19
third_party/WebIDL/tests/test_typedef_identifier_conflict.py
vendored
Normal file
19
third_party/WebIDL/tests/test_typedef_identifier_conflict.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
exception = None
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
typedef long foo;
|
||||
typedef long foo;
|
||||
"""
|
||||
)
|
||||
|
||||
parser.finish()
|
||||
except Exception as e:
|
||||
exception = e
|
||||
|
||||
harness.ok(exception, "Should have thrown.")
|
||||
harness.ok(
|
||||
"Multiple unresolvable definitions of identifier 'foo'" in str(exception),
|
||||
"Should have a sane exception message",
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user