mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
merge mozilla-inbound to mozilla-central a=merge
--HG-- rename : media/gmp-clearkey/0.1/ClearKeyCencParser.cpp => media/psshparser/PsshParser.cpp rename : media/gmp-clearkey/0.1/ClearKeyCencParser.h => media/psshparser/PsshParser.h rename : media/gmp-clearkey/0.1/gtest/TestClearKeyUtils.cpp => media/psshparser/gtest/TestPsshParser.cpp rename : media/gmp-clearkey/0.1/gtest/moz.build => media/psshparser/gtest/moz.build
This commit is contained in:
commit
2844380bd4
@ -9,7 +9,7 @@ support-files =
|
||||
worker.js
|
||||
|
||||
[browser_aboutURLs.js]
|
||||
skip-if = (debug && (os == "win" || os == "linux")) # intermittent negative leak bug 1271182
|
||||
skip-if = debug && os == "linux" # Assertion. See bug 1271182.
|
||||
[browser_eme.js]
|
||||
[browser_favicon.js]
|
||||
[browser_forgetaboutsite.js]
|
||||
|
@ -93,7 +93,9 @@ function focusTag(PlacesOrganizer) {
|
||||
let fooTag = tags.getChild(0);
|
||||
let tagNode = fooTag;
|
||||
PlacesOrganizer._places.selectNode(fooTag);
|
||||
is(tagNode.title, 'foo', "tagNode title is foo");
|
||||
// Bug 1283076: Nightly has a default 'bug' tag already set
|
||||
let tagValue = AppConstants.NIGHTLY_BUILD ? 'bug' : 'foo';
|
||||
is(tagNode.title, tagValue, "tagNode title is " + tagValue);
|
||||
let ip = PlacesOrganizer._places.insertionPoint;
|
||||
ok(ip.isTag, "IP is a tag");
|
||||
}
|
||||
|
@ -152,7 +152,9 @@ function test() {
|
||||
var tagsNode = PlacesUtils.history.executeQuery(query, options).root;
|
||||
|
||||
tagsNode.containerOpen = true;
|
||||
is(tagsNode.childCount, 1, "has new tag");
|
||||
// Bug 1283076: Nightly already has 7 tags set
|
||||
let tagsCount = AppConstants.NIGHTLY_BUILD ? 8 : 1;
|
||||
is(tagsNode.childCount, tagsCount, "has new tag");
|
||||
|
||||
var tagNode = tagsNode.getChild(0);
|
||||
|
||||
|
@ -23,9 +23,10 @@ add_task(function* () {
|
||||
let tree = PlacesOrganizer._places;
|
||||
let tagsContainer = tree.selectedNode;
|
||||
tagsContainer.containerOpen = true;
|
||||
let fooTag = tagsContainer.getChild(0);
|
||||
let tagNode = fooTag;
|
||||
tree.selectNode(fooTag);
|
||||
// Bug 1283076: Nightly already has several tags set, position changes
|
||||
let tagPosition = AppConstants.NIGHTLY_BUILD ? 7 : 0;
|
||||
let tagNode = tagsContainer.getChild(tagPosition);
|
||||
tree.selectNode(tagNode);
|
||||
is(tagNode.title, 'tag1', "tagNode title is correct");
|
||||
|
||||
ok(tree.controller.isCommandEnabled("placesCmd_show:info"),
|
||||
|
@ -205,8 +205,9 @@ add_task(function* test_tags() {
|
||||
|
||||
// Now select the tag.
|
||||
PlacesUtils.asContainer(tagsNode).containerOpen = true;
|
||||
let tag = tagsNode.getChild(0);
|
||||
PO._places.selectNode(tag);
|
||||
// Bug 1283076: Nightly already has several tags set, position changes
|
||||
let tagPosition = AppConstants.NIGHTLY_BUILD ? 7 : 0;
|
||||
PO._places.selectNode(tagsNode.getChild(tagPosition));
|
||||
is(PO._places.selectedNode.title, "test",
|
||||
"The created tag has been properly selected");
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
* corrupt, nor a JSON backup nor bookmarks.html are available.
|
||||
*/
|
||||
|
||||
Components.utils.import("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
function run_test() {
|
||||
// Remove bookmarks.html from profile.
|
||||
remove_bookmarks_html();
|
||||
@ -46,5 +48,8 @@ add_task(function* () {
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
index: SMART_BOOKMARKS_ON_TOOLBAR
|
||||
});
|
||||
do_check_eq(bm.title, "Getting Started");
|
||||
|
||||
// Bug 1283076: Nightly bookmark points to Get Involved page, not Getting Started one
|
||||
let chanTitle = AppConstants.NIGHTLY_BUILD ? "Get Involved" : "Getting Started";
|
||||
do_check_eq(bm.title, chanTitle);
|
||||
});
|
||||
|
@ -610,7 +610,7 @@ var pktApi = (function() {
|
||||
* Helper function to get current signup AB group the user is in
|
||||
*/
|
||||
function getSignupPanelTabTestVariant() {
|
||||
return getMultipleTestOption('panelSignUp', {control: 1, v1: 2, v2: 7 })
|
||||
return getMultipleTestOption('panelSignUp', {control: 1, v1: 8, v2: 1 })
|
||||
}
|
||||
|
||||
function getMultipleTestOption(testName, testOptions) {
|
||||
|
@ -37,4 +37,36 @@
|
||||
# link title for https://www.mozilla.org/en-US/about/
|
||||
#define firefox_about About Us
|
||||
|
||||
# LOCALIZATION NOTE (nightly_heading):
|
||||
# Firefox Nightly links folder name
|
||||
#define nightly_heading Firefox Nightly Resources
|
||||
|
||||
# LOCALIZATION NOTE (nightly_blog):
|
||||
# Nightly builds only, link title for https://blog.nightly.mozilla.org/
|
||||
#define nightly_blog Firefox Nightly blog
|
||||
|
||||
# LOCALIZATION NOTE (bugzilla):
|
||||
# Nightly builds only, link title for https://bugzilla.mozilla.org/
|
||||
#define bugzilla Mozilla Bug Tracker
|
||||
|
||||
# LOCALIZATION NOTE (mdn):
|
||||
# Nightly builds only, link title for https://developer.mozilla.org/
|
||||
#define mdn Mozilla Developer Network
|
||||
|
||||
# LOCALIZATION NOTE (nightly_tester_tools):
|
||||
# Nightly builds only, link title for https://addons.mozilla.org/en-US/firefox/addon/nightly-tester-tools/
|
||||
#define nightly_tester_tools Nightly Tester Tools
|
||||
|
||||
# LOCALIZATION NOTE (crashes):
|
||||
# Nightly builds only, link title for about:crashes
|
||||
#define crashes All your crashes
|
||||
|
||||
# LOCALIZATION NOTE (irc):
|
||||
# Nightly builds only, link title for ircs://irc.mozilla.org/nightly
|
||||
#define irc Discuss Nightly on IRC
|
||||
|
||||
# LOCALIZATION NOTE (planet):
|
||||
# Nightly builds only, link title for https://planet.mozilla.org/
|
||||
#define planet Planet Mozilla
|
||||
|
||||
#unfilter emptyLines
|
||||
|
@ -4,29 +4,53 @@
|
||||
#if AB_CD == ja_jp_mac
|
||||
#define AB_CD ja
|
||||
#endif
|
||||
|
||||
#define mozilla_icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=
|
||||
|
||||
#define nightly_icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA01JREFUeNpkk01oXFUUx//vzp33ZiaTzkwnyUwmsbbNRpp0GhuVKiVgQIUiLmoX7lyIG10I6qIUrG6KGyuYZbMwiATqxipSMVhQYwWhiwSJwUxKkzbz8ZJ5H/M+7/vunUIE7Vnc1f3/zjn/c46wsCbjIOI4Rlfew+Zf6/h9+RYYYzj70hymZp7GULUCSin+H8IBwLYsfLOwiOfffndK1c2LmhO84jl+2e5ZCTN6Xer0fpp5dmq+frxy5zGAY9n49IOLuHDls8uqE3y07YV0ywwQGA6oZsJRFRT0FnK2Hpw8PTl/7tXZDw8ApF/29YUvufjqxxqLPrnLQBUiQRUI4EcQHQ+EgwbjENl8Pv3H9W/f//m7W9cOAKkXzr+J4pm5umy6S/uEkiAEOlzscWHG5jTbhcsrDJiHsN1CIScJTlc5JaSlldEna9uk8fcGHNO6tOMGqfssQjNFoHOxyAXU9xF5HiRXw2AqhuUEsLs6giCkjbXG549a+O3mMhQneLnthOh0NBiaAdozkTEdpC0Hnm2hKAKR3ESJRigNFZBHCF2zn+p7SMIwRM9kRcI/D5g2xAcd1PQeMtw8xkGuafIRGRgZKfHfCbKlIu5t3IVASYYDDtMzL85il2fLuh6qIkFkWtjrARY3zjENJLwCKgqwOjLcnW30Qh/HnpmGYTJhT1bSdPL0NBpr+6rbs8qhIiPivQtRhDDJQuCViI4BxdJRrx/jBopob25BDmIMnzgZjFTK+2R4tAo4+q8iM9Ba3wBTuxirHELeM5AxFO6FCsnSsHNnFfL9XUiFIo7ypNmB9D3eQkT665nS5Xm72Q5r3KCo04be2MIRKULOUlEkPnJpAbn8AI7XJyEUy/CBhIrJlUdT6D/rP3x1u1yQFjP5bFIbH4HdbHG2j/GJMfiqzneCwVI0oFrD8OgTiKLgl5Ubi0v/uYV3ZqcrE2ff+Do2/LlUxAi/HKQZH9eegupzpxDztL4gIfTU9d3VG+ev/nh7s6/797wiz1K3VpYuDU3MvFWunXg9ly2WTNVNDZaPgIU08V3NMNXVZfmfP68lvt187Br78d5r52hoKaUkiWspQqqHx4+OCQLhFu3KAXNbCYQWzR5SBCr5X3x/M+lrHgowAMP2wWqd+FzxAAAAAElFTkSuQmCC
|
||||
|
||||
#define firefox_icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAz5JREFUeNpcU0toXFUY/s49596588ikySSmM8rk0UkJEirVTVEjYk1NUdRFFgouXZQI2k2hUCjdiYIuCi4Kuig0DbqQYgU3Yi0iFRuRCBMwaZvMZDTNY95z3/fM8b8jldpzOeeee/i/737n+/+f4ZExf730rkiaZ9NJMx/nmk5HypMqqLr+ZuD4F67N5ZYejmfRsnvhyKsLhSs3zP70SubgYKHSdFENu+gXAprQIGnvBi5ez0m1b6u7M399+PTx+UvtCKtFi2F6195qXK2byir88esy5ksfYND5DhuhRCtUKBNB0Q7w5Z8ee2GgWdjOn250fn5v5j8F5dOHlZD0kWRgAwp3hrKY0S9BJWKIcQ5PShhNG4+1bHx+IocT+RXcrRSDMfFNRvvt3Oyp/icIrRhUl9hoO4kt3F55Bxf3LkLV20jWOohbDjzXxyc/lMH0cRSyCd1xq+dFhu986t7T0CUwIzB8EkW3O5ibhj44ib7NJhiBKRoB/aS4ZWHjbxtjGQYP7nGRTjim1SaQqYiAVAREpHG8vzWJn+6PQ6CF0HPR7nQQczpYeEWHyWMUkwU8MSECGwgJxAWp9xWKNzkuH3oet+JDlIE9Momedh1G4CN0bfhVG9nsS0BQQthJx0V7j3elq7ihqV5ezQTwZmodP9ZGkU/bOPr4Nr53xtDYsaD7Dg4nNqFaH5OCYSSdGhf7daNmuv6wEKqXk/yExKGBHSznFsH6FFpKQ/JAA0ulUejWLt44lkHXsqDaX6C6Nl4Rnq8vK8s/KThDMlJhkI91YOO+iR3XwEelCdTCBLSgijNzd6DLNfhlHfZ6FtWiWBQpq/V2LdSrrNPljBQkoOjuCiPxAMutOIbkPqYSEqeequGZaTLzdhZhS0PlnlB9bvhtr5CuHj3y2Qj8hVQ/kEopxONEEsO/0yATDYXYAdWrE69JEElXq7Hyk0tro+xBU1yZmr4xrIcvptIRCZlJJAYBmRGRkD08aivA7VDvWPqt564Xn41w/AHB1/u7l1/uGxGU8mNcgodUNDIq0JDeLnpzc1uo1Qr76rWbqyf/142PjsXJqdkmN2YDnQ9oGkJNU+t57q7qUv4y9/t64+HYfwQYAN7OczrzUDvGAAAAAElFTkSuQmCC
|
||||
|
||||
#define bugzilla_icon data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnYCL7J0pY9wwETY9kYEM9AAAAAEBAYAhVVVUDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1bjTOS1Vb/wAA2/8JEqT/Q0g8kQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJnMqoiJtJ/0haST/NEkp/yQnW/8AAPD8AAHY/RsgP/JZUI+GKitih4ObUEAAAAAAAAAAAAAAAAAAAAAAKnouwip5Lv9ooW//a6Jz/y9GIv8JBXb/AADO/gEBvf8AAK7/FRJp/z9BfP8iLGj1AAAAAAAAAAAAAAAAL4YzwiB0I/+UwJ3/bK+C/02eZ/9CTjz/DBa1/wABxf8BAOj/AACp/w8Oc/sJCv//EhCN9AAAAAAAAAAANJA6iC2MMv93tYL/TZ5U/3mzjP9NoWr/NEss/wYIU/8CBOn/ARCX/wwNqP0TD6X/Cgyex5qacDAAAAAAAAAAADKUN/ZirWj/d76R/0SgXf9Ln1P/eLSM/1mda/8rOkb/CQiD/wMQvf8UEnT/MTAt4P//MwUhZyN8AAAAAAAAAAAznDf5UqlZ/228jP9NqnD/Qp9c/0yiVP+Dv5b/VaVw/0VxXf9PZXD/S3pQ/y54Nf8jcCf/I2wn/wAAAAA0ozjIM6E4/zOeOP+Uz6z/XLR+/06scv9BoV3/TqZX/4XBmP9XqHP/hr6Z/yp+Lf8leSr1JXUqbQAAAAA3rTz7Nqo7/zWmOqM3oz7rUK1W/43Mpf9etYD/T61z/0KjXf9Rqln/msup/46/lf8pgy7/JFg6sAAAAAAAAAAAOK8+8jqvOiMAAAAAAAAAADSlOv85pT//kM6o/2K5hP9Ysnv/YLJ2/ziXPv8piS3/V6Ri/yZQQ9wAAAAAAAAAAAAAAAAAAAAAAAAAADetP0E2qzz/OKg98UWsS/+e1K3/pNe4/4XDjv8ojy3/T7df/5fIqv8sjTH/K4kw/yqFLv8AAAAAAAAAAAAAAAA4sT3xN7A8+QAAAAA4qz3yNag6/zSlOf80oTn/csJ+/6/jwv9fjHj/MmRMdQAAAAAAAAAAAAAAAAAAAAAAAAAAOrdA/zm0QHQAAAAAAAAAADasO/k2qTvuRX5lpjqGT/gznDr/O3FXigAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADq9QiMAAAAAAAAAAAAAAAA4sj7/Nq09s0uOaSI1qTplM6U68wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOrc//zu0P0EAAAAAOK4+UjWsPPgAAAAAAAAAAAAAAAAAAAAA/48AAP8HAAD4AQAA8AAAAOAAAADAAQAAwAMAAMAAAACAAwAAAAMAAHADAADwAAAA5AcAAO4HAAD+bwAA/u8AAA==
|
||||
|
||||
#define mdn_icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAACYklEQVQ4y3WSTYjNYRTGf+f9/+/NuDN3GKMxt1mYpKR8RT6zEk1iyUo2IysSNspCxEIZRSN07YiUJSWkaUIZizELMzIZlO9h3MzXvf/341jcmTGa69RZvKfnPOc5z3mhQlRd651Ry17tqQQl5uR9ONHC3EtdiPPxWKZ24bhJvQV0OlBHhiV7pTs3WpUdEmeLrnWJAhhOtJA5/3RjqZg8Lrnwy4bQT/DvTb73Qt3N9ymATNvTU15Mvx8vfvTWDrmgT0y+dzuAZM527lM0Xx6jFKvnEKIYvIIqVeMFRCfEiDBWMw9UQUBUT8fBWvmrU9HEUpUWDq2cT23a0P6kQEqEwTFLQCBJpm9mYrV+6lW0ngNr62jb0kw6KvMeXJohZYSLzz9xvOMDJG6aPUKMtZPDObq+iXPbmoG/ooJC0QVaVy2g5AI3Bkq8/jYCkQEBo9ah1hESS1N1Gu9DxXNFRji0oYm+/Stoaa4tK0kcRq1HE4fxHqOKEf4bk16ubphd9iKxGKxFrcOWLB1vvuOCzmg0Irig1MxKMfBznPbOd2DLCmJNHKgSIdzr/kjXhwKbFtVPNQ+NJiw7+YDh0YTFuVr6CwLpaNJDjCYOtR61DldyHL7975c9dqeH4ZESscC7r79BFBI7kY5YrZsCC8qL/kFyR+6yY0UjS3M1PHz5ich71IOIQGSn0cskwdTeryTyfV9+jGzOP3rTQAiIHUNQEBkCeUbkcqguB2JEMGqt4sJlg8lGIsv0+p5dON8YaVgn3veJ85/F61YNtn5uXf3OCF0TQVacP0PiXMVzpfbemlnbna+I/QPSFTsRLd+hHAAAAABJRU5ErkJggg==
|
||||
|
||||
#define addon_icon data:image/vndmicrosofticon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAKoSURBVDiNjZNLaJRnFIaf75vvy2UGTWr8NYkxl0IFUYkNXSSZQNWFWlxIEVy1FLLo0i4adddVXRnS4kJwYxci2GaRTWlSFGKFGRXNmFBF62VMO4TENBdjMv9k5p//Oy4SLzgqHs7yPc95eTlHiQjvqniPbVYRzuBoR+FQDEvId4neIPNCY945DayNVff/8NUvn9XXNJMv5hhKnTvYP3ymHmj/IMBSbmHjjP8fycxv+MEzGqtatUI1vK7R7wM4J32XUv3Li/l5imGBkbtXlsMw/PF1jXozg3iP3aM0Z8XRBFDr1fl7Og9EnTguXx30p/6fjAIozb/i6C4BdB2z6QOfH27ZUFNL0QUELs/tycs4J2zdGEerCADTM1P8df3PxyUZiKPF8zyGHpwGFLC6QCCRuYA4QQQ6mw4hjhYT77GN2qiBWFnV5sXc0xMAgfKx5foVYKURB2vLPbxoM8auODE6ws/fH+77dHtjhxp5OHzywpWf/IIsRk25Rq0CRFY4UVNNndkmqZFRf3YuWaYUS0aE3RP5MXX3/iCOgu3Y1WYfL90sdSDgxRoYTY5mZ2anjwC/AqEBdM4tMJ4dwYs1YiOGSBkYrVHqlQNxoC34OV8BdxK9gQ+guo7bwdYdrXu92nU6nR7Pzc/PSXxfazTj30IpRaWpIqbX4UQoBDkWJlRwLzVeLBTyGs2UcUX5duzvsfPqNpvDovQhnBIdELGaWFk1hclYmLx2fxmFbNm5qXJNvdi2DQ1WAsO1P/5petshyf6v25gJ0nxUUUeiP531s/kvAcor7MDOL2pjz3JzVKpqUoMTpb8QsSqdeTT98fomjyDv8LP5aKI3uAgQP2orCkGAVRVMZxbQhnQJIAzkm3s3Js6GSfkEQEd4+bpa8+TW71P1ANqoB65I93OA2DgV+Z+omgAAAABJRU5ErkJggg==
|
||||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
||||
<!-- This is an automatically generated file.
|
||||
It will be read and overwritten.
|
||||
DO NOT EDIT! -->
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
|
||||
<TITLE>@bookmarks_title@</TITLE>
|
||||
<H1>@bookmarks_heading@</H1>
|
||||
<meta charset="UTF-8">
|
||||
<title>@bookmarks_title@</title>
|
||||
<h1>@bookmarks_heading@</h1>
|
||||
|
||||
<DL><p>
|
||||
<DT><H3 PERSONAL_TOOLBAR_FOLDER="true" ID="rdf:#$FvPhC3">@bookmarks_toolbarfolder@</H3>
|
||||
<DD>@bookmarks_toolbarfolder_description@
|
||||
<DL><p>
|
||||
<DT><A HREF="https://www.mozilla.org/@AB_CD@/firefox/central/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAz5JREFUeNpcU0toXFUY/s49596588ikySSmM8rk0UkJEirVTVEjYk1NUdRFFgouXZQI2k2hUCjdiYIuCi4Kuig0DbqQYgU3Yi0iFRuRCBMwaZvMZDTNY95z3/fM8b8jldpzOeeee/i/737n+/+f4ZExf730rkiaZ9NJMx/nmk5HypMqqLr+ZuD4F67N5ZYejmfRsnvhyKsLhSs3zP70SubgYKHSdFENu+gXAprQIGnvBi5ez0m1b6u7M399+PTx+UvtCKtFi2F6195qXK2byir88esy5ksfYND5DhuhRCtUKBNB0Q7w5Z8ee2GgWdjOn250fn5v5j8F5dOHlZD0kWRgAwp3hrKY0S9BJWKIcQ5PShhNG4+1bHx+IocT+RXcrRSDMfFNRvvt3Oyp/icIrRhUl9hoO4kt3F55Bxf3LkLV20jWOohbDjzXxyc/lMH0cRSyCd1xq+dFhu986t7T0CUwIzB8EkW3O5ibhj44ib7NJhiBKRoB/aS4ZWHjbxtjGQYP7nGRTjim1SaQqYiAVAREpHG8vzWJn+6PQ6CF0HPR7nQQczpYeEWHyWMUkwU8MSECGwgJxAWp9xWKNzkuH3oet+JDlIE9Momedh1G4CN0bfhVG9nsS0BQQthJx0V7j3elq7ihqV5ezQTwZmodP9ZGkU/bOPr4Nr53xtDYsaD7Dg4nNqFaH5OCYSSdGhf7daNmuv6wEKqXk/yExKGBHSznFsH6FFpKQ/JAA0ulUejWLt44lkHXsqDaX6C6Nl4Rnq8vK8s/KThDMlJhkI91YOO+iR3XwEelCdTCBLSgijNzd6DLNfhlHfZ6FtWiWBQpq/V2LdSrrNPljBQkoOjuCiPxAMutOIbkPqYSEqeequGZaTLzdhZhS0PlnlB9bvhtr5CuHj3y2Qj8hVQ/kEopxONEEsO/0yATDYXYAdWrE69JEElXq7Hyk0tro+xBU1yZmr4xrIcvptIRCZlJJAYBmRGRkD08aivA7VDvWPqt564Xn41w/AHB1/u7l1/uGxGU8mNcgodUNDIq0JDeLnpzc1uo1Qr76rWbqyf/142PjsXJqdkmN2YDnQ9oGkJNU+t57q7qUv4y9/t64+HYfwQYAN7OczrzUDvGAAAAAElFTkSuQmCC" ID="rdf:#$GvPhC3">@getting_started@</A>
|
||||
</DL><p>
|
||||
<DT><H3 ID="rdf:#$ZvPhC3">@firefox_heading@</H3>
|
||||
<DL><p>
|
||||
<DT><A HREF="https://www.mozilla.org/@AB_CD@/firefox/help/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=" ID="rdf:#$22iCK1">@firefox_help@</A>
|
||||
<DT><A HREF="https://www.mozilla.org/@AB_CD@/firefox/customize/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=" ID="rdf:#$32iCK1">@firefox_customize@</A>
|
||||
<DT><A HREF="https://www.mozilla.org/@AB_CD@/contribute/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=" ID="rdf:#$42iCK1">@firefox_community@</A>
|
||||
<DT><A HREF="https://www.mozilla.org/@AB_CD@/about/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=" ID="rdf:#$52iCK1">@firefox_about@</A>
|
||||
</DL><p>
|
||||
</DL><p>
|
||||
<dl><p>
|
||||
<dt><h3 personal_toolbar_folder="true">@bookmarks_toolbarfolder@</h3></dt>
|
||||
<dd>@bookmarks_toolbarfolder_description@
|
||||
#ifndef NIGHTLY_BUILD
|
||||
<dl>
|
||||
<p><dt><a href="https://www.mozilla.org/@AB_CD@/firefox/central/" icon="@firefox_icon@">@getting_started@</a></dt>
|
||||
</dl>
|
||||
<p><dt><h3>@firefox_heading@</h3></dt>
|
||||
<dl><p>
|
||||
<dt><a href="https://www.mozilla.org/@AB_CD@/firefox/help/" icon="@mozilla_icon@">@firefox_help@</a>
|
||||
<dt><a href="https://www.mozilla.org/@AB_CD@/firefox/customize/" icon="@mozilla_icon@">@firefox_customize@</a>
|
||||
<dt><a href="https://www.mozilla.org/@AB_CD@/contribute/" icon="@mozilla_icon@">@firefox_community@</a>
|
||||
<dt><a href="https://www.mozilla.org/@AB_CD@/about/" icon="@mozilla_icon@">@firefox_about@</a>
|
||||
</dl>
|
||||
#else
|
||||
<dl>
|
||||
<p><dt><a href="https://www.mozilla.org/@AB_CD@/contribute/" icon="@mozilla_icon@">@firefox_community@</a>
|
||||
</dl>
|
||||
<p><dt><h3>@nightly_heading@</h3></dt>
|
||||
<dl><p>
|
||||
<dt><a href="https://blog.nightly.mozilla.org/" icon="@nightly_icon@">@nightly_blog@</a>
|
||||
<dt><a href="https://bugzilla.mozilla.org/" icon="@bugzilla_icon@" shortcuturl="bz" tags="bug,issue">@bugzilla@</a>
|
||||
<dt><a href="https://developer.mozilla.org/" icon="@mdn_icon@" shortcuturl="mdn">@mdn@</a>
|
||||
<dt><a href="https://addons.mozilla.org/@AB_CD@/firefox/addon/nightly-tester-tools/" icon="@addon_icon@">@nightly_tester_tools@</a>
|
||||
<dt><a href="about:crashes" icon="@mozilla_icon@" tags="crash">@crashes@</a>
|
||||
<dt><a href="https://mibbit.com/?server=irc.mozilla.org&channel=%23nightly" icon="@mozilla_icon@" tags="chat,irc">@irc@</a>
|
||||
<dt><a href="https://planet.mozilla.org/" icon="@mozilla_icon@" tags="planet,news">@planet@</a>
|
||||
</dl>
|
||||
#endif
|
||||
</dl>
|
||||
|
@ -71,13 +71,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"be": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
"yandex.by", "yahoo", "google", "ddg", "be-x-old.wikipedia.org", "be.wikipedia.org", "ru.wikipedia.org-be", "tut.by"
|
||||
]
|
||||
}
|
||||
},
|
||||
"bg": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
@ -106,13 +99,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"brx": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
"google", "yahoo-in", "bing", "ddg", "wikipedia-hi"
|
||||
]
|
||||
}
|
||||
},
|
||||
"bs": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
@ -393,6 +379,13 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"kab": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
"google", "yahoo-france", "bing", "ddg", "wikipedia-kab"
|
||||
]
|
||||
}
|
||||
},
|
||||
"kk": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
@ -421,20 +414,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"kok": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
"google", "yahoo-in", "bing", "ddg", "wikipedia-hi"
|
||||
]
|
||||
}
|
||||
},
|
||||
"ks": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
"google", "yahoo-in", "bing", "ddg", "wikipedia-hi"
|
||||
]
|
||||
}
|
||||
},
|
||||
"lij": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
@ -589,13 +568,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"sat": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
"google", "yahoo-in", "bing", "wikipedia-hi", "ddg"
|
||||
]
|
||||
}
|
||||
},
|
||||
"si": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
@ -666,6 +638,13 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"tl": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
"google", "yahoo-tl", "bing", "amazondotcom", "ddg", "twitter", "wikipedia-tl"
|
||||
]
|
||||
}
|
||||
},
|
||||
"tr": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
@ -725,7 +704,7 @@
|
||||
"zh-TW": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
"google", "yahoo-zh-TW", "ddg", "findbook-zh-TW", "wikipedia-zh-TW", "yahoo-zh-TW-HK", "yahoo-bid-zh-TW", "yahoo-answer-zh-TW"
|
||||
"yahoo-zh-TW", "google", "ddg", "findbook-zh-TW", "wikipedia-zh-TW", "yahoo-zh-TW-HK", "yahoo-bid-zh-TW", "yahoo-answer-zh-TW"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
1
config/external/moz.build
vendored
1
config/external/moz.build
vendored
@ -58,6 +58,7 @@ external_dirs += [
|
||||
'media/libspeex_resampler',
|
||||
'media/libstagefright',
|
||||
'media/libsoundtouch',
|
||||
'media/psshparser'
|
||||
]
|
||||
|
||||
DIRS += ['../../' + i for i in external_dirs]
|
||||
|
@ -1023,7 +1023,7 @@ public:
|
||||
}
|
||||
|
||||
enum ETabFocusType {
|
||||
//eTabFocus_textControlsMask = (1<<0), // unused - textboxes always tabbable
|
||||
eTabFocus_textControlsMask = (1<<0), // textboxes and lists always tabbable
|
||||
eTabFocus_formElementsMask = (1<<1), // non-text form elements
|
||||
eTabFocus_linksMask = (1<<2), // links
|
||||
eTabFocus_any = 1 + (1<<1) + (1<<2) // everything that can be focused
|
||||
|
@ -892,6 +892,10 @@ nsXMLContentSerializer::AppendElementStart(Element* aElement,
|
||||
bool forceFormat = false;
|
||||
nsresult rv = NS_OK;
|
||||
if (!CheckElementStart(content, forceFormat, aStr, rv)) {
|
||||
// When we go to AppendElementEnd for this element, we're going to
|
||||
// MaybeLeaveFromPreContent(). So make sure to MaybeEnterInPreContent()
|
||||
// now, so our PreLevel() doesn't get confused.
|
||||
MaybeEnterInPreContent(content);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -1040,8 +1044,11 @@ nsXMLContentSerializer::AppendElementEnd(Element* aElement,
|
||||
}
|
||||
|
||||
if (!outputElementEnd) {
|
||||
// Keep this in sync with the cleanup at the end of this method.
|
||||
PopNameSpaceDeclsFor(aElement);
|
||||
MaybeLeaveFromPreContent(content);
|
||||
MaybeFlagNewlineForRootNode(aElement);
|
||||
AfterElementEnd(content, aStr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1085,6 +1092,7 @@ nsXMLContentSerializer::AppendElementEnd(Element* aElement,
|
||||
NS_ENSURE_TRUE(AppendToString(tagLocalName, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(kGreaterThan, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Keep what follows in sync with the cleanup in the !outputElementEnd case.
|
||||
PopNameSpaceDeclsFor(aElement);
|
||||
|
||||
MaybeLeaveFromPreContent(content);
|
||||
|
@ -35,10 +35,7 @@ comments -->
|
||||
<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
|
||||
Cras quis<br />
|
||||
nisi at odio<br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non
|
||||
urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci
|
||||
luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at
|
||||
pharetra rutrum, <br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
|
||||
lacus risus pulvinar ante.
|
||||
</pre>
|
||||
ut gravida eros <br />leo ut libero
|
||||
|
@ -45,14 +45,11 @@ var d = a < b && a > c;
|
||||
<!-- test on
|
||||
comments -->
|
||||
<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
|
||||
Cras quis<br />
|
||||
nisi at odio<br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non
|
||||
urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci
|
||||
luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla
|
||||
at pharetra rutrum, <br />
|
||||
lacus risus pulvinar ante.
|
||||
</pre>
|
||||
Cras quis<br />
|
||||
nisi at odio<br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
|
||||
lacus risus pulvinar ante.
|
||||
</pre>
|
||||
ut gravida eros <br />
|
||||
leo ut libero
|
||||
<!-- empty element: end tag should be generated for backward compatibility with HTML -->
|
||||
|
@ -43,10 +43,7 @@ comments -->
|
||||
<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
|
||||
Cras quis<br />
|
||||
nisi at odio<br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non
|
||||
urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci
|
||||
luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at
|
||||
pharetra rutrum, <br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
|
||||
lacus risus pulvinar ante.
|
||||
</pre>
|
||||
ut gravida eros <br />leo ut libero
|
||||
|
@ -43,10 +43,7 @@ comments -->
|
||||
<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
|
||||
Cras quis<br />
|
||||
nisi at odio<br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non
|
||||
urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci
|
||||
luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at
|
||||
pharetra rutrum, <br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
|
||||
lacus risus pulvinar ante.
|
||||
</pre>
|
||||
ut gravida eros <br />leo ut libero
|
||||
|
@ -43,10 +43,7 @@ comments -->
|
||||
<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
|
||||
Cras quis<br />
|
||||
nisi at odio<br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non
|
||||
urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci
|
||||
luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at
|
||||
pharetra rutrum, <br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
|
||||
lacus risus pulvinar ante.
|
||||
</pre>
|
||||
ut gravida eros <br />leo ut libero
|
||||
|
@ -43,10 +43,7 @@ comments -->
|
||||
<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
|
||||
Cras quis<br />
|
||||
nisi at odio<br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non
|
||||
urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci
|
||||
luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at
|
||||
pharetra rutrum, <br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
|
||||
lacus risus pulvinar ante.
|
||||
</pre>
|
||||
ut gravida eros <br />leo ut libero
|
||||
|
@ -40,13 +40,14 @@ var d = a < b && a > c;
|
||||
Donec sollicitudin tortor
|
||||
<!-- test on
|
||||
comments -->
|
||||
<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
|
||||
Cras quis<br />
|
||||
nisi at odio<br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non
|
||||
urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci
|
||||
luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at
|
||||
pharetra rutrum, <br />
|
||||
<pre>lacinia <em>libero</em> ullamcorper laoreet.
|
||||
|
||||
Cras quis
|
||||
|
||||
nisi at odio
|
||||
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
|
||||
|
||||
lacus risus pulvinar ante.
|
||||
</pre>
|
||||
ut gravida eros <br />leo ut libero
|
||||
|
@ -43,10 +43,7 @@ comments -->
|
||||
<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
|
||||
Cras quis<br />
|
||||
nisi at odio<br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non
|
||||
urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci
|
||||
luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at
|
||||
pharetra rutrum, <br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
|
||||
lacus risus pulvinar ante.
|
||||
</pre>
|
||||
ut gravida eros <br />leo ut libero
|
||||
|
@ -35,10 +35,7 @@ comments -->
|
||||
<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
|
||||
Cras quis<br />
|
||||
nisi at odio<br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non
|
||||
urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci
|
||||
luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at
|
||||
pharetra rutrum, <br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
|
||||
lacus risus pulvinar ante.
|
||||
</pre>
|
||||
ut gravida eros <br />leo ut libero
|
||||
|
@ -46,10 +46,7 @@ comments -->
|
||||
<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
|
||||
Cras quis<br />
|
||||
nisi at odio<br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non
|
||||
urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci
|
||||
luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at
|
||||
pharetra rutrum, <br />
|
||||
consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
|
||||
lacus risus pulvinar ante.
|
||||
</pre>
|
||||
ut gravida eros <br />leo ut libero
|
||||
|
@ -11,9 +11,10 @@
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=422043">Mozilla Bug </a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<iframe id="testframe" src="file_xhtmlserializer_1.xhtml">
|
||||
</iframe>
|
||||
</div>
|
||||
<!-- IMPORTANT: This iframe needs to actually be displayed, so the serializer
|
||||
sees the relevant styles for <pre> elements. -->
|
||||
<iframe id="testframe" src="file_xhtmlserializer_1.xhtml"></iframe>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
|
@ -41,11 +41,12 @@ def memberXrayExpandoReservedSlot(member, descriptor):
|
||||
member.slotIndices[descriptor.interface.identifier.name])
|
||||
|
||||
|
||||
def mayUseXrayExpandoSlots(attr):
|
||||
def mayUseXrayExpandoSlots(descriptor, attr):
|
||||
assert not attr.getExtendedAttribute("NewObject")
|
||||
# For attributes whose type is a Gecko interface we always use
|
||||
# slots on the reflector for caching.
|
||||
return not attr.type.isGeckoInterface()
|
||||
# slots on the reflector for caching. Also, for interfaces that
|
||||
# don't want Xrays we obviously never use the Xray expando slot.
|
||||
return descriptor.wantsXrays and not attr.type.isGeckoInterface()
|
||||
|
||||
|
||||
def toStringBool(arg):
|
||||
@ -7602,7 +7603,7 @@ class CGPerSignatureCall(CGThing):
|
||||
""",
|
||||
maybeWrap=getMaybeWrapValueFuncForType(self.idlNode.type))
|
||||
|
||||
checkForXray = mayUseXrayExpandoSlots(self.idlNode)
|
||||
checkForXray = mayUseXrayExpandoSlots(self.descriptor, self.idlNode)
|
||||
|
||||
# For the case of Cached attributes, go ahead and preserve our
|
||||
# wrapper if needed. We need to do this because otherwise the
|
||||
@ -8788,7 +8789,7 @@ class CGSpecializedGetter(CGAbstractStaticMethod):
|
||||
# Since [Cached] and [StoreInSlot] cannot be used with "NewObject",
|
||||
# we know that in the interface type case the returned object is
|
||||
# wrappercached. So creating Xrays to it is reasonable.
|
||||
if mayUseXrayExpandoSlots(self.attr):
|
||||
if mayUseXrayExpandoSlots(self.descriptor, self.attr):
|
||||
prefix = fill(
|
||||
"""
|
||||
// Have to either root across the getter call or reget after.
|
||||
|
@ -17,7 +17,6 @@ support-files =
|
||||
disabled = disabled
|
||||
[test_pointerevent_constructor.html]
|
||||
support-files = pointerevent_constructor.html
|
||||
disabled = should be investigated
|
||||
[test_pointerevent_element_haspointercapture-manual.html]
|
||||
support-files = pointerevent_element_haspointercapture-manual.html
|
||||
[test_pointerevent_element_haspointercapture_release_pending_capture-manual.html]
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "CrashReporterParent.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/ipc/CrashReporterHost.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include <time.h>
|
||||
@ -22,6 +23,8 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
void
|
||||
CrashReporterParent::AnnotateCrashReport(const nsCString& key,
|
||||
const nsCString& data)
|
||||
@ -94,7 +97,7 @@ CrashReporterParent::SetChildData(const NativeThreadId& tid,
|
||||
{
|
||||
mInitialized = true;
|
||||
mMainThread = tid;
|
||||
mProcessType = processType;
|
||||
mProcessType = GeckoProcessType(processType);
|
||||
}
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
@ -162,74 +165,7 @@ CrashReporterParent::FinalizeChildData()
|
||||
{
|
||||
MOZ_ASSERT(mInitialized);
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
// Inline, this is the main thread. Get this done.
|
||||
NotifyCrashService();
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
|
||||
class NotifyOnMainThread : public Runnable
|
||||
{
|
||||
public:
|
||||
explicit NotifyOnMainThread(CrashReporterParent* aCR)
|
||||
: mCR(aCR)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
mCR->NotifyCrashService();
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
CrashReporterParent* mCR;
|
||||
};
|
||||
SyncRunnable::DispatchToThread(mainThread, new NotifyOnMainThread(this));
|
||||
}
|
||||
|
||||
void
|
||||
CrashReporterParent::NotifyCrashService()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mChildDumpID.IsEmpty());
|
||||
|
||||
nsCOMPtr<nsICrashService> crashService =
|
||||
do_GetService("@mozilla.org/crashservice;1");
|
||||
if (!crashService) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t processType;
|
||||
int32_t crashType = nsICrashService::CRASH_TYPE_CRASH;
|
||||
|
||||
nsCString telemetryKey;
|
||||
|
||||
switch (mProcessType) {
|
||||
case GeckoProcessType_Content:
|
||||
processType = nsICrashService::PROCESS_TYPE_CONTENT;
|
||||
telemetryKey.AssignLiteral("content");
|
||||
break;
|
||||
case GeckoProcessType_Plugin: {
|
||||
processType = nsICrashService::PROCESS_TYPE_PLUGIN;
|
||||
telemetryKey.AssignLiteral("plugin");
|
||||
nsAutoCString val;
|
||||
if (mNotes.Get(NS_LITERAL_CSTRING("PluginHang"), &val) &&
|
||||
val.Equals(NS_LITERAL_CSTRING("1"))) {
|
||||
crashType = nsICrashService::CRASH_TYPE_HANG;
|
||||
telemetryKey.AssignLiteral("pluginhang");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GeckoProcessType_GMPlugin:
|
||||
processType = nsICrashService::PROCESS_TYPE_GMPLUGIN;
|
||||
telemetryKey.AssignLiteral("gmplugin");
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("unknown process type");
|
||||
return;
|
||||
}
|
||||
|
||||
crashService->AddCrash(processType, crashType, mChildDumpID);
|
||||
Telemetry::Accumulate(Telemetry::SUBPROCESS_CRASHES_WITH_DUMP, telemetryKey, 1);
|
||||
CrashReporterHost::NotifyCrashService(mProcessType, mChildDumpID, &mNotes);
|
||||
mNotes.Clear();
|
||||
}
|
||||
#endif
|
||||
|
@ -178,7 +178,7 @@ public:
|
||||
NativeThreadId mMainThread;
|
||||
time_t mStartTime;
|
||||
// stores the child process type
|
||||
uint32_t mProcessType;
|
||||
GeckoProcessType mProcessType;
|
||||
bool mInitialized;
|
||||
};
|
||||
|
||||
|
@ -144,6 +144,7 @@ LOCAL_INCLUDES += [
|
||||
'/layout/base',
|
||||
'/media/webrtc',
|
||||
'/netwerk/base',
|
||||
'/toolkit/crashreporter',
|
||||
'/toolkit/xre',
|
||||
'/uriloader/exthandler',
|
||||
'/widget',
|
||||
|
@ -239,6 +239,7 @@ bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||
data.mPicY = aPicture.y;
|
||||
data.mPicSize = aPicture.Size();
|
||||
data.mStereoMode = aInfo.mStereoMode;
|
||||
data.mYUVColorSpace = aBuffer.mYUVColorSpace;
|
||||
|
||||
aVideoImage->SetDelayedConversion(true);
|
||||
if (aCopyData) {
|
||||
|
@ -6,10 +6,11 @@
|
||||
#if !defined(MediaData_h)
|
||||
#define MediaData_h
|
||||
|
||||
#include "AudioSampleFormat.h"
|
||||
#include "ImageTypes.h"
|
||||
#include "nsSize.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "nsRect.h"
|
||||
#include "AudioSampleFormat.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "SharedBuffer.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
@ -443,6 +444,7 @@ public:
|
||||
};
|
||||
|
||||
Plane mPlanes[3];
|
||||
YUVColorSpace mYUVColorSpace = YUVColorSpace::BT601;
|
||||
};
|
||||
|
||||
// Constructs a VideoData object. If aImage is nullptr, creates a new Image
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "mozilla/dom/MediaKeyMessageEvent.h"
|
||||
#include "mozilla/dom/MediaEncryptedEvent.h"
|
||||
#include "mozilla/dom/MediaKeyStatusMap.h"
|
||||
#include "mozilla/dom/MediaKeySystemAccess.h"
|
||||
#include "mozilla/dom/KeyIdsInitDataBinding.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/CDMProxy.h"
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
@ -18,6 +20,7 @@
|
||||
#include "mozilla/EMEUtils.h"
|
||||
#include "GMPUtils.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "psshparser/PsshParser.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -39,6 +42,15 @@ NS_IMPL_RELEASE_INHERITED(MediaKeySession, DOMEventTargetHelper)
|
||||
// unique token.
|
||||
static uint32_t sMediaKeySessionNum = 0;
|
||||
|
||||
// Max length of keyId in EME "keyIds" or WebM init data format, as enforced
|
||||
// by web platform tests.
|
||||
static const uint32_t MAX_KEY_ID_LENGTH = 512;
|
||||
|
||||
// Max length of CENC PSSH init data tolerated, as enforced by web
|
||||
// platform tests.
|
||||
static const uint32_t MAX_CENC_INIT_DATA_LENGTH = 64 * 1024;
|
||||
|
||||
|
||||
MediaKeySession::MediaKeySession(JSContext* aCx,
|
||||
nsPIDOMWindowInner* aParent,
|
||||
MediaKeys* aKeys,
|
||||
@ -160,6 +172,58 @@ MediaKeySession::KeyStatuses() const
|
||||
return mKeyStatusMap;
|
||||
}
|
||||
|
||||
// The user agent MUST thoroughly validate the Initialization Data before
|
||||
// passing it to the CDM. This includes verifying that the length and
|
||||
// values of fields are reasonable, verifying that values are within
|
||||
// reasonable limits, and stripping irrelevant, unsupported, or unknown
|
||||
// data or fields. It is RECOMMENDED that user agents pre-parse, sanitize,
|
||||
// and/or generate a fully sanitized version of the Initialization Data.
|
||||
// If the Initialization Data format specified by initDataType supports
|
||||
// multiple entries, the user agent SHOULD remove entries that are not
|
||||
// needed by the CDM. The user agent MUST NOT re-order entries within
|
||||
// the Initialization Data.
|
||||
static bool
|
||||
ValidateInitData(const nsTArray<uint8_t>& aInitData, const nsAString& aInitDataType)
|
||||
{
|
||||
if (aInitDataType.LowerCaseEqualsLiteral("webm")) {
|
||||
// WebM initData consists of a single keyId. Ensure it's of reasonable length.
|
||||
return aInitData.Length() <= MAX_KEY_ID_LENGTH;
|
||||
} else if (aInitDataType.LowerCaseEqualsLiteral("cenc")) {
|
||||
// Limit initData to less than 64KB.
|
||||
if (aInitData.Length() > MAX_CENC_INIT_DATA_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
std::vector<std::vector<uint8_t>> keyIds;
|
||||
return ParseCENCInitData(aInitData.Elements(), aInitData.Length(), keyIds);
|
||||
} else if (aInitDataType.LowerCaseEqualsLiteral("keyids")) {
|
||||
if (aInitData.Length() > MAX_KEY_ID_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
// Ensure that init data matches the expected JSON format.
|
||||
mozilla::dom::KeyIdsInitData keyIds;
|
||||
nsString json;
|
||||
nsDependentCSubstring raw(reinterpret_cast<const char*>(aInitData.Elements()), aInitData.Length());
|
||||
if (NS_FAILED(nsContentUtils::ConvertStringFromEncoding(NS_LITERAL_CSTRING("UTF-8"), raw, json))) {
|
||||
return false;
|
||||
}
|
||||
if (!keyIds.Init(json)) {
|
||||
return false;
|
||||
}
|
||||
if (keyIds.mKids.Length() == 0) {
|
||||
return false;
|
||||
}
|
||||
for (const auto& kid : keyIds.mKids) {
|
||||
if (kid.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Generates a license request based on the initData. A message of type
|
||||
// "license-request" or "individualization-request" will always be queued
|
||||
// if the algorithm succeeds and the promise is resolved.
|
||||
already_AddRefed<Promise>
|
||||
MediaKeySession::GenerateRequest(const nsAString& aInitDataType,
|
||||
const ArrayBufferViewOrArrayBuffer& aInitData,
|
||||
@ -171,16 +235,30 @@ MediaKeySession::GenerateRequest(const nsAString& aInitDataType,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If this object is closed, return a promise rejected with an InvalidStateError.
|
||||
if (IsClosed()) {
|
||||
EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, closed",
|
||||
this, NS_ConvertUTF16toUTF8(mSessionId).get());
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
NS_LITERAL_CSTRING("Session is closed in MediaKeySession.generateRequest()"));
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// If this object's uninitialized value is false, return a promise rejected
|
||||
// with an InvalidStateError.
|
||||
if (!mUninitialized) {
|
||||
EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, uninitialized",
|
||||
this, NS_ConvertUTF16toUTF8(mSessionId).get());
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR,
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
NS_LITERAL_CSTRING("Session is already initialized in MediaKeySession.generateRequest()"));
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Let this object's uninitialized value be false.
|
||||
mUninitialized = false;
|
||||
|
||||
// If initDataType is the empty string, return a promise rejected
|
||||
// with a newly created TypeError.
|
||||
if (aInitDataType.IsEmpty()) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR,
|
||||
NS_LITERAL_CSTRING("Empty initDataType passed to MediaKeySession.generateRequest()"));
|
||||
@ -189,16 +267,56 @@ MediaKeySession::GenerateRequest(const nsAString& aInitDataType,
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// If initData is an empty array, return a promise rejected with
|
||||
// a newly created TypeError.
|
||||
nsTArray<uint8_t> data;
|
||||
CopyArrayBufferViewOrArrayBufferData(aInitData, data);
|
||||
if (data.IsEmpty()) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR,
|
||||
NS_LITERAL_CSTRING("Empty initData passed to MediaKeySession.generateRequest()"));
|
||||
EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, empty initData",
|
||||
this, NS_ConvertUTF16toUTF8(mSessionId).get());
|
||||
this, NS_ConvertUTF16toUTF8(mSessionId).get());
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// If the Key System implementation represented by this object's
|
||||
// cdm implementation value does not support initDataType as an
|
||||
// Initialization Data Type, return a promise rejected with a
|
||||
// NotSupportedError. String comparison is case-sensitive.
|
||||
if (!MediaKeySystemAccess::KeySystemSupportsInitDataType(mKeySystem, aInitDataType)) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
|
||||
NS_LITERAL_CSTRING("Unsupported initDataType passed to MediaKeySession.generateRequest()"));
|
||||
EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, unsupported initDataType",
|
||||
this, NS_ConvertUTF16toUTF8(mSessionId).get());
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Let init data be a copy of the contents of the initData parameter.
|
||||
// Note: Handled by the CopyArrayBufferViewOrArrayBufferData call above.
|
||||
|
||||
// Let session type be this object's session type.
|
||||
|
||||
// Let promise be a new promise.
|
||||
|
||||
// Run the following steps in parallel:
|
||||
|
||||
// If the init data is not valid for initDataType, reject promise with
|
||||
// a newly created TypeError.
|
||||
if (!ValidateInitData(data, aInitDataType)) {
|
||||
// If the preceding step failed, reject promise with a newly created TypeError.
|
||||
promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR,
|
||||
NS_LITERAL_CSTRING("initData sanitization failed in MediaKeySession.generateRequest()"));
|
||||
EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() initData sanitization failed",
|
||||
this, NS_ConvertUTF16toUTF8(mSessionId).get());
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Let sanitized init data be a validated and sanitized version of init data.
|
||||
|
||||
// If sanitized init data is empty, reject promise with a NotSupportedError.
|
||||
|
||||
// Note: Remaining steps of generateRequest method continue in CDM.
|
||||
|
||||
Telemetry::Accumulate(Telemetry::VIDEO_CDM_GENERATE_REQUEST_CALLED,
|
||||
ToCDMTypeTelemetryEnum(mKeySystem));
|
||||
|
||||
|
@ -512,6 +512,16 @@ GetKeySystemConfig(const nsAString& aKeySystem)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
MediaKeySystemAccess::KeySystemSupportsInitDataType(const nsAString& aKeySystem,
|
||||
const nsAString& aInitDataType)
|
||||
{
|
||||
const KeySystemConfig* implementation = GetKeySystemConfig(aKeySystem);
|
||||
return implementation &&
|
||||
implementation->mInitDataTypes.Contains(aInitDataType);
|
||||
}
|
||||
|
||||
enum CodecType
|
||||
{
|
||||
Audio,
|
||||
|
@ -75,6 +75,9 @@ public:
|
||||
MediaKeySystemConfiguration& aOutConfig,
|
||||
DecoderDoctorDiagnostics* aDiagnostics);
|
||||
|
||||
static bool KeySystemSupportsInitDataType(const nsAString& aKeySystem,
|
||||
const nsAString& aInitDataType);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsPIDOMWindowInner> mParent;
|
||||
const nsString mKeySystem;
|
||||
|
@ -86,16 +86,22 @@ FFmpegLibWrapper::Link()
|
||||
return false;
|
||||
}
|
||||
|
||||
#define AV_FUNC(func, ver) \
|
||||
if ((ver) & version) { \
|
||||
#define AV_FUNC_OPTION(func, ver) \
|
||||
if ((ver) & version) { \
|
||||
if (!(func = (decltype(func))PR_FindSymbol(((ver) & AV_FUNC_AVUTIL_MASK) ? mAVUtilLib : mAVCodecLib, #func))) { \
|
||||
FFMPEG_LOG("Couldn't load function " # func); \
|
||||
Unlink(); \
|
||||
return false; \
|
||||
} \
|
||||
} else { \
|
||||
func = (decltype(func))nullptr; \
|
||||
}
|
||||
|
||||
#define AV_FUNC(func, ver) \
|
||||
AV_FUNC_OPTION(func, ver) \
|
||||
if ((ver) & version && !func) { \
|
||||
Unlink(); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
AV_FUNC(av_lockmgr_register, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_alloc_context3, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_close, AV_FUNC_AVCODEC_ALL)
|
||||
@ -118,7 +124,9 @@ FFmpegLibWrapper::Link()
|
||||
AV_FUNC(av_frame_alloc, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
AV_FUNC(av_frame_free, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
AV_FUNC(av_frame_unref, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
AV_FUNC_OPTION(av_frame_get_colorspace, AV_FUNC_AVUTIL_ALL)
|
||||
#undef AV_FUNC
|
||||
#undef AV_FUNC_OPTION
|
||||
|
||||
avcodec_register_all();
|
||||
#ifdef DEBUG
|
||||
|
@ -67,6 +67,9 @@ struct FFmpegLibWrapper
|
||||
void (*av_frame_free)(AVFrame** frame);
|
||||
void (*av_frame_unref)(AVFrame* frame);
|
||||
|
||||
// libavutil optional
|
||||
int (*av_frame_get_colorspace)(const AVFrame *frame);
|
||||
|
||||
PRLibrary* mAVCodecLib;
|
||||
PRLibrary* mAVUtilLib;
|
||||
|
||||
|
@ -301,7 +301,19 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample,
|
||||
b.mPlanes[1].mWidth = b.mPlanes[2].mWidth = (mFrame->width + 1) >> 1;
|
||||
b.mPlanes[1].mHeight = b.mPlanes[2].mHeight = (mFrame->height + 1) >> 1;
|
||||
}
|
||||
|
||||
if (mLib->av_frame_get_colorspace) {
|
||||
switch (mLib->av_frame_get_colorspace(mFrame)) {
|
||||
case AVCOL_SPC_BT709:
|
||||
b.mYUVColorSpace = YUVColorSpace::BT709;
|
||||
break;
|
||||
case AVCOL_SPC_SMPTE170M:
|
||||
case AVCOL_SPC_BT470BG:
|
||||
b.mYUVColorSpace = YUVColorSpace::BT601;
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Unsupported yuv color space.");
|
||||
}
|
||||
}
|
||||
RefPtr<VideoData> v =
|
||||
VideoData::CreateAndCopyData(mInfo,
|
||||
mImageContainer,
|
||||
|
@ -32,7 +32,8 @@ namespace mozilla {
|
||||
NS_IMPL_ISUPPORTS(LoadManagerSingleton, nsIObserver)
|
||||
|
||||
|
||||
LoadManagerSingleton::LoadManagerSingleton(int aLoadMeasurementInterval,
|
||||
LoadManagerSingleton::LoadManagerSingleton(bool aEncoderOnly,
|
||||
int aLoadMeasurementInterval,
|
||||
int aAveragingMeasurements,
|
||||
float aHighLoadThreshold,
|
||||
float aLowLoadThreshold)
|
||||
@ -50,9 +51,11 @@ LoadManagerSingleton::LoadManagerSingleton(int aLoadMeasurementInterval,
|
||||
mLoadMeasurementInterval, mAveragingMeasurements,
|
||||
mHighLoadThreshold, mLowLoadThreshold));
|
||||
MOZ_ASSERT(mHighLoadThreshold > mLowLoadThreshold);
|
||||
mLoadMonitor = new LoadMonitor(mLoadMeasurementInterval);
|
||||
mLoadMonitor->Init(mLoadMonitor);
|
||||
mLoadMonitor->SetLoadChangeCallback(this);
|
||||
if (!aEncoderOnly) {
|
||||
mLoadMonitor = new LoadMonitor(mLoadMeasurementInterval);
|
||||
mLoadMonitor->Init(mLoadMonitor);
|
||||
mLoadMonitor->SetLoadChangeCallback(this);
|
||||
}
|
||||
|
||||
mLastStateChange = TimeStamp::Now();
|
||||
for (auto &in_state : mTimeInState) {
|
||||
@ -181,36 +184,36 @@ LoadManagerSingleton::RemoveObserver(webrtc::CPULoadStateObserver * aObserver)
|
||||
LOG(("LoadManager - Element to remove not found"));
|
||||
}
|
||||
if (mObservers.Length() == 0) {
|
||||
// Record how long we spent in the final state for later Telemetry or display
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
mTimeInState[mCurrentState] += (now - mLastStateChange).ToMilliseconds();
|
||||
|
||||
float total = 0;
|
||||
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(mTimeInState); i++) {
|
||||
total += mTimeInState[i];
|
||||
}
|
||||
// Don't include short calls; we don't have reasonable load data, and
|
||||
// such short calls rarely reach a stable state. Keep relatively
|
||||
// short calls separate from longer ones
|
||||
bool log = total > 5*PR_MSEC_PER_SEC;
|
||||
bool small = log && total < 30*PR_MSEC_PER_SEC;
|
||||
if (log) {
|
||||
// Note: We don't care about rounding here; thus total may be < 100
|
||||
Telemetry::Accumulate(small ? Telemetry::WEBRTC_LOAD_STATE_RELAXED_SHORT :
|
||||
Telemetry::WEBRTC_LOAD_STATE_RELAXED,
|
||||
(uint32_t) (mTimeInState[webrtc::CPULoadState::kLoadRelaxed]/total * 100));
|
||||
Telemetry::Accumulate(small ? Telemetry::WEBRTC_LOAD_STATE_NORMAL_SHORT :
|
||||
Telemetry::WEBRTC_LOAD_STATE_NORMAL,
|
||||
(uint32_t) (mTimeInState[webrtc::CPULoadState::kLoadNormal]/total * 100));
|
||||
Telemetry::Accumulate(small ? Telemetry::WEBRTC_LOAD_STATE_STRESSED_SHORT :
|
||||
Telemetry::WEBRTC_LOAD_STATE_STRESSED,
|
||||
(uint32_t) (mTimeInState[webrtc::CPULoadState::kLoadStressed]/total * 100));
|
||||
}
|
||||
for (auto &in_state : mTimeInState) {
|
||||
in_state = 0;
|
||||
}
|
||||
|
||||
if (mLoadMonitor) {
|
||||
// Record how long we spent in the final state for later Telemetry or display
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
mTimeInState[mCurrentState] += (now - mLastStateChange).ToMilliseconds();
|
||||
|
||||
float total = 0;
|
||||
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(mTimeInState); i++) {
|
||||
total += mTimeInState[i];
|
||||
}
|
||||
// Don't include short calls; we don't have reasonable load data, and
|
||||
// such short calls rarely reach a stable state. Keep relatively
|
||||
// short calls separate from longer ones
|
||||
bool log = total > 5*PR_MSEC_PER_SEC;
|
||||
bool small = log && total < 30*PR_MSEC_PER_SEC;
|
||||
if (log) {
|
||||
// Note: We don't care about rounding here; thus total may be < 100
|
||||
Telemetry::Accumulate(small ? Telemetry::WEBRTC_LOAD_STATE_RELAXED_SHORT :
|
||||
Telemetry::WEBRTC_LOAD_STATE_RELAXED,
|
||||
(uint32_t) (mTimeInState[webrtc::CPULoadState::kLoadRelaxed]/total * 100));
|
||||
Telemetry::Accumulate(small ? Telemetry::WEBRTC_LOAD_STATE_NORMAL_SHORT :
|
||||
Telemetry::WEBRTC_LOAD_STATE_NORMAL,
|
||||
(uint32_t) (mTimeInState[webrtc::CPULoadState::kLoadNormal]/total * 100));
|
||||
Telemetry::Accumulate(small ? Telemetry::WEBRTC_LOAD_STATE_STRESSED_SHORT :
|
||||
Telemetry::WEBRTC_LOAD_STATE_STRESSED,
|
||||
(uint32_t) (mTimeInState[webrtc::CPULoadState::kLoadStressed]/total * 100));
|
||||
}
|
||||
for (auto &in_state : mTimeInState) {
|
||||
in_state = 0;
|
||||
}
|
||||
|
||||
// Dance to avoid deadlock on mLock!
|
||||
RefPtr<LoadMonitor> loadMonitor = mLoadMonitor.forget();
|
||||
MutexAutoUnlock unlock(mLock);
|
||||
|
@ -44,7 +44,8 @@ public:
|
||||
void RemoveObserver(webrtc::CPULoadStateObserver * aObserver) override;
|
||||
|
||||
private:
|
||||
LoadManagerSingleton(int aLoadMeasurementInterval,
|
||||
LoadManagerSingleton(bool aEncoderOnly,
|
||||
int aLoadMeasurementInterval,
|
||||
int aAveragingMeasurements,
|
||||
float aHighLoadThreshold,
|
||||
float aLowLoadThreshold);
|
||||
|
@ -24,6 +24,8 @@ LoadManagerSingleton::Get() {
|
||||
if (!sSingleton) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
bool loadEncoderOnly =
|
||||
mozilla::Preferences::GetBool("media.navigator.load_adapt.encoder_only", true);
|
||||
int loadMeasurementInterval =
|
||||
mozilla::Preferences::GetInt("media.navigator.load_adapt.measure_interval", 1000);
|
||||
int averagingSeconds =
|
||||
@ -33,7 +35,8 @@ LoadManagerSingleton::Get() {
|
||||
float lowLoadThreshold =
|
||||
mozilla::Preferences::GetFloat("media.navigator.load_adapt.low_load", 0.40f);
|
||||
|
||||
sSingleton = new LoadManagerSingleton(loadMeasurementInterval,
|
||||
sSingleton = new LoadManagerSingleton(loadEncoderOnly,
|
||||
loadMeasurementInterval,
|
||||
averagingSeconds,
|
||||
highLoadThreshold,
|
||||
lowLoadThreshold);
|
||||
|
@ -769,7 +769,7 @@ PluginInstanceParent::RecvShowDirectBitmap(Shmem&& buffer,
|
||||
RefPtr<TextureClient> texture = allocator->CreateOrRecycle(
|
||||
format, size, BackendSelector::Content,
|
||||
TextureFlags::NO_FLAGS,
|
||||
ALLOC_FOR_OUT_OF_BAND_CONTENT);
|
||||
TextureAllocationFlags(ALLOC_FOR_OUT_OF_BAND_CONTENT | ALLOC_UPDATE_FROM_SURFACE));
|
||||
if (!texture) {
|
||||
NS_WARNING("Could not allocate a TextureClient for plugin!");
|
||||
return false;
|
||||
@ -836,7 +836,7 @@ PluginInstanceParent::RecvShowDirectDXGISurface(const WindowsHandle& handle,
|
||||
surface->GetFormat(), surface->GetSize(),
|
||||
BackendSelector::Content,
|
||||
TextureFlags::NO_FLAGS,
|
||||
ALLOC_FOR_OUT_OF_BAND_CONTENT);
|
||||
TextureAllocationFlags(ALLOC_FOR_OUT_OF_BAND_CONTENT | ALLOC_UPDATE_FROM_SURFACE));
|
||||
if (!texture) {
|
||||
NS_WARNING("Could not allocate a TextureClient for plugin!");
|
||||
return false;
|
||||
|
@ -1197,6 +1197,8 @@ var interfaceNamesInGlobalScope =
|
||||
{name: "VREyeParameters", release: false},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "VRFieldOfView", release: false},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "VRFrameData", release: false},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "VRPose", release: false},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
@ -299,11 +299,24 @@ VRPose::VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState)
|
||||
, mAngularVelocity(nullptr)
|
||||
, mAngularAcceleration(nullptr)
|
||||
{
|
||||
mTimeStamp = aState.timestamp * 1000.0f; // Converting from seconds to ms
|
||||
mFrameId = aState.inputFrameID;
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
VRPose::VRPose(nsISupports* aParent)
|
||||
: mParent(aParent)
|
||||
, mPosition(nullptr)
|
||||
, mLinearVelocity(nullptr)
|
||||
, mLinearAcceleration(nullptr)
|
||||
, mOrientation(nullptr)
|
||||
, mAngularVelocity(nullptr)
|
||||
, mAngularAcceleration(nullptr)
|
||||
{
|
||||
mFrameId = 0;
|
||||
mVRState.Clear();
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
VRPose::~VRPose()
|
||||
{
|
||||
mozilla::DropJSObjects(this);
|
||||
@ -491,6 +504,15 @@ VRDisplay::GetStageParameters()
|
||||
return mStageParameters;
|
||||
}
|
||||
|
||||
bool
|
||||
VRDisplay::GetFrameData(VRFrameData& aFrameData)
|
||||
{
|
||||
gfx::VRHMDSensorState state = mClient->GetSensorState();
|
||||
const gfx::VRDisplayInfo& info = mClient->GetDisplayInfo();
|
||||
aFrameData.Update(info, state, mDepthNear, mDepthFar);
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<VRPose>
|
||||
VRDisplay::GetPose()
|
||||
{
|
||||
@ -500,15 +522,6 @@ VRDisplay::GetPose()
|
||||
return obj.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<VRPose>
|
||||
VRDisplay::GetImmediatePose()
|
||||
{
|
||||
gfx::VRHMDSensorState state = mClient->GetImmediateSensorState();
|
||||
RefPtr<VRPose> obj = new VRPose(GetParentObject(), state);
|
||||
|
||||
return obj.forget();
|
||||
}
|
||||
|
||||
void
|
||||
VRDisplay::ResetPose()
|
||||
{
|
||||
@ -530,7 +543,7 @@ VRDisplay::RequestPresent(const nsTArray<VRLayer>& aLayers, ErrorResult& aRv)
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
NS_ENSURE_TRUE(obs, nullptr);
|
||||
|
||||
if (IsPresenting()) {
|
||||
if (mClient->GetIsPresenting()) {
|
||||
// Only one presentation allowed per VRDisplay
|
||||
// on a first-come-first-serve basis.
|
||||
promise->MaybeRejectWithUndefined();
|
||||
@ -581,12 +594,20 @@ VRDisplay::ExitPresent(ErrorResult& aRv)
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
ExitPresentInternal();
|
||||
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
|
||||
|
||||
promise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
if (!IsPresenting()) {
|
||||
// We can not exit a presentation outside of the context that
|
||||
// started the presentation.
|
||||
promise->MaybeRejectWithUndefined();
|
||||
} else {
|
||||
promise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
ExitPresentInternal();
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
@ -640,7 +661,9 @@ VRDisplay::CancelAnimationFrame(int32_t aHandle, ErrorResult& aError)
|
||||
bool
|
||||
VRDisplay::IsPresenting() const
|
||||
{
|
||||
return mClient->GetIsPresenting();
|
||||
// IsPresenting returns true only if this Javascript context is presenting
|
||||
// and will return false if another context is presenting.
|
||||
return mPresentation != nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -659,5 +682,174 @@ NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, DOMEventTargetHelper)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(VRFrameData)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(VRFrameData)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent, mPose)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
tmp->mLeftProjectionMatrix = nullptr;
|
||||
tmp->mLeftViewMatrix = nullptr;
|
||||
tmp->mRightProjectionMatrix = nullptr;
|
||||
tmp->mRightViewMatrix = nullptr;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(VRFrameData)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent, mPose)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(VRFrameData)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLeftProjectionMatrix)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLeftViewMatrix)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mRightProjectionMatrix)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mRightViewMatrix)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRFrameData, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRFrameData, Release)
|
||||
|
||||
VRFrameData::VRFrameData(nsISupports* aParent)
|
||||
: mParent(aParent)
|
||||
, mLeftProjectionMatrix(nullptr)
|
||||
, mLeftViewMatrix(nullptr)
|
||||
, mRightProjectionMatrix(nullptr)
|
||||
, mRightViewMatrix(nullptr)
|
||||
{
|
||||
mPose = new VRPose(aParent);
|
||||
}
|
||||
|
||||
VRFrameData::~VRFrameData()
|
||||
{
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<VRFrameData>
|
||||
VRFrameData::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<VRFrameData> obj = new VRFrameData(aGlobal.GetAsSupports());
|
||||
return obj.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
VRFrameData::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return VRFrameDataBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
VRPose*
|
||||
VRFrameData::Pose()
|
||||
{
|
||||
return mPose;
|
||||
}
|
||||
|
||||
void
|
||||
VRFrameData::LazyCreateMatrix(JS::Heap<JSObject*>& aArray, gfx::Matrix4x4& aMat, JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetval, ErrorResult& aRv)
|
||||
{
|
||||
if (!aArray) {
|
||||
// Lazily create the Float32Array
|
||||
aArray = dom::Float32Array::Create(aCx, this, 16, aMat.components);
|
||||
if (!aArray) {
|
||||
aRv.NoteJSContextException(aCx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (aArray) {
|
||||
JS::ExposeObjectToActiveJS(aArray);
|
||||
}
|
||||
aRetval.set(aArray);
|
||||
}
|
||||
|
||||
double
|
||||
VRFrameData::Timestamp() const
|
||||
{
|
||||
return mVRState.timestamp * 1000.0f; // Converting from seconds to milliseconds
|
||||
}
|
||||
|
||||
void
|
||||
VRFrameData::GetLeftProjectionMatrix(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
LazyCreateMatrix(mLeftProjectionMatrix, mLeftProjection, aCx, aRetval, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
VRFrameData::GetLeftViewMatrix(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
LazyCreateMatrix(mLeftViewMatrix, mLeftView, aCx, aRetval, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
VRFrameData::GetRightProjectionMatrix(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
LazyCreateMatrix(mRightProjectionMatrix, mRightProjection, aCx, aRetval, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
VRFrameData::GetRightViewMatrix(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
LazyCreateMatrix(mRightViewMatrix, mRightView, aCx, aRetval, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
VRFrameData::Update(const gfx::VRDisplayInfo& aInfo,
|
||||
const gfx::VRHMDSensorState& aState,
|
||||
float aDepthNear,
|
||||
float aDepthFar)
|
||||
{
|
||||
mVRState = aState;
|
||||
|
||||
mLeftProjectionMatrix = nullptr;
|
||||
mLeftViewMatrix = nullptr;
|
||||
mRightProjectionMatrix = nullptr;
|
||||
mRightViewMatrix = nullptr;
|
||||
|
||||
mPose = new VRPose(GetParentObject(), aState);
|
||||
|
||||
gfx::Quaternion qt;
|
||||
if (mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation) {
|
||||
qt.x = mVRState.orientation[0];
|
||||
qt.y = mVRState.orientation[1];
|
||||
qt.z = mVRState.orientation[2];
|
||||
qt.w = mVRState.orientation[3];
|
||||
}
|
||||
gfx::Point3D pos;
|
||||
if (mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) {
|
||||
pos.x = -mVRState.position[0];
|
||||
pos.y = -mVRState.position[1];
|
||||
pos.z = -mVRState.position[2];
|
||||
}
|
||||
gfx::Matrix4x4 matHead;
|
||||
matHead.SetRotationFromQuaternion(qt);
|
||||
matHead.PreTranslate(pos);
|
||||
|
||||
mLeftView = matHead;
|
||||
mLeftView.PostTranslate(-aInfo.mEyeTranslation[gfx::VRDisplayInfo::Eye_Left]);
|
||||
|
||||
mRightView = matHead;
|
||||
mRightView.PostTranslate(-aInfo.mEyeTranslation[gfx::VRDisplayInfo::Eye_Right]);
|
||||
|
||||
// Avoid division by zero within ConstructProjectionMatrix
|
||||
const float kEpsilon = 0.00001f;
|
||||
if (fabs(aDepthFar - aDepthNear) < kEpsilon) {
|
||||
aDepthFar = aDepthNear + kEpsilon;
|
||||
}
|
||||
|
||||
const gfx::VRFieldOfView leftFOV = aInfo.mEyeFOV[gfx::VRDisplayInfo::Eye_Left];
|
||||
mLeftProjection = leftFOV.ConstructProjectionMatrix(aDepthNear, aDepthFar, true);
|
||||
const gfx::VRFieldOfView rightFOV = aInfo.mEyeFOV[gfx::VRDisplayInfo::Eye_Right];
|
||||
mRightProjection = rightFOV.ConstructProjectionMatrix(aDepthNear, aDepthFar, true);
|
||||
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -100,11 +100,11 @@ class VRPose final : public nsWrapperCache
|
||||
|
||||
public:
|
||||
VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState);
|
||||
explicit VRPose(nsISupports* aParent);
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRPose)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRPose)
|
||||
|
||||
double Timestamp() const { return mTimeStamp; }
|
||||
uint32_t FrameID() const { return mFrameId; }
|
||||
|
||||
void GetPosition(JSContext* aCx,
|
||||
@ -133,7 +133,6 @@ protected:
|
||||
~VRPose();
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
|
||||
double mTimeStamp;
|
||||
uint32_t mFrameId;
|
||||
gfx::VRHMDSensorState mVRState;
|
||||
|
||||
@ -146,6 +145,63 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
class VRFrameData final : public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRFrameData)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRFrameData)
|
||||
|
||||
explicit VRFrameData(nsISupports* aParent);
|
||||
static already_AddRefed<VRFrameData> Constructor(const GlobalObject& aGlobal,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void Update(const gfx::VRDisplayInfo& aInfo,
|
||||
const gfx::VRHMDSensorState& aState,
|
||||
float aDepthNear,
|
||||
float aDepthFar);
|
||||
|
||||
// WebIDL Members
|
||||
double Timestamp() const;
|
||||
void GetLeftProjectionMatrix(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& aRv);
|
||||
void GetLeftViewMatrix(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& aRv);
|
||||
void GetRightProjectionMatrix(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& aRv);
|
||||
void GetRightViewMatrix(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& aRv);
|
||||
|
||||
VRPose* Pose();
|
||||
|
||||
// WebIDL Boilerplate
|
||||
nsISupports* GetParentObject() const { return mParent; }
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
protected:
|
||||
~VRFrameData();
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
|
||||
gfx::VRHMDSensorState mVRState;
|
||||
RefPtr<VRPose> mPose;
|
||||
JS::Heap<JSObject*> mLeftProjectionMatrix;
|
||||
JS::Heap<JSObject*> mLeftViewMatrix;
|
||||
JS::Heap<JSObject*> mRightProjectionMatrix;
|
||||
JS::Heap<JSObject*> mRightViewMatrix;
|
||||
|
||||
gfx::Matrix4x4 mLeftProjection;
|
||||
gfx::Matrix4x4 mLeftView;
|
||||
gfx::Matrix4x4 mRightProjection;
|
||||
gfx::Matrix4x4 mRightView;
|
||||
|
||||
void LazyCreateMatrix(JS::Heap<JSObject*>& aArray, gfx::Matrix4x4& aMat,
|
||||
JSContext* aCx, JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& aRv);
|
||||
};
|
||||
|
||||
class VRStageParameters final : public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
@ -237,8 +293,8 @@ public:
|
||||
|
||||
virtual already_AddRefed<VREyeParameters> GetEyeParameters(VREye aEye);
|
||||
|
||||
bool GetFrameData(VRFrameData& aFrameData);
|
||||
already_AddRefed<VRPose> GetPose();
|
||||
already_AddRefed<VRPose> GetImmediatePose();
|
||||
void ResetPose();
|
||||
|
||||
double DepthNear() {
|
||||
|
11
dom/webidl/KeyIdsInitData.webidl
Normal file
11
dom/webidl/KeyIdsInitData.webidl
Normal file
@ -0,0 +1,11 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/.
|
||||
*/
|
||||
|
||||
// "KeyIds" EME init data format definition/parser, as defined by
|
||||
// https://w3c.github.io/encrypted-media/format-registry/initdata/keyids.html
|
||||
dictionary KeyIdsInitData {
|
||||
required sequence<DOMString> kids;
|
||||
};
|
@ -26,8 +26,8 @@ interface PointerEvent : MouseEvent
|
||||
dictionary PointerEventInit : MouseEventInit
|
||||
{
|
||||
long pointerId = 0;
|
||||
long width = 0;
|
||||
long height = 0;
|
||||
long width = 1;
|
||||
long height = 1;
|
||||
float pressure = 0;
|
||||
long tiltX = 0;
|
||||
long tiltY = 0;
|
||||
|
@ -117,8 +117,6 @@ interface VRStageParameters {
|
||||
[Pref="dom.vr.enabled",
|
||||
HeaderFile="mozilla/dom/VRDisplay.h"]
|
||||
interface VRPose {
|
||||
readonly attribute DOMHighResTimeStamp timestamp;
|
||||
|
||||
/**
|
||||
* position, linearVelocity, and linearAcceleration are 3-component vectors.
|
||||
* position is relative to a sitting space. Transforming this point with
|
||||
@ -135,6 +133,21 @@ interface VRPose {
|
||||
[Constant, Throws] readonly attribute Float32Array? angularAcceleration;
|
||||
};
|
||||
|
||||
[Constructor,
|
||||
Pref="dom.vr.enabled",
|
||||
HeaderFile="mozilla/dom/VRDisplay.h"]
|
||||
interface VRFrameData {
|
||||
readonly attribute DOMHighResTimeStamp timestamp;
|
||||
|
||||
[Throws, Pure] readonly attribute Float32Array leftProjectionMatrix;
|
||||
[Throws, Pure] readonly attribute Float32Array leftViewMatrix;
|
||||
|
||||
[Throws, Pure] readonly attribute Float32Array rightProjectionMatrix;
|
||||
[Throws, Pure] readonly attribute Float32Array rightViewMatrix;
|
||||
|
||||
[Pure] readonly attribute VRPose pose;
|
||||
};
|
||||
|
||||
[Pref="dom.vr.enabled",
|
||||
HeaderFile="mozilla/dom/VRDisplay.h"]
|
||||
interface VREyeParameters {
|
||||
@ -189,6 +202,12 @@ interface VRDisplay : EventTarget {
|
||||
*/
|
||||
[Constant] readonly attribute DOMString displayName;
|
||||
|
||||
/**
|
||||
* Populates the passed VRFrameData with the information required to render
|
||||
* the current frame.
|
||||
*/
|
||||
boolean getFrameData(VRFrameData frameData);
|
||||
|
||||
/**
|
||||
* Return a VRPose containing the future predicted pose of the VRDisplay
|
||||
* when the current frame will be presented. Subsequent calls to getPose()
|
||||
@ -200,13 +219,6 @@ interface VRDisplay : EventTarget {
|
||||
*/
|
||||
[NewObject] VRPose getPose();
|
||||
|
||||
/**
|
||||
* Return the current instantaneous pose of the VRDisplay, with no
|
||||
* prediction applied. Every call to getImmediatePose() may
|
||||
* return a different value, even within a single frame.
|
||||
*/
|
||||
[NewObject] VRPose getImmediatePose();
|
||||
|
||||
/**
|
||||
* Reset the pose for this display, treating its current position and
|
||||
* orientation as the "origin/zero" values. VRPose.position,
|
||||
|
@ -293,6 +293,7 @@ WEBIDL_FILES = [
|
||||
'KeyEvent.webidl',
|
||||
'KeyframeAnimationOptions.webidl',
|
||||
'KeyframeEffect.webidl',
|
||||
'KeyIdsInitData.webidl',
|
||||
'LegacyQueryInterface.webidl',
|
||||
'LinkStyle.webidl',
|
||||
'ListBoxObject.webidl',
|
||||
|
@ -1818,11 +1818,7 @@ XMLHttpRequestMainThread::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
||||
nsAutoCString file;
|
||||
nsAutoCString scheme;
|
||||
uri->GetScheme(scheme);
|
||||
if (scheme.LowerCaseEqualsLiteral("app")) {
|
||||
uri->GetPath(file);
|
||||
// The actual file inside zip package has no leading slash.
|
||||
file.Trim("/", true, false, false);
|
||||
} else if (scheme.LowerCaseEqualsLiteral("jar")) {
|
||||
if (scheme.LowerCaseEqualsLiteral("jar")) {
|
||||
nsCOMPtr<nsIJARURI> jarURI = do_QueryInterface(uri);
|
||||
if (jarURI) {
|
||||
jarURI->GetJAREntry(file);
|
||||
@ -2897,8 +2893,7 @@ XMLHttpRequestMainThread::SendInternal(const RequestBodyBase* aBody)
|
||||
rv = mChannel->GetURI(getter_AddRefs(uri));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
uri->GetScheme(scheme);
|
||||
if (scheme.LowerCaseEqualsLiteral("app") ||
|
||||
scheme.LowerCaseEqualsLiteral("jar")) {
|
||||
if (scheme.LowerCaseEqualsLiteral("jar")) {
|
||||
mIsMappedArrayBuffer = true;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#if defined(XP_WIN)
|
||||
# include "mozilla/gfx/DeviceManagerDx.h"
|
||||
#endif
|
||||
#include "mozilla/ipc/CrashReporterHost.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
@ -113,9 +114,27 @@ GPUChild::RecvGraphicsError(const nsCString& aError)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GPUChild::RecvInitCrashReporter(Shmem&& aShmem)
|
||||
{
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
mCrashReporter = MakeUnique<ipc::CrashReporterHost>(GeckoProcessType_GPU, aShmem);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GPUChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
if (aWhy == AbnormalShutdown) {
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
if (mCrashReporter) {
|
||||
mCrashReporter->GenerateCrashReport(OtherPid());
|
||||
mCrashReporter = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
gfxVars::RemoveReceiver(this);
|
||||
mHost->OnChannelClosed();
|
||||
}
|
||||
|
@ -12,6 +12,9 @@
|
||||
#include "mozilla/gfx/gfxVarReceiver.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
class CrashReporterHost;
|
||||
} // namespace
|
||||
namespace gfx {
|
||||
|
||||
class GPUProcessHost;
|
||||
@ -34,6 +37,7 @@ public:
|
||||
// PGPUChild overrides.
|
||||
bool RecvInitComplete(const GPUDeviceData& aData) override;
|
||||
bool RecvReportCheckerboard(const uint32_t& aSeverity, const nsCString& aLog) override;
|
||||
bool RecvInitCrashReporter(Shmem&& shmem) override;
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
bool RecvGraphicsError(const nsCString& aError) override;
|
||||
|
||||
@ -41,6 +45,7 @@ public:
|
||||
|
||||
private:
|
||||
GPUProcessHost* mHost;
|
||||
UniquePtr<ipc::CrashReporterHost> mCrashReporter;
|
||||
bool mGPUReady;
|
||||
};
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "GPUProcessHost.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/ipc/CrashReporterClient.h"
|
||||
#include "mozilla/ipc/ProcessChild.h"
|
||||
#include "mozilla/layers/APZThreadUtils.h"
|
||||
#include "mozilla/layers/APZCTreeManager.h"
|
||||
@ -27,6 +28,7 @@
|
||||
#include "VRManager.h"
|
||||
#include "VRManagerParent.h"
|
||||
#include "VsyncBridgeParent.h"
|
||||
#include "nsExceptionHandler.h"
|
||||
#if defined(XP_WIN)
|
||||
# include "DeviceManagerD3D9.h"
|
||||
# include "mozilla/gfx/DeviceManagerDx.h"
|
||||
@ -70,6 +72,11 @@ GPUParent::Init(base::ProcessId aParentPid,
|
||||
|
||||
nsDebugImpl::SetMultiprocessMode("GPU");
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
// Init crash reporter support.
|
||||
CrashReporterClient::InitSingleton(this);
|
||||
#endif
|
||||
|
||||
// Ensure gfxPrefs are initialized.
|
||||
gfxPrefs::GetSingleton();
|
||||
gfxConfig::Init();
|
||||
@ -320,6 +327,9 @@ GPUParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
gfxVars::Shutdown();
|
||||
gfxConfig::Shutdown();
|
||||
gfxPrefs::DestroySingleton();
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
CrashReporterClient::DestroySingleton();
|
||||
#endif
|
||||
NS_ShutdownXPCOM(nullptr);
|
||||
XRE_ShutdownChildProcess();
|
||||
}
|
||||
|
@ -942,6 +942,14 @@ struct ParamTraits<mozilla::StereoMode>
|
||||
mozilla::StereoMode::MAX>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::YUVColorSpace>
|
||||
: public ContiguousEnumSerializer<
|
||||
mozilla::YUVColorSpace,
|
||||
mozilla::YUVColorSpace::BT601,
|
||||
mozilla::YUVColorSpace::UNKNOWN>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::ScrollableLayerGuid>
|
||||
{
|
||||
|
@ -78,6 +78,8 @@ child:
|
||||
|
||||
// Graphics errors, analogous to PContent::GraphicsError
|
||||
async GraphicsError(nsCString aError);
|
||||
|
||||
async InitCrashReporter(Shmem shmem);
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
@ -68,7 +68,10 @@ IPDL_SOURCES = [
|
||||
'PVsyncBridge.ipdl',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += ['/dom/ipc']
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/ipc',
|
||||
'/toolkit/crashreporter',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
|
@ -158,6 +158,7 @@ BufferTextureData::CreateInternal(LayersIPCChannel* aAllocator,
|
||||
BufferTextureData*
|
||||
BufferTextureData::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
|
||||
int32_t aBufferSize,
|
||||
YUVColorSpace aYUVColorSpace,
|
||||
TextureFlags aTextureFlags)
|
||||
{
|
||||
if (aBufferSize == 0 || !gfx::Factory::CheckBufferSize(aBufferSize)) {
|
||||
@ -171,6 +172,7 @@ BufferTextureData::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
|
||||
// afterwards since we don't know the dimensions of the texture at this point.
|
||||
BufferDescriptor desc = YCbCrDescriptor(gfx::IntSize(), gfx::IntSize(),
|
||||
0, 0, 0, StereoMode::MONO,
|
||||
aYUVColorSpace,
|
||||
hasIntermediateBuffer);
|
||||
|
||||
return CreateInternal(aAllocator->GetTextureForwarder(), desc, gfx::BackendType::NONE, aBufferSize,
|
||||
@ -182,6 +184,7 @@ BufferTextureData::CreateForYCbCr(KnowsCompositor* aAllocator,
|
||||
gfx::IntSize aYSize,
|
||||
gfx::IntSize aCbCrSize,
|
||||
StereoMode aStereoMode,
|
||||
YUVColorSpace aYUVColorSpace,
|
||||
TextureFlags aTextureFlags)
|
||||
{
|
||||
uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize(aYSize, aCbCrSize);
|
||||
@ -201,7 +204,7 @@ BufferTextureData::CreateForYCbCr(KnowsCompositor* aAllocator,
|
||||
: true;
|
||||
|
||||
YCbCrDescriptor descriptor = YCbCrDescriptor(aYSize, aCbCrSize, yOffset, cbOffset,
|
||||
crOffset, aStereoMode,
|
||||
crOffset, aStereoMode, aYUVColorSpace,
|
||||
hasIntermediateBuffer);
|
||||
|
||||
return CreateInternal(aAllocator ? aAllocator->GetTextureForwarder() : nullptr, descriptor,
|
||||
@ -244,6 +247,12 @@ BufferTextureData::GetCbCrSize() const
|
||||
return ImageDataSerializer::CbCrSizeFromBufferDescriptor(mDescriptor);
|
||||
}
|
||||
|
||||
Maybe<YUVColorSpace>
|
||||
BufferTextureData::GetYUVColorSpace() const
|
||||
{
|
||||
return ImageDataSerializer::YUVColorSpaceFromBufferDescriptor(mDescriptor);
|
||||
}
|
||||
|
||||
Maybe<StereoMode>
|
||||
BufferTextureData::GetStereoMode() const
|
||||
{
|
||||
|
@ -32,6 +32,7 @@ public:
|
||||
gfx::IntSize aYSize,
|
||||
gfx::IntSize aCbCrSize,
|
||||
StereoMode aStereoMode,
|
||||
YUVColorSpace aYUVColorSpace,
|
||||
TextureFlags aTextureFlags);
|
||||
|
||||
// It is generally better to use CreateForYCbCr instead.
|
||||
@ -39,6 +40,7 @@ public:
|
||||
// offsets in the buffer.
|
||||
static BufferTextureData* CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
|
||||
int32_t aSize,
|
||||
YUVColorSpace aYUVColorSpace,
|
||||
TextureFlags aTextureFlags);
|
||||
|
||||
virtual bool Lock(OpenMode aMode, FenceHandle*) override { return true; }
|
||||
@ -63,6 +65,8 @@ public:
|
||||
|
||||
Maybe<gfx::IntSize> GetCbCrSize() const;
|
||||
|
||||
Maybe<YUVColorSpace> GetYUVColorSpace() const;
|
||||
|
||||
Maybe<StereoMode> GetStereoMode() const;
|
||||
|
||||
protected:
|
||||
|
@ -688,6 +688,7 @@ struct PlanarYCbCrData {
|
||||
uint32_t mPicY;
|
||||
gfx::IntSize mPicSize;
|
||||
StereoMode mStereoMode;
|
||||
YUVColorSpace mYUVColorSpace;
|
||||
|
||||
gfx::IntRect GetPictureRect() const {
|
||||
return gfx::IntRect(mPicX, mPicY,
|
||||
@ -700,6 +701,7 @@ struct PlanarYCbCrData {
|
||||
, mCbChannel(nullptr), mCrChannel(nullptr)
|
||||
, mCbCrStride(0), mCbCrSize(0, 0) , mCbSkip(0), mCrSkip(0)
|
||||
, mPicX(0), mPicY(0), mPicSize(0, 0), mStereoMode(StereoMode::MONO)
|
||||
, mYUVColorSpace(YUVColorSpace::BT601)
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -135,6 +135,20 @@ Maybe<gfx::IntSize> CbCrSizeFromBufferDescriptor(const BufferDescriptor& aDescri
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<YUVColorSpace> YUVColorSpaceFromBufferDescriptor(const BufferDescriptor& aDescriptor)
|
||||
{
|
||||
{
|
||||
switch (aDescriptor.type()) {
|
||||
case BufferDescriptor::TRGBDescriptor:
|
||||
return Nothing();
|
||||
case BufferDescriptor::TYCbCrDescriptor:
|
||||
return Some(aDescriptor.get_YCbCrDescriptor().yUVColorSpace());
|
||||
default:
|
||||
MOZ_CRASH("GFX: CbCrSizeFromBufferDescriptor");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<StereoMode> StereoModeFromBufferDescriptor(const BufferDescriptor& aDescriptor)
|
||||
{
|
||||
switch (aDescriptor.type()) {
|
||||
@ -202,6 +216,7 @@ DataSourceSurfaceFromYCbCrDescriptor(uint8_t* aBuffer, const YCbCrDescriptor& aD
|
||||
ycbcrData.mCbCrStride = cbCrStride;
|
||||
ycbcrData.mCbCrSize = cbCrSize;
|
||||
ycbcrData.mPicSize = ySize;
|
||||
ycbcrData.mYUVColorSpace = aDescriptor.yUVColorSpace();
|
||||
|
||||
gfx::ConvertYCbCrToRGB(ycbcrData,
|
||||
gfx::SurfaceFormat::B8G8R8X8,
|
||||
@ -236,6 +251,7 @@ ConvertAndScaleFromYCbCrDescriptor(uint8_t* aBuffer,
|
||||
ycbcrData.mCbCrStride = cbCrStride;
|
||||
ycbcrData.mCbCrSize = cbCrSize;
|
||||
ycbcrData.mPicSize = ySize;
|
||||
ycbcrData.mYUVColorSpace = aDescriptor.yUVColorSpace();
|
||||
|
||||
gfx::ConvertYCbCrToRGB(ycbcrData, aDestFormat, aDestSize, aDestBuffer, aStride);
|
||||
}
|
||||
|
@ -60,6 +60,8 @@ gfx::IntSize SizeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
|
||||
|
||||
Maybe<gfx::IntSize> CbCrSizeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
|
||||
|
||||
Maybe<YUVColorSpace> YUVColorSpaceFromBufferDescriptor(const BufferDescriptor& aDescriptor);
|
||||
|
||||
Maybe<StereoMode> StereoModeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
|
||||
|
||||
uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
|
||||
|
@ -115,6 +115,13 @@ enum class StereoMode {
|
||||
MAX,
|
||||
};
|
||||
|
||||
enum class YUVColorSpace {
|
||||
BT601,
|
||||
BT709,
|
||||
// This represents the unknown format.
|
||||
UNKNOWN,
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
@ -123,6 +123,7 @@ ImageClient::CreateTextureClientForImage(Image* aImage, KnowsCompositor* aForwar
|
||||
}
|
||||
texture = TextureClient::CreateForYCbCr(aForwarder,
|
||||
data->mYSize, data->mCbCrSize, data->mStereoMode,
|
||||
data->mYUVColorSpace,
|
||||
TextureFlags::DEFAULT);
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
@ -231,7 +232,6 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag
|
||||
RefPtr<GonkNativeHandle::NhObj> nhObj = overlayImage->GetSidebandStream().GetDupNhObj();
|
||||
GonkNativeHandle handle(nhObj);
|
||||
if (!handle.IsValid()) {
|
||||
gfxWarning() << "ImageClientSingle::UpdateImage failed in GetDupNhObj";
|
||||
return false;
|
||||
}
|
||||
source.handle() = OverlayHandle(handle);
|
||||
|
@ -1280,6 +1280,7 @@ TextureClient::CreateForYCbCr(KnowsCompositor* aAllocator,
|
||||
gfx::IntSize aYSize,
|
||||
gfx::IntSize aCbCrSize,
|
||||
StereoMode aStereoMode,
|
||||
YUVColorSpace aYUVColorSpace,
|
||||
TextureFlags aTextureFlags)
|
||||
{
|
||||
// The only reason we allow aAllocator to be null is for gtests
|
||||
@ -1293,7 +1294,8 @@ TextureClient::CreateForYCbCr(KnowsCompositor* aAllocator,
|
||||
}
|
||||
|
||||
TextureData* data = BufferTextureData::CreateForYCbCr(aAllocator, aYSize, aCbCrSize,
|
||||
aStereoMode, aTextureFlags);
|
||||
aStereoMode, aYUVColorSpace,
|
||||
aTextureFlags);
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -1306,6 +1308,7 @@ TextureClient::CreateForYCbCr(KnowsCompositor* aAllocator,
|
||||
already_AddRefed<TextureClient>
|
||||
TextureClient::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
|
||||
size_t aSize,
|
||||
YUVColorSpace aYUVColorSpace,
|
||||
TextureFlags aTextureFlags)
|
||||
{
|
||||
// also test the validity of aAllocator
|
||||
@ -1315,7 +1318,7 @@ TextureClient::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
|
||||
}
|
||||
|
||||
TextureData* data =
|
||||
BufferTextureData::CreateForYCbCrWithBufferSize(aAllocator, aSize,
|
||||
BufferTextureData::CreateForYCbCrWithBufferSize(aAllocator, aSize, aYUVColorSpace,
|
||||
aTextureFlags);
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
|
@ -367,6 +367,7 @@ public:
|
||||
gfx::IntSize aYSize,
|
||||
gfx::IntSize aCbCrSize,
|
||||
StereoMode aStereoMode,
|
||||
YUVColorSpace aYUVColorSpace,
|
||||
TextureFlags aTextureFlags);
|
||||
|
||||
// Creates and allocates a TextureClient (can be accessed through raw
|
||||
@ -385,6 +386,7 @@ public:
|
||||
static already_AddRefed<TextureClient>
|
||||
CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
|
||||
size_t aSize,
|
||||
YUVColorSpace aYUVColorSpace,
|
||||
TextureFlags aTextureFlags);
|
||||
|
||||
// Creates and allocates a TextureClient of the same type.
|
||||
|
@ -106,6 +106,8 @@ YCbCrTextureClientAllocationHelper::IsCompatible(TextureClient* aTextureClient)
|
||||
aTextureClient->GetSize() != mData.mYSize ||
|
||||
bufferData->GetCbCrSize().isNothing() ||
|
||||
bufferData->GetCbCrSize().ref() != mData.mCbCrSize ||
|
||||
bufferData->GetYUVColorSpace().isNothing() ||
|
||||
bufferData->GetYUVColorSpace().ref() != mData.mYUVColorSpace ||
|
||||
bufferData->GetStereoMode().isNothing() ||
|
||||
bufferData->GetStereoMode().ref() != mData.mStereoMode) {
|
||||
return false;
|
||||
@ -119,6 +121,7 @@ YCbCrTextureClientAllocationHelper::Allocate(KnowsCompositor* aAllocator)
|
||||
return TextureClient::CreateForYCbCr(aAllocator,
|
||||
mData.mYSize, mData.mCbCrSize,
|
||||
mData.mStereoMode,
|
||||
mData.mYUVColorSpace,
|
||||
mTextureFlags);
|
||||
}
|
||||
|
||||
@ -165,12 +168,6 @@ TextureClientRecycleAllocator::CreateOrRecycle(gfx::SurfaceFormat aFormat,
|
||||
already_AddRefed<TextureClient>
|
||||
TextureClientRecycleAllocator::CreateOrRecycle(ITextureClientAllocationHelper& aHelper)
|
||||
{
|
||||
// TextureAllocationFlags is actually used only by ContentClient.
|
||||
// This class does not handle ContentClient's TextureClient allocation.
|
||||
MOZ_ASSERT(aHelper.mAllocationFlags == TextureAllocationFlags::ALLOC_DEFAULT ||
|
||||
aHelper.mAllocationFlags == TextureAllocationFlags::ALLOC_DISALLOW_BUFFERTEXTURECLIENT ||
|
||||
aHelper.mAllocationFlags == TextureAllocationFlags::ALLOC_FOR_OUT_OF_BAND_CONTENT ||
|
||||
aHelper.mAllocationFlags == TextureAllocationFlags::ALLOC_MANUAL_SYNCHRONIZATION);
|
||||
MOZ_ASSERT(aHelper.mTextureFlags & TextureFlags::RECYCLE);
|
||||
|
||||
RefPtr<TextureClientHolder> textureHolder;
|
||||
|
@ -8,6 +8,7 @@ using struct mozilla::layers::MagicGrallocBufferHandle from "gfxipc/ShadowLayerU
|
||||
using struct mozilla::layers::GrallocBufferRef from "gfxipc/ShadowLayerUtils.h";
|
||||
using struct mozilla::layers::SurfaceDescriptorX11 from "gfxipc/ShadowLayerUtils.h";
|
||||
using mozilla::StereoMode from "ImageTypes.h";
|
||||
using mozilla::YUVColorSpace from "ImageTypes.h";
|
||||
using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
|
||||
using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
|
||||
using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
|
||||
@ -115,6 +116,7 @@ struct YCbCrDescriptor {
|
||||
uint32_t cbOffset;
|
||||
uint32_t crOffset;
|
||||
StereoMode stereoMode;
|
||||
YUVColorSpace yUVColorSpace;
|
||||
bool hasIntermediateBuffer;
|
||||
};
|
||||
|
||||
|
@ -116,8 +116,10 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// XXX Add YUVColorSpace handling. Use YUVColorSpace::BT601 for now.
|
||||
mTextureClient = TextureClient::CreateForYCbCrWithBufferSize(mCompositable->GetForwarder(),
|
||||
size,
|
||||
YUVColorSpace::BT601,
|
||||
mCompositable->GetTextureFlags());
|
||||
|
||||
// get new buffer _without_ setting mBuffer.
|
||||
@ -163,7 +165,7 @@ SharedPlanarYCbCrImage::AdoptData(const Data &aData)
|
||||
|
||||
static_cast<BufferTextureData*>(mTextureClient->GetInternalData())->SetDesciptor(
|
||||
YCbCrDescriptor(aData.mYSize, aData.mCbCrSize, yOffset, cbOffset, crOffset,
|
||||
aData.mStereoMode, hasIntermediateBuffer)
|
||||
aData.mStereoMode, aData.mYUVColorSpace, hasIntermediateBuffer)
|
||||
);
|
||||
|
||||
return true;
|
||||
@ -219,6 +221,7 @@ SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData)
|
||||
mData.mPicY = aData.mPicY;
|
||||
mData.mPicSize = aData.mPicSize;
|
||||
mData.mStereoMode = aData.mStereoMode;
|
||||
mData.mYUVColorSpace = aData.mYUVColorSpace;
|
||||
// those members are not always equal to aData's, due to potentially different
|
||||
// packing.
|
||||
mData.mYSkip = 0;
|
||||
|
@ -258,6 +258,7 @@ TEST(Layers, TextureYCbCrSerialization) {
|
||||
clientData.mYStride = ySurface->Stride();
|
||||
clientData.mCbCrStride = cbSurface->Stride();
|
||||
clientData.mStereoMode = StereoMode::MONO;
|
||||
clientData.mYUVColorSpace = YUVColorSpace::BT601;
|
||||
clientData.mYSkip = 0;
|
||||
clientData.mCbSkip = 0;
|
||||
clientData.mCrSkip = 0;
|
||||
@ -266,7 +267,8 @@ TEST(Layers, TextureYCbCrSerialization) {
|
||||
clientData.mPicX = 0;
|
||||
|
||||
RefPtr<TextureClient> client = TextureClient::CreateForYCbCr(nullptr, clientData.mYSize, clientData.mCbCrSize,
|
||||
StereoMode::MONO, TextureFlags::DEALLOCATE_CLIENT);
|
||||
StereoMode::MONO, YUVColorSpace::BT601,
|
||||
TextureFlags::DEALLOCATE_CLIENT);
|
||||
|
||||
TestTextureClientYCbCr(client, clientData);
|
||||
|
||||
|
@ -110,7 +110,7 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry,
|
||||
static_cast<gfxDWriteFontFamily*>(fontList->GetDefaultFont(aFontStyle));
|
||||
|
||||
mFont = defaultFontFamily->GetDefaultFont();
|
||||
NS_WARNING("Using default font");
|
||||
MOZ_ASSERT(mFont);
|
||||
}
|
||||
|
||||
HRESULT hr = mFont->GetFontFamily(getter_AddRefs(mFontFamily));
|
||||
|
@ -212,21 +212,26 @@ gfxTextRun::ReleaseFontGroup()
|
||||
}
|
||||
|
||||
bool
|
||||
gfxTextRun::SetPotentialLineBreaks(Range aRange, uint8_t *aBreakBefore)
|
||||
gfxTextRun::SetPotentialLineBreaks(Range aRange, const uint8_t* aBreakBefore)
|
||||
{
|
||||
NS_ASSERTION(aRange.end <= GetLength(), "Overflow");
|
||||
|
||||
uint32_t changed = 0;
|
||||
uint32_t i;
|
||||
CompressedGlyph *charGlyphs = mCharacterGlyphs + aRange.start;
|
||||
for (i = 0; i < aRange.Length(); ++i) {
|
||||
uint8_t canBreak = aBreakBefore[i];
|
||||
if (canBreak && !charGlyphs[i].IsClusterStart()) {
|
||||
// This can happen ... there is no guarantee that our linebreaking rules
|
||||
// align with the platform's idea of what constitutes a cluster.
|
||||
canBreak = CompressedGlyph::FLAG_BREAK_TYPE_NONE;
|
||||
CompressedGlyph* cg = mCharacterGlyphs + aRange.start;
|
||||
const CompressedGlyph* const end = cg + aRange.Length();
|
||||
while (cg < end) {
|
||||
uint8_t canBreak = *aBreakBefore++;
|
||||
if (canBreak && !cg->IsClusterStart()) {
|
||||
// XXX If we replace the line-breaker with one based more closely
|
||||
// on UAX#14 (e.g. using ICU), this may not be needed any more.
|
||||
// Avoid possible breaks inside a cluster, EXCEPT when the previous
|
||||
// character was a space (compare UAX#14 rules LB9, LB10).
|
||||
if (cg == mCharacterGlyphs || !(cg - 1)->CharIsSpace()) {
|
||||
canBreak = CompressedGlyph::FLAG_BREAK_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
changed |= charGlyphs[i].SetCanBreakBefore(canBreak);
|
||||
changed |= cg->SetCanBreakBefore(canBreak);
|
||||
++cg;
|
||||
}
|
||||
return changed != 0;
|
||||
}
|
||||
|
@ -171,7 +171,8 @@ public:
|
||||
* @return true if this changed the linebreaks, false if the new line
|
||||
* breaks are the same as the old
|
||||
*/
|
||||
virtual bool SetPotentialLineBreaks(Range aRange, uint8_t *aBreakBefore);
|
||||
virtual bool SetPotentialLineBreaks(Range aRange,
|
||||
const uint8_t* aBreakBefore);
|
||||
|
||||
/**
|
||||
* Layout provides PropertyProvider objects. These allow detection of
|
||||
|
@ -23,7 +23,8 @@ VRDisplayManager::AllocateDisplayID()
|
||||
}
|
||||
|
||||
Matrix4x4
|
||||
VRFieldOfView::ConstructProjectionMatrix(float zNear, float zFar, bool rightHanded)
|
||||
VRFieldOfView::ConstructProjectionMatrix(float zNear, float zFar,
|
||||
bool rightHanded) const
|
||||
{
|
||||
float upTan = tan(upDegrees * M_PI / 180.0);
|
||||
float downTan = tan(downDegrees * M_PI / 180.0);
|
||||
|
@ -112,7 +112,7 @@ struct VRFieldOfView {
|
||||
leftDegrees == 0.0;
|
||||
}
|
||||
|
||||
Matrix4x4 ConstructProjectionMatrix(float zNear, float zFar, bool rightHanded);
|
||||
Matrix4x4 ConstructProjectionMatrix(float zNear, float zFar, bool rightHanded) const;
|
||||
|
||||
double upDegrees;
|
||||
double rightDegrees;
|
||||
|
@ -118,6 +118,7 @@ ConvertYCbCrToRGB(const layers::PlanarYCbCrData& aData,
|
||||
aData.mCbCrStride,
|
||||
aStride,
|
||||
yuvtype,
|
||||
aData.mYUVColorSpace,
|
||||
FILTER_BILINEAR);
|
||||
} else { // no prescale
|
||||
#if defined(HAVE_YCBCR_TO_RGB565)
|
||||
@ -147,7 +148,8 @@ ConvertYCbCrToRGB(const layers::PlanarYCbCrData& aData,
|
||||
aData.mYStride,
|
||||
aData.mCbCrStride,
|
||||
aStride,
|
||||
yuvtype);
|
||||
yuvtype,
|
||||
aData.mYUVColorSpace);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ struct YUVBuferIter {
|
||||
const uint8* src_v;
|
||||
|
||||
uint32 src_fourcc;
|
||||
const struct YuvConstants* yuvconstants;
|
||||
int y_index;
|
||||
const uint8* src_row_y;
|
||||
const uint8* src_row_u;
|
||||
@ -200,15 +201,20 @@ static void YUVBuferIter_MoveToNextRowForI420(YUVBuferIter& iter) {
|
||||
}
|
||||
|
||||
static __inline void YUVBuferIter_ConvertToARGBRow(YUVBuferIter& iter, uint8* argb_row) {
|
||||
iter.YUVToARGBRow(iter.src_row_y, iter.src_row_u, iter.src_row_v, argb_row, &kYuvI601Constants, iter.src_width);
|
||||
iter.YUVToARGBRow(iter.src_row_y, iter.src_row_u, iter.src_row_v, argb_row, iter.yuvconstants, iter.src_width);
|
||||
}
|
||||
|
||||
void YUVBuferIter_Init(YUVBuferIter& iter, uint32 src_fourcc) {
|
||||
void YUVBuferIter_Init(YUVBuferIter& iter, uint32 src_fourcc, mozilla::YUVColorSpace yuv_color_space) {
|
||||
iter.src_fourcc = src_fourcc;
|
||||
iter.y_index = 0;
|
||||
iter.src_row_y = iter.src_y;
|
||||
iter.src_row_u = iter.src_u;
|
||||
iter.src_row_v = iter.src_v;
|
||||
if (yuv_color_space == mozilla::YUVColorSpace::BT709) {
|
||||
iter.yuvconstants = &kYuvH709Constants;
|
||||
} else {
|
||||
iter.yuvconstants = &kYuvI601Constants;
|
||||
}
|
||||
|
||||
if (src_fourcc == FOURCC_I444) {
|
||||
YUVBuferIter_InitI444(iter);
|
||||
@ -241,7 +247,8 @@ static void ScaleYUVToARGBDown2(int src_width, int src_height,
|
||||
uint8* dst_argb,
|
||||
int x, int dx, int y, int dy,
|
||||
enum FilterMode filtering,
|
||||
uint32 src_fourcc) {
|
||||
uint32 src_fourcc,
|
||||
mozilla::YUVColorSpace yuv_color_space) {
|
||||
int j;
|
||||
|
||||
// Allocate 2 rows of ARGB for source conversion.
|
||||
@ -259,7 +266,7 @@ static void ScaleYUVToARGBDown2(int src_width, int src_height,
|
||||
iter.src_y = src_y;
|
||||
iter.src_u = src_u;
|
||||
iter.src_v = src_v;
|
||||
YUVBuferIter_Init(iter, src_fourcc);
|
||||
YUVBuferIter_Init(iter, src_fourcc, yuv_color_space);
|
||||
|
||||
void (*ScaleARGBRowDown2)(const uint8* src_argb, ptrdiff_t src_stride,
|
||||
uint8* dst_argb, int dst_width) =
|
||||
@ -377,7 +384,8 @@ static void ScaleYUVToARGBDownEven(int src_width, int src_height,
|
||||
uint8* dst_argb,
|
||||
int x, int dx, int y, int dy,
|
||||
enum FilterMode filtering,
|
||||
uint32 src_fourcc) {
|
||||
uint32 src_fourcc,
|
||||
mozilla::YUVColorSpace yuv_color_space) {
|
||||
int j;
|
||||
// Allocate 2 rows of ARGB for source conversion.
|
||||
const int kRowSize = (src_width * 4 + 15) & ~15;
|
||||
@ -424,7 +432,7 @@ static void ScaleYUVToARGBDownEven(int src_width, int src_height,
|
||||
iter.src_y = src_y;
|
||||
iter.src_u = src_u;
|
||||
iter.src_v = src_v;
|
||||
YUVBuferIter_Init(iter, src_fourcc);
|
||||
YUVBuferIter_Init(iter, src_fourcc, yuv_color_space);
|
||||
|
||||
const int dyi = dy >> 16;
|
||||
int lastyi = yi;
|
||||
@ -497,7 +505,8 @@ static void ScaleYUVToARGBBilinearDown(int src_width, int src_height,
|
||||
uint8* dst_argb,
|
||||
int x, int dx, int y, int dy,
|
||||
enum FilterMode filtering,
|
||||
uint32 src_fourcc) {
|
||||
uint32 src_fourcc,
|
||||
mozilla::YUVColorSpace yuv_color_space) {
|
||||
int j;
|
||||
void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
|
||||
ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
|
||||
@ -583,7 +592,7 @@ static void ScaleYUVToARGBBilinearDown(int src_width, int src_height,
|
||||
iter.src_y = src_y;
|
||||
iter.src_u = src_u;
|
||||
iter.src_v = src_v;
|
||||
YUVBuferIter_Init(iter, src_fourcc);
|
||||
YUVBuferIter_Init(iter, src_fourcc, yuv_color_space);
|
||||
iter.MoveTo(iter, yi);
|
||||
|
||||
// TODO(fbarchard): Consider not allocating row buffer for kFilterLinear.
|
||||
@ -665,7 +674,8 @@ static void ScaleYUVToARGBBilinearUp(int src_width, int src_height,
|
||||
uint8* dst_argb,
|
||||
int x, int dx, int y, int dy,
|
||||
enum FilterMode filtering,
|
||||
uint32 src_fourcc) {
|
||||
uint32 src_fourcc,
|
||||
mozilla::YUVColorSpace yuv_color_space) {
|
||||
int j;
|
||||
void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
|
||||
ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
|
||||
@ -762,7 +772,7 @@ static void ScaleYUVToARGBBilinearUp(int src_width, int src_height,
|
||||
iter.src_y = src_y;
|
||||
iter.src_u = src_u;
|
||||
iter.src_v = src_v;
|
||||
YUVBuferIter_Init(iter, src_fourcc);
|
||||
YUVBuferIter_Init(iter, src_fourcc, yuv_color_space);
|
||||
iter.MoveTo(iter, yi);
|
||||
|
||||
// Allocate 2 rows of ARGB.
|
||||
@ -848,7 +858,8 @@ static void ScaleYUVToARGBSimple(int src_width, int src_height,
|
||||
const uint8* src_v,
|
||||
uint8* dst_argb,
|
||||
int x, int dx, int y, int dy,
|
||||
uint32 src_fourcc) {
|
||||
uint32 src_fourcc,
|
||||
mozilla::YUVColorSpace yuv_color_space) {
|
||||
int j;
|
||||
void (*ScaleARGBCols)(uint8* dst_argb, const uint8* src_argb,
|
||||
int dst_width, int x, int dx) =
|
||||
@ -890,7 +901,7 @@ static void ScaleYUVToARGBSimple(int src_width, int src_height,
|
||||
iter.src_y = src_y;
|
||||
iter.src_u = src_u;
|
||||
iter.src_v = src_v;
|
||||
YUVBuferIter_Init(iter, src_fourcc);
|
||||
YUVBuferIter_Init(iter, src_fourcc, yuv_color_space);
|
||||
iter.MoveTo(iter, yi);
|
||||
|
||||
int lasty = yi;
|
||||
@ -916,7 +927,8 @@ static void YUVToARGBCopy(const uint8* src_y, int src_stride_y,
|
||||
int src_width, int src_height,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int dst_width, int dst_height,
|
||||
uint32 src_fourcc)
|
||||
uint32 src_fourcc,
|
||||
mozilla::YUVColorSpace yuv_color_space)
|
||||
{
|
||||
YUVBuferIter iter;
|
||||
iter.src_width = src_width;
|
||||
@ -927,7 +939,7 @@ static void YUVToARGBCopy(const uint8* src_y, int src_stride_y,
|
||||
iter.src_y = src_y;
|
||||
iter.src_u = src_u;
|
||||
iter.src_v = src_v;
|
||||
YUVBuferIter_Init(iter, src_fourcc);
|
||||
YUVBuferIter_Init(iter, src_fourcc, yuv_color_space);
|
||||
|
||||
for (int j = 0; j < dst_height; ++j) {
|
||||
YUVBuferIter_ConvertToARGBRow(iter, dst_argb);
|
||||
@ -943,7 +955,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int dst_width, int dst_height,
|
||||
enum FilterMode filtering,
|
||||
uint32 src_fourcc)
|
||||
uint32 src_fourcc,
|
||||
mozilla::YUVColorSpace yuv_color_space)
|
||||
{
|
||||
// Initial source x/y coordinate and step values as 16.16 fixed point.
|
||||
int x = 0;
|
||||
@ -979,7 +992,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
|
||||
dst_argb,
|
||||
x, dx, y, dy,
|
||||
filtering,
|
||||
src_fourcc);
|
||||
src_fourcc,
|
||||
yuv_color_space);
|
||||
return;
|
||||
}
|
||||
ScaleYUVToARGBDownEven(src_width, src_height,
|
||||
@ -994,7 +1008,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
|
||||
dst_argb,
|
||||
x, dx, y, dy,
|
||||
filtering,
|
||||
src_fourcc);
|
||||
src_fourcc,
|
||||
yuv_color_space);
|
||||
return;
|
||||
}
|
||||
// Optimized odd scale down. ie 3, 5, 7, 9x.
|
||||
@ -1008,7 +1023,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
|
||||
src_width, src_height,
|
||||
dst_argb, dst_stride_argb,
|
||||
dst_width, dst_height,
|
||||
src_fourcc);
|
||||
src_fourcc,
|
||||
yuv_color_space);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1027,7 +1043,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
|
||||
dst_argb,
|
||||
x, dx, y, dy,
|
||||
filtering,
|
||||
src_fourcc);
|
||||
src_fourcc,
|
||||
yuv_color_space);
|
||||
return;
|
||||
}
|
||||
if (filtering) {
|
||||
@ -1043,7 +1060,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
|
||||
dst_argb,
|
||||
x, dx, y, dy,
|
||||
filtering,
|
||||
src_fourcc);
|
||||
src_fourcc,
|
||||
yuv_color_space);
|
||||
return;
|
||||
}
|
||||
ScaleYUVToARGBSimple(src_width, src_height,
|
||||
@ -1057,7 +1075,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
|
||||
src_v,
|
||||
dst_argb,
|
||||
x, dx, y, dy,
|
||||
src_fourcc);
|
||||
src_fourcc,
|
||||
yuv_color_space);
|
||||
}
|
||||
|
||||
bool IsConvertSupported(uint32 src_fourcc)
|
||||
@ -1075,6 +1094,7 @@ int YUVToARGBScale(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint32 src_fourcc,
|
||||
mozilla::YUVColorSpace yuv_color_space,
|
||||
int src_width, int src_height,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int dst_width, int dst_height,
|
||||
@ -1095,7 +1115,8 @@ int YUVToARGBScale(const uint8* src_y, int src_stride_y,
|
||||
dst_argb, dst_stride_argb,
|
||||
dst_width, dst_height,
|
||||
filtering,
|
||||
src_fourcc);
|
||||
src_fourcc,
|
||||
yuv_color_space);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "libyuv/basic_types.h"
|
||||
#include "libyuv/scale.h" // For FilterMode
|
||||
|
||||
#include "ImageTypes.h" // For YUVColorSpace
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace libyuv {
|
||||
extern "C" {
|
||||
@ -23,6 +25,7 @@ int YUVToARGBScale(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint32 src_fourcc,
|
||||
mozilla::YUVColorSpace yuv_color_space,
|
||||
int src_width, int src_height,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int dst_width, int dst_height,
|
||||
|
@ -75,7 +75,8 @@ void ConvertYCbCrToRGB32(const uint8* y_buf,
|
||||
int y_pitch,
|
||||
int uv_pitch,
|
||||
int rgb_pitch,
|
||||
YUVType yuv_type) {
|
||||
YUVType yuv_type,
|
||||
YUVColorSpace yuv_color_space) {
|
||||
|
||||
|
||||
// Deprecated function's conversion is accurate.
|
||||
@ -87,7 +88,13 @@ void ConvertYCbCrToRGB32(const uint8* y_buf,
|
||||
// The function is still fast on some old intel chips.
|
||||
// See Bug 1256475.
|
||||
bool use_deprecated = gfxPrefs::YCbCrAccurateConversion() ||
|
||||
(supports_mmx() && supports_sse() && !supports_sse3());
|
||||
(supports_mmx() && supports_sse() && !supports_sse3() &&
|
||||
yuv_color_space == YUVColorSpace::BT601);
|
||||
// The deprecated function only support BT601.
|
||||
// See Bug 1210357.
|
||||
if (yuv_color_space != YUVColorSpace::BT601) {
|
||||
use_deprecated = false;
|
||||
}
|
||||
if (use_deprecated) {
|
||||
ConvertYCbCrToRGB32_deprecated(y_buf, u_buf, v_buf, rgb_buf,
|
||||
pic_x, pic_y, pic_width, pic_height,
|
||||
@ -120,12 +127,22 @@ void ConvertYCbCrToRGB32(const uint8* y_buf,
|
||||
const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
|
||||
const uint8* src_u = u_buf + (uv_pitch * pic_y + pic_x) / 2;
|
||||
const uint8* src_v = v_buf + (uv_pitch * pic_y + pic_x) / 2;
|
||||
DebugOnly<int> err = libyuv::I420ToARGB(src_y, y_pitch,
|
||||
src_u, uv_pitch,
|
||||
src_v, uv_pitch,
|
||||
rgb_buf, rgb_pitch,
|
||||
pic_width, pic_height);
|
||||
MOZ_ASSERT(!err);
|
||||
if (yuv_color_space == YUVColorSpace::BT709) {
|
||||
DebugOnly<int> err = libyuv::H420ToARGB(src_y, y_pitch,
|
||||
src_u, uv_pitch,
|
||||
src_v, uv_pitch,
|
||||
rgb_buf, rgb_pitch,
|
||||
pic_width, pic_height);
|
||||
MOZ_ASSERT(!err);
|
||||
} else {
|
||||
MOZ_ASSERT(yuv_color_space == YUVColorSpace::BT601);
|
||||
DebugOnly<int> err = libyuv::I420ToARGB(src_y, y_pitch,
|
||||
src_u, uv_pitch,
|
||||
src_v, uv_pitch,
|
||||
rgb_buf, rgb_pitch,
|
||||
pic_width, pic_height);
|
||||
MOZ_ASSERT(!err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,6 +274,7 @@ void ScaleYCbCrToRGB32(const uint8* y_buf,
|
||||
int uv_pitch,
|
||||
int rgb_pitch,
|
||||
YUVType yuv_type,
|
||||
YUVColorSpace yuv_color_space,
|
||||
ScaleFilter filter) {
|
||||
|
||||
bool use_deprecated = gfxPrefs::YCbCrAccurateConversion() ||
|
||||
@ -265,6 +283,11 @@ void ScaleYCbCrToRGB32(const uint8* y_buf,
|
||||
supports_sse3() ||
|
||||
#endif
|
||||
(supports_mmx() && supports_sse() && !supports_sse3());
|
||||
// The deprecated function only support BT601.
|
||||
// See Bug 1210357.
|
||||
if (yuv_color_space != YUVColorSpace::BT601) {
|
||||
use_deprecated = false;
|
||||
}
|
||||
if (use_deprecated) {
|
||||
ScaleYCbCrToRGB32_deprecated(y_buf, u_buf, v_buf,
|
||||
rgb_buf,
|
||||
@ -283,6 +306,7 @@ void ScaleYCbCrToRGB32(const uint8* y_buf,
|
||||
u_buf, uv_pitch,
|
||||
v_buf, uv_pitch,
|
||||
FourCCFromYUVType(yuv_type),
|
||||
yuv_color_space,
|
||||
source_width, source_height,
|
||||
rgb_buf, rgb_pitch,
|
||||
width, height,
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define MEDIA_BASE_YUV_CONVERT_H_
|
||||
|
||||
#include "chromium_types.h"
|
||||
#include "ImageTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -55,7 +56,8 @@ void ConvertYCbCrToRGB32(const uint8* yplane,
|
||||
int ystride,
|
||||
int uvstride,
|
||||
int rgbstride,
|
||||
YUVType yuv_type);
|
||||
YUVType yuv_type,
|
||||
YUVColorSpace yuv_color_space);
|
||||
|
||||
void ConvertYCbCrToRGB32_deprecated(const uint8* yplane,
|
||||
const uint8* uplane,
|
||||
@ -84,6 +86,7 @@ void ScaleYCbCrToRGB32(const uint8* yplane,
|
||||
int uvstride,
|
||||
int rgbstride,
|
||||
YUVType yuv_type,
|
||||
YUVColorSpace yuv_color_space,
|
||||
ScaleFilter filter);
|
||||
|
||||
void ScaleYCbCrToRGB32_deprecated(const uint8* yplane,
|
||||
|
66
ipc/glue/CrashReporterClient.cpp
Normal file
66
ipc/glue/CrashReporterClient.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "CrashReporterClient.h"
|
||||
#include "CrashReporterMetadataShmem.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
StaticMutex CrashReporterClient::sLock;
|
||||
StaticRefPtr<CrashReporterClient> CrashReporterClient::sClientSingleton;
|
||||
|
||||
CrashReporterClient::CrashReporterClient(const Shmem& aShmem)
|
||||
: mMetadata(new CrashReporterMetadataShmem(aShmem))
|
||||
{
|
||||
MOZ_COUNT_CTOR(CrashReporterClient);
|
||||
}
|
||||
|
||||
CrashReporterClient::~CrashReporterClient()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CrashReporterClient);
|
||||
}
|
||||
|
||||
void
|
||||
CrashReporterClient::AnnotateCrashReport(const nsCString& aKey, const nsCString& aData)
|
||||
{
|
||||
StaticMutexAutoLock lock(sLock);
|
||||
mMetadata->AnnotateCrashReport(aKey, aData);
|
||||
}
|
||||
|
||||
void
|
||||
CrashReporterClient::AppendAppNotes(const nsCString& aData)
|
||||
{
|
||||
StaticMutexAutoLock lock(sLock);
|
||||
mMetadata->AppendAppNotes(aData);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
CrashReporterClient::InitSingletonWithShmem(const Shmem& aShmem)
|
||||
{
|
||||
StaticMutexAutoLock lock(sLock);
|
||||
|
||||
MOZ_ASSERT(!sClientSingleton);
|
||||
sClientSingleton = new CrashReporterClient(aShmem);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
CrashReporterClient::DestroySingleton()
|
||||
{
|
||||
StaticMutexAutoLock lock(sLock);
|
||||
sClientSingleton = nullptr;
|
||||
}
|
||||
|
||||
/* static */ RefPtr<CrashReporterClient>
|
||||
CrashReporterClient::GetSingleton()
|
||||
{
|
||||
StaticMutexAutoLock lock(sLock);
|
||||
return sClientSingleton;
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
76
ipc/glue/CrashReporterClient.h
Normal file
76
ipc/glue/CrashReporterClient.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_ipc_CrashReporterClient_h
|
||||
#define mozilla_ipc_CrashReporterClient_h
|
||||
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/ipc/Shmem.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class CrashReporterMetadataShmem;
|
||||
|
||||
class CrashReporterClient
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CrashReporterClient);
|
||||
|
||||
// |aTopLevelProtocol| must be a top-level protocol instance, as sub-actors
|
||||
// do not have AllocUnsafeShmem. It must also have a child-to-parent message:
|
||||
//
|
||||
// async SetCrashReporterClient(Shmem shmem);
|
||||
//
|
||||
// The parent-side receive function of this message should save the shmem
|
||||
// somewhere, and when the top-level actor's ActorDestroy runs (or when the
|
||||
// crash reporter needs metadata), the shmem should be parsed.
|
||||
template <typename T>
|
||||
static bool InitSingleton(T* aToplevelProtocol) {
|
||||
// 16KB should be enough for most metadata - see bug 1278717 comment #11.
|
||||
static const size_t kShmemSize = 16 * 1024;
|
||||
|
||||
Shmem shmem;
|
||||
bool rv = aToplevelProtocol->AllocUnsafeShmem(
|
||||
kShmemSize,
|
||||
SharedMemory::TYPE_BASIC,
|
||||
&shmem);
|
||||
if (!rv) {
|
||||
return false;
|
||||
}
|
||||
|
||||
InitSingletonWithShmem(shmem);
|
||||
Unused << aToplevelProtocol->SendInitCrashReporter(shmem);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void DestroySingleton();
|
||||
static RefPtr<CrashReporterClient> GetSingleton();
|
||||
|
||||
void AnnotateCrashReport(const nsCString& aKey, const nsCString& aData);
|
||||
void AppendAppNotes(const nsCString& aData);
|
||||
|
||||
private:
|
||||
explicit CrashReporterClient(const Shmem& aShmem);
|
||||
~CrashReporterClient();
|
||||
|
||||
static void InitSingletonWithShmem(const Shmem& aShmem);
|
||||
|
||||
private:
|
||||
static StaticMutex sLock;
|
||||
static StaticRefPtr<CrashReporterClient> sClientSingleton;
|
||||
|
||||
private:
|
||||
UniquePtr<CrashReporterMetadataShmem> mMetadata;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ipc_CrashReporterClient_h
|
||||
|
124
ipc/glue/CrashReporterHost.cpp
Normal file
124
ipc/glue/CrashReporterHost.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "CrashReporterHost.h"
|
||||
#include "CrashReporterMetadataShmem.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/SyncRunnable.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
# include "nsICrashService.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
CrashReporterHost::CrashReporterHost(GeckoProcessType aProcessType,
|
||||
const Shmem& aShmem)
|
||||
: mProcessType(aProcessType),
|
||||
mShmem(aShmem),
|
||||
mStartTime(::time(nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
void
|
||||
CrashReporterHost::GenerateCrashReport(RefPtr<nsIFile> aCrashDump)
|
||||
{
|
||||
nsString dumpID;
|
||||
if (!CrashReporter::GetIDFromMinidump(aCrashDump, dumpID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CrashReporter::AnnotationTable notes;
|
||||
|
||||
nsAutoCString type;
|
||||
switch (mProcessType) {
|
||||
case GeckoProcessType_Content:
|
||||
type = NS_LITERAL_CSTRING("content");
|
||||
break;
|
||||
case GeckoProcessType_Plugin:
|
||||
case GeckoProcessType_GMPlugin:
|
||||
type = NS_LITERAL_CSTRING("plugin");
|
||||
break;
|
||||
case GeckoProcessType_GPU:
|
||||
type = NS_LITERAL_CSTRING("gpu");
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("unknown process type");
|
||||
break;
|
||||
}
|
||||
notes.Put(NS_LITERAL_CSTRING("ProcessType"), type);
|
||||
|
||||
char startTime[32];
|
||||
SprintfLiteral(startTime, "%lld", static_cast<long long>(mStartTime));
|
||||
notes.Put(NS_LITERAL_CSTRING("StartupTime"), nsDependentCString(startTime));
|
||||
|
||||
CrashReporterMetadataShmem::ReadAppNotes(mShmem, ¬es);
|
||||
|
||||
CrashReporter::AppendExtraData(dumpID, notes);
|
||||
NotifyCrashService(mProcessType, dumpID, ¬es);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
CrashReporterHost::NotifyCrashService(GeckoProcessType aProcessType,
|
||||
const nsString& aChildDumpID,
|
||||
const AnnotationTable* aNotes)
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
RefPtr<Runnable> runnable = NS_NewRunnableFunction([=] () -> void {
|
||||
CrashReporterHost::NotifyCrashService(aProcessType, aChildDumpID, aNotes);
|
||||
});
|
||||
RefPtr<nsIThread> mainThread = do_GetMainThread();
|
||||
SyncRunnable::DispatchToThread(mainThread, runnable);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!aChildDumpID.IsEmpty());
|
||||
|
||||
nsCOMPtr<nsICrashService> crashService =
|
||||
do_GetService("@mozilla.org/crashservice;1");
|
||||
if (!crashService) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t processType;
|
||||
int32_t crashType = nsICrashService::CRASH_TYPE_CRASH;
|
||||
|
||||
nsCString telemetryKey;
|
||||
|
||||
switch (aProcessType) {
|
||||
case GeckoProcessType_Content:
|
||||
processType = nsICrashService::PROCESS_TYPE_CONTENT;
|
||||
telemetryKey.AssignLiteral("content");
|
||||
break;
|
||||
case GeckoProcessType_Plugin: {
|
||||
processType = nsICrashService::PROCESS_TYPE_PLUGIN;
|
||||
telemetryKey.AssignLiteral("plugin");
|
||||
nsAutoCString val;
|
||||
if (aNotes->Get(NS_LITERAL_CSTRING("PluginHang"), &val) &&
|
||||
val.Equals(NS_LITERAL_CSTRING("1"))) {
|
||||
crashType = nsICrashService::CRASH_TYPE_HANG;
|
||||
telemetryKey.AssignLiteral("pluginhang");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GeckoProcessType_GMPlugin:
|
||||
processType = nsICrashService::PROCESS_TYPE_GMPLUGIN;
|
||||
telemetryKey.AssignLiteral("gmplugin");
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("unknown process type");
|
||||
return;
|
||||
}
|
||||
|
||||
crashService->AddCrash(processType, crashType, aChildDumpID);
|
||||
Telemetry::Accumulate(Telemetry::SUBPROCESS_CRASHES_WITH_DUMP, telemetryKey, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
63
ipc/glue/CrashReporterHost.h
Normal file
63
ipc/glue/CrashReporterHost.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_ipc_CrashReporterHost_h
|
||||
#define mozilla_ipc_CrashReporterHost_h
|
||||
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/ipc/Shmem.h"
|
||||
#include "base/process.h"
|
||||
#include "nsExceptionHandler.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
// This is the newer replacement for CrashReporterParent. It is created in
|
||||
// response to a InitCrashReporter message on a top-level actor, and simply
|
||||
// holds the metadata shmem alive until the process ends. When the process
|
||||
// terminates abnormally, the top-level should call GenerateCrashReport to
|
||||
// automatically integrate metadata.
|
||||
class CrashReporterHost
|
||||
{
|
||||
typedef mozilla::ipc::Shmem Shmem;
|
||||
typedef CrashReporter::AnnotationTable AnnotationTable;
|
||||
|
||||
public:
|
||||
CrashReporterHost(GeckoProcessType aProcessType, const Shmem& aShmem);
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
void GenerateCrashReport(base::ProcessId aPid) {
|
||||
RefPtr<nsIFile> crashDump;
|
||||
if (!XRE_TakeMinidumpForChild(aPid, getter_AddRefs(crashDump), nullptr)) {
|
||||
return;
|
||||
}
|
||||
GenerateCrashReport(crashDump);
|
||||
}
|
||||
|
||||
// This is a static helper function to notify the crash service that a
|
||||
// crash has occurred. When PCrashReporter is removed, we can make this
|
||||
// a member function. This can be called from any thread, and if not
|
||||
// called from the main thread, will post a synchronous message to the
|
||||
// main thread.
|
||||
static void NotifyCrashService(
|
||||
GeckoProcessType aProcessType,
|
||||
const nsString& aChildDumpID,
|
||||
const AnnotationTable* aNotes);
|
||||
#endif
|
||||
|
||||
private:
|
||||
void GenerateCrashReport(RefPtr<nsIFile> aCrashDump);
|
||||
|
||||
private:
|
||||
GeckoProcessType mProcessType;
|
||||
Shmem mShmem;
|
||||
time_t mStartTime;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ipc_CrashReporterHost_h
|
235
ipc/glue/CrashReporterMetadataShmem.cpp
Normal file
235
ipc/glue/CrashReporterMetadataShmem.cpp
Normal file
@ -0,0 +1,235 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "CrashReporterMetadataShmem.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
enum class EntryType : uint8_t {
|
||||
None,
|
||||
Annotation,
|
||||
};
|
||||
|
||||
CrashReporterMetadataShmem::CrashReporterMetadataShmem(const Shmem& aShmem)
|
||||
: mShmem(aShmem)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CrashReporterMetadataShmem);
|
||||
}
|
||||
|
||||
CrashReporterMetadataShmem::~CrashReporterMetadataShmem()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CrashReporterMetadataShmem);
|
||||
}
|
||||
|
||||
void
|
||||
CrashReporterMetadataShmem::AnnotateCrashReport(const nsCString& aKey, const nsCString& aData)
|
||||
{
|
||||
mNotes.Put(aKey, aData);
|
||||
SyncNotesToShmem();
|
||||
}
|
||||
|
||||
void
|
||||
CrashReporterMetadataShmem::AppendAppNotes(const nsCString& aData)
|
||||
{
|
||||
mAppNotes.Append(aData);
|
||||
mNotes.Put(NS_LITERAL_CSTRING("Notes"), mAppNotes);
|
||||
SyncNotesToShmem();
|
||||
}
|
||||
|
||||
class MOZ_STACK_CLASS MetadataShmemWriter
|
||||
{
|
||||
public:
|
||||
explicit MetadataShmemWriter(const Shmem& aShmem)
|
||||
: mCursor(aShmem.get<uint8_t>()),
|
||||
mEnd(mCursor + aShmem.Size<uint8_t>())
|
||||
{
|
||||
*mCursor = uint8_t(EntryType::None);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool WriteAnnotation(const nsCString& aKey, const nsCString& aValue) {
|
||||
// This shouldn't happen because Commit() guarantees mCursor < mEnd. But
|
||||
// we might as well be safe.
|
||||
if (mCursor >= mEnd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save the current position so we can write the entry type if the entire
|
||||
// entry fits.
|
||||
uint8_t* start = mCursor++;
|
||||
if (!Write(aKey) || !Write(aValue)) {
|
||||
return false;
|
||||
}
|
||||
return Commit(start, EntryType::Annotation);
|
||||
}
|
||||
|
||||
private:
|
||||
// On success, append a new terminal byte. On failure, rollback the cursor.
|
||||
MOZ_MUST_USE bool Commit(uint8_t* aStart, EntryType aType) {
|
||||
MOZ_ASSERT(aStart < mEnd);
|
||||
MOZ_ASSERT(EntryType(*aStart) == EntryType::None);
|
||||
|
||||
if (mCursor >= mEnd) {
|
||||
// No room for a terminating byte - rollback.
|
||||
mCursor = aStart;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Commit the entry and write a new terminal byte.
|
||||
*aStart = uint8_t(aType);
|
||||
*mCursor = uint8_t(EntryType::None);
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool Write(const nsCString& aString) {
|
||||
// 32-bit length is okay since our shmems are very small (16K),
|
||||
// a huge write would fail anyway.
|
||||
return Write(static_cast<uint32_t>(aString.Length())) &&
|
||||
Write(aString.get(), aString.Length());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
MOZ_MUST_USE bool Write(const T& aT) {
|
||||
return Write(&aT, sizeof(T));
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool Write(const void* aData, size_t aLength) {
|
||||
if (size_t(mEnd - mCursor) < aLength) {
|
||||
return false;
|
||||
}
|
||||
memcpy(mCursor, aData, aLength);
|
||||
mCursor += aLength;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// The cursor (beginning at start) always points to a single byte
|
||||
// representing the next EntryType. An EntryType is either None,
|
||||
// indicating there are no more entries, or Annotation, meaning
|
||||
// two strings follow.
|
||||
//
|
||||
// Strings are written as a 32-bit length and byte sequence. After each new
|
||||
// entry, a None entry is always appended, and a subsequent entry will
|
||||
// overwrite this byte.
|
||||
uint8_t* mCursor;
|
||||
uint8_t* mEnd;
|
||||
};
|
||||
|
||||
void
|
||||
CrashReporterMetadataShmem::SyncNotesToShmem()
|
||||
{
|
||||
MetadataShmemWriter writer(mShmem);
|
||||
|
||||
for (auto it = mNotes.Iter(); !it.Done(); it.Next()) {
|
||||
nsCString key = nsCString(it.Key());
|
||||
nsCString value = nsCString(it.Data());
|
||||
if (!writer.WriteAnnotation(key, value)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper class to iterate over metadata entries encoded in shmem.
|
||||
class MOZ_STACK_CLASS MetadataShmemReader
|
||||
{
|
||||
public:
|
||||
explicit MetadataShmemReader(const Shmem& aShmem)
|
||||
: mEntryType(EntryType::None)
|
||||
{
|
||||
mCursor = aShmem.get<uint8_t>();
|
||||
mEnd = mCursor + aShmem.Size<uint8_t>();
|
||||
|
||||
// Advance to the first item, if any.
|
||||
Next();
|
||||
}
|
||||
|
||||
bool Done() const {
|
||||
return mCursor >= mEnd || Type() == EntryType::None;
|
||||
}
|
||||
EntryType Type() const {
|
||||
return mEntryType;
|
||||
}
|
||||
void Next() {
|
||||
if (mCursor < mEnd) {
|
||||
mEntryType = EntryType(*mCursor++);
|
||||
} else {
|
||||
mEntryType = EntryType::None;
|
||||
}
|
||||
}
|
||||
|
||||
bool Read(nsCString& aOut) {
|
||||
uint32_t length = 0;
|
||||
if (!Read(&length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8_t* src = Read(length);
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aOut.Assign((const char *)src, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
bool Read(T* aOut) {
|
||||
return Read(aOut, sizeof(T));
|
||||
}
|
||||
bool Read(void* aOut, size_t aLength) {
|
||||
const uint8_t* src = Read(aLength);
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
memcpy(aOut, src, aLength);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If buffer has |aLength| bytes, return cursor and then advance it.
|
||||
// Otherwise, return null.
|
||||
const uint8_t* Read(size_t aLength) {
|
||||
if (size_t(mEnd - mCursor) < aLength) {
|
||||
return nullptr;
|
||||
}
|
||||
const uint8_t* result = mCursor;
|
||||
mCursor += aLength;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t* mCursor;
|
||||
const uint8_t* mEnd;
|
||||
EntryType mEntryType;
|
||||
};
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
void
|
||||
CrashReporterMetadataShmem::ReadAppNotes(const Shmem& aShmem, CrashReporter::AnnotationTable* aNotes)
|
||||
{
|
||||
for (MetadataShmemReader reader(aShmem); !reader.Done(); reader.Next()) {
|
||||
switch (reader.Type()) {
|
||||
case EntryType::Annotation: {
|
||||
nsCString key, value;
|
||||
if (!reader.Read(key) || !reader.Read(value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
aNotes->Put(key, value);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_ASSERTION(false, "Unknown metadata entry type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
48
ipc/glue/CrashReporterMetadataShmem.h
Normal file
48
ipc/glue/CrashReporterMetadataShmem.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_ipc_CrashReporterMetadataShmem_h
|
||||
#define mozilla_ipc_CrashReporterMetadataShmem_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mozilla/ipc/Shmem.h"
|
||||
#include "nsExceptionHandler.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class CrashReporterMetadataShmem
|
||||
{
|
||||
typedef mozilla::ipc::Shmem Shmem;
|
||||
typedef CrashReporter::AnnotationTable AnnotationTable;
|
||||
|
||||
public:
|
||||
explicit CrashReporterMetadataShmem(const Shmem& aShmem);
|
||||
~CrashReporterMetadataShmem();
|
||||
|
||||
// Metadata writers. These must only be called in child processes.
|
||||
void AnnotateCrashReport(const nsCString& aKey, const nsCString& aData);
|
||||
void AppendAppNotes(const nsCString& aData);
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
static void ReadAppNotes(const Shmem& aShmem, CrashReporter::AnnotationTable* aNotes);
|
||||
#endif
|
||||
|
||||
private:
|
||||
void SyncNotesToShmem();
|
||||
|
||||
private:
|
||||
Shmem mShmem;
|
||||
|
||||
AnnotationTable mNotes;
|
||||
nsCString mAppNotes;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ipc_CrashReporterMetadataShmem_h
|
@ -1,35 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=2 autoindent cindent expandtab: */
|
||||
/* 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/. */
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
struct FDRemap {
|
||||
FileDescriptor fd;
|
||||
int mapto;
|
||||
};
|
||||
|
||||
protocol PProcLoader
|
||||
{
|
||||
child:
|
||||
/**
|
||||
* Request B2G loader service to load content process.
|
||||
*
|
||||
* It actually calls the main() function of plugin-container.
|
||||
*/
|
||||
async Load(nsCString[] argv, nsCString[] env,
|
||||
FDRemap[] fdsRemap, uint32_t privs,
|
||||
int32_t cookie);
|
||||
|
||||
parent:
|
||||
/**
|
||||
* The acknowledgement of Load().
|
||||
*/
|
||||
async LoadComplete(int32_t pid, int32_t cookie);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "base/process_util.h"
|
||||
#include "base/task.h"
|
||||
|
||||
#ifdef OS_POSIX
|
||||
#include <errno.h>
|
||||
|
@ -15,6 +15,9 @@ EXPORTS.mozilla.ipc += [
|
||||
'BackgroundParent.h',
|
||||
'BackgroundUtils.h',
|
||||
'BrowserProcessSubThread.h',
|
||||
'CrashReporterClient.h',
|
||||
'CrashReporterHost.h',
|
||||
'CrashReporterMetadataShmem.h',
|
||||
'CrossProcessMutex.h',
|
||||
'FileDescriptor.h',
|
||||
'FileDescriptorSetChild.h',
|
||||
@ -119,6 +122,9 @@ UNIFIED_SOURCES += [
|
||||
'BackgroundImpl.cpp',
|
||||
'BackgroundUtils.cpp',
|
||||
'BrowserProcessSubThread.cpp',
|
||||
'CrashReporterClient.cpp',
|
||||
'CrashReporterHost.cpp',
|
||||
'CrashReporterMetadataShmem.cpp',
|
||||
'FileDescriptor.cpp',
|
||||
'FileDescriptorUtils.cpp',
|
||||
'InputStreamUtils.cpp',
|
||||
@ -170,14 +176,14 @@ IPDL_SOURCES = [
|
||||
'PBackgroundSharedTypes.ipdlh',
|
||||
'PBackgroundTest.ipdl',
|
||||
'PFileDescriptorSet.ipdl',
|
||||
'PProcLoader.ipdl',
|
||||
'ProtocolTypes.ipdlh',
|
||||
'PSendStream.ipdl',
|
||||
'URIParams.ipdlh',
|
||||
]
|
||||
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/ipc',
|
||||
'/toolkit/crashreporter',
|
||||
'/toolkit/xre',
|
||||
'/xpcom/threads',
|
||||
]
|
||||
@ -190,10 +196,6 @@ for var in ('MOZ_CHILD_PROCESS_NAME', 'MOZ_CHILD_PROCESS_NAME_PIE',
|
||||
'MOZ_CHILD_PROCESS_BUNDLE', 'DLL_PREFIX', 'DLL_SUFFIX'):
|
||||
DEFINES[var] = '"%s"' % CONFIG[var]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/crashreporter',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
|
||||
LOCAL_INCLUDES += [
|
||||
'/security/sandbox/chromium',
|
||||
|
@ -626,14 +626,14 @@ class AstImport : public AstNode
|
||||
DefinitionKind kind_;
|
||||
|
||||
AstRef funcSig_;
|
||||
ResizableLimits resizable_;
|
||||
Limits resizable_;
|
||||
AstGlobal global_;
|
||||
|
||||
public:
|
||||
AstImport(AstName name, AstName module, AstName field, AstRef funcSig)
|
||||
: name_(name), module_(module), field_(field), kind_(DefinitionKind::Function), funcSig_(funcSig)
|
||||
{}
|
||||
AstImport(AstName name, AstName module, AstName field, DefinitionKind kind, ResizableLimits resizable)
|
||||
AstImport(AstName name, AstName module, AstName field, DefinitionKind kind, Limits resizable)
|
||||
: name_(name), module_(module), field_(field), kind_(kind), resizable_(resizable)
|
||||
{}
|
||||
AstImport(AstName name, AstName module, AstName field, AstGlobal global)
|
||||
@ -649,7 +649,7 @@ class AstImport : public AstNode
|
||||
MOZ_ASSERT(kind_ == DefinitionKind::Function);
|
||||
return funcSig_;
|
||||
}
|
||||
ResizableLimits resizable() const {
|
||||
Limits resizable() const {
|
||||
MOZ_ASSERT(kind_ == DefinitionKind::Memory || kind_ == DefinitionKind::Table);
|
||||
return resizable_;
|
||||
}
|
||||
@ -744,8 +744,8 @@ class AstModule : public AstNode
|
||||
SigMap sigMap_;
|
||||
ImportVector imports_;
|
||||
NameVector funcImportNames_;
|
||||
Maybe<ResizableLimits> table_;
|
||||
Maybe<ResizableLimits> memory_;
|
||||
Maybe<Limits> table_;
|
||||
Maybe<Limits> memory_;
|
||||
ExportVector exports_;
|
||||
Maybe<AstStartFunc> startFunc_;
|
||||
FuncVector funcs_;
|
||||
@ -769,7 +769,7 @@ class AstModule : public AstNode
|
||||
bool init() {
|
||||
return sigMap_.init();
|
||||
}
|
||||
bool setMemory(ResizableLimits memory) {
|
||||
bool setMemory(Limits memory) {
|
||||
if (memory_)
|
||||
return false;
|
||||
memory_.emplace(memory);
|
||||
@ -778,10 +778,10 @@ class AstModule : public AstNode
|
||||
bool hasMemory() const {
|
||||
return !!memory_;
|
||||
}
|
||||
const ResizableLimits& memory() const {
|
||||
const Limits& memory() const {
|
||||
return *memory_;
|
||||
}
|
||||
bool setTable(ResizableLimits table) {
|
||||
bool setTable(Limits table) {
|
||||
if (table_)
|
||||
return false;
|
||||
table_.emplace(table);
|
||||
@ -790,7 +790,7 @@ class AstModule : public AstNode
|
||||
bool hasTable() const {
|
||||
return !!table_;
|
||||
}
|
||||
const ResizableLimits& table() const {
|
||||
const Limits& table() const {
|
||||
return *table_;
|
||||
}
|
||||
bool append(AstDataSegment* seg) {
|
||||
|
@ -142,7 +142,7 @@ wasm::DecodeGlobalType(Decoder& d, ValType* type, uint32_t* flags)
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::DecodeResizable(Decoder& d, ResizableLimits* limits)
|
||||
wasm::DecodeLimits(Decoder& d, Limits* limits)
|
||||
{
|
||||
uint32_t flags;
|
||||
if (!d.readVarU32(&flags))
|
||||
|
@ -1096,10 +1096,10 @@ DecodeLocalEntries(Decoder& d, ValTypeVector* locals);
|
||||
MOZ_MUST_USE bool
|
||||
DecodeGlobalType(Decoder& d, ValType* type, uint32_t* flags);
|
||||
|
||||
struct ResizableLimits;
|
||||
struct Limits;
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
DecodeResizable(Decoder& d, ResizableLimits* resizable);
|
||||
DecodeLimits(Decoder& d, Limits* limits);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
DecodeUnknownSections(Decoder& d);
|
||||
|
@ -1511,8 +1511,8 @@ AstDecodeTableSection(AstDecodeContext& c)
|
||||
if (typeConstructorValue != uint32_t(TypeConstructor::AnyFunc))
|
||||
return c.d.fail("unknown type constructor kind");
|
||||
|
||||
ResizableLimits table;
|
||||
if (!DecodeResizable(c.d, &table))
|
||||
Limits table;
|
||||
if (!DecodeLimits(c.d, &table))
|
||||
return false;
|
||||
|
||||
if (table.initial > MaxTableElems)
|
||||
@ -1547,7 +1547,7 @@ AstDecodeName(AstDecodeContext& c, AstName* name)
|
||||
}
|
||||
|
||||
static bool
|
||||
AstDecodeResizableTable(AstDecodeContext& c, ResizableLimits* resizable)
|
||||
AstDecodeLimitsTable(AstDecodeContext& c, Limits* limits)
|
||||
{
|
||||
uint32_t kind;
|
||||
if (!c.d.readVarU32(&kind))
|
||||
@ -1556,7 +1556,7 @@ AstDecodeResizableTable(AstDecodeContext& c, ResizableLimits* resizable)
|
||||
if (kind != uint32_t(TypeConstructor::AnyFunc))
|
||||
return c.d.fail("unknown type constructor kind");
|
||||
|
||||
if (!DecodeResizable(c.d, resizable))
|
||||
if (!DecodeLimits(c.d, limits))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -1611,8 +1611,8 @@ AstDecodeImport(AstDecodeContext& c, uint32_t importIndex, AstImport** import)
|
||||
break;
|
||||
}
|
||||
case uint32_t(DefinitionKind::Table): {
|
||||
ResizableLimits table;
|
||||
if (!AstDecodeResizableTable(c, &table))
|
||||
Limits table;
|
||||
if (!AstDecodeLimitsTable(c, &table))
|
||||
return false;
|
||||
|
||||
*import = new(c.lifo) AstImport(importName, moduleName, fieldName,
|
||||
@ -1620,8 +1620,8 @@ AstDecodeImport(AstDecodeContext& c, uint32_t importIndex, AstImport** import)
|
||||
break;
|
||||
}
|
||||
case uint32_t(DefinitionKind::Memory): {
|
||||
ResizableLimits memory;
|
||||
if (!DecodeResizable(c.d, &memory))
|
||||
Limits memory;
|
||||
if (!DecodeLimits(c.d, &memory))
|
||||
return false;
|
||||
|
||||
*import = new(c.lifo) AstImport(importName, moduleName, fieldName,
|
||||
@ -1684,8 +1684,8 @@ AstDecodeMemorySection(AstDecodeContext& c)
|
||||
if (numMemories != 1)
|
||||
return c.d.fail("the number of memories must be exactly one");
|
||||
|
||||
ResizableLimits memory;
|
||||
if (!DecodeResizable(c.d, &memory))
|
||||
Limits memory;
|
||||
if (!DecodeLimits(c.d, &memory))
|
||||
return false;
|
||||
|
||||
if (!c.d.finishSection(sectionStart, sectionSize, "memory"))
|
||||
|
@ -1170,7 +1170,7 @@ RenderTableSection(WasmRenderContext& c, const AstModule& module)
|
||||
if (!RenderIndent(c))
|
||||
return false;
|
||||
|
||||
if (!c.buffer.append("(table"))
|
||||
if (!c.buffer.append("(table anyfunc (elem "))
|
||||
return false;
|
||||
|
||||
for (const AstRef& elem : segment.elems()) {
|
||||
@ -1189,7 +1189,7 @@ RenderTableSection(WasmRenderContext& c, const AstModule& module)
|
||||
}
|
||||
}
|
||||
|
||||
if (!c.buffer.append(")\n"))
|
||||
if (!c.buffer.append("))\n"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -609,8 +609,8 @@ DecodeResizableMemory(Decoder& d, ModuleGeneratorData* init)
|
||||
if (UsesMemory(init->memoryUsage))
|
||||
return d.fail("already have default memory");
|
||||
|
||||
ResizableLimits limits;
|
||||
if (!DecodeResizable(d, &limits))
|
||||
Limits limits;
|
||||
if (!DecodeLimits(d, &limits))
|
||||
return false;
|
||||
|
||||
init->memoryUsage = MemoryUsage::Unshared;
|
||||
@ -644,8 +644,8 @@ DecodeResizableTable(Decoder& d, ModuleGeneratorData* init)
|
||||
if (elementType != uint32_t(TypeConstructor::AnyFunc))
|
||||
return d.fail("expected 'anyfunc' element type");
|
||||
|
||||
ResizableLimits limits;
|
||||
if (!DecodeResizable(d, &limits))
|
||||
Limits limits;
|
||||
if (!DecodeLimits(d, &limits))
|
||||
return false;
|
||||
|
||||
if (!init->tables.empty())
|
||||
|
@ -452,8 +452,8 @@ ToNonWrappingUint32(JSContext* cx, HandleValue v, uint32_t max, const char* kind
|
||||
}
|
||||
|
||||
static bool
|
||||
GetResizableLimits(JSContext* cx, HandleObject obj, uint32_t max, const char* kind,
|
||||
ResizableLimits* limits)
|
||||
GetLimits(JSContext* cx, HandleObject obj, uint32_t max, const char* kind,
|
||||
Limits* limits)
|
||||
{
|
||||
JSAtom* initialAtom = Atomize(cx, "initial", strlen("initial"));
|
||||
if (!initialAtom)
|
||||
@ -939,8 +939,8 @@ WasmMemoryObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
||||
}
|
||||
|
||||
RootedObject obj(cx, &args[0].toObject());
|
||||
ResizableLimits limits;
|
||||
if (!GetResizableLimits(cx, obj, UINT32_MAX / PageSize, "Memory", &limits))
|
||||
Limits limits;
|
||||
if (!GetLimits(cx, obj, UINT32_MAX / PageSize, "Memory", &limits))
|
||||
return false;
|
||||
|
||||
limits.initial *= PageSize;
|
||||
@ -1182,7 +1182,7 @@ WasmTableObject::trace(JSTracer* trc, JSObject* obj)
|
||||
}
|
||||
|
||||
/* static */ WasmTableObject*
|
||||
WasmTableObject::create(JSContext* cx, ResizableLimits limits)
|
||||
WasmTableObject::create(JSContext* cx, Limits limits)
|
||||
{
|
||||
RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmTable).toObject());
|
||||
|
||||
@ -1247,8 +1247,8 @@ WasmTableObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
||||
return false;
|
||||
}
|
||||
|
||||
ResizableLimits limits;
|
||||
if (!GetResizableLimits(cx, obj, UINT32_MAX, "Table", &limits))
|
||||
Limits limits;
|
||||
if (!GetLimits(cx, obj, UINT32_MAX, "Table", &limits))
|
||||
return false;
|
||||
|
||||
RootedWasmTableObject table(cx, WasmTableObject::create(cx, limits));
|
||||
|
@ -254,7 +254,7 @@ class WasmTableObject : public NativeObject
|
||||
// Note that, after creation, a WasmTableObject's table() is not initialized
|
||||
// and must be initialized before use.
|
||||
|
||||
static WasmTableObject* create(JSContext* cx, wasm::ResizableLimits limits);
|
||||
static WasmTableObject* create(JSContext* cx, wasm::Limits limits);
|
||||
wasm::Table& table() const;
|
||||
};
|
||||
|
||||
|
@ -503,9 +503,8 @@ Module::instantiateFunctions(JSContext* cx, Handle<FunctionVector> funcImports)
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckResizableLimits(JSContext* cx, uint32_t declaredMin, Maybe<uint32_t> declaredMax,
|
||||
uint32_t actualLength, Maybe<uint32_t> actualMax,
|
||||
bool isAsmJS, const char* kind)
|
||||
CheckLimits(JSContext* cx, uint32_t declaredMin, Maybe<uint32_t> declaredMax, uint32_t actualLength,
|
||||
Maybe<uint32_t> actualMax, bool isAsmJS, const char* kind)
|
||||
{
|
||||
if (isAsmJS) {
|
||||
MOZ_ASSERT(actualLength >= declaredMin);
|
||||
@ -515,14 +514,12 @@ CheckResizableLimits(JSContext* cx, uint32_t declaredMin, Maybe<uint32_t> declar
|
||||
}
|
||||
|
||||
if (actualLength < declaredMin || actualLength > declaredMax.valueOr(UINT32_MAX)) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_IMP_SIZE,
|
||||
kind);
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_IMP_SIZE, kind);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((actualMax && (!declaredMax || *actualMax > *declaredMax)) || (!actualMax && declaredMax)) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_IMP_MAX,
|
||||
kind);
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_IMP_MAX, kind);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -549,9 +546,8 @@ Module::instantiateMemory(JSContext* cx, MutableHandleWasmMemoryObject memory) c
|
||||
MOZ_ASSERT_IF(metadata_->isAsmJS(), buffer.isPreparedForAsmJS());
|
||||
MOZ_ASSERT_IF(!metadata_->isAsmJS(), buffer.as<ArrayBufferObject>().isWasm());
|
||||
|
||||
if (!CheckResizableLimits(cx, declaredMin, declaredMax,
|
||||
buffer.byteLength(), buffer.wasmMaxSize(),
|
||||
metadata_->isAsmJS(), "Memory")) {
|
||||
if (!CheckLimits(cx, declaredMin, declaredMax, buffer.byteLength(), buffer.wasmMaxSize(),
|
||||
metadata_->isAsmJS(), "Memory")) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@ -585,9 +581,8 @@ Module::instantiateTable(JSContext* cx, MutableHandleWasmTableObject tableObj,
|
||||
MOZ_ASSERT(td.external);
|
||||
|
||||
Table& table = tableObj->table();
|
||||
if (!CheckResizableLimits(cx, td.limits.initial, td.limits.maximum,
|
||||
table.length(), table.maximum(),
|
||||
metadata_->isAsmJS(), "Table")) {
|
||||
if (!CheckLimits(cx, td.limits.initial, td.limits.maximum, table.length(), table.maximum(),
|
||||
metadata_->isAsmJS(), "Table")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,7 @@ class WasmToken
|
||||
enum Kind
|
||||
{
|
||||
Align,
|
||||
AnyFunc,
|
||||
BinaryOpcode,
|
||||
Block,
|
||||
Br,
|
||||
@ -92,7 +93,6 @@ class WasmToken
|
||||
GetLocal,
|
||||
Global,
|
||||
If,
|
||||
Immutable,
|
||||
Import,
|
||||
Index,
|
||||
Memory,
|
||||
@ -101,12 +101,12 @@ class WasmToken
|
||||
Local,
|
||||
Loop,
|
||||
Module,
|
||||
Mutable,
|
||||
Name,
|
||||
Nop,
|
||||
Offset,
|
||||
OpenParen,
|
||||
Param,
|
||||
Resizable,
|
||||
Result,
|
||||
Return,
|
||||
Segment,
|
||||
@ -140,7 +140,12 @@ class WasmToken
|
||||
Expr expr_;
|
||||
} u;
|
||||
public:
|
||||
explicit WasmToken() = default;
|
||||
WasmToken()
|
||||
: kind_(Kind(-1)),
|
||||
begin_(nullptr),
|
||||
end_(nullptr),
|
||||
u()
|
||||
{ }
|
||||
WasmToken(Kind kind, const char16_t* begin, const char16_t* end)
|
||||
: kind_(kind),
|
||||
begin_(begin),
|
||||
@ -208,6 +213,7 @@ class WasmToken
|
||||
end_(begin)
|
||||
{}
|
||||
Kind kind() const {
|
||||
MOZ_ASSERT(kind_ != Kind(-1));
|
||||
return kind_;
|
||||
}
|
||||
const char16_t* begin() const {
|
||||
@ -283,6 +289,7 @@ class WasmToken
|
||||
case Unreachable:
|
||||
return true;
|
||||
case Align:
|
||||
case AnyFunc:
|
||||
case CloseParen:
|
||||
case Data:
|
||||
case Elem:
|
||||
@ -295,7 +302,7 @@ class WasmToken
|
||||
case Float:
|
||||
case Func:
|
||||
case Global:
|
||||
case Immutable:
|
||||
case Mutable:
|
||||
case Import:
|
||||
case Index:
|
||||
case Memory:
|
||||
@ -306,7 +313,6 @@ class WasmToken
|
||||
case Offset:
|
||||
case OpenParen:
|
||||
case Param:
|
||||
case Resizable:
|
||||
case Result:
|
||||
case Segment:
|
||||
case SignedInteger:
|
||||
@ -323,6 +329,12 @@ class WasmToken
|
||||
}
|
||||
};
|
||||
|
||||
struct InlineImport
|
||||
{
|
||||
WasmToken module;
|
||||
WasmToken field;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
static bool
|
||||
@ -822,6 +834,8 @@ WasmTokenStream::next()
|
||||
case 'a':
|
||||
if (consume(u"align"))
|
||||
return WasmToken(WasmToken::Align, begin, cur_);
|
||||
if (consume(u"anyfunc"))
|
||||
return WasmToken(WasmToken::AnyFunc, begin, cur_);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
@ -1369,8 +1383,6 @@ WasmTokenStream::next()
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (consume(u"immutable"))
|
||||
return WasmToken(WasmToken::Immutable, begin, cur_);
|
||||
if (consume(u"import"))
|
||||
return WasmToken(WasmToken::Import, begin, cur_);
|
||||
if (consume(u"infinity"))
|
||||
@ -1391,6 +1403,8 @@ WasmTokenStream::next()
|
||||
return WasmToken(WasmToken::Module, begin, cur_);
|
||||
if (consume(u"memory"))
|
||||
return WasmToken(WasmToken::Memory, begin, cur_);
|
||||
if (consume(u"mut"))
|
||||
return WasmToken(WasmToken::Mutable, begin, cur_);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
@ -1411,8 +1425,6 @@ WasmTokenStream::next()
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (consume(u"resizable"))
|
||||
return WasmToken(WasmToken::Resizable, begin, cur_);
|
||||
if (consume(u"result"))
|
||||
return WasmToken(WasmToken::Result, begin, cur_);
|
||||
if (consume(u"return"))
|
||||
@ -2488,100 +2500,49 @@ ParseLocalOrParam(WasmParseContext& c, AstNameVector* locals, AstValTypeVector*
|
||||
localTypes->append(token.valueType());
|
||||
}
|
||||
|
||||
static AstFunc*
|
||||
ParseFunc(WasmParseContext& c, AstModule* module)
|
||||
static bool
|
||||
ParseInlineImport(WasmParseContext& c, InlineImport* import)
|
||||
{
|
||||
AstValTypeVector vars(c.lifo);
|
||||
AstValTypeVector args(c.lifo);
|
||||
AstNameVector locals(c.lifo);
|
||||
|
||||
AstName exportName = c.ts.getIfText();
|
||||
AstName funcName = c.ts.getIfName();
|
||||
|
||||
AstRef sig;
|
||||
|
||||
WasmToken openParen;
|
||||
if (exportName.empty() && c.ts.getIf(WasmToken::OpenParen, &openParen)) {
|
||||
if (c.ts.getIf(WasmToken::Export)) {
|
||||
WasmToken text;
|
||||
if (!c.ts.match(WasmToken::Text, &text, c.error))
|
||||
return nullptr;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return nullptr;
|
||||
exportName = text.text();
|
||||
} else {
|
||||
c.ts.unget(openParen);
|
||||
}
|
||||
}
|
||||
|
||||
if (!exportName.empty()) {
|
||||
if (funcName.empty())
|
||||
funcName = exportName;
|
||||
AstExport* exp = new(c.lifo) AstExport(exportName, DefinitionKind::Function,
|
||||
AstRef(funcName, AstNoIndex));
|
||||
if (!exp || !module->append(exp))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (c.ts.getIf(WasmToken::OpenParen, &openParen)) {
|
||||
if (c.ts.getIf(WasmToken::Type)) {
|
||||
if (!c.ts.matchRef(&sig, c.error))
|
||||
return nullptr;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return nullptr;
|
||||
} else {
|
||||
c.ts.unget(openParen);
|
||||
}
|
||||
}
|
||||
|
||||
AstExprVector body(c.lifo);
|
||||
ExprType result = ExprType::Void;
|
||||
|
||||
while (c.ts.getIf(WasmToken::OpenParen)) {
|
||||
WasmToken token = c.ts.get();
|
||||
switch (token.kind()) {
|
||||
case WasmToken::Local:
|
||||
if (!ParseLocalOrParam(c, &locals, &vars))
|
||||
return nullptr;
|
||||
break;
|
||||
case WasmToken::Param:
|
||||
if (!vars.empty()) {
|
||||
c.ts.generateError(token, c.error);
|
||||
return nullptr;
|
||||
}
|
||||
if (!ParseLocalOrParam(c, &locals, &args))
|
||||
return nullptr;
|
||||
break;
|
||||
case WasmToken::Result:
|
||||
if (!ParseResult(c, &result))
|
||||
return nullptr;
|
||||
break;
|
||||
default:
|
||||
c.ts.unget(token);
|
||||
AstExpr* expr = ParseExprInsideParens(c);
|
||||
if (!expr || !body.append(expr))
|
||||
return nullptr;
|
||||
break;
|
||||
}
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!ParseExprList(c, &body, true))
|
||||
return nullptr;
|
||||
|
||||
if (sig.isInvalid()) {
|
||||
uint32_t sigIndex;
|
||||
if (!module->declare(AstSig(Move(args), result), &sigIndex))
|
||||
return nullptr;
|
||||
sig.setIndex(sigIndex);
|
||||
}
|
||||
|
||||
return new(c.lifo) AstFunc(funcName, sig, Move(vars), Move(locals), Move(body));
|
||||
return c.ts.match(WasmToken::Text, &import->module, c.error) &&
|
||||
c.ts.match(WasmToken::Text, &import->field, c.error);
|
||||
}
|
||||
|
||||
static bool
|
||||
ParseFuncType(WasmParseContext& c, AstSig* sig)
|
||||
ParseInlineExport(WasmParseContext& c, DefinitionKind kind, AstModule* module,
|
||||
AstRef ref = AstRef())
|
||||
{
|
||||
WasmToken name;
|
||||
if (!c.ts.match(WasmToken::Text, &name, c.error))
|
||||
return false;
|
||||
|
||||
AstExport* exp = nullptr;
|
||||
if (!ref.isInvalid())
|
||||
exp = new(c.lifo) AstExport(name.text(), kind, ref);
|
||||
else
|
||||
exp = new(c.lifo) AstExport(name.text(), kind);
|
||||
|
||||
return exp && module->append(exp);
|
||||
}
|
||||
|
||||
static bool
|
||||
MaybeParseTypeUse(WasmParseContext& c, AstRef* sig)
|
||||
{
|
||||
WasmToken openParen;
|
||||
if (c.ts.getIf(WasmToken::OpenParen, &openParen)) {
|
||||
if (c.ts.getIf(WasmToken::Type)) {
|
||||
if (!c.ts.matchRef(sig, c.error))
|
||||
return false;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
} else {
|
||||
c.ts.unget(openParen);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ParseFuncSig(WasmParseContext& c, AstSig* sig)
|
||||
{
|
||||
AstValTypeVector args(c.lifo);
|
||||
ExprType result = ExprType::Void;
|
||||
@ -2609,6 +2570,121 @@ ParseFuncType(WasmParseContext& c, AstSig* sig)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ParseFuncType(WasmParseContext& c, AstRef* ref, AstModule* module)
|
||||
{
|
||||
if (!MaybeParseTypeUse(c, ref))
|
||||
return false;
|
||||
|
||||
if (ref->isInvalid()) {
|
||||
AstSig sig(c.lifo);
|
||||
if (!ParseFuncSig(c, &sig))
|
||||
return false;
|
||||
uint32_t sigIndex;
|
||||
if (!module->declare(Move(sig), &sigIndex))
|
||||
return false;
|
||||
ref->setIndex(sigIndex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ParseFunc(WasmParseContext& c, AstModule* module)
|
||||
{
|
||||
AstValTypeVector vars(c.lifo);
|
||||
AstValTypeVector args(c.lifo);
|
||||
AstNameVector locals(c.lifo);
|
||||
|
||||
AstName funcName = c.ts.getIfName();
|
||||
|
||||
// Inline imports and exports.
|
||||
WasmToken openParen;
|
||||
if (c.ts.getIf(WasmToken::OpenParen, &openParen)) {
|
||||
if (c.ts.getIf(WasmToken::Import)) {
|
||||
if (module->funcs().length()) {
|
||||
c.ts.generateError(openParen, "import after function definition", c.error);
|
||||
return false;
|
||||
}
|
||||
|
||||
InlineImport names;
|
||||
if (!ParseInlineImport(c, &names))
|
||||
return false;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
|
||||
AstRef sig;
|
||||
if (!ParseFuncType(c, &sig, module))
|
||||
return false;
|
||||
|
||||
auto* imp = new(c.lifo) AstImport(funcName, names.module.text(), names.field.text(), sig);
|
||||
return imp && module->append(imp);
|
||||
}
|
||||
|
||||
if (c.ts.getIf(WasmToken::Export)) {
|
||||
AstRef ref = funcName.empty()
|
||||
? AstRef(AstName(), module->funcImportNames().length() + module->funcs().length())
|
||||
: AstRef(funcName, AstNoIndex);
|
||||
if (!ParseInlineExport(c, DefinitionKind::Function, module, ref))
|
||||
return false;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
} else {
|
||||
c.ts.unget(openParen);
|
||||
}
|
||||
}
|
||||
|
||||
AstRef sigRef;
|
||||
if (!MaybeParseTypeUse(c, &sigRef))
|
||||
return false;
|
||||
|
||||
AstExprVector body(c.lifo);
|
||||
|
||||
ExprType result = ExprType::Void;
|
||||
while (c.ts.getIf(WasmToken::OpenParen)) {
|
||||
WasmToken token = c.ts.get();
|
||||
switch (token.kind()) {
|
||||
case WasmToken::Local:
|
||||
if (!ParseLocalOrParam(c, &locals, &vars))
|
||||
return false;
|
||||
break;
|
||||
case WasmToken::Param:
|
||||
if (!vars.empty()) {
|
||||
c.ts.generateError(token, c.error);
|
||||
return false;
|
||||
}
|
||||
if (!ParseLocalOrParam(c, &locals, &args))
|
||||
return false;
|
||||
break;
|
||||
case WasmToken::Result:
|
||||
if (!ParseResult(c, &result))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
c.ts.unget(token);
|
||||
AstExpr* expr = ParseExprInsideParens(c);
|
||||
if (!expr || !body.append(expr))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ParseExprList(c, &body, true))
|
||||
return false;
|
||||
|
||||
if (sigRef.isInvalid()) {
|
||||
uint32_t sigIndex;
|
||||
if (!module->declare(AstSig(Move(args), result), &sigIndex))
|
||||
return false;
|
||||
sigRef.setIndex(sigIndex);
|
||||
}
|
||||
|
||||
auto* func = new(c.lifo) AstFunc(funcName, sigRef, Move(vars), Move(locals), Move(body));
|
||||
return func && module->append(func);
|
||||
}
|
||||
|
||||
static AstSig*
|
||||
ParseTypeDef(WasmParseContext& c)
|
||||
{
|
||||
@ -2620,7 +2696,7 @@ ParseTypeDef(WasmParseContext& c)
|
||||
return nullptr;
|
||||
|
||||
AstSig sig(c.lifo);
|
||||
if (!ParseFuncType(c, &sig))
|
||||
if (!ParseFuncSig(c, &sig))
|
||||
return nullptr;
|
||||
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
@ -2629,15 +2705,26 @@ ParseTypeDef(WasmParseContext& c)
|
||||
return new(c.lifo) AstSig(name, Move(sig));
|
||||
}
|
||||
|
||||
static bool
|
||||
MaybeParseOwnerIndex(WasmParseContext& c)
|
||||
{
|
||||
if (c.ts.peek().kind() == WasmToken::Index) {
|
||||
WasmToken elemIndex = c.ts.get();
|
||||
if (elemIndex.index()) {
|
||||
c.ts.generateError(elemIndex, "can't handle non-default memory/table yet", c.error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static AstDataSegment*
|
||||
ParseDataSegment(WasmParseContext& c)
|
||||
{
|
||||
AstExpr* offset;
|
||||
WasmToken dstOffset;
|
||||
if (c.ts.getIf(WasmToken::Index, &dstOffset))
|
||||
offset = new(c.lifo) AstConst(Val(dstOffset.index()));
|
||||
else
|
||||
offset = ParseExpr(c, true);
|
||||
if (!MaybeParseOwnerIndex(c))
|
||||
return nullptr;
|
||||
|
||||
AstExpr* offset = ParseExpr(c, true);
|
||||
if (!offset)
|
||||
return nullptr;
|
||||
|
||||
@ -2649,7 +2736,7 @@ ParseDataSegment(WasmParseContext& c)
|
||||
}
|
||||
|
||||
static bool
|
||||
ParseResizable(WasmParseContext& c, ResizableLimits* resizable)
|
||||
ParseLimits(WasmParseContext& c, Limits* resizable)
|
||||
{
|
||||
WasmToken initial;
|
||||
if (!c.ts.match(WasmToken::Index, &initial, c.error))
|
||||
@ -2660,7 +2747,7 @@ ParseResizable(WasmParseContext& c, ResizableLimits* resizable)
|
||||
if (c.ts.getIf(WasmToken::Index, &token))
|
||||
maximum.emplace(token.index());
|
||||
|
||||
ResizableLimits r = { initial.index(), maximum };
|
||||
Limits r = { initial.index(), maximum };
|
||||
*resizable = r;
|
||||
return true;
|
||||
}
|
||||
@ -2668,6 +2755,36 @@ ParseResizable(WasmParseContext& c, ResizableLimits* resizable)
|
||||
static bool
|
||||
ParseMemory(WasmParseContext& c, WasmToken token, AstModule* module)
|
||||
{
|
||||
AstName name = c.ts.getIfName();
|
||||
|
||||
WasmToken openParen;
|
||||
if (c.ts.getIf(WasmToken::OpenParen, &openParen)) {
|
||||
if (c.ts.getIf(WasmToken::Import)) {
|
||||
InlineImport names;
|
||||
if (!ParseInlineImport(c, &names))
|
||||
return false;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
|
||||
Limits memory;
|
||||
if (!ParseLimits(c, &memory))
|
||||
return false;
|
||||
|
||||
auto* imp = new(c.lifo) AstImport(name, names.module.text(), names.field.text(),
|
||||
DefinitionKind::Memory, memory);
|
||||
return imp && module->append(imp);
|
||||
}
|
||||
|
||||
if (c.ts.getIf(WasmToken::Export)) {
|
||||
if (!ParseInlineExport(c, DefinitionKind::Memory, module))
|
||||
return false;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
} else {
|
||||
c.ts.unget(openParen);
|
||||
}
|
||||
}
|
||||
|
||||
if (c.ts.getIf(WasmToken::OpenParen)) {
|
||||
if (!c.ts.match(WasmToken::Data, c.error))
|
||||
return false;
|
||||
@ -2688,7 +2805,7 @@ ParseMemory(WasmParseContext& c, WasmToken token, AstModule* module)
|
||||
return false;
|
||||
}
|
||||
|
||||
ResizableLimits memory = { uint32_t(pages), Some(uint32_t(pages)) };
|
||||
Limits memory = { uint32_t(pages), Some(uint32_t(pages)) };
|
||||
if (!module->setMemory(memory))
|
||||
return false;
|
||||
|
||||
@ -2698,8 +2815,8 @@ ParseMemory(WasmParseContext& c, WasmToken token, AstModule* module)
|
||||
return true;
|
||||
}
|
||||
|
||||
ResizableLimits memory;
|
||||
if (!ParseResizable(c, &memory))
|
||||
Limits memory;
|
||||
if (!ParseLimits(c, &memory))
|
||||
return false;
|
||||
|
||||
if (!module->setMemory(memory)) {
|
||||
@ -2728,15 +2845,32 @@ ParseStartFunc(WasmParseContext& c, WasmToken token, AstModule* module)
|
||||
static bool
|
||||
ParseGlobalType(WasmParseContext& c, WasmToken* typeToken, uint32_t* flags)
|
||||
{
|
||||
if (!c.ts.match(WasmToken::ValueType, typeToken, c.error))
|
||||
return false;
|
||||
// Either (mut i32) or i32.
|
||||
if (c.ts.getIf(WasmToken::OpenParen)) {
|
||||
// Immutable by default.
|
||||
*flags = c.ts.getIf(WasmToken::Mutable) ? 0x1 : 0x0;
|
||||
if (!c.ts.match(WasmToken::ValueType, typeToken, c.error))
|
||||
return false;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Mutable by default.
|
||||
*flags = 0x1;
|
||||
if (c.ts.getIf(WasmToken::Immutable))
|
||||
*flags = 0x0;
|
||||
return c.ts.match(WasmToken::ValueType, typeToken, c.error);
|
||||
}
|
||||
|
||||
return true;
|
||||
static bool
|
||||
ParseElemType(WasmParseContext& c)
|
||||
{
|
||||
// Only AnyFunc is allowed at the moment.
|
||||
return c.ts.match(WasmToken::AnyFunc, c.error);
|
||||
}
|
||||
|
||||
static bool
|
||||
ParseTableSig(WasmParseContext& c, Limits* table)
|
||||
{
|
||||
return ParseLimits(c, table) &&
|
||||
ParseElemType(c);
|
||||
}
|
||||
|
||||
static AstImport*
|
||||
@ -2756,8 +2890,11 @@ ParseImport(WasmParseContext& c, AstModule* module)
|
||||
WasmToken openParen;
|
||||
if (c.ts.getIf(WasmToken::OpenParen, &openParen)) {
|
||||
if (c.ts.getIf(WasmToken::Memory)) {
|
||||
ResizableLimits memory;
|
||||
if (!ParseResizable(c, &memory))
|
||||
if (name.empty())
|
||||
name = c.ts.getIfName();
|
||||
|
||||
Limits memory;
|
||||
if (!ParseLimits(c, &memory))
|
||||
return nullptr;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return nullptr;
|
||||
@ -2765,8 +2902,11 @@ ParseImport(WasmParseContext& c, AstModule* module)
|
||||
DefinitionKind::Memory, memory);
|
||||
}
|
||||
if (c.ts.getIf(WasmToken::Table)) {
|
||||
ResizableLimits table;
|
||||
if (!ParseResizable(c, &table))
|
||||
if (name.empty())
|
||||
name = c.ts.getIfName();
|
||||
|
||||
Limits table;
|
||||
if (!ParseTableSig(c, &table))
|
||||
return nullptr;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return nullptr;
|
||||
@ -2774,38 +2914,30 @@ ParseImport(WasmParseContext& c, AstModule* module)
|
||||
DefinitionKind::Table, table);
|
||||
}
|
||||
if (c.ts.getIf(WasmToken::Global)) {
|
||||
if (name.empty())
|
||||
name = c.ts.getIfName();
|
||||
|
||||
WasmToken typeToken;
|
||||
uint32_t flags = 0;
|
||||
if (!ParseGlobalType(c, &typeToken, &flags))
|
||||
return nullptr;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return nullptr;
|
||||
|
||||
return new(c.lifo) AstImport(name, moduleName.text(), fieldName.text(),
|
||||
AstGlobal(AstName(), typeToken.valueType(), flags));
|
||||
}
|
||||
if (c.ts.getIf(WasmToken::Func)) {
|
||||
AstName name = c.ts.getIfName();
|
||||
if (name.empty())
|
||||
name = c.ts.getIfName();
|
||||
|
||||
WasmToken token;
|
||||
if (c.ts.getIf(WasmToken::Type, &token)) {
|
||||
if (!c.ts.matchRef(&sigRef, c.error))
|
||||
return nullptr;
|
||||
} else {
|
||||
AstSig sig(c.lifo);
|
||||
if (!ParseFuncType(c, &sig))
|
||||
return nullptr;
|
||||
|
||||
uint32_t sigIndex;
|
||||
if (!module->declare(Move(sig), &sigIndex))
|
||||
return nullptr;
|
||||
|
||||
sigRef.setIndex(sigIndex);
|
||||
}
|
||||
AstRef sigRef;
|
||||
if (!ParseFuncType(c, &sigRef, module))
|
||||
return nullptr;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return nullptr;
|
||||
|
||||
return new(c.lifo) AstImport(name, moduleName.text(), fieldName.text(),
|
||||
sigRef);
|
||||
return new(c.lifo) AstImport(name, moduleName.text(), fieldName.text(), sigRef);
|
||||
}
|
||||
|
||||
if (c.ts.getIf(WasmToken::Type)) {
|
||||
@ -2820,7 +2952,7 @@ ParseImport(WasmParseContext& c, AstModule* module)
|
||||
|
||||
if (sigRef.isInvalid()) {
|
||||
AstSig sig(c.lifo);
|
||||
if (!ParseFuncType(c, &sig))
|
||||
if (!ParseFuncSig(c, &sig))
|
||||
return nullptr;
|
||||
|
||||
uint32_t sigIndex;
|
||||
@ -2879,10 +3011,14 @@ ParseExport(WasmParseContext& c)
|
||||
break;
|
||||
}
|
||||
case WasmToken::Table:
|
||||
if (!MaybeParseOwnerIndex(c))
|
||||
return nullptr;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return nullptr;
|
||||
return new(c.lifo) AstExport(name.text(), DefinitionKind::Table);
|
||||
case WasmToken::Memory:
|
||||
if (!MaybeParseOwnerIndex(c))
|
||||
return nullptr;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return nullptr;
|
||||
return new(c.lifo) AstExport(name.text(), DefinitionKind::Memory);
|
||||
@ -2905,20 +3041,48 @@ ParseExport(WasmParseContext& c)
|
||||
|
||||
c.ts.generateError(exportee, c.error);
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
static bool
|
||||
ParseTable(WasmParseContext& c, WasmToken token, AstModule* module)
|
||||
{
|
||||
AstName name = c.ts.getIfName();
|
||||
|
||||
if (c.ts.getIf(WasmToken::OpenParen)) {
|
||||
if (!c.ts.match(WasmToken::Resizable, c.error))
|
||||
// Either an import and we're done, or an export and continue.
|
||||
if (c.ts.getIf(WasmToken::Import)) {
|
||||
InlineImport names;
|
||||
if (!ParseInlineImport(c, &names))
|
||||
return false;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
|
||||
Limits table;
|
||||
if (!ParseTableSig(c, &table))
|
||||
return false;
|
||||
|
||||
auto* import = new(c.lifo) AstImport(name, names.module.text(), names.field.text(),
|
||||
DefinitionKind::Table, table);
|
||||
|
||||
return import && module->append(import);
|
||||
}
|
||||
|
||||
if (!c.ts.match(WasmToken::Export, c.error)) {
|
||||
c.ts.generateError(token, c.error);
|
||||
return false;
|
||||
ResizableLimits table;
|
||||
if (!ParseResizable(c, &table))
|
||||
}
|
||||
|
||||
if (!ParseInlineExport(c, DefinitionKind::Table, module))
|
||||
return false;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Either: min max? anyfunc
|
||||
if (c.ts.peek().kind() == WasmToken::Index) {
|
||||
Limits table;
|
||||
if (!ParseTableSig(c, &table))
|
||||
return false;
|
||||
if (!module->setTable(table)) {
|
||||
c.ts.generateError(token, c.error);
|
||||
return false;
|
||||
@ -2926,6 +3090,15 @@ ParseTable(WasmParseContext& c, WasmToken token, AstModule* module)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Or: anyfunc (elem 1 2 ...)
|
||||
if (!ParseElemType(c))
|
||||
return false;
|
||||
|
||||
if (!c.ts.match(WasmToken::OpenParen, c.error))
|
||||
return false;
|
||||
if (!c.ts.match(WasmToken::Elem, c.error))
|
||||
return false;
|
||||
|
||||
AstRefVector elems(c.lifo);
|
||||
|
||||
AstRef elem;
|
||||
@ -2934,11 +3107,14 @@ ParseTable(WasmParseContext& c, WasmToken token, AstModule* module)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
|
||||
uint32_t numElements = uint32_t(elems.length());
|
||||
if (numElements != elems.length())
|
||||
return false;
|
||||
|
||||
ResizableLimits r = { numElements, Some(numElements) };
|
||||
Limits r = { numElements, Some(numElements) };
|
||||
if (!module->setTable(r)) {
|
||||
c.ts.generateError(token, c.error);
|
||||
return false;
|
||||
@ -2955,6 +3131,9 @@ ParseTable(WasmParseContext& c, WasmToken token, AstModule* module)
|
||||
static AstElemSegment*
|
||||
ParseElemSegment(WasmParseContext& c)
|
||||
{
|
||||
if (!MaybeParseOwnerIndex(c))
|
||||
return nullptr;
|
||||
|
||||
AstExpr* offset = ParseExpr(c, true);
|
||||
if (!offset)
|
||||
return nullptr;
|
||||
@ -2970,21 +3149,58 @@ ParseElemSegment(WasmParseContext& c)
|
||||
return new(c.lifo) AstElemSegment(offset, Move(elems));
|
||||
}
|
||||
|
||||
static AstGlobal*
|
||||
ParseGlobal(WasmParseContext& c)
|
||||
static bool
|
||||
ParseGlobal(WasmParseContext& c, AstModule* module)
|
||||
{
|
||||
AstName name = c.ts.getIfName();
|
||||
|
||||
WasmToken typeToken;
|
||||
uint32_t flags = 0;
|
||||
|
||||
WasmToken openParen;
|
||||
if (c.ts.getIf(WasmToken::OpenParen, &openParen)) {
|
||||
if (c.ts.getIf(WasmToken::Import)) {
|
||||
if (module->globals().length()) {
|
||||
c.ts.generateError(openParen, "import after global definition", c.error);
|
||||
return false;
|
||||
}
|
||||
|
||||
InlineImport names;
|
||||
if (!ParseInlineImport(c, &names))
|
||||
return false;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
|
||||
if (!ParseGlobalType(c, &typeToken, &flags))
|
||||
return false;
|
||||
|
||||
auto* imp = new(c.lifo) AstImport(name, names.module.text(), names.field.text(),
|
||||
AstGlobal(AstName(), typeToken.valueType(), flags));
|
||||
return imp && module->append(imp);
|
||||
}
|
||||
|
||||
if (c.ts.getIf(WasmToken::Export)) {
|
||||
AstRef ref = name.empty()
|
||||
? AstRef(AstName(), module->globals().length())
|
||||
: AstRef(name, AstNoIndex);
|
||||
if (!ParseInlineExport(c, DefinitionKind::Global, module, ref))
|
||||
return false;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
} else {
|
||||
c.ts.unget(openParen);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ParseGlobalType(c, &typeToken, &flags))
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
AstExpr* init = ParseExpr(c, true);
|
||||
if (!init)
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
return new(c.lifo) AstGlobal(name, typeToken.valueType(), flags, Some(init));
|
||||
auto* glob = new(c.lifo) AstGlobal(name, typeToken.valueType(), flags, Some(init));
|
||||
return glob && module->append(glob);
|
||||
}
|
||||
|
||||
static AstModule*
|
||||
@ -2997,7 +3213,7 @@ ParseModule(const char16_t* text, LifoAlloc& lifo, UniqueChars* error)
|
||||
if (!c.ts.match(WasmToken::Module, c.error))
|
||||
return nullptr;
|
||||
|
||||
auto module = new(c.lifo) AstModule(c.lifo);
|
||||
auto* module = new(c.lifo) AstModule(c.lifo);
|
||||
if (!module || !module->init())
|
||||
return nullptr;
|
||||
|
||||
@ -3022,8 +3238,7 @@ ParseModule(const char16_t* text, LifoAlloc& lifo, UniqueChars* error)
|
||||
break;
|
||||
}
|
||||
case WasmToken::Global: {
|
||||
AstGlobal* global = ParseGlobal(c);
|
||||
if (!global || !module->append(global))
|
||||
if (!ParseGlobal(c, module))
|
||||
return nullptr;
|
||||
break;
|
||||
}
|
||||
@ -3057,8 +3272,7 @@ ParseModule(const char16_t* text, LifoAlloc& lifo, UniqueChars* error)
|
||||
break;
|
||||
}
|
||||
case WasmToken::Func: {
|
||||
AstFunc* func = ParseFunc(c, module);
|
||||
if (!func || !module->append(func))
|
||||
if (!ParseFunc(c, module))
|
||||
return nullptr;
|
||||
break;
|
||||
}
|
||||
@ -4072,20 +4286,20 @@ EncodeBytes(Encoder& e, AstName wasmName)
|
||||
}
|
||||
|
||||
static bool
|
||||
EncodeResizable(Encoder& e, const ResizableLimits& resizable)
|
||||
EncodeLimits(Encoder& e, const Limits& limits)
|
||||
{
|
||||
uint32_t flags = uint32_t(ResizableFlags::Default);
|
||||
if (resizable.maximum)
|
||||
if (limits.maximum)
|
||||
flags |= uint32_t(ResizableFlags::HasMaximum);
|
||||
|
||||
if (!e.writeVarU32(flags))
|
||||
return false;
|
||||
|
||||
if (!e.writeVarU32(resizable.initial))
|
||||
if (!e.writeVarU32(limits.initial))
|
||||
return false;
|
||||
|
||||
if (resizable.maximum) {
|
||||
if (!e.writeVarU32(*resizable.maximum))
|
||||
if (limits.maximum) {
|
||||
if (!e.writeVarU32(*limits.maximum))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -4093,12 +4307,12 @@ EncodeResizable(Encoder& e, const ResizableLimits& resizable)
|
||||
}
|
||||
|
||||
static bool
|
||||
EncodeResizableTable(Encoder& e, const ResizableLimits& resizable)
|
||||
EncodeTableLimits(Encoder& e, const Limits& limits)
|
||||
{
|
||||
if (!e.writeVarU32(uint32_t(TypeConstructor::AnyFunc)))
|
||||
return false;
|
||||
|
||||
return EncodeResizable(e, resizable);
|
||||
return EncodeLimits(e, limits);
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -4126,11 +4340,11 @@ EncodeImport(Encoder& e, AstImport& imp)
|
||||
return false;
|
||||
break;
|
||||
case DefinitionKind::Table:
|
||||
if (!EncodeResizableTable(e, imp.resizable()))
|
||||
if (!EncodeTableLimits(e, imp.resizable()))
|
||||
return false;
|
||||
break;
|
||||
case DefinitionKind::Memory:
|
||||
if (!EncodeResizable(e, imp.resizable()))
|
||||
if (!EncodeLimits(e, imp.resizable()))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
@ -4174,9 +4388,9 @@ EncodeMemorySection(Encoder& e, AstModule& module)
|
||||
if (!e.writeVarU32(numMemories))
|
||||
return false;
|
||||
|
||||
const ResizableLimits& memory = module.memory();
|
||||
const Limits& memory = module.memory();
|
||||
|
||||
if (!EncodeResizable(e, memory))
|
||||
if (!EncodeLimits(e, memory))
|
||||
return false;
|
||||
|
||||
e.finishSection(offset);
|
||||
@ -4273,8 +4487,8 @@ EncodeTableSection(Encoder& e, AstModule& module)
|
||||
if (!e.writeVarU32(numTables))
|
||||
return false;
|
||||
|
||||
const ResizableLimits& table = module.table();
|
||||
if (!EncodeResizableTable(e, table))
|
||||
const Limits& table = module.table();
|
||||
if (!EncodeTableLimits(e, table))
|
||||
return false;
|
||||
|
||||
e.finishSection(offset);
|
||||
|
@ -935,7 +935,7 @@ enum ModuleKind
|
||||
|
||||
// Represents the resizable limits of memories and tables.
|
||||
|
||||
struct ResizableLimits
|
||||
struct Limits
|
||||
{
|
||||
uint32_t initial;
|
||||
Maybe<uint32_t> maximum;
|
||||
@ -956,10 +956,10 @@ struct TableDesc
|
||||
TableKind kind;
|
||||
bool external;
|
||||
uint32_t globalDataOffset;
|
||||
ResizableLimits limits;
|
||||
Limits limits;
|
||||
|
||||
TableDesc() = default;
|
||||
TableDesc(TableKind kind, ResizableLimits limits)
|
||||
TableDesc(TableKind kind, Limits limits)
|
||||
: kind(kind),
|
||||
external(false),
|
||||
globalDataOffset(UINT32_MAX),
|
||||
|
@ -4335,9 +4335,9 @@ BytecodeEmitter::emitDestructuringLHS(ParseNode* target, DestructuringFlavor fla
|
||||
else if (target->isKind(PNK_ASSIGN))
|
||||
target = target->pn_left;
|
||||
if (target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT)) {
|
||||
if (!emitDestructuringOpsHelper(target, flav))
|
||||
if (!emitDestructuringOps(target, flav))
|
||||
return false;
|
||||
// Per its post-condition, emitDestructuringOpsHelper has left the
|
||||
// Per its post-condition, emitDestructuringOps has left the
|
||||
// to-be-destructured value on top of the stack.
|
||||
if (!emit1(JSOP_POP))
|
||||
return false;
|
||||
@ -4514,7 +4514,7 @@ BytecodeEmitter::emitDefault(ParseNode* defaultExpr)
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitDestructuringOpsArrayHelper(ParseNode* pattern, DestructuringFlavor flav)
|
||||
BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlavor flav)
|
||||
{
|
||||
MOZ_ASSERT(pattern->isKind(PNK_ARRAY));
|
||||
MOZ_ASSERT(pattern->isArity(PN_LIST));
|
||||
@ -4781,7 +4781,7 @@ BytecodeEmitter::emitComputedPropertyName(ParseNode* computedPropName)
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitDestructuringOpsObjectHelper(ParseNode* pattern, DestructuringFlavor flav)
|
||||
BytecodeEmitter::emitDestructuringOpsObject(ParseNode* pattern, DestructuringFlavor flav)
|
||||
{
|
||||
MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(pattern->isArity(PN_LIST));
|
||||
@ -4855,28 +4855,12 @@ BytecodeEmitter::emitDestructuringOpsObjectHelper(ParseNode* pattern, Destructur
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Recursive helper for emitDestructuringOps.
|
||||
* EmitDestructuringOpsHelper assumes the to-be-destructured value has been
|
||||
* pushed on the stack and emits code to destructure each part of a [] or {}
|
||||
* lhs expression.
|
||||
*/
|
||||
bool
|
||||
BytecodeEmitter::emitDestructuringOpsHelper(ParseNode* pattern, DestructuringFlavor flav)
|
||||
{
|
||||
if (pattern->isKind(PNK_ARRAY))
|
||||
return emitDestructuringOpsArrayHelper(pattern, flav);
|
||||
return emitDestructuringOpsObjectHelper(pattern, flav);
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitDestructuringOps(ParseNode* pattern, DestructuringFlavor flav)
|
||||
{
|
||||
/*
|
||||
* Call our recursive helper to emit the destructuring assignments and
|
||||
* related stack manipulations.
|
||||
*/
|
||||
return emitDestructuringOpsHelper(pattern, flav);
|
||||
if (pattern->isKind(PNK_ARRAY))
|
||||
return emitDestructuringOpsArray(pattern, flav);
|
||||
return emitDestructuringOpsObject(pattern, flav);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -4940,55 +4924,20 @@ BytecodeEmitter::emitDeclarationList(ParseNode* declList)
|
||||
return false;
|
||||
next = decl->pn_next;
|
||||
|
||||
if (decl->isKind(PNK_ARRAY) || decl->isKind(PNK_OBJECT)) {
|
||||
// Destructuring BindingPattern in a deprecated comprehension:
|
||||
// a = [x*y for (let [x, y] of pts)];
|
||||
//
|
||||
// (When emitting code for a plain LexicalDeclaration, like
|
||||
// `let [x, y] = pt;`, decl will be a PNK_ASSIGN node, not a
|
||||
// PNK_ARRAY node. `let [x, y];` without an initializer is a
|
||||
// SyntaxError.)
|
||||
|
||||
MOZ_ASSERT(declList->pn_count == 1);
|
||||
|
||||
auto emitInitializeToUndefined = [](BytecodeEmitter* bce, ParseNode *pn) {
|
||||
MOZ_ASSERT(bce->lookupName(pn->name()).hasKnownSlot());
|
||||
MOZ_ASSERT(bce->lookupName(pn->name()).isLexical());
|
||||
auto emitUndefined = [](BytecodeEmitter* bce, const NameLocation&, bool) {
|
||||
return bce->emit1(JSOP_UNDEFINED);
|
||||
};
|
||||
if (!bce->emitInitializeName(pn, emitUndefined))
|
||||
return false;
|
||||
// Pop the RHS.
|
||||
return bce->emit1(JSOP_POP);
|
||||
};
|
||||
|
||||
if (!emitDestructuringDeclsWithEmitter(decl, emitInitializeToUndefined))
|
||||
return false;
|
||||
} else if (decl->isKind(PNK_ASSIGN)) {
|
||||
/*
|
||||
* A destructuring initialiser assignment preceded by var will
|
||||
* never occur to the left of 'in' in a for-in loop. As with 'for
|
||||
* (var x = i in o)...', this will cause the entire 'var [a, b] =
|
||||
* i' to be hoisted out of the loop.
|
||||
*/
|
||||
if (decl->isKind(PNK_ASSIGN)) {
|
||||
MOZ_ASSERT(decl->isOp(JSOP_NOP));
|
||||
|
||||
if (decl->pn_left->isKind(PNK_NAME)) {
|
||||
if (!emitSingleDeclaration(declList, decl->pn_left, decl->pn_right))
|
||||
return false;
|
||||
} else {
|
||||
ParseNode* initializer = decl->pn_left;
|
||||
ParseNode* pattern = decl->pn_left;
|
||||
MOZ_ASSERT(pattern->isKind(PNK_ARRAY) || pattern->isKind(PNK_OBJECT));
|
||||
|
||||
if (!emitTree(decl->pn_right))
|
||||
return false;
|
||||
if (!emitTree(decl->pn_right))
|
||||
return false;
|
||||
|
||||
if (!emitDestructuringOpsHelper(initializer, DestructuringDeclaration))
|
||||
return false;
|
||||
if (!emitDestructuringOps(pattern, DestructuringDeclaration))
|
||||
return false;
|
||||
|
||||
if (!emit1(JSOP_POP))
|
||||
return false;
|
||||
}
|
||||
if (!emit1(JSOP_POP))
|
||||
return false;
|
||||
} else {
|
||||
if (!emitSingleDeclaration(declList, decl, decl->expr()))
|
||||
return false;
|
||||
@ -6082,9 +6031,7 @@ BytecodeEmitter::emitInitializeForInOrOfTarget(ParseNode* forHead)
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!target->isKind(PNK_ASSIGN),
|
||||
"for-in/of loop declarations can't have initializers; or if "
|
||||
"they do, those initializers are ignored -- see "
|
||||
"Parser::declarationPattern");
|
||||
"for-in/of loop destructuring declarations can't have initializers");
|
||||
|
||||
MOZ_ASSERT(target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT));
|
||||
return emitDestructuringOps(target, DestructuringDeclaration);
|
||||
@ -6226,6 +6173,33 @@ BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitte
|
||||
MOZ_ASSERT(forInHead->isKind(PNK_FORIN));
|
||||
MOZ_ASSERT(forInHead->isArity(PN_TERNARY));
|
||||
|
||||
// Annex B: Evaluate the var-initializer expression if present.
|
||||
// |for (var i = initializer in expr) { ... }|
|
||||
ParseNode* forInTarget = forInHead->pn_kid1;
|
||||
if (parser->handler.isDeclarationList(forInTarget)) {
|
||||
ParseNode* decl = parser->handler.singleBindingFromDeclaration(forInTarget);
|
||||
if (decl->isKind(PNK_NAME)) {
|
||||
if (ParseNode* initializer = decl->expr()) {
|
||||
MOZ_ASSERT(forInTarget->isKind(PNK_VAR),
|
||||
"for-in initializers are only permitted for |var| declarations");
|
||||
|
||||
if (!updateSourceCoordNotes(decl->pn_pos.begin))
|
||||
return false;
|
||||
|
||||
auto emitRhs = [initializer](BytecodeEmitter* bce, const NameLocation&, bool) {
|
||||
return bce->emitTree(initializer);
|
||||
};
|
||||
|
||||
if (!emitInitializeName(decl, emitRhs))
|
||||
return false;
|
||||
|
||||
// Pop the initializer.
|
||||
if (!emit1(JSOP_POP))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate the expression being iterated.
|
||||
ParseNode* expr = forInHead->pn_kid3;
|
||||
if (!emitTree(expr)) // EXPR
|
||||
@ -6268,7 +6242,6 @@ BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitte
|
||||
// recreation each iteration. If a lexical scope exists for the head,
|
||||
// it must be the innermost one. If that scope has closed-over
|
||||
// bindings inducing an environment, recreate the current environment.
|
||||
DebugOnly<ParseNode*> forInTarget = forInHead->pn_kid1;
|
||||
MOZ_ASSERT(forInTarget->isKind(PNK_LET) || forInTarget->isKind(PNK_CONST));
|
||||
MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope);
|
||||
MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
|
||||
|
@ -641,17 +641,19 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
||||
DestructuringAssignment
|
||||
};
|
||||
|
||||
// EmitDestructuringLHS assumes the to-be-destructured value has been pushed on
|
||||
// emitDestructuringLHS assumes the to-be-destructured value has been pushed on
|
||||
// the stack and emits code to destructure a single lhs expression (either a
|
||||
// name or a compound []/{} expression).
|
||||
MOZ_MUST_USE bool emitDestructuringLHS(ParseNode* target, DestructuringFlavor flav);
|
||||
MOZ_MUST_USE bool emitConditionallyExecutedDestructuringLHS(ParseNode* target,
|
||||
DestructuringFlavor flav);
|
||||
|
||||
// emitDestructuringOps assumes the to-be-destructured value has been
|
||||
// pushed on the stack and emits code to destructure each part of a [] or
|
||||
// {} lhs expression.
|
||||
MOZ_MUST_USE bool emitDestructuringOps(ParseNode* pattern, DestructuringFlavor flav);
|
||||
MOZ_MUST_USE bool emitDestructuringOpsHelper(ParseNode* pattern, DestructuringFlavor flav);
|
||||
MOZ_MUST_USE bool emitDestructuringOpsArrayHelper(ParseNode* pattern, DestructuringFlavor flav);
|
||||
MOZ_MUST_USE bool emitDestructuringOpsObjectHelper(ParseNode* pattern, DestructuringFlavor flav);
|
||||
MOZ_MUST_USE bool emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlavor flav);
|
||||
MOZ_MUST_USE bool emitDestructuringOpsObject(ParseNode* pattern, DestructuringFlavor flav);
|
||||
|
||||
typedef bool
|
||||
(*DestructuringDeclEmitter)(BytecodeEmitter* bce, ParseNode* pn);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user