Merge branch 'mozilla-central'

This commit is contained in:
Jacek Caban 2016-03-07 05:56:30 +01:00
commit bfa05a5560
68 changed files with 1969 additions and 1077 deletions

View File

@ -193,6 +193,18 @@ extensions.registerSchemaAPI("bookmarks", "bookmarks", (extension, context) => {
};
// The API doesn't give you the old bookmark at the moment
try {
return Bookmarks.remove(info, {preventRemovalOfNonEmptyFolders: true}).then(result => {});
} catch (e) {
return Promise.reject({message: `Invalid bookmark: ${JSON.stringify(info)}`});
}
},
removeTree: function(id) {
let info = {
guid: id,
};
try {
return Bookmarks.remove(info).then(result => {});
} catch (e) {

View File

@ -400,7 +400,6 @@
},
{
"name": "removeTree",
"unsupported": true,
"type": "function",
"description": "Recursively removes a bookmark folder.",
"async": "callback",

View File

@ -17,3 +17,4 @@ support-files =
[browser_service_workers_push.js]
[browser_service_workers_start.js]
[browser_service_workers_timeout.js]
skip-if = true # Bug 1232931

View File

@ -1,7 +1,7 @@
[DEFAULT]
tags = devtools
subsuite = devtools
skip-if = (e10s && debug && os == 'mac') # bug 1252283
skip-if = e10s && debug # bug 1252283
support-files =
doc_body_animation.html
doc_frame_script.js

View File

@ -70,7 +70,7 @@ support-files =
[browser_rules_completion-popup-hidden-after-navigation.js]
[browser_rules_content_01.js]
[browser_rules_content_02.js]
skip-if = e10s && debug && (os == 'mac' || os == 'win') # Bug 1250058 - Docshell leak on osx/win debug e10s
skip-if = e10s && debug # Bug 1250058 - Docshell leak on debug e10s
[browser_rules_context-menu-show-mdn-docs-01.js]
[browser_rules_context-menu-show-mdn-docs-02.js]
[browser_rules_context-menu-show-mdn-docs-03.js]

View File

@ -79,7 +79,7 @@ support-files =
[browser_inspector_iframe-navigation.js]
[browser_inspector_infobar_01.js]
[browser_inspector_initialization.js]
skip-if = e10s && debug && (os == 'mac' || os == 'win') # Bug 1250058 - Docshell leak on osx/win debug e10s
skip-if = (e10s && debug) # Bug 1250058 - Docshell leak on debug e10s
[browser_inspector_inspect-object-element.js]
[browser_inspector_invalidate.js]
[browser_inspector_keyboard-shortcuts-copy-outerhtml.js]

View File

@ -69,6 +69,7 @@ skip-if = e10s # Bug 1091596
[browser_net_cyrillic-01.js]
[browser_net_cyrillic-02.js]
[browser_net_details-no-duplicated-content.js]
skip-if = (os == 'linux' && e10s && debug) # Bug 1242204
[browser_net_filter-01.js]
[browser_net_filter-02.js]
[browser_net_filter-03.js]
@ -77,7 +78,7 @@ skip-if = e10s # Bug 1091596
[browser_net_html-preview.js]
[browser_net_icon-preview.js]
[browser_net_image-tooltip.js]
skip-if = (os == "win" && os_version == "6.2" && bits == 64) # Bug 1234341
skip-if = true # Bug 1234341, bug 1252641
[browser_net_json-long.js]
[browser_net_json-malformed.js]
[browser_net_json_custom_mime.js]

View File

@ -7,9 +7,9 @@ support-files =
[browser_responsive_cmd.js]
[browser_responsivecomputedview.js]
skip-if = e10s && debug && (os == 'win' || os == 'mac') # Bug 1252201 - Docshell leak on win/osx debug e10s
skip-if = e10s && debug # Bug 1252201 - Docshell leak on debug e10s
[browser_responsiveruleview.js]
skip-if = e10s && debug && (os == 'win' || os == 'mac') # Bug 1252201 - Docshell leak on win/osx debug e10s
skip-if = e10s && debug # Bug 1252201 - Docshell leak on debug e10s
[browser_responsiveui.js]
[browser_responsiveui_touch.js]
[browser_responsiveuiaddcustompreset.js]

View File

@ -16,5 +16,5 @@ support-files =
[browser_storage_overflow.js]
[browser_storage_search.js]
[browser_storage_sidebar.js]
skip-if = (os == 'win' && os_version == '6.1' && e10s && !debug) # bug 1229272
skip-if = (os == 'win' && e10s) # bug 1229272
[browser_storage_values.js]

View File

@ -59,6 +59,7 @@ support-files =
[browser_styleeditor_cmd_edit.js]
[browser_styleeditor_enabled.js]
[browser_styleeditor_fetch-from-cache.js]
skip-if = e10s && debug && (os == 'win')
[browser_styleeditor_filesave.js]
[browser_styleeditor_highlight-selector.js]
[browser_styleeditor_import.js]
@ -68,7 +69,7 @@ support-files =
[browser_styleeditor_loading.js]
[browser_styleeditor_media_sidebar.js]
[browser_styleeditor_media_sidebar_links.js]
skip-if = e10s && debug && (os == 'win' || os == 'mac') # Bug 1252201 - Docshell leak on win/osx debug e10s
skip-if = e10s && debug # Bug 1252201 - Docshell leak on debug e10s
[browser_styleeditor_media_sidebar_sourcemaps.js]
[browser_styleeditor_missing_stylesheet.js]
[browser_styleeditor_navigate.js]

View File

@ -314,24 +314,25 @@ ExplicitChildIterator::GetPreviousChild()
bool
AllChildrenIterator::Seek(nsIContent* aChildToFind)
{
if (mPhase == eNeedBeforeKid) {
mPhase = eNeedExplicitKids;
if (mPhase == eAtBegin || mPhase == eAtBeforeKid) {
mPhase = eAtExplicitKids;
nsIFrame* frame = mOriginalContent->GetPrimaryFrame();
if (frame) {
nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(frame);
if (beforeFrame) {
if (beforeFrame->GetContent() == aChildToFind) {
mPhase = eAtBeforeKid;
return true;
}
}
}
}
if (mPhase == eNeedExplicitKids) {
if (mPhase == eAtExplicitKids) {
if (ExplicitChildIterator::Seek(aChildToFind)) {
return true;
}
mPhase = eNeedAnonKids;
mPhase = eAtAnonKids;
}
nsIContent* child = nullptr;
@ -345,59 +346,124 @@ AllChildrenIterator::Seek(nsIContent* aChildToFind)
nsIContent*
AllChildrenIterator::GetNextChild()
{
if (mPhase == eNeedBeforeKid) {
mPhase = eNeedExplicitKids;
if (mPhase == eAtBegin) {
mPhase = eAtExplicitKids;
nsIFrame* frame = mOriginalContent->GetPrimaryFrame();
if (frame) {
nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(frame);
if (beforeFrame) {
mPhase = eAtBeforeKid;
return beforeFrame->GetContent();
}
}
}
if (mPhase == eNeedExplicitKids) {
if (mPhase == eAtBeforeKid) {
// Advance into our explicit kids.
mPhase = eAtExplicitKids;
}
if (mPhase == eAtExplicitKids) {
nsIContent* kid = ExplicitChildIterator::GetNextChild();
if (kid) {
return kid;
}
mPhase = eNeedAnonKids;
mPhase = eAtAnonKids;
}
if (mPhase == eNeedAnonKids) {
if (mPhase == eAtAnonKids) {
if (mAnonKids.IsEmpty()) {
MOZ_ASSERT(mAnonKidsIdx == UINT32_MAX);
nsIAnonymousContentCreator* ac =
do_QueryFrame(mOriginalContent->GetPrimaryFrame());
if (ac) {
ac->AppendAnonymousContentTo(mAnonKids, mFlags);
}
mAnonKidsIdx = 0;
}
if (!mAnonKids.IsEmpty()) {
nsIContent* nextKid = mAnonKids[0];
mAnonKids.RemoveElementAt(0);
if (mAnonKids.IsEmpty()) {
mPhase = eNeedAfterKid;
else {
if (mAnonKidsIdx == UINT32_MAX) {
mAnonKidsIdx = 0;
}
else {
mAnonKidsIdx++;
}
return nextKid;
}
mPhase = eNeedAfterKid;
}
if (mAnonKidsIdx < mAnonKids.Length()) {
return mAnonKids[mAnonKidsIdx];
}
if (mPhase == eNeedAfterKid) {
mPhase = eDone;
nsIFrame* frame = mOriginalContent->GetPrimaryFrame();
if (frame) {
nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(frame);
if (afterFrame) {
mPhase = eAtAfterKid;
return afterFrame->GetContent();
}
}
}
mPhase = eAtEnd;
return nullptr;
}
nsIContent*
AllChildrenIterator::GetPreviousChild()
{
if (mPhase == eAtEnd) {
MOZ_ASSERT(mAnonKidsIdx == mAnonKids.Length());
mPhase = eAtAnonKids;
nsIFrame* frame = mOriginalContent->GetPrimaryFrame();
if (frame) {
nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(frame);
if (afterFrame) {
mPhase = eAtAfterKid;
return afterFrame->GetContent();
}
}
}
if (mPhase == eAtAfterKid) {
mPhase = eAtAnonKids;
}
if (mPhase == eAtAnonKids) {
if (mAnonKids.IsEmpty()) {
nsIAnonymousContentCreator* ac =
do_QueryFrame(mOriginalContent->GetPrimaryFrame());
if (ac) {
ac->AppendAnonymousContentTo(mAnonKids, mFlags);
mAnonKidsIdx = mAnonKids.Length();
}
}
// If 0 then it turns into UINT32_MAX, which indicates the iterator is
// before the anonymous children.
--mAnonKidsIdx;
if (mAnonKidsIdx < mAnonKids.Length()) {
return mAnonKids[mAnonKidsIdx];
}
mPhase = eAtExplicitKids;
}
if (mPhase == eAtExplicitKids) {
nsIContent* kid = ExplicitChildIterator::GetPreviousChild();
if (kid) {
return kid;
}
nsIFrame* frame = mOriginalContent->GetPrimaryFrame();
if (frame) {
nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(frame);
if (beforeFrame) {
mPhase = eAtBeforeKid;
return beforeFrame->GetContent();
}
}
}
mPhase = eAtBegin;
return nullptr;
}

View File

@ -182,14 +182,14 @@ class AllChildrenIterator : private FlattenedChildIterator
public:
AllChildrenIterator(nsIContent* aNode, uint32_t aFlags, bool aStartAtBeginning = true) :
FlattenedChildIterator(aNode, aFlags, aStartAtBeginning),
mOriginalContent(aNode), mFlags(aFlags),
mPhase(eNeedBeforeKid) {}
mOriginalContent(aNode), mAnonKidsIdx(aStartAtBeginning ? UINT32_MAX : 0),
mFlags(aFlags), mPhase(aStartAtBeginning ? eAtBegin : eAtEnd) { }
AllChildrenIterator(AllChildrenIterator&& aOther)
: FlattenedChildIterator(Move(aOther)),
mOriginalContent(aOther.mOriginalContent),
mAnonKids(Move(aOther.mAnonKids)), mFlags(aOther.mFlags),
mPhase(aOther.mPhase)
mAnonKids(Move(aOther.mAnonKids)), mAnonKidsIdx(aOther.mAnonKidsIdx),
mFlags(aOther.mFlags), mPhase(aOther.mPhase)
#ifdef DEBUG
, mMutationGuard(aOther.mMutationGuard)
#endif
@ -202,20 +202,32 @@ public:
bool Seek(nsIContent* aChildToFind);
nsIContent* GetNextChild();
nsIContent* GetPreviousChild();
nsIContent* Parent() const { return mOriginalContent; }
private:
enum IteratorPhase
{
eNeedBeforeKid,
eNeedExplicitKids,
eNeedAnonKids,
eNeedAfterKid,
eDone
eAtBegin,
eAtBeforeKid,
eAtExplicitKids,
eAtAnonKids,
eAtAfterKid,
eAtEnd
};
IteratorPhase Phase() const { return mPhase; }
private:
nsIContent* mOriginalContent;
// mAnonKids is an array of native anonymous children, mAnonKidsIdx is index
// in the array. If mAnonKidsIdx < mAnonKids.Length() and mPhase is
// eAtAnonKids then the iterator points at a child at mAnonKidsIdx index. If
// mAnonKidsIdx == mAnonKids.Length() then the iterator is somewhere after
// the last native anon child. If mAnonKidsIdx == UINT32_MAX then the iterator
// is somewhere before the first native anon child.
nsTArray<nsIContent*> mAnonKids;
uint32_t mAnonKidsIdx;
uint32_t mFlags;
IteratorPhase mPhase;
#ifdef DEBUG

View File

@ -4357,8 +4357,8 @@ HTMLInputElement::HandleTypeChange(uint8_t aNewType)
// previous type does, we should clear out mFocusedValue.
if (MayFireChangeOnBlur(mType) && !MayFireChangeOnBlur(oldType)) {
GetValue(mFocusedValue);
} else if (!IsSingleLineTextControl(mType, false) &&
IsSingleLineTextControl(oldType, false)) {
} else if (!IsSingleLineTextControl(false, mType) &&
IsSingleLineTextControl(false, oldType)) {
mFocusedValue.Truncate();
}

View File

@ -14,11 +14,9 @@
var testAudio = createMediaElement('audio', 'testAudio');
return new Promise((resolve, reject) => {
navigator.mozGetUserMedia({ audio: true }, () => {
var syncXHR = new XMLHttpRequest();
syncXHR.open('GET', location, false);
syncXHR.send();
ok(true, "Didn't crash");
resolve();
SpecialPowers.spinEventLoop(window);
ok(true, "Didn't crash");
resolve();
}, () => {});
});
});

View File

@ -7,7 +7,6 @@ support-files =
hello.ogg^headers^
silence.ogg
silence.ogg^headers^
[test_abort.html]
skip-if = toolkit == 'android' # bug 1037287
[test_audio_capture_error.html]
@ -15,7 +14,7 @@ skip-if = toolkit == 'android' # bug 1037287
tags=capturestream
skip-if = (android_version == '18' && debug) # bug 967606
[test_nested_eventloop.html]
skip-if = buildapp == 'mulet' || toolkit == 'android' || e10s # b2g(showmodaldialog)
skip-if = buildapp == 'mulet' || toolkit == 'android'
[test_preference_enable.html]
[test_recognition_service_error.html]
[test_success_without_recognition_service.html]

View File

@ -27,12 +27,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=650295
* When this is done from inside DOM event handlers, it is possible to
* cause reentrancy in our C++ code, which we should be able to withstand.
*/
function abortAndSpinEventLoop(evt, sr) {
sr.abort();
window.showModalDialog("javascript:window.close()");
SpecialPowers.spinEventLoop(window);
}
function doneFunc() {
// Trigger gc now and wait some time to make sure this test gets the blame
// for any assertions caused by showModalDialog

View File

@ -25,7 +25,7 @@ skip-if = buildapp == 'b2g'
skip-if = toolkit=='gonk' || toolkit == 'android' #TIMED_OUT # b2g-debug(debug-only timeout)
[test_geolocation_is_undefined_when_pref_is_off.html]
[test_handlerSpinsEventLoop.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s #Don't run modal tests on Android # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #Don't run modal tests on Android
[test_manyCurrentConcurrent.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
[test_manyCurrentSerial.html]

View File

@ -38,7 +38,7 @@ function spinEventLoopAndSetTimeout() {
return;
}
window.showModalDialog("javascript:window.close()");
SpecialPowers.spinEventLoop(window);
setTimeout(function() {
ok(successCallbackCalled != errorCallbackCalled, "Ensure only one callback is called");

View File

@ -2113,8 +2113,14 @@ nsWindowWatcher::SizeOpenedDocShellItem(nsIDocShellTreeItem* aDocShellItem,
int32_t winWidth = width + (sizeChromeWidth ? 0 : chromeWidth),
winHeight = height + (sizeChromeHeight ? 0 : chromeHeight);
screen->GetAvailRectDisplayPix(&screenLeft, &screenTop, &screenWidth,
&screenHeight);
// Get screen dimensions (in device pixels)
screen->GetAvailRect(&screenLeft, &screenTop, &screenWidth,
&screenHeight);
// Convert them to CSS pixels
screenLeft = NSToIntRound(screenLeft / scale);
screenTop = NSToIntRound(screenTop / scale);
screenWidth = NSToIntRound(screenWidth / scale);
screenHeight = NSToIntRound(screenHeight / scale);
if (aSizeSpec.SizeSpecified()) {
/* Unlike position, force size out-of-bounds check only if

View File

@ -492,6 +492,10 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
aState.mPaintLogger.LogTestData(aMetrics.GetScrollId(),
"parentScrollId", apzc->GetParent()->GetGuid().mScrollId);
}
if (aMetrics.IsRootContent()) {
aState.mPaintLogger.LogTestData(aMetrics.GetScrollId(),
"isRootContent", true);
}
}
if (newApzc) {

View File

@ -39,46 +39,6 @@ function convertTestData(testData) {
return result;
}
// ----------------------------------------------------------------
// Utilities for reconstructing the structure of the APZC tree from
// 'parentScrollId' entries in the APZ test data.
// ----------------------------------------------------------------
// Create a node with scroll id 'id' in the APZC tree.
function makeNode(id) {
return {scrollId: id, children: []};
}
// Find a node with scroll id 'id' in the APZC tree rooted at 'root'.
function findNode(root, id) {
if (root.scrollId == id) {
return root;
}
for (var i = 0; i < root.children.length; ++i) {
var subtreeResult = findNode(root.children[i], id);
if (subtreeResult != null) {
return subtreeResult;
}
}
return null;
}
// Add a child -> parent link to the APZC tree rooted at 'root'.
function addLink(root, child, parent) {
var parentNode = findNode(root, parent);
if (parentNode == null) {
parentNode = makeNode(parent);
root.children.push(parentNode);
}
parentNode.children.push(makeNode(child));
}
// Add a root node to the APZC tree. It will become a direct
// child of 'root'.
function addRoot(root, id) {
root.children.push(makeNode(id));
}
// Given APZ test data for a single paint on the compositor side,
// reconstruct the APZC tree structure from the 'parentScrollId'
// entries that were logged. More specifically, the subset of the
@ -89,17 +49,38 @@ function buildApzcTree(paint) {
// The APZC tree can potentially have multiple root nodes,
// so we invent a node that is the parent of all roots.
// This 'root' does not correspond to an APZC.
var root = makeNode(-1);
var root = {scrollId: -1, children: []};
for (var scrollId in paint) {
paint[scrollId].children = [];
paint[scrollId].scrollId = scrollId;
}
for (var scrollId in paint) {
var parentNode = null;
if ("hasNoParentWithSameLayersId" in paint[scrollId]) {
addRoot(root, scrollId);
parentNode = root;
} else if ("parentScrollId" in paint[scrollId]) {
addLink(root, scrollId, paint[scrollId]["parentScrollId"]);
parentNode = paint[paint[scrollId].parentScrollId];
}
parentNode.children.push(paint[scrollId]);
}
return root;
}
// Given an APZC tree produced by buildApzcTree, return the RCD node in
// the tree, or null if there was none.
function findRcdNode(apzcTree) {
if (!!apzcTree.isRootContent) { // isRootContent will be undefined or "1"
return apzcTree;
}
for (var i = 0; i < apzcTree.children.length; i++) {
var rcd = findRcdNode(apzcTree.children[i]);
if (rcd != null) {
return rcd;
}
}
return null;
}
function flushApzRepaints(aCallback, aWindow = window) {
if (!aCallback) {
throw "A callback must be provided!";

View File

@ -55,15 +55,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1151663
// Convert the test data into a representation that's easier to navigate.
contentTestData = convertTestData(contentTestData);
compositorTestData = convertTestData(compositorTestData);
var paint = compositorTestData.paints[lastCompositorPaintSeqNo];
// Reconstruct the APZC tree structure in the last paint.
var apzcTree = buildApzcTree(compositorTestData.paints[lastCompositorPaintSeqNo]);
var apzcTree = buildApzcTree(paint);
// The apzc tree for this page should consist of a single root APZC,
// and no child APZCs.
SimpleTest.is(apzcTree.children.length, 1, "expected a single root APZC");
var rootApzc = apzcTree.children[0];
SimpleTest.is(rootApzc.children.length, 0, "expected no child APZCs");
// which either is the RCD with no child APZCs (e10s/B2G case) or has a
// single child APZC which is for the RCD (fennec case).
var rcd = findRcdNode(apzcTree);
SimpleTest.ok(rcd != null, "found the RCD node");
SimpleTest.is(rcd.children.length, 0, "expected no children on the RCD");
window.opener.finishTest();
}

View File

@ -59,12 +59,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=982141
// Reconstruct the APZC tree structure in the last paint.
var apzcTree = buildApzcTree(compositorTestData.paints[lastCompositorPaintSeqNo]);
// The apzc tree for this page should consist of a single root APZC
// and a child APZC for the scrollable <div>.
SimpleTest.is(apzcTree.children.length, 1, "expected a single root APZC");
var rootApzc = apzcTree.children[0];
SimpleTest.is(rootApzc.children.length, 1, "expected a single child APZC");
var childScrollId = rootApzc.children[0].scrollId;
// The apzc tree for this page should consist of a single child APZC on
// the RCD node (the child is for scrollable <div>). Note that in e10s/B2G
// cases the RCD will be the root of the tree but on Fennec it will not.
var rcd = findRcdNode(apzcTree);
SimpleTest.ok(rcd != null, "found the RCD node");
SimpleTest.is(rcd.children.length, 1, "expected a single child APZC");
var childScrollId = rcd.children[0].scrollId;
// We should have content-side data for the same paint.
SimpleTest.ok(lastCompositorPaintSeqNo in contentTestData.paints,
@ -82,7 +83,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=982141
var dpWidth = dpFields[2];
var dpHeight = dpFields[3];
SimpleTest.ok(dpWidth >= 50 && dpHeight >= 50,
"expected a displayport at least as large as the scrollable element");
"expected a displayport at least as large as the scrollable element, got " + childDisplayport);
window.opener.finishTest();
}
@ -92,6 +93,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=982141
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=982141">Mozilla Bug 982141</a>
<!-- A scrollable subframe, with enough content to make it have a nonzero scroll range -->
<div style="height: 50px; width: 50px; overflow: scroll">
<div style="width: 100px">
Wide content so that the vertical scrollbar for the parent div
doesn't eat into the 50px width and reduce the width of the
displayport.
</div>
Line 1<br>
Line 2<br>
Line 3<br>

View File

@ -13,9 +13,7 @@ support-files =
helper_tap.html
tags = apz
[test_bug982141.html]
skip-if = toolkit != 'gonk' # bug 991198
[test_bug1151663.html]
skip-if = toolkit != 'gonk' # bug 991198
[test_wheel_scroll.html]
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
[test_wheel_transactions.html]

View File

@ -8,7 +8,6 @@
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
SimpleTest.testInChaosMode();
// this page just serially loads each one of the following test helper pages in
// a new window and waits for it to call testDone()
@ -53,8 +52,10 @@ window.onload = function() {
["apz.touch_start_tolerance", "0.0"],
// The touchstart from the drag can turn into a long-tap if the touch-move
// events get held up. Try to prevent that by making long-taps require
// a 10 second hold.
["ui.click_hold_context_menus.delay", "10000"],
// a 10 second hold. Note that we also cannot enable chaos mode on this
// test for this reason, since chaos mode can cause the long-press timer
// to fire sooner than the pref dictates.
["ui.click_hold_context_menus.delay", 10000],
// The subtests in this test do touch-drags to pan the page, but we don't
// want those pans to turn into fling animations, so we increase the
// fling-stop threshold velocity to absurdly high.

View File

@ -17,6 +17,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1151663
// inside an iframe which means we have no control over the root APZC.
var w = null;
window.onload = function() {
if (!SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled) {
ok(true, "APZ is not enabled, this test is not relevant, sorry!\n");
SimpleTest.finish();
return;
}
SpecialPowers.pushPrefEnv({"set": [["apz.test.logging_enabled", true]]}, function() {
w = window.open("helper_bug1151663.html", "_blank");
});

View File

@ -17,6 +17,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=982141
// inside an iframe which means we have no control over the root APZC.
var w = null;
window.onload = function() {
if (!SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled) {
ok(true, "APZ is not enabled, this test is not relevant, sorry!\n");
SimpleTest.finish();
return;
}
SpecialPowers.pushPrefEnv({"set": [["apz.test.logging_enabled", true]]}, function() {
w = window.open("helper_bug982141.html", "_blank");
});

View File

@ -19,11 +19,12 @@ namespace mozilla {
namespace layout {
class RenderFrameChild;
class ShadowLayerForwarder;
} // namespace layout
namespace layers {
class ShadowLayerForwarder;
class LayerTransactionChild : public PLayerTransactionChild
, public AsyncTransactionTrackersHolder
{

View File

@ -2,6 +2,7 @@
skip-if = buildapp == 'mulet' || buildapp == 'b2g'
[test_acceleration.html]
fail-if = (os == "win" && os_version == "5.1" && e10s) # Bug 1253862
[test_bug509244.html]
[test_bug513439.html]
skip-if = e10s

View File

@ -2680,8 +2680,7 @@ class MOZ_STACK_CLASS FunctionValidator
LocalMap::AddPtr p = locals_.lookupForAdd(name);
if (p)
return failName(pn, "duplicate local name '%s' not allowed", name);
return locals_.add(p, name, Local(type, locals_.count())) &&
fg_.addLocal(type.canonicalToValType());
return locals_.add(p, name, Local(type, locals_.count()));
}
/****************************** For consistency of returns in a function */
@ -2823,7 +2822,7 @@ class MOZ_STACK_CLASS FunctionValidator
return encoder().writeExpr(Expr::I32Const) &&
encoder().writeVarU32(i32);
}
MOZ_WARN_UNUSED_RESULT bool writeLit(NumLit lit) {
MOZ_WARN_UNUSED_RESULT bool writeConstExpr(NumLit lit) {
switch (lit.which()) {
case NumLit::Fixnum:
case NumLit::NegativeInt:
@ -3486,15 +3485,7 @@ CheckFinalReturn(FunctionValidator& f, ParseNode* lastNonEmptyStmt)
}
static bool
SetLocal(FunctionValidator& f, NumLit lit)
{
return f.encoder().writeExpr(Expr::SetLocal) &&
f.encoder().writeVarU32(f.numLocals()) &&
f.writeLit(lit);
}
static bool
CheckVariable(FunctionValidator& f, ParseNode* var)
CheckVariable(FunctionValidator& f, ParseNode* var, ValTypeVector* types, Vector<NumLit>* inits)
{
if (!IsDefinition(var))
return f.fail(var, "local variable names must not restate argument names");
@ -3515,12 +3506,11 @@ CheckVariable(FunctionValidator& f, ParseNode* var)
if (!lit.valid())
return f.failName(var, "var '%s' initializer out of range", name);
if (!lit.isZeroBits()) {
if (!SetLocal(f, lit))
return false;
}
Type type = Type::canonicalize(Type::lit(lit));
return f.addLocal(var, name, Type::canonicalize(Type::lit(lit)));
return f.addLocal(var, name, type) &&
types->append(type.canonicalToValType()) &&
inits->append(lit);
}
static bool
@ -3528,13 +3518,40 @@ CheckVariables(FunctionValidator& f, ParseNode** stmtIter)
{
ParseNode* stmt = *stmtIter;
uint32_t firstVar = f.numLocals();
ValTypeVector types;
Vector<NumLit> inits(f.cx());
for (; stmt && stmt->isKind(PNK_VAR); stmt = NextNonEmptyStatement(stmt)) {
for (ParseNode* var = VarListHead(stmt); var; var = NextNode(var)) {
if (!CheckVariable(f, var))
if (!CheckVariable(f, var, &types, &inits))
return false;
}
}
MOZ_ASSERT(f.encoder().empty());
if (!f.encoder().writeVarU32(types.length()))
return false;
for (ValType v : types) {
if (!f.encoder().writeValType(v))
return false;
}
for (uint32_t i = 0; i < inits.length(); i++) {
NumLit lit = inits[i];
if (lit.isZeroBits())
continue;
if (!f.encoder().writeExpr(Expr::SetLocal))
return false;
if (!f.encoder().writeVarU32(firstVar + i))
return false;
if (!f.writeConstExpr(lit))
return false;
}
*stmtIter = stmt;
return true;
}
@ -3549,7 +3566,7 @@ CheckNumericLiteral(FunctionValidator& f, ParseNode* num, Type* type)
if (!lit.valid())
return f.fail(num, "numeric literal out of representable integer range");
*type = Type::lit(lit);
return f.writeLit(lit);
return f.writeConstExpr(lit);
}
static bool
@ -3570,7 +3587,7 @@ CheckVarRef(FunctionValidator& f, ParseNode* varRef, Type* type)
switch (global->which()) {
case ModuleValidator::Global::ConstantLiteral:
*type = global->varOrConstType();
return f.writeLit(global->constLiteralValue());
return f.writeConstExpr(global->constLiteralValue());
case ModuleValidator::Global::ConstantImport:
case ModuleValidator::Global::Variable: {
*type = global->varOrConstType();
@ -3729,14 +3746,14 @@ CheckLoadArray(FunctionValidator& f, ParseNode* elem, Type* type)
return false;
switch (viewType) {
case Scalar::Int8: f.encoder().patchExpr(opcodeAt, Expr::I32LoadMem8S); break;
case Scalar::Uint8: f.encoder().patchExpr(opcodeAt, Expr::I32LoadMem8U); break;
case Scalar::Int16: f.encoder().patchExpr(opcodeAt, Expr::I32LoadMem16S); break;
case Scalar::Uint16: f.encoder().patchExpr(opcodeAt, Expr::I32LoadMem16U); break;
case Scalar::Int8: f.encoder().patchExpr(opcodeAt, Expr::I32Load8S); break;
case Scalar::Uint8: f.encoder().patchExpr(opcodeAt, Expr::I32Load8U); break;
case Scalar::Int16: f.encoder().patchExpr(opcodeAt, Expr::I32Load16S); break;
case Scalar::Uint16: f.encoder().patchExpr(opcodeAt, Expr::I32Load16U); break;
case Scalar::Uint32:
case Scalar::Int32: f.encoder().patchExpr(opcodeAt, Expr::I32LoadMem); break;
case Scalar::Float32: f.encoder().patchExpr(opcodeAt, Expr::F32LoadMem); break;
case Scalar::Float64: f.encoder().patchExpr(opcodeAt, Expr::F64LoadMem); break;
case Scalar::Int32: f.encoder().patchExpr(opcodeAt, Expr::I32Load); break;
case Scalar::Float32: f.encoder().patchExpr(opcodeAt, Expr::F32Load); break;
case Scalar::Float64: f.encoder().patchExpr(opcodeAt, Expr::F64Load); break;
default: MOZ_CRASH("unexpected scalar type");
}
@ -3801,27 +3818,27 @@ CheckStoreArray(FunctionValidator& f, ParseNode* lhs, ParseNode* rhs, Type* type
switch (viewType) {
case Scalar::Int8:
case Scalar::Uint8:
f.encoder().patchExpr(opcodeAt, Expr::I32StoreMem8);
f.encoder().patchExpr(opcodeAt, Expr::I32Store8);
break;
case Scalar::Int16:
case Scalar::Uint16:
f.encoder().patchExpr(opcodeAt, Expr::I32StoreMem16);
f.encoder().patchExpr(opcodeAt, Expr::I32Store16);
break;
case Scalar::Int32:
case Scalar::Uint32:
f.encoder().patchExpr(opcodeAt, Expr::I32StoreMem);
f.encoder().patchExpr(opcodeAt, Expr::I32Store);
break;
case Scalar::Float32:
if (rhsType.isFloatish())
f.encoder().patchExpr(opcodeAt, Expr::F32StoreMem);
f.encoder().patchExpr(opcodeAt, Expr::F32Store);
else
f.encoder().patchExpr(opcodeAt, Expr::F64StoreMemF32);
f.encoder().patchExpr(opcodeAt, Expr::F64StoreF32);
break;
case Scalar::Float64:
if (rhsType.isFloatish())
f.encoder().patchExpr(opcodeAt, Expr::F32StoreMemF64);
f.encoder().patchExpr(opcodeAt, Expr::F32StoreF64);
else
f.encoder().patchExpr(opcodeAt, Expr::F64StoreMem);
f.encoder().patchExpr(opcodeAt, Expr::F64Store);
break;
default: MOZ_CRASH("unexpected scalar type");
}
@ -5461,7 +5478,7 @@ CheckCoercedCall(FunctionValidator& f, ParseNode* call, Type ret, Type* type)
if (!f.encoder().writePatchableExpr(&coerceOp))
return false;
NumLit lit = ExtractNumericLiteral(f.m(), call);
if (!f.writeLit(lit))
if (!f.writeConstExpr(lit))
return false;
return CoerceResult(f, call, ret, Type::lit(lit), coerceOp, type);
}

View File

@ -86,19 +86,21 @@ class FunctionDecoder
ModuleGenerator& mg_;
FunctionGenerator& fg_;
uint32_t funcIndex_;
const ValTypeVector& locals_;
Vector<ExprType> blocks_;
public:
FunctionDecoder(JSContext* cx, Decoder& d, ModuleGenerator& mg, FunctionGenerator& fg,
uint32_t funcIndex)
: cx_(cx), d_(d), mg_(mg), fg_(fg), funcIndex_(funcIndex), blocks_(cx)
uint32_t funcIndex, const ValTypeVector& locals)
: cx_(cx), d_(d), mg_(mg), fg_(fg), funcIndex_(funcIndex), locals_(locals), blocks_(cx)
{}
JSContext* cx() const { return cx_; }
Decoder& d() const { return d_; }
ModuleGenerator& mg() const { return mg_; }
FunctionGenerator& fg() const { return fg_; }
uint32_t funcIndex() const { return funcIndex_; }
ExprType ret() const { return mg_.funcSig(funcIndex_).ret(); }
const ValTypeVector& locals() const { return locals_; }
const DeclaredSig& sig() const { return mg_.funcSig(funcIndex_); }
bool fail(const char* str) {
return Fail(cx_, d_, str);
@ -154,21 +156,19 @@ DecodeValType(JSContext* cx, Decoder& d, ValType *type)
case ValType::I32:
case ValType::F32:
case ValType::F64:
break;
return true;
case ValType::I64:
#ifndef JS_CPU_X64
return Fail(cx, d, "i64 NYI on this platform");
#endif
return true;
default:
// Note: it's important not to remove this default since readValType()
// can return ValType values for which there is no enumerator.
break;
case ValType::I32x4:
case ValType::F32x4:
case ValType::B32x4:
return Fail(cx, d, "value type NYI");
case ValType::Limit:
MOZ_CRASH("Limit");
}
return true;
return Fail(cx, "bad value type");
}
static bool
@ -182,21 +182,19 @@ DecodeExprType(JSContext* cx, Decoder& d, ExprType *type)
case ExprType::F32:
case ExprType::F64:
case ExprType::Void:
break;
return true;
case ExprType::I64:
#ifndef JS_CPU_X64
return Fail(cx, d, "i64 NYI on this platform");
#endif
return true;
default:
// Note: it's important not to remove this default since readExprType()
// can return ExprType values for which there is no enumerator.
break;
case ExprType::I32x4:
case ExprType::F32x4:
case ExprType::B32x4:
return Fail(cx, d, "expression type NYI");
case ExprType::Limit:
MOZ_CRASH("Limit");
}
return true;
return Fail(cx, "bad expression type");
}
static bool
@ -329,10 +327,10 @@ DecodeGetLocal(FunctionDecoder& f, ExprType* type)
if (!f.d().readVarU32(&localIndex))
return f.fail("unable to read get_local index");
if (localIndex >= f.fg().locals().length())
if (localIndex >= f.locals().length())
return f.fail("get_local index out of range");
*type = ToExprType(f.fg().locals()[localIndex]);
*type = ToExprType(f.locals()[localIndex]);
return true;
}
@ -343,10 +341,10 @@ DecodeSetLocal(FunctionDecoder& f, ExprType* type)
if (!f.d().readVarU32(&localIndex))
return f.fail("unable to read set_local index");
if (localIndex >= f.fg().locals().length())
if (localIndex >= f.locals().length())
return f.fail("set_local index out of range");
*type = ToExprType(f.fg().locals()[localIndex]);
*type = ToExprType(f.locals()[localIndex]);
ExprType rhsType;
if (!DecodeExpr(f, &rhsType))
@ -605,12 +603,12 @@ DecodeBrTable(FunctionDecoder& f, ExprType* type)
static bool
DecodeReturn(FunctionDecoder& f, ExprType* type)
{
if (f.ret() != ExprType::Void) {
if (f.sig().ret() != ExprType::Void) {
ExprType actual;
if (!DecodeExpr(f, &actual))
return false;
if (!CheckType(f, actual, f.ret()))
if (!CheckType(f, actual, f.sig().ret()))
return false;
}
@ -807,38 +805,38 @@ DecodeExpr(FunctionDecoder& f, ExprType* type)
DecodeConversionOperator(f, ValType::F64, ValType::I64, type);
case Expr::F64PromoteF32:
return DecodeConversionOperator(f, ValType::F64, ValType::F32, type);
case Expr::I32LoadMem:
case Expr::I32LoadMem8S:
case Expr::I32LoadMem8U:
case Expr::I32LoadMem16S:
case Expr::I32LoadMem16U:
case Expr::I32Load:
case Expr::I32Load8S:
case Expr::I32Load8U:
case Expr::I32Load16S:
case Expr::I32Load16U:
return DecodeLoad(f, ValType::I32, type);
case Expr::I64LoadMem:
case Expr::I64LoadMem8S:
case Expr::I64LoadMem8U:
case Expr::I64LoadMem16S:
case Expr::I64LoadMem16U:
case Expr::I64LoadMem32S:
case Expr::I64LoadMem32U:
case Expr::I64Load:
case Expr::I64Load8S:
case Expr::I64Load8U:
case Expr::I64Load16S:
case Expr::I64Load16U:
case Expr::I64Load32S:
case Expr::I64Load32U:
return f.fail("NYI: i64") &&
DecodeLoad(f, ValType::I64, type);
case Expr::F32LoadMem:
case Expr::F32Load:
return DecodeLoad(f, ValType::F32, type);
case Expr::F64LoadMem:
case Expr::F64Load:
return DecodeLoad(f, ValType::F64, type);
case Expr::I32StoreMem:
case Expr::I32StoreMem8:
case Expr::I32StoreMem16:
case Expr::I32Store:
case Expr::I32Store8:
case Expr::I32Store16:
return DecodeStore(f, ValType::I32, type);
case Expr::I64StoreMem:
case Expr::I64StoreMem8:
case Expr::I64StoreMem16:
case Expr::I64StoreMem32:
case Expr::I64Store:
case Expr::I64Store8:
case Expr::I64Store16:
case Expr::I64Store32:
return f.fail("NYI: i64") &&
DecodeStore(f, ValType::I64, type);
case Expr::F32StoreMem:
case Expr::F32Store:
return DecodeStore(f, ValType::F32, type);
case Expr::F64StoreMem:
case Expr::F64Store:
return DecodeStore(f, ValType::F64, type);
case Expr::Br:
return DecodeBr(f, type);
@ -849,6 +847,8 @@ DecodeExpr(FunctionDecoder& f, ExprType* type)
case Expr::Return:
return DecodeReturn(f, type);
default:
// Note: it's important not to remove this default since readExpr()
// can return Expr values for which there is no enumerator.
break;
}
@ -1240,15 +1240,23 @@ DecodeFunctionBody(JSContext* cx, Decoder& d, ModuleGenerator& mg, uint32_t func
{
int64_t before = PRMJ_Now();
uint32_t bodySize;
if (!d.readVarU32(&bodySize))
return Fail(cx, d, "expected number of function body bytes");
if (d.bytesRemain() < bodySize)
return Fail(cx, d, "function body length too big");
const uint8_t* bodyBegin = d.currentPosition();
const uint8_t* bodyEnd = bodyBegin + bodySize;
FunctionGenerator fg;
if (!mg.startFuncDef(d.currentOffset(), &fg))
return false;
const DeclaredSig& sig = mg.funcSig(funcIndex);
for (ValType type : sig.args()) {
if (!fg.addLocal(type))
return false;
}
ValTypeVector locals;
if (!locals.appendAll(mg.funcSig(funcIndex).args()))
return false;
uint32_t numVars;
if (!d.readVarU32(&numVars))
@ -1258,21 +1266,11 @@ DecodeFunctionBody(JSContext* cx, Decoder& d, ModuleGenerator& mg, uint32_t func
ValType type;
if (!DecodeValType(cx, d, &type))
return false;
if (!fg.addLocal(type))
if (!locals.append(type))
return false;
}
FunctionDecoder f(cx, d, mg, fg, funcIndex);
uint32_t numBytes;
if (!d.readVarU32(&numBytes))
return Fail(cx, d, "expected number of function body bytes");
if (d.bytesRemain() < numBytes)
return Fail(cx, d, "function body length too big");
const uint8_t* bodyBegin = d.currentPosition();
const uint8_t* bodyEnd = bodyBegin + numBytes;
FunctionDecoder f(cx, d, mg, fg, funcIndex, locals);
ExprType type = ExprType::Void;
@ -1281,17 +1279,16 @@ DecodeFunctionBody(JSContext* cx, Decoder& d, ModuleGenerator& mg, uint32_t func
return false;
}
if (!CheckType(f, type, f.sig().ret()))
return false;
if (d.currentPosition() != bodyEnd)
return Fail(cx, d, "function body length mismatch");
if (!CheckType(f, type, f.ret()))
if (!fg.bytecode().resize(bodySize))
return false;
uintptr_t bodyLength = bodyEnd - bodyBegin;
if (!fg.bytecode().resize(bodyLength))
return false;
memcpy(fg.bytecode().begin(), bodyBegin, bodyLength);
memcpy(fg.bytecode().begin(), bodyBegin, bodySize);
int64_t after = PRMJ_Now();
unsigned generateTime = (after - before) / PRMJ_USEC_PER_MSEC;
@ -1517,17 +1514,23 @@ ImportFunctions(JSContext* cx, HandleObject importObj, const ImportNameVector& i
}
bool
wasm::Eval(JSContext* cx, Handle<ArrayBufferObject*> code,
HandleObject importObj, MutableHandleObject exportObj)
wasm::Eval(JSContext* cx, Handle<TypedArrayObject*> code, HandleObject importObj,
MutableHandleObject exportObj)
{
MOZ_ASSERT(!code->isSharedMemory());
if (!CheckCompilerSupport(cx))
return false;
const uint8_t* bytes = code->dataPointer();
if (!TypedArrayObject::ensureHasBuffer(cx, code))
return false;
const uint8_t* bufferStart = code->bufferUnshared()->dataPointer();
const uint8_t* bytes = bufferStart + code->byteOffset();
uint32_t length = code->byteLength();
Vector<uint8_t> copy(cx);
if (code->hasInlineData()) {
if (code->bufferUnshared()->hasInlineData()) {
if (!copy.append(bytes, length))
return false;
bytes = copy.begin();
@ -1551,10 +1554,7 @@ wasm::Eval(JSContext* cx, Handle<ArrayBufferObject*> code,
if (!ImportFunctions(cx, importObj, importNames, &imports))
return false;
if (!moduleObj->module().dynamicallyLink(cx, moduleObj, heap, imports, *exportMap, exportObj))
return false;
return true;
return moduleObj->module().dynamicallyLink(cx, moduleObj, heap, imports, *exportMap, exportObj);
}
static bool
@ -1563,7 +1563,13 @@ InstantiateModule(JSContext* cx, unsigned argc, Value* vp)
MOZ_ASSERT(cx->runtime()->options().wasm());
CallArgs args = CallArgsFromVp(argc, vp);
if (!args.get(0).isObject() || !args.get(0).toObject().is<ArrayBufferObject>()) {
if (!args.get(0).isObject() || !args.get(0).toObject().is<TypedArrayObject>()) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_BUF_ARG);
return false;
}
Rooted<TypedArrayObject*> code(cx, &args[0].toObject().as<TypedArrayObject>());
if (code->isSharedMemory()) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_BUF_ARG);
return false;
}
@ -1577,8 +1583,6 @@ InstantiateModule(JSContext* cx, unsigned argc, Value* vp)
importObj = &args[1].toObject();
}
Rooted<ArrayBufferObject*> code(cx, &args[0].toObject().as<ArrayBufferObject>());
RootedObject exportObj(cx);
if (!Eval(cx, code, importObj, &exportObj))
return false;

View File

@ -26,7 +26,7 @@
namespace js {
class ArrayBufferObject;
class TypedArrayObject;
namespace wasm {
@ -49,7 +49,7 @@ static const uint64_t MappedSize = 2 * Uint32Range + PageSize;
// Compiles the given binary wasm module given the ArrayBufferObject
// and links the module's imports with the given import object.
bool
Eval(JSContext* cx, Handle<ArrayBufferObject*> code, HandleObject importObj,
Eval(JSContext* cx, Handle<TypedArrayObject*> code, HandleObject importObj,
MutableHandleObject exportObj);
} // namespace wasm

View File

@ -19,24 +19,18 @@
#ifndef wasm_binary_h
#define wasm_binary_h
#include "jsstr.h"
#include "mozilla/DebugOnly.h"
#include "asmjs/WasmTypes.h"
#include "builtin/SIMD.h"
namespace js {
class PropertyName;
namespace wasm {
// Module header constants
static const uint32_t MagicNumber = 0x6d736100; // "\0asm"
static const uint32_t EncodingVersion = 0xa; // will change while iterating toward release,
// change to 1 at release, and hopefully never
// change after that
using mozilla::DebugOnly;
static const uint32_t MagicNumber = 0x6d736100; // "\0asm"
static const uint32_t EncodingVersion = 0xa;
// Section ids:
static const char SignaturesId[] = "signatures";
static const char ImportTableId[] = "import_table";
static const char FunctionSignaturesId[] = "function_signatures";
@ -46,199 +40,234 @@ static const char ExportTableId[] = "export_table";
static const char FunctionBodiesId[] = "function_bodies";
static const char DataSegmentsId[] = "data_segments";
enum class Expr : uint16_t
enum class ValType
{
// Control opcodes
Nop = 0x00,
Block = 0x01,
Loop = 0x02,
If = 0x03,
IfElse = 0x04,
Select = 0x05,
Br = 0x06,
BrIf = 0x07,
BrTable = 0x08,
Return = 0x14,
Unreachable = 0x15,
// 0x00 is reserved for ExprType::Void in the binary encoding. See comment
// below about ExprType going away.
// Calls
Call = 0x12,
CallIndirect = 0x13,
CallImport = 0x1f,
I32 = 0x01,
I64 = 0x02,
F32 = 0x03,
F64 = 0x04,
// Constants and calls
I32Const = 0x0a,
I64Const = 0x0b,
F64Const = 0x0c,
F32Const = 0x0d,
GetLocal = 0x0e,
SetLocal = 0x0f,
// ------------------------------------------------------------------------
// The rest of these types are currently only emitted internally when
// compiling asm.js and are rejected by wasm validation.
// I32 opcodes
I32Add = 0x40,
I32Sub = 0x41,
I32Mul = 0x42,
I32DivS = 0x43,
I32DivU = 0x44,
I32RemS = 0x45,
I32RemU = 0x46,
I32Or = 0x48,
I32And = 0x47,
I32Xor = 0x49,
I32Shl = 0x4a,
I32ShrU = 0x4b,
I32ShrS = 0x4c,
I32Eq = 0x4d,
I32Ne = 0x4e,
I32LtS = 0x4f,
I32LeS = 0x50,
I32LtU = 0x51,
I32LeU = 0x52,
I32GtS = 0x53,
I32GeS = 0x54,
I32GtU = 0x55,
I32GeU = 0x56,
I32Clz = 0x57,
I32Ctz = 0x58,
I32Popcnt = 0x59,
I32x4,
F32x4,
B32x4,
// I64 opcodes
I64Add = 0x5b,
I64Sub = 0x5c,
I64Mul = 0x5d,
I64DivS = 0x5e,
I64DivU = 0x5f,
I64RemS = 0x60,
I64RemU = 0x61,
I64Or = 0x63,
I64And = 0x62,
I64Xor = 0x64,
I64Shl = 0x65,
I64ShrU = 0x66,
I64ShrS = 0x67,
I64Eq = 0x68,
I64Ne = 0x69,
I64LtS = 0x6a,
I64LeS = 0x6b,
I64LtU = 0x6c,
I64LeU = 0x6d,
I64GtS = 0x6e,
I64GeS = 0x6f,
I64GtU = 0x70,
I64GeU = 0x71,
I64Clz = 0x72,
I64Ctz = 0x73,
I64Popcnt = 0x74,
Limit
};
// F32 opcodes
F32Add = 0x75,
F32Sub = 0x76,
F32Mul = 0x77,
F32Div = 0x78,
F32Min = 0x79,
F32Max = 0x7a,
F32Abs = 0x7b,
F32Neg = 0x7c,
F32CopySign = 0x7d,
F32Ceil = 0x7e,
F32Floor = 0x7f,
F32Trunc = 0x80,
F32Nearest = 0x81,
F32Sqrt = 0x82,
F32Eq = 0x83,
F32Ne = 0x84,
F32Lt = 0x85,
F32Le = 0x86,
F32Gt = 0x87,
F32Ge = 0x88,
enum class Expr
{
// Control flow operators
Nop = 0x00,
Block = 0x01,
Loop = 0x02,
If = 0x03,
IfElse = 0x04,
Select = 0x05,
Br = 0x06,
BrIf = 0x07,
BrTable = 0x08,
Return = 0x14,
Unreachable = 0x15,
// F64 opcodes
F64Add = 0x89,
F64Sub = 0x8a,
F64Mul = 0x8b,
F64Div = 0x8c,
F64Min = 0x8d,
F64Max = 0x8e,
F64Abs = 0x8f,
F64Neg = 0x90,
F64CopySign = 0x91,
F64Ceil = 0x92,
F64Floor = 0x93,
F64Trunc = 0x94,
F64Nearest = 0x95,
F64Sqrt = 0x96,
F64Eq = 0x97,
F64Ne = 0x98,
F64Lt = 0x99,
F64Le = 0x9a,
F64Gt = 0x9b,
F64Ge = 0x9c,
// Basic operators
I32Const = 0x0a,
I64Const = 0x0b,
F64Const = 0x0c,
F32Const = 0x0d,
GetLocal = 0x0e,
SetLocal = 0x0f,
Call = 0x12,
CallIndirect = 0x13,
CallImport = 0x1f,
// Memory-related operators
I32Load8S = 0x20,
I32Load8U = 0x21,
I32Load16S = 0x22,
I32Load16U = 0x23,
I64Load8S = 0x24,
I64Load8U = 0x25,
I64Load16S = 0x26,
I64Load16U = 0x27,
I64Load32S = 0x28,
I64Load32U = 0x29,
I32Load = 0x2a,
I64Load = 0x2b,
F32Load = 0x2c,
F64Load = 0x2d,
I32Store8 = 0x2e,
I32Store16 = 0x2f,
I64Store8 = 0x30,
I64Store16 = 0x31,
I64Store32 = 0x32,
I32Store = 0x33,
I64Store = 0x34,
F32Store = 0x35,
F64Store = 0x36,
MemorySize = 0x3b,
GrowMemory = 0x39,
// i32 operators
I32Add = 0x40,
I32Sub = 0x41,
I32Mul = 0x42,
I32DivS = 0x43,
I32DivU = 0x44,
I32RemS = 0x45,
I32RemU = 0x46,
I32And = 0x47,
I32Or = 0x48,
I32Xor = 0x49,
I32Shl = 0x4a,
I32ShrU = 0x4b,
I32ShrS = 0x4c,
I32Eq = 0x4d,
I32Ne = 0x4e,
I32LtS = 0x4f,
I32LeS = 0x50,
I32LtU = 0x51,
I32LeU = 0x52,
I32GtS = 0x53,
I32GeS = 0x54,
I32GtU = 0x55,
I32GeU = 0x56,
I32Clz = 0x57,
I32Ctz = 0x58,
I32Popcnt = 0x59,
// i64 operators
I64Add = 0x5b,
I64Sub = 0x5c,
I64Mul = 0x5d,
I64DivS = 0x5e,
I64DivU = 0x5f,
I64RemS = 0x60,
I64RemU = 0x61,
I64And = 0x62,
I64Or = 0x63,
I64Xor = 0x64,
I64Shl = 0x65,
I64ShrU = 0x66,
I64ShrS = 0x67,
I64Eq = 0x68,
I64Ne = 0x69,
I64LtS = 0x6a,
I64LeS = 0x6b,
I64LtU = 0x6c,
I64LeU = 0x6d,
I64GtS = 0x6e,
I64GeS = 0x6f,
I64GtU = 0x70,
I64GeU = 0x71,
I64Clz = 0x72,
I64Ctz = 0x73,
I64Popcnt = 0x74,
// f32 opcodes
F32Add = 0x75,
F32Sub = 0x76,
F32Mul = 0x77,
F32Div = 0x78,
F32Min = 0x79,
F32Max = 0x7a,
F32Abs = 0x7b,
F32Neg = 0x7c,
F32CopySign = 0x7d,
F32Ceil = 0x7e,
F32Floor = 0x7f,
F32Trunc = 0x80,
F32Nearest = 0x81,
F32Sqrt = 0x82,
F32Eq = 0x83,
F32Ne = 0x84,
F32Lt = 0x85,
F32Le = 0x86,
F32Gt = 0x87,
F32Ge = 0x88,
// f64 opcodes
F64Add = 0x89,
F64Sub = 0x8a,
F64Mul = 0x8b,
F64Div = 0x8c,
F64Min = 0x8d,
F64Max = 0x8e,
F64Abs = 0x8f,
F64Neg = 0x90,
F64CopySign = 0x91,
F64Ceil = 0x92,
F64Floor = 0x93,
F64Trunc = 0x94,
F64Nearest = 0x95,
F64Sqrt = 0x96,
F64Eq = 0x97,
F64Ne = 0x98,
F64Lt = 0x99,
F64Le = 0x9a,
F64Gt = 0x9b,
F64Ge = 0x9c,
// Conversions
I32WrapI64 = 0xa1,
I64ExtendSI32 = 0xa6,
I64ExtendUI32 = 0xa7,
I32TruncSF32 = 0x9d,
I32TruncSF64 = 0x9e,
I32TruncUF32 = 0x9f,
I32TruncUF64 = 0xa0,
I64TruncSF32 = 0xa2,
I64TruncSF64 = 0xa3,
I64TruncUF32 = 0xa4,
I64TruncUF64 = 0xa5,
F32ConvertSI32 = 0xa8,
F32ConvertUI32 = 0xa9,
F64ConvertSI32 = 0xae,
F64ConvertUI32 = 0xaf,
F32ConvertSI64 = 0xaa,
F32ConvertUI64 = 0xab,
F64ConvertSI64 = 0xb0,
F64ConvertUI64 = 0xb1,
F32DemoteF64 = 0xac,
F64PromoteF32 = 0xb2,
I32ReinterpretF32 = 0xb4,
F32ReinterpretI32 = 0xad,
I64ReinterpretF64 = 0xb5,
F64ReinterpretI64 = 0xb3,
I32TruncSF32 = 0x9d,
I32TruncSF64 = 0x9e,
I32TruncUF32 = 0x9f,
I32TruncUF64 = 0xa0,
I32WrapI64 = 0xa1,
I64TruncSF32 = 0xa2,
I64TruncSF64 = 0xa3,
I64TruncUF32 = 0xa4,
I64TruncUF64 = 0xa5,
I64ExtendSI32 = 0xa6,
I64ExtendUI32 = 0xa7,
F32ConvertSI32 = 0xa8,
F32ConvertUI32 = 0xa9,
F32ConvertSI64 = 0xaa,
F32ConvertUI64 = 0xab,
F32DemoteF64 = 0xac,
F32ReinterpretI32 = 0xad,
F64ConvertSI32 = 0xae,
F64ConvertUI32 = 0xaf,
F64ConvertSI64 = 0xb0,
F64ConvertUI64 = 0xb1,
F64PromoteF32 = 0xb2,
F64ReinterpretI64 = 0xb3,
I32ReinterpretF32 = 0xb4,
I64ReinterpretF64 = 0xb5,
// Load/store operations
I32LoadMem8S = 0x20,
I32LoadMem8U = 0x21,
I32LoadMem16S = 0x22,
I32LoadMem16U = 0x23,
I32LoadMem = 0x2a,
I64LoadMem8S = 0x24,
I64LoadMem8U = 0x25,
I64LoadMem16S = 0x26,
I64LoadMem16U = 0x27,
I64LoadMem32S = 0x28,
I64LoadMem32U = 0x29,
I64LoadMem = 0x2b,
F32LoadMem = 0x2c,
F64LoadMem = 0x2d,
I32StoreMem8 = 0x2e,
I32StoreMem16 = 0x2f,
I64StoreMem8 = 0x30,
I64StoreMem16 = 0x31,
I64StoreMem32 = 0x32,
I32StoreMem = 0x33,
I64StoreMem = 0x34,
F32StoreMem = 0x35,
F64StoreMem = 0x36,
// Special operators
MemorySize = 0x3b,
GrowMemory = 0x39,
// asm.js specific
Id = 0xc0, // Encodings from here down are specific to baldr.
// ------------------------------------------------------------------------
// The rest of these operators are currently only emitted internally when
// compiling asm.js and are rejected by wasm validation.
// asm.js-specific operators
Id = 0xc0,
LoadGlobal,
StoreGlobal,
I32Min,
I32Max,
I32Not,
I32Neg,
I32BitNot,
I32Abs,
F32StoreF64,
F64StoreF32,
F64Mod,
F64Sin,
F64Cos,
F64Tan,
F64Asin,
F64Acos,
F64Atan,
F64Exp,
F64Log,
F64Pow,
F64Atan2,
// Atomics
AtomicsFence,
@ -263,7 +292,6 @@ enum class Expr : uint16_t
I32x4greaterThanU,
I32x4greaterThanOrEqualU,
I32x4fromFloat32x4U,
#define _(OP) SIMD_OPCODE(F32x4, OP)
FORALL_FLOAT32X4_ASMJS_OP(_)
F32x4Constructor,
@ -276,40 +304,37 @@ enum class Expr : uint16_t
#undef _
#undef OPCODE
// I32 asm.js opcodes
I32Not,
I32Neg,
I32BitNot,
I32Abs,
Limit
};
// F32 asm.js opcodes
F32StoreMemF64,
// The ExprType enum represents the type of a WebAssembly expression or return
// value and may either be a value type or void. Soon, expression types will be
// generalized to a list of ValType and this enum will go away, replaced,
// wherever it is used, by a varU32 + list of ValType.
// F64 asm.js opcodes
F64Mod,
F64Sin,
F64Cos,
F64Tan,
F64Asin,
F64Acos,
F64Atan,
F64Exp,
F64Log,
F64Pow,
F64Atan2,
F64StoreMemF32,
enum class ExprType
{
Void = 0x00,
I32 = uint8_t(ValType::I32),
I64 = uint8_t(ValType::I64),
F32 = uint8_t(ValType::F32),
F64 = uint8_t(ValType::F64),
I32x4 = uint8_t(ValType::I32x4),
F32x4 = uint8_t(ValType::F32x4),
B32x4 = uint8_t(ValType::B32x4),
Limit
};
typedef int32_t I32x4[4];
typedef float F32x4[4];
typedef Vector<uint8_t, 0, SystemAllocPolicy> Bytecode;
typedef UniquePtr<Bytecode> UniqueBytecode;
// The Encoder class appends bytes to the Bytecode object it is given during
// construction. The client is responsible for the Bytecode's lifetime and must
// keep the Bytecode alive as long as the Encoder is used.
class Encoder
{
Bytecode& bytecode_;
@ -399,11 +424,11 @@ class Encoder
MOZ_WARN_UNUSED_RESULT bool writeFixedF64(double d) {
return write<double>(d);
}
MOZ_WARN_UNUSED_RESULT bool writeFixedI32x4(const Val::I32x4& i32x4) {
return write<Val::I32x4>(i32x4);
MOZ_WARN_UNUSED_RESULT bool writeFixedI32x4(const I32x4& i32x4) {
return write<I32x4>(i32x4);
}
MOZ_WARN_UNUSED_RESULT bool writeFixedF32x4(const Val::F32x4& f32x4) {
return write<Val::F32x4>(f32x4);
MOZ_WARN_UNUSED_RESULT bool writeFixedF32x4(const F32x4& f32x4) {
return write<F32x4>(f32x4);
}
// Variable-length encodings that all use LEB128.
@ -494,6 +519,10 @@ class Encoder
}
};
// The Decoder class decodes the bytes in the range it is given during
// construction. The client is responsible for keeping the byte range alive as
// long as the Decoder is used.
class Decoder
{
const uint8_t* const beg_;
@ -607,11 +636,11 @@ class Decoder
MOZ_WARN_UNUSED_RESULT bool readFixedF64(double* d = nullptr) {
return read<double>(d);
}
MOZ_WARN_UNUSED_RESULT bool readFixedI32x4(Val::I32x4* i32x4 = nullptr) {
return read<Val::I32x4>(i32x4);
MOZ_WARN_UNUSED_RESULT bool readFixedI32x4(I32x4* i32x4 = nullptr) {
return read<I32x4>(i32x4);
}
MOZ_WARN_UNUSED_RESULT bool readFixedF32x4(Val::F32x4* f32x4 = nullptr) {
return read<Val::F32x4>(f32x4);
MOZ_WARN_UNUSED_RESULT bool readFixedF32x4(F32x4* f32x4 = nullptr) {
return read<F32x4>(f32x4);
}
// Variable-length encodings that all use LEB128.
@ -625,10 +654,10 @@ class Decoder
MOZ_WARN_UNUSED_RESULT bool readExpr(Expr* expr = nullptr) {
return readEnum(expr);
}
MOZ_WARN_UNUSED_RESULT bool readValType(ValType* type = nullptr) {
MOZ_WARN_UNUSED_RESULT bool readValType(ValType* type) {
return readEnum(type);
}
MOZ_WARN_UNUSED_RESULT bool readExprType(ExprType* type = nullptr) {
MOZ_WARN_UNUSED_RESULT bool readExprType(ExprType* type) {
return readEnum(type);
}
@ -751,6 +780,9 @@ class Decoder
cur_ = before;
return ret;
}
ValType uncheckedReadValType() {
return uncheckedReadEnum<ValType>();
}
// Temporary encoding forms which should be removed as part of the
// conversion to wasm:
@ -766,66 +798,6 @@ class Decoder
}
};
// The FuncBytecode class contains the intermediate representation of a
// parsed/decoded and validated asm.js/WebAssembly function. The FuncBytecode
// lives only until it is fully compiled.
class FuncBytecode
{
// Function metadata
const DeclaredSig& sig_;
ValTypeVector locals_;
uint32_t lineOrBytecode_;
Uint32Vector callSiteLineNums_;
// Compilation bookkeeping
uint32_t index_;
unsigned generateTime_;
UniqueBytecode bytecode_;
public:
FuncBytecode(uint32_t index,
const DeclaredSig& sig,
UniqueBytecode bytecode,
ValTypeVector&& locals,
uint32_t lineOrBytecode,
Uint32Vector&& callSiteLineNums,
unsigned generateTime)
: sig_(sig),
locals_(Move(locals)),
lineOrBytecode_(lineOrBytecode),
callSiteLineNums_(Move(callSiteLineNums)),
index_(index),
generateTime_(generateTime),
bytecode_(Move(bytecode))
{}
UniqueBytecode recycleBytecode() { return Move(bytecode_); }
uint32_t lineOrBytecode() const { return lineOrBytecode_; }
const Uint32Vector& callSiteLineNums() const { return callSiteLineNums_; }
uint32_t index() const { return index_; }
const DeclaredSig& sig() const { return sig_; }
const Bytecode& bytecode() const { return *bytecode_; }
size_t numLocals() const { return locals_.length(); }
ValType localType(size_t i) const { return locals_[i]; }
unsigned generateTime() const { return generateTime_; }
};
typedef UniquePtr<FuncBytecode> UniqueFuncBytecode;
// Module generator limits
static const unsigned MaxSigs = 4 * 1024;
static const unsigned MaxFuncs = 512 * 1024;
static const unsigned MaxImports = 4 * 1024;
static const unsigned MaxExports = 4 * 1024;
static const unsigned MaxTableElems = 128 * 1024;
static const unsigned MaxArgsPerFunc = 4 * 1024;
static const unsigned MaxBrTableElems = 4 * 1024;
} // namespace wasm
} // namespace js

View File

@ -807,7 +807,6 @@ ModuleGenerator::finishFuncDef(uint32_t funcIndex, unsigned generateTime, Functi
js::MakeUnique<FuncBytecode>(funcIndex,
funcSig(funcIndex),
Move(fg->bytecode_),
Move(fg->locals_),
fg->lineOrBytecode_,
Move(fg->callSiteLineNums_),
generateTime);

View File

@ -295,7 +295,6 @@ class MOZ_STACK_CLASS FunctionGenerator
// FuncBytecode in ModuleGenerator::finishFunc().
UniqueBytecode bytecode_;
Uint32Vector callSiteLineNums_;
ValTypeVector locals_;
uint32_t lineOrBytecode_;
@ -310,12 +309,6 @@ class MOZ_STACK_CLASS FunctionGenerator
bool addCallSiteLineNum(uint32_t lineno) {
return callSiteLineNums_.append(lineno);
}
bool addLocal(ValType v) {
return locals_.append(v);
}
const ValTypeVector& locals() const {
return locals_;
}
};
} // namespace wasm

View File

@ -39,8 +39,9 @@ class FunctionCompiler
typedef Vector<BlockVector, 0, SystemAllocPolicy> BlocksVector;
ModuleGeneratorThreadView& mg_;
Decoder& decoder_;
const FuncBytecode& func_;
Decoder decoder_;
const ValTypeVector& locals_;
size_t lastReadCallSite_;
TempAllocator& alloc_;
@ -57,11 +58,16 @@ class FunctionCompiler
FuncCompileResults& compileResults_;
public:
FunctionCompiler(ModuleGeneratorThreadView& mg, const FuncBytecode& func, MIRGenerator& mirGen,
FunctionCompiler(ModuleGeneratorThreadView& mg,
Decoder& decoder,
const FuncBytecode& func,
const ValTypeVector& locals,
MIRGenerator& mirGen,
FuncCompileResults& compileResults)
: mg_(mg),
decoder_(decoder),
func_(func),
decoder_(func.bytecode()),
locals_(locals),
lastReadCallSite_(0),
alloc_(mirGen.alloc()),
graph_(mirGen.graph()),
@ -97,9 +103,9 @@ class FunctionCompiler
return false;
}
for (size_t i = args.length(); i < func_.numLocals(); i++) {
for (size_t i = args.length(); i < locals_.length(); i++) {
MInstruction* ins = nullptr;
switch (func_.localType(i)) {
switch (locals_[i]) {
case ValType::I32:
ins = MConstant::NewAsmJS(alloc(), Int32Value(0), MIRType_Int32);
break;
@ -164,7 +170,7 @@ class FunctionCompiler
return curBlock_->getSlot(info().localSlot(slot));
}
ValType localType(unsigned slot) const { return func_.localType(slot); }
ValType localType(unsigned slot) const { return locals_[slot]; }
/***************************** Code generation (after local scope setup) */
@ -1256,12 +1262,12 @@ class FunctionCompiler
Expr peakExpr() { return decoder_.uncheckedPeekExpr(); }
SimdConstant readI32X4() {
Val::I32x4 i32x4;
I32x4 i32x4;
JS_ALWAYS_TRUE(decoder_.readFixedI32x4(&i32x4));
return SimdConstant::CreateX4(i32x4);
}
SimdConstant readF32X4() {
Val::F32x4 f32x4;
F32x4 f32x4;
JS_ALWAYS_TRUE(decoder_.readFixedF32x4(&f32x4));
return SimdConstant::CreateX4(f32x4);
}
@ -2763,21 +2769,21 @@ EmitExpr(FunctionCompiler& f, MDefinition** def)
return EmitBitwise<MUrsh>(f, ValType::I32, def);
case Expr::I32BitNot:
return EmitBitwiseNot(f, def);
case Expr::I32LoadMem8S:
case Expr::I32Load8S:
return EmitLoad(f, Scalar::Int8, def);
case Expr::I32LoadMem8U:
case Expr::I32Load8U:
return EmitLoad(f, Scalar::Uint8, def);
case Expr::I32LoadMem16S:
case Expr::I32Load16S:
return EmitLoad(f, Scalar::Int16, def);
case Expr::I32LoadMem16U:
case Expr::I32Load16U:
return EmitLoad(f, Scalar::Uint16, def);
case Expr::I32LoadMem:
case Expr::I32Load:
return EmitLoad(f, Scalar::Int32, def);
case Expr::I32StoreMem8:
case Expr::I32Store8:
return EmitStore(f, Scalar::Int8, def);
case Expr::I32StoreMem16:
case Expr::I32Store16:
return EmitStore(f, Scalar::Int16, def);
case Expr::I32StoreMem:
case Expr::I32Store:
return EmitStore(f, Scalar::Int32, def);
case Expr::I32Eq:
case Expr::I32Ne:
@ -2880,11 +2886,11 @@ EmitExpr(FunctionCompiler& f, MDefinition** def)
return EmitUnary<MToFloat32>(f, def);
case Expr::F32ConvertUI32:
return EmitUnary<MAsmJSUnsignedToFloat32>(f, def);
case Expr::F32LoadMem:
case Expr::F32Load:
return EmitLoad(f, Scalar::Float32, def);
case Expr::F32StoreMem:
case Expr::F32Store:
return EmitStore(f, Scalar::Float32, def);
case Expr::F32StoreMemF64:
case Expr::F32StoreF64:
return EmitStoreWithCoercion(f, Scalar::Float32, Scalar::Float64, def);
// F64
@ -2929,11 +2935,11 @@ EmitExpr(FunctionCompiler& f, MDefinition** def)
return EmitUnary<MToDouble>(f, def);
case Expr::F64ConvertUI32:
return EmitUnary<MAsmJSUnsignedToDouble>(f, def);
case Expr::F64LoadMem:
case Expr::F64Load:
return EmitLoad(f, Scalar::Float64, def);
case Expr::F64StoreMem:
case Expr::F64Store:
return EmitStore(f, Scalar::Float64, def);
case Expr::F64StoreMemF32:
case Expr::F64StoreF32:
return EmitStoreWithCoercion(f, Scalar::Float64, Scalar::Float32, def);
// SIMD
@ -3012,17 +3018,17 @@ EmitExpr(FunctionCompiler& f, MDefinition** def)
case Expr::F64ReinterpretI64:
case Expr::I32ReinterpretF32:
case Expr::F32ReinterpretI32:
case Expr::I64LoadMem8S:
case Expr::I64LoadMem16S:
case Expr::I64LoadMem32S:
case Expr::I64LoadMem8U:
case Expr::I64LoadMem16U:
case Expr::I64LoadMem32U:
case Expr::I64LoadMem:
case Expr::I64StoreMem8:
case Expr::I64StoreMem16:
case Expr::I64StoreMem32:
case Expr::I64StoreMem:
case Expr::I64Load8S:
case Expr::I64Load16S:
case Expr::I64Load32S:
case Expr::I64Load8U:
case Expr::I64Load16U:
case Expr::I64Load32U:
case Expr::I64Load:
case Expr::I64Store8:
case Expr::I64Store16:
case Expr::I64Store32:
case Expr::I64Store:
case Expr::I64Clz:
case Expr::I64Ctz:
case Expr::I64Popcnt:
@ -3045,11 +3051,26 @@ wasm::IonCompileFunction(IonCompileTask* task)
const FuncBytecode& func = task->func();
FuncCompileResults& results = task->results();
JitContext jitContext(CompileRuntime::get(task->runtime()), &results.alloc());
// Read in the variable types to build the local types vector.
Decoder d(func.bytecode());
ValTypeVector locals;
if (!locals.appendAll(func.sig().args()))
return false;
uint32_t numVars = d.uncheckedReadVarU32();
for (uint32_t i = 0; i < numVars; i++) {
if (!locals.append(d.uncheckedReadValType()))
return false;
}
// Set up for Ion compilation.
JitContext jitContext(CompileRuntime::get(task->runtime()), &results.alloc());
const JitCompileOptions options;
MIRGraph graph(&results.alloc());
CompileInfo compileInfo(func.numLocals());
CompileInfo compileInfo(locals.length());
MIRGenerator mir(nullptr, options, &results.alloc(), &graph, &compileInfo,
IonOptimizations.get(OptimizationLevel::AsmJS));
mir.initUsesSignalHandlersForAsmJSOOB(task->mg().args().useSignalHandlersForOOB);
@ -3057,7 +3078,7 @@ wasm::IonCompileFunction(IonCompileTask* task)
// Build MIR graph
{
FunctionCompiler f(task->mg(), func, mir, results);
FunctionCompiler f(task->mg(), d, func, locals, mir, results);
if (!f.init())
return false;

View File

@ -31,6 +31,50 @@ typedef Vector<jit::MIRType, 8, SystemAllocPolicy> MIRTypeVector;
typedef jit::ABIArgIter<MIRTypeVector> ABIArgMIRTypeIter;
typedef jit::ABIArgIter<ValTypeVector> ABIArgValTypeIter;
// The FuncBytecode class contains the intermediate representation of a
// parsed/decoded and validated asm.js/WebAssembly function. The FuncBytecode
// lives only until it is fully compiled.
class FuncBytecode
{
// Function metadata
const DeclaredSig& sig_;
uint32_t lineOrBytecode_;
Uint32Vector callSiteLineNums_;
// Compilation bookkeeping
uint32_t index_;
unsigned generateTime_;
UniqueBytecode bytecode_;
public:
FuncBytecode(uint32_t index,
const DeclaredSig& sig,
UniqueBytecode bytecode,
uint32_t lineOrBytecode,
Uint32Vector&& callSiteLineNums,
unsigned generateTime)
: sig_(sig),
lineOrBytecode_(lineOrBytecode),
callSiteLineNums_(Move(callSiteLineNums)),
index_(index),
generateTime_(generateTime),
bytecode_(Move(bytecode))
{}
UniqueBytecode recycleBytecode() { return Move(bytecode_); }
uint32_t lineOrBytecode() const { return lineOrBytecode_; }
const Uint32Vector& callSiteLineNums() const { return callSiteLineNums_; }
uint32_t index() const { return index_; }
const DeclaredSig& sig() const { return sig_; }
const Bytecode& bytecode() const { return *bytecode_; }
unsigned generateTime() const { return generateTime_; }
};
typedef UniquePtr<FuncBytecode> UniqueFuncBytecode;
// The FuncCompileResults contains the results of compiling a single function
// body, ready to be merged into the whole-module MacroAssembler.
class FuncCompileResults

View File

@ -1457,7 +1457,7 @@ WasmTokenStream::next()
if (consume(MOZ_UTF16("lt")))
return WasmToken(WasmToken::ComparisonOpcode, Expr::F32Lt, begin, cur_);
if (consume(MOZ_UTF16("load")))
return WasmToken(WasmToken::Load, Expr::F32LoadMem, begin, cur_);
return WasmToken(WasmToken::Load, Expr::F32Load, begin, cur_);
break;
case 'm':
if (consume(MOZ_UTF16("max")))
@ -1486,7 +1486,7 @@ WasmTokenStream::next()
if (consume(MOZ_UTF16("sub")))
return WasmToken(WasmToken::BinaryOpcode, Expr::F32Sub, begin, cur_);
if (consume(MOZ_UTF16("store")))
return WasmToken(WasmToken::Store, Expr::F32StoreMem, begin, cur_);
return WasmToken(WasmToken::Store, Expr::F32Store, begin, cur_);
break;
case 't':
if (consume(MOZ_UTF16("trunc")))
@ -1544,7 +1544,7 @@ WasmTokenStream::next()
if (consume(MOZ_UTF16("lt")))
return WasmToken(WasmToken::ComparisonOpcode, Expr::F64Lt, begin, cur_);
if (consume(MOZ_UTF16("load")))
return WasmToken(WasmToken::Load, Expr::F64LoadMem, begin, cur_);
return WasmToken(WasmToken::Load, Expr::F64Load, begin, cur_);
break;
case 'm':
if (consume(MOZ_UTF16("max")))
@ -1573,7 +1573,7 @@ WasmTokenStream::next()
if (consume(MOZ_UTF16("sub")))
return WasmToken(WasmToken::BinaryOpcode, Expr::F64Sub, begin, cur_);
if (consume(MOZ_UTF16("store")))
return WasmToken(WasmToken::Store, Expr::F64StoreMem, begin, cur_);
return WasmToken(WasmToken::Store, Expr::F64Store, begin, cur_);
break;
case 't':
if (consume(MOZ_UTF16("trunc")))
@ -1640,15 +1640,15 @@ WasmTokenStream::next()
return WasmToken(WasmToken::ComparisonOpcode, Expr::I32LtU, begin, cur_);
if (consume(MOZ_UTF16("load"))) {
if (IsWasmSpace(*cur_))
return WasmToken(WasmToken::Load, Expr::I32LoadMem, begin, cur_);
return WasmToken(WasmToken::Load, Expr::I32Load, begin, cur_);
if (consume(MOZ_UTF16("8_s")))
return WasmToken(WasmToken::Load, Expr::I32LoadMem8S, begin, cur_);
return WasmToken(WasmToken::Load, Expr::I32Load8S, begin, cur_);
if (consume(MOZ_UTF16("8_u")))
return WasmToken(WasmToken::Load, Expr::I32LoadMem8U, begin, cur_);
return WasmToken(WasmToken::Load, Expr::I32Load8U, begin, cur_);
if (consume(MOZ_UTF16("16_s")))
return WasmToken(WasmToken::Load, Expr::I32LoadMem16S, begin, cur_);
return WasmToken(WasmToken::Load, Expr::I32Load16S, begin, cur_);
if (consume(MOZ_UTF16("16_u")))
return WasmToken(WasmToken::Load, Expr::I32LoadMem16U, begin, cur_);
return WasmToken(WasmToken::Load, Expr::I32Load16U, begin, cur_);
break;
}
break;
@ -1688,11 +1688,11 @@ WasmTokenStream::next()
return WasmToken(WasmToken::BinaryOpcode, Expr::I32ShrU, begin, cur_);
if (consume(MOZ_UTF16("store"))) {
if (IsWasmSpace(*cur_))
return WasmToken(WasmToken::Store, Expr::I32StoreMem, begin, cur_);
return WasmToken(WasmToken::Store, Expr::I32Store, begin, cur_);
if (consume(MOZ_UTF16("8")))
return WasmToken(WasmToken::Store, Expr::I32StoreMem8, begin, cur_);
return WasmToken(WasmToken::Store, Expr::I32Store8, begin, cur_);
if (consume(MOZ_UTF16("16")))
return WasmToken(WasmToken::Store, Expr::I32StoreMem16, begin, cur_);
return WasmToken(WasmToken::Store, Expr::I32Store16, begin, cur_);
break;
}
break;
@ -1778,19 +1778,19 @@ WasmTokenStream::next()
return WasmToken(WasmToken::ComparisonOpcode, Expr::I64LtU, begin, cur_);
if (consume(MOZ_UTF16("load"))) {
if (IsWasmSpace(*cur_))
return WasmToken(WasmToken::Load, Expr::I64LoadMem, begin, cur_);
return WasmToken(WasmToken::Load, Expr::I64Load, begin, cur_);
if (consume(MOZ_UTF16("8_s")))
return WasmToken(WasmToken::Load, Expr::I64LoadMem8S, begin, cur_);
return WasmToken(WasmToken::Load, Expr::I64Load8S, begin, cur_);
if (consume(MOZ_UTF16("8_u")))
return WasmToken(WasmToken::Load, Expr::I64LoadMem8U, begin, cur_);
return WasmToken(WasmToken::Load, Expr::I64Load8U, begin, cur_);
if (consume(MOZ_UTF16("16_s")))
return WasmToken(WasmToken::Load, Expr::I64LoadMem16S, begin, cur_);
return WasmToken(WasmToken::Load, Expr::I64Load16S, begin, cur_);
if (consume(MOZ_UTF16("16_u")))
return WasmToken(WasmToken::Load, Expr::I64LoadMem16U, begin, cur_);
return WasmToken(WasmToken::Load, Expr::I64Load16U, begin, cur_);
if (consume(MOZ_UTF16("32_s")))
return WasmToken(WasmToken::Load, Expr::I64LoadMem32S, begin, cur_);
return WasmToken(WasmToken::Load, Expr::I64Load32S, begin, cur_);
if (consume(MOZ_UTF16("32_u")))
return WasmToken(WasmToken::Load, Expr::I64LoadMem32U, begin, cur_);
return WasmToken(WasmToken::Load, Expr::I64Load32U, begin, cur_);
break;
}
break;
@ -1830,13 +1830,13 @@ WasmTokenStream::next()
return WasmToken(WasmToken::BinaryOpcode, Expr::I64ShrU, begin, cur_);
if (consume(MOZ_UTF16("store"))) {
if (IsWasmSpace(*cur_))
return WasmToken(WasmToken::Store, Expr::I64StoreMem, begin, cur_);
return WasmToken(WasmToken::Store, Expr::I64Store, begin, cur_);
if (consume(MOZ_UTF16("8")))
return WasmToken(WasmToken::Store, Expr::I64StoreMem8, begin, cur_);
return WasmToken(WasmToken::Store, Expr::I64Store8, begin, cur_);
if (consume(MOZ_UTF16("16")))
return WasmToken(WasmToken::Store, Expr::I64StoreMem16, begin, cur_);
return WasmToken(WasmToken::Store, Expr::I64Store16, begin, cur_);
if (consume(MOZ_UTF16("32")))
return WasmToken(WasmToken::Store, Expr::I64StoreMem32, begin, cur_);
return WasmToken(WasmToken::Store, Expr::I64Store32, begin, cur_);
break;
}
break;
@ -2540,26 +2540,26 @@ ParseLoad(WasmParseContext& c, Expr expr)
if (align == 0) {
switch (expr) {
case Expr::I32LoadMem8S:
case Expr::I32LoadMem8U:
case Expr::I64LoadMem8S:
case Expr::I64LoadMem8U:
case Expr::I32Load8S:
case Expr::I32Load8U:
case Expr::I64Load8S:
case Expr::I64Load8U:
align = 1;
break;
case Expr::I32LoadMem16S:
case Expr::I32LoadMem16U:
case Expr::I64LoadMem16S:
case Expr::I64LoadMem16U:
case Expr::I32Load16S:
case Expr::I32Load16U:
case Expr::I64Load16S:
case Expr::I64Load16U:
align = 2;
break;
case Expr::I32LoadMem:
case Expr::F32LoadMem:
case Expr::I64LoadMem32S:
case Expr::I64LoadMem32U:
case Expr::I32Load:
case Expr::F32Load:
case Expr::I64Load32S:
case Expr::I64Load32U:
align = 4;
break;
case Expr::I64LoadMem:
case Expr::F64LoadMem:
case Expr::I64Load:
case Expr::F64Load:
align = 8;
break;
default:
@ -2581,21 +2581,21 @@ ParseStore(WasmParseContext& c, Expr expr)
if (align == 0) {
switch (expr) {
case Expr::I32StoreMem8:
case Expr::I64StoreMem8:
case Expr::I32Store8:
case Expr::I64Store8:
align = 1;
break;
case Expr::I32StoreMem16:
case Expr::I64StoreMem16:
case Expr::I32Store16:
case Expr::I64Store16:
align = 2;
break;
case Expr::I32StoreMem:
case Expr::F32StoreMem:
case Expr::I64StoreMem32:
case Expr::I32Store:
case Expr::F32Store:
case Expr::I64Store32:
align = 4;
break;
case Expr::I64StoreMem:
case Expr::F64StoreMem:
case Expr::I64Store:
case Expr::F64Store:
align = 8;
break;
default:
@ -3919,6 +3919,12 @@ EncodeFunctionTable(Encoder& e, WasmAstModule& module)
static bool
EncodeFunctionBody(Encoder& e, WasmAstFunc& func)
{
size_t bodySizeAt;
if (!e.writePatchableVarU32(&bodySizeAt))
return false;
size_t beforeBody = e.currentOffset();
if (!e.writeVarU32(func.vars().length()))
return false;
@ -3927,12 +3933,6 @@ EncodeFunctionBody(Encoder& e, WasmAstFunc& func)
return false;
}
size_t bodySizeAt;
if (!e.writePatchableVarU32(&bodySizeAt))
return false;
size_t beforeBody = e.currentOffset();
for (WasmAstExpr* expr : func.body()) {
if (!EncodeExpr(e, *expr))
return false;

View File

@ -19,13 +19,13 @@
#ifndef wasm_types_h
#define wasm_types_h
#include "mozilla/DebugOnly.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/Move.h"
#include "NamespaceImports.h"
#include "asmjs/WasmBinary.h"
#include "ds/LifoAlloc.h"
#include "jit/IonTypes.h"
#include "js/UniquePtr.h"
@ -40,37 +40,50 @@ namespace wasm {
using mozilla::EnumeratedArray;
using mozilla::Move;
using mozilla::DebugOnly;
using mozilla::MallocSizeOf;
typedef Vector<uint32_t, 0, SystemAllocPolicy> Uint32Vector;
// The ValType enum represents the WebAssembly "value type", which are used to
// specify the type of locals and parameters.
// FIXME: uint16_t would make more sense for the underlying storage class, but
// causes miscompilations in GCC (fixed in 4.8.5 and 4.9.3).
enum class ValType
{
I32,
I64,
F32,
F64,
I32x4,
F32x4,
B32x4,
Limit
};
typedef Vector<ValType, 8, SystemAllocPolicy> ValTypeVector;
// ValType/ExprType utilities
static inline bool
IsVoid(ExprType et)
{
return et == ExprType::Void;
}
static inline ValType
NonVoidToValType(ExprType et)
{
MOZ_ASSERT(!IsVoid(et));
return ValType(et);
}
static inline ExprType
ToExprType(ValType vt)
{
return ExprType(vt);
}
static inline bool
IsSimdType(ValType vt)
{
return vt == ValType::I32x4 || vt == ValType::F32x4 || vt == ValType::B32x4;
}
static inline bool
IsSimdType(ExprType et)
{
return IsVoid(et) ? false : IsSimdType(ValType(et));
}
static inline bool
IsSimdBoolType(ValType vt)
{
return vt == ValType::B32x4;
}
static inline jit::MIRType
ToMIRType(ValType vt)
{
@ -87,6 +100,35 @@ ToMIRType(ValType vt)
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("bad type");
}
static inline jit::MIRType
ToMIRType(ExprType et)
{
return IsVoid(et) ? jit::MIRType_None : ToMIRType(ValType(et));
}
static inline const char*
ToCString(ExprType type)
{
switch (type) {
case ExprType::Void: return "void";
case ExprType::I32: return "i32";
case ExprType::I64: return "i64";
case ExprType::F32: return "f32";
case ExprType::F64: return "f64";
case ExprType::I32x4: return "i32x4";
case ExprType::F32x4: return "f32x4";
case ExprType::B32x4: return "b32x4";
case ExprType::Limit:;
}
MOZ_CRASH("bad expression type");
}
static inline const char*
ToCString(ValType type)
{
return ToCString(ToExprType(type));
}
// The Val class represents a single WebAssembly value of a given value type,
// mostly for the purpose of numeric literals and initializers. A Val does not
// directly map to a JS value since there is not (currently) a precise
@ -96,11 +138,6 @@ ToMIRType(ValType vt)
class Val
{
public:
typedef int32_t I32x4[4];
typedef float F32x4[4];
private:
ValType type_;
union {
uint32_t i32_;
@ -139,86 +176,6 @@ class Val
const F32x4& f32x4() const { MOZ_ASSERT(type_ == ValType::F32x4); return u.f32x4_; }
};
// The ExprType enum represents the type of a WebAssembly expression or return
// value and may either be a value type or void. A future WebAssembly extension
// may generalize expression types to instead be a list of value types (with
// void represented by the empty list). For now it's easier to have a flat enum
// and be explicit about conversions to/from value types.
enum class ExprType : uint16_t
{
I32 = uint8_t(ValType::I32),
I64 = uint8_t(ValType::I64),
F32 = uint8_t(ValType::F32),
F64 = uint8_t(ValType::F64),
I32x4 = uint8_t(ValType::I32x4),
F32x4 = uint8_t(ValType::F32x4),
B32x4 = uint8_t(ValType::B32x4),
Void,
Limit
};
static inline bool
IsVoid(ExprType et)
{
return et == ExprType::Void;
}
static inline ValType
NonVoidToValType(ExprType et)
{
MOZ_ASSERT(!IsVoid(et));
return ValType(et);
}
static inline ExprType
ToExprType(ValType vt)
{
return ExprType(vt);
}
static inline bool
IsSimdType(ExprType et)
{
return IsVoid(et) ? false : IsSimdType(ValType(et));
}
static inline bool
IsSimdBoolType(ValType vt)
{
return vt == ValType::B32x4;
}
static inline jit::MIRType
ToMIRType(ExprType et)
{
return IsVoid(et) ? jit::MIRType_None : ToMIRType(ValType(et));
}
static inline const char*
ToCString(ExprType type)
{
switch (type) {
case ExprType::Void: return "void";
case ExprType::I32: return "i32";
case ExprType::I64: return "i64";
case ExprType::F32: return "f32";
case ExprType::F64: return "f64";
case ExprType::I32x4: return "i32x4";
case ExprType::F32x4: return "f32x4";
case ExprType::B32x4: return "b32x4";
case ExprType::Limit:;
}
MOZ_CRASH("bad expression type");
}
static inline const char*
ToCString(ValType type)
{
return ToCString(ToExprType(type));
}
// The Sig class represents a WebAssembly function signature which takes a list
// of value types and returns an expression type. The engine uses two in-memory
// representations of the argument Vector's memory (when elements do not fit
@ -632,10 +589,18 @@ enum ModuleKind
// Constants:
static const unsigned ActivationGlobalDataOffset = 0;
static const unsigned HeapGlobalDataOffset = ActivationGlobalDataOffset + sizeof(void*);
static const unsigned NaN64GlobalDataOffset = HeapGlobalDataOffset + sizeof(void*);
static const unsigned NaN32GlobalDataOffset = NaN64GlobalDataOffset + sizeof(double);
static const unsigned InitialGlobalDataBytes = NaN32GlobalDataOffset + sizeof(float);
static const unsigned HeapGlobalDataOffset = ActivationGlobalDataOffset + sizeof(void*);
static const unsigned NaN64GlobalDataOffset = HeapGlobalDataOffset + sizeof(void*);
static const unsigned NaN32GlobalDataOffset = NaN64GlobalDataOffset + sizeof(double);
static const unsigned InitialGlobalDataBytes = NaN32GlobalDataOffset + sizeof(float);
static const unsigned MaxSigs = 4 * 1024;
static const unsigned MaxFuncs = 512 * 1024;
static const unsigned MaxImports = 4 * 1024;
static const unsigned MaxExports = 4 * 1024;
static const unsigned MaxTableElems = 128 * 1024;
static const unsigned MaxArgsPerFunc = 4 * 1024;
static const unsigned MaxBrTableElems = 4 * 1024;
} // namespace wasm
} // namespace js

View File

@ -533,13 +533,13 @@ WasmTextToBinary(JSContext* cx, unsigned argc, Value* vp)
return false;
}
Rooted<ArrayBufferObject*> buffer(cx, ArrayBufferObject::create(cx, bytes->length()));
if (!buffer)
RootedObject obj(cx, JS_NewUint8Array(cx, bytes->length()));
if (!obj)
return false;
memcpy(buffer->dataPointer(), bytes->begin(), bytes->length());
memcpy(obj->as<TypedArrayObject>().viewDataUnshared(), bytes->begin(), bytes->length());
args.rval().setObject(*buffer);
args.rval().setObject(*obj);
return true;
}

View File

@ -726,7 +726,6 @@ template <typename ParseHandler>
Parser<ParseHandler>::~Parser()
{
MOZ_ASSERT(checkOptionsCalled);
alloc.release(tempPoolMark);
/*
@ -3938,6 +3937,70 @@ Parser<ParseHandler>::AutoPushStmtInfoPC::makeInnermostLexicalScope(StaticBlockS
return generateBlockId();
}
template <typename ParseHandler>
Parser<ParseHandler>::PossibleError::PossibleError(Parser<ParseHandler>& parser)
: parser_(parser)
{
state_ = ErrorState::None;
}
template <typename ParseHandler>
void
Parser<ParseHandler>::PossibleError::setPending(ParseReportKind kind, unsigned errorNumber,
bool strict)
{
// If we report an error later, we'll do it from the position where we set
// the state to pending.
offset_ = parser_.pos().begin;
reportKind_ = kind;
strict_ = strict;
errorNumber_ = errorNumber;
state_ = ErrorState::Pending;
}
template <typename ParseHandler>
void
Parser<ParseHandler>::PossibleError::setResolved()
{
state_ = ErrorState::None;
}
template <typename ParseHandler>
bool
Parser<ParseHandler>::PossibleError::hasError()
{
return state_ == ErrorState::Pending;
}
template <typename ParseHandler>
bool
Parser<ParseHandler>::PossibleError::checkForExprErrors()
{
bool err = hasError();
if (err) {
parser_.reportWithOffset(reportKind_, strict_, offset_, errorNumber_);
}
return !err;
}
template <typename ParseHandler>
void
Parser<ParseHandler>::PossibleError::transferErrorTo(PossibleError* other)
{
if (other) {
MOZ_ASSERT(this != other);
MOZ_ASSERT(!other->hasError());
// We should never allow fields to be copied between instances
// that point to different underlying parsers.
MOZ_ASSERT(&parser_ == &other->parser_);
other->offset_ = offset_;
other->reportKind_ = reportKind_;
other->errorNumber_ = errorNumber_;
other->strict_ = strict_;
other->state_ = state_;
}
}
template <typename ParseHandler>
static inline bool
HasOuterLexicalBinding(ParseContext<ParseHandler>* pc, StmtInfoPC* stmt, HandleAtom atom)
@ -4429,7 +4492,8 @@ Parser<ParseHandler>::destructuringExpr(YieldHandling yieldHandling, BindData<Pa
MOZ_ASSERT(tokenStream.isCurrentTokenType(tt));
pc->inDeclDestructuring = true;
Node pn = primaryExpr(yieldHandling, TripledotProhibited, tt);
Node pn = primaryExpr(yieldHandling, TripledotProhibited,
nullptr /* possibleError */, tt);
pc->inDeclDestructuring = false;
if (!pn)
return null();
@ -4582,10 +4646,10 @@ Parser<ParseHandler>::expressionAfterForInOrOf(ParseNodeKind forHeadKind,
YieldHandling yieldHandling)
{
MOZ_ASSERT(forHeadKind == PNK_FORIN || forHeadKind == PNK_FOROF);
return forHeadKind == PNK_FOROF
Node pn = forHeadKind == PNK_FOROF
? assignExpr(InAllowed, yieldHandling, TripledotProhibited)
: expr(InAllowed, yieldHandling, TripledotProhibited);
return pn;
}
template <typename ParseHandler>
@ -4601,7 +4665,11 @@ Parser<ParseHandler>::declarationPattern(Node decl, TokenKind tt, BindData<Parse
Node pattern;
{
pc->inDeclDestructuring = true;
pattern = primaryExpr(yieldHandling, TripledotProhibited, tt);
// No possible error is required because we already know we're
// destructuring.
pattern = primaryExpr(yieldHandling, TripledotProhibited,
nullptr /* possibleError */ , tt);
pc->inDeclDestructuring = false;
}
if (!pattern)
@ -4648,7 +4716,14 @@ Parser<ParseHandler>::declarationPattern(Node decl, TokenKind tt, BindData<Parse
return null();
}
MUST_MATCH_TOKEN(TOK_ASSIGN, JSMSG_BAD_DESTRUCT_DECL);
TokenKind token;
if (!tokenStream.getToken(&token, TokenStream::None))
return null();
if (token != TOK_ASSIGN) {
report(ParseError, false, null(), JSMSG_BAD_DESTRUCT_DECL);
return null();
}
Node init = assignExpr(forHeadKind ? InProhibited : InAllowed,
yieldHandling, TripledotProhibited);
@ -6824,7 +6899,6 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
if (!catchName)
return null();
break;
case TOK_YIELD:
if (yieldHandling == YieldIsKeyword) {
report(ParseError, false, null(), JSMSG_RESERVED_ID, "yield");
@ -7459,9 +7533,12 @@ Parser<ParseHandler>::statement(YieldHandling yieldHandling, bool canHaveDirecti
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::expr(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling, InvokedPrediction invoked)
TripledotHandling tripledotHandling,
PossibleError* possibleError,
InvokedPrediction invoked)
{
Node pn = assignExpr(inHandling, yieldHandling, tripledotHandling, invoked);
Node pn = assignExpr(inHandling, yieldHandling, tripledotHandling,
possibleError, invoked);
if (!pn)
return null();
@ -7476,9 +7553,26 @@ Parser<ParseHandler>::expr(InHandling inHandling, YieldHandling yieldHandling,
return null();
while (true) {
pn = assignExpr(inHandling, yieldHandling, tripledotHandling);
// Additional calls to assignExpr should not reuse the possibleError
// which had been passed into the function. Otherwise we would lose
// information needed to determine whether or not we're dealing with
// a non-recoverable situation.
PossibleError possibleErrorInner(*this);
pn = assignExpr(inHandling, yieldHandling, tripledotHandling,
&possibleErrorInner);
if (!pn)
return null();
// If we find an error here we should report it immedately instead of
// passing it back out of the function.
if (possibleErrorInner.hasError()) {
// We begin by checking for an outer pending error since it would
// have occurred first.
if (possibleError->checkForExprErrors())
possibleErrorInner.checkForExprErrors();
return null();
}
handler.addList(seq, pn);
if (!tokenStream.matchToken(&matched, TOK_COMMA))
@ -7489,6 +7583,19 @@ Parser<ParseHandler>::expr(InHandling inHandling, YieldHandling yieldHandling,
return seq;
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::expr(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling,
InvokedPrediction invoked)
{
PossibleError possibleError(*this);
Node pn = expr(inHandling, yieldHandling, tripledotHandling, &possibleError, invoked);
if (!pn || !possibleError.checkForExprErrors())
return null();
return pn;
}
static const JSOp ParseNodeKindToJSOp[] = {
JSOP_OR,
JSOP_AND,
@ -7576,7 +7683,9 @@ Precedence(ParseNodeKind pnk) {
template <typename ParseHandler>
MOZ_ALWAYS_INLINE typename ParseHandler::Node
Parser<ParseHandler>::orExpr1(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling, InvokedPrediction invoked)
TripledotHandling tripledotHandling,
PossibleError* possibleError,
InvokedPrediction invoked)
{
// Shift-reduce parser for the binary operator part of the JS expression
// syntax.
@ -7589,7 +7698,7 @@ Parser<ParseHandler>::orExpr1(InHandling inHandling, YieldHandling yieldHandling
Node pn;
for (;;) {
pn = unaryExpr(yieldHandling, tripledotHandling, invoked);
pn = unaryExpr(yieldHandling, tripledotHandling, possibleError, invoked);
if (!pn)
return pn;
@ -7639,19 +7748,22 @@ Parser<ParseHandler>::orExpr1(InHandling inHandling, YieldHandling yieldHandling
template <typename ParseHandler>
MOZ_ALWAYS_INLINE typename ParseHandler::Node
Parser<ParseHandler>::condExpr1(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling, InvokedPrediction invoked)
TripledotHandling tripledotHandling,
PossibleError* possibleError,
InvokedPrediction invoked)
{
Node condition = orExpr1(inHandling, yieldHandling, tripledotHandling, invoked);
Node condition = orExpr1(inHandling, yieldHandling, tripledotHandling, possibleError, invoked);
if (!condition || !tokenStream.isCurrentTokenType(TOK_HOOK))
return condition;
Node thenExpr = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
Node thenExpr = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
possibleError);
if (!thenExpr)
return null();
MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_IN_COND);
Node elseExpr = assignExpr(inHandling, yieldHandling, TripledotProhibited);
Node elseExpr = assignExpr(inHandling, yieldHandling, TripledotProhibited,
possibleError);
if (!elseExpr)
return null();
@ -7664,7 +7776,8 @@ Parser<ParseHandler>::condExpr1(InHandling inHandling, YieldHandling yieldHandli
template <typename ParseHandler>
bool
Parser<ParseHandler>::checkAndMarkAsAssignmentLhs(Node target, AssignmentFlavor flavor)
Parser<ParseHandler>::checkAndMarkAsAssignmentLhs(Node target, AssignmentFlavor flavor,
PossibleError* possibleError)
{
MOZ_ASSERT(flavor != KeyedDestructuringAssignment,
"destructuring must use special checking/marking code, not "
@ -7676,7 +7789,13 @@ Parser<ParseHandler>::checkAndMarkAsAssignmentLhs(Node target, AssignmentFlavor
return false;
}
return checkDestructuringPattern(nullptr, target);
bool isDestructuring = checkDestructuringPattern(nullptr, target);
// Here we've successfully distinguished between destructuring and
// an object literal. In the case where "CoverInitializedName"
// syntax was used there will be a pending error that needs clearing.
if (possibleError && isDestructuring)
possibleError->setResolved();
return isDestructuring;
}
// All other permitted targets are simple.
@ -7704,9 +7823,12 @@ Parser<ParseHandler>::checkAndMarkAsAssignmentLhs(Node target, AssignmentFlavor
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling, InvokedPrediction invoked)
TripledotHandling tripledotHandling,
PossibleError* possibleError,
InvokedPrediction invoked)
{
JS_CHECK_RECURSION(context, return null());
MOZ_ASSERT(!possibleError->hasError());
// It's very common at this point to have a "detectably simple" expression,
// i.e. a name/number/string token followed by one of the following tokens
@ -7756,9 +7878,11 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
TokenStream::Position start(keepAtoms);
tokenStream.tell(&start);
Node lhs = condExpr1(inHandling, yieldHandling, tripledotHandling, invoked);
if (!lhs)
PossibleError possibleErrorInner(*this);
Node lhs = condExpr1(inHandling, yieldHandling, tripledotHandling, &possibleErrorInner, invoked);
if (!lhs) {
return null();
}
ParseNodeKind kind;
JSOp op;
@ -7778,6 +7902,7 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
case TOK_POWASSIGN: kind = PNK_POWASSIGN; op = JSOP_POW; break;
case TOK_ARROW: {
// A line terminator between ArrowParameters and the => should trigger a SyntaxError.
tokenStream.ungetToken();
TokenKind next = TOK_EOF;
@ -7840,24 +7965,42 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
default:
MOZ_ASSERT(!tokenStream.isCurrentTokenAssignment());
possibleErrorInner.transferErrorTo(possibleError);
tokenStream.ungetToken();
return lhs;
}
AssignmentFlavor flavor = kind == PNK_ASSIGN ? PlainAssignment : CompoundAssignment;
if (!checkAndMarkAsAssignmentLhs(lhs, flavor))
if (!checkAndMarkAsAssignmentLhs(lhs, flavor, &possibleErrorInner))
return null();
if (!possibleErrorInner.checkForExprErrors())
return null();
bool saved = pc->inDeclDestructuring;
pc->inDeclDestructuring = false;
Node rhs = assignExpr(inHandling, yieldHandling, TripledotProhibited);
Node rhs = assignExpr(inHandling, yieldHandling, TripledotProhibited,
possibleError);
pc->inDeclDestructuring = saved;
if (!rhs)
return null();
return handler.newAssignment(kind, lhs, rhs, pc, op);
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling,
InvokedPrediction invoked)
{
PossibleError possibleError(*this);
Node expr = assignExpr(inHandling, yieldHandling, tripledotHandling, &possibleError, invoked);
if (!expr || !possibleError.checkForExprErrors())
return null();
return expr;
}
template <typename ParseHandler>
bool
Parser<ParseHandler>::isValidSimpleAssignmentTarget(Node node,
@ -7982,8 +8125,9 @@ typename ParseHandler::Node
Parser<ParseHandler>::unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind, JSOp op,
uint32_t begin)
{
Node kid = unaryExpr(yieldHandling, TripledotProhibited);
if (!kid)
PossibleError possibleError(*this);
Node kid = unaryExpr(yieldHandling, TripledotProhibited, &possibleError);
if (!kid || !possibleError.checkForExprErrors())
return null();
return handler.newUnary(kind, op, begin, kid);
}
@ -7991,7 +8135,7 @@ Parser<ParseHandler>::unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kin
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::unaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
InvokedPrediction invoked)
PossibleError* possibleError, InvokedPrediction invoked)
{
JS_CHECK_RECURSION(context, return null());
@ -8023,7 +8167,7 @@ Parser<ParseHandler>::unaryExpr(YieldHandling yieldHandling, TripledotHandling t
// // Evaluates expression, triggering a runtime ReferenceError for
// // the undefined name.
// typeof (1, nonExistentName);
Node kid = unaryExpr(yieldHandling, TripledotProhibited);
Node kid = unaryExpr(yieldHandling, TripledotProhibited, possibleError);
if (!kid)
return null();
@ -8036,7 +8180,7 @@ Parser<ParseHandler>::unaryExpr(YieldHandling yieldHandling, TripledotHandling t
TokenKind tt2;
if (!tokenStream.getToken(&tt2, TokenStream::Operand))
return null();
Node pn2 = memberExpr(yieldHandling, TripledotProhibited, tt2, true);
Node pn2 = memberExpr(yieldHandling, TripledotProhibited, possibleError, tt2, true);
if (!pn2)
return null();
AssignmentFlavor flavor = (tt == TOK_INC) ? IncrementAssignment : DecrementAssignment;
@ -8049,7 +8193,7 @@ Parser<ParseHandler>::unaryExpr(YieldHandling yieldHandling, TripledotHandling t
}
case TOK_DELETE: {
Node expr = unaryExpr(yieldHandling, TripledotProhibited);
Node expr = unaryExpr(yieldHandling, TripledotProhibited, possibleError);
if (!expr)
return null();
@ -8065,7 +8209,7 @@ Parser<ParseHandler>::unaryExpr(YieldHandling yieldHandling, TripledotHandling t
}
default: {
Node pn = memberExpr(yieldHandling, tripledotHandling, tt, /* allowCallSyntax = */ true,
Node pn = memberExpr(yieldHandling, tripledotHandling, possibleError, tt, /* allowCallSyntax = */ true,
invoked);
if (!pn)
return null();
@ -8486,7 +8630,8 @@ Parser<ParseHandler>::checkAndMarkSuperScope()
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
TokenKind tt, bool allowCallSyntax, InvokedPrediction invoked)
PossibleError* possibleError, TokenKind tt,
bool allowCallSyntax, InvokedPrediction invoked)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(tt));
@ -8510,7 +8655,8 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
// Gotten by tryNewTarget
tt = tokenStream.currentToken().type;
Node ctorExpr = memberExpr(yieldHandling, TripledotProhibited, tt, false, PredictInvoked);
Node ctorExpr = memberExpr(yieldHandling, TripledotProhibited,
possibleError, tt, false, PredictInvoked);
if (!ctorExpr)
return null();
@ -8535,7 +8681,7 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
if (!lhs)
return null();
} else {
lhs = primaryExpr(yieldHandling, tripledotHandling, tt, invoked);
lhs = primaryExpr(yieldHandling, tripledotHandling, possibleError, tt, invoked);
if (!lhs)
return null();
}
@ -8566,7 +8712,7 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
return null();
}
} else if (tt == TOK_LB) {
Node propExpr = expr(InAllowed, yieldHandling, TripledotProhibited);
Node propExpr = expr(InAllowed, yieldHandling, TripledotProhibited, possibleError);
if (!propExpr)
return null();
@ -8689,6 +8835,19 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
return lhs;
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling, TokenKind tt,
bool allowCallSyntax, InvokedPrediction invoked)
{
PossibleError possibleError(*this);
Node pn = memberExpr(yieldHandling, tripledotHandling, &possibleError, tt,
allowCallSyntax, invoked);
if (!pn || !possibleError.checkForExprErrors())
return null();
return pn;
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::newName(PropertyName* name)
@ -9001,13 +9160,15 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, Node propList,
return propName;
}
if (ltok == TOK_NAME && (tt == TOK_COMMA || tt == TOK_RC)) {
if (ltok == TOK_NAME && (tt == TOK_COMMA || tt == TOK_RC || tt == TOK_ASSIGN)) {
if (isGenerator) {
report(ParseError, false, null(), JSMSG_BAD_PROP_ID);
return null();
}
tokenStream.ungetToken();
*propType = PropertyType::Shorthand;
*propType = tt == TOK_ASSIGN ?
PropertyType::CoverInitializedName :
PropertyType::Shorthand;
return propName;
}
@ -9048,7 +9209,7 @@ Parser<ParseHandler>::computedPropertyName(YieldHandling yieldHandling, Node lit
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling)
Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
@ -9057,6 +9218,7 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling)
return null();
bool seenPrototypeMutation = false;
bool seenCoverInitializedName = false;
RootedAtom propAtom(context);
for (;;) {
TokenKind tt;
@ -9115,6 +9277,43 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling)
if (!handler.addShorthand(literal, propName, nameExpr))
return null();
} else if (propType == PropertyType::CoverInitializedName) {
/*
* Support, e.g., |var {x=1, y=2} = o| as destructuring shorthand
* with default values, as per ES6 12.14.5 (2016/2/4)
*/
if (!tokenStream.checkForKeyword(propAtom, nullptr))
return null();
Node lhs = identifierName(yieldHandling);
if (!lhs)
return null();
tokenStream.consumeKnownToken(TOK_ASSIGN);
Node rhs = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
if (!rhs)
return null();
Node propExpr = handler.newAssignment(PNK_ASSIGN, lhs, rhs, pc, JSOP_NOP);
if (!propExpr)
return null();
if (!handler.addPropertyDefinition(literal, propName, propExpr))
return null();
if (!abortIfSyntaxParser())
return null();
if (!seenCoverInitializedName) {
seenCoverInitializedName = true;
// "shorthand default" or "CoverInitializedName" syntax is only
// valid in the case of destructuring. Here we set a pending error so
// that later in the parse, once we've determined whether or not we're
// destructuring, the error can be reported or ignored appropriately.
if (possibleError)
possibleError->setPending(ParseError, JSMSG_BAD_PROP_ID, false);
}
} else {
// FIXME: Implement ES6 function "name" property semantics
// (bug 883377).
@ -9214,7 +9413,8 @@ Parser<ParseHandler>::tryNewTarget(Node &newTarget)
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
TokenKind tt, InvokedPrediction invoked)
PossibleError* possibleError, TokenKind tt,
InvokedPrediction invoked)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(tt));
JS_CHECK_RECURSION(context, return null());
@ -9230,7 +9430,7 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling
return arrayInitializer(yieldHandling);
case TOK_LC:
return objectLiteral(yieldHandling);
return objectLiteral(yieldHandling, possibleError);
case TOK_LP: {
TokenKind next;
@ -9262,7 +9462,7 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling
return generatorComprehension(begin);
}
Node expr = exprInParens(InAllowed, yieldHandling, TripledotAllowed);
Node expr = exprInParens(InAllowed, yieldHandling, TripledotAllowed, possibleError);
if (!expr)
return null();
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
@ -9366,6 +9566,16 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling
}
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::exprInParens(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling,
PossibleError* possibleError)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LP));
return expr(inHandling, yieldHandling, tripledotHandling, possibleError, PredictInvoked);
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::exprInParens(InHandling inHandling, YieldHandling yieldHandling,

View File

@ -374,6 +374,7 @@ enum PropListType { ObjectLiteral, ClassBody, DerivedClassBody };
enum class PropertyType {
Normal,
Shorthand,
CoverInitializedName,
Getter,
GetterNoExpressionClosure,
Setter,
@ -415,6 +416,72 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
operator StmtInfoPC*() { return &stmt_; }
};
/*
* A class for temporarily stashing errors while parsing continues.
*
* The ability to stash an error is useful for handling situations where we
* aren't able to verify that an error has occurred until later in the parse.
* For instance | ({x=1}) | is always parsed as an object literal with
* a SyntaxError, however, in the case where it is followed by '=>' we rewind
* and reparse it as a valid arrow function. Here a PossibleError would be
* set to 'pending' when the initial SyntaxError was encountered then 'resolved'
* just before rewinding the parser.
*
* When using PossibleError one should set a pending error at the location
* where an error occurs. From that point, the error may be resolved
* (invalidated) or left until the PossibleError is checked.
*
* Ex:
* PossibleError possibleError(*this);
* possibleError.setPending(ParseError, JSMSG_BAD_PROP_ID, false);
* // A JSMSG_BAD_PROP_ID ParseError is reported, returns false.
* possibleError.checkForExprErrors();
*
* PossibleError possibleError(*this);
* possibleError.setPending(ParseError, JSMSG_BAD_PROP_ID, false);
* possibleError.setResolved();
* // Returns true, no error is reported.
* possibleError.checkForExprErrors();
*
* PossibleError possibleError(*this);
* // Returns true, no error is reported.
* possibleError.checkForExprErrors();
*/
class MOZ_STACK_CLASS PossibleError
{
enum ErrorState { None, Pending };
ErrorState state_;
// Error reporting fields.
uint32_t offset_;
unsigned errorNumber_;
ParseReportKind reportKind_;
Parser<ParseHandler>& parser_;
bool strict_;
public:
explicit PossibleError(Parser<ParseHandler>& parser);
// Set a pending error.
void setPending(ParseReportKind kind, unsigned errorNumber, bool strict);
// Resolve any pending error.
void setResolved();
// Return true if an error is pending without reporting
bool hasError();
// If there is a pending error report it and return false, otherwise return
// true.
bool checkForExprErrors();
// Pass pending errors between possible error instances. This is useful
// for extending the lifetime of a pending error beyond the scope of
// the PossibleError where it was initially set (keeping in mind that
// PossibleError is a MOZ_STACK_CLASS).
void transferErrorTo(PossibleError* other);
};
public:
ExclusiveContext* const context;
LifoAlloc& alloc;
@ -765,7 +832,15 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
Node expr(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling,
PossibleError* possibleError,
InvokedPrediction invoked = PredictUninvoked);
Node expr(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling,
InvokedPrediction invoked = PredictUninvoked);
Node assignExpr(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling,
PossibleError* possibleError,
InvokedPrediction invoked = PredictUninvoked);
Node assignExpr(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling,
InvokedPrediction invoked = PredictUninvoked);
@ -773,16 +848,26 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
Node yieldExpression(InHandling inHandling);
Node condExpr1(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling,
PossibleError* possibleError,
InvokedPrediction invoked = PredictUninvoked);
Node orExpr1(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling,
InvokedPrediction invoked = PredictUninvoked);
PossibleError* possibleError,
InvokedPrediction invoked = PredictUninvoked);
Node unaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
PossibleError* possibleError,
InvokedPrediction invoked = PredictUninvoked);
Node memberExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
PossibleError* possibleError, TokenKind tt,
bool allowCallSyntax, InvokedPrediction invoked = PredictUninvoked);
Node memberExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling, TokenKind tt,
bool allowCallSyntax, InvokedPrediction invoked = PredictUninvoked);
Node primaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling, TokenKind tt,
Node primaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
PossibleError* possibleError, TokenKind tt,
InvokedPrediction invoked = PredictUninvoked);
Node exprInParens(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling,
PossibleError* possibleError);
Node exprInParens(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling);
@ -854,7 +939,8 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
ForInOrOfTarget
};
bool checkAndMarkAsAssignmentLhs(Node pn, AssignmentFlavor flavor);
bool checkAndMarkAsAssignmentLhs(Node pn, AssignmentFlavor flavor,
PossibleError* possibleError=nullptr);
bool matchInOrOf(bool* isForInp, bool* isForOfp);
bool checkFunctionArguments();
@ -909,7 +995,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
Node arrayInitializer(YieldHandling yieldHandling);
Node newRegExp();
Node objectLiteral(YieldHandling yieldHandling);
Node objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError);
enum PrepareLexicalKind {
PrepareLet,

View File

@ -4,6 +4,7 @@ load(libdir + 'eqArrayHelper.js');
var arrayPattern = '[a = 1, b = 2, c = 3, d = 4, e = 5, f = 6]';
var objectPattern = '{0: a = 1, 1: b = 2, 2: c = 3, 3: d = 4, 4: e = 5, 5: f = 6}';
var objectPatternShorthand = '{a = 1, b = 2, c = 3, d = 4, e = 5, f = 6}';
var nestedPattern = '{a: a = 1, b: [b = 2] = [], c: {c: [c]} = {c: [3]}, d: {d, e} = {d: 4, e: 5}, f: f = 6}';
function testAll(fn) {
@ -17,6 +18,11 @@ function testAll(fn) {
assertEqArray(fn(objectPattern, [undefined, 0, false, null, "", undefined]), [1, 0, false, null, "", 6]);
assertEqArray(fn(objectPattern, [0, false]), [0, false, 3, 4, 5, 6]);
assertEqArray(fn(objectPatternShorthand, {}), [1, 2, 3, 4, 5, 6]);
assertEqArray(fn(objectPatternShorthand, {a: 2, b: 3, c: 4, d: 5, e: 6, f: 7, g: 8, h: 9}), [2, 3, 4, 5, 6, 7]);
assertEqArray(fn(objectPatternShorthand, {a: undefined, b: 0, c: false, d: null, e: "", f: undefined}),
[1, 0, false, null, "", 6]);
assertEqArray(fn(objectPatternShorthand, {a: 0, b: false}), [0, false, 3, 4, 5, 6]);
assertEqArray(fn(nestedPattern, {}), [1, 2, 3, 4, 5, 6]);
assertEqArray(fn(nestedPattern, {a: 2, b: [], c: undefined}), [2, 2, 3, 4, 5, 6]);
assertEqArray(fn(nestedPattern, {a: undefined, b: [3], c: {c: [4]}}), [1, 3, 4, 4, 5, 6]);
@ -175,5 +181,9 @@ if (defaultsSupportedInForVar) {
b = undefined;
for (let {1: c = 10} in " ") { b = c; }
assertEq(b, 10);
b = undefined;
for (let {c = 10} in " ") { b = c; }
assertEq(b, 10);
`)();
}

View File

@ -26,19 +26,16 @@ const versionError = /failed to match binary version/;
const unknownSectionError = /failed to skip unknown section at end/;
const sectionError = /failed to start section/;
const I32Code = 0;
const I64Code = 1;
const F32Code = 2;
const F64Code = 3;
const I32x4Code = 4;
const F32x4Code = 5;
const B32x4Code = 6;
const VoidCode = 7;
const VoidCode = 0;
const I32Code = 1;
const I64Code = 2;
const F32Code = 3;
const F64Code = 4;
function toBuf(array) {
function toU8(array) {
for (let b of array)
assertEq(b < 256, true);
return Uint8Array.from(array).buffer;
return Uint8Array.from(array);
}
function varU32(u32) {
@ -49,33 +46,33 @@ function varU32(u32) {
const U32MAX_LEB = [255, 255, 255, 255, 15];
const wasmEval = Wasm.instantiateModule;
assertErrorMessage(() => wasmEval(toU8([])), TypeError, magicError);
assertErrorMessage(() => wasmEval(toU8([42])), TypeError, magicError);
assertErrorMessage(() => wasmEval(toU8([magic0, magic1, magic2])), TypeError, magicError);
assertErrorMessage(() => wasmEval(toU8([1,2,3,4])), TypeError, magicError);
assertErrorMessage(() => wasmEval(toU8([magic0, magic1, magic2, magic3])), TypeError, versionError);
assertErrorMessage(() => wasmEval(toU8([magic0, magic1, magic2, magic3, 1])), TypeError, versionError);
assertErrorMessage(() => wasmEval(toU8([magic0, magic1, magic2, magic3, ver0])), TypeError, versionError);
assertErrorMessage(() => wasmEval(toU8([magic0, magic1, magic2, magic3, ver0, ver1, ver2])), TypeError, versionError);
function moduleHeaderThen(...rest) {
return [magic0, magic1, magic2, magic3, ver0, ver1, ver2, ver3, ...rest];
}
const wasmEval = Wasm.instantiateModule;
assertErrorMessage(() => wasmEval(toBuf([])), TypeError, magicError);
assertErrorMessage(() => wasmEval(toBuf([42])), TypeError, magicError);
assertErrorMessage(() => wasmEval(toBuf([magic0, magic1, magic2])), TypeError, magicError);
assertErrorMessage(() => wasmEval(toBuf([1,2,3,4])), TypeError, magicError);
assertErrorMessage(() => wasmEval(toBuf([magic0, magic1, magic2, magic3])), TypeError, versionError);
assertErrorMessage(() => wasmEval(toBuf([magic0, magic1, magic2, magic3, 1])), TypeError, versionError);
assertErrorMessage(() => wasmEval(toBuf([magic0, magic1, magic2, magic3, ver0])), TypeError, versionError);
assertErrorMessage(() => wasmEval(toBuf([magic0, magic1, magic2, magic3, ver0, ver1, ver2])), TypeError, versionError);
var o = wasmEval(toBuf(moduleHeaderThen()));
var o = wasmEval(toU8(moduleHeaderThen()));
assertEq(Object.getOwnPropertyNames(o).length, 0);
wasmEval(toBuf(moduleHeaderThen(1, 0))); // unknown section containing 0-length string
wasmEval(toBuf(moduleHeaderThen(2, 1, 0))); // unknown section containing 1-length string ("\0")
wasmEval(toBuf(moduleHeaderThen(1, 0, 1, 0)));
wasmEval(toBuf(moduleHeaderThen(1, 0, 2, 1, 0)));
wasmEval(toBuf(moduleHeaderThen(1, 0, 2, 1, 0)));
wasmEval(toU8(moduleHeaderThen(1, 0))); // unknown section containing 0-length string
wasmEval(toU8(moduleHeaderThen(2, 1, 0))); // unknown section containing 1-length string ("\0")
wasmEval(toU8(moduleHeaderThen(1, 0, 1, 0)));
wasmEval(toU8(moduleHeaderThen(1, 0, 2, 1, 0)));
wasmEval(toU8(moduleHeaderThen(1, 0, 2, 1, 0)));
assertErrorMessage(() => wasmEval(toBuf(moduleHeaderThen(1))), TypeError, sectionError);
assertErrorMessage(() => wasmEval(toBuf(moduleHeaderThen(0, 1))), TypeError, sectionError);
assertErrorMessage(() => wasmEval(toBuf(moduleHeaderThen(0, 0))), TypeError, unknownSectionError);
assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(1))), TypeError, sectionError);
assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0, 1))), TypeError, sectionError);
assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0, 0))), TypeError, unknownSectionError);
function cstring(name) {
return (name + '\0').split('').map(c => c.charCodeAt(0));
@ -94,7 +91,7 @@ function moduleWithSections(sectionArray) {
bytes.push(...string(section.name));
bytes.push(...section.body);
}
return bytes;
return toU8(bytes);
}
function sigSection(sigs) {
@ -121,8 +118,9 @@ function funcBody(func) {
var body = varU32(func.locals.length);
for (let local of func.locals)
body.push(...varU32(local));
body.push(...varU32(func.body.length));
return body.concat(...func.body);
body = body.concat(...func.body);
body.splice(0, 0, ...varU32(body.length));
return body;
}
function bodySection(bodies) {
@ -153,44 +151,45 @@ const v2vSig = {args:[], ret:VoidCode};
const i2vSig = {args:[I32Code], ret:VoidCode};
const v2vBody = funcBody({locals:[], body:[]});
assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([ {name: sigId, body: U32MAX_LEB, } ]))), TypeError, /too many signatures/);
assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([ {name: sigId, body: [1, ...U32MAX_LEB], } ]))), TypeError, /too many arguments in signature/);
assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([sigSection([{args:[], ret:VoidCode}, {args:[], ret:VoidCode}])]))), TypeError, /duplicate signature/);
assertErrorMessage(() => wasmEval(moduleWithSections([ {name: sigId, body: U32MAX_LEB } ])), TypeError, /too many signatures/);
assertErrorMessage(() => wasmEval(moduleWithSections([ {name: sigId, body: [1, ...U32MAX_LEB], } ])), TypeError, /too many arguments in signature/);
assertErrorMessage(() => wasmEval(moduleWithSections([sigSection([{args:[], ret:VoidCode}, {args:[], ret:VoidCode}])])), TypeError, /duplicate signature/);
assertThrowsInstanceOf(() => wasmEval(toBuf(moduleWithSections([{name: sigId, body: [1]}]))), TypeError);
assertThrowsInstanceOf(() => wasmEval(toBuf(moduleWithSections([{name: sigId, body: [1, 1, 0]}]))), TypeError);
assertThrowsInstanceOf(() => wasmEval(moduleWithSections([{name: sigId, body: [1]}])), TypeError);
assertThrowsInstanceOf(() => wasmEval(moduleWithSections([{name: sigId, body: [1, 1, 0]}])), TypeError);
wasmEval(toBuf(moduleWithSections([sigSection([])])));
wasmEval(toBuf(moduleWithSections([sigSection([v2vSig])])));
wasmEval(toBuf(moduleWithSections([sigSection([i2vSig])])));
wasmEval(toBuf(moduleWithSections([sigSection([v2vSig, i2vSig])])));
wasmEval(moduleWithSections([sigSection([])]));
wasmEval(moduleWithSections([sigSection([v2vSig])]));
wasmEval(moduleWithSections([sigSection([i2vSig])]));
wasmEval(moduleWithSections([sigSection([v2vSig, i2vSig])]));
assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([sigSection([{args:[], ret:100}])]))), TypeError, /bad expression type/);
assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([sigSection([{args:[100], ret:VoidCode}])]))), TypeError, /bad value type/);
assertErrorMessage(() => wasmEval(moduleWithSections([sigSection([{args:[], ret:100}])])), TypeError, /bad expression type/);
assertErrorMessage(() => wasmEval(moduleWithSections([sigSection([{args:[100], ret:VoidCode}])])), TypeError, /bad value type/);
assertThrowsInstanceOf(() => wasmEval(toBuf(moduleWithSections([sigSection([]), declSection([0])]))), TypeError, /signature index out of range/);
assertThrowsInstanceOf(() => wasmEval(toBuf(moduleWithSections([sigSection([v2vSig]), declSection([1])]))), TypeError, /signature index out of range/);
assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([sigSection([v2vSig]), declSection([0])]))), TypeError, /expected function bodies/);
wasmEval(toBuf(moduleWithSections([sigSection([v2vSig]), declSection([0]), bodySection([v2vBody])])));
assertThrowsInstanceOf(() => wasmEval(moduleWithSections([sigSection([]), declSection([0])])), TypeError, /signature index out of range/);
assertThrowsInstanceOf(() => wasmEval(moduleWithSections([sigSection([v2vSig]), declSection([1])])), TypeError, /signature index out of range/);
assertErrorMessage(() => wasmEval(moduleWithSections([sigSection([v2vSig]), declSection([0])])), TypeError, /expected function bodies/);
wasmEval(moduleWithSections([sigSection([v2vSig]), declSection([0]), bodySection([v2vBody])]));
assertThrowsInstanceOf(() => wasmEval(toBuf(moduleWithSections([sigSection([v2vSig]), {name: importId, body:[]}]))), TypeError);
assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([importSection([{sigIndex:0, module:"a", func:"b"}])]))), TypeError, /signature index out of range/);
assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([sigSection([v2vSig]), importSection([{sigIndex:1, module:"a", func:"b"}])]))), TypeError, /signature index out of range/);
wasmEval(toBuf(moduleWithSections([sigSection([v2vSig]), importSection([])])));
wasmEval(toBuf(moduleWithSections([sigSection([v2vSig]), importSection([{sigIndex:0, module:"a", func:""}])])), {a:()=>{}});
assertThrowsInstanceOf(() => wasmEval(moduleWithSections([sigSection([v2vSig]), {name: importId, body:[]}])), TypeError);
assertErrorMessage(() => wasmEval(moduleWithSections([importSection([{sigIndex:0, module:"a", func:"b"}])])), TypeError, /signature index out of range/);
assertErrorMessage(() => wasmEval(moduleWithSections([sigSection([v2vSig]), importSection([{sigIndex:1, module:"a", func:"b"}])])), TypeError, /signature index out of range/);
wasmEval(moduleWithSections([sigSection([v2vSig]), importSection([])]));
wasmEval(moduleWithSections([sigSection([v2vSig]), importSection([{sigIndex:0, module:"a", func:""}])]), {a:()=>{}});
wasmEval(toBuf(moduleWithSections([
wasmEval(moduleWithSections([
sigSection([v2vSig]),
importSection([{sigIndex:0, module:"a", func:""}]),
declSection([0]),
bodySection([v2vBody])])), {a:()=>{}});
bodySection([v2vBody])
]), {a:()=>{}});
assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([ {name: dataSegmentsId, body: [], } ]))), TypeError, /data section requires a memory section/);
assertErrorMessage(() => wasmEval(moduleWithSections([ {name: dataSegmentsId, body: [], } ])), TypeError, /data section requires a memory section/);
wasmEval(toBuf(moduleWithSections([tableSection([])])));
assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([tableSection([0])]))), TypeError, /table element out of range/);
wasmEval(toBuf(moduleWithSections([sigSection([v2vSig]), declSection([0]), tableSection([0]), bodySection([v2vBody])])));
wasmEval(toBuf(moduleWithSections([sigSection([v2vSig]), declSection([0]), tableSection([0,0]), bodySection([v2vBody])])));
assertErrorMessage(() => wasmEval(toBuf(moduleWithSections([sigSection([v2vSig]), declSection([0]), tableSection([0,1]), bodySection([v2vBody])]))), TypeError, /table element out of range/);
wasmEval(toBuf(moduleWithSections([sigSection([v2vSig]), declSection([0,0,0]), tableSection([0,1,0,2]), bodySection([v2vBody, v2vBody, v2vBody])])));
wasmEval(toBuf(moduleWithSections([sigSection([v2vSig,i2vSig]), declSection([0,0,1]), tableSection([0,1,2]), bodySection([v2vBody, v2vBody, v2vBody])])));
wasmEval(moduleWithSections([tableSection([])]));
assertErrorMessage(() => wasmEval(moduleWithSections([tableSection([0])])), TypeError, /table element out of range/);
wasmEval(moduleWithSections([sigSection([v2vSig]), declSection([0]), tableSection([0]), bodySection([v2vBody])]));
wasmEval(moduleWithSections([sigSection([v2vSig]), declSection([0]), tableSection([0,0]), bodySection([v2vBody])]));
assertErrorMessage(() => wasmEval(moduleWithSections([sigSection([v2vSig]), declSection([0]), tableSection([0,1]), bodySection([v2vBody])])), TypeError, /table element out of range/);
wasmEval(moduleWithSections([sigSection([v2vSig]), declSection([0,0,0]), tableSection([0,1,0,2]), bodySection([v2vBody, v2vBody, v2vBody])]));
wasmEval(moduleWithSections([sigSection([v2vSig,i2vSig]), declSection([0,0,1]), tableSection([0,1,2]), bodySection([v2vBody, v2vBody, v2vBody])]));

View File

@ -366,7 +366,7 @@ MSG_DEF(JSMSG_WASM_FAIL, 1, JSEXN_TYPEERR, "wasm error: {0}")
MSG_DEF(JSMSG_WASM_DECODE_FAIL, 2, JSEXN_TYPEERR, "wasm validation error at offset {0}: {1}")
MSG_DEF(JSMSG_WASM_TEXT_FAIL, 1, JSEXN_SYNTAXERR, "wasm text error: {0}")
MSG_DEF(JSMSG_WASM_BAD_IND_CALL, 0, JSEXN_ERR, "wasm indirect call signature mismatch")
MSG_DEF(JSMSG_WASM_BAD_BUF_ARG, 0, JSEXN_TYPEERR, "first argument must be an ArrayBuffer")
MSG_DEF(JSMSG_WASM_BAD_BUF_ARG, 0, JSEXN_TYPEERR, "first argument must be a typed array")
MSG_DEF(JSMSG_WASM_BAD_IMPORT_ARG, 0, JSEXN_TYPEERR, "second argument, if present, must be an object")
// Proxy

View File

@ -5069,12 +5069,8 @@ WasmLoop(JSContext* cx, unsigned argc, Value* vp)
return false;
Rooted<TypedArrayObject*> typedArray(cx, &ret->as<TypedArrayObject>());
if (!TypedArrayObject::ensureHasBuffer(cx, typedArray))
return false;
Rooted<ArrayBufferObject*> arrayBuffer(cx, typedArray->bufferUnshared());
RootedObject exportObj(cx);
if (!wasm::Eval(cx, arrayBuffer, importObj, &exportObj)) {
if (!wasm::Eval(cx, typedArray, importObj, &exportObj)) {
// Clear any pending exceptions, we don't care about them
cx->clearPendingException();
}

View File

@ -0,0 +1,102 @@
/* 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/. */
// Ensure that the syntax used in shorthand destructuring with defaults
// e.g. |{x=1, y=2} = {}| properly raises a syntax error within an object
// literal. As per ES6 12.2.6 Object Initializer, "NOTE 3."
const SYNTAX_ERROR_STMTS = [
// expressions
"({x={}={}}),",
"({y={x={}={}={}={}={}={}={}={}}={}}),",
"({a=1, b=2, c=3, x=({}={})}),",
"({x=1, y={z={1}}})",
"({x=1} = {y=1});",
"({x: y={z=1}}={})",
"({x=1}),",
"({z=1}={}, {w=2}, {e=3})=>{};",
"({z={x=1}})=>{};",
"({x = ({y=1}) => y})",
"(({x=1})) => x",
// declarations
"let o = {x=1};",
"var j = {x=1};",
"var j = {x={y=1}}={};",
"const z = {x=1};",
"const z = {x={y=1}}={};",
"const {x=1};",
"const {x={y=33}}={};",
"var {x=1};",
"let {x=1};",
"let x, y, {z=1}={}, {w=2}, {e=3};",
// array initialization
"[{x=1, y = ({z=2} = {})}];",
// try/catch
"try {throw 'a';} catch ({x={y=1}}) {}",
// if/else
"if ({k: 1, x={y=2}={}}) {}",
"if (false) {} else if (true) { ({x=1}) }",
// switch
"switch ('c') { case 'c': ({x=1}); }",
// for
"for ({x=1}; 1;) {1}",
"for ({x={y=2}}; 1;) {1}",
"for (var x = 0; x < 2; x++) { ({x=1, y=2}) }",
"for (let x=1;{x=1};){}",
"for (let x=1;{x={y=2}};){}",
"for (let x=1;1;{x=1}){}",
"for (let x=1;1;{x={y=2}}){}",
// while
"while ({x=1}) {1};",
"while ({x={y=2}}={}) {1};",
// with
"with ({x=1}) {};",
"with ({x={y=3}={}}) {};",
"with (Math) { ({x=1}) };"
]
for (var stmt of SYNTAX_ERROR_STMTS) {
assertThrowsInstanceOf(() => {
eval(stmt);
}, SyntaxError);
}
const REFERENCE_ERROR_STMTS = [
"({x} += {});",
"({x = 1}) = {x: 2};",
]
for (var stmt of REFERENCE_ERROR_STMTS) {
assertThrowsInstanceOf(() => {
eval(stmt);
}, ReferenceError);
}
// A few tricky but acceptable cases:
// see https://bugzilla.mozilla.org/show_bug.cgi?id=932080#c2
assertEq((({a = 0}) => a)({}), 0);
assertEq((({a = 0} = {}) => a)({}), 0);
assertEq((({a = 0} = {}) => a)({a: 1}), 1);
{
let x, y;
({x=1} = {});
assertEq(x, 1);
({x=1} = {x: 4});
assertEq(x, 4);
({x=1, y=2} = {})
assertEq(x, 1);
assertEq(y, 2);
}
{
let {x={i=1, j=2}={}}={};
assertDeepEq(x, ({}));
assertEq(i, 1);
assertEq(j, 2);
}
if (typeof reportCompare == "function")
reportCompare(true, true);

View File

@ -23,7 +23,7 @@ Gecko_ChildrenCount(RawGeckoNode* aNode)
return aNode->GetChildCount();
}
int
bool
Gecko_NodeIsElement(RawGeckoNode* aNode)
{
return aNode->IsElement();
@ -101,36 +101,37 @@ Gecko_ElementState(RawGeckoElement* aElement)
((1 << (NS_EVENT_STATE_HIGHEST_SERVO_BIT + 1)) - 1);
}
int
bool
Gecko_IsHTMLElementInHTMLDocument(RawGeckoElement* aElement)
{
return aElement->IsHTMLElement() && aElement->OwnerDoc()->IsHTMLDocument();
}
int
bool
Gecko_IsLink(RawGeckoElement* aElement)
{
return nsCSSRuleProcessor::IsLink(aElement);
}
int Gecko_IsTextNode(RawGeckoNode* aNode)
bool
Gecko_IsTextNode(RawGeckoNode* aNode)
{
return aNode->NodeInfo()->NodeType() == nsIDOMNode::TEXT_NODE;
}
int
bool
Gecko_IsVisitedLink(RawGeckoElement* aElement)
{
return aElement->StyleState().HasState(NS_EVENT_STATE_VISITED);
}
int
bool
Gecko_IsUnvisitedLink(RawGeckoElement* aElement)
{
return aElement->StyleState().HasState(NS_EVENT_STATE_UNVISITED);
}
int
bool
Gecko_IsRootElement(RawGeckoElement* aElement)
{
return aElement->OwnerDoc()->GetRootElement() == aElement;
@ -189,7 +190,8 @@ void Servo_RemoveStyleSheet(RawServoStyleSheet* sheet, RawServoStyleSet* set)
"non-MOZ_STYLO build");
}
int Servo_StyleSheetHasRules(RawServoStyleSheet* sheet)
bool
Servo_StyleSheetHasRules(RawServoStyleSheet* sheet)
{
MOZ_CRASH("stylo: shouldn't be calling Servo_StyleSheetHasRules in a "
"non-MOZ_STYLO build");

View File

@ -7,7 +7,7 @@
#ifndef mozilla_ServoBindings_h
#define mozilla_ServoBindings_h
#include <stdint.h>
#include "stdint.h"
/*
* API for Servo to access Gecko data structures. This file must compile as valid
@ -17,7 +17,6 @@
* Functions beginning with Servo_ are implemented in Servo and invoked from Gecko.
*/
#ifdef __cplusplus
class nsINode;
typedef nsINode RawGeckoNode;
namespace mozilla { namespace dom { class Element; } }
@ -28,28 +27,12 @@ typedef nsIDocument RawGeckoDocument;
struct ServoNodeData;
struct RawServoStyleSheet;
struct RawServoStyleSet;
#else
struct RawGeckoNode;
typedef struct RawGeckoNode RawGeckoNode;
struct RawGeckoElement;
typedef struct RawGeckoElement RawGeckoElement;
struct RawGeckoDocument;
typedef struct RawGeckoDocument RawGeckoDocument;
struct ServoNodeData;
typedef struct ServoNodeData ServoNodeData;
struct RawServoStyleSheet;
typedef struct RawServoStyleSheet RawServoStyleSheet;
struct RawServoStyleSet;
typedef struct RawServoStyleSet RawServoStyleSet;
#endif
#ifdef __cplusplus
extern "C" {
#endif
// DOM Traversal.
uint32_t Gecko_ChildrenCount(RawGeckoNode* node);
int Gecko_NodeIsElement(RawGeckoNode* node);
bool Gecko_NodeIsElement(RawGeckoNode* node);
RawGeckoNode* Gecko_GetParentNode(RawGeckoNode* node);
RawGeckoNode* Gecko_GetFirstChild(RawGeckoNode* node);
RawGeckoNode* Gecko_GetLastChild(RawGeckoNode* node);
@ -64,12 +47,12 @@ RawGeckoElement* Gecko_GetDocumentElement(RawGeckoDocument* document);
// Selector Matching.
uint8_t Gecko_ElementState(RawGeckoElement* element);
int Gecko_IsHTMLElementInHTMLDocument(RawGeckoElement* element);
int Gecko_IsLink(RawGeckoElement* element);
int Gecko_IsTextNode(RawGeckoNode* node);
int Gecko_IsVisitedLink(RawGeckoElement* element);
int Gecko_IsUnvisitedLink(RawGeckoElement* element);
int Gecko_IsRootElement(RawGeckoElement* element);
bool Gecko_IsHTMLElementInHTMLDocument(RawGeckoElement* element);
bool Gecko_IsLink(RawGeckoElement* element);
bool Gecko_IsTextNode(RawGeckoNode* node);
bool Gecko_IsVisitedLink(RawGeckoElement* element);
bool Gecko_IsUnvisitedLink(RawGeckoElement* element);
bool Gecko_IsRootElement(RawGeckoElement* element);
// Node data.
ServoNodeData* Gecko_GetNodeData(RawGeckoNode* node);
@ -85,15 +68,13 @@ void Servo_ReleaseStylesheet(RawServoStyleSheet* sheet);
void Servo_AppendStyleSheet(RawServoStyleSheet* sheet, RawServoStyleSet* set);
void Servo_PrependStyleSheet(RawServoStyleSheet* sheet, RawServoStyleSet* set);
void Servo_RemoveStyleSheet(RawServoStyleSheet* sheet, RawServoStyleSet* set);
int Servo_StyleSheetHasRules(RawServoStyleSheet* sheet);
bool Servo_StyleSheetHasRules(RawServoStyleSheet* sheet);
RawServoStyleSet* Servo_InitStyleSet();
void Servo_DropStyleSet(RawServoStyleSet* set);
// Servo API.
void Servo_RestyleDocument(RawGeckoDocument* doc, RawServoStyleSet* set);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // mozilla_ServoBindings_h

View File

@ -1286,7 +1286,7 @@ void SchedulableTrickleCandidate::Trickle() {
ASSERT_TRUE(NS_SUCCEEDED(res));
}
class IceGatherTest : public StunTest {
class WebRtcIceGatherTest : public StunTest {
public:
void SetUp() override {
StunTest::SetUp();
@ -1453,9 +1453,9 @@ class IceGatherTest : public StunTest {
mozilla::UniquePtr<IceTestPeer> peer_;
};
class IceConnectTest : public StunTest {
class WebRtcIceConnectTest : public StunTest {
public:
IceConnectTest() :
WebRtcIceConnectTest() :
initted_(false),
use_nat_(false),
filtering_type_(TestNat::ENDPOINT_INDEPENDENT),
@ -1676,7 +1676,7 @@ class IceConnectTest : public StunTest {
p2_->Connect(p1_.get(), TRICKLE_NONE, false);
p1_->Connect(p2_.get(), TRICKLE_NONE, true);
test_utils_->sts_target()->Dispatch(WrapRunnable(this,
&IceConnectTest::CloseP1),
&WebRtcIceConnectTest::CloseP1),
NS_DISPATCH_SYNC);
p2_->StartChecks();
@ -1706,12 +1706,12 @@ class IceConnectTest : public StunTest {
bool block_udp_;
};
class PrioritizerTest : public StunTest {
class WebRtcIcePrioritizerTest : public StunTest {
public:
PrioritizerTest():
WebRtcIcePrioritizerTest():
prioritizer_(nullptr) {}
~PrioritizerTest() {
~WebRtcIcePrioritizerTest() {
if (prioritizer_) {
nr_interface_prioritizer_destroy(&prioritizer_);
}
@ -1754,9 +1754,9 @@ class PrioritizerTest : public StunTest {
nr_interface_prioritizer *prioritizer_;
};
class PacketFilterTest : public StunTest {
class WebRtcIcePacketFilterTest : public StunTest {
public:
PacketFilterTest(): filter_(nullptr) {}
WebRtcIcePacketFilterTest(): filter_(nullptr) {}
void SetUp() {
StunTest::SetUp();
@ -1771,7 +1771,7 @@ class PacketFilterTest : public StunTest {
void TearDown() {
test_utils_->sts_target()->Dispatch(WrapRunnable(this,
&PacketFilterTest::TearDown_s),
&WebRtcIcePacketFilterTest::TearDown_s),
NS_DISPATCH_SYNC);
StunTest::TearDown();
}
@ -1819,7 +1819,7 @@ class PacketFilterTest : public StunTest {
};
} // end namespace
TEST_F(IceGatherTest, TestGatherFakeStunServerHostnameNoResolver) {
TEST_F(WebRtcIceGatherTest, TestGatherFakeStunServerHostnameNoResolver) {
if (stun_server_hostname_.empty()) {
return;
}
@ -1829,7 +1829,7 @@ TEST_F(IceGatherTest, TestGatherFakeStunServerHostnameNoResolver) {
Gather();
}
TEST_F(IceGatherTest, TestGatherFakeStunServerTcpHostnameNoResolver) {
TEST_F(WebRtcIceGatherTest, TestGatherFakeStunServerTcpHostnameNoResolver) {
if (stun_server_hostname_.empty()) {
return;
}
@ -1841,7 +1841,7 @@ TEST_F(IceGatherTest, TestGatherFakeStunServerTcpHostnameNoResolver) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, " TCP "));
}
TEST_F(IceGatherTest, TestGatherFakeStunServerIpAddress) {
TEST_F(WebRtcIceGatherTest, TestGatherFakeStunServerIpAddress) {
if (stun_server_address_.empty()) {
return;
}
@ -1852,7 +1852,7 @@ TEST_F(IceGatherTest, TestGatherFakeStunServerIpAddress) {
Gather();
}
TEST_F(IceGatherTest, TestGatherStunServerIpAddressDefaultRouteOnly) {
TEST_F(WebRtcIceGatherTest, TestGatherStunServerIpAddressDefaultRouteOnly) {
if (stun_server_address_.empty()) {
return;
}
@ -1865,7 +1865,7 @@ TEST_F(IceGatherTest, TestGatherStunServerIpAddressDefaultRouteOnly) {
ASSERT_FALSE(StreamHasMatchingCandidate(0, " host "));
}
TEST_F(IceGatherTest, TestGatherFakeStunServerHostname) {
TEST_F(WebRtcIceGatherTest, TestGatherFakeStunServerHostname) {
if (stun_server_hostname_.empty()) {
return;
}
@ -1876,14 +1876,14 @@ TEST_F(IceGatherTest, TestGatherFakeStunServerHostname) {
Gather();
}
TEST_F(IceGatherTest, TestGatherFakeStunBogusHostname) {
TEST_F(WebRtcIceGatherTest, TestGatherFakeStunBogusHostname) {
EnsurePeer();
peer_->SetStunServer(kBogusStunServerHostname, kDefaultStunServerPort);
peer_->SetFakeResolver(stun_server_address_, stun_server_hostname_);
Gather();
}
TEST_F(IceGatherTest, TestGatherDNSStunServerIpAddress) {
TEST_F(WebRtcIceGatherTest, TestGatherDNSStunServerIpAddress) {
if (stun_server_address_.empty()) {
return;
}
@ -1896,7 +1896,7 @@ TEST_F(IceGatherTest, TestGatherDNSStunServerIpAddress) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, "typ srflx raddr"));
}
TEST_F(IceGatherTest, TestGatherDNSStunServerIpAddressTcp) {
TEST_F(WebRtcIceGatherTest, TestGatherDNSStunServerIpAddressTcp) {
if (stun_server_address_.empty()) {
return;
}
@ -1913,7 +1913,7 @@ TEST_F(IceGatherTest, TestGatherDNSStunServerIpAddressTcp) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, "tcptype active", " 9 "));
}
TEST_F(IceGatherTest, TestGatherDNSStunServerHostname) {
TEST_F(WebRtcIceGatherTest, TestGatherDNSStunServerHostname) {
if (stun_server_hostname_.empty()) {
return;
}
@ -1926,7 +1926,7 @@ TEST_F(IceGatherTest, TestGatherDNSStunServerHostname) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, "typ srflx raddr"));
}
TEST_F(IceGatherTest, TestGatherDNSStunServerHostnameTcp) {
TEST_F(WebRtcIceGatherTest, TestGatherDNSStunServerHostnameTcp) {
EnsurePeer(ICE_TEST_PEER_OFFERER | ICE_TEST_PEER_ENABLED_TCP);
peer_->SetStunServer(stun_server_hostname_, kDefaultStunServerPort,
kNrIceTransportTcp);
@ -1939,7 +1939,7 @@ TEST_F(IceGatherTest, TestGatherDNSStunServerHostnameTcp) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, "tcptype active", " 9 "));
}
TEST_F(IceGatherTest, TestGatherDNSStunServerHostnameBothUdpTcp) {
TEST_F(WebRtcIceGatherTest, TestGatherDNSStunServerHostnameBothUdpTcp) {
if (stun_server_hostname_.empty()) {
return;
}
@ -1958,7 +1958,7 @@ TEST_F(IceGatherTest, TestGatherDNSStunServerHostnameBothUdpTcp) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, " TCP "));
}
TEST_F(IceGatherTest, TestGatherDNSStunServerIpAddressBothUdpTcp) {
TEST_F(WebRtcIceGatherTest, TestGatherDNSStunServerIpAddressBothUdpTcp) {
if (stun_server_address_.empty()) {
return;
}
@ -1977,7 +1977,7 @@ TEST_F(IceGatherTest, TestGatherDNSStunServerIpAddressBothUdpTcp) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, " TCP "));
}
TEST_F(IceGatherTest, TestGatherDNSStunBogusHostname) {
TEST_F(WebRtcIceGatherTest, TestGatherDNSStunBogusHostname) {
EnsurePeer();
peer_->SetStunServer(kBogusStunServerHostname, kDefaultStunServerPort);
peer_->SetDNSResolver();
@ -1985,7 +1985,7 @@ TEST_F(IceGatherTest, TestGatherDNSStunBogusHostname) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, " UDP "));
}
TEST_F(IceGatherTest, TestGatherDNSStunBogusHostnameTcp) {
TEST_F(WebRtcIceGatherTest, TestGatherDNSStunBogusHostnameTcp) {
EnsurePeer(ICE_TEST_PEER_OFFERER | ICE_TEST_PEER_ENABLED_TCP);
peer_->SetStunServer(kBogusStunServerHostname, kDefaultStunServerPort,
kNrIceTransportTcp);
@ -1994,7 +1994,7 @@ TEST_F(IceGatherTest, TestGatherDNSStunBogusHostnameTcp) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, " TCP "));
}
TEST_F(IceGatherTest, TestDefaultCandidate) {
TEST_F(WebRtcIceGatherTest, TestDefaultCandidate) {
EnsurePeer();
peer_->SetStunServer(stun_server_hostname_, kDefaultStunServerPort);
Gather();
@ -2002,7 +2002,7 @@ TEST_F(IceGatherTest, TestDefaultCandidate) {
ASSERT_TRUE(NS_SUCCEEDED(peer_->GetDefaultCandidate(0, &default_candidate)));
}
TEST_F(IceGatherTest, TestGatherTurn) {
TEST_F(WebRtcIceGatherTest, TestGatherTurn) {
EnsurePeer();
if (turn_server_.empty())
return;
@ -2011,7 +2011,7 @@ TEST_F(IceGatherTest, TestGatherTurn) {
Gather();
}
TEST_F(IceGatherTest, TestGatherTurnTcp) {
TEST_F(WebRtcIceGatherTest, TestGatherTurnTcp) {
EnsurePeer();
if (turn_server_.empty())
return;
@ -2020,7 +2020,7 @@ TEST_F(IceGatherTest, TestGatherTurnTcp) {
Gather();
}
TEST_F(IceGatherTest, TestGatherDisableComponent) {
TEST_F(WebRtcIceGatherTest, TestGatherDisableComponent) {
if (stun_server_hostname_.empty()) {
return;
}
@ -2039,12 +2039,12 @@ TEST_F(IceGatherTest, TestGatherDisableComponent) {
}
}
TEST_F(IceGatherTest, TestGatherVerifyNoLoopback) {
TEST_F(WebRtcIceGatherTest, TestGatherVerifyNoLoopback) {
Gather();
ASSERT_FALSE(StreamHasMatchingCandidate(0, "127.0.0.1"));
}
TEST_F(IceGatherTest, TestGatherAllowLoopback) {
TEST_F(WebRtcIceGatherTest, TestGatherAllowLoopback) {
// Set up peer with loopback allowed.
peer_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, true);
peer_->AddStream(1);
@ -2052,7 +2052,7 @@ TEST_F(IceGatherTest, TestGatherAllowLoopback) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, "127.0.0.1"));
}
TEST_F(IceGatherTest, TestGatherTcpDisabled) {
TEST_F(WebRtcIceGatherTest, TestGatherTcpDisabled) {
// Set up peer with tcp disabled.
peer_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, false, false);
peer_->AddStream(1);
@ -2063,25 +2063,25 @@ TEST_F(IceGatherTest, TestGatherTcpDisabled) {
// Verify that a bogus candidate doesn't cause crashes on the
// main thread. See bug 856433.
TEST_F(IceGatherTest, TestBogusCandidate) {
TEST_F(WebRtcIceGatherTest, TestBogusCandidate) {
Gather();
peer_->ParseCandidate(0, kBogusIceCandidate);
}
TEST_F(IceGatherTest, VerifyTestStunServer) {
TEST_F(WebRtcIceGatherTest, VerifyTestStunServer) {
UseFakeStunUdpServerWithResponse("192.0.2.133", 3333);
Gather();
ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.2.133 3333 "));
}
TEST_F(IceGatherTest, VerifyTestStunTcpServer) {
TEST_F(WebRtcIceGatherTest, VerifyTestStunTcpServer) {
UseFakeStunTcpServerWithResponse("192.0.2.233", 3333);
Gather();
ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.2.233 3333 typ srflx",
" tcptype "));
}
TEST_F(IceGatherTest, VerifyTestStunServerV6) {
TEST_F(WebRtcIceGatherTest, VerifyTestStunServerV6) {
if (!TestStunServer::GetInstance(AF_INET6)) {
// No V6 addresses
return;
@ -2091,13 +2091,13 @@ TEST_F(IceGatherTest, VerifyTestStunServerV6) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, " beef:: 3333 "));
}
TEST_F(IceGatherTest, VerifyTestStunServerFQDN) {
TEST_F(WebRtcIceGatherTest, VerifyTestStunServerFQDN) {
UseFakeStunUdpServerWithResponse("192.0.2.133", 3333, "stun.example.com");
Gather();
ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.2.133 3333 "));
}
TEST_F(IceGatherTest, VerifyTestStunServerV6FQDN) {
TEST_F(WebRtcIceGatherTest, VerifyTestStunServerV6FQDN) {
if (!TestStunServer::GetInstance(AF_INET6)) {
// No V6 addresses
return;
@ -2107,13 +2107,13 @@ TEST_F(IceGatherTest, VerifyTestStunServerV6FQDN) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, " beef:: 3333 "));
}
TEST_F(IceGatherTest, TestStunServerReturnsWildcardAddr) {
TEST_F(WebRtcIceGatherTest, TestStunServerReturnsWildcardAddr) {
UseFakeStunUdpServerWithResponse("0.0.0.0", 3333);
Gather(kDefaultTimeout * 3);
ASSERT_FALSE(StreamHasMatchingCandidate(0, " 0.0.0.0 "));
}
TEST_F(IceGatherTest, TestStunServerReturnsWildcardAddrV6) {
TEST_F(WebRtcIceGatherTest, TestStunServerReturnsWildcardAddrV6) {
if (!TestStunServer::GetInstance(AF_INET6)) {
// No V6 addresses
return;
@ -2123,19 +2123,19 @@ TEST_F(IceGatherTest, TestStunServerReturnsWildcardAddrV6) {
ASSERT_FALSE(StreamHasMatchingCandidate(0, " :: "));
}
TEST_F(IceGatherTest, TestStunServerReturnsPort0) {
TEST_F(WebRtcIceGatherTest, TestStunServerReturnsPort0) {
UseFakeStunUdpServerWithResponse("192.0.2.133", 0);
Gather(kDefaultTimeout * 3);
ASSERT_FALSE(StreamHasMatchingCandidate(0, " 192.0.2.133 0 "));
}
TEST_F(IceGatherTest, TestStunServerReturnsLoopbackAddr) {
TEST_F(WebRtcIceGatherTest, TestStunServerReturnsLoopbackAddr) {
UseFakeStunUdpServerWithResponse("127.0.0.133", 3333);
Gather(kDefaultTimeout * 3);
ASSERT_FALSE(StreamHasMatchingCandidate(0, " 127.0.0.133 "));
}
TEST_F(IceGatherTest, TestStunServerReturnsLoopbackAddrV6) {
TEST_F(WebRtcIceGatherTest, TestStunServerReturnsLoopbackAddrV6) {
if (!TestStunServer::GetInstance(AF_INET6)) {
// No V6 addresses
return;
@ -2145,7 +2145,7 @@ TEST_F(IceGatherTest, TestStunServerReturnsLoopbackAddrV6) {
ASSERT_FALSE(StreamHasMatchingCandidate(0, " ::1 "));
}
TEST_F(IceGatherTest, TestStunServerTrickle) {
TEST_F(WebRtcIceGatherTest, TestStunServerTrickle) {
UseFakeStunUdpServerWithResponse("192.0.2.1", 3333);
TestStunServer::GetInstance(AF_INET)->SetDropInitialPackets(3);
Gather(0);
@ -2156,7 +2156,7 @@ TEST_F(IceGatherTest, TestStunServerTrickle) {
// Test default route only with our fake STUN server and
// apparently NATted.
TEST_F(IceGatherTest, TestFakeStunServerNatedDefaultRouteOnly) {
TEST_F(WebRtcIceGatherTest, TestFakeStunServerNatedDefaultRouteOnly) {
peer_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, false, false, false, true);
peer_->AddStream(1);
UseFakeStunUdpServerWithResponse("192.0.2.1", 3333);
@ -2174,7 +2174,7 @@ TEST_F(IceGatherTest, TestFakeStunServerNatedDefaultRouteOnly) {
// Test default route only with our fake STUN server and
// apparently non-NATted.
TEST_F(IceGatherTest, TestFakeStunServerNoNatDefaultRouteOnly) {
TEST_F(WebRtcIceGatherTest, TestFakeStunServerNoNatDefaultRouteOnly) {
peer_ = MakeUnique<IceTestPeer>("P1", test_utils_, true, false, false, false, true);
peer_->AddStream(1);
UseTestStunServer();
@ -2185,7 +2185,7 @@ TEST_F(IceGatherTest, TestFakeStunServerNoNatDefaultRouteOnly) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, "srflx"));
}
TEST_F(IceGatherTest, TestStunTcpServerTrickle) {
TEST_F(WebRtcIceGatherTest, TestStunTcpServerTrickle) {
UseFakeStunTcpServerWithResponse("192.0.3.1", 3333);
TestStunTcpServer::GetInstance(AF_INET)->SetDelay(500);
Gather(0);
@ -2194,7 +2194,7 @@ TEST_F(IceGatherTest, TestStunTcpServerTrickle) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype "));
}
TEST_F(IceGatherTest, TestStunTcpAndUdpServerTrickle) {
TEST_F(WebRtcIceGatherTest, TestStunTcpAndUdpServerTrickle) {
UseFakeStunUdpTcpServersWithResponse("192.0.2.1", 3333, "192.0.3.1", 3333);
TestStunServer::GetInstance(AF_INET)->SetDropInitialPackets(3);
TestStunTcpServer::GetInstance(AF_INET)->SetDelay(500);
@ -2206,31 +2206,31 @@ TEST_F(IceGatherTest, TestStunTcpAndUdpServerTrickle) {
ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype "));
}
TEST_F(IceConnectTest, TestGather) {
TEST_F(WebRtcIceConnectTest, TestGather) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
}
TEST_F(IceConnectTest, TestGatherTcp) {
TEST_F(WebRtcIceConnectTest, TestGatherTcp) {
Init(false, true);
AddStream("first", 1);
ASSERT_TRUE(Gather());
}
TEST_F(IceConnectTest, TestGatherAutoPrioritize) {
TEST_F(WebRtcIceConnectTest, TestGatherAutoPrioritize) {
Init(false, false);
AddStream("first", 1);
ASSERT_TRUE(Gather());
}
TEST_F(IceConnectTest, TestConnect) {
TEST_F(WebRtcIceConnectTest, TestConnect) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
Connect();
}
TEST_F(IceConnectTest, TestConnectTcp) {
TEST_F(WebRtcIceConnectTest, TestConnectTcp) {
Init(false, true);
AddStream("first", 1);
ASSERT_TRUE(Gather());
@ -2242,7 +2242,7 @@ TEST_F(IceConnectTest, TestConnectTcp) {
//TCP SO tests works on localhost only with delay applied:
// tc qdisc add dev lo root netem delay 10ms
TEST_F(IceConnectTest, DISABLED_TestConnectTcpSo) {
TEST_F(WebRtcIceConnectTest, DISABLED_TestConnectTcpSo) {
Init(false, true);
AddStream("first", 1);
ASSERT_TRUE(Gather());
@ -2253,7 +2253,7 @@ TEST_F(IceConnectTest, DISABLED_TestConnectTcpSo) {
}
// Disabled because this breaks with hairpinning.
TEST_F(IceConnectTest, DISABLED_TestConnectDefaultRouteOnly) {
TEST_F(WebRtcIceConnectTest, DISABLED_TestConnectDefaultRouteOnly) {
Init(false, false, true);
AddStream("first", 1);
ASSERT_TRUE(Gather());
@ -2262,7 +2262,7 @@ TEST_F(IceConnectTest, DISABLED_TestConnectDefaultRouteOnly) {
Connect();
}
TEST_F(IceConnectTest, TestLoopbackOnlySortOf) {
TEST_F(WebRtcIceConnectTest, TestLoopbackOnlySortOf) {
Init(true, false);
AddStream("first", 1);
SetCandidateFilter(IsLoopbackCandidate);
@ -2271,7 +2271,7 @@ TEST_F(IceConnectTest, TestLoopbackOnlySortOf) {
Connect();
}
TEST_F(IceConnectTest, TestConnectBothControllingP1Wins) {
TEST_F(WebRtcIceConnectTest, TestConnectBothControllingP1Wins) {
AddStream("first", 1);
p1_->SetTiebreaker(1);
p2_->SetTiebreaker(0);
@ -2281,7 +2281,7 @@ TEST_F(IceConnectTest, TestConnectBothControllingP1Wins) {
Connect();
}
TEST_F(IceConnectTest, TestConnectBothControllingP2Wins) {
TEST_F(WebRtcIceConnectTest, TestConnectBothControllingP2Wins) {
AddStream("first", 1);
p1_->SetTiebreaker(0);
p2_->SetTiebreaker(1);
@ -2291,14 +2291,14 @@ TEST_F(IceConnectTest, TestConnectBothControllingP2Wins) {
Connect();
}
TEST_F(IceConnectTest, TestConnectIceLiteOfferer) {
TEST_F(WebRtcIceConnectTest, TestConnectIceLiteOfferer) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
p1_->SimulateIceLite();
Connect();
}
TEST_F(IceConnectTest, TestTrickleBothControllingP1Wins) {
TEST_F(WebRtcIceConnectTest, TestTrickleBothControllingP1Wins) {
AddStream("first", 1);
p1_->SetTiebreaker(1);
p2_->SetTiebreaker(0);
@ -2312,7 +2312,7 @@ TEST_F(IceConnectTest, TestTrickleBothControllingP1Wins) {
AssertCheckingReached();
}
TEST_F(IceConnectTest, TestTrickleBothControllingP2Wins) {
TEST_F(WebRtcIceConnectTest, TestTrickleBothControllingP2Wins) {
AddStream("first", 1);
p1_->SetTiebreaker(0);
p2_->SetTiebreaker(1);
@ -2326,7 +2326,7 @@ TEST_F(IceConnectTest, TestTrickleBothControllingP2Wins) {
AssertCheckingReached();
}
TEST_F(IceConnectTest, TestTrickleIceLiteOfferer) {
TEST_F(WebRtcIceConnectTest, TestTrickleIceLiteOfferer) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
p1_->SimulateIceLite();
@ -2337,7 +2337,7 @@ TEST_F(IceConnectTest, TestTrickleIceLiteOfferer) {
AssertCheckingReached();
}
TEST_F(IceConnectTest, TestGatherFullCone) {
TEST_F(WebRtcIceConnectTest, TestGatherFullCone) {
AddStream("first", 1);
UseNat();
SetFilteringType(TestNat::ENDPOINT_INDEPENDENT);
@ -2345,7 +2345,7 @@ TEST_F(IceConnectTest, TestGatherFullCone) {
ASSERT_TRUE(Gather());
}
TEST_F(IceConnectTest, TestGatherFullConeAutoPrioritize) {
TEST_F(WebRtcIceConnectTest, TestGatherFullConeAutoPrioritize) {
Init(true, false);
AddStream("first", 1);
UseNat();
@ -2355,7 +2355,7 @@ TEST_F(IceConnectTest, TestGatherFullConeAutoPrioritize) {
}
TEST_F(IceConnectTest, TestConnectFullCone) {
TEST_F(WebRtcIceConnectTest, TestConnectFullCone) {
AddStream("first", 1);
UseNat();
SetFilteringType(TestNat::ENDPOINT_INDEPENDENT);
@ -2366,7 +2366,7 @@ TEST_F(IceConnectTest, TestConnectFullCone) {
Connect();
}
TEST_F(IceConnectTest, TestConnectNoNatRouteOnly) {
TEST_F(WebRtcIceConnectTest, TestConnectNoNatRouteOnly) {
Init(false, false, true);
AddStream("first", 1);
UseTestStunServer();
@ -2379,7 +2379,7 @@ TEST_F(IceConnectTest, TestConnectNoNatRouteOnly) {
Connect();
}
TEST_F(IceConnectTest, TestConnectFullConeDefaultRouteOnly) {
TEST_F(WebRtcIceConnectTest, TestConnectFullConeDefaultRouteOnly) {
Init(false, false, true);
AddStream("first", 1);
UseNat();
@ -2391,7 +2391,7 @@ TEST_F(IceConnectTest, TestConnectFullConeDefaultRouteOnly) {
Connect();
}
TEST_F(IceConnectTest, TestGatherAddressRestrictedCone) {
TEST_F(WebRtcIceConnectTest, TestGatherAddressRestrictedCone) {
AddStream("first", 1);
UseNat();
SetFilteringType(TestNat::ADDRESS_DEPENDENT);
@ -2399,7 +2399,7 @@ TEST_F(IceConnectTest, TestGatherAddressRestrictedCone) {
ASSERT_TRUE(Gather());
}
TEST_F(IceConnectTest, TestConnectAddressRestrictedCone) {
TEST_F(WebRtcIceConnectTest, TestConnectAddressRestrictedCone) {
AddStream("first", 1);
UseNat();
SetFilteringType(TestNat::ADDRESS_DEPENDENT);
@ -2410,7 +2410,7 @@ TEST_F(IceConnectTest, TestConnectAddressRestrictedCone) {
Connect();
}
TEST_F(IceConnectTest, TestGatherPortRestrictedCone) {
TEST_F(WebRtcIceConnectTest, TestGatherPortRestrictedCone) {
AddStream("first", 1);
UseNat();
SetFilteringType(TestNat::PORT_DEPENDENT);
@ -2418,7 +2418,7 @@ TEST_F(IceConnectTest, TestGatherPortRestrictedCone) {
ASSERT_TRUE(Gather());
}
TEST_F(IceConnectTest, TestConnectPortRestrictedCone) {
TEST_F(WebRtcIceConnectTest, TestConnectPortRestrictedCone) {
AddStream("first", 1);
UseNat();
SetFilteringType(TestNat::PORT_DEPENDENT);
@ -2429,7 +2429,7 @@ TEST_F(IceConnectTest, TestConnectPortRestrictedCone) {
Connect();
}
TEST_F(IceConnectTest, TestGatherSymmetricNat) {
TEST_F(WebRtcIceConnectTest, TestGatherSymmetricNat) {
AddStream("first", 1);
UseNat();
SetFilteringType(TestNat::PORT_DEPENDENT);
@ -2437,7 +2437,7 @@ TEST_F(IceConnectTest, TestGatherSymmetricNat) {
ASSERT_TRUE(Gather());
}
TEST_F(IceConnectTest, TestConnectSymmetricNat) {
TEST_F(WebRtcIceConnectTest, TestConnectSymmetricNat) {
if (turn_server_.empty())
return;
@ -2455,7 +2455,7 @@ TEST_F(IceConnectTest, TestConnectSymmetricNat) {
Connect();
}
TEST_F(IceConnectTest, TestGatherNatBlocksUDP) {
TEST_F(WebRtcIceConnectTest, TestGatherNatBlocksUDP) {
if (turn_server_.empty())
return;
@ -2476,7 +2476,7 @@ TEST_F(IceConnectTest, TestGatherNatBlocksUDP) {
ASSERT_TRUE(Gather(kDefaultTimeout * 3));
}
TEST_F(IceConnectTest, TestConnectNatBlocksUDP) {
TEST_F(WebRtcIceConnectTest, TestConnectNatBlocksUDP) {
if (turn_server_.empty())
return;
@ -2503,13 +2503,13 @@ TEST_F(IceConnectTest, TestConnectNatBlocksUDP) {
Connect();
}
TEST_F(IceConnectTest, TestConnectTwoComponents) {
TEST_F(WebRtcIceConnectTest, TestConnectTwoComponents) {
AddStream("first", 2);
ASSERT_TRUE(Gather());
Connect();
}
TEST_F(IceConnectTest, TestConnectTwoComponentsDisableSecond) {
TEST_F(WebRtcIceConnectTest, TestConnectTwoComponentsDisableSecond) {
AddStream("first", 2);
ASSERT_TRUE(Gather());
p1_->DisableComponent(0, 2);
@ -2518,7 +2518,7 @@ TEST_F(IceConnectTest, TestConnectTwoComponentsDisableSecond) {
}
TEST_F(IceConnectTest, TestConnectP2ThenP1) {
TEST_F(WebRtcIceConnectTest, TestConnectP2ThenP1) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
ConnectP2();
@ -2527,7 +2527,7 @@ TEST_F(IceConnectTest, TestConnectP2ThenP1) {
WaitForComplete();
}
TEST_F(IceConnectTest, TestConnectP2ThenP1Trickle) {
TEST_F(WebRtcIceConnectTest, TestConnectP2ThenP1Trickle) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
ConnectP2();
@ -2537,7 +2537,7 @@ TEST_F(IceConnectTest, TestConnectP2ThenP1Trickle) {
WaitForComplete();
}
TEST_F(IceConnectTest, TestConnectP2ThenP1TrickleTwoComponents) {
TEST_F(WebRtcIceConnectTest, TestConnectP2ThenP1TrickleTwoComponents) {
AddStream("first", 1);
AddStream("second", 2);
ASSERT_TRUE(Gather());
@ -2552,14 +2552,14 @@ TEST_F(IceConnectTest, TestConnectP2ThenP1TrickleTwoComponents) {
WaitForComplete(2);
}
TEST_F(IceConnectTest, TestConnectAutoPrioritize) {
TEST_F(WebRtcIceConnectTest, TestConnectAutoPrioritize) {
Init(false, false);
AddStream("first", 1);
ASSERT_TRUE(Gather());
Connect();
}
TEST_F(IceConnectTest, TestConnectTrickleOneStreamOneComponent) {
TEST_F(WebRtcIceConnectTest, TestConnectTrickleOneStreamOneComponent) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
ConnectTrickle();
@ -2569,7 +2569,7 @@ TEST_F(IceConnectTest, TestConnectTrickleOneStreamOneComponent) {
AssertCheckingReached();
}
TEST_F(IceConnectTest, TestConnectTrickleTwoStreamsOneComponent) {
TEST_F(WebRtcIceConnectTest, TestConnectTrickleTwoStreamsOneComponent) {
AddStream("first", 1);
AddStream("second", 1);
ASSERT_TRUE(Gather());
@ -2650,7 +2650,7 @@ void DropTrickleCandidates(
std::vector<SchedulableTrickleCandidate*>& candidates) {
}
TEST_F(IceConnectTest, TestConnectTrickleAddStreamDuringICE) {
TEST_F(WebRtcIceConnectTest, TestConnectTrickleAddStreamDuringICE) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
ConnectTrickle();
@ -2664,7 +2664,7 @@ TEST_F(IceConnectTest, TestConnectTrickleAddStreamDuringICE) {
AssertCheckingReached();
}
TEST_F(IceConnectTest, TestConnectTrickleAddStreamAfterICE) {
TEST_F(WebRtcIceConnectTest, TestConnectTrickleAddStreamAfterICE) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
ConnectTrickle();
@ -2682,7 +2682,7 @@ TEST_F(IceConnectTest, TestConnectTrickleAddStreamAfterICE) {
AssertCheckingReached();
}
TEST_F(IceConnectTest, RemoveStream) {
TEST_F(WebRtcIceConnectTest, RemoveStream) {
AddStream("first", 1);
AddStream("second", 1);
ASSERT_TRUE(Gather());
@ -2699,7 +2699,7 @@ TEST_F(IceConnectTest, RemoveStream) {
ConnectTrickle();
}
TEST_F(IceConnectTest, P1NoTrickle) {
TEST_F(WebRtcIceConnectTest, P1NoTrickle) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
ConnectTrickle();
@ -2709,7 +2709,7 @@ TEST_F(IceConnectTest, P1NoTrickle) {
ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
}
TEST_F(IceConnectTest, P2NoTrickle) {
TEST_F(WebRtcIceConnectTest, P2NoTrickle) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
ConnectTrickle();
@ -2719,7 +2719,7 @@ TEST_F(IceConnectTest, P2NoTrickle) {
ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
}
TEST_F(IceConnectTest, RemoveAndAddStream) {
TEST_F(WebRtcIceConnectTest, RemoveAndAddStream) {
AddStream("first", 1);
AddStream("second", 1);
ASSERT_TRUE(Gather());
@ -2741,7 +2741,7 @@ TEST_F(IceConnectTest, RemoveAndAddStream) {
ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
}
TEST_F(IceConnectTest, RemoveStreamBeforeGather) {
TEST_F(WebRtcIceConnectTest, RemoveStreamBeforeGather) {
AddStream("first", 1);
AddStream("second", 1);
ASSERT_TRUE(Gather(0));
@ -2754,7 +2754,7 @@ TEST_F(IceConnectTest, RemoveStreamBeforeGather) {
ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
}
TEST_F(IceConnectTest, RemoveStreamDuringGather) {
TEST_F(WebRtcIceConnectTest, RemoveStreamDuringGather) {
AddStream("first", 1);
AddStream("second", 1);
RemoveStream(0);
@ -2766,7 +2766,7 @@ TEST_F(IceConnectTest, RemoveStreamDuringGather) {
ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
}
TEST_F(IceConnectTest, RemoveStreamDuringConnect) {
TEST_F(WebRtcIceConnectTest, RemoveStreamDuringConnect) {
AddStream("first", 1);
AddStream("second", 1);
ASSERT_TRUE(Gather());
@ -2780,7 +2780,7 @@ TEST_F(IceConnectTest, RemoveStreamDuringConnect) {
ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
}
TEST_F(IceConnectTest, TestConnectRealTrickleOneStreamOneComponent) {
TEST_F(WebRtcIceConnectTest, TestConnectRealTrickleOneStreamOneComponent) {
AddStream("first", 1);
AddStream("second", 1);
ASSERT_TRUE(Gather(0));
@ -2791,14 +2791,14 @@ TEST_F(IceConnectTest, TestConnectRealTrickleOneStreamOneComponent) {
AssertCheckingReached();
}
TEST_F(IceConnectTest, TestSendReceive) {
TEST_F(WebRtcIceConnectTest, TestSendReceive) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
Connect();
SendReceive();
}
TEST_F(IceConnectTest, TestSendReceiveTcp) {
TEST_F(WebRtcIceConnectTest, TestSendReceiveTcp) {
Init(false, true);
AddStream("first", 1);
ASSERT_TRUE(Gather());
@ -2811,7 +2811,7 @@ TEST_F(IceConnectTest, TestSendReceiveTcp) {
//TCP SO tests works on localhost only with delay applied:
// tc qdisc add dev lo root netem delay 10ms
TEST_F(IceConnectTest, DISABLED_TestSendReceiveTcpSo) {
TEST_F(WebRtcIceConnectTest, DISABLED_TestSendReceiveTcpSo) {
Init(false, true);
AddStream("first", 1);
ASSERT_TRUE(Gather());
@ -2822,7 +2822,7 @@ TEST_F(IceConnectTest, DISABLED_TestSendReceiveTcpSo) {
SendReceive();
}
TEST_F(IceConnectTest, TestConnectTurn) {
TEST_F(WebRtcIceConnectTest, TestConnectTurn) {
if (turn_server_.empty())
return;
@ -2833,7 +2833,7 @@ TEST_F(IceConnectTest, TestConnectTurn) {
Connect();
}
TEST_F(IceConnectTest, TestConnectTurnWithDelay) {
TEST_F(WebRtcIceConnectTest, TestConnectTurnWithDelay) {
if (turn_server_.empty())
return;
@ -2849,7 +2849,7 @@ TEST_F(IceConnectTest, TestConnectTurnWithDelay) {
WaitForComplete();
}
TEST_F(IceConnectTest, TestConnectTurnWithNormalTrickleDelay) {
TEST_F(WebRtcIceConnectTest, TestConnectTurnWithNormalTrickleDelay) {
if (turn_server_.empty())
return;
@ -2866,7 +2866,7 @@ TEST_F(IceConnectTest, TestConnectTurnWithNormalTrickleDelay) {
AssertCheckingReached();
}
TEST_F(IceConnectTest, TestConnectTurnWithNormalTrickleDelayOneSided) {
TEST_F(WebRtcIceConnectTest, TestConnectTurnWithNormalTrickleDelayOneSided) {
if (turn_server_.empty())
return;
@ -2883,7 +2883,7 @@ TEST_F(IceConnectTest, TestConnectTurnWithNormalTrickleDelayOneSided) {
AssertCheckingReached();
}
TEST_F(IceConnectTest, TestConnectTurnWithLargeTrickleDelay) {
TEST_F(WebRtcIceConnectTest, TestConnectTurnWithLargeTrickleDelay) {
if (turn_server_.empty())
return;
@ -2902,7 +2902,7 @@ TEST_F(IceConnectTest, TestConnectTurnWithLargeTrickleDelay) {
AssertCheckingReached();
}
TEST_F(IceConnectTest, TestConnectTurnTcp) {
TEST_F(WebRtcIceConnectTest, TestConnectTurnTcp) {
if (turn_server_.empty())
return;
@ -2913,7 +2913,7 @@ TEST_F(IceConnectTest, TestConnectTurnTcp) {
Connect();
}
TEST_F(IceConnectTest, TestConnectTurnOnly) {
TEST_F(WebRtcIceConnectTest, TestConnectTurnOnly) {
if (turn_server_.empty())
return;
@ -2927,7 +2927,7 @@ TEST_F(IceConnectTest, TestConnectTurnOnly) {
Connect();
}
TEST_F(IceConnectTest, TestConnectTurnTcpOnly) {
TEST_F(WebRtcIceConnectTest, TestConnectTurnTcpOnly) {
if (turn_server_.empty())
return;
@ -2942,7 +2942,7 @@ TEST_F(IceConnectTest, TestConnectTurnTcpOnly) {
Connect();
}
TEST_F(IceConnectTest, TestSendReceiveTurnOnly) {
TEST_F(WebRtcIceConnectTest, TestSendReceiveTurnOnly) {
if (turn_server_.empty())
return;
@ -2957,7 +2957,7 @@ TEST_F(IceConnectTest, TestSendReceiveTurnOnly) {
SendReceive();
}
TEST_F(IceConnectTest, TestSendReceiveTurnTcpOnly) {
TEST_F(WebRtcIceConnectTest, TestSendReceiveTurnTcpOnly) {
if (turn_server_.empty())
return;
@ -2973,7 +2973,7 @@ TEST_F(IceConnectTest, TestSendReceiveTurnTcpOnly) {
SendReceive();
}
TEST_F(IceConnectTest, TestSendReceiveTurnBothOnly) {
TEST_F(WebRtcIceConnectTest, TestSendReceiveTurnBothOnly) {
if (turn_server_.empty())
return;
@ -2998,13 +2998,13 @@ TEST_F(IceConnectTest, TestSendReceiveTurnBothOnly) {
SendReceive();
}
TEST_F(IceConnectTest, TestConnectShutdownOneSide) {
TEST_F(WebRtcIceConnectTest, TestConnectShutdownOneSide) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
ConnectThenDelete();
}
TEST_F(IceConnectTest, TestPollCandPairsBeforeConnect) {
TEST_F(WebRtcIceConnectTest, TestPollCandPairsBeforeConnect) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
@ -3019,7 +3019,7 @@ TEST_F(IceConnectTest, TestPollCandPairsBeforeConnect) {
ASSERT_EQ(0U, pairs.size());
}
TEST_F(IceConnectTest, TestPollCandPairsAfterConnect) {
TEST_F(WebRtcIceConnectTest, TestPollCandPairsAfterConnect) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
Connect();
@ -3042,7 +3042,7 @@ TEST_F(IceConnectTest, TestPollCandPairsAfterConnect) {
ASSERT_TRUE(ContainsSucceededPair(pairs));
}
TEST_F(IceConnectTest, TestHostCandPairingFilter) {
TEST_F(WebRtcIceConnectTest, TestHostCandPairingFilter) {
AddStream("first", 1);
ASSERT_TRUE(Gather(kDefaultTimeout, false));
SetCandidateFilter(IsIpv4Candidate);
@ -3070,7 +3070,7 @@ TEST_F(IceConnectTest, TestHostCandPairingFilter) {
}
}
TEST_F(IceConnectTest, TestSrflxCandPairingFilter) {
TEST_F(WebRtcIceConnectTest, TestSrflxCandPairingFilter) {
if (stun_server_address_.empty()) {
return;
}
@ -3112,7 +3112,7 @@ TEST_F(IceConnectTest, TestSrflxCandPairingFilter) {
}
}
TEST_F(IceConnectTest, TestPollCandPairsDuringConnect) {
TEST_F(WebRtcIceConnectTest, TestPollCandPairsDuringConnect) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
@ -3137,7 +3137,7 @@ TEST_F(IceConnectTest, TestPollCandPairsDuringConnect) {
ASSERT_TRUE(ContainsSucceededPair(pairs2));
}
TEST_F(IceConnectTest, TestRLogRingBuffer) {
TEST_F(WebRtcIceConnectTest, TestRLogRingBuffer) {
AddStream("first", 1);
ASSERT_TRUE(Gather());
@ -3178,7 +3178,7 @@ TEST_F(IceConnectTest, TestRLogRingBuffer) {
}
}
TEST_F(PrioritizerTest, TestPrioritizer) {
TEST_F(WebRtcIcePrioritizerTest, TestPrioritizer) {
SetPriorizer(::mozilla::CreateInterfacePrioritizer());
AddInterface("0", NR_INTERFACE_TYPE_VPN, 100); // unknown vpn
@ -3209,17 +3209,17 @@ TEST_F(PrioritizerTest, TestPrioritizer) {
HasLowerPreference("5", "4");
}
TEST_F(PacketFilterTest, TestSendNonStunPacket) {
TEST_F(WebRtcIcePacketFilterTest, TestSendNonStunPacket) {
const unsigned char data[] = "12345abcde";
TestOutgoing(data, sizeof(data), 123, 45, false);
}
TEST_F(PacketFilterTest, TestRecvNonStunPacket) {
TEST_F(WebRtcIcePacketFilterTest, TestRecvNonStunPacket) {
const unsigned char data[] = "12345abcde";
TestIncoming(data, sizeof(data), 123, 45, false);
}
TEST_F(PacketFilterTest, TestSendStunPacket) {
TEST_F(WebRtcIcePacketFilterTest, TestSendStunPacket) {
nr_stun_message *msg;
ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
@ -3228,7 +3228,7 @@ TEST_F(PacketFilterTest, TestSendStunPacket) {
ASSERT_EQ(0, nr_stun_message_destroy(&msg));
}
TEST_F(PacketFilterTest, TestRecvStunPacketWithoutAPendingId) {
TEST_F(WebRtcIcePacketFilterTest, TestRecvStunPacketWithoutAPendingId) {
nr_stun_message *msg;
ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
@ -3245,7 +3245,7 @@ TEST_F(PacketFilterTest, TestRecvStunPacketWithoutAPendingId) {
ASSERT_EQ(0, nr_stun_message_destroy(&msg));
}
TEST_F(PacketFilterTest, TestRecvStunPacketWithoutAPendingAddress) {
TEST_F(WebRtcIcePacketFilterTest, TestRecvStunPacketWithoutAPendingAddress) {
nr_stun_message *msg;
ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
@ -3261,7 +3261,7 @@ TEST_F(PacketFilterTest, TestRecvStunPacketWithoutAPendingAddress) {
ASSERT_EQ(0, nr_stun_message_destroy(&msg));
}
TEST_F(PacketFilterTest, TestRecvStunPacketWithPendingIdAndAddress) {
TEST_F(WebRtcIcePacketFilterTest, TestRecvStunPacketWithPendingIdAndAddress) {
nr_stun_message *msg;
ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
@ -3295,7 +3295,7 @@ TEST_F(PacketFilterTest, TestRecvStunPacketWithPendingIdAndAddress) {
ASSERT_EQ(0, nr_stun_message_destroy(&msg));
}
TEST_F(PacketFilterTest, TestSendNonRequestStunPacket) {
TEST_F(WebRtcIcePacketFilterTest, TestSendNonRequestStunPacket) {
nr_stun_message *msg;
ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
@ -3320,7 +3320,7 @@ TEST_F(PacketFilterTest, TestSendNonRequestStunPacket) {
ASSERT_EQ(0, nr_stun_message_destroy(&msg));
}
TEST(InternalsTest, TestAddBogusAttribute) {
TEST(WebRtcIceInternalsTest, TestAddBogusAttribute) {
nr_stun_message *req;
ASSERT_EQ(0, nr_stun_message_create(&req));
Data *data;

View File

@ -4,8 +4,8 @@ set -x -e
# Inputs, with defaults
# mozharness builds use three repositories: gecko (source), mozharness (build
# scripts) and tools (miscellaneous) for each, specify *_REPOSITORY. If the
# mozharness builds use two repositories: gecko (source)
# and build-tools (miscellaneous) for each, specify *_REPOSITORY. If the
# revision is not in the standard repo for the codebase, specify *_BASE_REPO as
# the canonical repo to clone and *_HEAD_REPO as the repo containing the
# desired revision. For Mercurial clones, only *_HEAD_REV is required; for Git

View File

@ -0,0 +1,15 @@
FROM taskcluster/centos6-build-upd:0.1.3.20160122142300
MAINTAINER Varun Joshi <varunj.1011@gmail.com>
ADD bin /home/worker/bin
ADD .hgrc /home/worker/.hgrc
RUN chmod +x /home/worker/bin/*
# Generate machine uuid file (like how desktop-build does)
RUN dbus-uuidgen --ensure=/var/lib/dbus/machine-id
ADD oauth.txt /home/worker
ADD buildprops.json /home/worker
ENV MOZ_AUTOMATION=1
CMD ["/bin/bash", "--login"]

View File

@ -0,0 +1,26 @@
#! /bin/bash -vex
set -x -e -v
# TODO: when bug 1093833 is solved and tasks can run as non-root, reduce this
# to a simple fail-if-root check
if [ $(id -u) = 0 ]; then
# each of the caches we have mounted are owned by root, so update that ownership
# to 'worker'
for cache in /home/worker/.tc-vcs /home/worker/workspace /home/worker/tooltool-cache; do
# -R probably isn't necessary forever, but it fixes some poisoned
# caches for now
chown -R worker:worker $cache
done
# ..then drop privileges by re-running this script
exec su worker /home/worker/bin/build.sh
fi
####
# The default build works for any fx_desktop_build based mozharness job:
# via linux-build.sh
####
. $HOME/bin/checkout-sources.sh
. $HOME/bin/l10n.sh

View File

@ -0,0 +1,62 @@
#! /bin/bash -vex
set -x -e
# Inputs, with defaults
# mozharness builds use two repositories: gecko (source)
# and build-tools (miscellaneous) for each, specify *_REPOSITORY. If the
# revision is not in the standard repo for the codebase, specify *_BASE_REPO as
# the canonical repo to clone and *_HEAD_REPO as the repo containing the
# desired revision. For Mercurial clones, only *_HEAD_REV is required; for Git
# clones, specify the branch name to fetch as *_HEAD_REF and the desired sha1
# as *_HEAD_REV.
: GECKO_REPOSITORY ${GECKO_REPOSITORY:=https://hg.mozilla.org/mozilla-central}
: GECKO_BASE_REPOSITORY ${GECKO_BASE_REPOSITORY:=${GECKO_REPOSITORY}}
: GECKO_HEAD_REPOSITORY ${GECKO_HEAD_REPOSITORY:=${GECKO_REPOSITORY}}
: GECKO_HEAD_REV ${GECKO_HEAD_REV:=default}
: GECKO_HEAD_REF ${GECKO_HEAD_REF:=${GECKO_HEAD_REV}}
: TOOLS_REPOSITORY ${TOOLS_REPOSITORY:=https://hg.mozilla.org/build/tools}
: TOOLS_BASE_REPOSITORY ${TOOLS_BASE_REPOSITORY:=${TOOLS_REPOSITORY}}
: TOOLS_HEAD_REPOSITORY ${TOOLS_HEAD_REPOSITORY:=${TOOLS_REPOSITORY}}
: TOOLS_HEAD_REV ${TOOLS_HEAD_REV:=default}
: TOOLS_HEAD_REF ${TOOLS_HEAD_REF:=${TOOLS_HEAD_REV}}
: TOOLS_DISABLE ${TOOLS_DISABLE:=false}
: WORKSPACE ${WORKSPACE:=/home/worker/workspace}
set -v
# check out tools where mozharness expects it to be ($PWD/build/tools and $WORKSPACE/build/tools)
if [ ! "$TOOLS_DISABLE" = true ]
then
tc-vcs checkout $WORKSPACE/build/tools $TOOLS_BASE_REPOSITORY $TOOLS_HEAD_REPOSITORY $TOOLS_HEAD_REV $TOOLS_HEAD_REF
if [ ! -d build ]; then
mkdir -p build
ln -s $WORKSPACE/build/tools build/tools
fi
fi
# desktop_l10n.py expects /builds/tooltool.py to be present
if ! [ -f /builds/tooltool.py ]
then
git clone https://github.com/mozilla/build-tooltool
cp build-tooltool/tooltool.py /builds
fi
# TODO - include tools repository in EXTRA_CHECKOUT_REPOSITORIES list
for extra_repo in $EXTRA_CHECKOUT_REPOSITORIES; do
BASE_REPO="${extra_repo}_BASE_REPOSITORY"
HEAD_REPO="${extra_repo}_HEAD_REPOSITORY"
HEAD_REV="${extra_repo}_HEAD_REV"
HEAD_REF="${extra_repo}_HEAD_REF"
DEST_DIR="${extra_repo}_DEST_DIR"
tc-vcs checkout ${!DEST_DIR} ${!BASE_REPO} ${!HEAD_REPO} ${!HEAD_REV} ${!HEAD_REF}
done
export GECKO_DIR=$WORKSPACE/build/mozilla-central
tc-vcs checkout $GECKO_DIR $GECKO_BASE_REPOSITORY $GECKO_HEAD_REPOSITORY $GECKO_HEAD_REV $GECKO_HEAD_REF

View File

@ -0,0 +1,9 @@
{
"properties": {
"buildername": ""
},
"sourcestamp": {
"changes": []
},
"comments": "TaskCluster Job"
}

View File

@ -0,0 +1,2 @@
taskcluster_clientId = None
taskcluster_accessToken = None

View File

@ -94,6 +94,7 @@ config = {
},
},
'mozilla-beta': {
'enable_release_promotion': 1,
'repo_path': 'releases/mozilla-beta',
# TODO I think we can remove update_channel since we don't run
# nightlies for mozilla-beta
@ -102,6 +103,21 @@ config = {
'use_branch_in_symbols_extra_buildid': False,
'stage_server': 'upload.ffxbld.productdelivery.prod.mozaws.net',
'platform_overrides': {
'linux': {
'src_mozconfig': 'browser/config/mozconfigs/linux32/beta',
},
'linux64': {
'src_mozconfig': 'browser/config/mozconfigs/linux64/beta',
},
'macosx64': {
'src_mozconfig': 'browser/config/mozconfigs/macosx-universal/beta',
},
'win32': {
'src_mozconfig': 'browser/config/mozconfigs/win32/beta',
},
'win64': {
'src_mozconfig': 'browser/config/mozconfigs/win64/beta',
},
'linux-debug': {
'update_channel': 'default',
},

View File

@ -0,0 +1,44 @@
config = {
"nightly_build": True,
"branch": "mozilla-beta",
"en_us_binary_url": "http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-beta/",
"update_channel": "beta",
"latest_mar_dir": '/pub/mozilla.org/firefox/nightly/latest-mozilla-beta-l10n',
# l10n
"hg_l10n_base": "https://hg.mozilla.org/releases/l10n/mozilla-beta",
# mar
# No nightly on beta, using aurora mar tools
"mar_tools_url": "http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-aurora/mar-tools/%(platform)s",
# repositories
"mozilla_dir": "mozilla-beta",
"repos": [{
"vcs": "hg",
"repo": "https://hg.mozilla.org/build/tools",
"revision": "default",
"dest": "tools",
}, {
"vcs": "hgtool",
"repo": "https://hg.mozilla.org/releases/mozilla-beta",
"revision": "default",
"dest": "mozilla-beta",
}, {
"vcs": "hgtool",
"repo": "https://hg.mozilla.org/build/compare-locales",
"revision": "RELEASE_AUTOMATION"
}],
# purge options
'purge_minsize': 12,
'is_automation': True,
'default_actions': [
"clobber",
"pull",
"list-locales",
"setup",
"repack",
"taskcluster-upload",
"summary",
],
}

View File

@ -1576,15 +1576,20 @@ SpecialPowersAPI.prototype = {
getService(Components.interfaces.nsICategoryManager).
deleteCategoryEntry(category, entry, persists);
},
openDialog: function(win, args) {
return win.openDialog.apply(win, args);
},
// This is a blocking call which creates and spins a native event loop
spinEventLoop: function(win) {
// simply do a sync XHR back to our windows location.
var syncXHR = new win.XMLHttpRequest();
syncXHR.open('GET', win.location, false);
syncXHR.send();
},
// :jdm gets credit for this. ex: getPrivilegedProps(window, 'location.href');
getPrivilegedProps: function(obj, props) {
var parts = props.split('.');
for (var i = 0; i < parts.length; i++) {
var p = parts[i];
if (obj[p]) {

View File

@ -5,54 +5,69 @@
[XMLHttpRequest: responseXML MIME type tests ('', should parse)]
expected:
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
[XMLHttpRequest: responseXML MIME type tests ('bogus', should parse)]
expected:
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
[XMLHttpRequest: responseXML MIME type tests ('bogus+xml', should parse)]
expected:
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
[XMLHttpRequest: responseXML MIME type tests ('application', should parse)]
expected:
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL

View File

@ -2,15 +2,19 @@
type: testharness
[XMLHttpRequest: send() - Redirects (bogus Location header) (302: mailto:someone@example.org)]
expected:
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL

View File

@ -3,7 +3,9 @@
expected: TIMEOUT
[In-policy async video src]
expected:
if debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if debug and not e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if not debug and not e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
[in-policy async video src w/redir]
@ -11,11 +13,15 @@
[In-policy async video source element]
expected:
if debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if debug and not e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if not debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
if not debug and not e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
[In-policy async video source element w/redir]
expected:
if debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): NOTRUN
if debug and not e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): NOTRUN
if not debug and e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): NOTRUN
if not debug and not e10s and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): NOTRUN

View File

@ -156,7 +156,15 @@ function backgroundScript() {
}).then(results => {
browser.test.assertTrue(results.length >= 9, "At least as many bookmarks as added were returned by search({})");
return browser.bookmarks.getSubTree(createdFolderId);
return Promise.resolve().then(() => {
return browser.bookmarks.remove(createdFolderId);
}).then(expectedError, error => {
browser.test.assertTrue(
error.message.includes("Cannot remove a non-empty folder"),
"Expected error thrown when trying to remove a non-empty folder"
);
return browser.bookmarks.getSubTree(createdFolderId);
});
});
}).then(results => {
browser.test.assertEq(1, results.length, "Expected number of nodes returned by getSubTree");
@ -334,9 +342,37 @@ function backgroundScript() {
browser.test.assertEq("Toolbar Item", results[3].title, "Bookmark has the expected title");
browser.test.assertEq("Menu Item", results[4].title, "Bookmark has the expected title");
return browser.bookmarks.search({});
}).then(results => {
let startBookmarkCount = results.length;
return browser.bookmarks.search({title: "Mozilla Folder"}).then(result => {
return browser.bookmarks.removeTree(result[0].id);
}).then(() => {
return browser.bookmarks.search({}).then(results => {
browser.test.assertEq(
startBookmarkCount - 4,
results.length,
"Expected number of results returned after removeTree");
});
});
}).then(() => {
return browser.bookmarks.create({title: "Empty Folder"});
}).then(result => {
let emptyFolderId = result.id;
browser.test.assertEq("Empty Folder", result.title, "Folder has the expected title");
return browser.bookmarks.remove(emptyFolderId).then(() => {
return browser.bookmarks.get(emptyFolderId).then(expectedError, error => {
browser.test.assertTrue(
error.message.includes("Bookmark not found"),
"Expected error thrown when trying to get a removed folder"
);
});
});
}).then(() => {
return browser.test.notifyPass("bookmarks");
}).catch(error => {
browser.test.fail(`Error: ${String(error)} :: ${error.stack}`);
browser.test.notifyFail("bookmarks");
});
}

View File

@ -132,12 +132,108 @@ function backgroundScript() {
sendHeaders: [],
responseStarted: [],
completed: []};
let testHeaders = {
request: {
added: {
"X-WebRequest-request": "text",
"X-WebRequest-request-binary": "binary",
},
modified: {
"User-Agent": "WebRequest",
},
deleted: [
"Referer",
],
},
response: {
added: {
"X-WebRequest-response": "text",
"X-WebRequest-response-binary": "binary",
},
modified: {
"Server": "WebRequest",
},
deleted: [
"Connection",
],
},
};
function checkResourceType(type) {
let key = type.toUpperCase();
browser.test.assertTrue(key in browser.webRequest.ResourceType, `valid resource type ${key}`);
}
function processHeaders(phase, details) {
let headers = details[`${phase}Headers`];
browser.test.assertTrue(Array.isArray(headers), `${phase}Headers array present`);
let processedMark = "WebRequest-processed";
if (headers.find(h => h.name === processedMark)) {
// This may happen because of redirections or cache
browser.test.log(`${phase}Headers in ${details.requestId} already processed`);
return null;
}
headers.push({name: processedMark, value: "1"});
let {added, modified, deleted} = testHeaders[phase];
for (let name in added) {
browser.test.assertTrue(!headers.find(h => h.name === name), `header ${name} to be added not present yet in ${phase}Headers`);
let header = {name: name};
if (name.endsWith("-binary")) {
header.binaryValue = Array.from(added[name], c => c.charCodeAt(0));
} else {
header.value = added[name];
}
headers.push(header);
}
let modifiedAny = false;
for (let header of headers.filter(h => h.name in modified)) {
header.value = modified[header.name];
modifiedAny = true;
}
browser.test.assertTrue(modifiedAny, `at least one ${phase}Headers element to modify`);
let deletedAny = false;
for (let j = headers.length; j-- > 0;) {
if (deleted.includes(headers[j].name)) {
headers.splice(j, 1);
deletedAny = true;
}
}
browser.test.assertTrue(deletedAny, `at least one ${phase}Headers element to delete`);
return headers;
}
function checkHeaders(phase, details) {
if (!/^https?:/.test(details.url)) {
return;
}
let headers = details[`${phase}Headers`];
browser.test.assertTrue(Array.isArray(headers), `valid ${phase}Headers array`);
let {added, modified, deleted} = testHeaders[phase];
for (let name in added) {
browser.test.assertTrue(headers.some(h => h.name === name && h.value === added[name]), `header ${name} correctly injected in ${phase}Headers`);
}
let modifiedAny = false;
for (let header of headers.filter(h => h.name in modified)) {
let {name, value} = header;
browser.test.assertTrue(value === modified[name], `header "${name}: ${value}" matches modified value ("${modified[name]}")`);
modifiedAny = true;
}
browser.test.assertTrue(modifiedAny, `at least one modified ${phase}Headers element`);
for (let name of deleted) {
browser.test.assertFalse(headers.some(h => h.name === name), `deleted header ${name} still found in ${phase}Headers`);
}
}
function onBeforeRequest(details) {
browser.test.log(`onBeforeRequest ${details.requestId} ${details.url}`);
@ -181,6 +277,7 @@ function backgroundScript() {
browser.test.log(`onBeforeSendHeaders ${details.url}`);
checkRequestId(details);
checkResourceType(details.type);
processHeaders("request", details);
if (shouldRecord(details.url)) {
recorded.beforeSendHeaders.push(details.url);
@ -193,7 +290,7 @@ function backgroundScript() {
if (details.url.indexOf("_redirect.") != -1) {
return {redirectUrl: details.url.replace("_redirect.", "_good.")};
}
return {};
return {requestHeaders: details.requestHeaders};
}
function onBeforeRedirect(details) {
@ -218,24 +315,28 @@ function backgroundScript() {
}
function onRecord(kind, details) {
browser.test.log(`${kind} ${details.url}`);
browser.test.log(`${kind} ${details.requestId} ${details.url}`);
checkResourceType(details.type);
checkRequestId(details, kind);
if (shouldRecord(details.url)) {
if (kind in recorded && shouldRecord(details.url)) {
recorded[kind].push(details.url);
}
}
let completedUrls = {
responseStarted: new Set(),
completed: new Set(),
};
function onSendHeaders(details) {
onRecord("sendHeaders", details);
checkHeaders("request", details);
}
let completedUrls = {};
function checkIpAndRecord(kind, details) {
onRecord(kind, details);
// When resources are cached, the ip property is not present,
// so only check for the ip property the first time around.
if (!(kind in completedUrls)) {
completedUrls[kind] = new Set();
}
if (checkCompleted && !completedUrls[kind].has(details.url)) {
// We can only tell IPs for HTTP requests.
if (/^https?:/.test(details.url)) {
@ -245,12 +346,25 @@ function backgroundScript() {
}
}
function onHeadersReceived(details) {
checkIpAndRecord("headersReceived", details);
processHeaders("response", details);
browser.test.log(`After processing response headers: ${details.responseHeaders.toSource()}`);
return {responseHeaders: details.responseHeaders};
}
function onCompleted(details) {
checkIpAndRecord("completed", details);
checkHeaders("response", details);
}
browser.webRequest.onBeforeRequest.addListener(onBeforeRequest, {urls: ["<all_urls>"]}, ["blocking"]);
browser.webRequest.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {urls: ["<all_urls>"]}, ["blocking"]);
browser.webRequest.onSendHeaders.addListener(onRecord.bind(null, "sendHeaders"), {urls: ["<all_urls>"]});
browser.webRequest.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {urls: ["<all_urls>"]}, ["blocking", "requestHeaders"]);
browser.webRequest.onSendHeaders.addListener(onSendHeaders, {urls: ["<all_urls>"]}, ["requestHeaders"]);
browser.webRequest.onBeforeRedirect.addListener(onBeforeRedirect, {urls: ["<all_urls>"]});
browser.webRequest.onHeadersReceived.addListener(onHeadersReceived, {urls: ["<all_urls>"]}, ["blocking", "responseHeaders"]);
browser.webRequest.onResponseStarted.addListener(checkIpAndRecord.bind(null, "responseStarted"), {urls: ["<all_urls>"]});
browser.webRequest.onCompleted.addListener(checkIpAndRecord.bind(null, "completed"), {urls: ["<all_urls>"]});
browser.webRequest.onCompleted.addListener(onCompleted, {urls: ["<all_urls>"]}, ["responseHeaders"]);
function onTestMessage(msg) {
if (msg == "skipCompleted") {

View File

@ -372,13 +372,18 @@ var Bookmarks = Object.freeze({
* @param guidOrInfo
* The globally unique identifier of the item to remove, or an
* object representing it, as defined above.
* @param {Object} [options={}]
* Additional options that can be passed to the function.
* Currently supports preventRemovalOfNonEmptyFolders which
* will cause an exception to be thrown if attempting to remove
* a folder that is not empty.
*
* @return {Promise} resolved when the removal is complete.
* @resolves to an object representing the removed bookmark.
* @rejects if the provided guid doesn't match any existing bookmark.
* @throws if the arguments are invalid.
*/
remove(guidOrInfo) {
remove(guidOrInfo, options={}) {
let info = guidOrInfo;
if (!info)
throw new Error("Input should be a valid object");
@ -400,7 +405,7 @@ var Bookmarks = Object.freeze({
if (!item)
throw new Error("No bookmarks found for the provided GUID.");
item = yield removeBookmark(item);
item = yield removeBookmark(item, options);
// Notify onItemRemoved to listeners.
let observers = PlacesUtils.bookmarks.getObservers();
@ -1068,7 +1073,7 @@ function fetchBookmarksByParent(info) {
////////////////////////////////////////////////////////////////////////////////
// Remove implementation.
function removeBookmark(item) {
function removeBookmark(item, options) {
return PlacesUtils.withConnectionWrapper("Bookmarks.jsm: updateBookmark",
Task.async(function*(db) {
@ -1076,8 +1081,12 @@ function removeBookmark(item) {
yield db.executeTransaction(function* transaction() {
// If it's a folder, remove its contents first.
if (item.type == Bookmarks.TYPE_FOLDER)
if (item.type == Bookmarks.TYPE_FOLDER) {
if (options.preventRemovalOfNonEmptyFolders && item._childCount > 0) {
throw new Error("Cannot remove a non-empty folder.");
}
yield removeFoldersContents(db, [item.guid]);
}
// Remove annotations first. If it's a tag, we can avoid paying that cost.
if (!isUntagging) {

View File

@ -55,7 +55,7 @@ add_task(function* remove_roots_fail() {
}
});
add_task(function* remove_normal_folder_undes_root_succeeds() {
add_task(function* remove_normal_folder_under_root_succeeds() {
let folder = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.rootGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER });
checkBookmarkObject(folder);
@ -151,6 +151,7 @@ add_task(function* test_nested_contents_removed() {
Assert.strictEqual((yield PlacesUtils.bookmarks.fetch(folder2.guid)), null);
Assert.strictEqual((yield PlacesUtils.bookmarks.fetch(sep.guid)), null);
});
add_task(function* remove_folder_empty_title() {
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
@ -182,6 +183,17 @@ add_task(function* remove_separator() {
Assert.ok(!("title" in bm2));
});
add_task(function* test_nested_content_fails_when_not_allowed() {
let folder1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "a folder" });
let folder2 = yield PlacesUtils.bookmarks.insert({ parentGuid: folder1.guid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "a folder" });
Assert.rejects(PlacesUtils.bookmarks.remove(folder1, {preventRemovalOfNonEmptyFolders: true}),
/Cannot remove a non-empty folder./);
});
function run_test() {
run_next_test();
}

View File

@ -340,6 +340,36 @@ HttpObserverManager = {
return headers;
},
replaceHeaders(headers, originalNames, setHeader) {
let failures = new Set();
// Start by clearing everything.
for (let name of originalNames) {
try {
setHeader(name, "");
} catch (e) {
// Let's collect physiological failures in order
// to know what is worth reporting.
failures.add(name);
}
}
try {
for (let {name, value, binaryValue} of headers) {
try {
if (Array.isArray(binaryValue)) {
value = String.fromCharCode.apply(String, binaryValue);
}
setHeader(name, value);
} catch (e) {
if (!failures.has(name)) {
Cu.reportError(e);
}
}
}
} catch (e) {
Cu.reportError(e);
}
},
observe(subject, topic, data) {
let channel = subject.QueryInterface(Ci.nsIHttpChannel);
switch (topic) {
@ -370,8 +400,8 @@ HttpObserverManager = {
loadInfo.externalContentPolicyType :
Ci.nsIContentPolicy.TYPE_OTHER;
let requestHeaders;
let responseHeaders;
let requestHeaderNames;
let responseHeaderNames;
let includeStatus = kind === "headersReceived" ||
kind === "onBeforeRedirect" ||
@ -405,16 +435,12 @@ HttpObserverManager = {
Object.assign(data, extraData);
}
if (opts.requestHeaders) {
if (!requestHeaders) {
requestHeaders = this.getHeaders(channel, "visitRequestHeaders");
}
data.requestHeaders = requestHeaders;
data.requestHeaders = this.getHeaders(channel, "visitRequestHeaders");
requestHeaderNames = data.requestHeaders.map(h => h.name);
}
if (opts.responseHeaders) {
if (!responseHeaders) {
responseHeaders = this.getHeaders(channel, "visitResponseHeaders");
}
data.responseHeaders = responseHeaders;
data.responseHeaders = this.getHeaders(channel, "visitResponseHeaders");
responseHeaderNames = data.responseHeaders.map(h => h.name);
}
if (includeStatus) {
data.statusCode = channel.responseStatus;
@ -439,24 +465,16 @@ HttpObserverManager = {
return false;
}
if (opts.requestHeaders && result.requestHeaders) {
// Start by clearing everything.
for (let {name} of requestHeaders) {
channel.setRequestHeader(name, "", false);
}
for (let {name, value} of result.requestHeaders) {
channel.setRequestHeader(name, value, false);
}
this.replaceHeaders(
result.requestHeaders, requestHeaderNames,
(name, value) => channel.setRequestHeader(name, value, false)
);
}
if (opts.responseHeaders && result.responseHeaders) {
// Start by clearing everything.
for (let {name} of responseHeaders) {
channel.setResponseHeader(name, "", false);
}
for (let {name, value} of result.responseHeaders) {
channel.setResponseHeader(name, value, false);
}
this.replaceHeaders(
result.responseHeaders, responseHeaderNames,
(name, value) => channel.setResponseHeader(name, value, false)
);
}
}

View File

@ -82,6 +82,7 @@ skip-if = true # Bug 1084646
[browser_navigateaway.js]
[browser_navigateaway2.js]
[browser_navigateaway3.js]
skip-if = (os == "mac" || os == "win") # Bug 1198261
[browser_navigateaway4.js]
[browser_offline.js]
[browser_relative.js]