Merge mozilla-central to autoland. a=merge CLOSED TREE

This commit is contained in:
Narcis Beleuzu 2018-08-30 20:07:36 +03:00
Родитель 19d09489b9 05d91d3e02
Коммит 682a2942bf
68 изменённых файлов: 2175 добавлений и 426 удалений

Просмотреть файл

@ -74,27 +74,6 @@
// show popup again for the next test
gQueue.push(new synthClick("popupbutton", new nofocusChecker()));
if (!MAC) {
// click menubutton of the 'menubutton' button while popup of button open.
gQueue.push(new synthClick("mbb", new focusChecker("mbb"), { where: "right" }));
// close popup, focus stays on menubutton, fire focus event
gQueue.push(new synthEscapeKey("mbb", new focusChecker("mbb")));
// click menubutton, open popup, focus stays on menubutton
gQueue.push(new synthClick("mbb", new nofocusChecker(), { where: "right" }));
// select first menu item ("item 1"), focus on menu item
gQueue.push(new synthDownKey("mbb", new focusChecker("mbb_item1")));
// choose select menu item, focus gets back to menubutton
gQueue.push(new synthEnterKey("mbb_item1", new focusChecker("mbb")));
// open popup, focus stays on menubutton
gQueue.push(new synthOpenComboboxKey("mbb", new nofocusChecker()));
// select second menu item ("item 2"), focus on menu item
gQueue.push(new synthUpKey("menubutton", new focusChecker("mbb_item2")));
// click on menu item of menubutton menu, focus menubutton
gQueue.push(new synthClick("mbb_item2", new focusChecker("mbb")));
} else {
todo(false, "mbb tests time out on OS X, fix bug 746970 and reenable!");
}
// focus colorpicker button
gQueue.push(new synthFocus("colorpicker"));
// click on button, open popup, focus goes to current color button
@ -139,8 +118,6 @@ if (!MAC) {
</radiogroup>
<checkbox id="checkbox" label="checkbox"/>
<button id="button" label="button"/>
<button id="checkbutton" type="checkbox" label="checkbutton"/>
<button id="radiobutton" type="radio" group="rbgroup" label="radio1"/>
<button id="menubutton" type="menu" label="menubutton">
<menupopup>
@ -148,12 +125,9 @@ if (!MAC) {
<menuitem id="mb_item2" label="item2"/>
</menupopup>
</button>
<button id="mbb" type="menu-button" label="menubutton button">
<menupopup>
<menuitem id="mbb_item1" label="item1"/>
<menuitem id="mbb_item2" label="item2"/>
</menupopup>
</button>
<button id="checkbutton" type="checkbox" label="checkbutton"/>
<button id="radiobutton" type="radio" group="rbgroup" label="radio1"/>
<colorpicker id="colorpicker" type="button" label="color picker"
color="#FFFFFF"/>

Просмотреть файл

@ -25,7 +25,6 @@
// aria-pressed
testRole("pressed_button", ROLE_TOGGLE_BUTTON);
testRole("pressed_menu_button", ROLE_TOGGLE_BUTTON);
SimpleTest.finish();
}
@ -59,11 +58,6 @@
<label id="presentation_label" role="presentation" value="label"/>
<description id="presentation_descr" role="presentation" value="description"/>
<button id="pressed_button" aria-pressed="true" label="I am pressed" />
<button id="pressed_menu_button" aria-pressed="true" label="I am pressed" type="menu-button">
<menupopup>
<menuitem label="I am a menu item" />
</menupopup>
</button>
</vbox>

Просмотреть файл

@ -22,7 +22,6 @@
{
// aria-pressed
testStates("pressed_button", STATE_PRESSED, 0, STATE_CHECKABLE);
testStates("pressed_menu_button", STATE_PRESSED | STATE_HASPOPUP, 0, STATE_CHECKABLE);
testStates("tabs", STATE_MULTISELECTABLE);
// Make sure XUL selection works, since aria-selected defaults to false.
@ -56,11 +55,6 @@
<vbox flex="1">
<button id="pressed_button" aria-pressed="true" label="I am pressed" />
<button id="pressed_menu_button" aria-pressed="true" label="I am pressed" type="menu-button">
<menupopup>
<menuitem label="I am a menu item" />
</menupopup>
</button>
<tabbox>
<tabs id="tabs" aria-multiselectable="true">

Просмотреть файл

@ -157,25 +157,9 @@ bool
XULButtonAccessible::IsAcceptableChild(nsIContent* aEl) const
{
// In general XUL button has not accessible children. Nevertheless menu
// buttons can have button (@type="menu-button") and popup accessibles
// (@type="menu-button", @type="menu" or columnpicker.
// Get an accessible for menupopup or popup elements.
if (aEl->IsXULElement(nsGkAtoms::menupopup) ||
aEl->IsXULElement(nsGkAtoms::popup)) {
return true;
}
// Button and toolbarbutton are real buttons. Get an accessible
// for it. Ignore dropmarker button which is placed as a last child.
if ((!aEl->IsXULElement(nsGkAtoms::button) &&
!aEl->IsXULElement(nsGkAtoms::toolbarbutton)) ||
aEl->IsXULElement(nsGkAtoms::dropMarker)) {
return false;
}
return mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
nsGkAtoms::menuButton, eCaseMatters);
// buttons can have popup accessibles (@type="menu" or columnpicker).
return aEl->IsXULElement(nsGkAtoms::menupopup) ||
aEl->IsXULElement(nsGkAtoms::popup);
}
////////////////////////////////////////////////////////////////////////////////
@ -184,12 +168,8 @@ XULButtonAccessible::IsAcceptableChild(nsIContent* aEl) const
bool
XULButtonAccessible::ContainsMenu() const
{
static Element::AttrValuesArray strings[] =
{&nsGkAtoms::menu, &nsGkAtoms::menuButton, nullptr};
return mContent->AsElement()->FindAttrValueIn(kNameSpaceID_None,
nsGkAtoms::type,
strings, eCaseMatters) >= 0;
return mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
nsGkAtoms::menu, eCaseMatters);
}
////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -370,6 +370,15 @@ DownloadsSubview.Button = class extends DownloadsViewUI.DownloadElementShell {
this.element.classList.add("subviewbutton", "subviewbutton-iconic", "download",
"download-state");
let hover = event => {
if (event.originalTarget.classList.contains("action-button")) {
this.element.classList.toggle("downloadHoveringButton",
event.type == "mouseover");
}
};
this.element.addEventListener("mouseover", hover);
this.element.addEventListener("mouseout", hover);
}
get browserWindow() {

Просмотреть файл

@ -111,9 +111,8 @@
</binding>
<binding id="download-subview-toolbarbutton"
extends="chrome://global/content/bindings/button.xml#menu-button-base">
extends="chrome://global/content/bindings/button.xml#button-base">
<content>
<children includes="observes|template|menupopup|panel|tooltip"/>
<xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label,consumeanchor"/>
<xul:vbox class="toolbarbutton-text" flex="1">
<xul:label crop="end" xbl:inherits="value=label,accesskey,crop,wrap"/>

Просмотреть файл

@ -230,15 +230,15 @@
.subviewbutton.download:hover:-moz-any(:not([openLabel]),:not([exists])):not([retryLabel]) > .toolbarbutton-text > .status-full,
/* When a Download is hovered and the it can be retried, but the action button
is _not_ hovered, keep showing the full status message. */
.subviewbutton.download:hover[retryLabel]:not([buttonover]) > .toolbarbutton-text > .status-full,
.subviewbutton.download:hover[retryLabel]:not(.downloadHoveringButton) > .toolbarbutton-text > .status-full,
/* When a Download is hovered and the file can be opened, but the action button
is _not_ hovered, show the 'Open File' status label. */
.subviewbutton.download:hover[openLabel][exists]:not([buttonover]) > .toolbarbutton-text > .status-open,
.subviewbutton.download:hover[openLabel][exists]:not(.downloadHoveringButton) > .toolbarbutton-text > .status-open,
/* When a Download is hovered - its action button explicitly - and it can be
retried, show the 'Retry Download' label. */
.subviewbutton.download:hover[retryLabel][buttonover] > .toolbarbutton-text > .status-retry,
.subviewbutton.download:hover[retryLabel].downloadHoveringButton > .toolbarbutton-text > .status-retry,
/* When a Download is hovered - its action button explicitly - and the file can
be shown in the OS's shell, show the 'Open Containing Folder' label. */
.subviewbutton.download:hover[openLabel][exists][buttonover] > .toolbarbutton-text > .status-show {
.subviewbutton.download:hover[openLabel][exists].downloadHoveringButton > .toolbarbutton-text > .status-show {
display: inline;
}

Просмотреть файл

@ -159,7 +159,6 @@ skip-if = !e10s || !crashreporter # the tab's process is killed during the test.
[browser_ext_sessions_window_tab_value.js]
[browser_ext_settings_overrides_default_search.js]
[browser_ext_sidebarAction.js]
skip-if = debug #Bug 1483325
[browser_ext_sidebarAction_browser_style.js]
[browser_ext_sidebarAction_context.js]
[browser_ext_sidebarAction_contextMenu.js]

Просмотреть файл

@ -70,6 +70,7 @@ add_task(async function sidebar_initial_install() {
ok(document.getElementById("sidebar-box").hidden, "sidebar box is not visible");
let extension = ExtensionTestUtils.loadExtension(getExtData());
await extension.startup();
await extension.awaitMessage("sidebar");
// Test sidebar is opened on install
ok(!document.getElementById("sidebar-box").hidden, "sidebar box is visible");

Просмотреть файл

@ -154,7 +154,7 @@ public:
bool IsTargetThread() const
{
return NS_IsMainThread() == mIsMainThread;
return NS_GetCurrentThread() == mTargetThread;
}
uint16_t ReadyState()
@ -312,6 +312,14 @@ public:
uint64_t mInnerWindowID;
private:
// Pointer to the target thread for checking whether we are
// on the target thread. This is intentionally a non-owning
// pointer in order not to affect the thread destruction
// sequence. This pointer must only be compared for equality
// and must not be dereferenced.
nsIThread* mTargetThread;
// prevent bad usage
EventSourceImpl(const EventSourceImpl& x) = delete;
EventSourceImpl& operator=(const EventSourceImpl& x) = delete;
@ -348,6 +356,7 @@ EventSourceImpl::EventSourceImpl(EventSource* aEventSource)
, mScriptLine(0)
, mScriptColumn(0)
, mInnerWindowID(0)
, mTargetThread(NS_GetCurrentThread())
{
MOZ_ASSERT(mEventSource);
if (!mIsMainThread) {

Просмотреть файл

@ -4106,7 +4106,7 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcess
already_AddRefed<gfxPattern> GetPatternFor(Style aStyle)
{
const CanvasPattern* pat = mCtx->CurrentState().patternStyles[aStyle];
RefPtr<gfxPattern> pattern = new gfxPattern(pat->mSurface, Matrix());
RefPtr<gfxPattern> pattern = new gfxPattern(pat->mSurface, pat->mTransform);
pattern->SetExtend(CvtCanvasRepeatToGfxRepeat(pat->mRepeat));
return pattern.forget();
}

Просмотреть файл

@ -1486,14 +1486,9 @@ EventStateManager::CreateClickHoldTimer(nsPresContext* inPresContext,
// if content clicked on has a popup, don't even start the timer
// since we'll end up conflicting and both will show.
if (mGestureDownContent) {
// check for the |popup| attribute
if (nsContentUtils::HasNonEmptyAttr(mGestureDownContent, kNameSpaceID_None,
nsGkAtoms::popup))
return;
// check for a <menubutton> like bookmarks
if (mGestureDownContent->IsXULElement(nsGkAtoms::menubutton))
if (mGestureDownContent &&
nsContentUtils::HasNonEmptyAttr(mGestureDownContent, kNameSpaceID_None,
nsGkAtoms::popup)) {
return;
}

Просмотреть файл

@ -906,7 +906,7 @@ JS_TransplantObject(JSContext* cx, HandleObject origobj, HandleObject target)
// destination, then we know that we won't find a wrapper in the
// destination's cross compartment map and that the same
// object will continue to work.
AutoRealmUnchecked ar(cx, origobj->deprecatedRealm());
AutoRealmUnchecked ar(cx, origobj->nonCCWRealm());
if (!JSObject::swap(cx, origobj, target))
MOZ_CRASH();
newIdentity = origobj;
@ -940,7 +940,7 @@ JS_TransplantObject(JSContext* cx, HandleObject origobj, HandleObject target)
// Lastly, update the original object to point to the new one.
if (origobj->compartment() != destination) {
RootedObject newIdentityWrapper(cx, newIdentity);
AutoRealmUnchecked ar(cx, origobj->deprecatedRealm());
AutoRealmUnchecked ar(cx, origobj->nonCCWRealm());
if (!JS_WrapObject(cx, &newIdentityWrapper))
MOZ_CRASH();
MOZ_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity);
@ -3601,6 +3601,7 @@ CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject env, Handle
// Note that funobj can be in a different compartment.
if (!funobj->is<JSFunction>()) {
MOZ_RELEASE_ASSERT(!IsCrossCompartmentWrapper(funobj));
AutoRealm ar(cx, funobj);
RootedValue v(cx, ObjectValue(*funobj));
ReportIsNotFunction(cx, v);
@ -3609,7 +3610,7 @@ CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject env, Handle
RootedFunction fun(cx, &funobj->as<JSFunction>());
if (fun->isInterpretedLazy()) {
AutoRealm ar(cx, funobj);
AutoRealm ar(cx, fun);
if (!JSFunction::getOrCreateScript(cx, fun))
return nullptr;
}

Просмотреть файл

@ -822,6 +822,8 @@ FormatValue(JSContext* cx, const Value& vArg, JSAutoByteString& bytes)
*/
RootedString str(cx);
if (v.isObject()) {
if (IsCrossCompartmentWrapper(&v.toObject()))
return "[cross-compartment wrapper]";
AutoRealm ar(cx, &v.toObject());
str = ToString<CanGC>(cx, v);
} else {

Просмотреть файл

@ -995,8 +995,8 @@ EnqueueJob(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (!IsCallable(args.get(0))) {
JS_ReportErrorASCII(cx, "EnqueueJob's first argument must be callable");
if (!IsFunctionObject(args.get(0))) {
JS_ReportErrorASCII(cx, "EnqueueJob's first argument must be a function");
return false;
}
@ -1054,7 +1054,7 @@ SetPromiseRejectionTrackerCallback(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (!IsCallable(args.get(0))) {
if (!IsFunctionObject(args.get(0))) {
JS_ReportErrorASCII(cx,
"setPromiseRejectionTrackerCallback expects a function as its sole "
"argument");

Просмотреть файл

@ -374,7 +374,7 @@ def load_wpt_tests(requested_paths, excluded_paths, debug, wasm):
if script.startswith("/"):
return os.path.join(wpt, script[1:])
return os.path.join(test_path, script)
return os.path.join(wpt, os.path.dirname(test_path), script)
return [
RefTestCase(

Просмотреть файл

@ -393,7 +393,7 @@ inline void
JSContext::enterRealmOf(JSObject* target)
{
MOZ_ASSERT(JS::CellIsNotGray(target));
enterRealm(target->deprecatedRealm());
enterRealm(target->nonCCWRealm());
}
inline void

Просмотреть файл

@ -1193,7 +1193,7 @@ js::RunJobs(JSContext* cx)
if (i == cx->jobQueue->length() - 1)
JS::JobQueueIsEmpty(cx);
AutoRealm ar(cx, job);
AutoRealm ar(cx, &job->as<JSFunction>());
{
if (!JS::Call(cx, UndefinedHandleValue, job, args, &rval)) {
// Nothing we can do about uncatchable exceptions.

Просмотреть файл

@ -396,12 +396,6 @@ SetNewObjectMetadata(JSContext* cx, T* obj)
} // namespace js
inline js::GlobalObject&
JSObject::deprecatedGlobal() const
{
return *deprecatedRealm()->unsafeUnbarrieredMaybeGlobal();
}
inline js::GlobalObject&
JSObject::nonCCWGlobal() const
{

Просмотреть файл

@ -430,9 +430,6 @@ class JSObject : public js::gc::Cell
*/
inline JSObject* enclosingEnvironment() const;
// Deprecated: call nonCCWGlobal or NativeObject::global() instead!
inline js::GlobalObject& deprecatedGlobal() const;
// Cross-compartment wrappers are not associated with a single realm/global,
// so these methods assert the object is not a CCW.
inline js::GlobalObject& nonCCWGlobal() const;

Просмотреть файл

@ -889,6 +889,9 @@ class MOZ_RAII AssertRealmUnchanged
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
// AutoRealm can be used to enter the realm of a JSObject, JSScript or
// ObjectGroup. It must not be used with cross-compartment wrappers, because
// CCWs are not associated with a single realm.
class AutoRealm
{
JSContext* const cx_;

Просмотреть файл

@ -241,7 +241,6 @@ GetClickableAncestor(nsIFrame* aFrame, nsAtom* stopAt = nullptr, nsAutoString* a
nsGkAtoms::checkbox,
nsGkAtoms::radio,
nsGkAtoms::menu,
nsGkAtoms::menubutton,
nsGkAtoms::menuitem,
nsGkAtoms::menulist,
nsGkAtoms::scrollbarbutton,

Просмотреть файл

@ -1789,14 +1789,10 @@ ConsumeOutsideClicksResult nsMenuPopupFrame::ConsumeOutsideClicks()
ni->Equals(nsGkAtoms::popupset, kNameSpaceID_XUL) ||
((ni->Equals(nsGkAtoms::button, kNameSpaceID_XUL) ||
ni->Equals(nsGkAtoms::toolbarbutton, kNameSpaceID_XUL)) &&
(parentContent->AsElement()->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::type,
nsGkAtoms::menu,
eCaseMatters) ||
parentContent->AsElement()->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::type,
nsGkAtoms::menuButton,
eCaseMatters)))) {
parentContent->AsElement()->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::type,
nsGkAtoms::menu,
eCaseMatters))) {
return ConsumeOutsideClicks_Never;
}
#endif

Просмотреть файл

@ -1122,6 +1122,25 @@ nsJARChannel::OnStartRequest(nsIRequest *req, nsISupports *ctx)
mRequest = req;
nsresult rv = mListener->OnStartRequest(this, mListenerContext);
mRequest = nullptr;
NS_ENSURE_SUCCESS(rv, rv);
// Restrict loadable content types.
nsAutoCString contentType;
GetContentType(contentType);
auto contentPolicyType = mLoadInfo->GetExternalContentPolicyType();
if (contentType.Equals(APPLICATION_HTTP_INDEX_FORMAT) &&
contentPolicyType != nsIContentPolicy::TYPE_DOCUMENT &&
contentPolicyType != nsIContentPolicy::TYPE_FETCH) {
return NS_ERROR_CORRUPTED_CONTENT;
}
if (contentPolicyType == nsIContentPolicy::TYPE_STYLESHEET &&
!contentType.EqualsLiteral(TEXT_CSS)) {
return NS_ERROR_CORRUPTED_CONTENT;
}
if (contentPolicyType == nsIContentPolicy::TYPE_SCRIPT &&
!nsContentUtils::IsJavascriptMIMEType(NS_ConvertUTF8toUTF16(contentType))) {
return NS_ERROR_CORRUPTED_CONTENT;
}
return rv;
}

Просмотреть файл

@ -310199,6 +310199,11 @@
{}
]
],
"wasm/jsapi/table/assertions.js": [
[
{}
]
],
"wasm/jsapi/wasm-constants.js": [
[
{}
@ -394822,6 +394827,70 @@
{}
]
],
"wasm/jsapi/global/constructor.any.js": [
[
"/wasm/jsapi/global/constructor.any.html",
{}
],
[
"/wasm/jsapi/global/constructor.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/global/constructor.any.worker.html",
{}
]
],
"wasm/jsapi/global/toString.any.js": [
[
"/wasm/jsapi/global/toString.any.html",
{}
],
[
"/wasm/jsapi/global/toString.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/global/toString.any.worker.html",
{}
]
],
"wasm/jsapi/global/value-set.any.js": [
[
"/wasm/jsapi/global/value-set.any.html",
{}
],
[
"/wasm/jsapi/global/value-set.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/global/value-set.any.worker.html",
{}
]
],
"wasm/jsapi/global/valueOf.any.js": [
[
"/wasm/jsapi/global/valueOf.any.html",
{}
],
[
"/wasm/jsapi/global/valueOf.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/global/valueOf.any.worker.html",
{}
]
],
"wasm/jsapi/instance/constructor-bad-imports.any.js": [
[
"/wasm/jsapi/instance/constructor-bad-imports.any.html",
@ -394854,6 +394923,38 @@
{}
]
],
"wasm/jsapi/instance/exports.any.js": [
[
"/wasm/jsapi/instance/exports.any.html",
{}
],
[
"/wasm/jsapi/instance/exports.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/instance/exports.any.worker.html",
{}
]
],
"wasm/jsapi/instance/toString.any.js": [
[
"/wasm/jsapi/instance/toString.any.html",
{}
],
[
"/wasm/jsapi/instance/toString.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/instance/toString.any.worker.html",
{}
]
],
"wasm/jsapi/interface.any.js": [
[
"/wasm/jsapi/interface.any.html",
@ -394870,6 +394971,22 @@
{}
]
],
"wasm/jsapi/memory/buffer.any.js": [
[
"/wasm/jsapi/memory/buffer.any.html",
{}
],
[
"/wasm/jsapi/memory/buffer.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/memory/buffer.any.worker.html",
{}
]
],
"wasm/jsapi/memory/constructor.any.js": [
[
"/wasm/jsapi/memory/constructor.any.html",
@ -394886,6 +395003,38 @@
{}
]
],
"wasm/jsapi/memory/grow.any.js": [
[
"/wasm/jsapi/memory/grow.any.html",
{}
],
[
"/wasm/jsapi/memory/grow.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/memory/grow.any.worker.html",
{}
]
],
"wasm/jsapi/memory/toString.any.js": [
[
"/wasm/jsapi/memory/toString.any.html",
{}
],
[
"/wasm/jsapi/memory/toString.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/memory/toString.any.worker.html",
{}
]
],
"wasm/jsapi/module/constructor.any.js": [
[
"/wasm/jsapi/module/constructor.any.html",
@ -394950,6 +395099,22 @@
{}
]
],
"wasm/jsapi/module/toString.any.js": [
[
"/wasm/jsapi/module/toString.any.html",
{}
],
[
"/wasm/jsapi/module/toString.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/module/toString.any.worker.html",
{}
]
],
"wasm/jsapi/table/constructor.any.js": [
[
"/wasm/jsapi/table/constructor.any.html",
@ -394966,6 +395131,70 @@
{}
]
],
"wasm/jsapi/table/get-set.any.js": [
[
"/wasm/jsapi/table/get-set.any.html",
{}
],
[
"/wasm/jsapi/table/get-set.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/table/get-set.any.worker.html",
{}
]
],
"wasm/jsapi/table/grow.any.js": [
[
"/wasm/jsapi/table/grow.any.html",
{}
],
[
"/wasm/jsapi/table/grow.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/table/grow.any.worker.html",
{}
]
],
"wasm/jsapi/table/length.any.js": [
[
"/wasm/jsapi/table/length.any.html",
{}
],
[
"/wasm/jsapi/table/length.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/table/length.any.worker.html",
{}
]
],
"wasm/jsapi/table/toString.any.js": [
[
"/wasm/jsapi/table/toString.any.html",
{}
],
[
"/wasm/jsapi/table/toString.any.js",
{
"jsshell": true
}
],
[
"/wasm/jsapi/table/toString.any.worker.html",
{}
]
],
"wasm/wasm_local_iframe_test.html": [
[
"/wasm/wasm_local_iframe_test.html",
@ -647673,40 +647902,100 @@
"86700298dfae66de6f4d026baa29e6e3584320f7",
"testharness"
],
"wasm/jsapi/global/constructor.any.js": [
"7a45cc4191c55684cde187fc73fb9741d6f5c2c5",
"testharness"
],
"wasm/jsapi/global/toString.any.js": [
"ca025576c2b49604f053c83002f3a9cc8ef41a7b",
"testharness"
],
"wasm/jsapi/global/value-set.any.js": [
"b4e6770f10ed9e3ad55b9ae18ee96deda3ff171e",
"testharness"
],
"wasm/jsapi/global/valueOf.any.js": [
"176c5a784698399351eedeaac0ec305aa8ab7b81",
"testharness"
],
"wasm/jsapi/instance/constructor-bad-imports.any.js": [
"24c51c10dc5df9d52c06bfb0715e435b17f24f7a",
"testharness"
],
"wasm/jsapi/instance/constructor.any.js": [
"93a3ffda033729d64562a583e823fab05f35f6fe",
"61a8f53a014c192f28a0c25252cf3702561e7191",
"testharness"
],
"wasm/jsapi/instance/exports.any.js": [
"31423918720543da2ba25e392267bf541b756242",
"testharness"
],
"wasm/jsapi/instance/toString.any.js": [
"08dcb14a50d04f6db196626ddb93f2b50da8f055",
"testharness"
],
"wasm/jsapi/interface.any.js": [
"64c1f60da1c7888be994f222af69f401402ae5f4",
"5d76ac56ec5fafde8dde3924df863a2694bd6691",
"testharness"
],
"wasm/jsapi/memory/buffer.any.js": [
"b04460b6c5e56cf1fe990e3107aa9efcb4964ed5",
"testharness"
],
"wasm/jsapi/memory/constructor.any.js": [
"33256f85e45749cc46842dccbd1ee7c40db41ae5",
"f9907ca6104d8ec76861e43b6b981042d86fb865",
"testharness"
],
"wasm/jsapi/memory/grow.any.js": [
"95300399f192b7eab70dd8f07c43f4db37eebe01",
"testharness"
],
"wasm/jsapi/memory/toString.any.js": [
"4e15d75ea20f1ebfeba5dc7c8a9a52c253dd01bf",
"testharness"
],
"wasm/jsapi/module/constructor.any.js": [
"0f5eecf957e8ca6af851ce12f5c18266a2eb0460",
"32f183fac8738d30cc8a432768da315949320257",
"testharness"
],
"wasm/jsapi/module/customSections.any.js": [
"146aa7fd332ca9b061fef51a7378d29f8c9c165e",
"58ac63b61c93a015bfa9d5daab39f8d5b48548da",
"testharness"
],
"wasm/jsapi/module/exports.any.js": [
"c7ecdcf6b619b4ab93cf4e878addeb9bed736d4e",
"e63a885a4c34add0f6787d3642de83d9766568d1",
"testharness"
],
"wasm/jsapi/module/imports.any.js": [
"522b262f549b9a07c0a426cd474151d3d3e02749",
"640da591d21d8924d261fdc58b8e7cc762187a11",
"testharness"
],
"wasm/jsapi/module/toString.any.js": [
"d9231a132ca8bf965f69c3cc81070a2ffe179efa",
"testharness"
],
"wasm/jsapi/table/assertions.js": [
"dde2fd770904207a1f9f287fa48d82954a418f2e",
"support"
],
"wasm/jsapi/table/constructor.any.js": [
"4aeac10f7adc6e0ec0abc56fa66c0259102798e2",
"e924bdb2ba42c67bcc6d4a949c2eeb50eac63e31",
"testharness"
],
"wasm/jsapi/table/get-set.any.js": [
"2bb43a9308d732b5b6fa689c181ac411880c3733",
"testharness"
],
"wasm/jsapi/table/grow.any.js": [
"d3efb511e4b1db1efa089322c0a3079705dfbdbd",
"testharness"
],
"wasm/jsapi/table/length.any.js": [
"a6a9661dbaddc800cb99b7b8e2b804cb0c8e3c62",
"testharness"
],
"wasm/jsapi/table/toString.any.js": [
"e576477910ad3198b446b4addf89ba9a571d020b",
"testharness"
],
"wasm/jsapi/wasm-constants.js": [

Просмотреть файл

@ -0,0 +1,30 @@
[constructor.any.html]
[Order of evaluation]
expected: FAIL
[Explicit value undefined for type f32]
expected: FAIL
[Explicit value undefined for type f64]
expected: FAIL
[constructor.any.worker.html]
[Order of evaluation]
expected: FAIL
[Explicit value undefined for type f32]
expected: FAIL
[Explicit value undefined for type f64]
expected: FAIL
[constructor.any.js]
[Order of evaluation]
expected: FAIL
[Explicit value undefined for type f32]
expected: FAIL
[Explicit value undefined for type f64]
expected: FAIL

Просмотреть файл

@ -0,0 +1,12 @@
[value-set.any.html]
[Calling setter without argument]
expected: FAIL
[value-set.any.worker.html]
[Calling setter without argument]
expected: FAIL
[value-set.any.js]
[Calling setter without argument]
expected: FAIL

Просмотреть файл

@ -1,5 +1,5 @@
[constructor.any.html]
[Empty descriptor]
[Invalid descriptor argument]
expected: FAIL
[Undefined initial value in descriptor]
@ -45,7 +45,7 @@
expected: FAIL
[constructor.any.worker.html]
[Empty descriptor]
[Invalid descriptor argument]
expected: FAIL
[Undefined initial value in descriptor]
@ -91,7 +91,7 @@
expected: FAIL
[constructor.any.js]
[Empty descriptor]
[Invalid descriptor argument]
expected: FAIL
[Undefined initial value in descriptor]

Просмотреть файл

@ -0,0 +1,93 @@
[grow.any.html]
[Missing arguments]
expected: FAIL
[Out-of-range argument: undefined]
expected: FAIL
[Out-of-range argument: NaN]
expected: FAIL
[Out-of-range argument: Infinity]
expected: FAIL
[Out-of-range argument: -Infinity]
expected: FAIL
[Out-of-range argument: -1]
expected: FAIL
[Out-of-range argument: 4294967296]
expected: FAIL
[Out-of-range argument: 68719476736]
expected: FAIL
[Out-of-range argument: "0x100000000"]
expected: FAIL
[Out-of-range argument: object "[object Object\]"]
expected: FAIL
[grow.any.worker.html]
[Missing arguments]
expected: FAIL
[Out-of-range argument: undefined]
expected: FAIL
[Out-of-range argument: NaN]
expected: FAIL
[Out-of-range argument: Infinity]
expected: FAIL
[Out-of-range argument: -Infinity]
expected: FAIL
[Out-of-range argument: -1]
expected: FAIL
[Out-of-range argument: 4294967296]
expected: FAIL
[Out-of-range argument: 68719476736]
expected: FAIL
[Out-of-range argument: "0x100000000"]
expected: FAIL
[Out-of-range argument: object "[object Object\]"]
expected: FAIL
[grow.any.js]
[Missing arguments]
expected: FAIL
[Out-of-range argument: undefined]
expected: FAIL
[Out-of-range argument: NaN]
expected: FAIL
[Out-of-range argument: Infinity]
expected: FAIL
[Out-of-range argument: -Infinity]
expected: FAIL
[Out-of-range argument: -1]
expected: FAIL
[Out-of-range argument: 4294967296]
expected: FAIL
[Out-of-range argument: 68719476736]
expected: FAIL
[Out-of-range argument: "0x100000000"]
expected: FAIL
[Out-of-range argument: object "[object Object\]"]
expected: FAIL

Просмотреть файл

@ -41,6 +41,12 @@
[Proxy descriptor]
expected: FAIL
[Type conversion for descriptor.element]
expected: FAIL
[Order of evaluation for descriptor]
expected: FAIL
[constructor.any.worker.html]
[Undefined initial value in descriptor]
expected: FAIL
@ -84,6 +90,12 @@
[Proxy descriptor]
expected: FAIL
[Type conversion for descriptor.element]
expected: FAIL
[Order of evaluation for descriptor]
expected: FAIL
[constructor.any.js]
[Undefined initial value in descriptor]
expected: FAIL
@ -126,3 +138,10 @@
[Proxy descriptor]
expected: FAIL
[Type conversion for descriptor.element]
expected: FAIL
[Order of evaluation for descriptor]
expected: FAIL

Просмотреть файл

@ -0,0 +1,174 @@
[get-set.any.html]
[Missing arguments: get]
expected: FAIL
[Getting out-of-range argument: undefined]
expected: FAIL
[Setting out-of-range argument: undefined]
expected: FAIL
[Getting out-of-range argument: NaN]
expected: FAIL
[Setting out-of-range argument: NaN]
expected: FAIL
[Getting out-of-range argument: Infinity]
expected: FAIL
[Setting out-of-range argument: Infinity]
expected: FAIL
[Getting out-of-range argument: -Infinity]
expected: FAIL
[Setting out-of-range argument: -Infinity]
expected: FAIL
[Getting out-of-range argument: -1]
expected: FAIL
[Setting out-of-range argument: -1]
expected: FAIL
[Getting out-of-range argument: 4294967296]
expected: FAIL
[Setting out-of-range argument: 4294967296]
expected: FAIL
[Getting out-of-range argument: 68719476736]
expected: FAIL
[Setting out-of-range argument: 68719476736]
expected: FAIL
[Getting out-of-range argument: "0x100000000"]
expected: FAIL
[Setting out-of-range argument: "0x100000000"]
expected: FAIL
[Getting out-of-range argument: object "[object Object\]"]
expected: FAIL
[Setting out-of-range argument: object "[object Object\]"]
expected: FAIL
[get-set.any.worker.html]
[Missing arguments: get]
expected: FAIL
[Getting out-of-range argument: undefined]
expected: FAIL
[Setting out-of-range argument: undefined]
expected: FAIL
[Getting out-of-range argument: NaN]
expected: FAIL
[Setting out-of-range argument: NaN]
expected: FAIL
[Getting out-of-range argument: Infinity]
expected: FAIL
[Setting out-of-range argument: Infinity]
expected: FAIL
[Getting out-of-range argument: -Infinity]
expected: FAIL
[Setting out-of-range argument: -Infinity]
expected: FAIL
[Getting out-of-range argument: -1]
expected: FAIL
[Setting out-of-range argument: -1]
expected: FAIL
[Getting out-of-range argument: 4294967296]
expected: FAIL
[Setting out-of-range argument: 4294967296]
expected: FAIL
[Getting out-of-range argument: 68719476736]
expected: FAIL
[Setting out-of-range argument: 68719476736]
expected: FAIL
[Getting out-of-range argument: "0x100000000"]
expected: FAIL
[Setting out-of-range argument: "0x100000000"]
expected: FAIL
[Getting out-of-range argument: object "[object Object\]"]
expected: FAIL
[Setting out-of-range argument: object "[object Object\]"]
expected: FAIL
[get-set.any.js]
[Missing arguments: get]
expected: FAIL
[Getting out-of-range argument: undefined]
expected: FAIL
[Setting out-of-range argument: undefined]
expected: FAIL
[Getting out-of-range argument: NaN]
expected: FAIL
[Setting out-of-range argument: NaN]
expected: FAIL
[Getting out-of-range argument: Infinity]
expected: FAIL
[Setting out-of-range argument: Infinity]
expected: FAIL
[Getting out-of-range argument: -Infinity]
expected: FAIL
[Setting out-of-range argument: -Infinity]
expected: FAIL
[Getting out-of-range argument: -1]
expected: FAIL
[Setting out-of-range argument: -1]
expected: FAIL
[Getting out-of-range argument: 4294967296]
expected: FAIL
[Setting out-of-range argument: 4294967296]
expected: FAIL
[Getting out-of-range argument: 68719476736]
expected: FAIL
[Setting out-of-range argument: 68719476736]
expected: FAIL
[Getting out-of-range argument: "0x100000000"]
expected: FAIL
[Setting out-of-range argument: "0x100000000"]
expected: FAIL
[Getting out-of-range argument: object "[object Object\]"]
expected: FAIL
[Setting out-of-range argument: object "[object Object\]"]
expected: FAIL

Просмотреть файл

@ -0,0 +1,93 @@
[grow.any.html]
[Missing arguments]
expected: FAIL
[Out-of-range argument: undefined]
expected: FAIL
[Out-of-range argument: NaN]
expected: FAIL
[Out-of-range argument: Infinity]
expected: FAIL
[Out-of-range argument: -Infinity]
expected: FAIL
[Out-of-range argument: -1]
expected: FAIL
[Out-of-range argument: 4294967296]
expected: FAIL
[Out-of-range argument: 68719476736]
expected: FAIL
[Out-of-range argument: "0x100000000"]
expected: FAIL
[Out-of-range argument: object "[object Object\]"]
expected: FAIL
[grow.any.worker.html]
[Missing arguments]
expected: FAIL
[Out-of-range argument: undefined]
expected: FAIL
[Out-of-range argument: NaN]
expected: FAIL
[Out-of-range argument: Infinity]
expected: FAIL
[Out-of-range argument: -Infinity]
expected: FAIL
[Out-of-range argument: -1]
expected: FAIL
[Out-of-range argument: 4294967296]
expected: FAIL
[Out-of-range argument: 68719476736]
expected: FAIL
[Out-of-range argument: "0x100000000"]
expected: FAIL
[Out-of-range argument: object "[object Object\]"]
expected: FAIL
[grow.any.js]
[Missing arguments]
expected: FAIL
[Out-of-range argument: undefined]
expected: FAIL
[Out-of-range argument: NaN]
expected: FAIL
[Out-of-range argument: Infinity]
expected: FAIL
[Out-of-range argument: -Infinity]
expected: FAIL
[Out-of-range argument: -1]
expected: FAIL
[Out-of-range argument: 4294967296]
expected: FAIL
[Out-of-range argument: 68719476736]
expected: FAIL
[Out-of-range argument: "0x100000000"]
expected: FAIL
[Out-of-range argument: object "[object Object\]"]
expected: FAIL

Просмотреть файл

@ -0,0 +1,121 @@
// META: global=jsshell
// META: script=/wasm/jsapi/assertions.js
function assert_Global(actual, expected) {
assert_equals(Object.getPrototypeOf(actual), WebAssembly.Global.prototype,
"prototype");
assert_true(Object.isExtensible(actual), "extensible");
assert_equals(actual.value, expected, "value");
assert_equals(actual.valueOf(), expected, "valueOf");
}
test(() => {
assert_function_name(WebAssembly.Global, "Global", "WebAssembly.Global");
}, "name");
test(() => {
assert_function_length(WebAssembly.Global, 1, "WebAssembly.Global");
}, "length");
test(() => {
assert_throws(new TypeError(), () => new WebAssembly.Global());
}, "No arguments");
test(() => {
const argument = { "value": "i32" };
assert_throws(new TypeError(), () => WebAssembly.Global(argument));
}, "Calling");
test(() => {
const order = [];
new WebAssembly.Global({
get value() {
order.push("descriptor value");
return {
toString() {
order.push("descriptor value toString");
return "f64";
},
};
},
get mutable() {
order.push("descriptor mutable");
return false;
},
}, {
valueOf() {
order.push("value valueOf()");
}
});
assert_array_equals(order, [
"descriptor mutable",
"descriptor value",
"descriptor value toString",
"value valueOf()",
]);
}, "Order of evaluation");
test(() => {
const invalidArguments = [
undefined,
null,
false,
true,
"",
"test",
Symbol(),
1,
NaN,
{},
];
for (const invalidArgument of invalidArguments) {
assert_throws(new TypeError(),
() => new WebAssembly.Global(invalidArgument),
`new Global(${format_value(invalidArgument)})`);
}
}, "Invalid descriptor argument");
test(() => {
const invalidTypes = ["i16", "i128", "f16", "f128", "u32", "u64", "i32\0"];
for (const value of invalidTypes) {
const argument = { value };
assert_throws(new TypeError(), () => new WebAssembly.Global(argument));
}
}, "Invalid type argument");
test(() => {
const argument = { "value": "i64" };
const global = new WebAssembly.Global(argument);
assert_throws(new TypeError(), () => global.value);
assert_throws(new TypeError(), () => global.valueOf());
}, "i64 with default");
for (const type of ["i32", "f32", "f64"]) {
test(() => {
const argument = { "value": type };
const global = new WebAssembly.Global(argument);
assert_Global(global, 0);
}, `Default value for type ${type}`);
const valueArguments = [
[undefined, 0],
[null, 0],
[true, 1],
[false, 0],
[2, 2],
["3", 3],
[{ toString() { return "5" } }, 5, "object with toString"],
[{ valueOf() { return "8" } }, 8, "object with valueOf"],
];
for (const [value, expected, name = format_value(value)] of valueArguments) {
test(() => {
const argument = { "value": type };
const global = new WebAssembly.Global(argument, value);
assert_Global(global, expected);
}, `Explicit value ${name} for type ${type}`);
}
}

Просмотреть файл

@ -0,0 +1,7 @@
// META: global=jsshell
test(() => {
const argument = { "value": "i32" };
const global = new WebAssembly.Global(argument);
assert_class_string(global, "WebAssembly.Global");
}, "Object.prototype.toString on an Global");

Просмотреть файл

@ -0,0 +1,94 @@
// META: global=jsshell
test(() => {
const thisValues = [
undefined,
null,
true,
"",
Symbol(),
1,
{},
WebAssembly.Global,
WebAssembly.Global.prototype,
];
const desc = Object.getOwnPropertyDescriptor(WebAssembly.Global.prototype, "value");
assert_equals(typeof desc, "object");
const getter = desc.get;
assert_equals(typeof getter, "function");
const setter = desc.set;
assert_equals(typeof setter, "function");
for (const thisValue of thisValues) {
assert_throws(new TypeError(), () => getter.call(thisValue), `getter with this=${format_value(thisValue)}`);
assert_throws(new TypeError(), () => setter.call(thisValue, 1), `setter with this=${format_value(thisValue)}`);
}
}, "Branding");
for (const type of ["i32", "f32", "f64"]) {
const immutableOptions = [
[{}, "missing"],
[{ "mutable": undefined }, "undefined"],
[{ "mutable": null }, "null"],
[{ "mutable": false }, "false"],
[{ "mutable": "" }, "empty string"],
[{ "mutable": 0 }, "zero"],
];
for (const [opts, name] of immutableOptions) {
test(() => {
opts.value = type;
const global = new WebAssembly.Global(opts);
assert_equals(global.value, 0, "initial value");
assert_equals(global.valueOf(), 0, "initial valueOf");
assert_throws(new TypeError(), () => global.value = 1);
assert_equals(global.value, 0, "post-set value");
assert_equals(global.valueOf(), 0, "post-set valueOf");
}, `Immutable ${type} (${name})`);
}
const mutableOptions = [
[{ "mutable": true }, "true"],
[{ "mutable": 1 }, "one"],
[{ "mutable": "x" }, "string"],
[Object.create({ "mutable": true }), "true on prototype"],
];
for (const [opts, name] of mutableOptions) {
test(() => {
opts.value = type;
const global = new WebAssembly.Global(opts);
assert_equals(global.value, 0, "initial value");
assert_equals(global.valueOf(), 0, "initial valueOf");
global.value = 1;
assert_equals(global.value, 1, "post-set value");
assert_equals(global.valueOf(), 1, "post-set valueOf");
}, `Mutable ${type} (${name})`);
}
}
test(() => {
const argument = { "value": "i64", "mutable": true };
const global = new WebAssembly.Global(argument);
assert_throws(new TypeError(), () => global.value);
assert_throws(new TypeError(), () => global.value = 0);
assert_throws(new TypeError(), () => global.valueOf());
}, "i64 with default");
test(() => {
const argument = { "value": "i32", "mutable": true };
const global = new WebAssembly.Global(argument);
const desc = Object.getOwnPropertyDescriptor(WebAssembly.Global.prototype, "value");
assert_equals(typeof desc, "object");
const setter = desc.set;
assert_equals(typeof setter, "function");
assert_throws(new TypeError(), () => setter.call(global));
}, "Calling setter without argument");

Просмотреть файл

@ -0,0 +1,22 @@
// META: global=jsshell
test(() => {
const argument = { "value": "i32" };
const thisValues = [
undefined,
null,
true,
"",
Symbol(),
1,
{},
WebAssembly.Global,
WebAssembly.Global.prototype,
];
const fn = WebAssembly.Global.prototype.valueOf;
for (const thisValue of thisValues) {
assert_throws(new TypeError(), () => fn.call(thisValue), `this=${format_value(thisValue)}`);
}
}, "Branding");

Просмотреть файл

@ -28,6 +28,7 @@ function assert_Instance(instance, expected_exports) {
assert_true(property.enumerable, `${key}: enumerable`);
assert_false(property.configurable, `${key}: configurable`);
const actual = property.value;
assert_true(Object.isExtensible(actual), `${key}: extensible`);
switch (expected.kind) {
case "function":
@ -75,6 +76,39 @@ test(() => {
assert_throws(new TypeError(), () => new WebAssembly.Instance());
}, "No arguments");
test(() => {
const invalidArguments = [
undefined,
null,
true,
"",
Symbol(),
1,
{},
WebAssembly.Module,
WebAssembly.Module.prototype,
];
for (const argument of invalidArguments) {
assert_throws(new TypeError(), () => new WebAssembly.Instance(argument),
`new Instance(${format_value(argument)})`);
}
}, "Non-Module arguments");
test(() => {
const module = new WebAssembly.Module(emptyModuleBinary);
const invalidArguments = [
null,
true,
"",
Symbol(),
1,
];
for (const argument of invalidArguments) {
assert_throws(new TypeError(), () => new WebAssembly.Instance(module, argument),
`new Instance(module, ${format_value(argument)})`);
}
}, "Non-object imports");
test(() => {
const module = new WebAssembly.Module(emptyModuleBinary);
assert_throws(new TypeError(), () => WebAssembly.Instance(module));

Просмотреть файл

@ -0,0 +1,53 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
let emptyModuleBinary;
setup(() => {
emptyModuleBinary = new WasmModuleBuilder().toBuffer();
});
test(() => {
const thisValues = [
undefined,
null,
true,
"",
Symbol(),
1,
{},
WebAssembly.Instance,
WebAssembly.Instance.prototype,
];
const desc = Object.getOwnPropertyDescriptor(WebAssembly.Instance.prototype, "exports");
assert_equals(typeof desc, "object");
const getter = desc.get;
assert_equals(typeof getter, "function");
assert_equals(typeof desc.set, "undefined");
for (const thisValue of thisValues) {
assert_throws(new TypeError(), () => getter.call(thisValue), `this=${format_value(thisValue)}`);
}
}, "Branding");
test(() => {
const module = new WebAssembly.Module(emptyModuleBinary);
const instance = new WebAssembly.Instance(module);
const exports = instance.exports;
instance.exports = {};
assert_equals(instance.exports, exports, "Should not change the exports");
}, "Setting (sloppy mode)");
test(() => {
const module = new WebAssembly.Module(emptyModuleBinary);
const instance = new WebAssembly.Instance(module);
const exports = instance.exports;
assert_throws(new TypeError(), () => {
"use strict";
instance.exports = {};
});
assert_equals(instance.exports, exports, "Should not change the exports");
}, "Setting (strict mode)");

Просмотреть файл

@ -0,0 +1,10 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
test(() => {
const emptyModuleBinary = new WasmModuleBuilder().toBuffer();
const module = new WebAssembly.Module(emptyModuleBinary);
const instance = new WebAssembly.Instance(module);
assert_class_string(instance, "WebAssembly.Instance");
}, "Object.prototype.toString on an Instance");

Просмотреть файл

@ -62,6 +62,10 @@ test(() => {
assert_equals(propdesc.value, this.WebAssembly);
}, "WebAssembly: property descriptor");
test(() => {
assert_throws(new TypeError(), () => WebAssembly());
}, "WebAssembly: calling");
test(() => {
assert_throws(new TypeError(), () => new WebAssembly());
}, "WebAssembly: constructing");
@ -87,6 +91,15 @@ for (const name of interfaces) {
assert_equals(propdesc.value, WebAssembly[name]);
}, `WebAssembly.${name}: property descriptor`);
test(() => {
const interface_object = WebAssembly[name];
const propdesc = Object.getOwnPropertyDescriptor(interface_object, "prototype");
assert_equals(typeof propdesc, "object");
assert_false(propdesc.writable, "writable");
assert_false(propdesc.enumerable, "enumerable");
assert_false(propdesc.configurable, "configurable");
}, `WebAssembly.${name}: prototype`);
test(() => {
const interface_object = WebAssembly[name];
const interface_prototype_object = interface_object.prototype;
@ -96,7 +109,7 @@ for (const name of interfaces) {
assert_false(propdesc.enumerable, "enumerable");
assert_true(propdesc.configurable, "configurable");
assert_equals(propdesc.value, interface_object);
}, `WebAssembly.${name}: prototype`);
}, `WebAssembly.${name}: prototype.constructor`);
}
test_operations(WebAssembly, "WebAssembly", [

Просмотреть файл

@ -0,0 +1,50 @@
// META: global=jsshell
test(() => {
const thisValues = [
undefined,
null,
true,
"",
Symbol(),
1,
{},
WebAssembly.Memory,
WebAssembly.Memory.prototype,
];
const desc = Object.getOwnPropertyDescriptor(WebAssembly.Memory.prototype, "buffer");
assert_equals(typeof desc, "object");
const getter = desc.get;
assert_equals(typeof getter, "function");
assert_equals(typeof desc.set, "undefined");
for (const thisValue of thisValues) {
assert_throws(new TypeError(), () => getter.call(thisValue), `this=${format_value(thisValue)}`);
}
}, "Branding");
test(() => {
const argument = { "initial": 0 };
const memory = new WebAssembly.Memory(argument);
const memory2 = new WebAssembly.Memory(argument);
const buffer = memory.buffer;
assert_not_equals(buffer, memory2.buffer, "Need two distinct buffers");
memory.buffer = memory2.buffer;
assert_equals(memory.buffer, buffer, "Should not change the buffer");
}, "Setting (sloppy mode)");
test(() => {
const argument = { "initial": 0 };
const memory = new WebAssembly.Memory(argument);
const memory2 = new WebAssembly.Memory(argument);
const buffer = memory.buffer;
assert_not_equals(buffer, memory2.buffer, "Need two distinct buffers");
assert_throws(new TypeError(), () => {
"use strict";
memory.buffer = memory2.buffer;
});
assert_equals(memory.buffer, buffer, "Should not change the buffer");
}, "Setting (strict mode)");

Просмотреть файл

@ -1,12 +1,23 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
// META: script=/wasm/jsapi/assertions.js
let emptyModuleBinary;
setup(() => {
emptyModuleBinary = new WasmModuleBuilder().toBuffer();
});
function assert_Memory(memory, expected) {
assert_equals(Object.getPrototypeOf(memory), WebAssembly.Memory.prototype,
"prototype");
assert_true(Object.isExtensible(memory), "extensible");
// https://github.com/WebAssembly/spec/issues/840
assert_equals(memory.buffer, memory.buffer, "buffer should be idempotent");
assert_equals(Object.getPrototypeOf(memory.buffer), ArrayBuffer.prototype,
"prototype of buffer");
assert_true(Object.isExtensible(memory.buffer), "buffer extensibility");
assert_equals(memory.buffer.byteLength, 0x10000 * expected.size, "size of buffer");
if (expected.size > 0) {
const array = new Uint8Array(memory.buffer);
assert_equals(array[0], 0, "first element of buffer");
assert_equals(array[array.byteLength - 1], 0, "last element of buffer");
}
}
test(() => {
assert_function_name(WebAssembly.Memory, "Memory", "WebAssembly.Memory");
@ -26,8 +37,24 @@ test(() => {
}, "Calling");
test(() => {
assert_throws(new TypeError(), () => new WebAssembly.Memory({}));
}, "Empty descriptor");
const invalidArguments = [
undefined,
null,
false,
true,
"",
"test",
Symbol(),
1,
NaN,
{},
];
for (const invalidArgument of invalidArguments) {
assert_throws(new TypeError(),
() => new WebAssembly.Memory(invalidArgument),
`new Memory(${format_value(invalidArgument)})`);
}
}, "Invalid descriptor argument");
test(() => {
assert_throws(new TypeError(), () => new WebAssembly.Memory({ "initial": undefined }));
@ -64,8 +91,47 @@ test(() => {
new WebAssembly.Memory(proxy);
}, "Proxy descriptor");
test(() => {
const order = [];
new WebAssembly.Memory({
get maximum() {
order.push("maximum");
return {
valueOf() {
order.push("maximum valueOf");
return 1;
},
};
},
get initial() {
order.push("initial");
return {
valueOf() {
order.push("initial valueOf");
return 1;
},
};
},
});
assert_array_equals(order, [
"initial",
"initial valueOf",
"maximum",
"maximum valueOf",
]);
}, "Order of evaluation for descriptor");
test(() => {
const argument = { "initial": 0 };
const memory = new WebAssembly.Memory(argument);
assert_equals(Object.getPrototypeOf(memory), WebAssembly.Memory.prototype);
}, "Prototype");
assert_Memory(memory, { "size": 0 });
}, "Zero initial");
test(() => {
const argument = { "initial": 4 };
const memory = new WebAssembly.Memory(argument);
assert_Memory(memory, { "size": 4 });
}, "Non-zero initial");

Просмотреть файл

@ -0,0 +1,170 @@
// META: global=jsshell
function assert_ArrayBuffer(actual, expected, message) {
// https://github.com/WebAssembly/spec/issues/840
assert_equals(Object.getPrototypeOf(actual), ArrayBuffer.prototype,
`${message}: prototype`);
if (expected.detached) {
// https://github.com/tc39/ecma262/issues/678
let byteLength;
try {
byteLength = actual.byteLength;
} catch (e) {
byteLength = 0;
}
assert_equals(byteLength, 0, `${message}: detached size`);
} else {
assert_equals(actual.byteLength, 0x10000 * expected.size, `${message}: size`);
if (expected.size > 0) {
const array = new Uint8Array(actual);
assert_equals(array[0], 0, `${message}: first element`);
assert_equals(array[array.byteLength - 1], 0, `${message}: last element`);
}
}
}
test(() => {
const argument = { "initial": 0 };
const memory = new WebAssembly.Memory(argument);
assert_throws(new TypeError(), () => memory.grow());
}, "Missing arguments");
test(t => {
const thisValues = [
undefined,
null,
true,
"",
Symbol(),
1,
{},
WebAssembly.Memory,
WebAssembly.Memory.prototype,
];
const argument = {
valueOf: t.unreached_func("Should not touch the argument (valueOf)"),
toString: t.unreached_func("Should not touch the argument (toString)"),
};
const fn = WebAssembly.Memory.prototype.grow;
for (const thisValue of thisValues) {
assert_throws(new TypeError(), () => fn.call(thisValue, argument), `this=${format_value(thisValue)}`);
}
}, "Branding");
test(() => {
const argument = { "initial": 0 };
const memory = new WebAssembly.Memory(argument);
const oldMemory = memory.buffer;
assert_ArrayBuffer(oldMemory, { "size": 0 }, "Buffer before growing");
const result = memory.grow(2);
assert_equals(result, 0);
const newMemory = memory.buffer;
assert_not_equals(oldMemory, newMemory);
assert_ArrayBuffer(oldMemory, { "detached": true }, "Old buffer after growing");
assert_ArrayBuffer(newMemory, { "size": 2 }, "New buffer after growing");
}, "Zero initial");
test(() => {
const argument = { "initial": { valueOf() { return 0 } } };
const memory = new WebAssembly.Memory(argument);
const oldMemory = memory.buffer;
assert_ArrayBuffer(oldMemory, { "size": 0 }, "Buffer before growing");
const result = memory.grow({ valueOf() { return 2 } });
assert_equals(result, 0);
const newMemory = memory.buffer;
assert_not_equals(oldMemory, newMemory);
assert_ArrayBuffer(oldMemory, { "detached": true }, "Old buffer after growing");
assert_ArrayBuffer(newMemory, { "size": 2 }, "New buffer after growing");
}, "Zero initial with valueOf");
test(() => {
const argument = { "initial": 3 };
const memory = new WebAssembly.Memory(argument);
const oldMemory = memory.buffer;
assert_ArrayBuffer(oldMemory, { "size": 3 }, "Buffer before growing");
const result = memory.grow(2);
assert_equals(result, 3);
const newMemory = memory.buffer;
assert_not_equals(oldMemory, newMemory);
assert_ArrayBuffer(oldMemory, { "detached": true }, "Old buffer after growing");
assert_ArrayBuffer(newMemory, { "size": 5 }, "New buffer after growing");
}, "Non-zero initial");
test(() => {
const argument = { "initial": 0, "maximum": 2 };
const memory = new WebAssembly.Memory(argument);
const oldMemory = memory.buffer;
assert_ArrayBuffer(oldMemory, { "size": 0 }, "Buffer before growing");
const result = memory.grow(2);
assert_equals(result, 0);
const newMemory = memory.buffer;
assert_not_equals(oldMemory, newMemory);
assert_ArrayBuffer(oldMemory, { "detached": true }, "Old buffer after growing");
assert_ArrayBuffer(newMemory, { "size": 2 }, "New buffer after growing");
}, "Zero initial with respected maximum");
test(() => {
const argument = { "initial": 0, "maximum": 2 };
const memory = new WebAssembly.Memory(argument);
const oldMemory = memory.buffer;
assert_ArrayBuffer(oldMemory, { "size": 0 }, "Buffer before growing");
const result = memory.grow(1);
assert_equals(result, 0);
const newMemory = memory.buffer;
assert_not_equals(oldMemory, newMemory);
assert_ArrayBuffer(oldMemory, { "detached": true }, "Old buffer after growing once");
assert_ArrayBuffer(newMemory, { "size": 1 }, "New buffer after growing once");
const result2 = memory.grow(1);
assert_equals(result2, 1);
const newestMemory = memory.buffer;
assert_not_equals(newMemory, newestMemory);
assert_ArrayBuffer(oldMemory, { "detached": true }, "New buffer after growing twice");
assert_ArrayBuffer(newMemory, { "detached": true }, "New buffer after growing twice");
assert_ArrayBuffer(newestMemory, { "size": 2 }, "Newest buffer after growing twice");
}, "Zero initial with respected maximum grown twice");
test(() => {
const argument = { "initial": 1, "maximum": 2 };
const memory = new WebAssembly.Memory(argument);
const oldMemory = memory.buffer;
assert_ArrayBuffer(oldMemory, { "size": 1 }, "Buffer before growing");
assert_throws(new RangeError(), () => memory.grow(2));
assert_equals(memory.buffer, oldMemory);
assert_ArrayBuffer(memory.buffer, { "size": 1 }, "Buffer before trying to grow");
}, "Zero initial growing too much");
const outOfRangeValues = [
undefined,
NaN,
Infinity,
-Infinity,
-1,
0x100000000,
0x1000000000,
"0x100000000",
{ valueOf() { return 0x100000000; } },
];
for (const value of outOfRangeValues) {
test(() => {
const argument = { "initial": 0 };
const memory = new WebAssembly.Memory(argument);
assert_throws(new TypeError(), () => memory.grow(value));
}, `Out-of-range argument: ${format_value(value)}`);
}

Просмотреть файл

@ -0,0 +1,7 @@
// META: global=jsshell
test(() => {
const argument = { "initial": 0 };
const memory = new WebAssembly.Memory(argument);
assert_class_string(memory, "WebAssembly.Memory");
}, "Object.prototype.toString on an Memory");

Просмотреть файл

@ -24,6 +24,26 @@ test(() => {
assert_throws(new TypeError(), () => WebAssembly.Module(emptyModuleBinary));
}, "Calling");
test(() => {
const invalidArguments = [
undefined,
null,
true,
"test",
Symbol(),
7,
NaN,
{},
ArrayBuffer,
ArrayBuffer.prototype,
Array.from(emptyModuleBinary),
];
for (const argument of invalidArguments) {
assert_throws(new TypeError(), () => new WebAssembly.Module(argument),
`new Module(${format_value(argument)})`);
}
}, "Invalid arguments");
test(() => {
const buffer = new Uint8Array();
assert_throws(new WebAssembly.CompileError(), () => new WebAssembly.Module(buffer));
@ -33,3 +53,8 @@ test(() => {
const module = new WebAssembly.Module(emptyModuleBinary);
assert_equals(Object.getPrototypeOf(module), WebAssembly.Module.prototype);
}, "Prototype");
test(() => {
const module = new WebAssembly.Module(emptyModuleBinary);
assert_true(Object.isExtensible(module));
}, "Extensibility");

Просмотреть файл

@ -4,12 +4,14 @@
function assert_ArrayBuffer(buffer, expected) {
assert_equals(Object.getPrototypeOf(buffer), ArrayBuffer.prototype, "Prototype");
assert_true(Object.isExtensible(buffer), "isExtensible");
assert_array_equals(new Uint8Array(buffer), expected);
}
function assert_sections(sections, expected) {
assert_true(Array.isArray(sections), "Should be array");
assert_equals(Object.getPrototypeOf(sections), Array.prototype, "Prototype");
assert_true(Object.isExtensible(sections), "isExtensible");
assert_equals(sections.length, expected.length);
for (let i = 0; i < expected.length; ++i) {
@ -29,10 +31,21 @@ test(() => {
}, "Missing arguments");
test(() => {
assert_throws(new TypeError(), () => WebAssembly.Module.customSections({}, ""));
assert_throws(new TypeError(), () => WebAssembly.Module.customSections("", ""));
assert_throws(new TypeError(), () => WebAssembly.Module.customSections(undefined, ""));
assert_throws(new TypeError(), () => WebAssembly.Module.customSections(null, ""));
const invalidArguments = [
undefined,
null,
true,
"",
Symbol(),
1,
{},
WebAssembly.Module,
WebAssembly.Module.prototype,
];
for (const argument of invalidArguments) {
assert_throws(new TypeError(), () => WebAssembly.Module.customSections(argument, ""),
`customSections(${format_value(argument)})`);
}
}, "Non-Module arguments");
test(() => {
@ -102,3 +115,48 @@ test(() => {
assert_sections(WebAssembly.Module.customSections(module, "name\0"), [])
assert_sections(WebAssembly.Module.customSections(module, "foo\0"), [])
}, "Custom sections");
test(() => {
const bytes = [87, 101, 98, 65, 115, 115, 101, 109, 98, 108, 121];
const name = "yee\uD801\uDC37eey"
const binary = new Binary;
binary.emit_section(kUnknownSectionCode, section => {
section.emit_string(name);
section.emit_bytes(bytes);
});
const builder = new WasmModuleBuilder();
builder.addExplicitSection(binary);
const buffer = builder.toBuffer();
const module = new WebAssembly.Module(buffer);
assert_sections(WebAssembly.Module.customSections(module, name), [
bytes,
]);
assert_sections(WebAssembly.Module.customSections(module, "yee\uFFFDeey"), []);
assert_sections(WebAssembly.Module.customSections(module, "yee\uFFFD\uFFFDeey"), []);
}, "Custom sections with surrogate pairs");
test(() => {
const bytes = [87, 101, 98, 65, 115, 115, 101, 109, 98, 108, 121];
const binary = new Binary;
binary.emit_section(kUnknownSectionCode, section => {
section.emit_string("na\uFFFDme");
section.emit_bytes(bytes);
});
const builder = new WasmModuleBuilder();
builder.addExplicitSection(binary);
const buffer = builder.toBuffer();
const module = new WebAssembly.Module(buffer);
assert_sections(WebAssembly.Module.customSections(module, "name"), []);
assert_sections(WebAssembly.Module.customSections(module, "na\uFFFDme"), [
bytes,
]);
assert_sections(WebAssembly.Module.customSections(module, "na\uDC01me"), [
bytes,
]);
}, "Custom sections with U+FFFD");

Просмотреть файл

@ -7,15 +7,54 @@ setup(() => {
emptyModuleBinary = new WasmModuleBuilder().toBuffer();
});
function assert_ModuleExportDescriptor(export_, expected) {
assert_equals(Object.getPrototypeOf(export_), Object.prototype, "Prototype");
assert_true(Object.isExtensible(export_), "isExtensible");
const name = Object.getOwnPropertyDescriptor(export_, "name");
assert_true(name.writable, "name: writable");
assert_true(name.enumerable, "name: enumerable");
assert_true(name.configurable, "name: configurable");
assert_equals(name.value, expected.name);
const kind = Object.getOwnPropertyDescriptor(export_, "kind");
assert_true(kind.writable, "kind: writable");
assert_true(kind.enumerable, "kind: enumerable");
assert_true(kind.configurable, "kind: configurable");
assert_equals(kind.value, expected.kind);
}
function assert_exports(exports, expected) {
assert_true(Array.isArray(exports), "Should be array");
assert_equals(Object.getPrototypeOf(exports), Array.prototype, "Prototype");
assert_true(Object.isExtensible(exports), "isExtensible");
assert_equals(exports.length, expected.length);
for (let i = 0; i < expected.length; ++i) {
assert_ModuleExportDescriptor(exports[i], expected[i]);
}
}
test(() => {
assert_throws(new TypeError(), () => WebAssembly.Module.exports());
}, "Missing arguments");
test(() => {
assert_throws(new TypeError(), () => WebAssembly.Module.exports({}));
assert_throws(new TypeError(), () => WebAssembly.Module.exports(""));
assert_throws(new TypeError(), () => WebAssembly.Module.exports(undefined));
assert_throws(new TypeError(), () => WebAssembly.Module.exports(null));
const invalidArguments = [
undefined,
null,
true,
"",
Symbol(),
1,
{},
WebAssembly.Module,
WebAssembly.Module.prototype,
];
for (const argument of invalidArguments) {
assert_throws(new TypeError(), () => WebAssembly.Module.exports(argument),
`exports(${format_value(argument)})`);
}
}, "Non-Module arguments");
test(() => {
@ -40,15 +79,7 @@ test(() => {
test(() => {
const module = new WebAssembly.Module(emptyModuleBinary);
const exports = WebAssembly.Module.exports(module);
assert_true(Array.isArray(exports));
}, "Return type");
test(() => {
const module = new WebAssembly.Module(emptyModuleBinary);
const exports = WebAssembly.Module.exports(module);
assert_true(Array.isArray(exports), "Should be array");
assert_equals(Object.getPrototypeOf(exports), Array.prototype, "Prototype");
assert_array_equals(exports, []);
assert_exports(exports, []);
}, "Empty module");
test(() => {
@ -56,22 +87,6 @@ test(() => {
assert_not_equals(WebAssembly.Module.exports(module), WebAssembly.Module.exports(module));
}, "Empty module: array caching");
function assert_ModuleExportDescriptor(export_, expected) {
assert_equals(Object.getPrototypeOf(export_), Object.prototype, "Prototype");
const name = Object.getOwnPropertyDescriptor(export_, "name");
assert_true(name.writable, "name: writable");
assert_true(name.enumerable, "name: enumerable");
assert_true(name.configurable, "name: configurable");
assert_equals(name.value, expected.name);
const kind = Object.getOwnPropertyDescriptor(export_, "kind");
assert_true(kind.writable, "kind: writable");
assert_true(kind.enumerable, "kind: enumerable");
assert_true(kind.configurable, "kind: configurable");
assert_equals(kind.value, expected.kind);
}
test(() => {
const builder = new WasmModuleBuilder();
@ -103,9 +118,6 @@ test(() => {
const buffer = builder.toBuffer()
const module = new WebAssembly.Module(buffer);
const exports = WebAssembly.Module.exports(module);
assert_true(Array.isArray(exports), "Should be array");
assert_equals(Object.getPrototypeOf(exports), Array.prototype, "Prototype");
const expected = [
{ "kind": "function", "name": "fn" },
{ "kind": "function", "name": "fn2" },
@ -114,8 +126,5 @@ test(() => {
{ "kind": "global", "name": "global2" },
{ "kind": "memory", "name": "memory" },
];
assert_equals(exports.length, expected.length);
for (let i = 0; i < expected.length; ++i) {
assert_ModuleExportDescriptor(exports[i], expected[i]);
}
assert_exports(exports, expected);
}, "exports");

Просмотреть файл

@ -2,6 +2,40 @@
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
function assert_ModuleImportDescriptor(import_, expected) {
assert_equals(Object.getPrototypeOf(import_), Object.prototype, "Prototype");
assert_true(Object.isExtensible(import_), "isExtensible");
const module = Object.getOwnPropertyDescriptor(import_, "module");
assert_true(module.writable, "module: writable");
assert_true(module.enumerable, "module: enumerable");
assert_true(module.configurable, "module: configurable");
assert_equals(module.value, expected.module);
const name = Object.getOwnPropertyDescriptor(import_, "name");
assert_true(name.writable, "name: writable");
assert_true(name.enumerable, "name: enumerable");
assert_true(name.configurable, "name: configurable");
assert_equals(name.value, expected.name);
const kind = Object.getOwnPropertyDescriptor(import_, "kind");
assert_true(kind.writable, "kind: writable");
assert_true(kind.enumerable, "kind: enumerable");
assert_true(kind.configurable, "kind: configurable");
assert_equals(kind.value, expected.kind);
}
function assert_imports(imports, expected) {
assert_true(Array.isArray(imports), "Should be array");
assert_equals(Object.getPrototypeOf(imports), Array.prototype, "Prototype");
assert_true(Object.isExtensible(imports), "isExtensible");
assert_equals(imports.length, expected.length);
for (let i = 0; i < expected.length; ++i) {
assert_ModuleImportDescriptor(imports[i], expected[i]);
}
}
let emptyModuleBinary;
setup(() => {
emptyModuleBinary = new WasmModuleBuilder().toBuffer();
@ -12,10 +46,21 @@ test(() => {
}, "Missing arguments");
test(() => {
assert_throws(new TypeError(), () => WebAssembly.Module.imports({}));
assert_throws(new TypeError(), () => WebAssembly.Module.imports(""));
assert_throws(new TypeError(), () => WebAssembly.Module.imports(undefined));
assert_throws(new TypeError(), () => WebAssembly.Module.imports(null));
const invalidArguments = [
undefined,
null,
true,
"",
Symbol(),
1,
{},
WebAssembly.Module,
WebAssembly.Module.prototype,
];
for (const argument of invalidArguments) {
assert_throws(new TypeError(), () => WebAssembly.Module.imports(argument),
`imports(${format_value(argument)})`);
}
}, "Non-Module arguments");
test(() => {
@ -46,9 +91,7 @@ test(() => {
test(() => {
const module = new WebAssembly.Module(emptyModuleBinary);
const imports = WebAssembly.Module.imports(module);
assert_true(Array.isArray(imports), "Should be array");
assert_equals(Object.getPrototypeOf(imports), Array.prototype, "Prototype");
assert_array_equals(imports, []);
assert_imports(imports, []);
}, "Empty module");
test(() => {
@ -56,28 +99,6 @@ test(() => {
assert_not_equals(WebAssembly.Module.imports(module), WebAssembly.Module.imports(module));
}, "Empty module: array caching");
function assert_ModuleImportDescriptor(import_, expected) {
assert_equals(Object.getPrototypeOf(import_), Object.prototype, "Prototype");
const module = Object.getOwnPropertyDescriptor(import_, "module");
assert_true(module.writable, "module: writable");
assert_true(module.enumerable, "module: enumerable");
assert_true(module.configurable, "module: configurable");
assert_equals(module.value, expected.module);
const name = Object.getOwnPropertyDescriptor(import_, "name");
assert_true(name.writable, "name: writable");
assert_true(name.enumerable, "name: enumerable");
assert_true(name.configurable, "name: configurable");
assert_equals(name.value, expected.name);
const kind = Object.getOwnPropertyDescriptor(import_, "kind");
assert_true(kind.writable, "kind: writable");
assert_true(kind.enumerable, "kind: enumerable");
assert_true(kind.configurable, "kind: configurable");
assert_equals(kind.value, expected.kind);
}
test(() => {
const builder = new WasmModuleBuilder();
@ -89,17 +110,11 @@ test(() => {
const buffer = builder.toBuffer()
const module = new WebAssembly.Module(buffer);
const imports = WebAssembly.Module.imports(module);
assert_true(Array.isArray(imports), "Should be array");
assert_equals(Object.getPrototypeOf(imports), Array.prototype, "Prototype");
const expected = [
{ "module": "module", "kind": "function", "name": "fn" },
{ "module": "module", "kind": "global", "name": "global" },
{ "module": "module", "kind": "memory", "name": "memory" },
{ "module": "module", "kind": "table", "name": "table" },
];
assert_equals(imports.length, expected.length);
for (let i = 0; i < expected.length; ++i) {
assert_ModuleImportDescriptor(imports[i], expected[i]);
}
assert_imports(imports, expected);
}, "imports");

Просмотреть файл

@ -0,0 +1,9 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
test(() => {
const emptyModuleBinary = new WasmModuleBuilder().toBuffer();
const module = new WebAssembly.Module(emptyModuleBinary);
assert_class_string(module, "WebAssembly.Module");
}, "Object.prototype.toString on an Module");

Просмотреть файл

@ -0,0 +1,11 @@
function assert_equal_to_array(table, expected, message) {
assert_equals(table.length, expected.length, `${message}: length`);
assert_throws(new RangeError(), () => table.get(-1), `${message}: table.get(-1)`);
for (let i = 0; i < expected.length; ++i) {
assert_equals(table.get(i), expected[i], `${message}: table.get(${i} of ${expected.length})`);
}
assert_throws(new RangeError(), () => table.get(expected.length),
`${message}: table.get(${expected.length} of ${expected.length})`);
assert_throws(new RangeError(), () => table.get(expected.length + 1),
`${message}: table.get(${expected.length + 1} of ${expected.length})`);
}

Просмотреть файл

@ -1,12 +1,16 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
// META: script=/wasm/jsapi/assertions.js
let emptyModuleBinary;
setup(() => {
emptyModuleBinary = new WasmModuleBuilder().toBuffer();
});
function assert_Table(actual, expected) {
assert_equals(Object.getPrototypeOf(actual), WebAssembly.Table.prototype,
"prototype");
assert_true(Object.isExtensible(actual), "extensible");
assert_equals(actual.length, expected.length, "length");
for (let i = 0; i < expected.length; ++i) {
assert_equals(actual.get(i), null, `actual.get(${i})`);
}
}
test(() => {
assert_function_name(WebAssembly.Table, "Table", "WebAssembly.Table");
@ -21,7 +25,7 @@ test(() => {
}, "No arguments");
test(() => {
const argument = { "initial": 0 };
const argument = { "element": "anyfunc", "initial": 0 };
assert_throws(new TypeError(), () => WebAssembly.Table(argument));
}, "Calling");
@ -29,6 +33,26 @@ test(() => {
assert_throws(new TypeError(), () => new WebAssembly.Table({}));
}, "Empty descriptor");
test(() => {
const invalidArguments = [
undefined,
null,
false,
true,
"",
"test",
Symbol(),
1,
NaN,
{},
];
for (const invalidArgument of invalidArguments) {
assert_throws(new TypeError(),
() => new WebAssembly.Table(invalidArgument),
`new Table(${format_value(invalidArgument)})`);
}
}, "Invalid descriptor argument");
test(() => {
assert_throws(new TypeError(), () => new WebAssembly.Table({ "element": "anyfunc", "initial": undefined }));
}, "Undefined initial value in descriptor");
@ -56,6 +80,22 @@ for (const value of outOfRangeValues) {
}, `Out-of-range maximum value in descriptor: ${format_value(value)}`);
}
test(() => {
assert_throws(new RangeError(), () => new WebAssembly.Table({ "element": "anyfunc", "initial": 10, "maximum": 9 }));
}, "Initial value exceeds maximum");
test(() => {
const argument = { "element": "anyfunc", "initial": 0 };
const table = new WebAssembly.Table(argument);
assert_Table(table, { "length": 0 });
}, "Basic (zero)");
test(() => {
const argument = { "element": "anyfunc", "initial": 5 };
const table = new WebAssembly.Table(argument);
assert_Table(table, { "length": 5 });
}, "Basic (non-zero)");
test(() => {
const proxy = new Proxy({}, {
has(o, x) {
@ -73,11 +113,61 @@ test(() => {
}
},
});
new WebAssembly.Table(proxy);
const table = new WebAssembly.Table(proxy);
assert_Table(table, { "length": 0 });
}, "Proxy descriptor");
test(() => {
const argument = { "element": "anyfunc", "initial": 0 };
const table = new WebAssembly.Table(argument);
assert_equals(Object.getPrototypeOf(table), WebAssembly.Table.prototype);
}, "Prototype");
const table = new WebAssembly.Table({
"element": {
toString() { return "anyfunc"; },
},
"initial": 1,
});
assert_Table(table, { "length": 1 });
}, "Type conversion for descriptor.element");
test(() => {
const order = [];
new WebAssembly.Table({
get maximum() {
order.push("maximum");
return {
valueOf() {
order.push("maximum valueOf");
return 1;
},
};
},
get initial() {
order.push("initial");
return {
valueOf() {
order.push("initial valueOf");
return 1;
},
};
},
get element() {
order.push("element");
return {
toString() {
order.push("element toString");
return "anyfunc";
},
};
},
});
assert_array_equals(order, [
"element",
"element toString",
"initial",
"initial valueOf",
"maximum",
"maximum valueOf",
]);
}, "Order of evaluation for descriptor");

Просмотреть файл

@ -0,0 +1,220 @@
// META: global=jsshell
// META: script=/wasm/jsapi/wasm-constants.js
// META: script=/wasm/jsapi/wasm-module-builder.js
// META: script=assertions.js
let functions;
setup(() => {
const builder = new WasmModuleBuilder();
builder
.addFunction("fn", kSig_v_d)
.addBody([
kExprEnd
])
.exportFunc();
builder
.addFunction("fn2", kSig_v_v)
.addBody([
kExprEnd
])
.exportFunc();
const buffer = builder.toBuffer()
const module = new WebAssembly.Module(buffer);
const instance = new WebAssembly.Instance(module, {});
functions = instance.exports;
});
test(() => {
const argument = { "element": "anyfunc", "initial": 5 };
const table = new WebAssembly.Table(argument);
assert_throws(new TypeError(), () => table.get());
}, "Missing arguments: get");
test(t => {
const thisValues = [
undefined,
null,
true,
"",
Symbol(),
1,
{},
WebAssembly.Table,
WebAssembly.Table.prototype,
];
const argument = {
valueOf: t.unreached_func("Should not touch the argument (valueOf)"),
toString: t.unreached_func("Should not touch the argument (toString)"),
};
const fn = WebAssembly.Table.prototype.get;
for (const thisValue of thisValues) {
assert_throws(new TypeError(), () => fn.call(thisValue, argument), `this=${format_value(thisValue)}`);
}
}, "Branding: get");
test(() => {
const argument = { "element": "anyfunc", "initial": 5 };
const table = new WebAssembly.Table(argument);
assert_throws(new TypeError(), () => table.set());
assert_throws(new TypeError(), () => table.set(0));
}, "Missing arguments: set");
test(t => {
const thisValues = [
undefined,
null,
true,
"",
Symbol(),
1,
{},
WebAssembly.Table,
WebAssembly.Table.prototype,
];
const argument = {
valueOf: t.unreached_func("Should not touch the argument (valueOf)"),
toString: t.unreached_func("Should not touch the argument (toString)"),
};
const fn = WebAssembly.Table.prototype.set;
for (const thisValue of thisValues) {
assert_throws(new TypeError(), () => fn.call(thisValue, argument, null), `this=${format_value(thisValue)}`);
}
}, "Branding: set");
test(() => {
const argument = { "element": "anyfunc", "initial": 5 };
const table = new WebAssembly.Table(argument);
assert_equal_to_array(table, [null, null, null, null, null]);
const {fn, fn2} = functions;
assert_equals(table.set(0, fn), undefined, "set() returns undefined.");
table.set(2, fn2);
table.set(4, fn);
assert_equal_to_array(table, [fn, null, fn2, null, fn]);
table.set(0, null);
assert_equal_to_array(table, [null, null, fn2, null, fn]);
}, "Basic");
test(() => {
const argument = { "element": "anyfunc", "initial": 5 };
const table = new WebAssembly.Table(argument);
assert_equal_to_array(table, [null, null, null, null, null]);
const {fn, fn2} = functions;
table.set(0, fn);
table.set(2, fn2);
table.set(4, fn);
assert_equal_to_array(table, [fn, null, fn2, null, fn]);
table.grow(4);
assert_equal_to_array(table, [fn, null, fn2, null, fn, null, null, null, null]);
}, "Growing");
test(() => {
const argument = { "element": "anyfunc", "initial": 5 };
const table = new WebAssembly.Table(argument);
assert_equal_to_array(table, [null, null, null, null, null]);
const {fn} = functions;
assert_throws(new RangeError(), () => table.set(-1, fn));
assert_throws(new RangeError(), () => table.set(5, fn));
assert_equal_to_array(table, [null, null, null, null, null]);
}, "Setting out-of-bounds");
test(() => {
const argument = { "element": "anyfunc", "initial": 1 };
const table = new WebAssembly.Table(argument);
assert_equal_to_array(table, [null]);
const invalidArguments = [
undefined,
true,
false,
"test",
Symbol(),
7,
NaN,
{},
];
for (const argument of invalidArguments) {
assert_throws(new TypeError(), () => table.set(0, argument),
`set(${format_value(argument)})`);
}
assert_equal_to_array(table, [null]);
}, "Setting non-function");
test(() => {
const argument = { "element": "anyfunc", "initial": 1 };
const table = new WebAssembly.Table(argument);
assert_equal_to_array(table, [null]);
const fn = function() {};
assert_throws(new TypeError(), () => table.set(0, fn));
assert_equal_to_array(table, [null]);
}, "Setting non-wasm function");
test(() => {
const argument = { "element": "anyfunc", "initial": 1 };
const table = new WebAssembly.Table(argument);
assert_equal_to_array(table, [null]);
const fn = () => {};
assert_throws(new TypeError(), () => table.set(0, fn));
assert_equal_to_array(table, [null]);
}, "Setting non-wasm arrow function");
const outOfRangeValues = [
undefined,
NaN,
Infinity,
-Infinity,
-1,
0x100000000,
0x1000000000,
"0x100000000",
{ valueOf() { return 0x100000000; } },
];
for (const value of outOfRangeValues) {
test(() => {
const argument = { "element": "anyfunc", "initial": 1 };
const table = new WebAssembly.Table(argument);
assert_throws(new TypeError(), () => table.get(value));
}, `Getting out-of-range argument: ${format_value(value)}`);
test(() => {
const argument = { "element": "anyfunc", "initial": 1 };
const table = new WebAssembly.Table(argument);
assert_throws(new TypeError(), () => table.set(value, null));
}, `Setting out-of-range argument: ${format_value(value)}`);
}
test(() => {
const argument = { "element": "anyfunc", "initial": 1 };
const table = new WebAssembly.Table(argument);
let called = 0;
const value = {
valueOf() {
called++;
return 0;
},
};
assert_throws(new TypeError(), () => table.set(value, {}));
assert_equals(called, 1);
}, "Order of argument conversion");

Просмотреть файл

@ -0,0 +1,86 @@
// META: global=jsshell
// META: script=assertions.js
function nulls(n) {
return Array(n).fill(null);
}
test(() => {
const argument = { "element": "anyfunc", "initial": 5 };
const table = new WebAssembly.Table(argument);
assert_throws(new TypeError(), () => table.grow());
}, "Missing arguments");
test(t => {
const thisValues = [
undefined,
null,
true,
"",
Symbol(),
1,
{},
WebAssembly.Table,
WebAssembly.Table.prototype,
];
const argument = {
valueOf: t.unreached_func("Should not touch the argument (valueOf)"),
toString: t.unreached_func("Should not touch the argument (toString)"),
};
const fn = WebAssembly.Table.prototype.grow;
for (const thisValue of thisValues) {
assert_throws(new TypeError(), () => fn.call(thisValue, argument), `this=${format_value(thisValue)}`);
}
}, "Branding");
test(() => {
const argument = { "element": "anyfunc", "initial": 5 };
const table = new WebAssembly.Table(argument);
assert_equal_to_array(table, nulls(5), "before");
const result = table.grow(3);
assert_equals(result, 5);
assert_equal_to_array(table, nulls(8), "after");
}, "Basic");
test(() => {
const argument = { "element": "anyfunc", "initial": 3, "maximum": 5 };
const table = new WebAssembly.Table(argument);
assert_equal_to_array(table, nulls(3), "before");
const result = table.grow(2);
assert_equals(result, 3);
assert_equal_to_array(table, nulls(5), "after");
}, "Reached maximum");
test(() => {
const argument = { "element": "anyfunc", "initial": 2, "maximum": 5 };
const table = new WebAssembly.Table(argument);
assert_equal_to_array(table, nulls(2), "before");
assert_throws(new RangeError(), () => table.grow(4));
assert_equal_to_array(table, nulls(2), "after");
}, "Exceeded maximum");
const outOfRangeValues = [
undefined,
NaN,
Infinity,
-Infinity,
-1,
0x100000000,
0x1000000000,
"0x100000000",
{ valueOf() { return 0x100000000; } },
];
for (const value of outOfRangeValues) {
test(() => {
const argument = { "element": "anyfunc", "initial": 1 };
const table = new WebAssembly.Table(argument);
assert_throws(new TypeError(), () => table.grow(value));
}, `Out-of-range argument: ${format_value(value)}`);
}

Просмотреть файл

@ -0,0 +1,46 @@
// META: global=jsshell
test(() => {
const thisValues = [
undefined,
null,
true,
"",
Symbol(),
1,
{},
WebAssembly.Table,
WebAssembly.Table.prototype,
];
const desc = Object.getOwnPropertyDescriptor(WebAssembly.Table.prototype, "length");
assert_equals(typeof desc, "object");
const getter = desc.get;
assert_equals(typeof getter, "function");
assert_equals(typeof desc.set, "undefined");
for (const thisValue of thisValues) {
assert_throws(new TypeError(), () => getter.call(thisValue), `this=${format_value(thisValue)}`);
}
}, "Branding");
test(() => {
const argument = { "element": "anyfunc", "initial": 2 };
const table = new WebAssembly.Table(argument);
assert_equals(table.length, 2, "Initial length");
table.length = 4;
assert_equals(table.length, 2, "Should not change the length");
}, "Setting (sloppy mode)");
test(() => {
const argument = { "element": "anyfunc", "initial": 2 };
const table = new WebAssembly.Table(argument);
assert_equals(table.length, 2, "Initial length");
assert_throws(new TypeError(), () => {
"use strict";
table.length = 4;
});
assert_equals(table.length, 2, "Should not change the length");
}, "Setting (strict mode)");

Просмотреть файл

@ -0,0 +1,7 @@
// META: global=jsshell
test(() => {
const argument = { "element": "anyfunc", "initial": 0 };
const table = new WebAssembly.Table(argument);
assert_class_string(table, "WebAssembly.Table");
}, "Object.prototype.toString on an Table");

Просмотреть файл

@ -181,19 +181,11 @@ var tests =
},
{
test: function(nb, ntf) {
// Create a popup to be used by a menu-button.
var doc = nb.ownerDocument;
var menuPopup = doc.createElementNS(NSXUL, "menupopup");
var menuItem = menuPopup.appendChild(doc.createElementNS(NSXUL, "menuitem"));
menuItem.setAttribute("label", "Menu Item");
// Append a notification with a button of type 'menu-button'.
ntf = nb.appendNotification(
"Notification", "note", "happy.png",
nb.PRIORITY_WARNING_LOW,
[{
label: "Button",
type: "menu-button",
popup: menuPopup
}]
);
@ -203,14 +195,6 @@ var tests =
testtag_notificationbox_State(nb, "append", ntf, 1);
testtag_notification_State(nb, ntf, "append", "Notification", "note",
"happy.png", nb.PRIORITY_WARNING_LOW);
var button = ntf.querySelector(".notification-button");
SimpleTest.is(button.type, "menu-button", "Button type should be set");
var menuPopup = button.getElementsByTagNameNS(NSXUL, "menupopup");
SimpleTest.is(menuPopup.length, 1, "There should be a menu attached");
var menuItem = menuPopup[0].firstChild;
SimpleTest.is(menuItem.localName, "menuitem", "There should be a menu item");
SimpleTest.is(menuItem.getAttribute("label"), "Menu Item", "Label should match");
// Clean up.
nb.removeNotification(ntf);
return [1, null];

Просмотреть файл

@ -233,118 +233,4 @@
</handler>
</handlers>
</binding>
<binding id="menu-button-base"
extends="chrome://global/content/bindings/button.xml#button-base">
<implementation>
<constructor>
this.init();
</constructor>
<method name="init">
<body>
<![CDATA[
var btn = document.getAnonymousElementByAttribute(this, "anonid", "button");
if (!btn)
throw "XBL binding for <button type=\"menu-button\"/> binding must contain an element with anonid=\"button\"";
var menubuttonParent = this;
btn.addEventListener("mouseover", function() {
if (!this.disabled)
menubuttonParent.buttonover = true;
}, true);
btn.addEventListener("mouseout", function() {
menubuttonParent.buttonover = false;
}, true);
btn.addEventListener("mousedown", function() {
if (!this.disabled) {
menubuttonParent.buttondown = true;
document.addEventListener("mouseup", menubuttonParent, true);
}
}, true);
]]>
</body>
</method>
<property name="buttonover" onget="return this.getAttribute('buttonover');">
<setter>
<![CDATA[
var v = val || val == "true";
if (!v && this.buttondown) {
this.buttondown = false;
this._pendingActive = true;
} else if (this._pendingActive) {
this.buttondown = true;
this._pendingActive = false;
}
if (v)
this.setAttribute("buttonover", "true");
else
this.removeAttribute("buttonover");
return val;
]]>
</setter>
</property>
<property name="buttondown" onget="return this.getAttribute('buttondown') == 'true';">
<setter>
<![CDATA[
if (val || val == "true")
this.setAttribute("buttondown", "true");
else
this.removeAttribute("buttondown");
return val;
]]>
</setter>
</property>
<field name="_pendingActive">false</field>
<method name="handleEvent">
<parameter name="aEvent"/>
<body>
<![CDATA[
this._pendingActive = false;
this.buttondown = false;
document.removeEventListener("mouseup", this, true);
]]>
</body>
</method>
</implementation>
<handlers>
<handler event="keypress" keycode="VK_RETURN">
if (event.originalTarget == this)
this.open = true;
</handler>
<handler event="keypress" key=" ">
if (event.originalTarget == this) {
this.open = true;
// Prevent page from scrolling on the space key.
event.preventDefault();
}
</handler>
</handlers>
</binding>
<binding id="menu-button" display="xul:menu"
extends="chrome://global/content/bindings/button.xml#menu-button-base">
<resources>
<stylesheet src="chrome://global/skin/button.css"/>
</resources>
<content>
<children includes="observes|template|menupopup|panel|tooltip"/>
<xul:button class="box-inherit button-menubutton-button"
anonid="button" flex="1" allowevents="true"
xbl:inherits="disabled,crop,image,label,accesskey,command,
buttonover,buttondown,align,dir,pack,orient">
<children/>
</xul:button>
<xul:dropmarker class="button-menubutton-dropmarker" xbl:inherits="open,disabled,label"/>
</content>
</binding>
</bindings>

Просмотреть файл

@ -136,16 +136,6 @@
buttonElem.setAttribute("label", button.label);
if (typeof button.accessKey == "string")
buttonElem.setAttribute("accesskey", button.accessKey);
if (typeof button.type == "string") {
buttonElem.setAttribute("type", button.type);
if ((button.type == "menu-button" || button.type == "menu") &&
"popup" in button) {
buttonElem.appendChild(button.popup);
delete button.popup;
}
if (typeof button.anchor == "string")
buttonElem.setAttribute("anchor", button.anchor);
}
buttonElem.classList.add("notification-button");
if (button.isDefault ||

Просмотреть файл

@ -108,10 +108,6 @@ button[type="menu"] {
-moz-binding: url("chrome://global/content/bindings/button.xml#menu");
}
button[type="menu-button"] {
-moz-binding: url("chrome://global/content/bindings/button.xml#menu-button");
}
/********** toolbarbutton **********/
toolbarbutton {

Просмотреть файл

@ -151,7 +151,7 @@ Lock::Find(void* aNativeLock)
}
void
Lock::Enter(const std::function<void()>& aCallback)
Lock::Enter()
{
MOZ_RELEASE_ASSERT(!AreThreadEventsPassedThrough() && !HasDivergedFromRecording());
MOZ_RELEASE_ASSERT(!AreThreadEventsDisallowed());
@ -174,9 +174,16 @@ Lock::Enter(const std::function<void()>& aCallback)
while (thread->Id() != acquires->mNextOwner) {
Thread::Wait();
}
// Acquire the lock before updating the next owner.
aCallback();
acquires->ReadAndNotifyNextOwner(thread);
}
}
void
Lock::Exit()
{
if (IsReplaying()) {
// Notify the next owner before releasing the lock.
LockAcquires* acquires = gLockAcquires.Get(mId);
acquires->ReadAndNotifyNextOwner(Thread::Current());
}
}

Просмотреть файл

@ -42,9 +42,12 @@ public:
// When recording, this is called after the lock has been acquired, and
// records the acquire in the lock's acquire order stream. When replaying,
// this is called before the lock has been acquired, and blocks the thread
// until it is next in line to acquire the lock before acquiring it via
// aCallback.
void Enter(const std::function<void()>& aCallback);
// until it is next in line to acquire the lock.
void Enter();
// This is called before releasing the lock, allowing the next owner to
// acquire it while replaying.
void Exit();
// Create a new Lock corresponding to a native lock, with a fresh ID.
static void New(void* aNativeLock);

Просмотреть файл

@ -1180,14 +1180,16 @@ WaitForCvar(pthread_mutex_t* aMutex, bool aRecordReturnValue,
RecordReplayAssert("WaitForCvar %d", (int) lock->Id());
ssize_t rv = 0;
if (IsRecording()) {
{
AutoPassThroughThreadEvents pt;
rv = aCallback();
}
AutoPassThroughThreadEvents pt;
rv = aCallback();
} else {
DirectUnlockMutex(aMutex);
}
lock->Enter([=]() { DirectLockMutex(aMutex); });
lock->Exit();
lock->Enter();
if (IsReplaying()) {
DirectLockMutex(aMutex);
}
if (aRecordReturnValue) {
return RecordReplayValue(rv);
}
@ -1273,11 +1275,20 @@ RR_pthread_mutex_lock(pthread_mutex_t* aMutex)
AutoEnsurePassThroughThreadEventsUseStackPointer pt;
return OriginalCall(pthread_mutex_lock, ssize_t, aMutex);
}
ssize_t rv = 0;
if (IsRecording()) {
DirectLockMutex(aMutex);
AutoPassThroughThreadEvents pt;
rv = OriginalCall(pthread_mutex_lock, ssize_t, aMutex);
}
lock->Enter([=]() { DirectLockMutex(aMutex); });
return 0;
rv = RecordReplayValue(rv);
MOZ_RELEASE_ASSERT(rv == 0 || rv == EDEADLK);
if (rv == 0) {
lock->Enter();
if (IsReplaying()) {
DirectLockMutex(aMutex);
}
}
return rv;
}
static ssize_t
@ -1296,7 +1307,10 @@ RR_pthread_mutex_trylock(pthread_mutex_t* aMutex)
rv = RecordReplayValue(rv);
MOZ_RELEASE_ASSERT(rv == 0 || rv == EBUSY);
if (rv == 0) {
lock->Enter([=]() { DirectLockMutex(aMutex); });
lock->Enter();
if (IsReplaying()) {
DirectLockMutex(aMutex);
}
}
return rv;
}
@ -1304,8 +1318,14 @@ RR_pthread_mutex_trylock(pthread_mutex_t* aMutex)
static ssize_t
RR_pthread_mutex_unlock(pthread_mutex_t* aMutex)
{
AutoEnsurePassThroughThreadEventsUseStackPointer pt;
return OriginalCall(pthread_mutex_unlock, ssize_t, aMutex);
Lock* lock = Lock::Find(aMutex);
if (!lock) {
AutoEnsurePassThroughThreadEventsUseStackPointer pt;
return OriginalCall(pthread_mutex_unlock, ssize_t, aMutex);
}
lock->Exit();
DirectUnlockMutex(aMutex);
return 0;
}
///////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -43,25 +43,12 @@ button[disabled="true"] {
color: GrayText;
}
/* ::::: menu/menu-button buttons ::::: */
/* ::::: menu buttons ::::: */
button[type="menu-button"] {
-moz-appearance: dualbutton;
}
.button-menubutton-button {
margin: 0;
}
.button-menu-dropmarker,
.button-menubutton-dropmarker {
.button-menu-dropmarker {
-moz-appearance: toolbarbutton-dropdown !important;
}
.button-menubutton-dropmarker {
margin-inline-end: 3px;
}
/* ::::: plain buttons ::::: */
button.plain {

Просмотреть файл

@ -80,7 +80,7 @@ menucaption {
/* ::::: menu/menuitems in menulist popups ::::: */
menulist > menupopup {
font: message-box;
font: inherit;
}
menulist > menupopup > menuitem,

Просмотреть файл

@ -51,25 +51,16 @@ button[disabled="true"] {
color: GrayText;
}
/* ::::: menu/menu-button buttons ::::: */
/* ::::: menu buttons ::::: */
button[type="menu-button"] {
margin: 0;
border: none;
}
.button-menu-dropmarker,
.button-menubutton-dropmarker {
.button-menu-dropmarker {
display: none;
-moz-appearance: none !important;
border: none;
background-color: transparent !important;
margin: 1px;
}
.button-menu-dropmarker {
display: none;
}
/* ::::: plain buttons ::::: */
button.plain {

Просмотреть файл

@ -77,27 +77,15 @@ button[disabled="true"] {
}
}
/* ::::: menu/menu-button buttons ::::: */
/* ::::: menu buttons ::::: */
button[type="menu-button"] {
margin: 0;
}
.button-menu-dropmarker,
.button-menubutton-dropmarker {
.button-menu-dropmarker {
-moz-appearance: none !important;
margin: 1px;
width: 11px;
height: 11px;
}
.button-menubutton-dropmarker[open="true"] {
margin-top: 2px;
margin-bottom: 0px;
margin-inline-start: 2px;
margin-inline-end: 0px;
}
/* ::::: plain buttons ::::: */
button.plain {

Просмотреть файл

@ -170,7 +170,7 @@ menuitem[_moz-menuactive="true"] {
/* ::::: menu/menuitems in menulist popups ::::: */
menulist > menupopup {
font: message-box;
font: inherit;
}
menulist > menupopup > menuitem,

Просмотреть файл

@ -590,7 +590,6 @@ STATIC_ATOMS = [
Atom("menu", "menu"),
Atom("menubar", "menubar"),
Atom("menubutton", "menubutton"),
Atom("menuButton", "menu-button"),
Atom("menucaption", "menucaption"),
Atom("menugroup", "menugroup"),
Atom("menuitem", "menuitem"),