зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. a=merge CLOSED TREE
This commit is contained in:
Коммит
09ac74505a
|
@ -106,17 +106,17 @@
|
|||
</vbox>
|
||||
|
||||
<button id="tracking-action-unblock"
|
||||
class="tracking-protection-button"
|
||||
class="panel-button tracking-protection-button"
|
||||
label="&trackingProtection.unblock4.label;"
|
||||
accesskey="&trackingProtection.unblock4.accesskey;"
|
||||
oncommand="ContentBlocking.disableForCurrentPage(); gIdentityHandler.recordClick('unblock');" />
|
||||
<button id="tracking-action-unblock-private"
|
||||
class="tracking-protection-button"
|
||||
class="panel-button tracking-protection-button"
|
||||
label="&trackingProtection.unblockPrivate4.label;"
|
||||
accesskey="&trackingProtection.unblockPrivate4.accesskey;"
|
||||
oncommand="ContentBlocking.disableForCurrentPage(); gIdentityHandler.recordClick('unblock_private');" />
|
||||
<button id="tracking-action-block"
|
||||
class="tracking-protection-button"
|
||||
class="panel-button tracking-protection-button"
|
||||
label="&trackingProtection.block5.label;"
|
||||
accesskey="&trackingProtection.block5.accesskey;"
|
||||
oncommand="ContentBlocking.enableForCurrentPage(); gIdentityHandler.recordClick('block');" />
|
||||
|
@ -188,6 +188,7 @@
|
|||
<button when-connection="secure-cert-user-overridden"
|
||||
label="&identity.removeCertException.label;"
|
||||
accesskey="&identity.removeCertException.accesskey;"
|
||||
class="panel-button"
|
||||
oncommand="gIdentityHandler.removeCertException()"/>
|
||||
|
||||
<!-- Connection is Not Secure -->
|
||||
|
@ -230,10 +231,12 @@
|
|||
<button when-mixedcontent="active-blocked"
|
||||
label="&identity.disableMixedContentBlocking.label;"
|
||||
accesskey="&identity.disableMixedContentBlocking.accesskey;"
|
||||
class="panel-button"
|
||||
oncommand="gIdentityHandler.disableMixedContentProtection()"/>
|
||||
<button when-mixedcontent="active-loaded"
|
||||
label="&identity.enableMixedContentBlocking.label;"
|
||||
accesskey="&identity.enableMixedContentBlocking.accesskey;"
|
||||
class="panel-button"
|
||||
oncommand="gIdentityHandler.enableMixedContentProtection()"/>
|
||||
</vbox>
|
||||
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"title": "OnboardingMessage",
|
||||
"description": "A template with a title, icon, button and description. No markup allowed.",
|
||||
"version": "1.0.0",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The message displayed in the title of the onboarding card"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"string_id": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["string_id"],
|
||||
"description": "Id of localized string for onboarding card title"
|
||||
}
|
||||
],
|
||||
"description": "Id of localized string or message override."
|
||||
},
|
||||
"text": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The message displayed in the description of the onboarding card"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"string_id": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["string_id"],
|
||||
"description": "Id of localized string for onboarding card description"
|
||||
}
|
||||
],
|
||||
"description": "Id of localized string or message override."
|
||||
},
|
||||
"icon": {
|
||||
"allOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Image associated with the onboarding card"
|
||||
}
|
||||
]
|
||||
},
|
||||
"button_label": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The label of the onboarding card's action button"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"string_id": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["string_id"],
|
||||
"description": "Id of localized string for onboarding card button"
|
||||
}
|
||||
],
|
||||
"description": "Id of localized string or message override."
|
||||
},
|
||||
"button_action": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Action dispatched by the button."
|
||||
},
|
||||
"data": {
|
||||
"properties": {
|
||||
"args": {
|
||||
"type": "string",
|
||||
"description": "Additional parameters for button action, for example which link the button should open."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["title", "text", "icon", "button_label", "button_action"]
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ const ONBOARDING_MESSAGES = () => ([
|
|||
button_label: {string_id: "onboarding-button-label-try-now"},
|
||||
button_action: {
|
||||
type: "OPEN_URL",
|
||||
data: {url: "https://screenshots.firefox.com/#tour"},
|
||||
data: {args: "https://screenshots.firefox.com/#tour"},
|
||||
},
|
||||
},
|
||||
trigger: {id: "firstRun"},
|
||||
|
@ -52,7 +52,7 @@ const ONBOARDING_MESSAGES = () => ([
|
|||
button_label: {string_id: "onboarding-button-label-try-now"},
|
||||
button_action: {
|
||||
type: "OPEN_ABOUT_PAGE",
|
||||
data: {page: "addons"},
|
||||
data: {args: "addons"},
|
||||
},
|
||||
},
|
||||
trigger: {id: "firstRun"},
|
||||
|
@ -69,7 +69,7 @@ const ONBOARDING_MESSAGES = () => ([
|
|||
button_label: {string_id: "onboarding-button-label-try-now"},
|
||||
button_action: {
|
||||
type: "OPEN_URL",
|
||||
data: {url: "https://addons.mozilla.org/en-US/firefox/addon/ghostery/"},
|
||||
data: {args: "https://addons.mozilla.org/en-US/firefox/addon/ghostery/"},
|
||||
},
|
||||
},
|
||||
targeting: "providerCohorts.onboarding == 'ghostery'",
|
||||
|
@ -89,6 +89,10 @@ const OnboardingMessageProvider = {
|
|||
const messages = await this.translateMessages(ONBOARDING_MESSAGES());
|
||||
return messages;
|
||||
},
|
||||
getUntranslatedMessages() {
|
||||
// This is helpful for jsonSchema testing - since we are localizing in the provider
|
||||
return ONBOARDING_MESSAGES();
|
||||
},
|
||||
async translateMessages(messages) {
|
||||
let translatedMessages = [];
|
||||
for (const msg of messages) {
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
import {OnboardingMessageProvider} from "lib/OnboardingMessageProvider.jsm";
|
||||
import schema from "content-src/asrouter/templates/OnboardingMessage/OnboardingMessage.schema.json";
|
||||
|
||||
const DEFAULT_CONTENT = {
|
||||
"title": "A title",
|
||||
"text": "A description",
|
||||
"icon": "icon",
|
||||
"button_label": "some_button_label",
|
||||
"button_action": {
|
||||
"type": "SOME_TYPE",
|
||||
"data": {"args": "example.com"},
|
||||
},
|
||||
};
|
||||
|
||||
const L10N_CONTENT = {
|
||||
"title": {string_id: "onboarding-private-browsing-title"},
|
||||
"text": {string_id: "onboarding-private-browsing-text"},
|
||||
"icon": "icon",
|
||||
"button_label": {string_id: "onboarding-button-label-try-now"},
|
||||
"button_action": {type: "SOME_TYPE"},
|
||||
};
|
||||
|
||||
describe("OnboardingMessage", () => {
|
||||
it("should validate DEFAULT_CONTENT", () => {
|
||||
assert.jsonSchema(DEFAULT_CONTENT, schema);
|
||||
});
|
||||
it("should validate L10N_CONTENT", () => {
|
||||
assert.jsonSchema(L10N_CONTENT, schema);
|
||||
});
|
||||
it("should validate all messages from OnboardingMessageProvider", () => {
|
||||
const messages = OnboardingMessageProvider.getUntranslatedMessages();
|
||||
messages.forEach(msg => assert.jsonSchema(msg.content, schema));
|
||||
});
|
||||
});
|
||||
|
|
@ -641,15 +641,15 @@ var gEditItemOverlay = {
|
|||
toggleFolderTreeVisibility() {
|
||||
var expander = this._element("foldersExpander");
|
||||
var folderTreeRow = this._element("folderTreeRow");
|
||||
expander.classList.toggle("expander-up", folderTreeRow.collapsed);
|
||||
expander.classList.toggle("expander-down", !folderTreeRow.collapsed);
|
||||
if (!folderTreeRow.collapsed) {
|
||||
expander.className = "expander-down";
|
||||
expander.setAttribute("tooltiptext",
|
||||
expander.getAttribute("tooltiptextdown"));
|
||||
folderTreeRow.collapsed = true;
|
||||
this._element("chooseFolderSeparator").hidden =
|
||||
this._element("chooseFolderMenuItem").hidden = false;
|
||||
} else {
|
||||
expander.className = "expander-up";
|
||||
expander.setAttribute("tooltiptext",
|
||||
expander.getAttribute("tooltiptextup"));
|
||||
folderTreeRow.collapsed = false;
|
||||
|
@ -802,8 +802,9 @@ var gEditItemOverlay = {
|
|||
var tagsSelector = this._element("tagsSelector");
|
||||
var tagsSelectorRow = this._element("tagsSelectorRow");
|
||||
var expander = this._element("tagsSelectorExpander");
|
||||
expander.classList.toggle("expander-up", tagsSelectorRow.collapsed);
|
||||
expander.classList.toggle("expander-down", !tagsSelectorRow.collapsed);
|
||||
if (tagsSelectorRow.collapsed) {
|
||||
expander.className = "expander-up";
|
||||
expander.setAttribute("tooltiptext",
|
||||
expander.getAttribute("tooltiptextup"));
|
||||
tagsSelectorRow.collapsed = false;
|
||||
|
@ -813,7 +814,6 @@ var gEditItemOverlay = {
|
|||
tagsSelector.addEventListener("mousedown", this);
|
||||
tagsSelector.addEventListener("keypress", this);
|
||||
} else {
|
||||
expander.className = "expander-down";
|
||||
expander.setAttribute("tooltiptext",
|
||||
expander.getAttribute("tooltiptextdown"));
|
||||
tagsSelectorRow.collapsed = true;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
control="editBMPanel_folderMenuList"/>
|
||||
<hbox flex="1" align="center">
|
||||
<menulist id="editBMPanel_folderMenuList"
|
||||
class="folder-icon"
|
||||
class="folder-icon panel-button"
|
||||
flex="1"
|
||||
oncommand="gEditItemOverlay.onFolderMenuListCommand(event).catch(Components.utils.reportError);">
|
||||
<menupopup>
|
||||
|
@ -48,7 +48,7 @@
|
|||
</menupopup>
|
||||
</menulist>
|
||||
<button id="editBMPanel_foldersExpander"
|
||||
class="expander-down"
|
||||
class="expander-down panel-button"
|
||||
tooltiptext="&editBookmarkOverlay.foldersExpanderDown.tooltip;"
|
||||
tooltiptextdown="&editBookmarkOverlay.foldersExpanderDown.tooltip;"
|
||||
tooltiptextup="&editBookmarkOverlay.expanderUp.tooltip;"
|
||||
|
@ -98,7 +98,7 @@
|
|||
placeholder="&editBookmarkOverlay.tagsEmptyDesc.label;"
|
||||
onchange="gEditItemOverlay.onTagsFieldChange();"/>
|
||||
<button id="editBMPanel_tagsSelectorExpander"
|
||||
class="expander-down"
|
||||
class="expander-down panel-button"
|
||||
tooltiptext="&editBookmarkOverlay.tagsExpanderDown.tooltip;"
|
||||
tooltiptextdown="&editBookmarkOverlay.tagsExpanderDown.tooltip;"
|
||||
tooltiptextup="&editBookmarkOverlay.expanderUp.tooltip;"
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
top: -5px;
|
||||
}
|
||||
|
||||
.pkt_ext_saved_sendtomobile.pkt_ext_ho2_v1 .pkt_ext_loadingspinner {
|
||||
top: 110px;
|
||||
}
|
||||
|
||||
.pkt_ext_save_title_wrapper {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
|
@ -95,13 +91,6 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pkt_ext_ho2_v1 {
|
||||
background-color: #EBEBEB;
|
||||
border-top: 1px solid #C3C3C3;
|
||||
padding: 17px;
|
||||
height: 144px;
|
||||
}
|
||||
|
||||
.pkt_ext_experiment_saved_tile {
|
||||
position: relative;
|
||||
margin: 0 auto 17px;
|
||||
|
|
|
@ -3,31 +3,11 @@
|
|||
var PKT_SENDTOMOBILE = (function() {
|
||||
|
||||
var width = 350;
|
||||
var variant1Height = 312;
|
||||
var variant2Height = 200;
|
||||
var ctaHeight = 200;
|
||||
var confirmHeight = 275;
|
||||
var premDetailsHeight = 110;
|
||||
var email = null;
|
||||
|
||||
function _swapPlaceholder(data) {
|
||||
var info = {};
|
||||
|
||||
if (!data.item_preview) {
|
||||
info.domain = data.fallback_domain;
|
||||
info.title = data.fallback_title;
|
||||
} else {
|
||||
info.domain = data.item_preview.resolved_domain;
|
||||
info.title = data.item_preview.title;
|
||||
info.has_image = (data.item_preview.top_image_url) ? 1 : 0;
|
||||
|
||||
if (data.item_preview.top_image_url) {
|
||||
info.image_src = getImageCacheUrl(data.item_preview.top_image_url, "w225");
|
||||
}
|
||||
}
|
||||
|
||||
$("#pkt_ext_swap").replaceWith(Handlebars.templates.ho2_articleinfo(info));
|
||||
}
|
||||
|
||||
function _initPanelOneClicks() {
|
||||
$("#pkt_ext_sendtomobile_button").click(function() {
|
||||
$("#pkt_ext_sendtomobile_button").replaceWith("<div class=\"pkt_ext_loadingspinner\"><div></div></div>");
|
||||
|
@ -49,22 +29,10 @@ var PKT_SENDTOMOBILE = (function() {
|
|||
$("body").addClass("pkt_ext_ho2_experiment");
|
||||
var height = (adjustHeight) ? premDetailsHeight : 0;
|
||||
|
||||
if (ho2 == "show_prompt_preview") {
|
||||
height += variant1Height;
|
||||
$("body").append(Handlebars.templates.ho2_sharebutton_v1());
|
||||
thePKT_SAVED.sendMessage("resizePanel", { width, height });
|
||||
thePKT_SAVED.sendMessage("getArticleInfo", {}, function(data) {
|
||||
_swapPlaceholder(data);
|
||||
});
|
||||
} else if (ho2 == "show_prompt_no_preview") {
|
||||
height += variant2Height;
|
||||
$("body").append(Handlebars.templates.ho2_sharebutton_v2());
|
||||
thePKT_SAVED.sendMessage("resizePanel", { width, height });
|
||||
} else if (ho2 == "show_prompt_get_app") {
|
||||
height += variant2Height;
|
||||
$("body").append(Handlebars.templates.ho2_sharebutton_v3());
|
||||
thePKT_SAVED.sendMessage("resizePanel", { width, height });
|
||||
}
|
||||
// Show "Send to your phone" CTA
|
||||
height += ctaHeight;
|
||||
$("body").append(Handlebars.templates.ho2_sharebutton());
|
||||
thePKT_SAVED.sendMessage("resizePanel", { width, height });
|
||||
|
||||
_initPanelOneClicks();
|
||||
}
|
||||
|
@ -76,23 +44,3 @@ var PKT_SENDTOMOBILE = (function() {
|
|||
create,
|
||||
};
|
||||
}());
|
||||
|
||||
|
||||
/**
|
||||
* This function is based on getImageCacheUrl in:
|
||||
* https://github.com/Pocket/Web/blob/master/public_html/a/j/shared.js
|
||||
*/
|
||||
function getImageCacheUrl(url, resize, fallback) {
|
||||
if (!url)
|
||||
return false;
|
||||
// The full URL should be included in the get parameters such that the image cache can request it.
|
||||
var query = {
|
||||
"url": url,
|
||||
};
|
||||
if (resize)
|
||||
query.resize = resize;
|
||||
if (fallback)
|
||||
query.f = fallback;
|
||||
|
||||
return "https://d33ypg4xwx0n86.cloudfront.net/direct?" + $.param(query);
|
||||
}
|
||||
|
|
|
@ -33,15 +33,9 @@ templates['ho2_download'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":fu
|
|||
templates['ho2_download_error'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
|
||||
return "<div class=\"pkt_ext_detail pkt_ext_saved_sendcollectemail\">\n <h3 class=\"pkt_ext_heading\">There was a problem</h3>\n <p class=\"pkt_ext_description\">Email failed to send, please try again later</p>\n\n <div class=\"pkt_ext_download_section\">\n <p class=\"pkt_ext_description\">You can also get the Pocket app on the App Store here:</p>\n\n <div class=\"pkt_ext_download_button_wrapper\">\n <a href=\"https://getpocket.com/apps/link/pocket-iphone/?s=fx_save_hanger\" target=\"_blank\" ><div class=\"pkt_ext_apple_download\"></div></a>\n <a href=\"https://getpocket.com/apps/link/pocket-android/?s=fx_save_hanger\" target=\"_blank\" ><img class=\"pkt_ext_google_download\" alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png'/></a>\n </div>\n </div>\n</div>\n";
|
||||
},"useData":true});
|
||||
templates['ho2_sharebutton_v1'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
|
||||
return "<div class=\"pkt_ext_detail pkt_ext_saved_sendtomobile pkt_ext_ho2_v1\">\n <div id=\"pkt_ext_articleinfo\">\n <div id=\"pkt_ext_swap\" class=\"pkt_ext_experiment_saved_tile pkt_ext_has_image pkt_ext_cf\">\n <div class=\"pkt_ext_save_image pkt_ext_save_image_placeholder\"></div>\n\n <div class=\"pkt_ext_save_title pkt_ext_title_image_placeholder\">\n <div class=\"pkt_ext_save_open\"> </div>\n <div class=\"pkt_ext_save_source\"> </div>\n </div>\n </div>\n </div>\n\n <button id=\"pkt_ext_sendtomobile_button\" class=\"pkt_ext_button\">\n <span class=\"pkt_ext_save_title_wrapper pkt_ext_mobile_icon\">\n <span class=\"pkt_ext_logo_action_copy\">Send to your phone</span>\n </span>\n </button>\n</div>\n";
|
||||
},"useData":true});
|
||||
templates['ho2_sharebutton_v2'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
|
||||
templates['ho2_sharebutton'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
|
||||
return "<div class=\"pkt_ext_detail pkt_ext_saved_sendtomobile\">\n <button id=\"pkt_ext_sendtomobile_button\" class=\"pkt_ext_button\">\n <span class=\"pkt_ext_save_title_wrapper pkt_ext_mobile_icon\">\n <span class=\"pkt_ext_logo_action_copy\">Send to your phone</span>\n </span>\n </button>\n</div>\n";
|
||||
},"useData":true});
|
||||
templates['ho2_sharebutton_v3'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
|
||||
return "<div class=\"pkt_ext_detail pkt_ext_saved_sendtomobile\">\n <button id=\"pkt_ext_sendtomobile_button\" class=\"pkt_ext_button\">\n <span class=\"pkt_ext_save_title_wrapper pkt_ext_mobile_icon\">\n <span class=\"pkt_ext_logo_action_copy\">Get the Pocket Mobile App</span>\n </span>\n </button>\n</div>\n";
|
||||
},"useData":true});
|
||||
templates['saved_premiumextras'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
|
||||
return "<div class=\"pkt_ext_suggestedtag_detailshown\">\r\n</div> ";
|
||||
},"useData":true});
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
<div class="pkt_ext_detail pkt_ext_saved_sendtomobile pkt_ext_ho2_v1">
|
||||
<div id="pkt_ext_articleinfo">
|
||||
<div id="pkt_ext_swap" class="pkt_ext_experiment_saved_tile pkt_ext_has_image pkt_ext_cf">
|
||||
<div class="pkt_ext_save_image pkt_ext_save_image_placeholder"></div>
|
||||
|
||||
<div class="pkt_ext_save_title pkt_ext_title_image_placeholder">
|
||||
<div class="pkt_ext_save_open"> </div>
|
||||
<div class="pkt_ext_save_source"> </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="pkt_ext_sendtomobile_button" class="pkt_ext_button">
|
||||
<span class="pkt_ext_save_title_wrapper pkt_ext_mobile_icon">
|
||||
<span class="pkt_ext_logo_action_copy">Send to your phone</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
|
@ -1,7 +0,0 @@
|
|||
<div class="pkt_ext_detail pkt_ext_saved_sendtomobile">
|
||||
<button id="pkt_ext_sendtomobile_button" class="pkt_ext_button">
|
||||
<span class="pkt_ext_save_title_wrapper pkt_ext_mobile_icon">
|
||||
<span class="pkt_ext_logo_action_copy">Get the Pocket Mobile App</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
|
@ -2,7 +2,7 @@
|
|||
* 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 shared.inc
|
||||
%include ../../../toolkit/themes/osx/global/shared.inc
|
||||
%define toolbarButtonPressed :hover:active:not([disabled="true"]):not([cui-areatype="menu-panel"])
|
||||
|
||||
@namespace html url("http://www.w3.org/1999/xhtml");
|
||||
|
@ -25,6 +25,8 @@
|
|||
--arrowpanel-dimmed-further: hsla(0,0%,80%,.45);
|
||||
--arrowpanel-dimmed-even-further: hsla(0,0%,80%,.8);
|
||||
|
||||
--arrowpanel-field-background: rgba(249,249,250,.3);
|
||||
|
||||
--urlbar-separator-color: hsla(0,0%,16%,.2);
|
||||
|
||||
--toolbox-border-bottom-color: #e1e1e2;
|
||||
|
@ -43,6 +45,8 @@
|
|||
--arrowpanel-dimmed: rgba(249,249,250,.1);
|
||||
--arrowpanel-dimmed-further: rgba(249,249,250,.15);
|
||||
--arrowpanel-dimmed-even-further: rgba(249,249,250,.2);
|
||||
|
||||
--arrowpanel-field-background: rgba(12,12,13,.3);
|
||||
}
|
||||
|
||||
#navigator-toolbox {
|
||||
|
@ -398,12 +402,10 @@ html|input.urlbar-input {
|
|||
#editBookmarkPanelRows > vbox > textbox,
|
||||
#editBookmarkPanelRows > vbox > hbox > textbox {
|
||||
-moz-appearance: none;
|
||||
background: linear-gradient(#fafafa, #fff);
|
||||
background-clip: padding-box;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(0,0,0,.3) !important;
|
||||
box-shadow: inset 0 1px 1px 1px rgba(0,0,0,.05),
|
||||
0 1px rgba(255,255,255,.3);
|
||||
background-color: var(--arrowpanel-field-background);
|
||||
color: inherit;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--panel-separator-color) !important;
|
||||
margin: 0;
|
||||
padding: 3px 6px;
|
||||
}
|
||||
|
@ -420,49 +422,38 @@ html|input.urlbar-input {
|
|||
editBookmark.css. */
|
||||
|
||||
#editBMPanel_newFolderBox {
|
||||
background: linear-gradient(#fff, #f2f2f2);
|
||||
background-origin: padding-box;
|
||||
background-clip: padding-box;
|
||||
border-radius: 0 0 3px 3px;
|
||||
border: 1px solid #a5a5a5;
|
||||
box-shadow: inset 0 1px rgba(255,255,255,.8),
|
||||
inset 0 0 1px rgba(255,255, 255,.25),
|
||||
0 1px rgba(255,255,255,.3);
|
||||
background-color: var(--arrowpanel-field-background);
|
||||
color: inherit;
|
||||
border-radius: 0 2px;
|
||||
border: 1px solid var(--panel-separator-color);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
#editBMPanel_newFolderButton {
|
||||
-moz-appearance: none;
|
||||
border: 0 solid #a5a5a5;
|
||||
border: 0 solid var(--panel-separator-color);
|
||||
border-inline-end-width: 1px;
|
||||
padding: 0 9px;
|
||||
margin: 0;
|
||||
min-width: 21px;
|
||||
min-height: 20px;
|
||||
height: 20px;
|
||||
color: #fff;
|
||||
height: 20px;
|
||||
color: inherit;
|
||||
list-style-image: url("chrome://browser/skin/panel-plus-sign.png");
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#editBMPanel_newFolderButton:hover:active {
|
||||
background: linear-gradient(rgba(40,40,40,.9), rgba(70,70,70,.9));
|
||||
box-shadow: inset 0 0 3px rgba(0,0,0,.2), inset 0 1px 7px rgba(0,0,0,.4);
|
||||
background-color: var(--arrowpanel-dimmed-further);
|
||||
}
|
||||
|
||||
#editBMPanel_newFolderButton:-moz-focusring {
|
||||
box-shadow: var(--focus-ring-box-shadow);
|
||||
}
|
||||
|
||||
#editBMPanel_newFolderButton .button-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#editBMPanel_folderMenuList {
|
||||
@hudButton@
|
||||
background-clip: padding-box;
|
||||
margin: 0;
|
||||
min-height: 22px;
|
||||
padding-top: 2px;
|
||||
|
@ -475,18 +466,16 @@ html|input.urlbar-input {
|
|||
box-shadow: var(--focus-ring-box-shadow);
|
||||
}
|
||||
|
||||
#editBMPanel_folderMenuList[open="true"],
|
||||
#editBMPanel_folderMenuList:hover:active {
|
||||
@hudButtonPressed@
|
||||
}
|
||||
|
||||
#editBMPanel_folderMenuList > .menulist-dropmarker {
|
||||
-moz-appearance: none;
|
||||
-moz-context-properties: fill, fill-opacity;
|
||||
fill: currentColor;
|
||||
fill-opacity: 0.8;
|
||||
list-style-image: url("chrome://global/skin/icons/arrow-dropdown-12.svg");
|
||||
display: -moz-box;
|
||||
-moz-box-align: center;
|
||||
padding-inline-end: 4px;
|
||||
width: 7px;
|
||||
list-style-image: url("chrome://global/skin/icons/panel-dropmarker.png");
|
||||
}
|
||||
|
||||
/**** folder tree and tag selector ****/
|
||||
|
@ -494,12 +483,10 @@ html|input.urlbar-input {
|
|||
#editBMPanel_folderTree,
|
||||
#editBMPanel_tagsSelector {
|
||||
-moz-appearance: none;
|
||||
background: linear-gradient(#fafafa, #fff);
|
||||
background-clip: padding-box;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(0,0,0,.3);
|
||||
box-shadow: inset 0 1px 1px 1px rgba(0,0,0,.05),
|
||||
0 1px rgba(255,255,255,.3);
|
||||
background-color: var(--arrowpanel-field-background);
|
||||
color: inherit;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--panel-separator-color);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
@ -523,31 +510,16 @@ html|input.urlbar-input {
|
|||
|
||||
#editBookmarkPanel .expander-up,
|
||||
#editBookmarkPanel .expander-down {
|
||||
@hudButton@
|
||||
-moz-appearance: none; /* override button.css */
|
||||
-moz-context-properties: fill, fill-opacity;
|
||||
fill: currentColor;
|
||||
fill-opacity: 0.8;
|
||||
margin: 0;
|
||||
margin-inline-start: 4px;
|
||||
min-width: 27px;
|
||||
min-height: 22px;
|
||||
}
|
||||
|
||||
#editBookmarkPanel .expander-up:-moz-focusring,
|
||||
#editBookmarkPanel .expander-down:-moz-focusring {
|
||||
box-shadow: var(--focus-ring-box-shadow);
|
||||
}
|
||||
|
||||
#editBookmarkPanel .expander-up:hover:active,
|
||||
#editBookmarkPanel .expander-down:hover:active {
|
||||
@hudButtonPressed@
|
||||
}
|
||||
|
||||
#editBookmarkPanel .expander-up {
|
||||
list-style-image: url("chrome://browser/skin/panel-expander-open.png");
|
||||
}
|
||||
|
||||
#editBookmarkPanel .expander-down {
|
||||
list-style-image: url("chrome://browser/skin/panel-expander-closed.png");
|
||||
}
|
||||
|
||||
#editBookmarkPanel .expander-up > .button-box > .button-icon,
|
||||
#editBookmarkPanel .expander-down > .button-box > .button-icon {
|
||||
margin: 1px 0 0;
|
||||
|
@ -558,19 +530,12 @@ html|input.urlbar-input {
|
|||
display: none;
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#editBookmarkPanel .expander-up {
|
||||
list-style-image: url("chrome://browser/skin/panel-expander-open@2x.png");
|
||||
}
|
||||
#editBookmarkPanel .expander-up {
|
||||
list-style-image: url("chrome://global/skin/icons/arrow-up-12.svg");
|
||||
}
|
||||
|
||||
#editBookmarkPanel .expander-down {
|
||||
list-style-image: url("chrome://browser/skin/panel-expander-closed@2x.png");
|
||||
}
|
||||
|
||||
#editBookmarkPanel .expander-up > .button-box > .button-icon,
|
||||
#editBookmarkPanel .expander-down > .button-box > .button-icon {
|
||||
width: 9px;
|
||||
}
|
||||
#editBookmarkPanel .expander-down {
|
||||
list-style-image: url("chrome://global/skin/icons/arrow-dropdown-12.svg");
|
||||
}
|
||||
|
||||
#editBMPanel_tagsField > moz-input-box > html|*.textbox-input::placeholder {
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
* 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 ../shared.inc
|
||||
%include ../../shared/controlcenter/panel.inc.css
|
||||
|
||||
.identity-popup-expander:-moz-focusring,
|
||||
|
@ -12,15 +11,9 @@
|
|||
|
||||
.tracking-protection-button,
|
||||
#identity-popup-securityView-body > button {
|
||||
@hudButton@
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
.tracking-protection-button:hover:active,
|
||||
#identity-popup-securityView-body > button:hover:active {
|
||||
@hudButtonPressed@
|
||||
}
|
||||
|
||||
.tracking-protection-button:-moz-focusring,
|
||||
#identity-popup-securityView-body > button:-moz-focusring {
|
||||
box-shadow: var(--focus-ring-box-shadow);
|
||||
|
|
|
@ -80,3 +80,23 @@ menu.subviewbutton > .menu-right {
|
|||
#PanelUI-remotetabs-tabslist {
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.panel-button {
|
||||
-moz-appearance: none;
|
||||
border-radius: 2px;
|
||||
background-color: var(--arrowpanel-dimmed);
|
||||
color: inherit;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
.panel-button@buttonStateHover@ {
|
||||
background-color: var(--arrowpanel-dimmed-further);
|
||||
}
|
||||
|
||||
.panel-button@buttonStateActive@ {
|
||||
background-color: var(--arrowpanel-dimmed-even-further);
|
||||
}
|
||||
|
||||
.panel-button:-moz-focusring {
|
||||
box-shadow: var(--focus-ring-box-shadow);
|
||||
}
|
||||
|
|
|
@ -9,10 +9,6 @@ browser.jar:
|
|||
* skin/classic/browser/syncedtabs/sidebar.css (syncedtabs/sidebar.css)
|
||||
* skin/classic/browser/browser.css
|
||||
* skin/classic/browser/compacttheme.css
|
||||
skin/classic/browser/panel-expander-closed.png
|
||||
skin/classic/browser/panel-expander-closed@2x.png
|
||||
skin/classic/browser/panel-expander-open.png
|
||||
skin/classic/browser/panel-expander-open@2x.png
|
||||
skin/classic/browser/panel-plus-sign.png
|
||||
* skin/classic/browser/pageInfo.css
|
||||
* skin/classic/browser/searchbar.css
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
@import "chrome://global/skin/";
|
||||
|
||||
%include shared.inc
|
||||
%include ../../../toolkit/themes/osx/global/shared.inc
|
||||
|
||||
#topBar {
|
||||
-moz-appearance: toolbar;
|
||||
|
|
Двоичные данные
browser/themes/osx/panel-expander-closed.png
Двоичные данные
browser/themes/osx/panel-expander-closed.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 154 B |
Двоичные данные
browser/themes/osx/panel-expander-closed@2x.png
Двоичные данные
browser/themes/osx/panel-expander-closed@2x.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 362 B |
Двоичные данные
browser/themes/osx/panel-expander-open.png
Двоичные данные
browser/themes/osx/panel-expander-open.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 154 B |
Двоичные данные
browser/themes/osx/panel-expander-open@2x.png
Двоичные данные
browser/themes/osx/panel-expander-open@2x.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 356 B |
|
@ -1,6 +0,0 @@
|
|||
%include ../../../toolkit/themes/osx/global/shared.inc
|
||||
|
||||
%filter substitution
|
||||
|
||||
%define hudButton -moz-appearance: none; color: #434343; border-radius: 4px; border: 1px solid #b5b5b5; background: linear-gradient(#fff, #f2f2f2); box-shadow: inset 0 1px rgba(255,255,255,.8), inset 0 0 1px rgba(255,255, 255,.25), 0 1px rgba(255,255,255,.3); background-clip: padding-box; background-origin: padding-box; padding: 2px 6px;
|
||||
%define hudButtonPressed box-shadow: inset 0 1px 4px -3px #000, 0 1px rgba(255,255,255,.3);
|
|
@ -294,7 +294,7 @@ cbindgen = check_prog('CBINDGEN', add_rustup_path('cbindgen'), paths=toolchain_s
|
|||
@checking('cbindgen version')
|
||||
@imports(_from='textwrap', _import='dedent')
|
||||
def cbindgen_version(cbindgen):
|
||||
cbindgen_min_version = Version('0.6.6')
|
||||
cbindgen_min_version = Version('0.6.7')
|
||||
|
||||
# cbindgen x.y.z
|
||||
version = Version(check_cmd_output(cbindgen, '--version').strip().split(" ")[1])
|
||||
|
|
|
@ -61,6 +61,16 @@ async function testWithNoTouch(ui) {
|
|||
await EventUtils.synthesizeClick(div);
|
||||
is(div.dataset.isDelay, "false",
|
||||
"300ms delay between touch events and mouse events should not work");
|
||||
|
||||
// Assuming that this test runs on devices having no touch screen device.
|
||||
ok(!content.document.defaultView.matchMedia("(pointer: coarse)").matches,
|
||||
"pointer: coarse shouldn't be matched");
|
||||
ok(!content.document.defaultView.matchMedia("(hover: none)").matches,
|
||||
"hover: none shouldn't be matched");
|
||||
ok(!content.document.defaultView.matchMedia("(any-pointer: coarse)").matches,
|
||||
"any-pointer: coarse shouldn't be matched");
|
||||
ok(!content.document.defaultView.matchMedia("(any-hover: none)").matches,
|
||||
"any-hover: none shouldn't be matched");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -98,6 +108,15 @@ async function testWithTouch(ui) {
|
|||
{ type: "mousemove", isSynthesized: false }, content);
|
||||
isnot(div.style.backgroundColor, "blue",
|
||||
"mouseout or mouseleave should not work");
|
||||
|
||||
ok(content.document.defaultView.matchMedia("(pointer: coarse)").matches,
|
||||
"pointer: coarse should be matched");
|
||||
ok(content.document.defaultView.matchMedia("(hover: none)").matches,
|
||||
"hover: none should be matched");
|
||||
ok(content.document.defaultView.matchMedia("(any-pointer: coarse)").matches,
|
||||
"any-pointer: coarse should be matched");
|
||||
ok(content.document.defaultView.matchMedia("(any-hover: none)").matches,
|
||||
"any-hover: none should be matched");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -773,9 +773,6 @@ CustomElementRegistry::Define(JSContext* aCx,
|
|||
const ElementDefinitionOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// Note: No calls that might run JS or trigger CC before this point, or
|
||||
// there's a (vanishingly small) chance of our constructor being nulled
|
||||
// before we access it.
|
||||
JS::Rooted<JSObject*> constructor(aCx, aFunctionConstructor.CallableOrNull());
|
||||
|
||||
JS::Rooted<JSObject*> constructorUnwrapped(aCx, js::CheckedUnwrap(constructor));
|
||||
|
|
|
@ -2674,7 +2674,8 @@ nsContentUtils::PositionIsBefore(nsINode* aNode1, nsINode* aNode2,
|
|||
int32_t
|
||||
nsContentUtils::ComparePoints(nsINode* aParent1, int32_t aOffset1,
|
||||
nsINode* aParent2, int32_t aOffset2,
|
||||
bool* aDisconnected)
|
||||
bool* aDisconnected,
|
||||
ComparePointsCache* aParent1Cache)
|
||||
{
|
||||
if (aParent1 == aParent2) {
|
||||
// XXX This is odd. aOffset1 and/or aOffset2 may be -1, e.g., it's result
|
||||
|
@ -2716,7 +2717,9 @@ nsContentUtils::ComparePoints(nsINode* aParent1, int32_t aOffset1,
|
|||
nsINode* child1 = parents1.ElementAt(--pos1);
|
||||
nsINode* child2 = parents2.ElementAt(--pos2);
|
||||
if (child1 != child2) {
|
||||
return parent->ComputeIndexOf(child1) < parent->ComputeIndexOf(child2) ? -1 : 1;
|
||||
int32_t child1index = aParent1Cache ? aParent1Cache->ComputeIndexOf(parent, child1) :
|
||||
parent->ComputeIndexOf(child1);
|
||||
return child1index < parent->ComputeIndexOf(child2) ? -1 : 1;
|
||||
}
|
||||
parent = child1;
|
||||
}
|
||||
|
@ -2738,7 +2741,9 @@ nsContentUtils::ComparePoints(nsINode* aParent1, int32_t aOffset1,
|
|||
nsINode* child1 = parents1.ElementAt(--pos1);
|
||||
// XXX aOffset2 may be -1 as mentioned above. So, why does this return it's
|
||||
// *after* of the valid DOM point?
|
||||
return parent->ComputeIndexOf(child1) < aOffset2 ? -1 : 1;
|
||||
int32_t child1index = aParent1Cache ? aParent1Cache->ComputeIndexOf(parent, child1) :
|
||||
parent->ComputeIndexOf(child1);
|
||||
return child1index < aOffset2 ? -1 : 1;
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -458,6 +458,27 @@ public:
|
|||
int32_t* aNode1Index = nullptr,
|
||||
int32_t* aNode2Index = nullptr);
|
||||
|
||||
|
||||
struct ComparePointsCache {
|
||||
int32_t ComputeIndexOf(nsINode* aParent, nsINode* aChild) {
|
||||
if (aParent == mParent &&
|
||||
aChild == mChild) {
|
||||
return mIndex;
|
||||
}
|
||||
|
||||
mIndex = aParent->ComputeIndexOf(aChild);
|
||||
mParent = aParent;
|
||||
mChild = aChild;
|
||||
return mIndex;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
nsINode* mParent = nullptr;
|
||||
nsINode* mChild = nullptr;
|
||||
int32_t mIndex = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility routine to compare two "points", where a point is a
|
||||
* node/offset pair
|
||||
|
@ -467,6 +488,9 @@ public:
|
|||
* the result is 1, and the optional aDisconnected parameter
|
||||
* is set to true.
|
||||
*
|
||||
* Pass a cache object as aParent1Cache if you expect to repeatedly
|
||||
* call this function with the same value as aParent1.
|
||||
*
|
||||
* XXX aOffset1 and aOffset2 should be uint32_t since valid offset value is
|
||||
* between 0 - UINT32_MAX. However, these methods work even with
|
||||
* negative offset values! E.g., when aOffset1 is -1 and aOffset is 0,
|
||||
|
@ -476,7 +500,8 @@ public:
|
|||
*/
|
||||
static int32_t ComparePoints(nsINode* aParent1, int32_t aOffset1,
|
||||
nsINode* aParent2, int32_t aOffset2,
|
||||
bool* aDisconnected = nullptr);
|
||||
bool* aDisconnected = nullptr,
|
||||
ComparePointsCache* aParent1Cache = nullptr);
|
||||
static int32_t ComparePoints(const mozilla::RawRangeBoundary& aFirst,
|
||||
const mozilla::RawRangeBoundary& aSecond,
|
||||
bool* aDisconnected = nullptr);
|
||||
|
|
|
@ -171,6 +171,7 @@ struct IsItemInRangeComparator
|
|||
nsINode* mNode;
|
||||
uint32_t mStartOffset;
|
||||
uint32_t mEndOffset;
|
||||
nsContentUtils::ComparePointsCache* mCache;
|
||||
|
||||
int operator()(const nsRange* const aRange) const
|
||||
{
|
||||
|
@ -178,13 +179,13 @@ struct IsItemInRangeComparator
|
|||
nsContentUtils::ComparePoints(
|
||||
mNode, static_cast<int32_t>(mEndOffset),
|
||||
aRange->GetStartContainer(),
|
||||
static_cast<int32_t>(aRange->StartOffset()));
|
||||
static_cast<int32_t>(aRange->StartOffset()), nullptr, mCache);
|
||||
if (cmp == 1) {
|
||||
cmp =
|
||||
nsContentUtils::ComparePoints(
|
||||
mNode, static_cast<int32_t>(mStartOffset),
|
||||
aRange->GetEndContainer(),
|
||||
static_cast<int32_t>(aRange->EndOffset()));
|
||||
static_cast<int32_t>(aRange->EndOffset()), nullptr, mCache);
|
||||
if (cmp == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -228,7 +229,8 @@ nsRange::IsNodeSelected(nsINode* aNode, uint32_t aStartOffset,
|
|||
}
|
||||
}
|
||||
|
||||
IsItemInRangeComparator comparator = { aNode, aStartOffset, aEndOffset };
|
||||
nsContentUtils::ComparePointsCache cache;
|
||||
IsItemInRangeComparator comparator = { aNode, aStartOffset, aEndOffset, &cache };
|
||||
if (!ancestorSelections.IsEmpty()) {
|
||||
for (auto iter = ancestorSelections.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
Selection* selection = iter.Get()->GetKey();
|
||||
|
@ -254,7 +256,7 @@ nsRange::IsNodeSelected(nsINode* aNode, uint32_t aStartOffset,
|
|||
nsContentUtils::ComparePoints(
|
||||
aNode, static_cast<int32_t>(aEndOffset),
|
||||
middlePlus1->GetStartContainer(),
|
||||
static_cast<int32_t>(middlePlus1->StartOffset())) > 0) {
|
||||
static_cast<int32_t>(middlePlus1->StartOffset()), nullptr, &cache) > 0) {
|
||||
result = 1;
|
||||
// if node start < end of middle - 1, result = -1
|
||||
} else if (middle >= 1 &&
|
||||
|
@ -262,7 +264,7 @@ nsRange::IsNodeSelected(nsINode* aNode, uint32_t aStartOffset,
|
|||
nsContentUtils::ComparePoints(
|
||||
aNode, static_cast<int32_t>(aStartOffset),
|
||||
middleMinus1->GetEndContainer(),
|
||||
static_cast<int32_t>(middleMinus1->EndOffset())) < 0) {
|
||||
static_cast<int32_t>(middleMinus1->EndOffset()), nullptr, &cache) < 0) {
|
||||
result = -1;
|
||||
} else {
|
||||
break;
|
||||
|
|
|
@ -1050,8 +1050,6 @@ public:
|
|||
retval.set(GetParameter(cx, pname, rv));
|
||||
}
|
||||
|
||||
void GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index,
|
||||
JS::MutableHandle<JS::Value> retval);
|
||||
bool IsEnabled(GLenum cap);
|
||||
|
||||
private:
|
||||
|
|
|
@ -602,36 +602,6 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
|||
return JS::NullValue();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index,
|
||||
JS::MutableHandle<JS::Value> retval)
|
||||
{
|
||||
const FuncScope funcScope(*this, "getParameterIndexed");
|
||||
if (IsContextLost()) {
|
||||
retval.setNull();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
|
||||
{
|
||||
if (index >= mGLMaxTransformFeedbackSeparateAttribs) {
|
||||
ErrorInvalidValue("`index` should be less than MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
|
||||
retval.setNull();
|
||||
return;
|
||||
}
|
||||
retval.setNull(); // See bug 903594
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ErrorInvalidEnumInfo("pname", pname);
|
||||
retval.setNull();
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::IsEnabled(GLenum cap)
|
||||
{
|
||||
|
|
|
@ -293,7 +293,6 @@ SystemClockDriver::SystemClockDriver(MediaStreamGraphImpl* aGraphImpl)
|
|||
: ThreadedDriver(aGraphImpl),
|
||||
mInitialTimeStamp(TimeStamp::Now()),
|
||||
mLastTimeStamp(TimeStamp::Now()),
|
||||
mWaitState(WAITSTATE_RUNNING),
|
||||
mIsFallback(false)
|
||||
{}
|
||||
|
||||
|
@ -401,70 +400,68 @@ OfflineClockDriver::GetCurrentTimeStamp()
|
|||
}
|
||||
|
||||
void
|
||||
SystemClockDriver::WaitForNextIteration()
|
||||
ThreadedDriver::WaitForNextIteration()
|
||||
{
|
||||
GraphImpl()->GetMonitor().AssertCurrentThreadOwns();
|
||||
|
||||
TimeDuration timeout = TimeDuration::Forever();
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
|
||||
// This lets us avoid hitting the Atomic twice when we know we won't sleep
|
||||
bool another = GraphImpl()->mNeedAnotherIteration; // atomic
|
||||
if (!another) {
|
||||
GraphImpl()->mGraphDriverAsleep = true; // atomic
|
||||
mWaitState = WAITSTATE_WAITING_INDEFINITELY;
|
||||
}
|
||||
// NOTE: mNeedAnotherIteration while also atomic may have changed before
|
||||
// we could set mGraphDriverAsleep, so we must re-test it.
|
||||
// (EnsureNextIteration sets mNeedAnotherIteration, then tests
|
||||
// mGraphDriverAsleep
|
||||
if (another || GraphImpl()->mNeedAnotherIteration) { // atomic
|
||||
int64_t timeoutMS = MEDIA_GRAPH_TARGET_PERIOD_MS -
|
||||
int64_t((now - mCurrentTimeStamp).ToMilliseconds());
|
||||
// Make sure timeoutMS doesn't overflow 32 bits by waking up at
|
||||
// least once a minute, if we need to wake up at all
|
||||
timeoutMS = std::max<int64_t>(0, std::min<int64_t>(timeoutMS, 60*1000));
|
||||
timeout = TimeDuration::FromMilliseconds(timeoutMS);
|
||||
LOG(LogLevel::Verbose,
|
||||
("%p: Waiting for next iteration; at %f, timeout=%f",
|
||||
GraphImpl(),
|
||||
(now - mInitialTimeStamp).ToSeconds(),
|
||||
timeoutMS / 1000.0));
|
||||
if (mWaitState == WAITSTATE_WAITING_INDEFINITELY) {
|
||||
timeout = WaitInterval();
|
||||
if (!another) {
|
||||
GraphImpl()->mGraphDriverAsleep = false; // atomic
|
||||
another = true;
|
||||
}
|
||||
mWaitState = WAITSTATE_WAITING_FOR_NEXT_ITERATION;
|
||||
}
|
||||
if (!timeout.IsZero()) {
|
||||
GraphImpl()->GetMonitor().Wait(timeout);
|
||||
CVStatus status = GraphImpl()->GetMonitor().Wait(timeout);
|
||||
LOG(LogLevel::Verbose,
|
||||
("%p: Resuming after timeout; at %f, elapsed=%f",
|
||||
("%p: Resuming after %s",
|
||||
GraphImpl(),
|
||||
(TimeStamp::Now() - mInitialTimeStamp).ToSeconds(),
|
||||
(TimeStamp::Now() - now).ToSeconds()));
|
||||
status == CVStatus::Timeout ? "timeout" : "wake-up"));
|
||||
}
|
||||
|
||||
if (mWaitState == WAITSTATE_WAITING_INDEFINITELY) {
|
||||
if (!another) {
|
||||
GraphImpl()->mGraphDriverAsleep = false; // atomic
|
||||
}
|
||||
// Note: this can race against the EnsureNextIteration setting
|
||||
// WAITSTATE_RUNNING and setting mGraphDriverAsleep to false, so you can
|
||||
// have an iteration with WAITSTATE_WAKING_UP instead of RUNNING.
|
||||
mWaitState = WAITSTATE_RUNNING;
|
||||
GraphImpl()->mNeedAnotherIteration = false; // atomic
|
||||
}
|
||||
|
||||
void SystemClockDriver::WakeUp()
|
||||
void
|
||||
ThreadedDriver::WakeUp()
|
||||
{
|
||||
GraphImpl()->GetMonitor().AssertCurrentThreadOwns();
|
||||
// Note: this can race against the thread setting WAITSTATE_RUNNING and
|
||||
// setting mGraphDriverAsleep to false, so you can have an iteration
|
||||
// with WAITSTATE_WAKING_UP instead of RUNNING.
|
||||
mWaitState = WAITSTATE_WAKING_UP;
|
||||
GraphImpl()->mGraphDriverAsleep = false; // atomic
|
||||
GraphImpl()->GetMonitor().Notify();
|
||||
}
|
||||
|
||||
TimeDuration
|
||||
SystemClockDriver::WaitInterval()
|
||||
{
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
int64_t timeoutMS = MEDIA_GRAPH_TARGET_PERIOD_MS -
|
||||
int64_t((now - mCurrentTimeStamp).ToMilliseconds());
|
||||
// Make sure timeoutMS doesn't overflow 32 bits by waking up at
|
||||
// least once a minute, if we need to wake up at all
|
||||
timeoutMS = std::max<int64_t>(0, std::min<int64_t>(timeoutMS, 60*1000));
|
||||
LOG(LogLevel::Verbose,
|
||||
("%p: Waiting for next iteration; at %f, timeout=%f",
|
||||
GraphImpl(),
|
||||
(now - mInitialTimeStamp).ToSeconds(),
|
||||
timeoutMS / 1000.0));
|
||||
|
||||
return TimeDuration::FromMilliseconds(timeoutMS);
|
||||
}
|
||||
|
||||
OfflineClockDriver::OfflineClockDriver(MediaStreamGraphImpl* aGraphImpl, GraphTime aSlice)
|
||||
: ThreadedDriver(aGraphImpl),
|
||||
mSlice(aSlice)
|
||||
|
@ -482,16 +479,11 @@ OfflineClockDriver::GetIntervalForIteration()
|
|||
return GraphImpl()->MillisecondsToMediaTime(mSlice);
|
||||
}
|
||||
|
||||
void
|
||||
OfflineClockDriver::WaitForNextIteration()
|
||||
TimeDuration
|
||||
OfflineClockDriver::WaitInterval()
|
||||
{
|
||||
// No op: we want to go as fast as possible when we are offline
|
||||
}
|
||||
|
||||
void
|
||||
OfflineClockDriver::WakeUp()
|
||||
{
|
||||
MOZ_ASSERT(false, "An offline graph should not have to wake up.");
|
||||
// We want to go as fast as possible when we are offline
|
||||
return 0;
|
||||
}
|
||||
|
||||
AsyncCubebTask::AsyncCubebTask(AudioCallbackDriver* aDriver,
|
||||
|
@ -850,13 +842,12 @@ AudioCallbackDriver::AddMixerCallback()
|
|||
void
|
||||
AudioCallbackDriver::WaitForNextIteration()
|
||||
{
|
||||
// Do not block.
|
||||
}
|
||||
|
||||
void
|
||||
AudioCallbackDriver::WakeUp()
|
||||
{
|
||||
mGraphImpl->GetMonitor().AssertCurrentThreadOwns();
|
||||
mGraphImpl->GetMonitor().Notify();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -116,8 +116,8 @@ public:
|
|||
explicit GraphDriver(MediaStreamGraphImpl* aGraphImpl);
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GraphDriver);
|
||||
/* For real-time graphs, this waits until it's time to process more data. For
|
||||
* offline graphs, this is a no-op. */
|
||||
/* For {System,Offline}ClockDriver, this waits until it's time to process
|
||||
* more data. For AudioCallbackDriver, this is a no-op. */
|
||||
virtual void WaitForNextIteration() = 0;
|
||||
/* Wakes up the graph if it is waiting. */
|
||||
virtual void WakeUp() = 0;
|
||||
|
@ -254,6 +254,8 @@ class ThreadedDriver : public GraphDriver
|
|||
public:
|
||||
explicit ThreadedDriver(MediaStreamGraphImpl* aGraphImpl);
|
||||
virtual ~ThreadedDriver();
|
||||
void WaitForNextIteration() override;
|
||||
void WakeUp() override;
|
||||
void Start() override;
|
||||
void Revive() override;
|
||||
void Shutdown() override;
|
||||
|
@ -276,7 +278,10 @@ public:
|
|||
{
|
||||
return mThreadRunning;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the TimeDuration to wait before the next rendering iteration.
|
||||
*/
|
||||
virtual TimeDuration WaitInterval() = 0;
|
||||
/* When the graph wakes up to do an iteration, implementations return the
|
||||
* range of time that will be processed. This is called only once per
|
||||
* iteration; it may determine the interval from state in a previous
|
||||
|
@ -299,9 +304,8 @@ class SystemClockDriver : public ThreadedDriver
|
|||
public:
|
||||
explicit SystemClockDriver(MediaStreamGraphImpl* aGraphImpl);
|
||||
virtual ~SystemClockDriver();
|
||||
TimeDuration WaitInterval() override;
|
||||
MediaTime GetIntervalForIteration() override;
|
||||
void WaitForNextIteration() override;
|
||||
void WakeUp() override;
|
||||
void MarkAsFallback();
|
||||
bool IsFallback();
|
||||
SystemClockDriver* AsSystemClockDriver() override {
|
||||
|
@ -314,22 +318,6 @@ private:
|
|||
TimeStamp mInitialTimeStamp;
|
||||
TimeStamp mLastTimeStamp;
|
||||
|
||||
// This enum specifies the wait state of the driver.
|
||||
enum WaitState {
|
||||
// RunThread() is running normally
|
||||
WAITSTATE_RUNNING,
|
||||
// RunThread() is paused waiting for its next iteration, which will
|
||||
// happen soon
|
||||
WAITSTATE_WAITING_FOR_NEXT_ITERATION,
|
||||
// RunThread() is paused indefinitely waiting for something to change
|
||||
WAITSTATE_WAITING_INDEFINITELY,
|
||||
// Something has signaled RunThread() to wake up immediately,
|
||||
// but it hasn't done so yet
|
||||
WAITSTATE_WAKING_UP
|
||||
};
|
||||
// This must be access with the monitor.
|
||||
WaitState mWaitState;
|
||||
|
||||
// This is true if this SystemClockDriver runs the graph because we could not
|
||||
// open an audio stream.
|
||||
bool mIsFallback;
|
||||
|
@ -344,9 +332,8 @@ class OfflineClockDriver : public ThreadedDriver
|
|||
public:
|
||||
OfflineClockDriver(MediaStreamGraphImpl* aGraphImpl, GraphTime aSlice);
|
||||
virtual ~OfflineClockDriver();
|
||||
TimeDuration WaitInterval() override;
|
||||
MediaTime GetIntervalForIteration() override;
|
||||
void WaitForNextIteration() override;
|
||||
void WakeUp() override;
|
||||
TimeStamp GetCurrentTimeStamp() override;
|
||||
OfflineClockDriver* AsOfflineClockDriver() override {
|
||||
return this;
|
||||
|
|
|
@ -1113,7 +1113,11 @@ MediaStreamGraphImpl::ShouldUpdateMainThread()
|
|||
}
|
||||
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
if ((now - mLastMainThreadUpdate).ToMilliseconds() > CurrentDriver()->IterationDuration()) {
|
||||
// For offline graphs, update now if there is no pending iteration or if it
|
||||
// has been long enough since the last update.
|
||||
if (!mNeedAnotherIteration ||
|
||||
((now - mLastMainThreadUpdate).ToMilliseconds() >
|
||||
CurrentDriver()->IterationDuration())) {
|
||||
mLastMainThreadUpdate = now;
|
||||
return true;
|
||||
}
|
||||
|
@ -1226,18 +1230,6 @@ MediaStreamGraphImpl::ProduceDataForStreamsBlockByBlock(uint32_t aStreamIndex,
|
|||
"Something went wrong with rounding to block boundaries");
|
||||
}
|
||||
|
||||
bool
|
||||
MediaStreamGraphImpl::AllFinishedStreamsNotified()
|
||||
{
|
||||
MOZ_ASSERT(OnGraphThread());
|
||||
for (MediaStream* stream : AllStreams()) {
|
||||
if (stream->mFinished && !stream->mNotifiedFinished) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MediaStreamGraphImpl::RunMessageAfterProcessing(UniquePtr<ControlMessage> aMessage)
|
||||
{
|
||||
|
@ -1344,14 +1336,16 @@ MediaStreamGraphImpl::UpdateGraph(GraphTime aEndBlockingDecisions)
|
|||
stream->mStartBlocking = mStateComputedTime;
|
||||
}
|
||||
|
||||
// The loop is woken up so soon that IterationEnd() barely advances and we
|
||||
// end up having aEndBlockingDecision == mStateComputedTime.
|
||||
// Since stream blocking is computed in the interval of
|
||||
// [mStateComputedTime, aEndBlockingDecision), it won't be computed at all.
|
||||
// We should ensure next iteration so that pending blocking changes will be
|
||||
// computed in next loop.
|
||||
// If the loop is woken up so soon that IterationEnd() barely advances or
|
||||
// if an offline graph is not currently rendering, we end up having
|
||||
// aEndBlockingDecisions == mStateComputedTime.
|
||||
// Since the process interval [mStateComputedTime, aEndBlockingDecision) is
|
||||
// empty, Process() will not find any unblocked stream and so will not
|
||||
// ensure another iteration. If the graph should be rendering, then ensure
|
||||
// another iteration to render.
|
||||
if (ensureNextIteration ||
|
||||
aEndBlockingDecisions == mStateComputedTime) {
|
||||
(aEndBlockingDecisions == mStateComputedTime &&
|
||||
mStateComputedTime < mEndTime)) {
|
||||
EnsureNextIteration();
|
||||
}
|
||||
}
|
||||
|
@ -1445,7 +1439,6 @@ MediaStreamGraphImpl::UpdateMainThreadState()
|
|||
MOZ_ASSERT(OnGraphThread());
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
bool finalUpdate = mForceShutDown ||
|
||||
(mProcessedTime >= mEndTime && AllFinishedStreamsNotified()) ||
|
||||
(IsEmpty() && mBackMessageQueue.IsEmpty());
|
||||
PrepareUpdatesToMainThreadState(finalUpdate);
|
||||
if (finalUpdate) {
|
||||
|
@ -3641,21 +3634,6 @@ ProcessedMediaStream::AllocateInputPort(MediaStream* aStream, TrackID aTrackID,
|
|||
return port.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ProcessedMediaStream::QueueFinish()
|
||||
{
|
||||
class Message : public ControlMessage {
|
||||
public:
|
||||
explicit Message(ProcessedMediaStream* aStream)
|
||||
: ControlMessage(aStream) {}
|
||||
void Run() override
|
||||
{
|
||||
mStream->FinishOnGraphThread();
|
||||
}
|
||||
};
|
||||
GraphImpl()->AppendMessage(MakeUnique<Message>(this));
|
||||
}
|
||||
|
||||
void
|
||||
ProcessedMediaStream::QueueSetAutofinish(bool aAutofinish)
|
||||
{
|
||||
|
|
|
@ -471,10 +471,6 @@ public:
|
|||
{
|
||||
mConsumers.RemoveElement(aPort);
|
||||
}
|
||||
uint32_t ConsumerCount() const
|
||||
{
|
||||
return mConsumers.Length();
|
||||
}
|
||||
StreamTracks& GetStreamTracks() { return mTracks; }
|
||||
GraphTime GetStreamTracksStartTime() const { return mTracksStartTime; }
|
||||
|
||||
|
@ -1190,10 +1186,6 @@ public:
|
|||
uint16_t aInputNumber = 0,
|
||||
uint16_t aOutputNumber = 0,
|
||||
nsTArray<TrackID>* aBlockedTracks = nullptr);
|
||||
/**
|
||||
* Queue a message to force this stream into the finished state.
|
||||
*/
|
||||
void QueueFinish();
|
||||
/**
|
||||
* Queue a message to set the autofinish flag on this stream (defaults to
|
||||
* false). When this flag is set, and all input streams are in the finished
|
||||
|
|
|
@ -203,11 +203,6 @@ public:
|
|||
*/
|
||||
void SignalMainThreadCleanup();
|
||||
|
||||
bool Running() const
|
||||
{
|
||||
return LifecycleStateRef() == LIFECYCLE_RUNNING;
|
||||
}
|
||||
|
||||
/* This is the end of the current iteration, that is, the current time of the
|
||||
* graph. */
|
||||
GraphTime IterationEnd() const;
|
||||
|
@ -223,11 +218,6 @@ public:
|
|||
* mMonitor must be held.
|
||||
*/
|
||||
void PrepareUpdatesToMainThreadState(bool aFinalUpdate);
|
||||
/**
|
||||
* Returns false if there is any stream that has finished but not yet finished
|
||||
* playing out.
|
||||
*/
|
||||
bool AllFinishedStreamsNotified();
|
||||
/**
|
||||
* If we are rendering in non-realtime mode, we don't want to send messages to
|
||||
* the main thread at each iteration for performance reasons. We instead
|
||||
|
|
|
@ -1276,7 +1276,7 @@ impl DisplayListBuilder {
|
|||
clip_node_id: Option<ClipId>,
|
||||
transform_style: TransformStyle,
|
||||
mix_blend_mode: MixBlendMode,
|
||||
filters: Vec<FilterOp>,
|
||||
filters: &[FilterOp],
|
||||
raster_space: RasterSpace,
|
||||
) {
|
||||
let item = SpecificDisplayItem::PushStackingContext(PushStackingContextDisplayItem {
|
||||
|
@ -1289,7 +1289,7 @@ impl DisplayListBuilder {
|
|||
});
|
||||
|
||||
self.push_item(item, info);
|
||||
self.push_iter(&filters);
|
||||
self.push_iter(filters);
|
||||
}
|
||||
|
||||
pub fn pop_stacking_context(&mut self) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
f3d6f138c9d15f498384f13aeaa5f5dd6ee76dd6
|
||||
a2997bc78ce6e161fd379e04e2e4479525d12782
|
||||
|
|
|
@ -1903,7 +1903,7 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
|
|||
clip_node_id,
|
||||
transform_style,
|
||||
mix_blend_mode,
|
||||
filters,
|
||||
&filters,
|
||||
glyph_raster_space);
|
||||
}
|
||||
|
||||
|
|
|
@ -1654,7 +1654,7 @@ impl YamlFrameReader {
|
|||
clip_node_id,
|
||||
transform_style,
|
||||
mix_blend_mode,
|
||||
filters,
|
||||
&filters,
|
||||
raster_space,
|
||||
);
|
||||
|
||||
|
|
|
@ -322,9 +322,7 @@ EvalKernel(JSContext* cx, HandleValue v, EvalType evalType, AbstractFramePtr cal
|
|||
? SourceBufferHolder::GiveOwnership
|
||||
: SourceBufferHolder::NoOwnership;
|
||||
SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
|
||||
JSScript* compiled = frontend::CompileEvalScript(cx, cx->tempLifoAlloc(),
|
||||
env, enclosing,
|
||||
options, srcBuf);
|
||||
JSScript* compiled = frontend::CompileEvalScript(cx, env, enclosing, options, srcBuf);
|
||||
if (!compiled) {
|
||||
return false;
|
||||
}
|
||||
|
@ -408,9 +406,7 @@ js::DirectEvalStringFromIon(JSContext* cx,
|
|||
? SourceBufferHolder::GiveOwnership
|
||||
: SourceBufferHolder::NoOwnership;
|
||||
SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
|
||||
JSScript* compiled = frontend::CompileEvalScript(cx, cx->tempLifoAlloc(),
|
||||
env, enclosing,
|
||||
options, srcBuf);
|
||||
JSScript* compiled = frontend::CompileEvalScript(cx, env, enclosing, options, srcBuf);
|
||||
if (!compiled) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -185,9 +185,10 @@ js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, Handle<RegExpObject*>
|
|||
static bool
|
||||
CheckPatternSyntaxSlow(JSContext* cx, HandleAtom pattern, RegExpFlag flags)
|
||||
{
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
CompileOptions options(cx);
|
||||
frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
|
||||
return irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), pattern,
|
||||
return irregexp::ParsePatternSyntax(dummyTokenStream, allocScope.alloc(), pattern,
|
||||
flags & UnicodeFlag);
|
||||
}
|
||||
|
||||
|
|
|
@ -4703,7 +4703,7 @@ AssertionTypeToString(irregexp::RegExpAssertion::AssertionType type)
|
|||
}
|
||||
|
||||
static JSObject*
|
||||
ConvertRegExpTreeToObject(JSContext* cx, irregexp::RegExpTree* tree)
|
||||
ConvertRegExpTreeToObject(JSContext* cx, LifoAlloc& alloc, irregexp::RegExpTree* tree)
|
||||
{
|
||||
RootedObject obj(cx, JS_NewPlainObject(cx));
|
||||
if (!obj) {
|
||||
|
@ -4750,18 +4750,18 @@ ConvertRegExpTreeToObject(JSContext* cx, irregexp::RegExpTree* tree)
|
|||
return JS_SetProperty(cx, obj, name, val);
|
||||
};
|
||||
|
||||
auto TreeProp = [&ObjectProp](JSContext* cx, HandleObject obj,
|
||||
const char* name, irregexp::RegExpTree* tree) {
|
||||
RootedObject treeObj(cx, ConvertRegExpTreeToObject(cx, tree));
|
||||
auto TreeProp = [&ObjectProp, &alloc](JSContext* cx, HandleObject obj,
|
||||
const char* name, irregexp::RegExpTree* tree) {
|
||||
RootedObject treeObj(cx, ConvertRegExpTreeToObject(cx, alloc, tree));
|
||||
if (!treeObj) {
|
||||
return false;
|
||||
}
|
||||
return ObjectProp(cx, obj, name, treeObj);
|
||||
};
|
||||
|
||||
auto TreeVectorProp = [&ObjectProp](JSContext* cx, HandleObject obj,
|
||||
const char* name,
|
||||
const irregexp::RegExpTreeVector& nodes) {
|
||||
auto TreeVectorProp = [&ObjectProp, &alloc](JSContext* cx, HandleObject obj,
|
||||
const char* name,
|
||||
const irregexp::RegExpTreeVector& nodes) {
|
||||
size_t len = nodes.length();
|
||||
RootedObject array(cx, JS_NewArrayObject(cx, len));
|
||||
if (!array) {
|
||||
|
@ -4769,7 +4769,7 @@ ConvertRegExpTreeToObject(JSContext* cx, irregexp::RegExpTree* tree)
|
|||
}
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
RootedObject child(cx, ConvertRegExpTreeToObject(cx, nodes[i]));
|
||||
RootedObject child(cx, ConvertRegExpTreeToObject(cx, alloc, nodes[i]));
|
||||
if (!child) {
|
||||
return false;
|
||||
}
|
||||
|
@ -4823,8 +4823,8 @@ ConvertRegExpTreeToObject(JSContext* cx, irregexp::RegExpTree* tree)
|
|||
return ObjectProp(cx, obj, name, array);
|
||||
};
|
||||
|
||||
auto ElemProp = [&ObjectProp](JSContext* cx, HandleObject obj,
|
||||
const char* name, const irregexp::TextElementVector& elements) {
|
||||
auto ElemProp = [&ObjectProp, &alloc](JSContext* cx, HandleObject obj, const char* name,
|
||||
const irregexp::TextElementVector& elements) {
|
||||
size_t len = elements.length();
|
||||
RootedObject array(cx, JS_NewArrayObject(cx, len));
|
||||
if (!array) {
|
||||
|
@ -4833,7 +4833,7 @@ ConvertRegExpTreeToObject(JSContext* cx, irregexp::RegExpTree* tree)
|
|||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
const irregexp::TextElement& element = elements[i];
|
||||
RootedObject elemTree(cx, ConvertRegExpTreeToObject(cx, element.tree()));
|
||||
RootedObject elemTree(cx, ConvertRegExpTreeToObject(cx, alloc, element.tree()));
|
||||
if (!elemTree) {
|
||||
return false;
|
||||
}
|
||||
|
@ -4884,8 +4884,7 @@ ConvertRegExpTreeToObject(JSContext* cx, irregexp::RegExpTree* tree)
|
|||
if (!BooleanProp(cx, obj, "is_negated", t->is_negated())) {
|
||||
return nullptr;
|
||||
}
|
||||
LifoAlloc* alloc = &cx->tempLifoAlloc();
|
||||
if (!CharRangesProp(cx, obj, "ranges", t->ranges(alloc))) {
|
||||
if (!CharRangesProp(cx, obj, "ranges", t->ranges(&alloc))) {
|
||||
return nullptr;
|
||||
}
|
||||
return obj;
|
||||
|
@ -5022,8 +5021,10 @@ ParseRegExp(JSContext* cx, unsigned argc, Value* vp)
|
|||
CompileOptions options(cx);
|
||||
frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
|
||||
|
||||
// Data lifetime is controlled by LifoAllocScope.
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
irregexp::RegExpCompileData data;
|
||||
if (!irregexp::ParsePattern(dummyTokenStream, cx->tempLifoAlloc(), pattern,
|
||||
if (!irregexp::ParsePattern(dummyTokenStream, allocScope.alloc(), pattern,
|
||||
flags & MultilineFlag, match_only,
|
||||
flags & UnicodeFlag, flags & IgnoreCaseFlag,
|
||||
flags & GlobalFlag, flags & StickyFlag,
|
||||
|
@ -5032,7 +5033,7 @@ ParseRegExp(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
RootedObject obj(cx, ConvertRegExpTreeToObject(cx, data.tree));
|
||||
RootedObject obj(cx, ConvertRegExpTreeToObject(cx, allocScope.alloc(), data.tree));
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -4357,7 +4357,6 @@ BinASTParser<Tok>::parseInterfaceLiteralRegExpExpression(const size_t start, con
|
|||
BINJS_TRY_VAR(reobj, RegExpObject::create(cx_,
|
||||
pattern,
|
||||
reflags,
|
||||
alloc_,
|
||||
TenuredObject));
|
||||
|
||||
BINJS_TRY_DECL(result, factory_.newRegExp(reobj, tokenizer_->pos(start), *this));
|
||||
|
|
|
@ -1081,7 +1081,6 @@ LiteralRegExpExpression:
|
|||
BINJS_TRY_VAR(reobj, RegExpObject::create(cx_,
|
||||
pattern,
|
||||
reflags,
|
||||
alloc_,
|
||||
TenuredObject));
|
||||
|
||||
BINJS_TRY_DECL(result, factory_.newRegExp(reobj, tokenizer_->pos(start), *this));
|
||||
|
|
|
@ -45,7 +45,6 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
public:
|
||||
// Construct an object passing mandatory arguments.
|
||||
BytecodeCompiler(JSContext* cx,
|
||||
LifoAlloc& alloc,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& sourceBuffer,
|
||||
HandleScope enclosingScope);
|
||||
|
@ -83,7 +82,6 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
AutoKeepAtoms keepAtoms;
|
||||
|
||||
JSContext* cx;
|
||||
LifoAlloc& alloc;
|
||||
const ReadOnlyCompileOptions& options;
|
||||
SourceBufferHolder& sourceBuffer;
|
||||
|
||||
|
@ -154,13 +152,11 @@ AutoFrontendTraceLog::AutoFrontendTraceLog(JSContext* cx, const TraceLoggerTextI
|
|||
#endif
|
||||
|
||||
BytecodeCompiler::BytecodeCompiler(JSContext* cx,
|
||||
LifoAlloc& alloc,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& sourceBuffer,
|
||||
HandleScope enclosingScope)
|
||||
: keepAtoms(cx),
|
||||
cx(cx),
|
||||
alloc(alloc),
|
||||
options(options),
|
||||
sourceBuffer(sourceBuffer),
|
||||
enclosingScope(cx, enclosingScope),
|
||||
|
@ -233,15 +229,15 @@ BytecodeCompiler::createParser(ParseGoal goal)
|
|||
usedNames.emplace(cx);
|
||||
|
||||
if (canLazilyParse()) {
|
||||
syntaxParser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(),
|
||||
/* foldConstants = */ false, *usedNames, nullptr, nullptr,
|
||||
sourceObject, goal);
|
||||
syntaxParser.emplace(cx, cx->tempLifoAlloc(), options, sourceBuffer.get(),
|
||||
sourceBuffer.length(), /* foldConstants = */ false,
|
||||
*usedNames, nullptr, nullptr, sourceObject, goal);
|
||||
if (!syntaxParser->checkOptions()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
parser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(),
|
||||
parser.emplace(cx, cx->tempLifoAlloc(), options, sourceBuffer.get(), sourceBuffer.length(),
|
||||
/* foldConstants = */ true, *usedNames, syntaxParser.ptrOr(nullptr), nullptr,
|
||||
sourceObject, goal);
|
||||
parser->ss = scriptSource;
|
||||
|
@ -643,14 +639,14 @@ class MOZ_RAII AutoAssertReportedException
|
|||
};
|
||||
|
||||
JSScript*
|
||||
frontend::CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKind,
|
||||
frontend::CompileGlobalScript(JSContext* cx, ScopeKind scopeKind,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
ScriptSourceObject** sourceObjectOut)
|
||||
{
|
||||
MOZ_ASSERT(scopeKind == ScopeKind::Global || scopeKind == ScopeKind::NonSyntactic);
|
||||
AutoAssertReportedException assertException(cx);
|
||||
BytecodeCompiler compiler(cx, alloc, options, srcBuf, /* enclosingScope = */ nullptr);
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, /* enclosingScope = */ nullptr);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
JSScript* script = compiler.compileGlobalScript(scopeKind);
|
||||
if (!script) {
|
||||
|
@ -724,14 +720,14 @@ frontend::CompileGlobalBinASTScript(JSContext* cx, LifoAlloc& alloc, const ReadO
|
|||
#endif // JS_BUILD_BINAST
|
||||
|
||||
JSScript*
|
||||
frontend::CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
|
||||
HandleObject environment, HandleScope enclosingScope,
|
||||
frontend::CompileEvalScript(JSContext* cx, HandleObject environment,
|
||||
HandleScope enclosingScope,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
ScriptSourceObject** sourceObjectOut)
|
||||
{
|
||||
AutoAssertReportedException assertException(cx);
|
||||
BytecodeCompiler compiler(cx, alloc, options, srcBuf, enclosingScope);
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, enclosingScope);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
JSScript* script = compiler.compileEvalScript(environment, enclosingScope);
|
||||
if (!script) {
|
||||
|
@ -744,7 +740,7 @@ frontend::CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
|
|||
|
||||
ModuleObject*
|
||||
frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& optionsInput,
|
||||
SourceBufferHolder& srcBuf, LifoAlloc& alloc,
|
||||
SourceBufferHolder& srcBuf,
|
||||
ScriptSourceObject** sourceObjectOut)
|
||||
{
|
||||
MOZ_ASSERT(srcBuf.get());
|
||||
|
@ -758,7 +754,7 @@ frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& optionsInpu
|
|||
options.allowHTMLComments = false;
|
||||
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
BytecodeCompiler compiler(cx, alloc, options, srcBuf, emptyGlobalScope);
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, emptyGlobalScope);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
ModuleObject* module = compiler.compileModule();
|
||||
if (!module) {
|
||||
|
@ -779,8 +775,7 @@ frontend::CompileModule(JSContext* cx, const JS::ReadOnlyCompileOptions& options
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
LifoAlloc& alloc = cx->tempLifoAlloc();
|
||||
RootedModuleObject module(cx, CompileModule(cx, options, srcBuf, alloc));
|
||||
RootedModuleObject module(cx, CompileModule(cx, options, srcBuf, nullptr));
|
||||
if (!module) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1011,7 +1006,7 @@ frontend::CompileStandaloneFunction(JSContext* cx, MutableHandleFunction fun,
|
|||
scope = &cx->global()->emptyGlobalScope();
|
||||
}
|
||||
|
||||
BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, scope);
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, scope);
|
||||
if (!compiler.compileStandaloneFunction(fun, GeneratorKind::NotGenerator,
|
||||
FunctionAsyncKind::SyncFunction,
|
||||
parameterListEnd))
|
||||
|
@ -1033,7 +1028,7 @@ frontend::CompileStandaloneGenerator(JSContext* cx, MutableHandleFunction fun,
|
|||
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
|
||||
BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope);
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, emptyGlobalScope);
|
||||
if (!compiler.compileStandaloneFunction(fun, GeneratorKind::Generator,
|
||||
FunctionAsyncKind::SyncFunction,
|
||||
parameterListEnd))
|
||||
|
@ -1055,7 +1050,7 @@ frontend::CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fu
|
|||
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
|
||||
BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope);
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, emptyGlobalScope);
|
||||
if (!compiler.compileStandaloneFunction(fun, GeneratorKind::NotGenerator,
|
||||
FunctionAsyncKind::AsyncFunction,
|
||||
parameterListEnd))
|
||||
|
@ -1077,7 +1072,7 @@ frontend::CompileStandaloneAsyncGenerator(JSContext* cx, MutableHandleFunction f
|
|||
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
|
||||
BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope);
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, emptyGlobalScope);
|
||||
if (!compiler.compileStandaloneFunction(fun, GeneratorKind::Generator,
|
||||
FunctionAsyncKind::AsyncFunction,
|
||||
parameterListEnd))
|
||||
|
|
|
@ -20,7 +20,6 @@ class JSLinearString;
|
|||
namespace js {
|
||||
|
||||
class LazyScript;
|
||||
class LifoAlloc;
|
||||
class ModuleObject;
|
||||
class ScriptSourceObject;
|
||||
|
||||
|
@ -31,7 +30,7 @@ class FunctionBox;
|
|||
class ParseNode;
|
||||
|
||||
JSScript*
|
||||
CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKind,
|
||||
CompileGlobalScript(JSContext* cx, ScopeKind scopeKind,
|
||||
const JS::ReadOnlyCompileOptions& options,
|
||||
JS::SourceBufferHolder& srcBuf,
|
||||
ScriptSourceObject** sourceObjectOut = nullptr);
|
||||
|
@ -50,8 +49,8 @@ CompileLazyBinASTFunction(JSContext* cx, Handle<LazyScript*> lazy, const uint8_t
|
|||
#endif // JS_BUILD_BINAST
|
||||
|
||||
JSScript*
|
||||
CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
|
||||
HandleObject scopeChain, HandleScope enclosingScope,
|
||||
CompileEvalScript(JSContext* cx, HandleObject environment,
|
||||
HandleScope enclosingScope,
|
||||
const JS::ReadOnlyCompileOptions& options,
|
||||
JS::SourceBufferHolder& srcBuf,
|
||||
ScriptSourceObject** sourceObjectOut = nullptr);
|
||||
|
@ -62,8 +61,8 @@ CompileModule(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
|
|||
|
||||
ModuleObject*
|
||||
CompileModule(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
|
||||
JS::SourceBufferHolder& srcBuf, LifoAlloc& alloc,
|
||||
ScriptSourceObject** sourceObjectOut = nullptr);
|
||||
JS::SourceBufferHolder& srcBuf,
|
||||
ScriptSourceObject** sourceObjectOut);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const char16_t* chars, size_t length);
|
||||
|
|
|
@ -10032,8 +10032,7 @@ Parser<FullParseHandler, Unit>::newRegExp()
|
|||
RegExpFlag flags = anyChars.currentToken().regExpFlags();
|
||||
|
||||
Rooted<RegExpObject*> reobj(context);
|
||||
reobj = RegExpObject::create(context, chars.begin(), chars.length(), flags, anyChars, alloc,
|
||||
TenuredObject);
|
||||
reobj = RegExpObject::create(context, chars.begin(), chars.length(), flags, anyChars, TenuredObject);
|
||||
if (!reobj) {
|
||||
return null();
|
||||
}
|
||||
|
@ -10052,8 +10051,13 @@ Parser<SyntaxParseHandler, Unit>::newRegExp()
|
|||
RegExpFlag flags = anyChars.currentToken().regExpFlags();
|
||||
|
||||
mozilla::Range<const char16_t> source(chars.begin(), chars.length());
|
||||
if (!js::irregexp::ParsePatternSyntax(anyChars, alloc, source, flags & UnicodeFlag)) {
|
||||
return null();
|
||||
{
|
||||
LifoAllocScope scopeAlloc(&alloc);
|
||||
if (!js::irregexp::ParsePatternSyntax(anyChars, scopeAlloc.alloc(),
|
||||
source, flags & UnicodeFlag))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
||||
return handler.newRegExp(SyntaxParseHandler::NodeGeneric, pos(), *this);
|
||||
|
|
|
@ -1735,17 +1735,16 @@ IsNativeRegExpEnabled(JSContext* cx)
|
|||
}
|
||||
|
||||
RegExpCode
|
||||
irregexp::CompilePattern(JSContext* cx, HandleRegExpShared shared, RegExpCompileData* data,
|
||||
HandleLinearString sample, bool is_global, bool ignore_case,
|
||||
bool is_latin1, bool match_only, bool force_bytecode, bool sticky,
|
||||
bool unicode, RegExpShared::JitCodeTables& tables)
|
||||
irregexp::CompilePattern(JSContext* cx, LifoAlloc& alloc, HandleRegExpShared shared,
|
||||
RegExpCompileData* data, HandleLinearString sample, bool is_global,
|
||||
bool ignore_case, bool is_latin1, bool match_only, bool force_bytecode,
|
||||
bool sticky, bool unicode, RegExpShared::JitCodeTables& tables)
|
||||
{
|
||||
if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) {
|
||||
JS_ReportErrorASCII(cx, "regexp too big");
|
||||
return RegExpCode();
|
||||
}
|
||||
|
||||
LifoAlloc& alloc = cx->tempLifoAlloc();
|
||||
RegExpCompiler compiler(cx, &alloc, data->capture_count, ignore_case, is_latin1, match_only,
|
||||
unicode);
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ struct RegExpCode
|
|||
};
|
||||
|
||||
RegExpCode
|
||||
CompilePattern(JSContext* cx, HandleRegExpShared shared, RegExpCompileData* data,
|
||||
CompilePattern(JSContext* cx, LifoAlloc& alloc, HandleRegExpShared shared, RegExpCompileData* data,
|
||||
HandleLinearString sample, bool is_global, bool ignore_case,
|
||||
bool is_latin1, bool match_only, bool force_bytecode, bool sticky,
|
||||
bool unicode, RegExpShared::JitCodeTables& tables);
|
||||
|
|
|
@ -1958,8 +1958,6 @@ static bool
|
|||
ParsePatternSyntax(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc,
|
||||
const CharT* chars, size_t length, bool unicode)
|
||||
{
|
||||
LifoAllocScope scope(&alloc);
|
||||
|
||||
RegExpParser<CharT> parser(ts, &alloc, chars, chars + length, false, unicode, false);
|
||||
return parser.ParsePattern() != nullptr;
|
||||
}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
// Based on work by André Bargull
|
||||
|
||||
function f() {
|
||||
var x = [1,2,3];
|
||||
x[3] = 0xff;
|
||||
|
||||
// Should have been defined on typed array.
|
||||
assertEq(x.length, 3);
|
||||
assertEq(x[3], -1);
|
||||
|
||||
x[3] = 0;
|
||||
}
|
||||
|
||||
Object.setPrototypeOf(Array.prototype, new Int8Array(4));
|
||||
f();
|
||||
f();
|
||||
|
||||
function g() {
|
||||
var x = [1,2,3,4];
|
||||
x[4] = 0xff;
|
||||
|
||||
// OOB [[Set]] should have been ignored
|
||||
assertEq(x.length, 4);
|
||||
assertEq(x[4], undefined);
|
||||
}
|
||||
|
||||
Object.setPrototypeOf(Array.prototype, new Int8Array(4));
|
||||
g();
|
||||
g();
|
|
@ -21,3 +21,4 @@ function test(arr) {
|
|||
}
|
||||
|
||||
test([123]);
|
||||
test(new Int32Array([123]));
|
||||
|
|
|
@ -4016,11 +4016,6 @@ CanAttachAddElement(NativeObject* obj, bool isInit)
|
|||
return false;
|
||||
}
|
||||
|
||||
// TypedArrayObjects [[Set]] has special behavior.
|
||||
if (proto->is<TypedArrayObject>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We have to make sure the proto has no non-writable (frozen) elements
|
||||
// because we're not allowed to shadow them. There are a few cases to
|
||||
// consider:
|
||||
|
|
|
@ -6005,8 +6005,7 @@ JS_NewRegExpObject(JSContext* cx, const char* bytes, size_t length, unsigned fla
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return RegExpObject::create(cx, chars.get(), length, RegExpFlag(flags), cx->tempLifoAlloc(),
|
||||
GenericObject);
|
||||
return RegExpObject::create(cx, chars.get(), length, RegExpFlag(flags), GenericObject);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject*)
|
||||
|
@ -6015,8 +6014,7 @@ JS_NewUCRegExpObject(JSContext* cx, const char16_t* chars, size_t length, unsign
|
|||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
return RegExpObject::create(cx, chars, length, RegExpFlag(flags), cx->tempLifoAlloc(),
|
||||
GenericObject);
|
||||
return RegExpObject::create(cx, chars, length, RegExpFlag(flags), GenericObject);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
|
|
@ -881,7 +881,8 @@ FormatFrame(JSContext* cx, const FrameIter& iter, Sprinter& sp, int num,
|
|||
JSAutoRealm ar(cx, envChain);
|
||||
|
||||
const char* filename = script->filename();
|
||||
unsigned lineno = PCToLineNumber(script, pc);
|
||||
unsigned column = 0;
|
||||
unsigned lineno = PCToLineNumber(script, pc, &column);
|
||||
RootedFunction fun(cx, iter.maybeCallee(cx));
|
||||
RootedString funname(cx);
|
||||
if (fun) {
|
||||
|
@ -990,11 +991,12 @@ FormatFrame(JSContext* cx, const FrameIter& iter, Sprinter& sp, int num,
|
|||
}
|
||||
}
|
||||
|
||||
// print filename and line number
|
||||
if (!sp.printf("%s [\"%s\":%d]\n",
|
||||
// print filename, line number and column
|
||||
if (!sp.printf("%s [\"%s\":%d:%d]\n",
|
||||
fun ? ")" : "",
|
||||
filename ? filename : "<unknown>",
|
||||
lineno))
|
||||
lineno,
|
||||
column))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import os
|
|||
import posixpath
|
||||
import sys
|
||||
import traceback
|
||||
import subprocess
|
||||
from collections import namedtuple
|
||||
from datetime import datetime
|
||||
|
||||
|
@ -21,7 +20,7 @@ else:
|
|||
from tasks_win import run_all_tests
|
||||
|
||||
from progressbar import ProgressBar, NullProgressBar
|
||||
from results import TestOutput
|
||||
from results import TestOutput, escape_cmdline
|
||||
from structuredlog import TestLogger
|
||||
|
||||
TESTS_LIB_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
@ -429,7 +428,7 @@ def run_test_remote(test, device, prefix, options):
|
|||
posixpath.join(options.remote_test_root, 'modules/'),
|
||||
posixpath.join(options.remote_test_root, 'tests'))
|
||||
if options.show_cmd:
|
||||
print(subprocess.list2cmdline(cmd))
|
||||
print(escape_cmdline(cmd))
|
||||
|
||||
env = {}
|
||||
if test.tz_pacific:
|
||||
|
@ -615,7 +614,7 @@ def print_test_summary(num_tests, failures, complete, doing, options):
|
|||
|
||||
def show_test(res):
|
||||
if options.show_failed:
|
||||
print(' ' + subprocess.list2cmdline(res.cmd))
|
||||
print(' ' + escape_cmdline(res.cmd))
|
||||
else:
|
||||
print(' ' + ' '.join(res.test.jitflags + [res.test.relpath_tests]))
|
||||
|
||||
|
|
|
@ -1,21 +1,15 @@
|
|||
for (var constructor of anyTypedArrayConstructors) {
|
||||
var receiver = new Proxy({}, {
|
||||
getOwnPropertyDescriptor(p) {
|
||||
throw "fail";
|
||||
},
|
||||
|
||||
defineProperty() {
|
||||
throw "fail";
|
||||
}
|
||||
});
|
||||
var receiver = {};
|
||||
|
||||
var ta = new constructor(1);
|
||||
assertEq(Reflect.set(ta, 0, 47, receiver), true);
|
||||
assertEq(ta[0], 47);
|
||||
assertEq(ta[0], 0);
|
||||
assertEq(receiver[0], 47);
|
||||
|
||||
// Out-of-bounds
|
||||
assertEq(Reflect.set(ta, 10, 47, receiver), false);
|
||||
assertEq(Reflect.set(ta, 10, 47, receiver), true);
|
||||
assertEq(ta[10], undefined);
|
||||
assertEq(receiver[10], 47);
|
||||
|
||||
// Detached
|
||||
if (typeof detachArrayBuffer === "function" &&
|
||||
|
@ -24,8 +18,9 @@ for (var constructor of anyTypedArrayConstructors) {
|
|||
detachArrayBuffer(ta.buffer)
|
||||
|
||||
assertEq(ta[0], undefined);
|
||||
assertEq(Reflect.set(ta, 0, 47, receiver), false);
|
||||
assertEq(Reflect.set(ta, 0, 42, receiver), true);
|
||||
assertEq(ta[0], undefined);
|
||||
assertEq(receiver[0], 42);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -441,7 +441,7 @@ class BytecodeParser
|
|||
};
|
||||
|
||||
JSContext* cx_;
|
||||
LifoAllocScope allocScope_;
|
||||
LifoAlloc& alloc_;
|
||||
RootedScript script_;
|
||||
|
||||
Bytecode** codeArray_;
|
||||
|
@ -454,9 +454,9 @@ class BytecodeParser
|
|||
#endif
|
||||
|
||||
public:
|
||||
BytecodeParser(JSContext* cx, JSScript* script)
|
||||
BytecodeParser(JSContext* cx, LifoAlloc& alloc, JSScript* script)
|
||||
: cx_(cx),
|
||||
allocScope_(&cx->tempLifoAlloc()),
|
||||
alloc_(alloc),
|
||||
script_(cx, script),
|
||||
codeArray_(nullptr)
|
||||
#ifdef DEBUG
|
||||
|
@ -540,11 +540,10 @@ class BytecodeParser
|
|||
|
||||
private:
|
||||
LifoAlloc& alloc() {
|
||||
return allocScope_.alloc();
|
||||
return alloc_;
|
||||
}
|
||||
|
||||
void reportOOM() {
|
||||
allocScope_.releaseEarly();
|
||||
ReportOutOfMemory(cx_);
|
||||
}
|
||||
|
||||
|
@ -1003,7 +1002,8 @@ BytecodeParser::parse()
|
|||
bool
|
||||
js::ReconstructStackDepth(JSContext* cx, JSScript* script, jsbytecode* pc, uint32_t* depth, bool* reachablePC)
|
||||
{
|
||||
BytecodeParser parser(cx, script);
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
BytecodeParser parser(cx, allocScope.alloc(), script);
|
||||
if (!parser.parse()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1030,8 +1030,9 @@ static MOZ_MUST_USE bool
|
|||
DisassembleAtPC(JSContext* cx, JSScript* scriptArg, bool lines,
|
||||
jsbytecode* pc, bool showAll, Sprinter* sp)
|
||||
{
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
RootedScript script(cx, scriptArg);
|
||||
BytecodeParser parser(cx, script);
|
||||
BytecodeParser parser(cx, allocScope.alloc(), script);
|
||||
parser.setStackDump();
|
||||
if (!parser.parse()) {
|
||||
return false;
|
||||
|
@ -2262,7 +2263,8 @@ static bool
|
|||
DecompileAtPCForStackDump(JSContext* cx, HandleScript script,
|
||||
const OffsetAndDefIndex& offsetAndDefIndex, Sprinter* sp)
|
||||
{
|
||||
BytecodeParser parser(cx, script);
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
BytecodeParser parser(cx, allocScope.alloc(), script);
|
||||
parser.setStackDump();
|
||||
if (!parser.parse()) {
|
||||
return false;
|
||||
|
@ -2385,7 +2387,8 @@ DecompileExpressionFromStack(JSContext* cx, int spindex, int skipStackHits, Hand
|
|||
return true;
|
||||
}
|
||||
|
||||
BytecodeParser parser(cx, frameIter.script());
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
BytecodeParser parser(cx, allocScope.alloc(), frameIter.script());
|
||||
if (!parser.parse()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2489,7 +2492,8 @@ DecompileArgumentFromStack(JSContext* cx, int formalIndex, UniqueChars* res)
|
|||
return true;
|
||||
}
|
||||
|
||||
BytecodeParser parser(cx, script);
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
BytecodeParser parser(cx, allocScope.alloc(), script);
|
||||
if (!parser.parse()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2749,7 +2753,8 @@ GetPCCountJSON(JSContext* cx, const ScriptAndCounts& sac, Sprinter& sp)
|
|||
|
||||
RootedScript script(cx, sac.script);
|
||||
|
||||
BytecodeParser parser(cx, script);
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
BytecodeParser parser(cx, allocScope.alloc(), script);
|
||||
if (!parser.parse()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ CompileSourceBuffer(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
script.set(frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(), scopeKind, options, srcBuf));
|
||||
script.set(frontend::CompileGlobalScript(cx, scopeKind, options, srcBuf));
|
||||
return !!script;
|
||||
}
|
||||
|
||||
|
@ -491,8 +491,7 @@ Evaluate(JSContext* cx, ScopeKind scopeKind, HandleObject env,
|
|||
MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(env), scopeKind == ScopeKind::NonSyntactic);
|
||||
|
||||
options.setIsRunOnce(true);
|
||||
RootedScript script(cx, frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(),
|
||||
scopeKind, options, srcBuf));
|
||||
RootedScript script(cx, frontend::CompileGlobalScript(cx, scopeKind, options, srcBuf));
|
||||
if (!script) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -8903,8 +8903,7 @@ EvaluateInEnv(JSContext* cx, Handle<Env*> env, AbstractFramePtr frame,
|
|||
if (!scope) {
|
||||
return false;
|
||||
}
|
||||
script = frontend::CompileEvalScript(cx, cx->tempLifoAlloc(), env, scope,
|
||||
options, srcBuf);
|
||||
script = frontend::CompileEvalScript(cx, env, scope, options, srcBuf);
|
||||
if (script) {
|
||||
script->setActiveEval();
|
||||
}
|
||||
|
@ -8914,8 +8913,7 @@ EvaluateInEnv(JSContext* cx, Handle<Env*> env, AbstractFramePtr frame,
|
|||
// circumvent the fresh lexical scope that all eval have, so that the
|
||||
// users of executeInGlobal, like the web console, may add new bindings to
|
||||
// the global scope.
|
||||
script = frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(), scopeKind, options,
|
||||
srcBuf);
|
||||
script = frontend::CompileGlobalScript(cx, scopeKind, options, srcBuf);
|
||||
}
|
||||
|
||||
if (!script) {
|
||||
|
|
|
@ -568,8 +568,7 @@ ScriptParseTask::parse(JSContext* cx)
|
|||
|
||||
ScopeKind scopeKind = options.nonSyntacticScope ? ScopeKind::NonSyntactic : ScopeKind::Global;
|
||||
|
||||
JSScript* script = frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(), scopeKind,
|
||||
options, data,
|
||||
JSScript* script = frontend::CompileGlobalScript(cx, scopeKind, options, data,
|
||||
/* sourceObjectOut = */ &sourceObject.get());
|
||||
if (script) {
|
||||
scripts.infallibleAppend(script);
|
||||
|
@ -592,7 +591,7 @@ ModuleParseTask::parse(JSContext* cx)
|
|||
|
||||
Rooted<ScriptSourceObject*> sourceObject(cx);
|
||||
|
||||
ModuleObject* module = frontend::CompileModule(cx, options, data, cx->tempLifoAlloc(), &sourceObject.get());
|
||||
ModuleObject* module = frontend::CompileModule(cx, options, data, &sourceObject.get());
|
||||
if (module) {
|
||||
scripts.infallibleAppend(module->script());
|
||||
if (sourceObject) {
|
||||
|
@ -615,8 +614,7 @@ ScriptDecodeTask::parse(JSContext* cx)
|
|||
RootedScript resultScript(cx);
|
||||
Rooted<ScriptSourceObject*> sourceObject(cx);
|
||||
|
||||
XDROffThreadDecoder decoder(cx, cx->tempLifoAlloc(), &options,
|
||||
/* sourceObjectOut = */ &sourceObject.get(), range);
|
||||
XDROffThreadDecoder decoder(cx, &options, /* sourceObjectOut = */ &sourceObject.get(), range);
|
||||
XDRResult res = decoder.codeScript(&resultScript);
|
||||
MOZ_ASSERT(bool(resultScript) == res.isOk());
|
||||
if (res.isOk()) {
|
||||
|
@ -681,7 +679,7 @@ MultiScriptsDecodeTask::parse(JSContext* cx)
|
|||
RootedScript resultScript(cx);
|
||||
Rooted<ScriptSourceObject*> sourceObject(cx);
|
||||
|
||||
XDROffThreadDecoder decoder(cx, cx->tempLifoAlloc(), &opts, &sourceObject.get(),
|
||||
XDROffThreadDecoder decoder(cx, &opts, &sourceObject.get(),
|
||||
source.range);
|
||||
XDRResult res = decoder.codeScript(&resultScript);
|
||||
MOZ_ASSERT(bool(resultScript) == res.isOk());
|
||||
|
@ -2310,6 +2308,8 @@ HelperThread::handleParseWorkload(AutoLockHelperThreadState& locked)
|
|||
|
||||
task->parse(cx);
|
||||
|
||||
MOZ_ASSERT(cx->tempLifoAlloc().isEmpty());
|
||||
cx->tempLifoAlloc().freeAll();
|
||||
cx->frontendCollectionPool().purge();
|
||||
cx->atomsZoneFreeLists().clear();
|
||||
}
|
||||
|
|
|
@ -2040,12 +2040,6 @@ DefineNonexistentProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
{
|
||||
// Optimized NativeDefineProperty() version for known absent properties.
|
||||
|
||||
#ifdef DEBUG
|
||||
// Indexed properties of typed arrays should have been handled by SetTypedArrayElement.
|
||||
uint64_t index;
|
||||
MOZ_ASSERT_IF(obj->is<TypedArrayObject>(), !IsTypedArrayIndex(id, &index));
|
||||
#endif
|
||||
|
||||
// Dispense with custom behavior of exotic native objects first.
|
||||
if (obj->is<ArrayObject>()) {
|
||||
// Array's length property is non-configurable, so we shouldn't
|
||||
|
@ -2059,7 +2053,35 @@ DefineNonexistentProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
return result.fail(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
|
||||
}
|
||||
}
|
||||
} else if (obj->is<ArgumentsObject>()) {
|
||||
} else if (obj->is<TypedArrayObject>()) {
|
||||
// 9.4.5.5 step 2. Indexed properties of typed arrays are special.
|
||||
uint64_t index;
|
||||
if (IsTypedArrayIndex(id, &index)) {
|
||||
// This method is only called for non-existent properties, which
|
||||
// means any absent indexed property must be out of range.
|
||||
MOZ_ASSERT(index >= obj->as<TypedArrayObject>().length());
|
||||
|
||||
// Steps 1-2 are enforced by the caller.
|
||||
|
||||
// Step 3.
|
||||
// We still need to call ToNumber, because of its possible side
|
||||
// effects.
|
||||
double d;
|
||||
if (!ToNumber(cx, v, &d)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Steps 4-5.
|
||||
// ToNumber may have detached the array buffer.
|
||||
if (obj->as<TypedArrayObject>().hasDetachedBuffer()) {
|
||||
return result.failSoft(JSMSG_TYPED_ARRAY_DETACHED);
|
||||
}
|
||||
|
||||
// Steps 6-9.
|
||||
// We (wrongly) ignore out of range defines.
|
||||
return result.failSoft(JSMSG_BAD_INDEX);
|
||||
}
|
||||
} else if (obj->is<ArgumentsObject>()) {
|
||||
// If this method is called with either |length| or |@@iterator|, the
|
||||
// property was previously deleted and hence should already be marked
|
||||
// as overridden.
|
||||
|
@ -2939,8 +2961,6 @@ SetExistingProperty(JSContext* cx, HandleId id, HandleValue v, HandleValue recei
|
|||
{
|
||||
// Step 5 for dense elements.
|
||||
if (prop.isDenseOrTypedArrayElement()) {
|
||||
MOZ_ASSERT(!pobj->is<TypedArrayObject>());
|
||||
|
||||
// Step 5.a.
|
||||
if (pobj->denseElementsAreFrozen()) {
|
||||
return result.fail(JSMSG_READ_ONLY);
|
||||
|
@ -2948,7 +2968,14 @@ SetExistingProperty(JSContext* cx, HandleId id, HandleValue v, HandleValue recei
|
|||
|
||||
// Pure optimization for the common case:
|
||||
if (receiver.isObject() && pobj == &receiver.toObject()) {
|
||||
return SetDenseElement(cx, pobj, JSID_TO_INT(id), v, result);
|
||||
uint32_t index = JSID_TO_INT(id);
|
||||
|
||||
if (pobj->is<TypedArrayObject>()) {
|
||||
Rooted<TypedArrayObject*> tobj(cx, &pobj->as<TypedArrayObject>());
|
||||
return SetTypedArrayElement(cx, tobj, index, v, result);
|
||||
}
|
||||
|
||||
return SetDenseElement(cx, pobj, index, v, result);
|
||||
}
|
||||
|
||||
// Steps 5.b-f.
|
||||
|
@ -3014,17 +3041,6 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, Handle
|
|||
return false;
|
||||
}
|
||||
|
||||
if (pobj->is<TypedArrayObject>()) {
|
||||
uint64_t index;
|
||||
if (IsTypedArrayIndex(id, &index)) {
|
||||
Rooted<TypedArrayObject*> tobj(cx, &pobj->as<TypedArrayObject>());
|
||||
return SetTypedArrayElement(cx, tobj, index, v, result);
|
||||
}
|
||||
|
||||
// This case should have been handled.
|
||||
MOZ_ASSERT(!prop.isDenseOrTypedArrayElement());
|
||||
}
|
||||
|
||||
if (prop) {
|
||||
// Steps 5-6.
|
||||
return SetExistingProperty(cx, id, v, receiver, pobj, prop, result);
|
||||
|
|
|
@ -209,8 +209,7 @@ const Class RegExpObject::protoClass_ = {
|
|||
template<typename CharT>
|
||||
RegExpObject*
|
||||
RegExpObject::create(JSContext* cx, const CharT* chars, size_t length, RegExpFlag flags,
|
||||
frontend::TokenStreamAnyChars& tokenStream, LifoAlloc& alloc,
|
||||
NewObjectKind newKind)
|
||||
frontend::TokenStreamAnyChars& tokenStream, NewObjectKind newKind)
|
||||
{
|
||||
static_assert(mozilla::IsSame<CharT, char16_t>::value,
|
||||
"this code may need updating if/when CharT encodes UTF-8");
|
||||
|
@ -220,18 +219,17 @@ RegExpObject::create(JSContext* cx, const CharT* chars, size_t length, RegExpFla
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return create(cx, source, flags, tokenStream, alloc, newKind);
|
||||
return create(cx, source, flags, tokenStream, newKind);
|
||||
}
|
||||
|
||||
template RegExpObject*
|
||||
RegExpObject::create(JSContext* cx, const char16_t* chars, size_t length, RegExpFlag flags,
|
||||
frontend::TokenStreamAnyChars& tokenStream, LifoAlloc& alloc,
|
||||
NewObjectKind newKind);
|
||||
frontend::TokenStreamAnyChars& tokenStream, NewObjectKind newKind);
|
||||
|
||||
template<typename CharT>
|
||||
RegExpObject*
|
||||
RegExpObject::create(JSContext* cx, const CharT* chars, size_t length, RegExpFlag flags,
|
||||
LifoAlloc& alloc, NewObjectKind newKind)
|
||||
RegExpObject::create(JSContext* cx, const CharT* chars, size_t length,
|
||||
RegExpFlag flags, NewObjectKind newKind)
|
||||
{
|
||||
static_assert(mozilla::IsSame<CharT, char16_t>::value,
|
||||
"this code may need updating if/when CharT encodes UTF-8");
|
||||
|
@ -241,19 +239,21 @@ RegExpObject::create(JSContext* cx, const CharT* chars, size_t length, RegExpFla
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return create(cx, source, flags, alloc, newKind);
|
||||
return create(cx, source, flags, newKind);
|
||||
}
|
||||
|
||||
template RegExpObject*
|
||||
RegExpObject::create(JSContext* cx, const char16_t* chars, size_t length, RegExpFlag flags,
|
||||
LifoAlloc& alloc, NewObjectKind newKind);
|
||||
RegExpObject::create(JSContext* cx, const char16_t* chars, size_t length,
|
||||
RegExpFlag flags, NewObjectKind newKind);
|
||||
|
||||
RegExpObject*
|
||||
RegExpObject::create(JSContext* cx, HandleAtom source, RegExpFlag flags,
|
||||
frontend::TokenStreamAnyChars& tokenStream,
|
||||
LifoAlloc& alloc, NewObjectKind newKind)
|
||||
frontend::TokenStreamAnyChars& tokenStream, NewObjectKind newKind)
|
||||
{
|
||||
if (!irregexp::ParsePatternSyntax(tokenStream, alloc, source, flags & UnicodeFlag)) {
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
if (!irregexp::ParsePatternSyntax(tokenStream, allocScope.alloc(),
|
||||
source, flags & UnicodeFlag))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -268,13 +268,15 @@ RegExpObject::create(JSContext* cx, HandleAtom source, RegExpFlag flags,
|
|||
}
|
||||
|
||||
RegExpObject*
|
||||
RegExpObject::create(JSContext* cx, HandleAtom source, RegExpFlag flags, LifoAlloc& alloc,
|
||||
NewObjectKind newKind)
|
||||
RegExpObject::create(JSContext* cx, HandleAtom source, RegExpFlag flags, NewObjectKind newKind)
|
||||
{
|
||||
CompileOptions dummyOptions(cx);
|
||||
TokenStream dummyTokenStream(cx, dummyOptions, (const char16_t*) nullptr, 0, nullptr);
|
||||
|
||||
if (!irregexp::ParsePatternSyntax(dummyTokenStream, alloc, source, flags & UnicodeFlag)) {
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
if (!irregexp::ParsePatternSyntax(dummyTokenStream, allocScope.alloc(),
|
||||
source, flags & UnicodeFlag))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1050,11 +1052,11 @@ RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re, HandleAtom pa
|
|||
CompileOptions options(cx);
|
||||
frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
|
||||
|
||||
LifoAllocScope scope(&cx->tempLifoAlloc());
|
||||
|
||||
/* Parse the pattern. */
|
||||
/* Parse the pattern. The RegExpCompileData is allocated in LifoAlloc and
|
||||
* will only be live while LifoAllocScope is on stack. */
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
irregexp::RegExpCompileData data;
|
||||
if (!irregexp::ParsePattern(dummyTokenStream, cx->tempLifoAlloc(), pattern,
|
||||
if (!irregexp::ParsePattern(dummyTokenStream, allocScope.alloc(), pattern,
|
||||
re->multiline(), mode == MatchOnly, re->unicode(),
|
||||
re->ignoreCase(), re->global(), re->sticky(), &data))
|
||||
{
|
||||
|
@ -1064,7 +1066,8 @@ RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re, HandleAtom pa
|
|||
re->parenCount = data.capture_count;
|
||||
|
||||
JitCodeTables tables;
|
||||
irregexp::RegExpCode code = irregexp::CompilePattern(cx, re, &data, input,
|
||||
irregexp::RegExpCode code = irregexp::CompilePattern(cx, allocScope.alloc(),
|
||||
re, &data, input,
|
||||
false /* global() */,
|
||||
re->ignoreCase(),
|
||||
input->hasLatin1Chars(),
|
||||
|
@ -1515,7 +1518,7 @@ js::XDRScriptRegExpObject(XDRState<mode>* xdr, MutableHandle<RegExpObject*> objp
|
|||
MOZ_TRY(xdr->codeUint32(&flagsword));
|
||||
if (mode == XDR_DECODE) {
|
||||
RegExpObject* reobj = RegExpObject::create(xdr->cx(), source, RegExpFlag(flagsword),
|
||||
xdr->lifoAlloc(), TenuredObject);
|
||||
TenuredObject);
|
||||
if (!reobj) {
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
@ -1539,7 +1542,7 @@ js::CloneScriptRegExpObject(JSContext* cx, RegExpObject& reobj)
|
|||
RootedAtom source(cx, reobj.getSource());
|
||||
cx->markAtom(source);
|
||||
|
||||
return RegExpObject::create(cx, source, reobj.getFlags(), cx->tempLifoAlloc(), TenuredObject);
|
||||
return RegExpObject::create(cx, source, reobj.getFlags(), TenuredObject);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(RegExpShared*)
|
||||
|
|
|
@ -70,21 +70,20 @@ class RegExpObject : public NativeObject
|
|||
|
||||
template<typename CharT>
|
||||
static RegExpObject*
|
||||
create(JSContext* cx, const CharT* chars, size_t length, RegExpFlag flags, LifoAlloc& alloc,
|
||||
NewObjectKind newKind);
|
||||
create(JSContext* cx, const CharT* chars, size_t length,
|
||||
RegExpFlag flags, NewObjectKind newKind);
|
||||
|
||||
template<typename CharT>
|
||||
static RegExpObject*
|
||||
create(JSContext* cx, const CharT* chars, size_t length, RegExpFlag flags,
|
||||
frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, NewObjectKind kind);
|
||||
frontend::TokenStreamAnyChars& ts, NewObjectKind kind);
|
||||
|
||||
static RegExpObject*
|
||||
create(JSContext* cx, HandleAtom atom, RegExpFlag flags, LifoAlloc& alloc,
|
||||
NewObjectKind newKind);
|
||||
create(JSContext* cx, HandleAtom source, RegExpFlag flags, NewObjectKind newKind);
|
||||
|
||||
static RegExpObject*
|
||||
create(JSContext* cx, HandleAtom atom, RegExpFlag flags, frontend::TokenStreamAnyChars& ts,
|
||||
LifoAlloc& alloc, NewObjectKind newKind);
|
||||
create(JSContext* cx, HandleAtom source, RegExpFlag flags,
|
||||
frontend::TokenStreamAnyChars& ts, NewObjectKind newKind);
|
||||
|
||||
/*
|
||||
* Compute the initial shape to associate with fresh RegExp objects,
|
||||
|
|
|
@ -3184,8 +3184,7 @@ CloneObject(JSContext* cx, HandleNativeObject selfHostedObject)
|
|||
RegExpObject& reobj = selfHostedObject->as<RegExpObject>();
|
||||
RootedAtom source(cx, reobj.getSource());
|
||||
MOZ_ASSERT(source->isPermanentAtom());
|
||||
clone = RegExpObject::create(cx, source, reobj.getFlags(), cx->tempLifoAlloc(),
|
||||
TenuredObject);
|
||||
clone = RegExpObject::create(cx, source, reobj.getFlags(), TenuredObject);
|
||||
} else if (selfHostedObject->is<DateObject>()) {
|
||||
clone = JS::NewDateObject(cx, selfHostedObject->as<DateObject>().clippedTime());
|
||||
} else if (selfHostedObject->is<BooleanObject>()) {
|
||||
|
|
|
@ -2595,8 +2595,7 @@ JSStructuredCloneReader::startRead(MutableHandleValue vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
RegExpObject* reobj = RegExpObject::create(context(), atom, flags,
|
||||
context()->tempLifoAlloc(), GenericObject);
|
||||
RegExpObject* reobj = RegExpObject::create(context(), atom, flags, GenericObject);
|
||||
if (!reobj) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -30,12 +30,6 @@ using namespace js;
|
|||
using mozilla::ArrayEqual;
|
||||
using mozilla::Utf8Unit;
|
||||
|
||||
template<XDRMode mode>
|
||||
LifoAlloc&
|
||||
XDRState<mode>::lifoAlloc() const {
|
||||
return buf.cx()->tempLifoAlloc();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool
|
||||
XDRCoderBase::validateResultCode(JSContext* cx, JS::TranscodeResult code) const
|
||||
|
|
|
@ -254,7 +254,6 @@ class XDRState : public XDRCoderBase
|
|||
JSContext* cx() const {
|
||||
return buf.cx();
|
||||
}
|
||||
virtual LifoAlloc& lifoAlloc() const;
|
||||
|
||||
virtual bool hasOptions() const { return false; }
|
||||
virtual const JS::ReadOnlyCompileOptions& options() {
|
||||
|
@ -508,7 +507,6 @@ class XDROffThreadDecoder : public XDRDecoder
|
|||
{
|
||||
const JS::ReadOnlyCompileOptions* options_;
|
||||
ScriptSourceObject** sourceObjectOut_;
|
||||
LifoAlloc& alloc_;
|
||||
|
||||
public:
|
||||
// Note, when providing an JSContext, where isJSContext is false,
|
||||
|
@ -519,24 +517,19 @@ class XDROffThreadDecoder : public XDRDecoder
|
|||
//
|
||||
// When providing a sourceObjectOut pointer, you have to ensure that it is
|
||||
// marked by the GC to avoid dangling pointers.
|
||||
XDROffThreadDecoder(JSContext* cx, LifoAlloc& alloc,
|
||||
XDROffThreadDecoder(JSContext* cx,
|
||||
const JS::ReadOnlyCompileOptions* options,
|
||||
ScriptSourceObject** sourceObjectOut,
|
||||
const JS::TranscodeRange& range)
|
||||
: XDRDecoder(cx, range),
|
||||
options_(options),
|
||||
sourceObjectOut_(sourceObjectOut),
|
||||
alloc_(alloc)
|
||||
sourceObjectOut_(sourceObjectOut)
|
||||
{
|
||||
MOZ_ASSERT(options);
|
||||
MOZ_ASSERT(sourceObjectOut);
|
||||
MOZ_ASSERT(*sourceObjectOut == nullptr);
|
||||
}
|
||||
|
||||
LifoAlloc& lifoAlloc() const override {
|
||||
return alloc_;
|
||||
}
|
||||
|
||||
bool hasOptions() const override { return true; }
|
||||
const JS::ReadOnlyCompileOptions& options() override {
|
||||
return *options_;
|
||||
|
|
|
@ -1192,6 +1192,27 @@ nsFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle)
|
|||
mMayHaveRoundedCorners = true;
|
||||
}
|
||||
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
void
|
||||
nsIFrame::AssertNewStyleIsSane(ComputedStyle& aNewStyle)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(PresShell() == aNewStyle.PresContextForFrame()->PresShell());
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
aNewStyle.GetPseudo() == mComputedStyle->GetPseudo() ||
|
||||
// ::first-line continuations are weird, this should probably be fixed via
|
||||
// bug 1465474.
|
||||
(mComputedStyle->GetPseudo() == nsCSSPseudoElements::firstLine() &&
|
||||
aNewStyle.GetPseudo() == nsCSSAnonBoxes::mozLineFrame()) ||
|
||||
// ::first-letter continuations are broken, in particular floating ones, see
|
||||
// bug 1490281. The construction code tries to fix this up after the fact,
|
||||
// then restyling undoes it...
|
||||
(mComputedStyle->GetPseudo() == nsCSSAnonBoxes::mozText() &&
|
||||
aNewStyle.GetPseudo() == nsCSSAnonBoxes::firstLetterContinuation()) ||
|
||||
(mComputedStyle->GetPseudo() == nsCSSAnonBoxes::firstLetterContinuation() &&
|
||||
aNewStyle.GetPseudo() == nsCSSAnonBoxes::mozText()));
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
nsIFrame::ReparentFrameViewTo(nsViewManager* aViewManager,
|
||||
nsView* aNewParentView,
|
||||
|
|
|
@ -772,10 +772,18 @@ public:
|
|||
* Get the style associated with this frame.
|
||||
*/
|
||||
ComputedStyle* Style() const { return mComputedStyle; }
|
||||
|
||||
void AssertNewStyleIsSane(ComputedStyle&)
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
|
||||
void SetComputedStyle(ComputedStyle* aStyle)
|
||||
{
|
||||
if (aStyle != mComputedStyle) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(PresShell() == aStyle->PresContextForFrame()->PresShell());
|
||||
AssertNewStyleIsSane(*aStyle);
|
||||
RefPtr<ComputedStyle> oldComputedStyle = mComputedStyle.forget();
|
||||
mComputedStyle = aStyle;
|
||||
DidSetComputedStyle(oldComputedStyle);
|
||||
|
|
|
@ -268,6 +268,17 @@ GetPointerCapabilities(nsIDocument* aDocument, LookAndFeel::IntID aID)
|
|||
{
|
||||
MOZ_ASSERT(aID == LookAndFeel::eIntID_PrimaryPointerCapabilities ||
|
||||
aID == LookAndFeel::eIntID_AllPointerCapabilities);
|
||||
MOZ_ASSERT(aDocument);
|
||||
|
||||
if (nsIDocShell* docShell = aDocument->GetDocShell()) {
|
||||
// The touch-events-override happens only for the Responsive Design Mode so
|
||||
// that we don't need to care about ResistFingerprinting.
|
||||
uint32_t touchEventsOverride = nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE;
|
||||
docShell->GetTouchEventsOverride(&touchEventsOverride);
|
||||
if (touchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_ENABLED) {
|
||||
return PointerCapabilities::Coarse;
|
||||
}
|
||||
}
|
||||
|
||||
// The default value is mouse-type pointer.
|
||||
const PointerCapabilities kDefaultCapabilities =
|
||||
|
|
|
@ -31,6 +31,7 @@ public class TestGeckoProfile {
|
|||
private static final String PROFILE_NAME = "profileName";
|
||||
|
||||
private static final String CLIENT_ID_JSON_ATTR = "clientID";
|
||||
private static final String CLIENT_ID_CANARY = "c0ffeec0-ffee-c0ff-eec0-ffeec0ffeec0";
|
||||
private static final String PROFILE_CREATION_DATE_JSON_ATTR = "created";
|
||||
|
||||
@Rule
|
||||
|
@ -52,9 +53,12 @@ public class TestGeckoProfile {
|
|||
timesFile = new File(profileDir, "times.json");
|
||||
}
|
||||
|
||||
public void assertValidClientId(final String clientId) {
|
||||
private void assertValidClientId(final String clientId) throws IllegalStateException {
|
||||
// This isn't the method we use in the main GeckoProfile code, but it should be equivalent.
|
||||
UUID.fromString(clientId); // assert: will throw if null or invalid UUID.
|
||||
if (CLIENT_ID_CANARY.equals(clientId)) {
|
||||
throw new IllegalArgumentException("Canary client id: " + clientId);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -76,6 +80,15 @@ public class TestGeckoProfile {
|
|||
assertEquals("clientID file format matches expectations", clientId, readClientIdFromFile(clientIdFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIfHadCanaryClientIdForFreshProfile() throws Exception {
|
||||
assertFalse("client ID file does not exist", clientIdFile.exists());
|
||||
|
||||
// Asking for getClientId() will create a new one if none existed
|
||||
profile.getClientId();
|
||||
assertEquals(false, profile.getIfHadCanaryClientId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetClientIdFileAlreadyExists() throws Exception {
|
||||
final String validClientId = "905de1c0-0ea6-4a43-95f9-6170035f5a82";
|
||||
|
@ -125,6 +138,47 @@ public class TestGeckoProfile {
|
|||
assertNotEquals("Created new ID when file format was invalid", validClientId, clientIdForInvalidFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetClientIdForCanaryId() throws Exception {
|
||||
assertTrue("Created the parent dirs of the client ID file", clientIdFile.getParentFile().mkdirs());
|
||||
writeClientIdToFile(clientIdFile, CLIENT_ID_CANARY);
|
||||
|
||||
final String clientIdForCanaryId = profile.getClientId();
|
||||
assertValidClientId(clientIdForCanaryId);
|
||||
assertNotEquals(CLIENT_ID_CANARY, clientIdForCanaryId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanaryFlagForValidId() throws Exception {
|
||||
assertTrue("Created the parent dirs of the client ID file", clientIdFile.getParentFile().mkdirs());
|
||||
final String generatedValidClientId = UUID.randomUUID().toString();
|
||||
writeClientIdToFile(clientIdFile, generatedValidClientId);
|
||||
createCanaryIdFlag();
|
||||
|
||||
final boolean hasCanaryFlagForValidId = profile.getIfHadCanaryClientId();
|
||||
assertEquals(false, hasCanaryFlagForValidId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanaryIdFlagForInvalidId() throws Exception {
|
||||
assertTrue("Created the parent dirs of the client ID file", clientIdFile.getParentFile().mkdirs());
|
||||
writeClientIdToFile(clientIdFile, "invalid");
|
||||
createCanaryIdFlag();
|
||||
|
||||
final boolean hasCanaryFlagForInvalidId = profile.getIfHadCanaryClientId();
|
||||
assertEquals(false, hasCanaryFlagForInvalidId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanaryIdFlagForCanaryId() throws Exception {
|
||||
assertTrue("Created the parent dirs of the client ID file", clientIdFile.getParentFile().mkdirs());
|
||||
writeClientIdToFile(clientIdFile, CLIENT_ID_CANARY);
|
||||
createCanaryIdFlag();
|
||||
|
||||
final boolean hasCanaryFlagForCanaryId = profile.getIfHadCanaryClientId();
|
||||
assertEquals(true, hasCanaryFlagForCanaryId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnsureParentDirs() {
|
||||
final File grandParentDir = new File(profileDir, "grandParent");
|
||||
|
@ -171,6 +225,7 @@ public class TestGeckoProfile {
|
|||
"905de1c0-0ea6-4a43-95f9-6170035f5a8", // too short (last section)
|
||||
"05de1c0-0ea6-4a43-95f9-6170035f5a82", // too short (first section)
|
||||
"905de1c0-0ea6-4a43-95f9-6170035f5a8!", // contains a symbol
|
||||
CLIENT_ID_CANARY,
|
||||
};
|
||||
for (final String invalidClientId : invalidClientIds) {
|
||||
assertFalse("Client ID, " + invalidClientId + ", is invalid", GeckoProfile.isClientIdValid(invalidClientId));
|
||||
|
@ -231,4 +286,8 @@ public class TestGeckoProfile {
|
|||
obj.put(CLIENT_ID_JSON_ATTR, clientId);
|
||||
FileUtils.writeJSONObjectToFile(file, obj);
|
||||
}
|
||||
|
||||
private void createCanaryIdFlag() throws Exception{
|
||||
profile.getClientId();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,10 +155,12 @@ public class TelemetryCorePingDelegate extends BrowserAppDelegateWithReference
|
|||
}
|
||||
|
||||
final String clientID;
|
||||
final boolean hadCanaryClientId;
|
||||
try {
|
||||
clientID = profile.getClientId();
|
||||
hadCanaryClientId = profile.getIfHadCanaryClientId();
|
||||
} catch (final IOException e) {
|
||||
Log.w(LOGTAG, "Unable to get client ID to generate core ping: " + e);
|
||||
Log.w(LOGTAG, "Unable to get client ID properties to generate core ping: " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -168,6 +170,7 @@ public class TelemetryCorePingDelegate extends BrowserAppDelegateWithReference
|
|||
sessionMeasurements.getAndResetSessionMeasurements(activity);
|
||||
final TelemetryCorePingBuilder pingBuilder = new TelemetryCorePingBuilder(activity)
|
||||
.setClientID(clientID)
|
||||
.setHadCanaryClientId(hadCanaryClientId)
|
||||
.setDefaultSearchEngine(TelemetryCorePingBuilder.getEngineIdentifier(engine))
|
||||
.setProfileCreationDate(TelemetryCorePingBuilder.getProfileCreationDate(activity, profile))
|
||||
.setSequenceNumber(TelemetryCorePingBuilder.getAndIncrementSequenceNumber(sharedPrefs))
|
||||
|
|
|
@ -54,7 +54,7 @@ public class TelemetryCorePingBuilder extends TelemetryPingBuilder {
|
|||
private static final String PREF_SEQ_COUNT = "telemetry-seqCount";
|
||||
|
||||
private static final String NAME = "core";
|
||||
private static final int VERSION_VALUE = 9; // For version history, see toolkit/components/telemetry/docs/core-ping.rst
|
||||
private static final int VERSION_VALUE = 10; // For version history, see toolkit/components/telemetry/docs/core-ping.rst
|
||||
|
||||
private static final String DEFAULT_BROWSER = "defaultBrowser";
|
||||
private static final String ARCHITECTURE = "arch";
|
||||
|
@ -78,6 +78,7 @@ public class TelemetryCorePingBuilder extends TelemetryPingBuilder {
|
|||
private static final String VERSION_ATTR = "v";
|
||||
private static final String FLASH_USAGE = "flashUsage";
|
||||
private static final String ACCESSIBILITY_SERVICES = "accessibilityServices";
|
||||
private static final String HAD_CANARY_CLIENT_ID = "bug_1501329_affected";
|
||||
|
||||
public TelemetryCorePingBuilder(final Context context) {
|
||||
initPayloadConstants(context);
|
||||
|
@ -133,6 +134,7 @@ public class TelemetryCorePingBuilder extends TelemetryPingBuilder {
|
|||
SEQ,
|
||||
TIMEZONE_OFFSET,
|
||||
VERSION_ATTR,
|
||||
HAD_CANARY_CLIENT_ID,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -144,6 +146,11 @@ public class TelemetryCorePingBuilder extends TelemetryPingBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public TelemetryCorePingBuilder setHadCanaryClientId(final boolean hadCanaryClientId) {
|
||||
payload.put(HAD_CANARY_CLIENT_ID, hadCanaryClientId);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param engine the default search engine identifier, or null if there is an error.
|
||||
*/
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
@ -22,7 +22,6 @@ import org.mozilla.gecko.util.FileUtils;
|
|||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.INIParser;
|
||||
import org.mozilla.gecko.util.INISection;
|
||||
import org.mozilla.gecko.util.IntentUtils;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
|
@ -46,6 +45,9 @@ public final class GeckoProfile {
|
|||
private static final String CLIENT_ID_FILE_PATH = "datareporting/state.json";
|
||||
// In the client ID file, the attribute title in the JSON object containing the client ID value.
|
||||
private static final String CLIENT_ID_JSON_ATTR = "clientID";
|
||||
private static final String HAD_CANARY_CLIENT_ID_JSON_ATTR = "wasCanary";
|
||||
// Must match the one from TelemetryUtils.jsm
|
||||
private static final String CANARY_CLIENT_ID = "c0ffeec0-ffee-c0ff-eec0-ffeec0ffeec0";
|
||||
|
||||
private static final String TIMES_PATH = "times.json";
|
||||
private static final String PROFILE_CREATION_DATE_JSON_ATTR = "created";
|
||||
|
@ -449,26 +451,37 @@ public final class GeckoProfile {
|
|||
// Mimics ClientID.jsm - _doLoadClientID.
|
||||
@WorkerThread
|
||||
public String getClientId() throws IOException {
|
||||
String clientId = "";
|
||||
try {
|
||||
return getValidClientIdFromDisk(CLIENT_ID_FILE_PATH);
|
||||
clientId = getClientIdFromDisk(CLIENT_ID_FILE_PATH);
|
||||
} catch (final IOException e) {
|
||||
// Avoid log spam: don't log the full Exception w/ the stack trace.
|
||||
Log.d(LOGTAG, "Could not get client ID - creating a new one: " + e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
String clientIdToWrite = generateNewClientId();
|
||||
if (isClientIdValid(clientId)) {
|
||||
return clientId;
|
||||
} else {
|
||||
String newClientId = generateNewClientId();
|
||||
// There is a possibility Gecko is running and the Gecko telemetry implementation decided it's time to generate
|
||||
// the client ID, writing client ID underneath us. Since it's highly unlikely (e.g. we run in onStart before
|
||||
// Gecko is started), we don't handle that possibility besides writing the ID and then reading from the file
|
||||
// again (rather than just returning the value we generated before writing).
|
||||
//
|
||||
// In the event it does happen, any discrepancy will be resolved after a restart. In the mean time, both this
|
||||
// implementation and the Gecko implementation could upload documents with inconsistent IDs.
|
||||
//
|
||||
// In any case, if we get an exception, intentionally throw - there's nothing more to do here.
|
||||
persistNewClientId(clientId, newClientId);
|
||||
}
|
||||
|
||||
// There is a possibility Gecko is running and the Gecko telemetry implementation decided it's time to generate
|
||||
// the client ID, writing client ID underneath us. Since it's highly unlikely (e.g. we run in onStart before
|
||||
// Gecko is started), we don't handle that possibility besides writing the ID and then reading from the file
|
||||
// again (rather than just returning the value we generated before writing).
|
||||
//
|
||||
// In the event it does happen, any discrepancy will be resolved after a restart. In the mean time, both this
|
||||
// implementation and the Gecko implementation could upload documents with inconsistent IDs.
|
||||
//
|
||||
// In any case, if we get an exception, intentionally throw - there's nothing more to do here.
|
||||
persistClientId(clientIdToWrite);
|
||||
return getValidClientIdFromDisk(CLIENT_ID_FILE_PATH);
|
||||
return getClientIdFromDisk(CLIENT_ID_FILE_PATH);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public boolean getIfHadCanaryClientId() throws IOException {
|
||||
final JSONObject obj = readJSONObjectFromFile(CLIENT_ID_FILE_PATH);
|
||||
return obj.optBoolean(HAD_CANARY_CLIENT_ID_JSON_ATTR);
|
||||
}
|
||||
|
||||
protected static String generateNewClientId() {
|
||||
|
@ -480,45 +493,52 @@ public final class GeckoProfile {
|
|||
* @throws IOException if a valid client ID could not be retrieved
|
||||
*/
|
||||
@WorkerThread
|
||||
private String getValidClientIdFromDisk(final String filePath) throws IOException {
|
||||
private String getClientIdFromDisk(final String filePath) throws IOException {
|
||||
final JSONObject obj = readJSONObjectFromFile(filePath);
|
||||
final String clientId = obj.optString(CLIENT_ID_JSON_ATTR);
|
||||
if (isClientIdValid(clientId)) {
|
||||
return clientId;
|
||||
}
|
||||
throw new IOException("Received client ID is invalid: " + clientId);
|
||||
return obj.optString(CLIENT_ID_JSON_ATTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists the given client ID to disk. This will overwrite any existing files.
|
||||
*/
|
||||
@WorkerThread
|
||||
private void persistClientId(final String clientId) throws IOException {
|
||||
private void persistNewClientId(@Nullable final String oldClientId,
|
||||
@NonNull final String newClientId) throws IOException {
|
||||
if (!ensureParentDirs(CLIENT_ID_FILE_PATH)) {
|
||||
throw new IOException("Could not create client ID parent directories");
|
||||
}
|
||||
|
||||
final JSONObject obj = new JSONObject();
|
||||
try {
|
||||
obj.put(CLIENT_ID_JSON_ATTR, clientId);
|
||||
obj.put(CLIENT_ID_JSON_ATTR, newClientId);
|
||||
obj.put(HAD_CANARY_CLIENT_ID_JSON_ATTR, isCanaryClientId(oldClientId));
|
||||
} catch (final JSONException e) {
|
||||
throw new IOException("Could not create client ID JSON object", e);
|
||||
}
|
||||
|
||||
// ClientID.jsm overwrites the file to store the client ID so it's okay if we do it too.
|
||||
Log.d(LOGTAG, "Attempting to write new client ID");
|
||||
Log.d(LOGTAG, "Attempting to write new client ID properties");
|
||||
writeFile(CLIENT_ID_FILE_PATH, obj.toString()); // Logs errors within function: ideally we'd throw.
|
||||
}
|
||||
|
||||
// From ClientID.jsm - isValidClientID.
|
||||
public static boolean isClientIdValid(final String clientId) {
|
||||
public static boolean isClientIdValid(@Nullable final String clientId) {
|
||||
// We could use UUID.fromString but, for consistency, we take the implementation from ClientID.jsm.
|
||||
if (TextUtils.isEmpty(clientId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CANARY_CLIENT_ID.equals(clientId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return clientId.matches("(?i:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})");
|
||||
}
|
||||
|
||||
private static boolean isCanaryClientId(@Nullable final String clientId) {
|
||||
return CANARY_CLIENT_ID.equals(clientId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the profile creation date and persists it if it had to be generated.
|
||||
*
|
||||
|
@ -958,7 +978,7 @@ public final class GeckoProfile {
|
|||
// Create the client ID file before Gecko starts (we assume this method
|
||||
// is called before Gecko starts). If we let Gecko start, the JS telemetry
|
||||
// code may try to write to the file at the same time Java does.
|
||||
persistClientId(generateNewClientId());
|
||||
persistNewClientId(null, generateNewClientId());
|
||||
|
||||
return profileDir;
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"rules": {
|
||||
"mozilla/use-chromeutils-generateqi": 0,
|
||||
},
|
||||
};
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
/* eslint-disable mozilla/use-cc-etc */
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
/* eslint-disable mozilla/use-chromeutils-generateqi */
|
||||
/* eslint-disable mozilla/use-services */
|
||||
|
||||
var _quit = false;
|
||||
|
|
|
@ -56,7 +56,9 @@ function testOneFile(uri) {
|
|||
let principal = SpecialPowers.Cc["@mozilla.org/systemprincipal;1"]
|
||||
.createInstance(SpecialPowers.Ci.nsIPrincipal);
|
||||
|
||||
let testScope = SpecialPowers.Cu.Sandbox(principal);
|
||||
let testScope =
|
||||
SpecialPowers.Cu.Sandbox(principal, { sandboxName: uri,
|
||||
wantGlobalProperties: ["ChromeUtils"] });
|
||||
|
||||
// Populate test environment with test harness prerequisites.
|
||||
testScope.Components = SpecialPowers.Components;
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.io.IOException;
|
|||
public class testUnifiedTelemetryClientId extends JavascriptBridgeTest {
|
||||
private static final String TEST_JS = "testUnifiedTelemetryClientId.js";
|
||||
private static final String CLIENT_ID_PATH = "datareporting/state.json";
|
||||
private static final String CLIENT_ID_CANARY = "c0ffeec0-ffee-c0ff-eec0-ffeec0ffeec0";
|
||||
|
||||
private GeckoProfile profile;
|
||||
private File profileDir;
|
||||
|
@ -138,6 +139,7 @@ public class testUnifiedTelemetryClientId extends JavascriptBridgeTest {
|
|||
// file is created when Java attempts to retrieve it if it does not exist.
|
||||
final String clientId = profile.getClientId();
|
||||
fAssertNotNull("Returned client ID is not null", clientId);
|
||||
fAssertNotEquals("Client ID is not the canary id", clientId, CLIENT_ID_CANARY);
|
||||
fAssertTrue("Client ID file exists after getClientId call", getClientIdFile().exists());
|
||||
return clientId;
|
||||
}
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Cu.import("resource://gre/modules/Geometry.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Messaging.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Geometry.jsm");
|
||||
|
||||
const ACCESSIBLECARET_PREF = "layout.accessiblecaret.enabled";
|
||||
const BASE_TEST_URL = "http://mochi.test:8888/tests/robocop/testAccessibleCarets.html";
|
||||
|
@ -46,10 +44,8 @@ function do_promiseTabChangeEvent(tabId, eventType) {
|
|||
* or if we have basic content.
|
||||
*/
|
||||
function isInputOrTextarea(element) {
|
||||
// ChromeUtils isn't included in robocop tests, so we have to use a different
|
||||
// way to test elements.
|
||||
return (element.namespaceURI === "http://www.w3.org/1999/xhtml" &&
|
||||
(element.localName === "input" || element.localName === "textarea"));
|
||||
return (ChromeUtils.getClassName(element) === "HTMLInputElement" ||
|
||||
ChromeUtils.getClassName(element) === "HTMLTextAreaElement");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
* 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/. */
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Messaging.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let java = new JavaBridge(this);
|
||||
do_register_cleanup(() => {
|
||||
|
|
|
@ -8,12 +8,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const {ChromeUtils} = Cu.getGlobalForObject(XPCOMUtils);
|
||||
ChromeUtils.import("resource://gre/modules/Messaging.jsm");
|
||||
|
||||
// event name
|
||||
const TOPIC_ANDROID_CAST_DEVICE_ADDED = "AndroidCastDevice:Added";
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// We use a global variable to track the <browser> where the tests are happening
|
||||
var browser;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Messaging.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var java = new JavaBridge(this);
|
||||
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
add_test(function filepicker_open() {
|
||||
let chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
|
|
|
@ -5,10 +5,8 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Messaging.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const TEST_URL = "http://mochi.test:8888/tests/robocop/robocop_text_page.html";
|
||||
|
||||
|
|
|
@ -5,10 +5,8 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// Make the timer global so it doesn't get GC'd
|
||||
var gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
* 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/. */
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/ReaderMode.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/ReaderMode.jsm");
|
||||
|
||||
var java = new JavaBridge(this);
|
||||
|
||||
|
|
|
@ -5,11 +5,9 @@
|
|||
|
||||
/* globals ReaderMode */
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/ReaderMode.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/ReaderMode.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
var Reader = Services.wm.getMostRecentWindow("navigator:browser").Reader;
|
||||
|
||||
|
|
|
@ -3,11 +3,9 @@
|
|||
* 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/. */
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RuntimePermissions", "resource://gre/modules/RuntimePermissions.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "RuntimePermissions", "resource://gre/modules/RuntimePermissions.jsm");
|
||||
|
||||
add_task(async function test_snackbar_api() {
|
||||
RuntimePermissions.waitForPermissions([
|
||||
|
|
|
@ -3,12 +3,8 @@
|
|||
* 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/. */
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Snackbars", "resource://gre/modules/Snackbars.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher", "resource://gre/modules/Messaging.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "Snackbars", "resource://gre/modules/Snackbars.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "EventDispatcher", "resource://gre/modules/Messaging.jsm");
|
||||
|
||||
add_task(async function test_snackbar_api() {
|
||||
Snackbars.show("This is a Snackbar", Snackbars.LENGTH_INDEFINITE, {
|
||||
|
|
|
@ -5,11 +5,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Messaging.jsm");
|
||||
|
||||
function promiseLoadEvent(browser, url, eventType = "load", runBeforeLoad) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -58,12 +56,7 @@ function doUpdate() {
|
|||
|
||||
return new Promise((resolve, reject) => {
|
||||
let listener = {
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Ci.nsISupports) || iid.equals(Ci.nsIUrlClassifierUpdateObserver))
|
||||
return this;
|
||||
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIUrlClassifierUpdateObserver]),
|
||||
updateUrlRequested: function(url) { },
|
||||
streamFinished: function(status) { },
|
||||
updateError: function(errorCode) {
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
* 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/. */
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const EVENT_TEST1 = "_test_event_1.1";
|
||||
const EVENT_TEST2 = "_test_event_2.1";
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/ClientID.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/ClientID.jsm");
|
||||
|
||||
var java = new JavaBridge(this);
|
||||
do_register_cleanup(() => {
|
||||
|
|
|
@ -5,10 +5,8 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/use-chromeutils-import */
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/SimpleServiceDiscovery.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/SimpleServiceDiscovery.jsm");
|
||||
|
||||
Cu.importGlobalProperties(["InspectorUtils"]);
|
||||
|
||||
|
|
|
@ -503,7 +503,7 @@ class OSXBootstrapper(BaseBootstrapper):
|
|||
return active_name.lower()
|
||||
|
||||
def ensure_stylo_packages(self, state_dir, checkout_root):
|
||||
cbindgen_min_version = '0.6.6'
|
||||
cbindgen_min_version = '0.6.7'
|
||||
# We installed clang via homebrew earlier.
|
||||
self.ensure_rust_package('cbindgen', cbindgen_min_version)
|
||||
|
||||
|
|
|
@ -811,7 +811,11 @@ class RecursiveMakeBackend(CommonBackend):
|
|||
|
||||
def add_category_rules(category, roots, graph):
|
||||
rule = root_deps_mk.create_rule(['recurse_%s' % category])
|
||||
rule.add_dependencies(roots)
|
||||
# Directories containing rust compilations don't generally depend
|
||||
# on other directories in the tree, so putting them first here will
|
||||
# start them earlier in the build.
|
||||
rule.add_dependencies(chain((r for r in roots if 'rust' in r),
|
||||
(r for r in roots if 'rust' not in r)))
|
||||
for target, deps in sorted(graph.items()):
|
||||
if deps:
|
||||
rule = root_deps_mk.create_rule([target])
|
||||
|
|
|
@ -38,19 +38,19 @@ derive_helper_methods = true
|
|||
[export]
|
||||
prefix = "Style"
|
||||
include = [
|
||||
"StyleAppearance",
|
||||
"StyleComputedFontStretchRange",
|
||||
"StyleComputedFontStyleDescriptor",
|
||||
"StyleComputedFontWeightRange",
|
||||
"StyleComputedTimingFunction",
|
||||
"StyleDisplay",
|
||||
"StyleDisplayMode",
|
||||
"StyleFillRule",
|
||||
"StyleFontDisplay",
|
||||
"StyleFontFaceSourceListComponent",
|
||||
"StyleFontLanguageOverride",
|
||||
"StyleTimingFunction",
|
||||
"StylePathCommand",
|
||||
"StyleUnicodeRange",
|
||||
"Appearance",
|
||||
"ComputedFontStretchRange",
|
||||
"ComputedFontStyleDescriptor",
|
||||
"ComputedFontWeightRange",
|
||||
"ComputedTimingFunction",
|
||||
"Display",
|
||||
"DisplayMode",
|
||||
"FillRule",
|
||||
"FontDisplay",
|
||||
"FontFaceSourceListComponent",
|
||||
"FontLanguageOverride",
|
||||
"TimingFunction",
|
||||
"PathCommand",
|
||||
"UnicodeRange",
|
||||
]
|
||||
item_types = ["enums", "structs", "typedefs"]
|
||||
|
|
|
@ -3,7 +3,7 @@ set -x -e -v
|
|||
|
||||
# If you update this, make sure to update the minimum version in
|
||||
# build/moz.configure/rust.configure and python/mozboot/mozboot/osx.py as well.
|
||||
CBINDGEN_VERSION=v0.6.6
|
||||
CBINDGEN_VERSION=v0.6.7
|
||||
TARGET="$1"
|
||||
|
||||
case "$(uname -s)" in
|
||||
|
|
|
@ -1410,8 +1410,8 @@ GeckoDriver.prototype.getWindowRect = async function() {
|
|||
* Set the window position and size of the browser on the operating
|
||||
* system window manager.
|
||||
*
|
||||
* The supplied |width| and |height| values refer to the window outerWidth
|
||||
* and outerHeight values, which include browser chrome and OS-level
|
||||
* The supplied `width` and `height` values refer to the window `outerWidth`
|
||||
* and `outerHeight` values, which include browser chrome and OS-level
|
||||
* window borders.
|
||||
*
|
||||
* @param {number} x
|
||||
|
@ -1426,7 +1426,7 @@ GeckoDriver.prototype.getWindowRect = async function() {
|
|||
* Height to resize the window to.
|
||||
*
|
||||
* @return {Object.<string, number>}
|
||||
* Object with |x| and |y| coordinates and |width| and |height|
|
||||
* Object with `x` and `y` coordinates and `width` and `height`
|
||||
* dimensions.
|
||||
*
|
||||
* @throws {UnsupportedOperationError}
|
||||
|
@ -2054,6 +2054,7 @@ GeckoDriver.prototype.findElement = async function(cmd) {
|
|||
*/
|
||||
GeckoDriver.prototype.findElements = async function(cmd) {
|
||||
const win = assert.open(this.getCurrentWindow());
|
||||
await this._handleUserPrompts();
|
||||
|
||||
let {using, value} = cmd.parameters;
|
||||
let startNode;
|
||||
|
@ -3228,6 +3229,8 @@ GeckoDriver.prototype._handleUserPrompts = async function() {
|
|||
return;
|
||||
}
|
||||
|
||||
let {textContent} = this.dialog.ui.infoBody;
|
||||
|
||||
let behavior = this.capabilities.get("unhandledPromptBehavior");
|
||||
switch (behavior) {
|
||||
case UnhandledPromptBehavior.Accept:
|
||||
|
@ -3236,7 +3239,8 @@ GeckoDriver.prototype._handleUserPrompts = async function() {
|
|||
|
||||
case UnhandledPromptBehavior.AcceptAndNotify:
|
||||
await this.acceptDialog();
|
||||
throw new UnexpectedAlertOpenError();
|
||||
throw new UnexpectedAlertOpenError(
|
||||
`Accepted user prompt dialog: ${textContent}`);
|
||||
|
||||
case UnhandledPromptBehavior.Dismiss:
|
||||
await this.dismissDialog();
|
||||
|
@ -3244,10 +3248,12 @@ GeckoDriver.prototype._handleUserPrompts = async function() {
|
|||
|
||||
case UnhandledPromptBehavior.DismissAndNotify:
|
||||
await this.dismissDialog();
|
||||
throw new UnexpectedAlertOpenError();
|
||||
throw new UnexpectedAlertOpenError(
|
||||
`Dismissed user prompt dialog: ${textContent}`);
|
||||
|
||||
case UnhandledPromptBehavior.Ignore:
|
||||
throw new UnexpectedAlertOpenError();
|
||||
throw new UnexpectedAlertOpenError(
|
||||
"Encountered unhandled user prompt dialog");
|
||||
|
||||
default:
|
||||
throw new TypeError(`Unknown unhandledPromptBehavior "${behavior}"`);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче