Update On Thu Nov 28 19:22:49 CET 2024

This commit is contained in:
github-action[bot] 2024-11-28 19:22:50 +01:00
parent 649568dd1a
commit 1542cc8cd0
1449 changed files with 19875 additions and 9246 deletions

View file

@ -24,7 +24,13 @@ export const editableFieldTemplate = ({
noteL10nId,
}) =>
html`
<label for="input" class="field-label" data-l10n-id=${labelL10nId}> </label>
<label
for="input"
class="field-label"
data-l10n-id=${labelL10nId}
tabindex="-1"
>
</label>
<input
id="input"
class="input-field"

View file

@ -13,8 +13,6 @@ class LoginOriginField extends MozLitElement {
required: { type: Boolean, reflect: true },
};
static formAssociated = true;
static queries = {
input: "input",
};
@ -24,14 +22,6 @@ class LoginOriginField extends MozLitElement {
this.value = "";
}
connectedCallback() {
super.connectedCallback();
this.internals.setFormValue(this.value);
this.addEventListener("input", e => {
this.internals.setFormValue(e.composedTarget.value);
});
}
addHTTPSPrefix(e) {
const input = e.composedTarget;
let originValue = input.value.trim();
@ -41,12 +31,6 @@ class LoginOriginField extends MozLitElement {
if (!originValue.match(/:\/\//)) {
input.value = "https://" + originValue;
input.dispatchEvent(
new InputEvent("input", {
composed: true,
bubbles: true,
})
);
}
}

View file

@ -10,45 +10,40 @@ class LoginPasswordField extends MozLitElement {
static CONCEALED_PASSWORD_TEXT = " ".repeat(8);
static properties = {
_value: { type: String, state: true },
value: { type: String },
name: { type: String },
readonly: { type: Boolean, reflect: true },
newPassword: { type: Boolean },
visible: { type: Boolean, reflect: true },
required: { type: Boolean, reflect: true },
onRevealClick: { type: Function },
};
static queries = {
input: "input",
button: "button",
label: "label",
button: "moz-button",
};
static formAssociated = true;
constructor() {
super();
this._value = "";
this.value = "";
}
connectedCallback() {
super.connectedCallback();
this.internals.setFormValue(this._value);
this.addEventListener("input", e => {
this.internals.setFormValue(e.composedTarget.value);
this.value = e.composedTarget.value;
});
}
set value(newValue) {
this._value = newValue;
}
get #type() {
return this.visible ? "text" : "password";
}
get #password() {
return this.readonly && !this.visible
return !this.newPassword && !this.visible
? LoginPasswordField.CONCEALED_PASSWORD_TEXT
: this._value;
: this.value;
}
#revealIconSrc(concealed) {
@ -57,6 +52,12 @@ class LoginPasswordField extends MozLitElement {
: "chrome://browser/content/aboutlogins/icons/password.svg";
}
updated(changedProperties) {
if (changedProperties.has("visible") && !changedProperties.visible) {
this.input.selectionStart = this.value.length;
}
}
render() {
return html`
${stylesTemplate()}
@ -78,28 +79,32 @@ class LoginPasswordField extends MozLitElement {
class="reveal-password-button"
type="icon ghost"
iconSrc=${this.#revealIconSrc(this.visible)}
@click=${this.toggleVisibility}
@mousedown=${() => {
/* Programmatically focus the button on mousedown instead of waiting for focus on click
* because the blur event occurs before the click event.
*/
this.button.focus();
}}
@click=${this.onRevealClick}
></moz-button>
`;
}
handleFocus(ev) {
if (ev.relatedTarget !== this.button) {
this.visible = true;
handleFocus() {
if (this.visible) {
return;
}
this.onRevealClick();
}
handleBlur(ev) {
if (ev.relatedTarget !== this.button) {
this.visible = false;
if (ev.relatedTarget === this.button || ev.relatedTarget === this.label) {
return;
}
}
toggleVisibility() {
this.visible = !this.visible;
if (this.visible) {
this.onPasswordVisible?.();
if (!this.visible) {
return;
}
this.onRevealClick();
}
}

View file

@ -13,8 +13,6 @@ class LoginUsernameField extends MozLitElement {
required: { type: Boolean, reflect: true },
};
static formAssociated = true;
static queries = {
input: "input",
};
@ -24,14 +22,6 @@ class LoginUsernameField extends MozLitElement {
this.value = "";
}
connectedCallback() {
super.connectedCallback();
this.internals.setFormValue(this.value);
this.addEventListener("input", e => {
this.internals.setFormValue(e.composedTarget.value);
});
}
render() {
return html`
${stylesTemplate()}

View file

@ -298,6 +298,7 @@ export const CustomizableWidgets = [
if (lazy.sidebarRevampEnabled) {
const { SidebarController } = aNode.ownerGlobal;
SidebarController.updateToolbarButton(aNode);
aNode.setAttribute("overflows", "false");
} else {
// Add an observer so the button is checked while the sidebar is open
let doc = aNode.ownerDocument;

View file

@ -315,10 +315,6 @@ add_task(async function construct_widget() {
add_task(async function insertBeforeFirstItemInOverflow() {
originalWindowWidth = window.outerWidth;
let sidebarRevampEnabled = Services.prefs.getBoolPref(
"sidebar.revamp",
false
);
ok(
!navbar.hasAttribute("overflowing"),
"Should start insertBeforeFirstItemInOverflow with a non-overflowing toolbar."
@ -328,6 +324,9 @@ add_task(async function insertBeforeFirstItemInOverflow() {
"Should start insertBeforeFirstItemInOverflow in default state."
);
// Remove sidebar button if present
CustomizableUI.removeWidgetFromArea("sidebar-button");
CustomizableUI.addWidgetToArea(
kLibraryButton,
"nav-bar",
@ -358,15 +357,9 @@ add_task(async function insertBeforeFirstItemInOverflow() {
);
window.resizeBy(resizeWidthToMakeLibraryLast, 0);
await TestUtils.waitForCondition(() => {
if (!sidebarRevampEnabled) {
return (
libraryButton.getAttribute("overflowedItem") == "true" &&
!libraryButton.previousElementSibling
);
}
return (
libraryButton.getAttribute("overflowedItem") == "true" &&
libraryButton.previousElementSibling?.id === "sidebar-button"
!libraryButton.previousElementSibling
);
});

View file

@ -17,7 +17,7 @@
}
.img-wrapper {
width: 127px;
width: 120px;
flex-shrink: 0;
flex-grow: 0;
aspect-ratio: 1/1;
@ -50,10 +50,11 @@
.meta {
padding: var(--space-xsmall) 0;
align-self: flex-start;
.info-wrap .title {
font-size: var(--font-size-small);
margin-bottom: 0;
margin-block: var(--space-xsmall) 0;
-webkit-line-clamp: 3;
}
@ -125,7 +126,7 @@
.title {
-webkit-line-clamp: 3;
font-size: var(--font-size-root);
margin-bottom: var(--space-small);
margin-block: 0 var(--space-small);
}
.excerpt {
@ -145,9 +146,15 @@
@media (min-width: $break-point-layout-variant ) and (max-width: $break-point-widest ),
(min-width: $break-point-sections-variant ) {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-columns: auto 1fr;
gap: var(--space-xlarge);
padding: var(--space-xxlarge);
align-items: center;
.img-wrapper {
width: 220px;
height: 220px;
}
.ds-image.img {
// Square ratio
@ -160,11 +167,14 @@
.meta {
padding: 0;
// match height of image for large cards
min-height: 220px;
.title {
-webkit-line-clamp: 3;
font-size: var(--font-size-large);
font-weight: var(--font-weight-bold);
margin-block: 0 var(--space-small);
}
.excerpt {
@ -345,10 +355,9 @@
.ds-section-grid.ds-card-grid {
grid-gap: var(--space-large);
grid-template-columns: repeat(1, 300px);
@media (min-width: $break-point-medium) {
grid-template-columns: repeat(1, 300px);
@for $i from 0 through 6 {
.col-1-position-#{$i} {
order: $i;

View file

@ -4563,11 +4563,9 @@ main section {
.ds-section-grid.ds-card-grid {
grid-gap: var(--space-large);
grid-template-columns: repeat(1, 300px);
}
@media (min-width: 610px) {
.ds-section-grid.ds-card-grid {
grid-template-columns: repeat(1, 300px);
}
.ds-section-grid.ds-card-grid .col-1-position-0 {
order: 0;
}
@ -4606,7 +4604,7 @@ main section {
display: none;
}
.ds-section-grid.ds-card-grid .col-1-small .img-wrapper {
width: 127px;
width: 120px;
flex-shrink: 0;
flex-grow: 0;
aspect-ratio: 1/1;
@ -4632,10 +4630,11 @@ main section {
}
.ds-section-grid.ds-card-grid .col-1-small .meta {
padding: var(--space-xsmall) 0;
align-self: flex-start;
}
.ds-section-grid.ds-card-grid .col-1-small .meta .info-wrap .title {
font-size: var(--font-size-small);
margin-bottom: 0;
margin-block: var(--space-xsmall) 0;
-webkit-line-clamp: 3;
}
.ds-section-grid.ds-card-grid .col-1-small .meta .info-wrap .excerpt {
@ -4689,7 +4688,7 @@ main section {
.ds-section-grid.ds-card-grid .col-1-medium .meta .info-wrap .title {
-webkit-line-clamp: 3;
font-size: var(--font-size-root);
margin-bottom: var(--space-small);
margin-block: 0 var(--space-small);
}
.ds-section-grid.ds-card-grid .col-1-medium .meta .info-wrap .excerpt {
display: block;
@ -4703,9 +4702,14 @@ main section {
@media (min-width: 610px) and (min-width: 724px) and (max-width: 1122px), (min-width: 610px) and (min-width: 1390px) {
.ds-section-grid.ds-card-grid .col-1-large.ds-card.sections-card-ui {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-columns: auto 1fr;
gap: var(--space-xlarge);
padding: var(--space-xxlarge);
align-items: center;
}
.ds-section-grid.ds-card-grid .col-1-large.ds-card.sections-card-ui .img-wrapper {
width: 220px;
height: 220px;
}
.ds-section-grid.ds-card-grid .col-1-large.ds-card.sections-card-ui .ds-image.img {
aspect-ratio: 1/1;
@ -4715,11 +4719,13 @@ main section {
}
.ds-section-grid.ds-card-grid .col-1-large.ds-card.sections-card-ui .meta {
padding: 0;
min-height: 220px;
}
.ds-section-grid.ds-card-grid .col-1-large.ds-card.sections-card-ui .meta .title {
-webkit-line-clamp: 3;
font-size: var(--font-size-large);
font-weight: var(--font-weight-bold);
margin-block: 0 var(--space-small);
}
.ds-section-grid.ds-card-grid .col-1-large.ds-card.sections-card-ui .meta .excerpt {
-webkit-line-clamp: 4;
@ -4768,7 +4774,7 @@ main section {
display: none;
}
.ds-section-grid.ds-card-grid .col-2-small .img-wrapper {
width: 127px;
width: 120px;
flex-shrink: 0;
flex-grow: 0;
aspect-ratio: 1/1;
@ -4794,10 +4800,11 @@ main section {
}
.ds-section-grid.ds-card-grid .col-2-small .meta {
padding: var(--space-xsmall) 0;
align-self: flex-start;
}
.ds-section-grid.ds-card-grid .col-2-small .meta .info-wrap .title {
font-size: var(--font-size-small);
margin-bottom: 0;
margin-block: var(--space-xsmall) 0;
-webkit-line-clamp: 3;
}
.ds-section-grid.ds-card-grid .col-2-small .meta .info-wrap .excerpt {
@ -4851,7 +4858,7 @@ main section {
.ds-section-grid.ds-card-grid .col-2-medium .meta .info-wrap .title {
-webkit-line-clamp: 3;
font-size: var(--font-size-root);
margin-bottom: var(--space-small);
margin-block: 0 var(--space-small);
}
.ds-section-grid.ds-card-grid .col-2-medium .meta .info-wrap .excerpt {
display: block;
@ -4865,9 +4872,14 @@ main section {
@media (min-width: 724px) and (min-width: 724px) and (max-width: 1122px), (min-width: 724px) and (min-width: 1390px) {
.ds-section-grid.ds-card-grid .col-2-large.ds-card.sections-card-ui {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-columns: auto 1fr;
gap: var(--space-xlarge);
padding: var(--space-xxlarge);
align-items: center;
}
.ds-section-grid.ds-card-grid .col-2-large.ds-card.sections-card-ui .img-wrapper {
width: 220px;
height: 220px;
}
.ds-section-grid.ds-card-grid .col-2-large.ds-card.sections-card-ui .ds-image.img {
aspect-ratio: 1/1;
@ -4877,11 +4889,13 @@ main section {
}
.ds-section-grid.ds-card-grid .col-2-large.ds-card.sections-card-ui .meta {
padding: 0;
min-height: 220px;
}
.ds-section-grid.ds-card-grid .col-2-large.ds-card.sections-card-ui .meta .title {
-webkit-line-clamp: 3;
font-size: var(--font-size-large);
font-weight: var(--font-weight-bold);
margin-block: 0 var(--space-small);
}
.ds-section-grid.ds-card-grid .col-2-large.ds-card.sections-card-ui .meta .excerpt {
-webkit-line-clamp: 4;
@ -4931,7 +4945,7 @@ main section {
display: none;
}
.ds-section-grid.ds-card-grid .col-3-small .img-wrapper {
width: 127px;
width: 120px;
flex-shrink: 0;
flex-grow: 0;
aspect-ratio: 1/1;
@ -4957,10 +4971,11 @@ main section {
}
.ds-section-grid.ds-card-grid .col-3-small .meta {
padding: var(--space-xsmall) 0;
align-self: flex-start;
}
.ds-section-grid.ds-card-grid .col-3-small .meta .info-wrap .title {
font-size: var(--font-size-small);
margin-bottom: 0;
margin-block: var(--space-xsmall) 0;
-webkit-line-clamp: 3;
}
.ds-section-grid.ds-card-grid .col-3-small .meta .info-wrap .excerpt {
@ -5014,7 +5029,7 @@ main section {
.ds-section-grid.ds-card-grid .col-3-medium .meta .info-wrap .title {
-webkit-line-clamp: 3;
font-size: var(--font-size-root);
margin-bottom: var(--space-small);
margin-block: 0 var(--space-small);
}
.ds-section-grid.ds-card-grid .col-3-medium .meta .info-wrap .excerpt {
display: block;
@ -5028,9 +5043,14 @@ main section {
@media (min-width: 1122px) and (min-width: 724px) and (max-width: 1122px), (min-width: 1122px) and (min-width: 1390px) {
.ds-section-grid.ds-card-grid .col-3-large.ds-card.sections-card-ui {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-columns: auto 1fr;
gap: var(--space-xlarge);
padding: var(--space-xxlarge);
align-items: center;
}
.ds-section-grid.ds-card-grid .col-3-large.ds-card.sections-card-ui .img-wrapper {
width: 220px;
height: 220px;
}
.ds-section-grid.ds-card-grid .col-3-large.ds-card.sections-card-ui .ds-image.img {
aspect-ratio: 1/1;
@ -5040,11 +5060,13 @@ main section {
}
.ds-section-grid.ds-card-grid .col-3-large.ds-card.sections-card-ui .meta {
padding: 0;
min-height: 220px;
}
.ds-section-grid.ds-card-grid .col-3-large.ds-card.sections-card-ui .meta .title {
-webkit-line-clamp: 3;
font-size: var(--font-size-large);
font-weight: var(--font-weight-bold);
margin-block: 0 var(--space-small);
}
.ds-section-grid.ds-card-grid .col-3-large.ds-card.sections-card-ui .meta .excerpt {
-webkit-line-clamp: 4;
@ -5093,7 +5115,7 @@ main section {
display: none;
}
.ds-section-grid.ds-card-grid .col-4-small .img-wrapper {
width: 127px;
width: 120px;
flex-shrink: 0;
flex-grow: 0;
aspect-ratio: 1/1;
@ -5119,10 +5141,11 @@ main section {
}
.ds-section-grid.ds-card-grid .col-4-small .meta {
padding: var(--space-xsmall) 0;
align-self: flex-start;
}
.ds-section-grid.ds-card-grid .col-4-small .meta .info-wrap .title {
font-size: var(--font-size-small);
margin-bottom: 0;
margin-block: var(--space-xsmall) 0;
-webkit-line-clamp: 3;
}
.ds-section-grid.ds-card-grid .col-4-small .meta .info-wrap .excerpt {
@ -5176,7 +5199,7 @@ main section {
.ds-section-grid.ds-card-grid .col-4-medium .meta .info-wrap .title {
-webkit-line-clamp: 3;
font-size: var(--font-size-root);
margin-bottom: var(--space-small);
margin-block: 0 var(--space-small);
}
.ds-section-grid.ds-card-grid .col-4-medium .meta .info-wrap .excerpt {
display: block;
@ -5190,9 +5213,14 @@ main section {
@media (min-width: 1390px) and (min-width: 724px) and (max-width: 1122px), (min-width: 1390px) and (min-width: 1390px) {
.ds-section-grid.ds-card-grid .col-4-large.ds-card.sections-card-ui {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-columns: auto 1fr;
gap: var(--space-xlarge);
padding: var(--space-xxlarge);
align-items: center;
}
.ds-section-grid.ds-card-grid .col-4-large.ds-card.sections-card-ui .img-wrapper {
width: 220px;
height: 220px;
}
.ds-section-grid.ds-card-grid .col-4-large.ds-card.sections-card-ui .ds-image.img {
aspect-ratio: 1/1;
@ -5202,11 +5230,13 @@ main section {
}
.ds-section-grid.ds-card-grid .col-4-large.ds-card.sections-card-ui .meta {
padding: 0;
min-height: 220px;
}
.ds-section-grid.ds-card-grid .col-4-large.ds-card.sections-card-ui .meta .title {
-webkit-line-clamp: 3;
font-size: var(--font-size-large);
font-weight: var(--font-weight-bold);
margin-block: 0 var(--space-small);
}
.ds-section-grid.ds-card-grid .col-4-large.ds-card.sections-card-ui .meta .excerpt {
-webkit-line-clamp: 4;

View file

@ -17,58 +17,64 @@ const PROFILE_THEMES_MAP = new Map([
toolbarColor: "#F9F9FB",
contentColor: "#FFFFFF",
},
isDark: false,
useInAutomation: true,
},
],
[
"expressionist-soft-colorway@mozilla.org",
"{b90acfd0-f0fc-4add-9195-f6306d25cdfa}",
{
dataL10nId: "profiles-marigold-theme",
downloadURL:
"https://addons.mozilla.org/firefox/downloads/file/4066185/expressionist_soft-2.1.xpi",
"https://addons.mozilla.org/firefox/downloads/file/4381985/marigold-1.9.xpi",
colors: {
chromeColor: "#F1CA52",
toolbarColor: "#FBDF8C",
contentColor: "#FEF7E0",
},
isDark: false,
},
],
[
"lush-soft-colorway@mozilla.org",
"{388d9fae-8a28-4f9f-9aad-fb9e84e4f3c3}",
{
dataL10nId: "profiles-lichen-theme",
downloadURL:
"https://addons.mozilla.org/firefox/downloads/file/4066281/lush_soft-2.1.xpi",
"https://addons.mozilla.org/firefox/downloads/file/4381979/lichen_soft-1.3.xpi",
colors: {
chromeColor: "#D2E4DA",
toolbarColor: "#E9F2EC",
contentColor: "#F5F9F7",
},
isDark: false,
},
],
[
"playmaker-soft-colorway@mozilla.org",
"{3ac3b0d7-f017-40e1-b142-a26f794e7015}",
{
dataL10nId: "profiles-magnolia-theme",
downloadURL:
"https://addons.mozilla.org/firefox/downloads/file/4066243/playmaker_soft-2.1.xpi",
"https://addons.mozilla.org/firefox/downloads/file/4381978/magnolia-1.1.xpi",
colors: {
chromeColor: "#FB5B9E",
toolbarColor: "#F986B6",
contentColor: "#FBE0ED",
},
isDark: false,
},
],
[
"dreamer-soft-colorway@mozilla.org",
"{ba48d251-0732-45c2-9f2f-39c68e82d047}",
{
dataL10nId: "profiles-lavender-theme",
downloadURL:
"https://addons.mozilla.org/firefox/downloads/file/4066182/dreamer_soft-2.1.xpi",
"https://addons.mozilla.org/firefox/downloads/file/4381983/lavender_soft-1.2.xpi",
colors: {
chromeColor: "#CDC1EA",
toolbarColor: "#EBE4FA",
contentColor: "#F4F0FD",
},
isDark: false,
},
],
[
@ -80,45 +86,50 @@ const PROFILE_THEMES_MAP = new Map([
toolbarColor: "#2B2A33",
contentColor: "#42414D",
},
isDark: true,
useInAutomation: true,
},
],
[
"activist-bold-colorway@mozilla.org",
"{750fa518-b61f-4068-9974-330dcf45442f}",
{
dataL10nId: "profiles-ocean-theme",
downloadURL:
"https://addons.mozilla.org/firefox/downloads/file/4066178/activist_bold-2.1.xpi",
"https://addons.mozilla.org/firefox/downloads/file/4381977/ocean_dark-1.1.xpi",
colors: {
chromeColor: "#080D33",
toolbarColor: "#050D5B",
contentColor: "#000511",
},
isDark: true,
},
],
[
"playmaker-bold-colorway@mozilla.org",
"{25b5a343-4238-4bae-b1f9-93a33f258167}",
{
dataL10nId: "profiles-terracotta-theme",
downloadURL:
"https://addons.mozilla.org/firefox/downloads/file/4066242/playmaker_bold-2.1.xpi",
"https://addons.mozilla.org/firefox/downloads/file/4381976/terracotta_dark-1.1.xpi",
colors: {
chromeColor: "#591305",
toolbarColor: "#98240B",
contentColor: "#060100",
},
isDark: true,
},
],
[
"elemental-bold-colorway@mozilla.org",
"{f9261f02-c03c-4352-92ee-78dd8b41ca98}",
{
dataL10nId: "profiles-moss-theme",
downloadURL:
"https://addons.mozilla.org/firefox/downloads/file/4066261/elemental_bold-2.1.xpi",
"https://addons.mozilla.org/firefox/downloads/file/4381975/moss_dark-1.1.xpi",
colors: {
chromeColor: "#405948",
toolbarColor: "#5B7B65",
contentColor: "#323433",
},
isDark: true,
},
],
[
@ -269,7 +280,13 @@ export class ProfilesParent extends JSWindowActorParent {
}
case "Profiles:UpdateProfileTheme": {
let themeId = message.data;
await this.enableTheme(themeId);
let gBrowser = this.browsingContext.topChromeWindow.gBrowser;
// Where the theme was installed from
let telemetryInfo = {
source: gBrowser.selectedBrowser.currentURI.displaySpec,
method: "url",
};
await this.enableTheme(themeId, telemetryInfo);
// The enable theme promise resolves after the
// "lightweight-theme-styling-update" observer so we know the profile
// theme is up to date at this point.
@ -289,11 +306,13 @@ export class ProfilesParent extends JSWindowActorParent {
return null;
}
async enableTheme(themeId) {
async enableTheme(themeId, telemetryInfo) {
let theme = await lazy.AddonManager.getAddonByID(themeId);
if (!theme) {
let themeUrl = PROFILE_THEMES_MAP.get(themeId).downloadURL;
let themeInstall = await lazy.AddonManager.getInstallForURL(themeUrl);
let themeInstall = await lazy.AddonManager.getInstallForURL(themeUrl, {
telemetryInfo,
});
await themeInstall.install();
theme = await lazy.AddonManager.getAddonByID(themeId);
}
@ -311,6 +330,8 @@ export class ProfilesParent extends JSWindowActorParent {
dataL10nId: themeObj.dataL10nId,
isActive: theme.isActive,
...themeObj.colors,
isDark: themeObj.isDark,
useInAutomation: themeObj?.useInAutomation,
});
} else {
themes.push({
@ -318,6 +339,8 @@ export class ProfilesParent extends JSWindowActorParent {
dataL10nId: themeObj.dataL10nId,
isActive: false,
...themeObj.colors,
isDark: themeObj.isDark,
useInAutomation: themeObj?.useInAutomation,
});
}
}

View file

@ -130,6 +130,15 @@ export class EditProfileCard extends MozLitElement {
this.initialized = true;
}
async getUpdateComplete() {
const result = await super.getUpdateComplete();
await Promise.all(
Array.from(this.themeCards).map(card => card.updateComplete)
);
return result;
}
setFavicon() {
let favicon = document.getElementById("favicon");
favicon.href = `chrome://browser/content/profiles/assets/16_${this.profile.avatar}.svg`;
@ -180,6 +189,12 @@ export class EditProfileCard extends MozLitElement {
return;
}
this.getUpdateComplete().then(() => {
for (let t of this.themeCards) {
t.selected = t.theme.id === newThemeId;
}
});
let theme = await RPMSendQuery("Profiles:UpdateProfileTheme", newThemeId);
this.profile.themeId = theme.themeId;
this.profile.themeFg = theme.themeFg;
@ -300,14 +315,7 @@ export class EditProfileCard extends MozLitElement {
}
handleThemeClick(event) {
for (let t of this.themeCards) {
t.selected = false;
}
let selectedTheme = event.target;
selectedTheme.selected = true;
this.updateTheme(selectedTheme.theme.id);
this.updateTheme(event.target.theme.id);
}
avatarsTemplate() {

View file

@ -9,6 +9,8 @@ import { EditProfileCard } from "chrome://browser/content/profiles/edit-profile-
// eslint-disable-next-line import/no-unassigned-import
import "chrome://global/content/elements/moz-support-link.mjs";
const DEFAULT_THEME_ID = "default-theme@mozilla.org";
/**
* Element used for updating a profile's name, theme, and avatar.
*/
@ -29,6 +31,8 @@ export class NewProfileCard extends EditProfileCard {
this.profiles = profiles;
this.themes = themes;
this.setRandomTheme(isInAutomation);
this.setInitialInput();
super.setFavicon();
@ -36,6 +40,21 @@ export class NewProfileCard extends EditProfileCard {
this.initialized = true;
}
async setRandomTheme(isInAutomation) {
if (this.profile.themeId !== DEFAULT_THEME_ID) {
return;
}
let isDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
let possibleThemes = this.themes.filter(t => t.isDark === isDark);
if (isInAutomation) {
possibleThemes = possibleThemes.filter(t => t.useInAutomation);
}
let newTheme =
possibleThemes[Math.floor(Math.random() * possibleThemes.length)];
super.updateTheme(newTheme.id);
}
async setInitialInput() {
if (RPMGetBoolPref("browser.profiles.profile-name.updated", false)) {
return;

View file

@ -7,10 +7,10 @@
async function verifySpoofed() {
ok(true, "Running on " + content.location.origin);
SpecialPowers.Cu.getJSTestingFunctions().setTimeZone("America/Los_Angeles");
SpecialPowers.Cu.getJSTestingFunctions().setTimeZone("PST8PDT");
is(
Intl.DateTimeFormat("en-US").resolvedOptions().timeZone,
"America/Los_Angeles",
"PST8PDT",
"Default time zone should have changed"
);
@ -113,10 +113,10 @@ add_task(async function test_timezone_exempt() {
});
await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
SpecialPowers.Cu.getJSTestingFunctions().setTimeZone("America/Los_Angeles");
SpecialPowers.Cu.getJSTestingFunctions().setTimeZone("PST8PDT");
is(
Intl.DateTimeFormat("en-US").resolvedOptions().timeZone,
"America/Los_Angeles",
"PST8PDT",
"Default time zone should have changed"
);
@ -129,7 +129,7 @@ add_task(async function test_timezone_exempt() {
is(
Intl.DateTimeFormat("en-US").resolvedOptions().timeZone,
"America/Los_Angeles",
"PST8PDT",
"Content should use default time zone"
);
}
@ -169,10 +169,10 @@ add_task(async function test_timezone_exempt_wrong_domain() {
});
add_task(async function test_timezone_exmpt_browser() {
SpecialPowers.Cu.getJSTestingFunctions().setTimeZone("America/Los_Angeles");
SpecialPowers.Cu.getJSTestingFunctions().setTimeZone("PST8PDT");
is(
Intl.DateTimeFormat("en-US").resolvedOptions().timeZone,
"America/Los_Angeles",
"PST8PDT",
"Default time zone should have changed"
);
@ -182,7 +182,7 @@ add_task(async function test_timezone_exmpt_browser() {
is(
Intl.DateTimeFormat("en-US").resolvedOptions().timeZone,
"America/Los_Angeles",
"PST8PDT",
"Timezone in chrome should be unaffected by resistFingerprinting"
);
@ -196,7 +196,7 @@ add_task(async function test_timezone_exmpt_browser() {
is(
newWindow.Intl.DateTimeFormat("en-US").resolvedOptions().timeZone,
"America/Los_Angeles",
"PST8PDT",
"Timezone in new chrome window should be unaffected by resistFingerprinting"
);

View file

@ -316,7 +316,10 @@ function createTabGroupSubmenu(aTabGroup, aIndex, aDocument, aFragment) {
"tab-context-reopen-tab-group"
);
reopenTabGroupItem.addEventListener("command", () => {
// TODO Bug 1932670: Session Restore support for restoring tab groups
lazy.SessionStore.restoreTabGroup({
closedTabGroupId: aTabGroup.id,
sourceWindowId: aDocument.ownerGlobal.__SSi,
});
});
menuPopup.appendChild(reopenTabGroupItem);
@ -391,7 +394,10 @@ function createTabGroupSubpanel(aTabGroup, aIndex, aDocument, aFragment) {
"panel-subview-footer-button"
);
reopenTabGroupItem.addEventListener("command", () => {
// TODO Bug 1932670: Session Restore support for restoring tab groups
lazy.SessionStore.restoreTabGroup({
closedTabGroupId: aTabGroup.id,
sourceWindowId: aDocument.ownerGlobal.__SSi,
});
});
panelview.appendChild(reopenTabGroupItem);

View file

@ -7594,6 +7594,8 @@ var SessionStoreInternal = {
);
}
let tabDataList = tabGroupData.tabs.map(tab => tab.state);
if (targetWindow && !targetWindow.__SSi) {
throw Components.Exception(
"Target window is not tracked",
@ -7607,11 +7609,11 @@ var SessionStoreInternal = {
let tabs = targetWindow.gBrowser.createTabsForSessionRestore(
true,
0, // TODO Bug 1933113 - Save tab group position and selected tab with saved tab group data
tabGroupData.tabs,
tabDataList,
[tabGroupData]
);
this.restoreTabs(targetWindow, tabs, tabGroupData.tabs, 0);
this.restoreTabs(targetWindow, tabs, tabDataList, 0);
if (source.savedTabGroupId) {
this.forgetSavedTabGroup(source.savedTabGroupId);

View file

@ -133,7 +133,7 @@ static nsresult PinCurrentAppToTaskbarWin10(bool aCheckOnly,
const nsAString& aAppUserModelId,
const nsAString& aShortcutPath);
static nsresult WriteBitmap(nsIFile* aFile, imgIContainer* aImage);
static nsresult WriteIcon(nsIFile* aIcoFile, imgIContainer* aImage);
static nsresult WriteIcon(nsIFile* aIcoFile, gfx::DataSourceSurface* aSurface);
static nsresult OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName,
HKEY* aKey) {
@ -462,16 +462,29 @@ nsWindowsShellService::CreateWindowsIcon(nsIFile* aIcoFile,
auto promiseHolder = MakeRefPtr<nsMainThreadPtrHolder<dom::Promise>>(
"CreateWindowsIcon promise", promise);
MOZ_LOG(sLog, LogLevel::Debug,
("%s:%d - Reading input image...\n", __FILE__, __LINE__));
RefPtr<gfx::SourceSurface> surface = aImage->GetFrame(
imgIContainer::FRAME_FIRST, imgIContainer::FLAG_SYNC_DECODE);
NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
// At time of writing only `DataSourceSurface` was guaranteed thread safe. We
// need this guarantee to write the icon file off the main thread.
RefPtr<gfx::DataSourceSurface> dataSurface = surface->GetDataSurface();
NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
MOZ_LOG(sLog, LogLevel::Debug,
("%s:%d - Surface found, writing icon... \n", __FILE__, __LINE__));
NS_DispatchBackgroundTask(
NS_NewRunnableFunction(
"CreateWindowsIcon",
[icoFile = nsCOMPtr<nsIFile>(aIcoFile),
image = nsCOMPtr<imgIContainer>(aImage),
promiseHolder = std::move(promiseHolder)] {
nsresult rv = WriteIcon(icoFile, image);
[icoFile = nsCOMPtr<nsIFile>(aIcoFile), dataSurface, promiseHolder] {
nsresult rv = WriteIcon(icoFile, dataSurface);
NS_DispatchToMainThread(NS_NewRunnableFunction(
"CreateWindowsIcon callback",
[rv, promiseHolder = std::move(promiseHolder)] {
"CreateWindowsIcon callback", [rv, promiseHolder] {
dom::Promise* promise = promiseHolder.get()->get();
if (NS_SUCCEEDED(rv)) {
@ -487,28 +500,19 @@ nsWindowsShellService::CreateWindowsIcon(nsIFile* aIcoFile,
return NS_OK;
}
static nsresult WriteIcon(nsIFile* aIcoFile, imgIContainer* aImage) {
MOZ_LOG(sLog, LogLevel::Debug,
("%s:%d - Reading input image...\n", __FILE__, __LINE__));
static nsresult WriteIcon(nsIFile* aIcoFile, gfx::DataSourceSurface* aSurface) {
NS_ENSURE_ARG(aIcoFile);
NS_ENSURE_ARG(aSurface);
RefPtr<gfx::SourceSurface> surface = aImage->GetFrame(
imgIContainer::FRAME_FIRST, imgIContainer::FLAG_SYNC_DECODE);
NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
MOZ_LOG(sLog, LogLevel::Debug,
("%s:%d - Surface found, writing icon... \n", __FILE__, __LINE__));
const gfx::IntSize size = surface->GetSize();
const gfx::IntSize size = aSurface->GetSize();
if (size.IsEmpty()) {
MOZ_LOG(sLog, LogLevel::Debug,
("%s:%d - The input image looks empty :(\n", __FILE__, __LINE__));
return NS_ERROR_FAILURE;
}
RefPtr<gfx::DataSourceSurface> dataSurface = surface->GetDataSurface();
NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
int32_t width = dataSurface->GetSize().width;
int32_t height = dataSurface->GetSize().height;
int32_t width = aSurface->GetSize().width;
int32_t height = aSurface->GetSize().height;
MOZ_LOG(sLog, LogLevel::Debug,
("%s:%d - Input image dimensions are: %dx%d pixels\n", __FILE__,
@ -523,14 +527,12 @@ static nsresult WriteIcon(nsIFile* aIcoFile, imgIContainer* aImage) {
ScopedCloseFile file;
nsresult rv = aIcoFile->OpenANSIFileDesc("wb", getter_Transfers(file));
if (NS_FAILED(rv)) {
return rv;
}
NS_ENSURE_SUCCESS(rv, rv);
MOZ_LOG(sLog, LogLevel::Debug,
("%s:%d - Writing icon...\n", __FILE__, __LINE__));
rv = gfxUtils::EncodeSourceSurface(surface, ImageType::ICO, u""_ns,
rv = gfxUtils::EncodeSourceSurface(aSurface, ImageType::ICO, u""_ns,
gfxUtils::eBinaryEncode, file.get());
if (NS_FAILED(rv)) {

View file

@ -356,6 +356,7 @@ var SidebarController = {
!window.toolbar.visible ||
(this.sidebarRevampVisibility === "hide-sidebar" && !this.isOpen);
document.getElementById("sidebar-header").hidden = true;
this._updateTabbrowser();
if (!this._mainResizeObserverAdded) {
this._mainResizeObserver.observe(this.sidebarMain);
this._mainResizeObserverAdded = true;
@ -430,7 +431,6 @@ var SidebarController = {
this.setUIState(backupState);
}
});
this._initDeferred.resolve();
},
@ -548,6 +548,7 @@ var SidebarController = {
}
this.updateToolbarButton();
this._updateLauncherWidth();
this._updateTabbrowser();
}
this.uiStateInitialized = true;
},
@ -640,6 +641,12 @@ var SidebarController = {
}
},
_updateTabbrowser() {
document
.getElementById("tabbrowser-tabbox")
.toggleAttribute("sidebar-shown", !this.sidebarContainer.hidden);
},
hideSwitcherPanel() {
this._switcherPanel.hidePopup();
},
@ -996,6 +1003,8 @@ var SidebarController = {
this.toggleExpanded(true);
}
this.sidebarContainer.hidden = !isHidden;
this._updateTabbrowser();
},
async _animateSidebarMain() {

View file

@ -65,7 +65,7 @@ function getExpectedElements(win, tabstripOrientation = "horizontal") {
if (win.TabsInTitlebar.enabled) {
selectors.push("#nav-bar .titlebar-buttonbox-container");
if (sizeMode == "normal") {
selectors.push("#nav-bar .titlebar-spacer");
selectors.push("#nav-bar .titlebar-spacer[type='post-tabs']");
}
}
return selectors;

View file

@ -8106,14 +8106,12 @@ var TabBarVisibility = {
TabsInTitlebar.enabled && hideTabstrip
);
for (let id of ["sidebar-main", "sidebar-box"]) {
document
.getElementById(id)
.classList.toggle(
"browser-toolbox-background",
TabsInTitlebar.enabled && nonPopupWithVerticalTabs
);
}
document
.getElementById("browser")
.classList.toggle(
"browser-toolbox-background",
TabsInTitlebar.enabled && nonPopupWithVerticalTabs
);
if (
hideTabstrip == toolbar.collapsed &&

View file

@ -16,6 +16,10 @@ ChromeUtils.defineESModuleGetters(lazy, {
// List of prepositions used in subject cleaning.
const PREPOSITIONS = ["in", "at", "on", "for", "to", "near"];
const MAX_QUERY_LENGTH = 200;
const NAME_PUNCTUATION = [".", "-", "'"];
const NAME_PUNCTUATION_EXCEPT_DOT = NAME_PUNCTUATION.filter(p => p !== ".");
/**
* Class for handling ML-based suggestions using intent and NER models.
*
@ -63,7 +67,7 @@ class _MLSuggest {
* The user's input query.
* @returns {object | null}
* The suggestion result including intent, location, and subject, or null if
* an error occurs.
* an error occurs or query length > MAX_QUERY_LENGTH
* {string} intent
* The predicted intent label of the query. Possible values include:
* - 'information_intent': For queries seeking general information.
@ -87,6 +91,11 @@ class _MLSuggest {
* information about the model's performance.
*/
async makeSuggestions(query) {
// avoid bunch of work for very long strings
if (query.length > MAX_QUERY_LENGTH) {
return null;
}
let intentRes, nerResult;
try {
[intentRes, nerResult] = await Promise.all([
@ -253,51 +262,34 @@ class _MLSuggest {
for (let i = 0; i < nerResult.length; i++) {
const res = nerResult[i];
// Handle B-CITY, I-CITY
if (
(res.entity === "B-CITY" || res.entity === "I-CITY") &&
res.score > nerThreshold
) {
if (res.word.startsWith("##") && cityResult.length) {
cityResult[cityResult.length - 1] += res.word.slice(2);
} else {
cityResult.push(res.word);
}
}
// Handle B-STATE, I-STATE
else if (
(res.entity === "B-STATE" || res.entity === "I-STATE") &&
res.score > nerThreshold
) {
if (res.word.startsWith("##") && stateResult.length) {
stateResult[stateResult.length - 1] += res.word.slice(2);
} else {
stateResult.push(res.word);
}
}
// Handle B-CITYSTATE, I-CITYSTATE
else if (
(res.entity === "B-CITYSTATE" || res.entity === "I-CITYSTATE") &&
res.score > nerThreshold
) {
if (res.word.startsWith("##") && cityStateResult.length) {
cityStateResult[cityStateResult.length - 1] += res.word.slice(2);
} else {
cityStateResult.push(res.word);
}
if (res.entity === "B-CITY" || res.entity === "I-CITY") {
this.#processNERToken(res, cityResult, nerThreshold);
} else if (res.entity === "B-STATE" || res.entity === "I-STATE") {
this.#processNERToken(res, stateResult, nerThreshold);
} else if (res.entity === "B-CITYSTATE" || res.entity === "I-CITYSTATE") {
this.#processNERToken(res, cityStateResult, nerThreshold);
}
}
// Handle city_state as combined and split into city and state
if (cityStateResult.length) {
if (cityStateResult.length && !cityResult.length && !stateResult.length) {
let cityStateSplit = cityStateResult.join(" ").split(",");
return {
city: cityStateSplit[0]?.trim() || null,
state: cityStateSplit[1]?.trim() || null,
};
cityResult =
cityStateSplit[0]
?.trim?.()
.split(",")
.filter(item => item.trim() !== "") || [];
stateResult =
cityStateSplit[1]
?.trim?.()
.split(",")
.filter(item => item.trim() !== "") || [];
}
// Remove trailing punctuation from the last cityResult element if present
this.#removePunctFromEndIfPresent(cityResult);
this.#removePunctFromEndIfPresent(stateResult);
// Return city and state as separate components if detected
return {
city: cityResult.join(" ").trim() || null,
@ -305,6 +297,74 @@ class _MLSuggest {
};
}
/**
* Processes a token from the NER results, appending it to the provided result
* array while handling wordpieces (e.g., "##"), punctuation, and
* multi-token entities.
*
* - Appends wordpieces (starting with "##") to the last token in the array.
* - Handles punctuation tokens like ".", "-", or "'".
* - Ensures continuity for entities split across multiple tokens.
*
* @param {object} res
* The NER result token to process. Should include:
* - {string} word: The word or token from the NER output.
* - {number} score: The confidence score for the token.
* - {string} entity: The entity type label (e.g., "B-CITY", "I-STATE").
* @param {string[]} resultArray
* The array to append the processed token. Typically `cityResult`,
* `stateResult`, or `cityStateResult`.
* @param {number} nerThreshold
* The confidence threshold for including tokens. Tokens with a score below
* this threshold will be ignored.
*/
async #processNERToken(res, resultArray, nerThreshold) {
// Skip low-confidence tokens
if (res.score <= nerThreshold) {
return;
}
const lastTokenIndex = resultArray.length - 1;
// "##" prefix indicates that a token is continuation of a word
// rather than a start of a new word.
// reference -> https://github.com/google-research/bert/blob/master/tokenization.py#L314-L316
if (res.word.startsWith("##") && resultArray.length) {
resultArray[lastTokenIndex] += res.word.slice(2);
} else if (
resultArray.length &&
(NAME_PUNCTUATION.includes(res.word) ||
NAME_PUNCTUATION_EXCEPT_DOT.includes(
resultArray[lastTokenIndex].slice(-1)
))
) {
// Special handling for punctuation like ".", "-", or "'"
resultArray[lastTokenIndex] += res.word;
} else {
resultArray.push(res.word);
}
}
/**
* Removes trailing punctuation from the last element in the result array
* if the last character matches any punctuation in `NAME_PUNCTUATION`.
*
* This method is useful for cleaning up city or state tokens that may
* contain unwanted punctuation after processing NER results.
*
* @param {string[]} resultArray
* An array of strings representing detected entities (e.g., cities or states).
* The array is modified in place if the last element ends with punctuation.
*/
async #removePunctFromEndIfPresent(resultArray) {
const lastTokenIndex = resultArray.length - 1;
if (
resultArray.length &&
NAME_PUNCTUATION.includes(resultArray[lastTokenIndex].slice(-1))
) {
resultArray[lastTokenIndex] = resultArray[lastTokenIndex].slice(0, -1);
}
}
#findSubjectFromQuery(query, location) {
// If location is null or no city/state, return the entire query
if (!location || (!location.city && !location.state)) {
@ -313,10 +373,19 @@ class _MLSuggest {
// Remove the city and state values from the query
let locValues = Object.values(location).filter(v => !!v);
// Regular expression to remove locations
// This handles single & multi-worded cities/states
let locPattern = locValues
.map(loc => `\\b${loc.replace(/[-/\\^$*+?.()|[\]{}]'/g, "\\$&")}\\b`)
.join("|");
let locRegex = new RegExp(locPattern, "g");
// Remove locations, trim whitespace, and split words
let words = query
.trim()
.split(/\s+|,/)
.filter(w => !!w && !locValues.includes(w));
.replace(locRegex, "")
.split(/\W+/)
.filter(word => !!word.length);
let subjectWords = this.#cleanSubject(words);
return subjectWords.join(" ");

View file

@ -15,157 +15,169 @@ Services.scriptloader.loadSubScript(
this
);
let nerResultsMap = {
let nerResultsMap = {};
function getNerResult(query, nerExample) {
nerResultsMap[query] = nerExample.map(
([entity, index, word, score = 0.999]) => ({
entity,
index,
word,
score,
})
);
}
let nerExamples = {
"restaurants in seattle, wa": [
{
entity: "B-CITYSTATE",
score: 0.9999846816062927,
index: 3,
word: "seattle",
},
{
entity: "I-CITYSTATE",
score: 0.9999918341636658,
index: 4,
word: ",",
},
{
entity: "I-CITYSTATE",
score: 0.9999667406082153,
index: 5,
word: "wa",
},
["B-CITYSTATE", 3, "seattle"],
["I-CITYSTATE", 4, ","],
["I-CITYSTATE", 5, "wa"],
],
"hotels in new york, ny": [
{
entity: "B-CITYSTATE",
score: 0.999022364616394,
index: 3,
word: "new",
},
{
entity: "I-CITYSTATE",
score: 0.9999206066131592,
index: 4,
word: "york",
},
{
entity: "I-CITYSTATE",
score: 0.9999917149543762,
index: 5,
word: ",",
},
{
entity: "I-CITYSTATE",
score: 0.9999532103538513,
index: 6,
word: "ny",
},
],
"restaurants seattle": [
{
entity: "B-CITY",
score: 0.9980050921440125,
index: 2,
word: "seattle",
},
],
"restaurants in seattle": [
{
entity: "B-CITY",
score: 0.9980319738388062,
index: 3,
word: "seattle",
},
],
"restaurants near seattle": [
{
entity: "B-CITY",
score: 0.998751163482666,
index: 3,
word: "seattle",
},
],
"seattle restaurants": [
{
entity: "B-CITY",
score: 0.8563504219055176,
index: 1,
word: "seattle",
},
["B-CITYSTATE", 3, "new"],
["I-CITYSTATE", 4, "york"],
["I-CITYSTATE", 5, ","],
["I-CITYSTATE", 6, "ny"],
],
"restaurants seattle": [["B-CITY", 2, "seattle"]],
"restaurants in seattle": [["B-CITY", 3, "seattle"]],
"restaurants near seattle": [["B-CITY", 3, "seattle"]],
"seattle restaurants": [["B-CITY", 1, "seattle"]],
"seattle wa restaurants": [
{
entity: "B-CITY",
score: 0.5729296207427979,
index: 1,
word: "seattle",
},
{
entity: "B-STATE",
score: 0.7850125432014465,
index: 2,
word: "wa",
},
["B-CITY", 1, "seattle"],
["B-STATE", 2, "wa"],
],
"seattle, wa restaurants": [
{
entity: "B-CITYSTATE",
score: 0.9999499320983887,
index: 1,
word: "seattle",
},
{
entity: "I-CITYSTATE",
score: 0.9999974370002747,
index: 2,
word: ",",
},
{
entity: "I-CITYSTATE",
score: 0.9999855160713196,
index: 3,
word: "wa",
},
["B-CITYSTATE", 1, "seattle"],
["I-CITYSTATE", 2, ","],
["I-CITYSTATE", 3, "wa"],
],
"dumplings in ca": [
{
entity: "B-STATE",
score: 0.998980700969696,
index: 4,
word: "ca",
},
"dumplings in ca": [["B-STATE", 4, "ca"]],
"ramen ra": [["B-CITY", 3, "ra"]],
"ra ramen": [["B-CITY", 1, "ra"]],
"ramen st. louis": [
["B-CITY", 3, "st"],
["I-CITY", 4, "."],
["I-CITY", 5, "louis"],
],
"ramen ra": [
{
entity: "B-CITY",
score: 0.6767462491989136,
index: 3,
word: "ra",
},
"st. louis ramen": [
["B-CITY", 1, "st"],
["I-CITY", 2, "."],
["I-CITY", 3, "louis"],
],
"ramen winston-salem": [
["B-CITY", 3, "winston"],
["I-CITY", 4, "-"],
["I-CITY", 5, "salem"],
],
"winston-salem ramen": [
["B-CITY", 1, "winston"],
["I-CITY", 2, "-"],
["I-CITY", 3, "salem"],
],
"ramen hawai'i": [
["B-CITY", 3, "ha"],
["I-CITY", 4, "##wai"],
["I-CITY", 5, "'"],
["I-CITY", 6, "i"],
],
"hawai'i ramen": [
["B-CITY", 1, "ha"],
["I-CITY", 2, "##wai"],
["I-CITY", 3, "'"],
["I-CITY", 4, "i"],
],
"cafe in ca": [["B-STATE", 3, "ca"]],
"ramen noodles ra ca": [
["B-CITY", 4, "ra"],
["B-STATE", 5, "ca"],
],
"ra ca ramen noodles": [
["B-CITY", 1, "ra"],
["B-STATE", 2, "ca"],
],
"plumbers in seattle,wa": [
{
entity: "B-CITYSTATE",
index: 4,
score: 0.99997478723526,
word: "seattle",
},
{
entity: "I-CITYSTATE",
index: 5,
score: 0.9999989867210388,
word: ",",
},
{
entity: "I-CITYSTATE",
index: 6,
score: 0.9999985098838806,
word: "wa",
},
["B-CITYSTATE", 4, "seattle"],
["I-CITYSTATE", 5, ","],
["I-CITYSTATE", 6, "wa"],
],
"cafe in san francisco": [
["B-CITY", 3, "san"],
["I-CITY", 4, "francisco"],
],
"san francisco cafe": [
["B-CITY", 1, "san"],
["I-CITY", 2, "francisco"],
],
"cafe in st. louis": [
["B-CITY", 3, "st"],
["I-CITY", 4, "."],
["I-CITY", 5, "louis"],
],
"st. louis cafe": [
["B-CITY", 1, "st"],
["I-CITY", 2, "."],
["I-CITY", 3, "louis"],
],
"cafe in winston-salem": [
["B-CITY", 3, "winston"],
["I-CITY", 4, "-"],
["I-CITY", 5, "salem"],
],
"winston-salem cafe": [
["B-CITY", 1, "winston"],
["I-CITY", 2, "-"],
["I-CITY", 3, "salem"],
],
"cafe in winston-": [
["B-CITY", 3, "winston"],
["I-CITY", 4, "-"],
],
"cafe in hawai'i": [
["B-CITY", 3, "ha"],
["I-CITY", 4, "##wai"],
["I-CITY", 5, "'"],
["I-CITY", 6, "i"],
],
"hawai'i cafe": [
["B-CITY", 1, "ha"],
["I-CITY", 2, "##wai"],
["I-CITY", 3, "'"],
["I-CITY", 4, "i"],
],
"cafe in san francisco, ca": [
["B-ORG", 1, "cafe"],
["B-CITYSTATE", 3, "san"],
["I-CITYSTATE", 4, "francisco"],
["I-CITYSTATE", 5, ","],
["I-CITYSTATE", 6, "ca"],
],
"cafe in sf": [["B-CITY", 3, "sf"]],
"cafe in san francisco,ca": [
["B-ORG", 1, "cafe"],
["B-CITYSTATE", 3, "san"],
["I-CITYSTATE", 4, "francisco"],
["I-CITYSTATE", 5, ","],
["I-CITYSTATE", 6, "ca"],
],
"cafe in san francisco,ca-": [
["B-ORG", 1, "cafe"],
["B-CITYSTATE", 3, "san"],
["I-CITYSTATE", 4, "francisco"],
["I-CITYSTATE", 5, ","],
["I-CITYSTATE", 6, "ca"],
["I-CITYSTATE", 7, "-"],
],
"cafe in ca-": [
["B-STATE", 4, "ca"],
["I-STATE", 5, "-"],
],
};
for (const [query, nerExample] of Object.entries(nerExamples)) {
getNerResult(query, nerExample);
}
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [
@ -414,6 +426,33 @@ class MLEngineWithHighYelpIntent {
}
}
// utility function for asserting suggestion
async function checkSuggestion(query, expected) {
let suggestion = await MLSuggest.makeSuggestions(query);
Assert.ok(suggestion, "Suggestion should be good");
Assert.deepEqual(suggestion.intent, expected.intent);
Assert.deepEqual(suggestion.location, expected.location);
Assert.deepEqual(suggestion.subject, expected.subject);
}
// utility to prepare queriesAndExpectations
function prepQueriesAndExpectations(
queryVal,
intentVal,
cityVal,
stateVal,
subjectVal
) {
return {
query: queryVal,
expected: {
intent: intentVal,
location: { city: cityVal, state: stateVal },
subject: subjectVal,
},
};
}
add_task(async function test_MLSuggest_city_dup_in_subject() {
// Restore any previous stubs
sinon.restore();
@ -428,16 +467,70 @@ add_task(async function test_MLSuggest_city_dup_in_subject() {
await MLSuggest.initialize();
let suggestion = await MLSuggest.makeSuggestions("ramen ra");
Assert.ok(suggestion, "Suggestion should be good");
const expected = {
intent: "yelp_intent",
location: { city: "ra", state: null },
subject: "ramen",
};
Assert.deepEqual(suggestion.intent, expected.intent);
Assert.deepEqual(suggestion.location, expected.location);
Assert.deepEqual(suggestion.subject, expected.subject);
// syntax for test_examples [[query, intent, city, state, subject]]
let testExamples = [
["ramen ra", "yelp_intent", "ra", null, "ramen"],
["ra ramen", "yelp_intent", "ra", null, "ramen"],
["ramen st. louis", "yelp_intent", "st. louis", null, "ramen"],
["st. louis ramen", "yelp_intent", "st. louis", null, "ramen"],
["ramen winston-salem", "yelp_intent", "winston-salem", null, "ramen"],
["winston-salem ramen", "yelp_intent", "winston-salem", null, "ramen"],
["ramen hawai'i", "yelp_intent", "hawai'i", null, "ramen"],
["hawai'i ramen", "yelp_intent", "hawai'i", null, "ramen"],
["cafe in ca", "yelp_intent", null, "ca", "cafe"],
["ramen noodles ra ca", "yelp_intent", "ra", "ca", "ramen noodles"],
["ra ca ramen noodles", "yelp_intent", "ra", "ca", "ramen noodles"],
];
let queriesAndExpectations = testExamples.map(args =>
prepQueriesAndExpectations(...args)
);
for (const { query, expected } of queriesAndExpectations) {
checkSuggestion(query, expected);
}
await MLSuggest.shutdown();
await EngineProcess.destroyMLEngine();
await cleanup();
sinon.restore();
});
add_task(async function test_MLSuggest_location_and_subject() {
// Restore any previous stubs
sinon.restore();
sinon.stub(MLSuggest, "createEngine").callsFake(() => {
return new MLEngineWithHighYelpIntent();
});
sinon.stub(MLSuggest, "_findNER").callsFake(query => {
return nerResultsMap[query] || [];
});
const { cleanup } = await setup();
await MLSuggest.initialize();
// syntax for test_examples [[query, intent, city, state, subject]]
let testExamples = [
["cafe in san francisco", "yelp_intent", "san francisco", null, "cafe"],
["san francisco cafe", "yelp_intent", "san francisco", null, "cafe"],
["cafe in st. louis", "yelp_intent", "st. louis", null, "cafe"],
["cafe in winston-salem", "yelp_intent", "winston-salem", null, "cafe"],
["st. louis cafe", "yelp_intent", "st. louis", null, "cafe"],
["winston-salem cafe", "yelp_intent", "winston-salem", null, "cafe"],
["cafe in winston-", "yelp_intent", "winston", null, "cafe"],
["cafe in hawai'i", "yelp_intent", "hawai'i", null, "cafe"],
["hawai'i cafe", "yelp_intent", "hawai'i", null, "cafe"],
["cafe in san francisco, ca", "yelp_intent", "san francisco", "ca", "cafe"],
["cafe in sf", "yelp_intent", "sf", null, "cafe"],
["cafe in san francisco,ca", "yelp_intent", "san francisco", "ca", "cafe"],
["cafe in san francisco,ca-", "yelp_intent", "san francisco", "ca", "cafe"],
["cafe in ca-", "yelp_intent", null, "ca", "cafe"],
];
let queriesAndExpectations = testExamples.map(args =>
prepQueriesAndExpectations(...args)
);
for (const { query, expected } of queriesAndExpectations) {
checkSuggestion(query, expected);
}
await MLSuggest.shutdown();
await EngineProcess.destroyMLEngine();

View file

@ -270,6 +270,13 @@ root-certificate-succession-infobar-secondary-button =
.label = Later
.accesskey = L
## Root Certificate Succession Windows Background Notification
root-certificate-windows-background-notification-title = You missed an important { -brand-short-name } update
root-certificate-windows-background-notification-subtitle = Parts of the browser will stop working soon if you dont update. Now is a great time to get our latest protections and features.
root-certificate-windows-background-notification-learn-more-button = Learn more
root-certificate-windows-background-notification-update-button = Update { -brand-short-name }
## FxA Menu Message variants
fxa-menu-message-close-button =

View file

@ -16,7 +16,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"af": {
"pin": false,
@ -35,7 +35,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"an": {
"pin": false,
@ -54,7 +54,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ar": {
"pin": false,
@ -73,7 +73,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ast": {
"pin": false,
@ -92,7 +92,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"az": {
"pin": false,
@ -111,7 +111,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"be": {
"pin": false,
@ -130,7 +130,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"bg": {
"pin": false,
@ -149,7 +149,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"bn": {
"pin": false,
@ -168,7 +168,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"bo": {
"pin": false,
@ -187,7 +187,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"br": {
"pin": false,
@ -206,7 +206,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"brx": {
"pin": false,
@ -225,7 +225,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"bs": {
"pin": false,
@ -244,7 +244,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ca": {
"pin": false,
@ -263,7 +263,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ca-valencia": {
"pin": false,
@ -282,7 +282,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"cak": {
"pin": false,
@ -301,7 +301,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ckb": {
"pin": false,
@ -320,7 +320,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"cs": {
"pin": false,
@ -339,7 +339,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"cy": {
"pin": false,
@ -358,7 +358,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"da": {
"pin": false,
@ -377,7 +377,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"de": {
"pin": false,
@ -396,7 +396,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"dsb": {
"pin": false,
@ -415,7 +415,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"el": {
"pin": false,
@ -434,7 +434,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"en-CA": {
"pin": false,
@ -453,7 +453,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"en-GB": {
"pin": false,
@ -472,7 +472,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"eo": {
"pin": false,
@ -491,7 +491,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"es-AR": {
"pin": false,
@ -510,7 +510,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"es-CL": {
"pin": false,
@ -529,7 +529,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"es-ES": {
"pin": false,
@ -548,7 +548,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"es-MX": {
"pin": false,
@ -567,7 +567,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"et": {
"pin": false,
@ -586,7 +586,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"eu": {
"pin": false,
@ -605,7 +605,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"fa": {
"pin": false,
@ -624,7 +624,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ff": {
"pin": false,
@ -643,7 +643,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"fi": {
"pin": false,
@ -662,7 +662,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"fr": {
"pin": false,
@ -681,7 +681,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"fur": {
"pin": false,
@ -700,7 +700,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"fy-NL": {
"pin": false,
@ -719,7 +719,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ga-IE": {
"pin": false,
@ -738,7 +738,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"gd": {
"pin": false,
@ -757,7 +757,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"gl": {
"pin": false,
@ -776,7 +776,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"gn": {
"pin": false,
@ -795,7 +795,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"gu-IN": {
"pin": false,
@ -814,7 +814,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"he": {
"pin": false,
@ -833,7 +833,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"hi-IN": {
"pin": false,
@ -852,7 +852,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"hr": {
"pin": false,
@ -871,7 +871,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"hsb": {
"pin": false,
@ -890,7 +890,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"hu": {
"pin": false,
@ -909,7 +909,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"hy-AM": {
"pin": false,
@ -928,7 +928,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"hye": {
"pin": false,
@ -947,7 +947,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ia": {
"pin": false,
@ -966,7 +966,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"id": {
"pin": false,
@ -985,7 +985,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"is": {
"pin": false,
@ -1004,7 +1004,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"it": {
"pin": false,
@ -1023,7 +1023,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ja": {
"pin": false,
@ -1040,7 +1040,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ja-JP-mac": {
"pin": false,
@ -1048,7 +1048,7 @@
"macosx64",
"macosx64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ka": {
"pin": false,
@ -1067,7 +1067,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"kab": {
"pin": false,
@ -1086,7 +1086,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"kk": {
"pin": false,
@ -1105,7 +1105,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"km": {
"pin": false,
@ -1124,7 +1124,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"kn": {
"pin": false,
@ -1143,7 +1143,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ko": {
"pin": false,
@ -1162,7 +1162,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"lij": {
"pin": false,
@ -1181,7 +1181,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"lo": {
"pin": false,
@ -1200,7 +1200,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"lt": {
"pin": false,
@ -1219,7 +1219,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ltg": {
"pin": false,
@ -1238,7 +1238,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"lv": {
"pin": false,
@ -1257,7 +1257,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"meh": {
"pin": false,
@ -1276,7 +1276,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"mk": {
"pin": false,
@ -1295,7 +1295,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"mr": {
"pin": false,
@ -1314,7 +1314,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ms": {
"pin": false,
@ -1333,7 +1333,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"my": {
"pin": false,
@ -1352,7 +1352,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"nb-NO": {
"pin": false,
@ -1371,7 +1371,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ne-NP": {
"pin": false,
@ -1390,7 +1390,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"nl": {
"pin": false,
@ -1409,7 +1409,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"nn-NO": {
"pin": false,
@ -1428,7 +1428,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"oc": {
"pin": false,
@ -1447,7 +1447,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"pa-IN": {
"pin": false,
@ -1466,7 +1466,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"pl": {
"pin": false,
@ -1485,7 +1485,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"pt-BR": {
"pin": false,
@ -1504,7 +1504,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"pt-PT": {
"pin": false,
@ -1523,7 +1523,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"rm": {
"pin": false,
@ -1542,7 +1542,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ro": {
"pin": false,
@ -1561,7 +1561,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ru": {
"pin": false,
@ -1580,7 +1580,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"sat": {
"pin": false,
@ -1599,7 +1599,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"sc": {
"pin": false,
@ -1618,7 +1618,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"scn": {
"pin": false,
@ -1637,7 +1637,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"sco": {
"pin": false,
@ -1656,7 +1656,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"si": {
"pin": false,
@ -1675,7 +1675,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"sk": {
"pin": false,
@ -1694,7 +1694,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"skr": {
"pin": false,
@ -1713,7 +1713,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"sl": {
"pin": false,
@ -1732,7 +1732,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"son": {
"pin": false,
@ -1751,7 +1751,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"sq": {
"pin": false,
@ -1770,7 +1770,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"sr": {
"pin": false,
@ -1789,7 +1789,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"sv-SE": {
"pin": false,
@ -1808,7 +1808,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"szl": {
"pin": false,
@ -1827,7 +1827,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ta": {
"pin": false,
@ -1846,7 +1846,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"te": {
"pin": false,
@ -1865,7 +1865,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"tg": {
"pin": false,
@ -1884,7 +1884,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"th": {
"pin": false,
@ -1903,7 +1903,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"tl": {
"pin": false,
@ -1922,7 +1922,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"tr": {
"pin": false,
@ -1941,7 +1941,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"trs": {
"pin": false,
@ -1960,7 +1960,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"uk": {
"pin": false,
@ -1979,7 +1979,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"ur": {
"pin": false,
@ -1998,7 +1998,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"uz": {
"pin": false,
@ -2017,7 +2017,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"vi": {
"pin": false,
@ -2036,7 +2036,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"wo": {
"pin": false,
@ -2055,7 +2055,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"xh": {
"pin": false,
@ -2074,7 +2074,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"zh-CN": {
"pin": false,
@ -2093,7 +2093,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
},
"zh-TW": {
"pin": false,
@ -2112,6 +2112,6 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "072782988bce849b3f260ba25e78e3eb3af7aaba"
"revision": "98abfedeaeec5d06148dc9f78ad8679531fdb4b8"
}
}

View file

@ -53,7 +53,7 @@ body {
/* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.verticalTabs") {
min-width: 800px;
min-width: 732px;
@media (-moz-platform: macos) {
min-width: 670px;

View file

@ -39,25 +39,13 @@
text-shadow: none;
max-width: 75vw;
&:not(.browser-toolbox-background) {
/* stylelint-disable-next-line media-query-no-invalid */
@media not (-moz-bool-pref: "sidebar.revamp") {
background-color: var(--sidebar-background-color);
color: var(--sidebar-text-color);
/* Note that with sidebar.revamp we apply the --sidebar-background-color to the
* #sidebar browser. We still need the #sidebar-box background to match the
* toolbar tho */
/* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.revamp") {
background-color: var(--toolbar-bgcolor);
color: var(--toolbar-color);
:root[lwtheme] & {
/* Ensure toolbar color displays on top of the frame/toolbox color to
* guarantee full opacity */
background-color: var(--lwt-accent-color);
background-image: linear-gradient(var(--toolbar-bgcolor), var(--toolbar-bgcolor));
}
}
* toolbar tho - this background is set on the #browser ancestor rather than here */
}
}

View file

@ -49,6 +49,18 @@
min-height: 0;
}
#browser:not(.browser-toolbox-background) {
background-color: var(--toolbar-bgcolor);
color: var(--toolbar-color);
:root[lwtheme] & {
/* Ensure toolbar color displays on top of the frame/toolbox color to
* guarantee full opacity */
background-color: var(--lwt-accent-color);
background-image: linear-gradient(var(--toolbar-bgcolor), var(--toolbar-bgcolor));
}
}
#tabbrowser-tabbox {
position: relative;
z-index: var(--browser-area-z-index-tabbox);
@ -58,6 +70,17 @@
@media (-moz-bool-pref: "sidebar.revamp") {
outline: 0.01px solid var(--chrome-content-separator-color);
box-shadow: var(--content-area-shadow);
:root:not([inDOMFullscreen]) &[sidebar-shown] {
overflow: clip;
border-start-end-radius: var(--border-radius-medium);
/* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.position_start") {
border-start-start-radius: var(--border-radius-medium);
border-start-end-radius: 0;
}
}
}
}

View file

@ -1326,6 +1326,13 @@
}
}
/* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "sidebar.verticalTabs") {
.titlebar-spacer[type="pre-tabs"] {
display: none;
}
}
/* Firefox View button and menu item */
#TabsToolbar #firefox-view-button[open] > .toolbarbutton-icon {

View file

@ -20,23 +20,24 @@
#ifdef __cpp_lib_optional
#include <optional>
template<typename T> using optional = std::optional<T>;
template <typename T> using optional = std::optional<T>;
#else
#include <llvm/ADT/Optional.h>
template<typename T> using optional = clang::Optional<T>;
template <typename T> using optional = clang::Optional<T>;
#endif
using namespace clang;
namespace {
template<typename InputIt>
bool hasReverseQualifiedName(InputIt first, InputIt last, const NamedDecl &tag)
{
template <typename InputIt>
bool hasReverseQualifiedName(InputIt first, InputIt last,
const NamedDecl &tag) {
const NamedDecl *currentDecl = &tag;
InputIt currentName;
for (currentName = first; currentName != last; currentName++) {
if (!currentDecl || !currentDecl->getIdentifier() || currentDecl->getName() != *currentName)
if (!currentDecl || !currentDecl->getIdentifier() ||
currentDecl->getName() != *currentName)
return false;
currentDecl = dyn_cast<NamedDecl>(currentDecl->getDeclContext());
@ -50,20 +51,21 @@ bool hasReverseQualifiedName(InputIt first, InputIt last, const NamedDecl &tag)
return true;
}
bool isMozillaJniObjectBase(const CXXRecordDecl &klass)
{
const auto qualifiedName = std::array<StringRef, 3>{"mozilla", "jni", "ObjectBase"};
return hasReverseQualifiedName(qualifiedName.crbegin(), qualifiedName.crend(), klass);
bool isMozillaJniObjectBase(const CXXRecordDecl &klass) {
const auto qualifiedName =
std::array<StringRef, 3>{"mozilla", "jni", "ObjectBase"};
return hasReverseQualifiedName(qualifiedName.crbegin(), qualifiedName.crend(),
klass);
}
bool isMozillaJniNativeImpl(const CXXRecordDecl &klass)
{
const auto qualifiedName = std::array<StringRef, 3>{"mozilla", "jni", "NativeImpl"};
return hasReverseQualifiedName(qualifiedName.crbegin(), qualifiedName.crend(), klass);
bool isMozillaJniNativeImpl(const CXXRecordDecl &klass) {
const auto qualifiedName =
std::array<StringRef, 3>{"mozilla", "jni", "NativeImpl"};
return hasReverseQualifiedName(qualifiedName.crbegin(), qualifiedName.crend(),
klass);
}
const NamedDecl *fieldNamed(StringRef name, const RecordDecl &strukt)
{
const NamedDecl *fieldNamed(StringRef name, const RecordDecl &strukt) {
for (const auto *decl : strukt.decls()) {
const auto *namedDecl = dyn_cast<VarDecl>(decl);
if (!namedDecl)
@ -78,8 +80,7 @@ const NamedDecl *fieldNamed(StringRef name, const RecordDecl &strukt)
return {};
}
optional<StringRef> nameFieldValue(const RecordDecl &strukt)
{
optional<StringRef> nameFieldValue(const RecordDecl &strukt) {
const auto *nameField = dyn_cast_or_null<VarDecl>(fieldNamed("name", strukt));
if (!nameField)
return {};
@ -103,22 +104,18 @@ struct AbstractBinding {
};
static constexpr size_t LangLength = 2;
static constexpr std::array<StringRef, LangLength> langNames = {
"cpp",
"jvm",
"cpp",
"jvm",
};
static optional<Lang> langFromString(StringRef langName)
{
static optional<Lang> langFromString(StringRef langName) {
const auto it = std::find(langNames.begin(), langNames.end(), langName);
if (it == langNames.end())
return {};
return Lang(it - langNames.begin());
}
static StringRef stringFromLang(Lang lang)
{
return langNames[size_t(lang)];
}
static StringRef stringFromLang(Lang lang) { return langNames[size_t(lang)]; }
// Subset of tools/analysis/BindingSlotKind
enum class Kind {
@ -130,34 +127,28 @@ struct AbstractBinding {
};
static constexpr size_t KindLength = 5;
static constexpr std::array<StringRef, KindLength> kindNames = {
"class",
"method",
"getter",
"setter",
"const",
"class", "method", "getter", "setter", "const",
};
static optional<Kind> kindFromString(StringRef kindName)
{
static optional<Kind> kindFromString(StringRef kindName) {
const auto it = std::find(kindNames.begin(), kindNames.end(), kindName);
if (it == kindNames.end())
return {};
return Kind(it - kindNames.begin());
}
static StringRef stringFromKind(Kind kind)
{
return kindNames[size_t(kind)];
}
static StringRef stringFromKind(Kind kind) { return kindNames[size_t(kind)]; }
Lang lang;
Kind kind;
StringRef symbol;
};
constexpr size_t AbstractBinding::KindLength;
constexpr std::array<StringRef, AbstractBinding::KindLength> AbstractBinding::kindNames;
constexpr std::array<StringRef, AbstractBinding::KindLength>
AbstractBinding::kindNames;
constexpr size_t AbstractBinding::LangLength;
constexpr std::array<StringRef, AbstractBinding::LangLength> AbstractBinding::langNames;
constexpr std::array<StringRef, AbstractBinding::LangLength>
AbstractBinding::langNames;
struct BindingTo : public AbstractBinding {
BindingTo(AbstractBinding b) : AbstractBinding(std::move(b)) {}
@ -171,25 +162,26 @@ struct BoundAs : public AbstractBinding {
};
constexpr StringRef BoundAs::ANNOTATION;
template<typename B>
void setBindingAttr(ASTContext &C, Decl &decl, B binding)
{
template <typename B>
void setBindingAttr(ASTContext &C, Decl &decl, B binding) {
#if CLANG_VERSION_MAJOR >= 18
auto utf8 = StringLiteralKind::UTF8;
#else
auto utf8 = StringLiteral::UTF8;
#endif
// recent LLVM: CreateImplicit then setDelayedArgs
Expr *langExpr = StringLiteral::Create(C, AbstractBinding::stringFromLang(binding.lang), utf8, false, {}, {});
Expr *kindExpr = StringLiteral::Create(C, AbstractBinding::stringFromKind(binding.kind), utf8, false, {}, {});
Expr *symbolExpr = StringLiteral::Create(C, binding.symbol, utf8, false, {}, {});
Expr *langExpr = StringLiteral::Create(
C, AbstractBinding::stringFromLang(binding.lang), utf8, false, {}, {});
Expr *kindExpr = StringLiteral::Create(
C, AbstractBinding::stringFromKind(binding.kind), utf8, false, {}, {});
Expr *symbolExpr =
StringLiteral::Create(C, binding.symbol, utf8, false, {}, {});
auto **args = new (C, 16) Expr *[3]{langExpr, kindExpr, symbolExpr};
auto *attr = AnnotateAttr::CreateImplicit(C, B::ANNOTATION, args, 3);
decl.addAttr(attr);
}
optional<AbstractBinding> readBinding(const AnnotateAttr &attr)
{
optional<AbstractBinding> readBinding(const AnnotateAttr &attr) {
if (attr.args_size() != 3)
return {};
@ -199,9 +191,12 @@ optional<AbstractBinding> readBinding(const AnnotateAttr &attr)
if (!langExpr || !kindExpr || !symbolExpr)
return {};
const auto *langName = dyn_cast<StringLiteral>(langExpr->IgnoreUnlessSpelledInSource());
const auto *kindName = dyn_cast<StringLiteral>(kindExpr->IgnoreUnlessSpelledInSource());
const auto *symbol = dyn_cast<StringLiteral>(symbolExpr->IgnoreUnlessSpelledInSource());
const auto *langName =
dyn_cast<StringLiteral>(langExpr->IgnoreUnlessSpelledInSource());
const auto *kindName =
dyn_cast<StringLiteral>(kindExpr->IgnoreUnlessSpelledInSource());
const auto *symbol =
dyn_cast<StringLiteral>(symbolExpr->IgnoreUnlessSpelledInSource());
if (!langName || !kindName || !symbol)
return {};
@ -211,15 +206,14 @@ optional<AbstractBinding> readBinding(const AnnotateAttr &attr)
if (!lang || !kind)
return {};
return AbstractBinding {
.lang = *lang,
.kind = *kind,
.symbol = symbol->getString(),
return AbstractBinding{
.lang = *lang,
.kind = *kind,
.symbol = symbol->getString(),
};
}
optional<BindingTo> getBindingTo(const Decl &decl)
{
optional<BindingTo> getBindingTo(const Decl &decl) {
for (const auto *attr : decl.specific_attrs<AnnotateAttr>()) {
if (attr->getAnnotation() != BindingTo::ANNOTATION)
continue;
@ -234,8 +228,7 @@ optional<BindingTo> getBindingTo(const Decl &decl)
}
// C++23: turn into generator
std::vector<BoundAs> getBoundAs(const Decl &decl)
{
std::vector<BoundAs> getBoundAs(const Decl &decl) {
std::vector<BoundAs> found;
for (const auto *attr : decl.specific_attrs<AnnotateAttr>()) {
@ -252,8 +245,7 @@ std::vector<BoundAs> getBoundAs(const Decl &decl)
return found;
}
class FindCallCall : private RecursiveASTVisitor<FindCallCall>
{
class FindCallCall : private RecursiveASTVisitor<FindCallCall> {
public:
struct Result {
using Kind = AbstractBinding::Kind;
@ -262,8 +254,7 @@ public:
StringRef name;
};
static optional<Result> search(Stmt *statement)
{
static optional<Result> search(Stmt *statement) {
FindCallCall finder;
finder.TraverseStmt(statement);
return finder.result;
@ -274,8 +265,9 @@ private:
friend RecursiveASTVisitor<FindCallCall>;
optional<Result> tryParseCallCall(CallExpr *callExpr){
const auto *callee = dyn_cast_or_null<CXXMethodDecl>(callExpr->getDirectCallee());
optional<Result> tryParseCallCall(CallExpr *callExpr) {
const auto *callee =
dyn_cast_or_null<CXXMethodDecl>(callExpr->getDirectCallee());
if (!callee)
return {};
@ -287,7 +279,8 @@ private:
if (action != "Call" && action != "Get" && action != "Set")
return {};
const auto *parentClass = dyn_cast_or_null<ClassTemplateSpecializationDecl>(callee->getParent());
const auto *parentClass =
dyn_cast_or_null<ClassTemplateSpecializationDecl>(callee->getParent());
if (!parentClass)
return {};
@ -318,7 +311,8 @@ private:
return {};
}
const auto *templateArg = parentClass->getTemplateArgs().get(0).getAsType()->getAsRecordDecl();
const auto *templateArg =
parentClass->getTemplateArgs().get(0).getAsType()->getAsRecordDecl();
if (!templateArg)
return {};
@ -327,23 +321,22 @@ private:
if (!name)
return {};
return Result {
.kind = kind,
.name = *name,
return Result{
.kind = kind,
.name = *name,
};
return {};
}
bool VisitCallExpr(CallExpr *callExpr)
{
bool VisitCallExpr(CallExpr *callExpr) {
return !(result = tryParseCallCall(callExpr));
}
};
constexpr StringRef JVM_SCIP_SYMBOL_PREFIX = "S_jvm_";
std::string javaScipSymbol(StringRef prefix, StringRef name, AbstractBinding::Kind kind)
{
std::string javaScipSymbol(StringRef prefix, StringRef name,
AbstractBinding::Kind kind) {
auto symbol = (prefix + name).str();
switch (kind) {
@ -364,8 +357,7 @@ std::string javaScipSymbol(StringRef prefix, StringRef name, AbstractBinding::Ki
return symbol;
}
void addSlotOwnerAttribute(llvm::json::OStream &J, const Decl &decl)
{
void addSlotOwnerAttribute(llvm::json::OStream &J, const Decl &decl) {
if (const auto bindingTo = getBindingTo(decl)) {
J.attributeBegin("slotOwner");
J.objectBegin();
@ -377,8 +369,7 @@ void addSlotOwnerAttribute(llvm::json::OStream &J, const Decl &decl)
J.attributeEnd();
}
}
void addBindingSlotsAttribute(llvm::json::OStream &J, const Decl &decl)
{
void addBindingSlotsAttribute(llvm::json::OStream &J, const Decl &decl) {
const auto allBoundAs = getBoundAs(decl);
if (!allBoundAs.empty()) {
J.attributeBegin("bindingSlots");
@ -396,7 +387,8 @@ void addBindingSlotsAttribute(llvm::json::OStream &J, const Decl &decl)
}
}
// The mangling scheme is documented at https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html
// The mangling scheme is documented at
// https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html
// The main takeaways are:
// - _0xxxx is the utf16 code unit xxxx
// - _1 is _
@ -405,75 +397,77 @@ void addBindingSlotsAttribute(llvm::json::OStream &J, const Decl &decl)
// - __ is the separator between function name and overload specification
// - _ is otherwise the separator between packages/classes/methods
//
// This method takes a StringRef & and mutates it and can be called twice on a Jnicall function name to get
// This method takes a StringRef & and mutates it and can be called twice on a
// Jnicall function name to get
// first the demangled name
// second the demangled overload specification
// But we don't use the later for now because we have no way to map that to how SCIP resolves overloads.
optional<std::string> demangleJnicallPart(StringRef &remainder)
{
// But we don't use the later for now because we have no way to map that to how
// SCIP resolves overloads.
optional<std::string> demangleJnicallPart(StringRef &remainder) {
std::string demangled;
std::mbstate_t ps = {};
while (!remainder.empty()) {
switch (remainder[0]) {
case '0': {
remainder = remainder.drop_front(1);
case '0': {
remainder = remainder.drop_front(1);
uint16_t codeUnit;
const auto ok = remainder.substr(1, 4).getAsInteger(16, codeUnit);
remainder = remainder.drop_front(4);
uint16_t codeUnit;
const auto ok = remainder.substr(1, 4).getAsInteger(16, codeUnit);
remainder = remainder.drop_front(4);
if (!ok) // failed reading xxxx as hexadecimal from _0xxxx
return {};
if (!ok) // failed reading xxxx as hexadecimal from _0xxxx
return {};
std::array<char, MB_LEN_MAX> codePoint;
const auto mbLen = std::c16rtomb(codePoint.data(), codeUnit, &ps);
std::array<char, MB_LEN_MAX> codePoint;
const auto mbLen = std::c16rtomb(codePoint.data(), codeUnit, &ps);
if (mbLen == -1) // failed converting utf16 to utf8
return {};
if (mbLen == -1) // failed converting utf16 to utf8
return {};
demangled += StringRef(codePoint.begin(), mbLen);
break;
}
demangled += StringRef(codePoint.begin(), mbLen);
break;
}
case '1':
remainder = remainder.drop_front(1);
ps = {};
demangled += '_';
break;
case '2':
remainder = remainder.drop_front(1);
ps = {};
demangled += ';';
break;
case '3':
remainder = remainder.drop_front(1);
ps = {};
demangled += '[';
break;
case '_':
remainder = remainder.drop_front(1);
ps = {};
if (remainder.empty()) // the string ends with _
return {};
switch (remainder[0]) {
case '0':
case '1':
remainder = remainder.drop_front(1);
ps = {};
demangled += '_';
break;
case '2':
remainder = remainder.drop_front(1);
ps = {};
demangled += ';';
break;
case '3':
remainder = remainder.drop_front(1);
ps = {};
demangled += '[';
break;
case '_':
remainder = remainder.drop_front(1);
ps = {};
if (remainder.empty()) // the string ends with _
return {};
switch (remainder[0]) {
case '0':
case '1':
case '2':
case '3':
demangled += '.';
break;
default:
// either:
// * the string began with _[^0-3], which is not supposed to happen; or
// * we reached __[^0-3] meaning we finished the first part of the name and remainder holds the overload specification
return demangled;
}
default:
ps = {};
demangled += '.';
break;
default:
// either:
// * the string began with _[^0-3], which is not supposed to happen; or
// * we reached __[^0-3] meaning we finished the first part of the name
// and remainder holds the overload specification
return demangled;
}
default:
ps = {};
demangled += '.';
break;
}
StringRef token;
std::tie(token, remainder) = remainder.split('_');
@ -483,8 +477,8 @@ optional<std::string> demangleJnicallPart(StringRef &remainder)
return demangled;
}
optional<std::string> scipSymbolFromJnicallFunctionName(StringRef functionName)
{
optional<std::string>
scipSymbolFromJnicallFunctionName(StringRef functionName) {
if (!functionName.consume_front("Java_"))
return {};
@ -493,7 +487,8 @@ optional<std::string> scipSymbolFromJnicallFunctionName(StringRef functionName)
if (!demangledName || demangledName->empty())
return {};
// demangleJavaName returns something like .some.package.Class$InnerClass.method
// demangleJavaName returns something like
// .some.package.Class$InnerClass.method
// - prepend S_jvm_
// - remove the leading dot
// - replace the last dot with a #
@ -508,8 +503,10 @@ optional<std::string> scipSymbolFromJnicallFunctionName(StringRef functionName)
std::replace(symbol.begin(), symbol.end(), '.', '/');
std::replace(symbol.begin(), symbol.end(), '$', '#');
// Keep track of how many times we have seen this method, to build the ([+overloadNumber]). suffix.
// This assumes this function is called on C function definitions in the same order the matching overloads are declared in Java.
// Keep track of how many times we have seen this method, to build the
// ([+overloadNumber]). suffix. This assumes this function is called on C
// function definitions in the same order the matching overloads are declared
// in Java.
static std::unordered_map<std::string, uint> jnicallFunctions;
auto &overloadNumber = jnicallFunctions[symbol];
@ -530,8 +527,7 @@ optional<std::string> scipSymbolFromJnicallFunctionName(StringRef functionName)
// {
// static constexpr char name[] = "[nameFieldValue]";
// }
void findBindingToJavaClass(ASTContext &C, CXXRecordDecl &klass)
{
void findBindingToJavaClass(ASTContext &C, CXXRecordDecl &klass) {
for (const auto &baseSpecifier : klass.bases()) {
const auto *base = baseSpecifier.getType()->getAsCXXRecordDecl();
if (!base)
@ -544,11 +540,12 @@ void findBindingToJavaClass(ASTContext &C, CXXRecordDecl &klass)
if (!name)
continue;
const auto symbol = javaScipSymbol(JVM_SCIP_SYMBOL_PREFIX, *name, BindingTo::Kind::Class);
const auto binding = BindingTo {{
.lang = BindingTo::Lang::Jvm,
.kind = BindingTo::Kind::Class,
.symbol = symbol,
const auto symbol =
javaScipSymbol(JVM_SCIP_SYMBOL_PREFIX, *name, BindingTo::Kind::Class);
const auto binding = BindingTo{{
.lang = BindingTo::Lang::Jvm,
.kind = BindingTo::Kind::Class,
.symbol = symbol,
}};
setBindingAttr(C, klass, binding);
@ -556,10 +553,10 @@ void findBindingToJavaClass(ASTContext &C, CXXRecordDecl &klass)
}
}
// When a Java method is marked as native, the JRE looks by default for a function
// named Java_<mangled method name>[__<mangled overload specification>].
void findBindingToJavaFunction(ASTContext &C, FunctionDecl &function)
{
// When a Java method is marked as native, the JRE looks by default for a
// function named Java_<mangled method name>[__<mangled overload
// specification>].
void findBindingToJavaFunction(ASTContext &C, FunctionDecl &function) {
const auto *identifier = function.getIdentifier();
if (!identifier)
return;
@ -569,10 +566,10 @@ void findBindingToJavaFunction(ASTContext &C, FunctionDecl &function)
if (!symbol)
return;
const auto binding = BoundAs {{
.lang = BindingTo::Lang::Jvm,
.kind = BindingTo::Kind::Method,
.symbol = *symbol,
const auto binding = BoundAs{{
.lang = BindingTo::Lang::Jvm,
.kind = BindingTo::Kind::Method,
.symbol = *symbol,
}};
setBindingAttr(C, function, binding);
@ -590,8 +587,7 @@ void findBindingToJavaFunction(ASTContext &C, FunctionDecl &function)
// ...
// }
// }
void findBindingToJavaMember(ASTContext &C, CXXMethodDecl &method)
{
void findBindingToJavaMember(ASTContext &C, CXXMethodDecl &method) {
const auto *parent = method.getParent();
if (!parent)
return;
@ -607,11 +603,12 @@ void findBindingToJavaMember(ASTContext &C, CXXMethodDecl &method)
if (!found)
return;
const auto symbol = javaScipSymbol(classBinding->symbol, found->name, found->kind);
const auto binding = BindingTo {{
.lang = BindingTo::Lang::Jvm,
.kind = found->kind,
.symbol = symbol,
const auto symbol =
javaScipSymbol(classBinding->symbol, found->name, found->kind);
const auto binding = BindingTo{{
.lang = BindingTo::Lang::Jvm,
.kind = found->kind,
.symbol = symbol,
}};
setBindingAttr(C, method, binding);
@ -629,8 +626,7 @@ void findBindingToJavaMember(ASTContext &C, CXXMethodDecl &method)
// ...
// }
// }
void findBindingToJavaConstant(ASTContext &C, VarDecl &field)
{
void findBindingToJavaConstant(ASTContext &C, VarDecl &field) {
const auto *parent = dyn_cast_or_null<CXXRecordDecl>(field.getDeclContext());
if (!parent)
return;
@ -639,11 +635,12 @@ void findBindingToJavaConstant(ASTContext &C, VarDecl &field)
if (!classBinding)
return;
const auto symbol = javaScipSymbol(classBinding->symbol, field.getName(), BindingTo::Kind::Const);
const auto binding = BindingTo {{
.lang = BindingTo::Lang::Jvm,
.kind = BindingTo::Kind::Const,
.symbol = symbol,
const auto symbol = javaScipSymbol(classBinding->symbol, field.getName(),
BindingTo::Kind::Const);
const auto binding = BindingTo{{
.lang = BindingTo::Lang::Jvm,
.kind = BindingTo::Kind::Const,
.symbol = symbol,
}};
setBindingAttr(C, field, binding);
@ -667,22 +664,23 @@ void findBindingToJavaConstant(ASTContext &C, VarDecl &field)
// }
// }
// }
void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
{
void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass) {
for (const auto &baseSpecifier : klass.bases()) {
const auto *base = baseSpecifier.getType()->getAsCXXRecordDecl();
if (!base)
continue;
for (const auto &baseBaseSpecifier : base->bases()) {
const auto *baseBase = dyn_cast_or_null<ClassTemplateSpecializationDecl>(baseBaseSpecifier.getType()->getAsCXXRecordDecl());
const auto *baseBase = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
baseBaseSpecifier.getType()->getAsCXXRecordDecl());
if (!baseBase)
continue;
if (!isMozillaJniNativeImpl(*baseBase))
continue;
const auto *wrapper = baseBase->getTemplateArgs().get(0).getAsType()->getAsCXXRecordDecl();
const auto *wrapper =
baseBase->getTemplateArgs().get(0).getAsType()->getAsCXXRecordDecl();
if (!wrapper)
continue;
@ -691,15 +689,17 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
if (!name)
continue;
const auto javaClassSymbol = javaScipSymbol(JVM_SCIP_SYMBOL_PREFIX, *name, BoundAs::Kind::Class);
const auto classBinding = BoundAs {{
.lang = BoundAs::Lang::Jvm,
.kind = BoundAs::Kind::Class,
.symbol = javaClassSymbol,
const auto javaClassSymbol =
javaScipSymbol(JVM_SCIP_SYMBOL_PREFIX, *name, BoundAs::Kind::Class);
const auto classBinding = BoundAs{{
.lang = BoundAs::Lang::Jvm,
.kind = BoundAs::Kind::Class,
.symbol = javaClassSymbol,
}};
setBindingAttr(C, klass, classBinding);
const auto *methodsDecl = dyn_cast_or_null<VarDecl>(fieldNamed("methods", *base));
const auto *methodsDecl =
dyn_cast_or_null<VarDecl>(fieldNamed("methods", *base));
if (!methodsDecl)
continue;
@ -714,7 +714,8 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
std::set<const CXXMethodDecl *> alreadyBound;
for (const auto *init : inits->inits()) {
const auto *call = dyn_cast<CallExpr>(init->IgnoreUnlessSpelledInSource());
const auto *call =
dyn_cast<CallExpr>(init->IgnoreUnlessSpelledInSource());
if (!call)
continue;
@ -726,15 +727,18 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
if (!templateArgs)
continue;
const auto *strukt = dyn_cast_or_null<RecordDecl>(templateArgs->get(0).getAsType()->getAsRecordDecl());
const auto *strukt = dyn_cast_or_null<RecordDecl>(
templateArgs->get(0).getAsType()->getAsRecordDecl());
if (!strukt)
continue;
const auto *wrapperRef = dyn_cast_or_null<DeclRefExpr>(call->getArg(0)->IgnoreUnlessSpelledInSource());
const auto *wrapperRef = dyn_cast_or_null<DeclRefExpr>(
call->getArg(0)->IgnoreUnlessSpelledInSource());
if (!wrapperRef)
continue;
const auto *boundRef = dyn_cast_or_null<UnaryOperator>(wrapperRef->template_arguments().front().getArgument().getAsExpr());
const auto *boundRef = dyn_cast_or_null<UnaryOperator>(
wrapperRef->template_arguments().front().getArgument().getAsExpr());
if (!boundRef)
continue;
@ -752,25 +756,30 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
}
javaMethodSymbol += ").";
const auto binding = BoundAs {{
.lang = BoundAs::Lang::Jvm,
.kind = BoundAs::Kind::Method,
.symbol = javaMethodSymbol,
const auto binding = BoundAs{{
.lang = BoundAs::Lang::Jvm,
.kind = BoundAs::Kind::Method,
.symbol = javaMethodSymbol,
}};
setBindingAttr(C, boundDecl, binding);
};
if (auto *bound = dyn_cast_or_null<DeclRefExpr>(boundRef->getSubExpr())) {
if (auto *bound =
dyn_cast_or_null<DeclRefExpr>(boundRef->getSubExpr())) {
auto *method = dyn_cast_or_null<CXXMethodDecl>(bound->getDecl());
if (!method)
continue;
addToBound(*method, 0);
} else if (const auto *bound = dyn_cast_or_null<UnresolvedLookupExpr>(boundRef->getSubExpr())) {
} else if (const auto *bound = dyn_cast_or_null<UnresolvedLookupExpr>(
boundRef->getSubExpr())) {
// XXX This is hackish
// In case of overloads it's not obvious which one we should use
// this expects the declaration order between C++ and Java to match
auto declarations = std::vector<Decl*>(bound->decls_begin(), bound->decls_end());
auto byLocation = [](Decl *a, Decl *b){ return a->getLocation() < b->getLocation(); };
auto declarations =
std::vector<Decl *>(bound->decls_begin(), bound->decls_end());
auto byLocation = [](Decl *a, Decl *b) {
return a->getLocation() < b->getLocation();
};
std::sort(declarations.begin(), declarations.end(), byLocation);
uint i = 0;
@ -791,8 +800,7 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
}
}
void emitBindingAttributes(llvm::json::OStream &J, const Decl &decl)
{
void emitBindingAttributes(llvm::json::OStream &J, const Decl &decl) {
addSlotOwnerAttribute(J, decl);
addBindingSlotsAttribute(J, decl);
}

View file

@ -10,8 +10,10 @@
void findBindingToJavaClass(clang::ASTContext &C, clang::CXXRecordDecl &klass);
void findBoundAsJavaClasses(clang::ASTContext &C, clang::CXXRecordDecl &klass);
void findBindingToJavaFunction(clang::ASTContext &C, clang::FunctionDecl &function);
void findBindingToJavaMember(clang::ASTContext &C, clang::CXXMethodDecl &method);
void findBindingToJavaFunction(clang::ASTContext &C,
clang::FunctionDecl &function);
void findBindingToJavaMember(clang::ASTContext &C,
clang::CXXMethodDecl &method);
void findBindingToJavaConstant(clang::ASTContext &C, clang::VarDecl &field);
void emitBindingAttributes(llvm::json::OStream &json, const clang::Decl &decl);

View file

@ -9,10 +9,10 @@
#include <stdlib.h>
#if defined(_WIN32) || defined(_WIN64)
#include "StringOperations.h"
#include <direct.h>
#include <io.h>
#include <windows.h>
#include "StringOperations.h"
#else
#include <sys/file.h>
#include <sys/time.h>
@ -50,7 +50,8 @@ void ensurePath(std::string Path) {
}
#if defined(_WIN32) || defined(_WIN64)
AutoLockFile::AutoLockFile(const std::string &SrcFile, const std::string &DstFile) {
AutoLockFile::AutoLockFile(const std::string &SrcFile,
const std::string &DstFile) {
this->Filename = DstFile;
std::string Hash = hash(SrcFile);
std::string MutexName = std::string("Local\\searchfox-") + Hash;
@ -71,12 +72,11 @@ AutoLockFile::~AutoLockFile() {
CloseHandle(Handle);
}
bool AutoLockFile::success() {
return Handle != NULL;
}
bool AutoLockFile::success() { return Handle != NULL; }
FILE *AutoLockFile::openTmp() {
int TmpDescriptor = _open((Filename + ".tmp").c_str(), _O_WRONLY | _O_APPEND | _O_CREAT | _O_BINARY, 0666);
int TmpDescriptor = _open((Filename + ".tmp").c_str(),
_O_WRONLY | _O_APPEND | _O_CREAT | _O_BINARY, 0666);
return _fdopen(TmpDescriptor, "ab");
}
@ -97,7 +97,8 @@ std::string getAbsolutePath(const std::string &Filename) {
return std::string(Full);
}
#else
AutoLockFile::AutoLockFile(const std::string &SrcFile, const std::string &DstFile) {
AutoLockFile::AutoLockFile(const std::string &SrcFile,
const std::string &DstFile) {
this->Filename = DstFile;
FileDescriptor = open(SrcFile.c_str(), O_RDONLY);
if (FileDescriptor == -1) {
@ -116,8 +117,9 @@ AutoLockFile::~AutoLockFile() { close(FileDescriptor); }
bool AutoLockFile::success() { return FileDescriptor != -1; }
FILE* AutoLockFile::openTmp() {
int TmpDescriptor = open((Filename + ".tmp").c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
FILE *AutoLockFile::openTmp() {
int TmpDescriptor =
open((Filename + ".tmp").c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
return fdopen(TmpDescriptor, "ab");
}

File diff suppressed because it is too large Load diff

View file

@ -37,6 +37,4 @@ std::string hash(const std::string &Str) {
return std::string(HashStr);
}
std::string toString(int N) {
return stringFormat("%d", N);
}
std::string toString(int N) { return stringFormat("%d", N); }

View file

@ -7,8 +7,8 @@
#define StringOperations_h
#include <memory>
#include <string>
#include <string.h>
#include <string>
std::string hash(const std::string &Str);

View file

@ -36,6 +36,7 @@ module.exports = {
plugins: [
"@babel/plugin-proposal-class-static-block",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-explicit-resource-management",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-private-methods",

View file

@ -29872,6 +29872,7 @@
"classPrivateProperties",
"classPrivateMethods",
"classProperties",
"explicitResourceManagement",
"objectRestSpread",
"optionalChaining",
"privateIn",
@ -29894,6 +29895,7 @@
"classPrivateProperties",
"classPrivateMethods",
"classProperties",
"explicitResourceManagement",
"exportDefaultFrom",
"exportNamespaceFrom",
"asyncGenerators",
@ -29964,6 +29966,7 @@
"classStaticBlock",
"classPrivateProperties",
"classPrivateMethods",
"explicitResourceManagement",
"objectRestSpread",
"dynamicImport",
"nullishCoalescingOperator",

View file

@ -54,6 +54,7 @@
"@babel/parser": "^7.23.0",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-class-static-block": "^7.21.0",
"@babel/plugin-proposal-explicit-resource-management": "^7.25.9",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
"@babel/plugin-proposal-private-methods": "^7.18.6",

View file

@ -25,6 +25,7 @@ const sourceOptions = {
"classPrivateProperties",
"classPrivateMethods",
"classProperties",
"explicitResourceManagement",
"objectRestSpread",
"optionalChaining",
"privateIn",
@ -47,6 +48,7 @@ const sourceOptions = {
"classPrivateProperties",
"classPrivateMethods",
"classProperties",
"explicitResourceManagement",
"exportDefaultFrom",
"exportNamespaceFrom",
"asyncGenerators",
@ -117,6 +119,7 @@ export function parseConsoleScript(text, opts) {
"classStaticBlock",
"classPrivateProperties",
"classPrivateMethods",
"explicitResourceManagement",
"objectRestSpread",
"dynamicImport",
"nullishCoalescingOperator",

View file

@ -20,6 +20,7 @@ support-files = [
prefs = [
"dom.ipc.processPrelaunch.enabled=false", # Disable randomly spawning processes during tests. After enabling windowless service workers, a process spawning will trigger an update of the service workers list which can fail the test if it occurs during shutdown (unhandled promise rejection).
"devtools.debugger.features.javascript-tracing=true", # This pref has to be set before the process starts
"javascript.options.experimental.explicit_resource_management=true", # This pref has to be set before the process starts
]
["browser_dbg-async-stepping.js"]

View file

@ -49,6 +49,13 @@ add_task(async function () {
{ identifier: "self:", value: `Object { x: 1, #privateVar: 2 }` },
]);
await checkInlinePreview(dbg, "explicitResourceManagement", [
{
identifier: "erm:",
value: `Object { foo: 42, Symbol("Symbol.dispose"): Symbol.dispose() }`,
},
]);
// Check inline previews for values within a module script
await checkInlinePreview(dbg, "runInModule", [
{ identifier: "val:", value: "4" },

View file

@ -104,6 +104,12 @@ add_task(async function () {
},
]);
await testPreviews(dbg, "explicitResourceManagement", [
// assignment
{ line: 106, column: 10, expression: "erm", result: "Object" },
{ line: 110, column: 20, expression: "foo", result: "42" },
]);
await testHoveringInvalidTargetTokens(dbg);
info(

View file

@ -20,6 +20,7 @@ support-files = [
prefs = [
"dom.ipc.processPrelaunch.enabled=false", # Disable randomly spawning processes during tests. After enabling windowless service workers, a process spawning will trigger an update of the service workers list which can fail the test if it occurs during shutdown (unhandled promise rejection).
"devtools.debugger.features.javascript-tracing=true", # This pref has to be set before the process starts
"javascript.options.experimental.explicit_resource_management=true", # This pref has to be set before the process starts
]
["browser_dbg-keyboard-navigation.js"]

View file

@ -49,6 +49,15 @@ function classProperties() {
foo.breakFn();
}
function explicitResourceManagement() {
using erm = {
[Symbol.dispose]() {},
foo: 42
};
console.log(erm);
debugger;
}
function btnClick() {
const btn = document.querySelector("button");
debugger;

View file

@ -100,4 +100,13 @@ function thisProperties() {
debugger;
}
});
}
}
function explicitResourceManagement() {
using erm = {
[Symbol.dispose]() {},
foo: 42
};
console.log(erm.foo);
debugger;
}

View file

@ -171,6 +171,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295"
integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==
"@babel/helper-plugin-utils@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz#9cbdd63a9443a2c92a725cca7ebca12cc8dd9f46"
integrity sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==
"@babel/helper-remap-async-to-generator@^7.22.20", "@babel/helper-remap-async-to-generator@^7.22.5":
version "7.22.20"
resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0"
@ -290,6 +295,13 @@
"@babel/helper-plugin-utils" "^7.20.2"
"@babel/plugin-syntax-class-static-block" "^7.14.5"
"@babel/plugin-proposal-explicit-resource-management@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-explicit-resource-management/-/plugin-proposal-explicit-resource-management-7.25.9.tgz#d4efc3cac38daaa16bb5f9f5dcdfef7440471c39"
integrity sha512-EbtfSvb6s4lZwef1nH52nw4DTUAvHY6bl1mbLgEHUkR6L8j4WY70mM/InB8Ozgdlok/7etbiSW+Wc88ZebZAKQ==
dependencies:
"@babel/helper-plugin-utils" "^7.25.9"
"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1"

View file

@ -11,9 +11,11 @@
var(--theme-highlight-yellow),
#521C76
);
--inspector-highlight-color: inherit;
&[forced-colors-active] {
--inspector-highlight-background-color: Mark;
--inspector-highlight-color: MarkText;
}
}

View file

@ -78,6 +78,7 @@
.inspector-shape-point.active,
.inspector-shapeswatch[aria-pressed="true"] + .inspector-shape > .inspector-shape-point:hover {
background-color: var(--inspector-highlight-background-color);
color: var(--inspector-highlight-color);
/* Add an outline so when the property is highlighted because of search,
the active point still stands out */
outline: 1px solid var(--theme-contrast-border);

View file

@ -352,9 +352,13 @@
background: var(--theme-tab-toolbar-background);
}
.ruleview-rule.unmatched,
.ruleview-rule[unmatched=true] {
opacity: 0.5;
:root[forced-colors-active] .ruleview-rule:is(
.unmatched,
[unmatched=true]
) {
/* Set an inactive color in High Contrast Mode as we don't have the
distinct background that is set in regular mode */
color: var(--theme-text-color-inactive);
}
.ruleview-rule.uneditable :focus,
@ -779,6 +783,7 @@
color: var(--theme-text-color-alt);
}
.ruleview-rule:is(.unmatched, [unmatched=true]) .ruleview-selector,
.ruleview-selector.unmatched,
.ruleview-property:is(.unused, .ruleview-overridden) :is(.ruleview-propertyname,.ruleview-propertyvalue) {
color: var(--theme-text-color-inactive);
@ -789,7 +794,8 @@
:is(
.ruleview-selector.unmatched,
.inspector-unmatched,
.ruleview-invalid-at-computed-value-time
.ruleview-invalid-at-computed-value-time,
.ruleview-rule:is(.unmatched, [unmatched=true]) .ruleview-selector,
):not(
/* don't show the strike through when the element is hovered so it's more legible */
:hover

View file

@ -163,8 +163,7 @@ struct TimingParams {
StickyTimeDuration CalcBeforeActiveBoundary() const {
static constexpr StickyTimeDuration zeroDuration;
// https://drafts.csswg.org/web-animations-1/#before-active-boundary-time
return std::max(std::min(StickyTimeDuration(mDelay), mEndTime),
zeroDuration);
return std::clamp(StickyTimeDuration(mDelay), zeroDuration, mEndTime);
}
StickyTimeDuration CalcActiveAfterBoundary() const {

View file

@ -1674,6 +1674,80 @@ already_AddRefed<nsIPrincipal> Element::CreateDevtoolsPrincipal() {
return dtPrincipal.forget();
}
void Element::SetAttribute(
const nsAString& aName,
const TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString& aValue,
nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError) {
aError = nsContentUtils::CheckQName(aName, false);
if (aError.Failed()) {
return;
}
nsAutoString nameToUse;
const nsAttrName* name = InternalGetAttrNameFromQName(aName, &nameToUse);
if (!name) {
RefPtr<nsAtom> nameAtom = NS_AtomizeMainThread(nameToUse);
Maybe<nsAutoString> compliantStringHolder;
const nsAString* compliantString =
TrustedTypeUtils::GetTrustedTypesCompliantAttributeValue(
*this, nameAtom, kNameSpaceID_None, aValue, compliantStringHolder,
aError);
if (aError.Failed()) {
return;
}
aError = SetAttr(kNameSpaceID_None, nameAtom, *compliantString,
aTriggeringPrincipal, true);
return;
}
Maybe<nsAutoString> compliantStringHolder;
RefPtr<nsAtom> attributeName = name->LocalName();
nsMutationGuard guard;
const nsAString* compliantString =
TrustedTypeUtils::GetTrustedTypesCompliantAttributeValue(
*this, attributeName, name->NamespaceID(), aValue,
compliantStringHolder, aError);
if (aError.Failed()) {
return;
}
if (!guard.Mutated(0)) {
aError = SetAttr(name->NamespaceID(), name->LocalName(), name->GetPrefix(),
*compliantString, aTriggeringPrincipal, true);
return;
}
// GetTrustedTypesCompliantAttributeValue may have modified mAttrs and made
// the result of InternalGetAttrNameFromQName above invalid. It may now return
// a different value, perhaps a nullptr. To be safe, just call the version of
// Element::SetAttribute accepting a string value.
SetAttribute(aName, *compliantString, aTriggeringPrincipal, aError);
}
void Element::SetAttributeNS(
const nsAString& aNamespaceURI, const nsAString& aQualifiedName,
const TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString& aValue,
nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError) {
RefPtr<mozilla::dom::NodeInfo> ni;
aError = nsContentUtils::GetNodeInfoFromQName(
aNamespaceURI, aQualifiedName, mNodeInfo->NodeInfoManager(),
ATTRIBUTE_NODE, getter_AddRefs(ni));
if (aError.Failed()) {
return;
}
Maybe<nsAutoString> compliantStringHolder;
RefPtr<nsAtom> attributeName = ni->NameAtom();
const nsAString* compliantString =
TrustedTypeUtils::GetTrustedTypesCompliantAttributeValue(
*this, attributeName, ni->NamespaceID(), aValue,
compliantStringHolder, aError);
if (aError.Failed()) {
return;
}
aError = SetAttr(ni->NamespaceID(), ni->NameAtom(), ni->GetPrefixAtom(),
*compliantString, aTriggeringPrincipal, true);
}
void Element::SetAttributeDevtools(const nsAString& aName,
const nsAString& aValue,
ErrorResult& aError) {

View file

@ -235,6 +235,7 @@ class Grid;
class OwningTrustedHTMLOrNullIsEmptyString;
class TrustedHTML;
class TrustedHTMLOrNullIsEmptyString;
class TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString;
// IID for the dom::Element interface
#define NS_ELEMENT_IID \
@ -1253,6 +1254,22 @@ class Element : public FragmentOrElement {
ErrorResult& aError) {
SetAttribute(aName, aValue, nullptr, aError);
}
MOZ_CAN_RUN_SCRIPT void SetAttribute(
const nsAString& aName,
const TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString& aValue,
nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError);
MOZ_CAN_RUN_SCRIPT void SetAttributeNS(
const nsAString& aNamespaceURI, const nsAString& aLocalName,
const TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString& aValue,
nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError);
MOZ_CAN_RUN_SCRIPT void SetAttribute(
const nsAString& aName,
const TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString& aValue,
ErrorResult& aError) {
SetAttribute(aName, aValue, nullptr, aError);
}
/**
* This method creates a principal that subsumes this element's NodePrincipal
* and which has flags set for elevated permissions that devtools needs to

View file

@ -1368,7 +1368,6 @@ StructuredCloneHolder::CustomReadTransferHandler(
static_cast<OffscreenCanvasCloneData*>(aContent);
RefPtr<OffscreenCanvas> canvas =
OffscreenCanvas::CreateFromCloneData(mGlobal, data);
delete data;
JS::Rooted<JS::Value> value(aCx);
if (!GetOrCreateDOMReflector(aCx, canvas, &value)) {
@ -1376,6 +1375,7 @@ StructuredCloneHolder::CustomReadTransferHandler(
return false;
}
delete data;
aReturnObject.set(&value.toObject());
return true;
}
@ -1389,7 +1389,6 @@ StructuredCloneHolder::CustomReadTransferHandler(
ImageBitmapCloneData* data = static_cast<ImageBitmapCloneData*>(aContent);
RefPtr<ImageBitmap> bitmap =
ImageBitmap::CreateFromCloneData(mGlobal, data);
delete data;
JS::Rooted<JS::Value> value(aCx);
if (!GetOrCreateDOMReflector(aCx, bitmap, &value)) {
@ -1397,6 +1396,7 @@ StructuredCloneHolder::CustomReadTransferHandler(
return false;
}
delete data;
aReturnObject.set(&value.toObject());
return true;
}
@ -1464,14 +1464,14 @@ StructuredCloneHolder::CustomReadTransferHandler(
if (!frame) {
return false;
}
delete data;
aContent = nullptr;
JS::Rooted<JS::Value> value(aCx);
if (!GetOrCreateDOMReflector(aCx, frame, &value)) {
JS_ClearPendingException(aCx);
return false;
}
delete data;
aContent = nullptr;
aReturnObject.set(&value.toObject());
return true;
}
@ -1497,14 +1497,14 @@ StructuredCloneHolder::CustomReadTransferHandler(
if (!audioData) {
return false;
}
delete data;
aContent = nullptr;
JS::Rooted<JS::Value> value(aCx);
if (!GetOrCreateDOMReflector(aCx, audioData, &value)) {
JS_ClearPendingException(aCx);
return false;
}
delete data;
aContent = nullptr;
aReturnObject.set(&value.toObject());
return true;
}

View file

@ -3039,15 +3039,13 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow,
// care of lowering the present active window. This happens in
// a separate runnable to avoid touching multiple windows in
// the current runnable.
nsCOMPtr<nsPIDOMWindowOuter> window(aWindow);
RefPtr<nsFocusManager> self(this);
NS_DispatchToCurrentThread(NS_NewRunnableFunction(
"nsFocusManager::RaiseWindow",
// TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1770093)
[self, window]() MOZ_CAN_RUN_SCRIPT_BOUNDARY -> void {
self->WindowRaised(window, GenerateFocusActionId());
}));
[self = RefPtr{this}, window = nsCOMPtr{aWindow}]()
MOZ_CAN_RUN_SCRIPT_BOUNDARY -> void {
self->WindowRaised(window, GenerateFocusActionId());
}));
return;
}
@ -3062,36 +3060,6 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow,
}
}
#if defined(XP_WIN)
// Windows would rather we focus the child widget, otherwise, the toplevel
// widget will always end up being focused. Fortunately, focusing the child
// widget will also have the effect of raising the window this widget is in.
// But on other platforms, we can just focus the toplevel widget to raise
// the window.
nsCOMPtr<nsPIDOMWindowOuter> childWindow;
GetFocusedDescendant(aWindow, eIncludeAllDescendants,
getter_AddRefs(childWindow));
if (!childWindow) {
childWindow = aWindow;
}
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
if (!docShell) {
return;
}
PresShell* presShell = docShell->GetPresShell();
if (!presShell) {
return;
}
if (nsViewManager* vm = presShell->GetViewManager()) {
nsCOMPtr<nsIWidget> widget = vm->GetRootWidget();
if (widget) {
widget->SetFocus(nsIWidget::Raise::Yes, aCallerType);
}
}
#else
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin =
do_QueryInterface(aWindow->GetDocShell());
if (treeOwnerAsWin) {
@ -3101,7 +3069,6 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow,
widget->SetFocus(nsIWidget::Raise::Yes, aCallerType);
}
}
#endif
}
void nsFocusManager::UpdateCaretForCaretBrowsingMode() {

View file

@ -67,7 +67,8 @@ async function testKnownCiStrings() {
unmasked_renderer: [
'Adreno (TM) 540', // Android
'Adreno (TM) 620', // Android pixel5
'llvmpipe (LLVM 10.0.0, 256 bits)', // Linux
'llvmpipe (LLVM 10.0.0, 256 bits)', // Linux (Ubuntu 18.04)
'llvmpipe (LLVM 17.0.6, 256 bits)', // Linux (Ubuntu 24.04)
'Intel(R) UHD Graphics 630', // Mac
'Apple M1', // Mac
'Apple M2', // Mac
@ -78,6 +79,7 @@ async function testKnownCiStrings() {
unmasked_vendor: [
'Qualcomm', // Android
'VMware, Inc.', // Linux
'Mesa', // Linux
'Intel Inc.', // Mac
'Apple', // Mac
'Google Inc. (NVIDIA)', // Windows

View file

@ -3589,13 +3589,17 @@ ContentParent::BlockShutdown(nsIAsyncShutdownClient* aClient) {
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
mBlockShutdownCalled = true;
#endif
// Our real shutdown has not yet started. Just notify the impending
// shutdown and eventually cancel content JS.
SignalImpendingShutdownToContentJS();
// This will make our process unusable for normal content, so we need to
// ensure we won't get re-used by GetUsedBrowserProcess as we have not yet
// done MarkAsDead.
PreallocatedProcessManager::Erase(this);
{
RecursiveMutexAutoLock lock(mThreadsafeHandle->mMutex);
mThreadsafeHandle->mShutdownStarted = true;
}
// Our real shutdown has not yet started. Just notify the impending
// shutdown and eventually cancel content JS.
SignalImpendingShutdownToContentJS();
if (sQuitApplicationGrantedClient) {
Unused << sQuitApplicationGrantedClient->RemoveBlocker(this);

View file

@ -57,6 +57,10 @@
# include "VideoUtils.h"
#endif
namespace TelemetryScalar {
void Set(mozilla::Telemetry::ScalarID aId, uint32_t aValue);
}
namespace mozilla {
using namespace ipc;
@ -284,7 +288,7 @@ mozilla::ipc::IPCResult RDDParent::RecvTestTriggerMetrics(
mozilla::ipc::IPCResult RDDParent::RecvTestTelemetryProbes() {
const uint32_t kExpectedUintValue = 42;
Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_RDD_ONLY_UINT,
TelemetryScalar::Set(Telemetry::ScalarID::TELEMETRY_TEST_RDD_ONLY_UINT,
kExpectedUintValue);
return IPC_OK();
}

View file

@ -7,6 +7,7 @@ import hashlib
import json
import logging
import re
from urllib.parse import urlparse, urlunparse
import requests
@ -24,6 +25,17 @@ def fetch_url_for_cdms(cdms, urlParams):
)
)
redirectUrl = response.headers["Location"]
parsedUrl = urlparse(redirectUrl)
if parsedUrl.scheme != "https":
raise Exception(
"{} expected https scheme '{}'".format(cdm["target"], redirectUrl)
)
sanitizedUrl = urlunparse(
(parsedUrl.scheme, parsedUrl.netloc, parsedUrl.path, None, None, None)
)
# Note that here we modify the returned URL from the
# component update service because it returns a preferred
# server for the caller of the script. This may not match
@ -31,17 +43,29 @@ def fetch_url_for_cdms(cdms, urlParams):
# that we instead replace these results with the
# edgedl.me.gvt1.com domain/path, which should be location
# agnostic.
redirectUrl = response.headers["Location"]
normalizedUrl = re.sub(
r"https.+?release2",
"https://edgedl.me.gvt1.com/edgedl/release2",
redirectUrl,
sanitizedUrl,
)
if not normalizedUrl:
raise Exception(
"{} cannot normalize '{}'".format(cdm["target"], sanitizedUrl)
)
# Because some users are unable to resolve *.gvt1.com
# URLs, we supply an alternative based on www.google.com.
# This should resolve with success more frequently.
mirrorUrl = re.sub(
r"https.+?release2",
"https://www.google.com/dl/release2",
sanitizedUrl,
)
version = re.search(r".*?_([\d]+\.[\d]+\.[\d]+\.[\d]+)/", redirectUrl)
version = re.search(r".*?_([\d]+\.[\d]+\.[\d]+\.[\d]+)/", sanitizedUrl)
if version is None:
raise Exception(
"{} cannot extract version '{}'".format(cdm["target"], redirectUrl)
"{} cannot extract version '{}'".format(cdm["target"], sanitizedUrl)
)
if any_version is None:
any_version = version.group(1)
@ -52,6 +76,8 @@ def fetch_url_for_cdms(cdms, urlParams):
)
)
cdm["fileName"] = normalizedUrl
if mirrorUrl and mirrorUrl != normalizedUrl:
cdm["fileNameMirror"] = mirrorUrl
return any_version
@ -62,6 +88,17 @@ def fetch_data_for_cdms(cdms, urlParams):
response = requests.get(cdm["fileUrl"])
response.raise_for_status()
cdm["hashValue"] = hashlib.sha512(response.content).hexdigest()
if "fileNameMirror" in cdm:
cdm["mirrorUrl"] = cdm["fileNameMirror"].format_map(urlParams)
mirrorresponse = requests.get(cdm["mirrorUrl"])
mirrorresponse.raise_for_status()
mirrorhash = hashlib.sha512(mirrorresponse.content).hexdigest()
if cdm["hashValue"] != mirrorhash:
raise Exception(
"Primary hash {} and mirror hash {} differ",
cdm["hashValue"],
mirrorhash,
)
cdm["filesize"] = len(response.content)
if cdm["filesize"] == 0:
raise Exception("Empty response for {target}".format_map(cdm))
@ -76,10 +113,22 @@ def generate_json_for_cdms(cdms):
+ ' "alias": "{alias}"\n'
+ " }},\n"
).format_map(cdm)
elif "mirrorUrl" in cdm:
cdm_json += (
' "{target}": {{\n'
+ ' "fileUrl": "{fileUrl}",\n'
+ ' "mirrorUrls": [\n'
+ ' "{mirrorUrl}"\n'
+ " ],\n"
+ ' "filesize": {filesize},\n'
+ ' "hashValue": "{hashValue}"\n'
+ " }},\n"
).format_map(cdm)
else:
cdm_json += (
' "{target}": {{\n'
+ ' "fileUrl": "{fileUrl}",\n'
+ ' "mirrorUrls": [],\n'
+ ' "filesize": {filesize},\n'
+ ' "hashValue": "{hashValue}"\n'
+ " }},\n"
@ -92,10 +141,10 @@ def calculate_gmpopenh264_json(version: str, version_hash: str, url_base: str) -
cdms = [
{"target": "Darwin_aarch64-gcc3", "fileName": "{url_base}/openh264-macosx64-aarch64-{version}.zip"},
{"target": "Darwin_x86_64-gcc3", "fileName": "{url_base}/openh264-macosx64-{version}.zip"},
{"target": "Linux_aarch64-gcc3", "fileName": "{url_base}/openh264-linux64-aarch64-{version}.zip"},
{"target": "Linux_x86-gcc3", "fileName": "{url_base}/openh264-linux32-{version}.zip"},
{"target": "Linux_x86_64-gcc3", "fileName": "{url_base}/openh264-linux64-{version}.zip"},
{"target": "Linux_x86_64-gcc3-asan", "alias": "Linux_x86_64-gcc3"},
{"target": "Linux_aarch64-gcc3", "fileName": "{url_base}/openh264-linux64-aarch64-{version}.zip"},
{"target": "WINNT_aarch64-msvc-aarch64", "fileName": "{url_base}/openh264-win64-aarch64-{version}.zip"},
{"target": "WINNT_x86-msvc", "fileName": "{url_base}/openh264-win32-{version}.zip"},
{"target": "WINNT_x86-msvc-x64", "alias": "WINNT_x86-msvc"},
@ -273,7 +322,7 @@ def main():
parser.error("widevine requires version")
if args.revision is not None:
parser.error("widevine cannot use revision")
elif args.plugin == "widevine_component" or args.plugin == "widevine_l1_component":
elif args.plugin in ("widevine_component", "widevine_l1_component"):
url_base = "https://update.googleapis.com/service/update2/crx?response=redirect&x=id%3D{guid}%26uc&acceptformat=crx3&updaterversion=999"
if args.testrequest:
url_base += "&testrequest=1"

View file

@ -204,49 +204,48 @@ void TrustedTypePolicyFactory::GetAttributeType(const nsAString& aTagName,
const nsAString& aElementNs,
const nsAString& aAttrNs,
DOMString& aResult) {
// We first determine the namespace IDs for the element and attribute.
// Currently, GetTrustedTypeDataForAttribute() only test a few of them so use
// direct string comparisons instead of relying on
// nsNameSpaceManager::GetNameSpaceID().
// GetTrustedTypeDataForAttribute() can only return true for empty or XLink
// attribute namespaces, so don't bother calling it for other namespaces.
int32_t attributeNamespaceID = kNameSpaceID_Unknown;
if (aAttrNs.IsEmpty()) {
attributeNamespaceID = kNameSpaceID_None;
} else if (nsGkAtoms::nsuri_xlink->Equals(aAttrNs)) {
attributeNamespaceID = kNameSpaceID_XLink;
} else {
aResult.SetNull();
return;
}
// GetTrustedTypeDataForAttribute() only test HTML or SVG element namespaces,
// for testing event handler attributes the element namespace does not matter.
int32_t elementNamespaceID = kNameSpaceID_Unknown;
if (aElementNs.IsEmpty() || nsGkAtoms::nsuri_xhtml->Equals(aElementNs)) {
elementNamespaceID = kNameSpaceID_XHTML;
} else if (nsGkAtoms::nsuri_svg->Equals(aElementNs)) {
elementNamespaceID = kNameSpaceID_SVG;
}
nsAutoString attribute;
nsContentUtils::ASCIIToLower(aAttribute, attribute);
RefPtr<nsAtom> attributeAtom = NS_Atomize(attribute);
// The spec is not really clear about which "event handler content attributes"
// we should consider, so we just include everything but XUL's specific ones.
// See https://github.com/w3c/trusted-types/issues/520.
if (aAttrNs.IsEmpty() &&
nsContentUtils::IsEventAttributeName(
attributeAtom, EventNameType_All & ~EventNameType_XUL)) {
// Event handler content attribute.
aResult.SetKnownLiveString(GetTrustedTypeName<TrustedScript>());
nsAutoString localName;
nsContentUtils::ASCIIToLower(aTagName, localName);
RefPtr<nsAtom> elementAtom = NS_Atomize(localName);
TrustedType trustedType;
nsAutoString unusedSink;
if (GetTrustedTypeDataForAttribute(elementAtom, elementNamespaceID,
attributeAtom, attributeNamespaceID,
trustedType, unusedSink)) {
aResult.SetKnownLiveString(GetTrustedTypeName(trustedType));
return;
}
if (aElementNs.IsEmpty() ||
aElementNs == nsDependentAtomString(nsGkAtoms::nsuri_xhtml)) {
if (nsContentUtils::EqualsIgnoreASCIICase(
aTagName, nsDependentAtomString(nsGkAtoms::iframe))) {
// HTMLIFrameElement
if (aAttrNs.IsEmpty() && attributeAtom == nsGkAtoms::srcdoc) {
aResult.SetKnownLiveString(GetTrustedTypeName<TrustedHTML>());
return;
}
} else if (nsContentUtils::EqualsIgnoreASCIICase(
aTagName, nsDependentAtomString(nsGkAtoms::script))) {
// HTMLScriptElement
if (aAttrNs.IsEmpty() && attributeAtom == nsGkAtoms::src) {
aResult.SetKnownLiveString(GetTrustedTypeName<TrustedScriptURL>());
return;
}
}
} else if (aElementNs == nsDependentAtomString(nsGkAtoms::nsuri_svg)) {
if (nsContentUtils::EqualsIgnoreASCIICase(
aTagName, nsDependentAtomString(nsGkAtoms::script))) {
// SVGScriptElement
if ((aAttrNs.IsEmpty() ||
aAttrNs == nsDependentAtomString(nsGkAtoms::nsuri_xlink)) &&
attributeAtom == nsGkAtoms::href) {
aResult.SetKnownLiveString(GetTrustedTypeName<TrustedScriptURL>());
return;
}
}
}
aResult.SetNull();
}
@ -263,8 +262,7 @@ void TrustedTypePolicyFactory::GetPropertyType(const nsAString& aTagName,
const nsAString& aElementNs,
DOMString& aResult) {
RefPtr<nsAtom> propertyAtom = NS_Atomize(aProperty);
if (aElementNs.IsEmpty() ||
aElementNs == nsDependentAtomString(nsGkAtoms::nsuri_xhtml)) {
if (aElementNs.IsEmpty() || nsGkAtoms::nsuri_xhtml->Equals(aElementNs)) {
if (nsContentUtils::EqualsIgnoreASCIICase(
aTagName, nsDependentAtomString(nsGkAtoms::iframe))) {
// HTMLIFrameElement

View file

@ -18,6 +18,7 @@
#include "mozilla/dom/TrustedScriptURL.h"
#include "mozilla/dom/TrustedTypePolicy.h"
#include "mozilla/dom/TrustedTypePolicyFactory.h"
#include "mozilla/dom/TrustedTypesConstants.h"
#include "nsGlobalWindowInner.h"
#include "nsLiteralString.h"
#include "nsTArray.h"
@ -34,6 +35,22 @@
namespace mozilla::dom::TrustedTypeUtils {
nsString GetTrustedTypeName(TrustedType aTrustedType) {
switch (aTrustedType) {
case TrustedType::TrustedHTML:
return GetTrustedTypeName<TrustedHTML>();
break;
case TrustedType::TrustedScript:
return GetTrustedTypeName<TrustedScript>();
break;
case TrustedType::TrustedScriptURL:
return GetTrustedTypeName<TrustedScriptURL>();
break;
}
MOZ_ASSERT_UNREACHABLE();
return EmptyString();
}
// https://w3c.github.io/trusted-types/dist/spec/#abstract-opdef-does-sink-type-require-trusted-types
static bool DoesSinkTypeRequireTrustedTypes(nsIContentSecurityPolicy* aCSP,
const nsAString& aSinkGroup) {
@ -234,6 +251,10 @@ MOZ_CAN_RUN_SCRIPT inline const nsAString* GetTrustedTypesCompliantString(
TrustedScriptOrNullIsEmptyString>) {
return aInput.IsNullIsEmptyString();
}
if constexpr (std::is_same_v<TrustedTypeOrStringArg, const nsAString*>) {
Unused << aInput;
return true;
}
MOZ_ASSERT_UNREACHABLE();
return false;
};
@ -251,6 +272,9 @@ MOZ_CAN_RUN_SCRIPT inline const nsAString* GetTrustedTypesCompliantString(
TrustedScriptOrNullIsEmptyString>) {
return &aInput.GetAsNullIsEmptyString();
}
if constexpr (std::is_same_v<TrustedTypeOrStringArg, const nsAString*>) {
return aInput;
}
MOZ_ASSERT_UNREACHABLE();
return static_cast<const nsAString*>(&EmptyString());
};
@ -270,6 +294,10 @@ MOZ_CAN_RUN_SCRIPT inline const nsAString* GetTrustedTypesCompliantString(
TrustedScriptURLOrString>) {
return aInput.IsTrustedScriptURL();
}
if constexpr (std::is_same_v<TrustedTypeOrStringArg, const nsAString*>) {
Unused << aInput;
return false;
}
MOZ_ASSERT_UNREACHABLE();
return false;
};
@ -289,6 +317,7 @@ MOZ_CAN_RUN_SCRIPT inline const nsAString* GetTrustedTypesCompliantString(
TrustedScriptURLOrString>) {
return &aInput.GetAsTrustedScriptURL().mData;
}
Unused << aInput;
MOZ_ASSERT_UNREACHABLE();
return &EmptyString();
};
@ -373,4 +402,124 @@ IMPL_GET_TRUSTED_TYPES_COMPLIANT_STRING(TrustedScriptOrNullIsEmptyString,
IMPL_GET_TRUSTED_TYPES_COMPLIANT_STRING(TrustedScriptURLOrString,
TrustedScriptURL);
bool GetTrustedTypeDataForAttribute(const nsAtom* aElementName,
int32_t aElementNamespaceID,
nsAtom* aAttributeName,
int32_t aAttributeNamespaceID,
TrustedType& aTrustedType,
nsAString& aSink) {
// The spec is not really clear about which "event handler content attributes"
// we should consider, so we just include everything but XUL's specific ones.
// See https://github.com/w3c/trusted-types/issues/520.
if (aAttributeNamespaceID == kNameSpaceID_None &&
nsContentUtils::IsEventAttributeName(
aAttributeName, EventNameType_All & ~EventNameType_XUL)) {
aTrustedType = TrustedType::TrustedScript;
return true;
}
if (aElementNamespaceID == kNameSpaceID_XHTML) {
if (aElementName == nsGkAtoms::iframe) {
// HTMLIFrameElement
if (aAttributeNamespaceID == kNameSpaceID_None &&
aAttributeName == nsGkAtoms::srcdoc) {
aTrustedType = TrustedType::TrustedHTML;
aSink.AssignLiteral(u"HTMLIFrameElement srcdoc");
return true;
}
} else if (aElementName == nsGkAtoms::script) {
// HTMLScriptElement
if (aAttributeNamespaceID == kNameSpaceID_None &&
aAttributeName == nsGkAtoms::src) {
aTrustedType = TrustedType::TrustedScriptURL;
aSink.AssignLiteral(u"HTMLScriptElement src");
return true;
}
}
} else if (aElementNamespaceID == kNameSpaceID_SVG) {
if (aElementName == nsGkAtoms::script) {
// SVGScriptElement
if ((aAttributeNamespaceID == kNameSpaceID_None ||
aAttributeNamespaceID == kNameSpaceID_XLink) &&
aAttributeName == nsGkAtoms::href) {
aTrustedType = TrustedType::TrustedScriptURL;
aSink.AssignLiteral(u"SVGScriptElement href");
return true;
}
}
}
return false;
}
MOZ_CAN_RUN_SCRIPT const nsAString* GetTrustedTypesCompliantAttributeValue(
const nsINode& aElement, nsAtom* aAttributeName,
int32_t aAttributeNamespaceID,
const TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString& aNewValue,
Maybe<nsAutoString>& aResultHolder, ErrorResult& aError) {
auto getAsTrustedType = [&aNewValue] {
if (aNewValue.IsTrustedHTML()) {
return &aNewValue.GetAsTrustedHTML().mData;
}
if (aNewValue.IsTrustedScript()) {
return &aNewValue.GetAsTrustedScript().mData;
}
MOZ_ASSERT(aNewValue.IsTrustedScriptURL());
return &aNewValue.GetAsTrustedScriptURL().mData;
};
auto getContent = [&aNewValue, &getAsTrustedType] {
return aNewValue.IsString() ? &aNewValue.GetAsString() : getAsTrustedType();
};
if (!StaticPrefs::dom_security_trusted_types_enabled()) {
// A trusted type might've been created before the pref was set to `false`,
// so we cannot assume aNewValue.IsString().
return getContent();
}
// In the common situation of non-data document without any
// require-trusted-types-for directive, we just return immediately.
const NodeInfo* nodeInfo = aElement.NodeInfo();
Document* ownerDoc = nodeInfo->GetDocument();
const bool ownerDocLoadedAsData = ownerDoc->IsLoadedAsData();
if (!ownerDoc->HasPolicyWithRequireTrustedTypesForDirective() &&
!ownerDocLoadedAsData) {
return getContent();
}
TrustedType expectedType;
nsAutoString sink;
if (!GetTrustedTypeDataForAttribute(
nodeInfo->NameAtom(), nodeInfo->NamespaceID(), aAttributeName,
aAttributeNamespaceID, expectedType, sink)) {
return getContent();
}
if ((expectedType == TrustedType::TrustedHTML && aNewValue.IsTrustedHTML()) ||
(expectedType == TrustedType::TrustedScript &&
aNewValue.IsTrustedScript()) ||
(expectedType == TrustedType::TrustedScriptURL &&
aNewValue.IsTrustedScriptURL())) {
return getAsTrustedType();
}
const nsAString* input =
aNewValue.IsString() ? &aNewValue.GetAsString() : getAsTrustedType();
switch (expectedType) {
case TrustedType::TrustedHTML:
return GetTrustedTypesCompliantString<TrustedHTML>(
input, sink, kTrustedTypesOnlySinkGroup, aElement, aResultHolder,
aError);
case TrustedType::TrustedScript:
return GetTrustedTypesCompliantString<TrustedScript>(
input, sink, kTrustedTypesOnlySinkGroup, aElement, aResultHolder,
aError);
case TrustedType::TrustedScriptURL:
return GetTrustedTypesCompliantString<TrustedScriptURL>(
input, sink, kTrustedTypesOnlySinkGroup, aElement, aResultHolder,
aError);
}
MOZ_ASSERT_UNREACHABLE();
return nullptr;
}
} // namespace mozilla::dom::TrustedTypeUtils

View file

@ -33,6 +33,7 @@ class TrustedScriptOrString;
class TrustedScriptOrNullIsEmptyString;
class TrustedScriptURL;
class TrustedScriptURLOrString;
class TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString;
namespace TrustedTypeUtils {
@ -48,6 +49,13 @@ nsString GetTrustedTypeName() {
return u"TrustedScriptURL"_ns;
}
enum class TrustedType : int8_t {
TrustedHTML,
TrustedScript,
TrustedScriptURL,
};
nsString GetTrustedTypeName(TrustedType aTrustedType);
// https://w3c.github.io/trusted-types/dist/spec/#get-trusted-type-compliant-string-algorithm
//
// May only run script if aInput is not a trusted type and if the trusted types
@ -82,6 +90,21 @@ MOZ_CAN_RUN_SCRIPT void ProcessValueWithADefaultPolicy(
const Document& aDocument, const nsAString& aInput, const nsAString& aSink,
ExpectedType** aResult, ErrorResult& aError);
// https://w3c.github.io/trusted-types/dist/spec/#get-trusted-type-data-for-attribute
bool GetTrustedTypeDataForAttribute(const nsAtom* aElementName,
int32_t aElementNamespaceID,
nsAtom* aAttributeName,
int32_t aAttributeNamespaceID,
TrustedType& aTrustedType,
nsAString& aSink);
// https://w3c.github.io/trusted-types/dist/spec/#abstract-opdef-get-trusted-types-compliant-attribute-value
MOZ_CAN_RUN_SCRIPT const nsAString* GetTrustedTypesCompliantAttributeValue(
const nsINode& aElement, nsAtom* aAttributeName,
int32_t aAttributeNamespaceID,
const TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString& aNewValue,
Maybe<nsAutoString>& aResultHolder, ErrorResult& aError);
} // namespace TrustedTypeUtils
} // namespace dom

View file

@ -23,7 +23,7 @@ GPU_IMPL_CYCLE_COLLECTION(CommandEncoder, mParent, mBridge)
GPU_IMPL_JS_WRAP(CommandEncoder)
void CommandEncoder::ConvertTextureDataLayoutToFFI(
const dom::GPUImageDataLayout& aLayout,
const dom::GPUTexelCopyBufferLayout& aLayout,
ffi::WGPUImageDataLayout* aLayoutFFI) {
*aLayoutFFI = {};
aLayoutFFI->offset = aLayout.mOffset;
@ -42,7 +42,7 @@ void CommandEncoder::ConvertTextureDataLayoutToFFI(
}
void CommandEncoder::ConvertTextureCopyViewToFFI(
const dom::GPUImageCopyTexture& aCopy,
const dom::GPUTexelCopyTextureInfo& aCopy,
ffi::WGPUImageCopyTexture* aViewFFI) {
*aViewFFI = {};
aViewFFI->texture = aCopy.mTexture->mId;
@ -64,7 +64,7 @@ void CommandEncoder::ConvertTextureCopyViewToFFI(
}
static ffi::WGPUImageCopyTexture ConvertTextureCopyView(
const dom::GPUImageCopyTexture& aCopy) {
const dom::GPUTexelCopyTextureInfo& aCopy) {
ffi::WGPUImageCopyTexture view = {};
CommandEncoder::ConvertTextureCopyViewToFFI(aCopy, &view);
return view;
@ -120,8 +120,8 @@ void CommandEncoder::CopyBufferToBuffer(const Buffer& aSource,
}
void CommandEncoder::CopyBufferToTexture(
const dom::GPUImageCopyBuffer& aSource,
const dom::GPUImageCopyTexture& aDestination,
const dom::GPUTexelCopyBufferInfo& aSource,
const dom::GPUTexelCopyTextureInfo& aDestination,
const dom::GPUExtent3D& aCopySize) {
if (!mBridge->CanSend()) {
return;
@ -138,8 +138,8 @@ void CommandEncoder::CopyBufferToTexture(
TrackPresentationContext(aDestination.mTexture->mTargetContext);
}
void CommandEncoder::CopyTextureToBuffer(
const dom::GPUImageCopyTexture& aSource,
const dom::GPUImageCopyBuffer& aDestination,
const dom::GPUTexelCopyTextureInfo& aSource,
const dom::GPUTexelCopyBufferInfo& aDestination,
const dom::GPUExtent3D& aCopySize) {
if (!mBridge->CanSend()) {
return;
@ -154,8 +154,8 @@ void CommandEncoder::CopyTextureToBuffer(
mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(bb));
}
void CommandEncoder::CopyTextureToTexture(
const dom::GPUImageCopyTexture& aSource,
const dom::GPUImageCopyTexture& aDestination,
const dom::GPUTexelCopyTextureInfo& aSource,
const dom::GPUTexelCopyTextureInfo& aDestination,
const dom::GPUExtent3D& aCopySize) {
if (!mBridge->CanSend()) {
return;

View file

@ -24,10 +24,10 @@ class Sequence;
struct GPUCommandBufferDescriptor;
class GPUComputePipelineOrGPURenderPipeline;
class RangeEnforcedUnsignedLongSequenceOrGPUExtent3DDict;
struct GPUImageCopyBuffer;
struct GPUImageCopyTexture;
struct GPUTexelCopyBufferInfo;
struct GPUTexelCopyTextureInfo;
struct GPUImageBitmapCopyView;
struct GPUImageDataLayout;
struct GPUTexelCopyBufferLayout;
struct GPURenderPassDescriptor;
using GPUExtent3D = RangeEnforcedUnsignedLongSequenceOrGPUExtent3DDict;
} // namespace dom
@ -51,10 +51,10 @@ class CommandEncoder final : public ObjectBase, public ChildOf<Device> {
const RawId mId;
static void ConvertTextureDataLayoutToFFI(
const dom::GPUImageDataLayout& aLayout,
const dom::GPUTexelCopyBufferLayout& aLayout,
ffi::WGPUImageDataLayout* aLayoutFFI);
static void ConvertTextureCopyViewToFFI(
const dom::GPUImageCopyTexture& aCopy,
const dom::GPUTexelCopyTextureInfo& aCopy,
ffi::WGPUImageCopyTexture_TextureId* aViewFFI);
private:
@ -76,14 +76,14 @@ class CommandEncoder final : public ObjectBase, public ChildOf<Device> {
const Buffer& aDestination,
BufferAddress aDestinationOffset,
BufferAddress aSize);
void CopyBufferToTexture(const dom::GPUImageCopyBuffer& aSource,
const dom::GPUImageCopyTexture& aDestination,
void CopyBufferToTexture(const dom::GPUTexelCopyBufferInfo& aSource,
const dom::GPUTexelCopyTextureInfo& aDestination,
const dom::GPUExtent3D& aCopySize);
void CopyTextureToBuffer(const dom::GPUImageCopyTexture& aSource,
const dom::GPUImageCopyBuffer& aDestination,
void CopyTextureToBuffer(const dom::GPUTexelCopyTextureInfo& aSource,
const dom::GPUTexelCopyBufferInfo& aDestination,
const dom::GPUExtent3D& aCopySize);
void CopyTextureToTexture(const dom::GPUImageCopyTexture& aSource,
const dom::GPUImageCopyTexture& aDestination,
void CopyTextureToTexture(const dom::GPUTexelCopyTextureInfo& aSource,
const dom::GPUTexelCopyTextureInfo& aDestination,
const dom::GPUExtent3D& aCopySize);
void ClearBuffer(const Buffer& aBuffer, const uint64_t aOffset,
const dom::Optional<uint64_t>& aSize);

View file

@ -125,9 +125,9 @@ void Queue::WriteBuffer(const Buffer& aBuffer, uint64_t aBufferOffset,
});
}
void Queue::WriteTexture(const dom::GPUImageCopyTexture& aDestination,
void Queue::WriteTexture(const dom::GPUTexelCopyTextureInfo& aDestination,
const dom::ArrayBufferViewOrArrayBuffer& aData,
const dom::GPUImageDataLayout& aDataLayout,
const dom::GPUTexelCopyBufferLayout& aDataLayout,
const dom::GPUExtent3D& aSize, ErrorResult& aRv) {
ffi::WGPUImageCopyTexture copyView = {};
CommandEncoder::ConvertTextureCopyViewToFFI(aDestination, &copyView);
@ -214,8 +214,8 @@ static WebGLTexelFormat ToWebGLTexelFormat(dom::GPUTextureFormat aFormat) {
}
void Queue::CopyExternalImageToTexture(
const dom::GPUImageCopyExternalImage& aSource,
const dom::GPUImageCopyTextureTagged& aDestination,
const dom::GPUCopyExternalImageSourceInfo& aSource,
const dom::GPUCopyExternalImageDestInfo& aDestination,
const dom::GPUExtent3D& aCopySize, ErrorResult& aRv) {
const auto dstFormat = ToWebGLTexelFormat(aDestination.mTexture->Format());
if (dstFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion) {

View file

@ -20,8 +20,10 @@ template <typename T>
class Optional;
template <typename T>
class Sequence;
struct GPUImageCopyTexture;
struct GPUImageDataLayout;
struct GPUCopyExternalImageDestInfo;
struct GPUCopyExternalImageSourceInfo;
struct GPUTexelCopyTextureInfo;
struct GPUTexelCopyBufferLayout;
struct TextureCopyView;
struct TextureDataLayout;
using GPUExtent3D = RangeEnforcedUnsignedLongSequenceOrGPUExtent3DDict;
@ -50,14 +52,14 @@ class Queue final : public ObjectBase, public ChildOf<Device> {
uint64_t aDataOffset, const dom::Optional<uint64_t>& aSize,
ErrorResult& aRv);
void WriteTexture(const dom::GPUImageCopyTexture& aDestination,
void WriteTexture(const dom::GPUTexelCopyTextureInfo& aDestination,
const dom::ArrayBufferViewOrArrayBuffer& aData,
const dom::GPUImageDataLayout& aDataLayout,
const dom::GPUTexelCopyBufferLayout& aDataLayout,
const dom::GPUExtent3D& aSize, ErrorResult& aRv);
void CopyExternalImageToTexture(
const dom::GPUImageCopyExternalImage& aSource,
const dom::GPUImageCopyTextureTagged& aDestination,
const dom::GPUCopyExternalImageSourceInfo& aSource,
const dom::GPUCopyExternalImageDestInfo& aDestination,
const dom::GPUExtent3D& aCopySize, ErrorResult& aRv);
private:

View file

@ -50,9 +50,9 @@ interface Element : Node {
[CEReactions, NeedsSubjectPrincipal=NonSystem, Throws]
boolean toggleAttribute(DOMString name, optional boolean force);
[CEReactions, NeedsSubjectPrincipal=NonSystem, Throws]
undefined setAttribute(DOMString name, DOMString value);
undefined setAttribute(DOMString name, (TrustedType or DOMString) value);
[CEReactions, NeedsSubjectPrincipal=NonSystem, Throws]
undefined setAttributeNS(DOMString? namespace, DOMString name, DOMString value);
undefined setAttributeNS(DOMString? namespace, DOMString name, (TrustedType or DOMString) value);
[CEReactions, Throws]
undefined removeAttribute(DOMString name);
[CEReactions, Throws]
@ -417,3 +417,6 @@ partial interface Element {
[Pref="dom.webcomponents.shadowdom.declarative.enabled"]
DOMString getHTML(optional GetHTMLOptions options = {});
};
// https://w3c.github.io/trusted-types/dist/spec/#integrations
typedef (TrustedHTML or TrustedScript or TrustedScriptURL) TrustedType;

View file

@ -886,31 +886,31 @@ dictionary GPUVertexAttribute {
required GPUIndex32 shaderLocation;
};
dictionary GPUImageDataLayout {
dictionary GPUTexelCopyBufferLayout {
GPUSize64 offset = 0;
GPUSize32 bytesPerRow;
GPUSize32 rowsPerImage;
};
dictionary GPUImageCopyBuffer
: GPUImageDataLayout {
dictionary GPUTexelCopyBufferInfo
: GPUTexelCopyBufferLayout {
required GPUBuffer buffer;
};
dictionary GPUImageCopyTexture {
dictionary GPUTexelCopyTextureInfo {
required GPUTexture texture;
GPUIntegerCoordinate mipLevel = 0;
GPUOrigin3D origin = {};
GPUTextureAspect aspect = "all";
};
dictionary GPUImageCopyTextureTagged
: GPUImageCopyTexture {
dictionary GPUCopyExternalImageDestInfo
: GPUTexelCopyTextureInfo {
//GPUPredefinedColorSpace colorSpace = "srgb"; //TODO
boolean premultipliedAlpha = false;
};
dictionary GPUImageCopyExternalImage {
dictionary GPUCopyExternalImageSourceInfo {
required (ImageBitmap or HTMLCanvasElement or OffscreenCanvas) source;
GPUOrigin2D origin = {};
boolean flipY = false;
@ -943,18 +943,18 @@ interface GPUCommandEncoder {
GPUSize64 size);
undefined copyBufferToTexture(
GPUImageCopyBuffer source,
GPUImageCopyTexture destination,
GPUTexelCopyBufferInfo source,
GPUTexelCopyTextureInfo destination,
GPUExtent3D copySize);
undefined copyTextureToBuffer(
GPUImageCopyTexture source,
GPUImageCopyBuffer destination,
GPUTexelCopyTextureInfo source,
GPUTexelCopyBufferInfo destination,
GPUExtent3D copySize);
undefined copyTextureToTexture(
GPUImageCopyTexture source,
GPUImageCopyTexture destination,
GPUTexelCopyTextureInfo source,
GPUTexelCopyTextureInfo destination,
GPUExtent3D copySize);
undefined clearBuffer(
@ -1166,15 +1166,15 @@ interface GPUQueue {
[Throws]
undefined writeTexture(
GPUImageCopyTexture destination,
GPUTexelCopyTextureInfo destination,
BufferSource data,
GPUImageDataLayout dataLayout,
GPUTexelCopyBufferLayout dataLayout,
GPUExtent3D size);
[Throws]
undefined copyExternalImageToTexture(
GPUImageCopyExternalImage source,
GPUImageCopyTextureTagged destination,
GPUCopyExternalImageSourceInfo source,
GPUCopyExternalImageDestInfo destination,
GPUExtent3D copySize);
};
GPUQueue includes GPUObjectBase;

View file

@ -41,10 +41,10 @@
"file": "helper_fission_animation_styling_in_transformed_oopif.html",
"prefs": animation_prefs
},
{
file: "helper_fission_irregular_areas.html",
"prefs": hit_test_prefs
},
// { Bug 1929541 - Intermittent failures, disabled until fixed
// file: "helper_fission_irregular_areas.html",
// "prefs": hit_test_prefs
// },
{
file: "helper_fission_empty_clip.html",
"prefs": hit_test_prefs

View file

@ -7,7 +7,7 @@
#ifndef MOZILLA_GFX_VideoProcessorD3D11_H
#define MOZILLA_GFX_VideoProcessorD3D11_H
#include <winerror.h>
#include <d3d11.h>
#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"

View file

@ -14,7 +14,7 @@ fuzzy-if(winWidget,0-1,0-4) == 1435143.html 1435143-ref.html
== 1444904.html 1444904-ref.html
fuzzy-if(winWidget,46-95,1000-1100) fuzzy-if(cocoaWidget&&swgl,1-1,1-1) == 1451168.html 1451168-ref.html
== 1461313.html 1461313-ref.html
fuzzy-if(!useDrawSnapshot,0-5,0-1060) fuzzy-if(useDrawSnapshot,32-32,26350-26350) fuzzy-if(Android&&device&&!swgl,31-31,2028-2028) == 1463802.html 1463802-ref.html
fuzzy-if(!useDrawSnapshot,0-5,0-1060) fuzzy-if(useDrawSnapshot,32-32,26350-26350) == 1463802.html 1463802-ref.html
fuzzy(0-11,0-4) fails-if(useDrawSnapshot) == 1474722.html 1474722-ref.html
fails-if(useDrawSnapshot) == 1501195.html 1501195-ref.html
== 1519754.html 1519754-ref.html

View file

@ -49,6 +49,10 @@
#include "mozilla/Services.h"
namespace TelemetryScalar {
void Set(mozilla::Telemetry::ScalarID aId, uint32_t aValue);
}
namespace mozilla::ipc {
using namespace layers;
@ -256,7 +260,7 @@ mozilla::ipc::IPCResult UtilityProcessChild::RecvTestTriggerMetrics(
mozilla::ipc::IPCResult UtilityProcessChild::RecvTestTelemetryProbes() {
const uint32_t kExpectedUintValue = 42;
Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_UTILITY_ONLY_UINT,
TelemetryScalar::Set(Telemetry::ScalarID::TELEMETRY_TEST_UTILITY_ONLY_UINT,
kExpectedUintValue);
return IPC_OK();
}

View file

@ -135,7 +135,8 @@ class TracingContext {
// currently set tracing context.
class Functor {
public:
virtual void operator()(TracingContext* tcx, char* buf, size_t bufsize) = 0;
virtual void operator()(TracingContext* tcx, const char* name, char* buf,
size_t bufsize) = 0;
};
private:

View file

@ -1755,9 +1755,10 @@ bool js::Stringify(JSContext* cx, MutableHandleValue vp, JSObject* replacer_,
}
/* https://262.ecma-international.org/14.0/#sec-internalizejsonproperty */
static bool InternalizeJSONProperty(
JSContext* cx, HandleObject holder, HandleId name, HandleValue reviver,
MutableHandle<ParseRecordObject> parseRecord, MutableHandleValue vp) {
static bool InternalizeJSONProperty(JSContext* cx, HandleObject holder,
HandleId name, HandleValue reviver,
Handle<ParseRecordObject*> parseRecord,
MutableHandleValue vp) {
AutoCheckRecursionLimit recursion(cx);
if (!recursion.check(cx)) {
return false;
@ -1770,29 +1771,31 @@ static bool InternalizeJSONProperty(
}
RootedObject context(cx);
Rooted<UniquePtr<ParseRecordObject::EntryMap>> entries(cx);
Rooted<ParseRecordObject::EntryMap*> entries(cx);
if (JS::Prefs::experimental_json_parse_with_source()) {
// https://tc39.es/proposal-json-parse-with-source/#sec-internalizejsonproperty
bool sameVal = false;
Rooted<Value> parsedValue(cx, parseRecord.get().value);
if (!SameValue(cx, parsedValue, val, &sameVal)) {
return false;
}
if (!parseRecord.get().isEmpty() && sameVal) {
if (parseRecord.get().parseNode) {
MOZ_ASSERT(!val.isObject());
Rooted<IdValueVector> props(cx, cx);
if (!props.emplaceBack(
IdValuePair(NameToId(cx->names().source),
StringValue(parseRecord.get().parseNode)))) {
return false;
}
context = NewPlainObjectWithUniqueNames(cx, props);
if (!context) {
return false;
}
if (parseRecord) {
bool sameVal = false;
Rooted<Value> parsedValue(cx, parseRecord->getValue());
if (!SameValue(cx, parsedValue, val, &sameVal)) {
return false;
}
if (parseRecord->hasValue() && sameVal) {
if (parseRecord->getParseNode()) {
MOZ_ASSERT(!val.isObject());
Rooted<IdValueVector> props(cx, cx);
if (!props.emplaceBack(
IdValuePair(NameToId(cx->names().source),
StringValue(parseRecord->getParseNode())))) {
return false;
}
context = NewPlainObjectWithUniqueNames(cx, props);
if (!context) {
return false;
}
}
entries = parseRecord->getEntries(cx);
}
entries = std::move(parseRecord.get().entries);
}
if (!context) {
context = NewPlainObject(cx);
@ -1831,13 +1834,17 @@ static bool InternalizeJSONProperty(
}
/* Step 2a(iii)(1). */
Rooted<ParseRecordObject> elementRecord(cx);
Rooted<ParseRecordObject*> elementRecord(cx);
if (entries) {
if (auto entry = entries->lookup(id)) {
elementRecord = std::move(entry->value());
Rooted<Value> value(cx);
if (!JS_GetPropertyById(cx, entries, id, &value)) {
return false;
}
if (!value.isNullOrUndefined()) {
elementRecord = &value.toObject().as<ParseRecordObject>();
}
}
if (!InternalizeJSONProperty(cx, obj, id, reviver, &elementRecord,
if (!InternalizeJSONProperty(cx, obj, id, reviver, elementRecord,
&newElement)) {
return false;
}
@ -1877,13 +1884,17 @@ static bool InternalizeJSONProperty(
/* Step 2c(ii)(1). */
id = keys[i];
Rooted<ParseRecordObject> entryRecord(cx);
Rooted<ParseRecordObject*> entryRecord(cx);
if (entries) {
if (auto entry = entries->lookup(id)) {
entryRecord = std::move(entry->value());
Rooted<Value> value(cx);
if (!JS_GetPropertyById(cx, entries, id, &value)) {
return false;
}
if (!value.isNullOrUndefined()) {
entryRecord = &value.toObject().as<ParseRecordObject>();
}
}
if (!InternalizeJSONProperty(cx, obj, id, reviver, &entryRecord,
if (!InternalizeJSONProperty(cx, obj, id, reviver, entryRecord,
&newElement)) {
return false;
}
@ -1924,8 +1935,7 @@ static bool InternalizeJSONProperty(
}
static bool Revive(JSContext* cx, HandleValue reviver,
MutableHandle<ParseRecordObject> pro,
MutableHandleValue vp) {
Handle<ParseRecordObject*> pro, MutableHandleValue vp) {
Rooted<PlainObject*> obj(cx, NewPlainObject(cx));
if (!obj) {
return false;
@ -1936,7 +1946,7 @@ static bool Revive(JSContext* cx, HandleValue reviver,
}
MOZ_ASSERT_IF(JS::Prefs::experimental_json_parse_with_source(),
pro.get().value == vp.get());
pro->getValue() == vp.get());
Rooted<jsid> id(cx, NameToId(cx->names().empty_));
return InternalizeJSONProperty(cx, obj, id, reviver, pro, vp);
}
@ -1956,7 +1966,7 @@ bool js::ParseJSONWithReviver(JSContext* cx,
js::AutoGeckoProfilerEntry pseudoFrame(cx, "parse JSON",
JS::ProfilingCategoryPair::JS_Parsing);
/* https://262.ecma-international.org/14.0/#sec-json.parse steps 2-10. */
Rooted<ParseRecordObject> pro(cx);
Rooted<ParseRecordObject*> pro(cx);
if (JS::Prefs::experimental_json_parse_with_source() && IsCallable(reviver)) {
Rooted<JSONReviveParser<CharT>> parser(cx, cx, chars);
if (!parser.get().parse(vp, &pro)) {
@ -1968,7 +1978,7 @@ bool js::ParseJSONWithReviver(JSContext* cx,
/* Steps 11-12. */
if (IsCallable(reviver)) {
return Revive(cx, reviver, &pro, vp);
return Revive(cx, reviver, pro, vp);
}
return true;
}

View file

@ -6,40 +6,83 @@
#include "builtin/ParseRecordObject.h"
#include "jsapi.h" // JS_ValueToId, JS_IdToValue
#include "builtin/Object.h"
#include "vm/PlainObject.h"
#include "vm/JSObject-inl.h" // NewBuiltinClassInstance
using namespace js;
// https://tc39.es/proposal-json-parse-with-source/#sec-json-parse-record
ParseRecordObject::ParseRecordObject()
: parseNode(nullptr), key(JS::PropertyKey::Void()) {}
const JSClass ParseRecordObject::class_ = {
"ParseRecordObject",
JSCLASS_HAS_RESERVED_SLOTS(SlotCount),
};
ParseRecordObject::ParseRecordObject(Handle<js::JSONParseNode*> parseNode,
const Value& val)
: parseNode(parseNode), key(JS::PropertyKey::Void()), value(val) {}
/* static */
ParseRecordObject* ParseRecordObject::create(JSContext* cx, const Value& val) {
Rooted<JSONParseNode*> parseNode(cx);
return ParseRecordObject::create(cx, parseNode, val);
}
bool ParseRecordObject::addEntries(JSContext* cx, EntryMap&& appendEntries) {
if (!entries) {
entries = js::MakeUnique<EntryMap>(std::move(appendEntries));
if (!entries) {
ReportOutOfMemory(cx);
}
return !!entries;
/* static */
ParseRecordObject* ParseRecordObject::create(JSContext* cx,
Handle<JSONParseNode*> parseNode,
const Value& val) {
Rooted<ParseRecordObject*> obj(
cx, NewObjectWithGivenProto<ParseRecordObject>(cx, nullptr));
if (!obj) {
return nullptr;
}
for (auto iter = appendEntries.iter(); !iter.done(); iter.next()) {
if (!entries->put(iter.get().key(), std::move(iter.get().value()))) {
if (parseNode) {
obj->initSlot(ParseNodeSlot, StringValue(parseNode));
}
obj->initSlot(ValueSlot, val);
return obj;
}
JS::PropertyKey ParseRecordObject::getKey(JSContext* cx) const {
Rooted<Value> slot(cx, getSlot(KeySlot));
Rooted<JS::PropertyKey> key(cx);
MOZ_ALWAYS_TRUE(JS_ValueToId(cx, slot, &key));
return key;
};
bool ParseRecordObject::setKey(JSContext* cx, const JS::PropertyKey& key) {
Rooted<Value> val(cx);
if (!JS_IdToValue(cx, key, &val)) {
return false;
}
setSlot(KeySlot, val);
return true;
}
bool ParseRecordObject::setEntries(JSContext* cx, Handle<EntryMap*> entries) {
Rooted<JS::IdVector> props(cx, IdVector(cx));
Rooted<JSObject*> obj(cx, this);
if (!JS_Enumerate(cx, entries, &props)) {
return false;
}
Rooted<Value> prop(cx);
for (uint32_t i = 0; i < props.length(); i++) {
if (!JS_GetPropertyById(cx, entries, props[i], &prop)) {
return false;
}
if (!JS_SetPropertyById(cx, obj, props[i], prop)) {
return false;
}
}
return true;
}
void ParseRecordObject::trace(JSTracer* trc) {
JS::TraceRoot(trc, &parseNode, "ParseRecordObject parse node");
JS::TraceRoot(trc, &key, "ParseRecordObject key");
JS::TraceRoot(trc, &value, "ParseRecordObject value");
if (entries) {
entries->trace(trc);
ParseRecordObject::EntryMap* ParseRecordObject::getEntries(JSContext* cx) {
Rooted<JSObject*> obj(cx, this);
int32_t length = 0;
if (!obj_keys_length(cx, obj, length)) {
return nullptr;
}
return length ? obj.get() : nullptr;
}

View file

@ -15,46 +15,45 @@ namespace js {
using JSONParseNode = JSString;
class ParseRecordObject {
class ParseRecordObject : public NativeObject {
enum { ParseNodeSlot, ValueSlot, KeySlot, EntriesSlot, SlotCount };
public:
using EntryMap = js::GCHashMap<PropertyKey, ParseRecordObject>;
using EntryMap = JSObject;
static const JSClass class_;
static ParseRecordObject* create(JSContext* cx, const Value& val);
static ParseRecordObject* create(JSContext* cx,
Handle<js::JSONParseNode*> parseNode,
const Value& val);
// The source text that was parsed for this record. According to the spec, we
// don't track this for objects and arrays, so it will be a null pointer.
JSONParseNode* parseNode;
// For object members, the member key. For arrays, the index. For JSON
// primitives, it will be undefined.
JS::PropertyKey key;
// The original value corresponding to this record, used to determine if the
// reviver function has modified it.
Value value;
// For objects and arrays, the records for the members and elements
// (respectively). If there are none, or for JSON primitives, we won't
// allocate an EntryMap.
UniquePtr<EntryMap> entries;
ParseRecordObject();
ParseRecordObject(Handle<js::JSONParseNode*> parseNode, const Value& val);
ParseRecordObject(ParseRecordObject&& other)
: parseNode(std::move(other.parseNode)),
key(std::move(other.key)),
value(std::move(other.value)),
entries(std::move(other.entries)) {}
bool isEmpty() const { return value.isUndefined(); }
bool addEntries(JSContext* cx, EntryMap&& appendEntries);
// move assignment
ParseRecordObject& operator=(ParseRecordObject&& other) noexcept {
parseNode = other.parseNode;
key = other.key;
value = other.value;
entries = std::move(other.entries);
return *this;
JSONParseNode* getParseNode() const {
const Value& slot = getSlot(ParseNodeSlot);
return slot.isUndefined() ? nullptr : slot.toString();
}
void trace(JSTracer* trc);
// For object members, the member key. For arrays, the index. For JSON
// primitives, it will be undefined.
JS::PropertyKey getKey(JSContext* cx) const;
bool setKey(JSContext* cx, const JS::PropertyKey& key);
// The original value corresponding to this record, used to determine if the
// reviver function has modified it.
const Value& getValue() const { return getSlot(ValueSlot); }
void setValue(JS::Handle<JS::Value> value) { setSlot(ValueSlot, value); }
bool hasValue() const { return !getValue().isUndefined(); }
// For objects and arrays, the records for the members and elements
// (respectively). If there are none, or for JSON primitives, return null.
EntryMap* getEntries(JSContext* cx);
bool setEntries(JSContext* cx, Handle<EntryMap*> entries);
};
} // namespace js

View file

@ -102,9 +102,6 @@ constexpr size_t INITIAL_CHAR_BUFFER_SIZE = 32;
void AddICUCellMemory(JSObject* obj, size_t nbytes);
void RemoveICUCellMemory(JS::GCContext* gcx, JSObject* obj, size_t nbytes);
JSLinearString* CanonicalizeTimeZone(JSContext* cx,
JS::Handle<JSString*> timeZone);
} // namespace intl
} // namespace js

View file

@ -365,69 +365,51 @@ bool js::intl_IsValidTimeZoneName(JSContext* cx, unsigned argc, Value* vp) {
} else {
args.rval().setNull();
}
return true;
}
JSLinearString* js::intl::CanonicalizeTimeZone(JSContext* cx,
Handle<JSString*> timeZone) {
SharedIntlData& sharedIntlData = cx->runtime()->sharedIntlData.ref();
// Some time zone names are canonicalized differently by ICU -- handle those
// first.
Rooted<JSAtom*> ianaTimeZone(cx);
if (!sharedIntlData.tryCanonicalizeTimeZoneConsistentWithIANA(
cx, timeZone, &ianaTimeZone)) {
return nullptr;
}
JSLinearString* resultTimeZone;
if (ianaTimeZone) {
cx->markAtom(ianaTimeZone);
resultTimeZone = ianaTimeZone;
} else {
AutoStableStringChars stableChars(cx);
if (!stableChars.initTwoByte(cx, timeZone)) {
return nullptr;
}
// Call into ICU to canonicalize the time zone.
FormatBuffer<char16_t, INITIAL_CHAR_BUFFER_SIZE> canonicalTimeZone(cx);
auto result = mozilla::intl::TimeZone::GetCanonicalTimeZoneID(
stableChars.twoByteRange(), canonicalTimeZone);
if (result.isErr()) {
ReportInternalError(cx, result.unwrapErr());
return nullptr;
}
resultTimeZone = canonicalTimeZone.toString(cx);
if (!resultTimeZone) {
return nullptr;
}
}
MOZ_ASSERT(!StringEqualsLiteral(resultTimeZone, "Etc/Unknown"),
"Invalid canonical time zone");
// Links to UTC are handled by SharedIntlData.
MOZ_ASSERT(!StringEqualsLiteral(resultTimeZone, "GMT"));
MOZ_ASSERT(!StringEqualsLiteral(resultTimeZone, "Etc/UTC"));
MOZ_ASSERT(!StringEqualsLiteral(resultTimeZone, "Etc/GMT"));
return resultTimeZone;
}
bool js::intl_canonicalizeTimeZone(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
MOZ_ASSERT(args[0].isString());
SharedIntlData& sharedIntlData = cx->runtime()->sharedIntlData.ref();
// Some time zone names are canonicalized differently by ICU -- handle
// those first:
RootedString timeZone(cx, args[0].toString());
auto* result = intl::CanonicalizeTimeZone(cx, timeZone);
if (!result) {
Rooted<JSAtom*> ianaTimeZone(cx);
if (!sharedIntlData.tryCanonicalizeTimeZoneConsistentWithIANA(
cx, timeZone, &ianaTimeZone)) {
return false;
}
args.rval().setString(result);
if (ianaTimeZone) {
cx->markAtom(ianaTimeZone);
args.rval().setString(ianaTimeZone);
return true;
}
AutoStableStringChars stableChars(cx);
if (!stableChars.initTwoByte(cx, timeZone)) {
return false;
}
FormatBuffer<char16_t, intl::INITIAL_CHAR_BUFFER_SIZE> canonicalTimeZone(cx);
auto result = mozilla::intl::TimeZone::GetCanonicalTimeZoneID(
stableChars.twoByteRange(), canonicalTimeZone);
if (result.isErr()) {
intl::ReportInternalError(cx, result.unwrapErr());
return false;
}
JSString* str = canonicalTimeZone.toString(cx);
if (!str) {
return false;
}
args.rval().setString(str);
return true;
}

View file

@ -195,10 +195,10 @@ function CanonicalizeTimeZoneName(timeZone) {
"Unsupported canonical time zone"
);
// Step 3. (Not applicable.)
assert(ianaTimeZone !== "Etc/UTC", "Invalid link to UTC");
assert(ianaTimeZone !== "Etc/GMT", "Invalid link to UTC");
assert(ianaTimeZone !== "GMT", "Invalid link to UTC");
// Step 3.
if (ianaTimeZone === "Etc/UTC" || ianaTimeZone === "Etc/GMT") {
ianaTimeZone = "UTC";
}
// Step 4.
return ianaTimeZone;

View file

@ -736,7 +736,8 @@ static ArrayObject* AvailableNumberingSystems(JSContext* cx) {
* AvailableTimeZones ( )
*/
static ArrayObject* AvailableTimeZones(JSContext* cx) {
// Unsorted list of canonical time zone names, possibly containing duplicates.
// Unsorted list of canonical time zone names, possibly containing
// duplicates.
Rooted<StringList> timeZones(cx, StringList(cx));
intl::SharedIntlData& sharedIntlData = cx->runtime()->sharedIntlData.ref();
@ -747,15 +748,54 @@ static ArrayObject* AvailableTimeZones(JSContext* cx) {
auto iter = iterResult.unwrap();
Rooted<JSAtom*> validatedTimeZone(cx);
Rooted<JSAtom*> ianaTimeZone(cx);
for (; !iter.done(); iter.next()) {
validatedTimeZone = iter.get();
// Canonicalize the time zone before adding it to the result array.
auto* timeZone = intl::CanonicalizeTimeZone(cx, validatedTimeZone);
if (!timeZone) {
// Some time zone names are canonicalized differently by ICU -- handle
// those first.
ianaTimeZone.set(nullptr);
if (!sharedIntlData.tryCanonicalizeTimeZoneConsistentWithIANA(
cx, validatedTimeZone, &ianaTimeZone)) {
return nullptr;
}
JSLinearString* timeZone;
if (ianaTimeZone) {
cx->markAtom(ianaTimeZone);
timeZone = ianaTimeZone;
} else {
// Call into ICU to canonicalize the time zone.
JS::AutoStableStringChars stableChars(cx);
if (!stableChars.initTwoByte(cx, validatedTimeZone)) {
return nullptr;
}
intl::FormatBuffer<char16_t, intl::INITIAL_CHAR_BUFFER_SIZE>
canonicalTimeZone(cx);
auto result = mozilla::intl::TimeZone::GetCanonicalTimeZoneID(
stableChars.twoByteRange(), canonicalTimeZone);
if (result.isErr()) {
intl::ReportInternalError(cx, result.unwrapErr());
return nullptr;
}
timeZone = canonicalTimeZone.toString(cx);
if (!timeZone) {
return nullptr;
}
// Canonicalize both to "UTC" per CanonicalizeTimeZoneName().
if (StringEqualsLiteral(timeZone, "Etc/UTC") ||
StringEqualsLiteral(timeZone, "Etc/GMT")) {
timeZone = cx->names().UTC;
}
}
if (!timeZones.append(timeZone)) {
return nullptr;
}

View file

@ -10,26 +10,58 @@ namespace timezone {
// Format:
// "ZoneName" // ICU-Name [time zone file]
const char* const ianaZonesTreatedAsLinksByICU[] = {
"Africa/Asmara", // Africa/Asmera [backward]
"Africa/Asmara", // Africa/Asmera [backzone]
"Africa/Timbuktu", // Africa/Bamako [backzone]
"America/Argentina/Buenos_Aires", // America/Buenos_Aires [southamerica]
"America/Argentina/Catamarca", // America/Catamarca [southamerica]
"America/Argentina/ComodRivadavia", // America/Catamarca [backzone]
"America/Argentina/Cordoba", // America/Cordoba [southamerica]
"America/Argentina/Jujuy", // America/Jujuy [southamerica]
"America/Argentina/Mendoza", // America/Mendoza [southamerica]
"America/Atikokan", // America/Coral_Harbour [backward]
"America/Atikokan", // America/Coral_Harbour [backzone]
"America/Ensenada", // America/Tijuana [backzone]
"America/Indiana/Indianapolis", // America/Indianapolis [northamerica]
"America/Kentucky/Louisville", // America/Louisville [northamerica]
"America/Montreal", // America/Toronto [backzone]
"America/Nipigon", // America/Toronto [backzone]
"America/Nuuk", // America/Godthab [europe]
"America/Pangnirtung", // America/Iqaluit [backzone]
"America/Rainy_River", // America/Winnipeg [backzone]
"America/Rosario", // America/Cordoba [backzone]
"America/Thunder_Bay", // America/Toronto [backzone]
"America/Yellowknife", // America/Edmonton [backzone]
"Asia/Chongqing", // Asia/Shanghai [backzone]
"Asia/Harbin", // Asia/Shanghai [backzone]
"Asia/Ho_Chi_Minh", // Asia/Saigon [asia]
"Asia/Kashgar", // Asia/Urumqi [backzone]
"Asia/Kathmandu", // Asia/Katmandu [asia]
"Asia/Kolkata", // Asia/Calcutta [asia]
"Asia/Tel_Aviv", // Asia/Jerusalem [backzone]
"Asia/Yangon", // Asia/Rangoon [asia]
"Atlantic/Faroe", // Atlantic/Faeroe [europe]
"Atlantic/Jan_Mayen", // Arctic/Longyearbyen [backzone]
"Australia/Currie", // Australia/Hobart [backzone]
"CET", // Europe/Brussels [backzone]
"CST6CDT", // America/Chicago [backzone]
"EET", // Europe/Athens [backzone]
"EST", // America/Panama [backzone]
"EST5EDT", // America/New_York [backzone]
"Europe/Belfast", // Europe/London [backzone]
"Europe/Kyiv", // Europe/Kiev [europe]
"Pacific/Chuuk", // Pacific/Truk [backward]
"Europe/Tiraspol", // Europe/Chisinau [backzone]
"Europe/Uzhgorod", // Europe/Kiev [backzone]
"Europe/Zaporozhye", // Europe/Kiev [backzone]
"Factory", // Etc/Unknown [factory]
"HST", // Pacific/Honolulu [backzone]
"MET", // Europe/Brussels [backzone]
"MST", // America/Phoenix [backzone]
"MST7MDT", // America/Denver [backzone]
"PST8PDT", // America/Los_Angeles [backzone]
"Pacific/Chuuk", // Pacific/Truk [backzone]
"Pacific/Johnston", // Pacific/Honolulu [backzone]
"Pacific/Kanton", // Pacific/Enderbury [australasia]
"Pacific/Pohnpei", // Pacific/Ponape [backward]
"UTC", // Etc/UTC [backward]
"Pacific/Pohnpei", // Pacific/Ponape [backzone]
"WET", // Europe/Lisbon [backzone]
};
// Format:
@ -42,49 +74,38 @@ struct LinkAndTarget
const LinkAndTarget ianaLinksCanonicalizedDifferentlyByICU[] = {
{ "Africa/Asmera", "Africa/Asmara" }, // Africa/Asmera [backward]
{ "America/Argentina/ComodRivadavia", "America/Argentina/Catamarca" }, // America/Catamarca [backward]
{ "America/Buenos_Aires", "America/Argentina/Buenos_Aires" }, // America/Buenos_Aires [backward]
{ "America/Catamarca", "America/Argentina/Catamarca" }, // America/Catamarca [backward]
{ "America/Coral_Harbour", "America/Atikokan" }, // America/Coral_Harbour [backward]
{ "America/Cordoba", "America/Argentina/Cordoba" }, // America/Cordoba [backward]
{ "America/Fort_Wayne", "America/Indiana/Indianapolis" }, // America/Indianapolis [backward]
{ "America/Godthab", "America/Nuuk" }, // America/Godthab [backward]
{ "America/Indianapolis", "America/Indiana/Indianapolis" }, // America/Indianapolis [backward]
{ "America/Jujuy", "America/Argentina/Jujuy" }, // America/Jujuy [backward]
{ "America/Kralendijk", "America/Curacao" }, // America/Kralendijk [backward]
{ "America/Louisville", "America/Kentucky/Louisville" }, // America/Louisville [backward]
{ "America/Lower_Princes", "America/Curacao" }, // America/Lower_Princes [backward]
{ "America/Marigot", "America/Port_of_Spain" }, // America/Marigot [backward]
{ "America/Mendoza", "America/Argentina/Mendoza" }, // America/Mendoza [backward]
{ "America/Rosario", "America/Argentina/Cordoba" }, // America/Cordoba [backward]
{ "America/St_Barthelemy", "America/Port_of_Spain" }, // America/St_Barthelemy [backward]
{ "Antarctica/South_Pole", "Antarctica/McMurdo" }, // Pacific/Auckland [backward]
{ "Arctic/Longyearbyen", "Europe/Oslo" }, // Arctic/Longyearbyen [backward]
{ "Asia/Calcutta", "Asia/Kolkata" }, // Asia/Calcutta [backward]
{ "Asia/Chungking", "Asia/Chongqing" }, // Asia/Shanghai [backward]
{ "Asia/Katmandu", "Asia/Kathmandu" }, // Asia/Katmandu [backward]
{ "Asia/Rangoon", "Asia/Yangon" }, // Asia/Rangoon [backward]
{ "Asia/Saigon", "Asia/Ho_Chi_Minh" }, // Asia/Saigon [backward]
{ "Atlantic/Faeroe", "Atlantic/Faroe" }, // Atlantic/Faeroe [backward]
{ "Etc/GMT", "UTC" }, // Etc/GMT [etcetera]
{ "Etc/GMT+0", "UTC" }, // Etc/GMT [backward]
{ "Etc/GMT-0", "UTC" }, // Etc/GMT [backward]
{ "Etc/GMT0", "UTC" }, // Etc/GMT [backward]
{ "Etc/Greenwich", "UTC" }, // Etc/GMT [backward]
{ "Etc/UCT", "UTC" }, // Etc/UTC [backward]
{ "Etc/UTC", "UTC" }, // Etc/UTC [etcetera]
{ "Etc/Universal", "UTC" }, // Etc/UTC [backward]
{ "Etc/Zulu", "UTC" }, // Etc/UTC [backward]
{ "Europe/Bratislava", "Europe/Prague" }, // Europe/Bratislava [backward]
{ "Europe/Busingen", "Europe/Zurich" }, // Europe/Busingen [backward]
{ "Europe/Kiev", "Europe/Kyiv" }, // Europe/Kiev [backward]
{ "Europe/Uzhgorod", "Europe/Kyiv" }, // Europe/Kiev [backward]
{ "Europe/Zaporozhye", "Europe/Kyiv" }, // Europe/Kiev [backward]
{ "GMT", "UTC" }, // Etc/GMT [etcetera]
{ "GMT+0", "UTC" }, // Etc/GMT [backward]
{ "GMT-0", "UTC" }, // Etc/GMT [backward]
{ "GMT0", "UTC" }, // Etc/GMT [backward]
{ "Greenwich", "UTC" }, // Etc/GMT [backward]
{ "Pacific/Enderbury", "Pacific/Kanton" }, // Pacific/Enderbury [backward]
{ "Europe/Mariehamn", "Europe/Helsinki" }, // Europe/Mariehamn [backward]
{ "Europe/Podgorica", "Europe/Belgrade" }, // Europe/Podgorica [backward]
{ "Europe/San_Marino", "Europe/Rome" }, // Europe/San_Marino [backward]
{ "Europe/Vatican", "Europe/Rome" }, // Europe/Vatican [backward]
{ "Pacific/Ponape", "Pacific/Pohnpei" }, // Pacific/Ponape [backward]
{ "Pacific/Truk", "Pacific/Chuuk" }, // Pacific/Truk [backward]
{ "Pacific/Yap", "Pacific/Chuuk" }, // Pacific/Truk [backward]
{ "UCT", "UTC" }, // Etc/UTC [backward]
{ "US/East-Indiana", "America/Indiana/Indianapolis" }, // America/Indianapolis [backward]
{ "Universal", "UTC" }, // Etc/UTC [backward]
{ "Zulu", "UTC" }, // Etc/UTC [backward]
};
// Legacy ICU time zones, these are not valid IANA time zone names. We also
@ -118,7 +139,6 @@ const char* const legacyICUTimeZones[] = {
"SST",
"US/Pacific-New",
"VST",
"Factory",
"SystemV/AST4",
"SystemV/AST4ADT",
"SystemV/CST6",

View file

@ -1,157 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Provide mapping from time zone identifiers to region codes for time zones
# which aren't listed in tzdata's zone.tab file.
Africa/Timbuktu: ML
Africa/Asmera: ER
America/Argentina/ComodRivadavia: AR
America/Atka: US
America/Buenos_Aires: AR
America/Catamarca: AR
America/Coral_Harbour: CA
America/Cordoba: AR
America/Ensenada: MX
America/Fort_Wayne: US
America/Godthab: GL
America/Indianapolis: US
America/Jujuy: AR
America/Knox_IN: US
America/Louisville: US
America/Mendoza: AR
America/Montreal: CA
America/Nipigon: CA
America/Pangnirtung: CA
America/Porto_Acre: BR
America/Rainy_River: CA
America/Rosario: AR
America/Santa_Isabel: MX
America/Shiprock: US
America/Thunder_Bay: CA
America/Virgin: VI
America/Yellowknife: CA
Antarctica/South_Pole: AQ
Asia/Choibalsan: MN
Asia/Chongqing: CN
Asia/Harbin: CN
Asia/Kashgar: CN
Asia/Tel_Aviv: IL
Asia/Ashkhabad: TM
Asia/Calcutta: IN
Asia/Chungking: CN
Asia/Dacca: BD
Asia/Istanbul: TR
Asia/Katmandu: NP
Asia/Macao: MO
Asia/Rangoon: MM
Asia/Saigon: VN
Asia/Thimbu: BT
Asia/Ujung_Pandang: ID
Asia/Ulan_Bator: MN
Atlantic/Jan_Mayen: SJ
Atlantic/Faeroe: FO
Australia/ACT: AU
Australia/LHI: AU
Australia/NSW: AU
Australia/Canberra: AU
Australia/Currie: AU
Australia/North: AU
Australia/Queensland: AU
Australia/South: AU
Australia/Tasmania: AU
Australia/Victoria: AU
Australia/West: AU
Australia/Yancowinna: AU
Europe/Belfast: GB
Europe/Tiraspol: MD
Europe/Uzhgorod: UA
Europe/Zaporozhye: UA
Europe/Kiev: UA
Europe/Nicosia: CY
Pacific/Samoa: AS
Pacific/Enderbury: KI
Pacific/Johnston: US
Pacific/Yap: FM
Pacific/Ponape: FM
Pacific/Truk: FM
Brazil/Acre: BR
Brazil/DeNoronha: BR
Brazil/East: BR
Brazil/West: BR
Canada/Atlantic: CA
Canada/Central: CA
Canada/Eastern: CA
Canada/Mountain: CA
Canada/Newfoundland: CA
Canada/Pacific: CA
Canada/Saskatchewan: CA
Canada/Yukon: CA
Chile/Continental: CL
Chile/EasterIsland: CL
Mexico/BajaNorte: MX
Mexico/BajaSur: MX
Mexico/General: MX
US/Alaska: US
US/Aleutian: US
US/Arizona: US
US/Central: US
US/East-Indiana: US
US/Eastern: US
US/Hawaii: US
US/Indiana-Starke: US
US/Michigan: US
US/Mountain: US
US/Pacific: US
US/Samoa: AS
CET: BE
EET: GR
MET: BE
WET: PT
CST6CDT: US
EST5EDT: US
EST: PA
HST: US
MST7MDT: US
MST: US
PST8PDT: US
Cuba: CU
Egypt: EG
Eire: IE
GB: GB
GB-Eire: GB
Hongkong: HK
Iceland: IS
Iran: IR
Israel: IL
Jamaica: JM
Japan: JP
Kwajalein: MH
Libya: LY
NZ: NZ
NZ-CHAT: NZ
Navajo: US
PRC: CN
Poland: PL
Portugal: PT
ROC: TW
ROK: KR
Singapore: SG
Turkey: TR
W-SU: RU

View file

@ -45,19 +45,32 @@ import io
import json
import os
import re
import sys
import tarfile
import tempfile
from contextlib import closing
from functools import partial, total_ordering
from itertools import chain, filterfalse, groupby, tee, zip_longest
from itertools import chain, groupby, tee
from operator import attrgetter, itemgetter
from urllib.parse import urlsplit
from urllib.request import Request as UrlRequest
from urllib.request import urlopen
from zipfile import ZipFile
import yaml
if sys.version_info.major == 2:
from itertools import ifilter as filter
from itertools import ifilterfalse as filterfalse
from itertools import imap as map
from itertools import izip_longest as zip_longest
from urllib2 import Request as UrlRequest
from urllib2 import urlopen
from urlparse import urlsplit
else:
from itertools import filterfalse, zip_longest
from urllib.parse import urlsplit
from urllib.request import Request as UrlRequest
from urllib.request import urlopen
# From https://docs.python.org/3/library/itertools.html
def grouper(iterable, n, fillvalue=None):
@ -2202,8 +2215,7 @@ def readIANAFiles(tzdataDir, files):
nameSyntax = r"[\w/+\-]+"
pZone = re.compile(r"Zone\s+(?P<name>%s)\s+.*" % nameSyntax)
pLink = re.compile(
r"(#PACKRATLIST\s+zone.tab\s+)?Link\s+(?P<target>%s)\s+(?P<name>%s)(?:\s+#.*)?"
% (nameSyntax, nameSyntax)
r"Link\s+(?P<target>%s)\s+(?P<name>%s)(?:\s+#.*)?" % (nameSyntax, nameSyntax)
)
def createZone(line, fname):
@ -2218,7 +2230,6 @@ def readIANAFiles(tzdataDir, files):
zones = set()
links = dict()
packrat_links = dict()
for filename in files:
filepath = tzdataDir.resolve(filename)
for line in tzdataDir.readlines(filepath):
@ -2227,26 +2238,31 @@ def readIANAFiles(tzdataDir, files):
if line.startswith("Link"):
(link, target) = createLink(line, filename)
links[link] = target
if line.startswith("#PACKRATLIST zone.tab Link"):
(link, target) = createLink(line, filename)
packrat_links[link] = target
return (zones, links, packrat_links)
return (zones, links)
def readIANATimeZones(tzdataDir, ignoreFactory):
def readIANATimeZones(tzdataDir, ignoreBackzone, ignoreFactory):
"""Read the IANA time zone information from `tzdataDir`."""
files_to_ignore = ["backzone"]
# Ignore the placeholder time zone "Factory".
if ignoreFactory:
files_to_ignore.append("factory")
tzfiles = (file for file in listIANAFiles(tzdataDir) if file not in files_to_ignore)
backzoneFiles = {"backzone"}
(bkfiles, tzfiles) = partition(listIANAFiles(tzdataDir), backzoneFiles.__contains__)
# Read zone and link infos.
(zones, links, _) = readIANAFiles(tzdataDir, tzfiles)
(zones, links) = readIANAFiles(tzdataDir, tzfiles)
(backzones, backlinks) = readIANAFiles(tzdataDir, bkfiles)
# Remove the placeholder time zone "Factory".
if ignoreFactory:
zones.remove(Zone("Factory"))
# Merge with backzone data.
if not ignoreBackzone:
zones |= backzones
links = {
name: target for name, target in links.items() if name not in backzones
}
links.update(backlinks)
validateTimeZones(zones, links)
@ -2415,13 +2431,7 @@ def readICUTimeZones(icuDir, icuTzDir, ignoreFactory):
# Remove the placeholder time zone "Factory".
# See also <https://github.com/eggert/tz/blob/master/factory>.
if ignoreFactory:
assert Zone("Factory") in zoneinfoZones
assert Zone("Factory") not in zoneinfoLinks
assert Zone("Factory") not in typesZones
assert Zone("Factory") in typesLinks
zoneinfoZones.remove(Zone("Factory"))
del typesLinks[Zone("Factory")]
# Remove the ICU placeholder time zone "Etc/Unknown".
# See also <https://unicode.org/reports/tr35/#Time_Zone_Identifiers>.
@ -2487,7 +2497,7 @@ def readICULegacyZones(icuDir):
# non-IANA time zones and links.
# Most legacy, non-IANA time zones and links are in the icuzones file.
(zones, links, _) = readIANAFiles(tzdir, ["icuzones"])
(zones, links) = readIANAFiles(tzdir, ["icuzones"])
# Remove the ICU placeholder time zone "Etc/Unknown".
# See also <https://unicode.org/reports/tr35/#Time_Zone_Identifiers>.
@ -2551,7 +2561,7 @@ def icuTzDataVersion(icuTzDir):
return version
def findIncorrectICUZones(ianaZones, ianaLinks, icuZones, icuLinks):
def findIncorrectICUZones(ianaZones, ianaLinks, icuZones, icuLinks, ignoreBackzone):
"""Find incorrect ICU zone entries."""
def isIANATimeZone(zone):
@ -2565,7 +2575,11 @@ def findIncorrectICUZones(ianaZones, ianaLinks, icuZones, icuLinks):
# All IANA zones should be present in ICU.
missingTimeZones = [zone for zone in ianaZones if not isICUTimeZone(zone)]
if missingTimeZones:
# Normally zones in backzone are also present as links in one of the other
# time zone files. The only exception to this rule is the Asia/Hanoi time
# zone, this zone is only present in the backzone file.
expectedMissing = [] if ignoreBackzone else [Zone("Asia/Hanoi")]
if missingTimeZones != expectedMissing:
raise RuntimeError(
"Not all zones are present in ICU, did you forget "
"to run intl/update-tzdata.sh? %s" % missingTimeZones
@ -2646,157 +2660,28 @@ def findIncorrectICULinks(ianaZones, ianaLinks, icuZones, icuLinks):
return sorted(result, key=itemgetter(0))
def readZoneTab(tzdataDir):
zone_country = dict()
zonetab_path = tzdataDir.resolve("zone.tab")
for line in tzdataDir.readlines(zonetab_path):
if line.startswith("#"):
continue
(country, coords, zone, *comments) = line.strip().split("\t")
assert zone not in zone_country
zone_country[zone] = country
return zone_country
# 6.5.1 AvailableNamedTimeZoneIdentifiers ( )
#
# https://tc39.es/ecma402/#sup-availablenamedtimezoneidentifiers
def availableNamedTimeZoneIdentifiers(tzdataDir, ignoreFactory):
js_src_builtin_intl_dir = os.path.dirname(os.path.abspath(__file__))
with io.open(
os.path.join(js_src_builtin_intl_dir, "TimeZoneMapping.yaml"),
mode="r",
encoding="utf-8",
) as f:
time_zone_mapping = yaml.safe_load(f)
zone_country = readZoneTab(tzdataDir)
def country_code_for(name):
if name in zone_country:
return zone_country[name]
return time_zone_mapping[name]
(ianaZones, ianaLinks) = readIANATimeZones(tzdataDir, ignoreFactory)
(backzones, backlinks, packratlinks) = readIANAFiles(tzdataDir, ["backzone"])
all_backzone_links = {**backlinks, **packratlinks}
# Steps 1-3. (Not applicable)
# Step 4.
zones = set()
links = dict()
# Step 5. (Partial, only zones)
for zone in ianaZones:
# Step 5.a.
primary = zone
# Step 5.b. (Not applicable for zones)
# Step 5.c.
if primary.name in ["Etc/UTC", "Etc/GMT", "GMT"]:
primary = Zone("UTC", primary.filename)
# Step 5.d. (Not applicable)
# Steps 5.e-f.
if primary == zone:
assert zone not in zones
zones.add(primary)
else:
assert zone not in links
links[zone] = primary.name
# Step 5. (Partial, only links)
for zone, target in ianaLinks.items():
identifier = zone.name
# Step 5.a.
primary = identifier
# Step 5.b.
if identifier not in zone_country:
# Step 5.b.i. (Not applicable)
# Steps 5.b.ii-iii.
if target.startswith("Etc/"):
primary = target
else:
# Step 5.b.iii.1.
identifier_code_code = country_code_for(identifier)
# Step 5.b.iii.2.
target_code_code = country_code_for(target)
# Steps 5.b.iii.3-4
if identifier_code_code == target_code_code:
primary = target
else:
# Step 5.b.iii.4.a.
country_code_line_count = [
zone
for (zone, code) in zone_country.items()
if code == identifier_code_code
]
# Steps 5.b.iii.4.b-c.
if len(country_code_line_count) == 1:
primary = country_code_line_count[0]
else:
assert Zone(identifier) in all_backzone_links
primary = all_backzone_links[Zone(identifier)]
assert identifier_code_code == country_code_for(primary)
# Step 5.c.
if primary in ["Etc/UTC", "Etc/GMT", "GMT"]:
primary = "UTC"
# Step 5.d. (Not applicable)
# Steps 5.e-f.
if primary == identifier:
assert zone not in zones
zones.add(zone)
else:
assert zone not in links
links[zone] = primary
# Ensure all zones and links are valid.
validateTimeZones(zones, links)
# Step 6.
assert Zone("UTC") in zones
# Step 7.
return (zones, links)
generatedFileWarning = "// Generated by make_intl_data.py. DO NOT EDIT."
tzdataVersionComment = "// tzdata version = {0}"
def processTimeZones(tzdataDir, icuDir, icuTzDir, version, ignoreFactory, out):
def processTimeZones(
tzdataDir, icuDir, icuTzDir, version, ignoreBackzone, ignoreFactory, out
):
"""Read the time zone info and create a new time zone cpp file."""
print("Processing tzdata mapping...")
(ianaZones, ianaLinks) = availableNamedTimeZoneIdentifiers(tzdataDir, ignoreFactory)
(ianaZones, ianaLinks) = readIANATimeZones(tzdataDir, ignoreBackzone, ignoreFactory)
(icuZones, icuLinks) = readICUTimeZones(icuDir, icuTzDir, ignoreFactory)
(legacyZones, legacyLinks) = readICULegacyZones(icuDir)
if ignoreFactory:
legacyZones.add(Zone("Factory"))
# Remove all legacy ICU time zones.
icuZones = {zone for zone in icuZones if zone not in legacyZones}
icuLinks = {
zone: target for (zone, target) in icuLinks.items() if zone not in legacyLinks
}
incorrectZones = findIncorrectICUZones(ianaZones, ianaLinks, icuZones, icuLinks)
incorrectZones = findIncorrectICUZones(
ianaZones, ianaLinks, icuZones, icuLinks, ignoreBackzone
)
if not incorrectZones:
print("<<< No incorrect ICU time zones found, please update Intl.js! >>>")
print("<<< Maybe https://ssl.icu-project.org/trac/ticket/12044 was fixed? >>>")
@ -2866,12 +2751,28 @@ def processTimeZones(tzdataDir, icuDir, icuTzDir, version, ignoreFactory, out):
println("#endif /* builtin_intl_TimeZoneDataGenerated_h */")
def generateTzDataTestLinks(tzdataDir, version, ignoreFactory, testDir):
fileName = "timeZone_links.js"
def updateBackzoneLinks(tzdataDir, links):
def withZone(fn):
return lambda zone_target: fn(zone_target[0])
# Read zone and link infos.
(_, links) = availableNamedTimeZoneIdentifiers(tzdataDir, ignoreFactory)
(backzoneZones, backzoneLinks) = readIANAFiles(tzdataDir, ["backzone"])
(stableZones, updatedLinks, updatedZones) = partition(
links.items(),
# Link not changed in backzone.
withZone(lambda zone: zone not in backzoneLinks and zone not in backzoneZones),
# Link has a new target.
withZone(lambda zone: zone in backzoneLinks),
)
# Keep stable zones and links with updated target.
return dict(
chain(
stableZones,
map(withZone(lambda zone: (zone, backzoneLinks[zone])), updatedLinks),
)
)
def generateTzDataLinkTestContent(testDir, version, fileName, description, links):
with io.open(
os.path.join(testDir, fileName), mode="w", encoding="utf-8", newline=""
) as f:
@ -2891,9 +2792,9 @@ const tzMapper = [
"""
)
println("// Link names derived from IANA Time Zone Database.")
println(description)
println("const links = {")
for zone, target in sorted(links.items(), key=itemgetter(0)):
for zone, target in sorted(links, key=itemgetter(0)):
println(' "%s": "%s",' % (zone, target))
println("};")
@ -2919,6 +2820,112 @@ if (typeof reportCompare === "function")
)
def generateTzDataTestBackwardLinks(tzdataDir, version, ignoreBackzone, testDir):
(zones, links) = readIANAFiles(tzdataDir, ["backward"])
assert len(zones) == 0
if not ignoreBackzone:
links = updateBackzoneLinks(tzdataDir, links)
generateTzDataLinkTestContent(
testDir,
version,
"timeZone_backward_links.js",
"// Link names derived from IANA Time Zone Database, backward file.",
links.items(),
)
def generateTzDataTestNotBackwardLinks(tzdataDir, version, ignoreBackzone, testDir):
tzfiles = filterfalse(
{"backward", "backzone"}.__contains__, listIANAFiles(tzdataDir)
)
(zones, links) = readIANAFiles(tzdataDir, tzfiles)
if not ignoreBackzone:
links = updateBackzoneLinks(tzdataDir, links)
generateTzDataLinkTestContent(
testDir,
version,
"timeZone_notbackward_links.js",
"// Link names derived from IANA Time Zone Database, excluding backward file.",
links.items(),
)
def generateTzDataTestBackzone(tzdataDir, version, ignoreBackzone, testDir):
backzoneFiles = {"backzone"}
(bkfiles, tzfiles) = partition(listIANAFiles(tzdataDir), backzoneFiles.__contains__)
# Read zone and link infos.
(zones, links) = readIANAFiles(tzdataDir, tzfiles)
(backzones, backlinks) = readIANAFiles(tzdataDir, bkfiles)
if not ignoreBackzone:
comment = """\
// This file was generated with historical, pre-1970 backzone information
// respected. Therefore, every zone key listed below is its own Zone, not
// a Link to a modern-day target as IANA ignoring backzones would say.
"""
else:
comment = """\
// This file was generated while ignoring historical, pre-1970 backzone
// information. Therefore, every zone key listed below is part of a Link
// whose target is the corresponding value.
"""
generateTzDataLinkTestContent(
testDir,
version,
"timeZone_backzone.js",
comment + "// Backzone zones derived from IANA Time Zone Database.",
(
(zone, zone if not ignoreBackzone else links[zone])
for zone in backzones
if zone in links
),
)
def generateTzDataTestBackzoneLinks(tzdataDir, version, ignoreBackzone, testDir):
backzoneFiles = {"backzone"}
(bkfiles, tzfiles) = partition(listIANAFiles(tzdataDir), backzoneFiles.__contains__)
# Read zone and link infos.
(zones, links) = readIANAFiles(tzdataDir, tzfiles)
(backzones, backlinks) = readIANAFiles(tzdataDir, bkfiles)
if not ignoreBackzone:
comment = """\
// This file was generated with historical, pre-1970 backzone information
// respected. Therefore, every zone key listed below points to a target
// in the backzone file and not to its modern-day target as IANA ignoring
// backzones would say.
"""
else:
comment = """\
// This file was generated while ignoring historical, pre-1970 backzone
// information. Therefore, every zone key listed below is part of a Link
// whose target is the corresponding value ignoring any backzone entries.
"""
generateTzDataLinkTestContent(
testDir,
version,
"timeZone_backzone_links.js",
comment + "// Backzone links derived from IANA Time Zone Database.",
(
(zone, target if not ignoreBackzone else links[zone])
for (zone, target) in backlinks.items()
),
)
def generateTzDataTestVersion(tzdataDir, version, testDir):
fileName = "timeZone_version.js"
@ -2949,11 +2956,32 @@ if (typeof reportCompare === "function")
)
def generateTzDataTestCanonicalZones(tzdataDir, version, ignoreFactory, testDir):
def generateTzDataTestCanonicalZones(
tzdataDir, version, ignoreBackzone, ignoreFactory, testDir
):
fileName = "supportedValuesOf-timeZones-canonical.js"
# Read zone and link infos.
(zones, _) = availableNamedTimeZoneIdentifiers(tzdataDir, ignoreFactory)
(ianaZones, _) = readIANATimeZones(tzdataDir, ignoreBackzone, ignoreFactory)
# Replace Etc/GMT and Etc/UTC with UTC.
ianaZones.remove(Zone("Etc/GMT"))
ianaZones.remove(Zone("Etc/UTC"))
ianaZones.add(Zone("UTC"))
# See findIncorrectICUZones() for why Asia/Hanoi has to be special-cased.
ianaZones.remove(Zone("Asia/Hanoi"))
if not ignoreBackzone:
comment = """\
// This file was generated with historical, pre-1970 backzone information
// respected.
"""
else:
comment = """\
// This file was generated while ignoring historical, pre-1970 backzone
// information.
"""
with io.open(
os.path.join(testDir, fileName), mode="w", encoding="utf-8", newline=""
@ -2964,9 +2992,11 @@ def generateTzDataTestCanonicalZones(tzdataDir, version, ignoreFactory, testDir)
println("")
println(generatedFileWarning)
println(tzdataVersionComment.format(version))
println("")
println(comment)
println("const zones = [")
for zone in sorted(zones):
for zone in sorted(ianaZones):
println(f' "{zone}",')
println("];")
@ -2982,14 +3012,19 @@ if (typeof reportCompare === "function")
)
def generateTzDataTests(tzdataDir, version, ignoreFactory, testDir):
def generateTzDataTests(tzdataDir, version, ignoreBackzone, ignoreFactory, testDir):
dtfTestDir = os.path.join(testDir, "DateTimeFormat")
if not os.path.isdir(dtfTestDir):
raise RuntimeError("not a directory: %s" % dtfTestDir)
generateTzDataTestLinks(tzdataDir, version, ignoreFactory, dtfTestDir)
generateTzDataTestBackwardLinks(tzdataDir, version, ignoreBackzone, dtfTestDir)
generateTzDataTestNotBackwardLinks(tzdataDir, version, ignoreBackzone, dtfTestDir)
generateTzDataTestBackzone(tzdataDir, version, ignoreBackzone, dtfTestDir)
generateTzDataTestBackzoneLinks(tzdataDir, version, ignoreBackzone, dtfTestDir)
generateTzDataTestVersion(tzdataDir, version, dtfTestDir)
generateTzDataTestCanonicalZones(tzdataDir, version, ignoreFactory, testDir)
generateTzDataTestCanonicalZones(
tzdataDir, version, ignoreBackzone, ignoreFactory, testDir
)
def updateTzdata(topsrcdir, args):
@ -3010,11 +3045,11 @@ def updateTzdata(topsrcdir, args):
tzDir = args.tz
if tzDir is not None and not (os.path.isdir(tzDir) or os.path.isfile(tzDir)):
raise RuntimeError("not a directory or file: %s" % tzDir)
ignoreBackzone = args.ignore_backzone
# TODO: Accept or ignore the placeholder time zone "Factory"?
ignoreFactory = False
out = args.out
# Ignore the placeholder time zone "Factory".
ignoreFactory = True
version = icuTzDataVersion(icuTzDir)
url = (
"https://www.iana.org/time-zones/repository/releases/tzdata%s.tar.gz" % version
@ -3026,6 +3061,7 @@ def updateTzdata(topsrcdir, args):
print("\ttzdata directory|file: %s" % tzDir)
print("\tICU directory: %s" % icuDir)
print("\tICU timezone directory: %s" % icuTzDir)
print("\tIgnore backzone file: %s" % ignoreBackzone)
print("\tOutput file: %s" % out)
print("")
@ -3037,11 +3073,12 @@ def updateTzdata(topsrcdir, args):
icuDir,
icuTzDir,
version,
ignoreBackzone,
ignoreFactory,
out,
)
generateTzDataTests(
TzDataFile(tar), version, ignoreFactory, intlTestDir
TzDataFile(tar), version, ignoreBackzone, ignoreFactory, intlTestDir
)
elif os.path.isdir(f):
processTimeZones(
@ -3049,10 +3086,13 @@ def updateTzdata(topsrcdir, args):
icuDir,
icuTzDir,
version,
ignoreBackzone,
ignoreFactory,
out,
)
generateTzDataTests(TzDataDir(f), version, ignoreFactory, intlTestDir)
generateTzDataTests(
TzDataDir(f), version, ignoreBackzone, ignoreFactory, intlTestDir
)
else:
raise RuntimeError("unknown format")
@ -4044,6 +4084,17 @@ if __name__ == "__main__":
help="Local tzdata directory or file, if omitted downloads tzdata "
"distribution from https://www.iana.org/time-zones/",
)
# ICU doesn't include the backzone file by default, but we still like to
# use the backzone time zone names to avoid user confusion. This does lead
# to formatting "historic" dates (pre-1970 era) with the wrong time zone,
# but that's probably acceptable for now.
parser_tz.add_argument(
"--ignore-backzone",
action="store_true",
help="Ignore tzdata's 'backzone' file. Can be enabled to generate more "
"accurate time zone canonicalization reflecting the actual time "
"zones as used by ICU.",
)
parser_tz.add_argument(
"--out",
default=os.path.join(thisDir, "TimeZoneDataGenerated.h"),

View file

@ -212,9 +212,11 @@ JSLinearString* js::temporal::CanonicalizeTimeZoneName(
"Unsupported canonical time zone");
#endif
// Step 3. (Links to UTC are handled by SharedIntlData.)
MOZ_ASSERT(!StringEqualsLiteral(ianaTimeZone, "Etc/UTC"));
MOZ_ASSERT(!StringEqualsLiteral(ianaTimeZone, "Etc/GMT"));
// Step 3.
if (StringEqualsLiteral(ianaTimeZone, "Etc/UTC") ||
StringEqualsLiteral(ianaTimeZone, "Etc/GMT")) {
return cx->names().UTC;
}
// We don't need to check against "GMT", because ICU uses the tzdata rearguard
// format, where "GMT" is a link to "Etc/GMT".

View file

@ -42,7 +42,7 @@ void JS::TracingContext::getEdgeName(const char* name, char* buffer,
size_t bufferSize) {
MOZ_ASSERT(bufferSize > 0);
if (functor_) {
(*functor_)(this, buffer, bufferSize);
(*functor_)(this, name, buffer, bufferSize);
return;
}
if (index_ != InvalidIndex) {

View file

@ -998,7 +998,7 @@ void SMRegExpMacroAssembler::JumpOrBacktrack(Label* to) {
void SMRegExpMacroAssembler::CheckBacktrackStackLimit() {
js::jit::Label no_stack_overflow;
masm_.branchPtr(
Assembler::BelowOrEqual,
Assembler::Below,
AbsoluteAddress(isolate()->regexp_stack()->limit_address_address()),
backtrack_stack_pointer_, &no_stack_overflow);

View file

@ -14,7 +14,7 @@ let originalDT = Intl.DateTimeFormat("en-US", {
timeStyle: "full",
});
assertEq(originalDT.format(original).endsWith("Pacific Standard Time"), true);
assertEq(originalDT.resolvedOptions().timeZone, "America/Los_Angeles");
assertEq(originalDT.resolvedOptions().timeZone, "PST8PDT");
let global = newGlobal({forceUTC: true});

View file

@ -1129,36 +1129,38 @@ void MacroAssembler::patchSub32FromMemAndBranchIfNegative(CodeOffset offset,
// Primitive atomic operations.
static void ExtendTo32(MacroAssembler& masm, Scalar::Type type, Register r) {
switch (Scalar::byteSize(type)) {
case 1:
if (Scalar::isSignedIntType(type)) {
masm.movsbl(r, r);
} else {
masm.movzbl(r, r);
}
switch (type) {
case Scalar::Int8:
masm.movsbl(r, r);
break;
case 2:
if (Scalar::isSignedIntType(type)) {
masm.movswl(r, r);
} else {
masm.movzwl(r, r);
}
case Scalar::Uint8:
masm.movzbl(r, r);
break;
case Scalar::Int16:
masm.movswl(r, r);
break;
case Scalar::Uint16:
masm.movzwl(r, r);
break;
case Scalar::Int32:
case Scalar::Uint32:
break;
default:
break;
MOZ_CRASH("unexpected type");
}
}
static inline void CheckBytereg(Register r) {
#ifdef DEBUG
static inline bool IsByteReg(Register r) {
AllocatableGeneralRegisterSet byteRegs(Registers::SingleByteRegs);
MOZ_ASSERT(byteRegs.has(r));
#endif
return byteRegs.has(r);
}
static inline void CheckBytereg(Imm32 r) {
static inline bool IsByteReg(Imm32 r) {
// Nothing
return true;
}
#endif
template <typename T>
static void CompareExchange(MacroAssembler& masm,
@ -1180,7 +1182,7 @@ static void CompareExchange(MacroAssembler& masm,
// GenerateAtomicOperations.py
switch (Scalar::byteSize(type)) {
case 1:
CheckBytereg(newval);
MOZ_ASSERT(IsByteReg(newval));
masm.lock_cmpxchgb(newval, Operand(mem));
break;
case 2:
@ -1239,7 +1241,7 @@ static void AtomicExchange(MacroAssembler& masm,
switch (Scalar::byteSize(type)) {
case 1:
CheckBytereg(output);
MOZ_ASSERT(IsByteReg(output));
masm.xchgb(output, Operand(mem));
break;
case 2:
@ -1297,6 +1299,34 @@ static void SetupValue(MacroAssembler& masm, AtomicOp op, Register src,
}
}
static auto WasmTrapMachineInsn(Scalar::Type arrayType, AtomicOp op) {
switch (op) {
case AtomicOp::Add:
case AtomicOp::Sub:
return wasm::TrapMachineInsn::Atomic;
case AtomicOp::And:
case AtomicOp::Or:
case AtomicOp::Xor:
switch (arrayType) {
case Scalar::Int8:
case Scalar::Uint8:
return wasm::TrapMachineInsn::Load8;
case Scalar::Int16:
case Scalar::Uint16:
return wasm::TrapMachineInsn::Load16;
case Scalar::Int32:
case Scalar::Uint32:
return wasm::TrapMachineInsn::Load32;
default:
break;
}
[[fallthrough]];
default:
break;
}
MOZ_CRASH();
}
template <typename T, typename V>
static void AtomicFetchOp(MacroAssembler& masm,
const wasm::MemoryAccessDesc* access,
@ -1306,117 +1336,150 @@ static void AtomicFetchOp(MacroAssembler& masm,
// NOTE: the generated code must match the assembly code in gen_fetchop in
// GenerateAtomicOperations.py
#define ATOMIC_BITOP_BODY(LOAD, LOAD_DESCR, OP, LOCK_CMPXCHG) \
do { \
MOZ_ASSERT(output != temp); \
MOZ_ASSERT(output == eax); \
if (access) \
masm.append(*access, LOAD_DESCR, \
FaultingCodeOffset(masm.currentOffset())); \
masm.LOAD(Operand(mem), eax); \
Label again; \
masm.bind(&again); \
masm.movl(eax, temp); \
masm.OP(value, temp); \
masm.LOCK_CMPXCHG(temp, Operand(mem)); \
masm.j(MacroAssembler::NonZero, &again); \
} while (0)
MOZ_ASSERT_IF(op == AtomicOp::Add || op == AtomicOp::Sub, temp == InvalidReg);
// Setup the output register.
switch (op) {
case AtomicOp::Add:
case AtomicOp::Sub:
MOZ_ASSERT(temp == InvalidReg);
MOZ_ASSERT_IF(Scalar::byteSize(arrayType) == 1,
IsByteReg(output) && IsByteReg(value));
switch (Scalar::byteSize(arrayType)) {
case 1:
CheckBytereg(output);
switch (op) {
case AtomicOp::Add:
case AtomicOp::Sub:
CheckBytereg(value); // But not for the bitwise ops
SetupValue(masm, op, value, output);
if (access) {
masm.append(*access, wasm::TrapMachineInsn::Atomic,
FaultingCodeOffset(masm.currentOffset()));
}
masm.lock_xaddb(output, Operand(mem));
break;
case AtomicOp::And:
CheckBytereg(temp);
ATOMIC_BITOP_BODY(movb, wasm::TrapMachineInsn::Load8, andl,
lock_cmpxchgb);
break;
case AtomicOp::Or:
CheckBytereg(temp);
ATOMIC_BITOP_BODY(movb, wasm::TrapMachineInsn::Load8, orl,
lock_cmpxchgb);
break;
case AtomicOp::Xor:
CheckBytereg(temp);
ATOMIC_BITOP_BODY(movb, wasm::TrapMachineInsn::Load8, xorl,
lock_cmpxchgb);
break;
default:
MOZ_CRASH();
}
SetupValue(masm, op, value, output);
break;
case 2:
switch (op) {
case AtomicOp::Add:
case AtomicOp::Sub:
SetupValue(masm, op, value, output);
if (access) {
masm.append(*access, wasm::TrapMachineInsn::Atomic,
FaultingCodeOffset(masm.currentOffset()));
}
masm.lock_xaddw(output, Operand(mem));
break;
case AtomicOp::And:
ATOMIC_BITOP_BODY(movw, wasm::TrapMachineInsn::Load16, andl,
lock_cmpxchgw);
break;
case AtomicOp::Or:
ATOMIC_BITOP_BODY(movw, wasm::TrapMachineInsn::Load16, orl,
lock_cmpxchgw);
break;
case AtomicOp::Xor:
ATOMIC_BITOP_BODY(movw, wasm::TrapMachineInsn::Load16, xorl,
lock_cmpxchgw);
break;
default:
MOZ_CRASH();
}
break;
case 4:
switch (op) {
case AtomicOp::Add:
case AtomicOp::Sub:
SetupValue(masm, op, value, output);
if (access) {
masm.append(*access, wasm::TrapMachineInsn::Atomic,
FaultingCodeOffset(masm.currentOffset()));
}
masm.lock_xaddl(output, Operand(mem));
break;
case AtomicOp::And:
ATOMIC_BITOP_BODY(movl, wasm::TrapMachineInsn::Load32, andl,
lock_cmpxchgl);
break;
case AtomicOp::Or:
ATOMIC_BITOP_BODY(movl, wasm::TrapMachineInsn::Load32, orl,
lock_cmpxchgl);
break;
case AtomicOp::Xor:
ATOMIC_BITOP_BODY(movl, wasm::TrapMachineInsn::Load32, xorl,
lock_cmpxchgl);
break;
default:
MOZ_CRASH();
}
case AtomicOp::And:
case AtomicOp::Or:
case AtomicOp::Xor:
MOZ_ASSERT(output != temp && output == eax);
MOZ_ASSERT_IF(Scalar::byteSize(arrayType) == 1,
IsByteReg(output) && IsByteReg(temp));
// Bitwise operations don't require any additional setup.
break;
default:
MOZ_CRASH("Invalid size");
MOZ_CRASH();
}
ExtendTo32(masm, arrayType, output);
#undef ATOMIC_BITOP_BODY
auto lock_xadd = [&]() {
switch (arrayType) {
case Scalar::Int8:
case Scalar::Uint8:
masm.lock_xaddb(output, Operand(mem));
break;
case Scalar::Int16:
case Scalar::Uint16:
masm.lock_xaddw(output, Operand(mem));
break;
case Scalar::Int32:
case Scalar::Uint32:
masm.lock_xaddl(output, Operand(mem));
break;
default:
MOZ_CRASH();
}
};
auto load = [&]() {
switch (arrayType) {
case Scalar::Int8:
case Scalar::Uint8:
masm.movzbl(Operand(mem), eax);
break;
case Scalar::Int16:
case Scalar::Uint16:
masm.movzwl(Operand(mem), eax);
break;
case Scalar::Int32:
case Scalar::Uint32:
masm.movl(Operand(mem), eax);
break;
default:
MOZ_CRASH();
}
};
auto bitwiseOp = [&]() {
switch (op) {
case AtomicOp::And:
masm.andl(value, temp);
break;
case AtomicOp::Or:
masm.orl(value, temp);
break;
case AtomicOp::Xor:
masm.xorl(value, temp);
break;
default:
MOZ_CRASH();
}
};
auto lock_cmpxchg = [&]() {
switch (arrayType) {
case Scalar::Int8:
case Scalar::Uint8:
masm.lock_cmpxchgb(temp, Operand(mem));
break;
case Scalar::Int16:
case Scalar::Uint16:
masm.lock_cmpxchgw(temp, Operand(mem));
break;
case Scalar::Int32:
case Scalar::Uint32:
masm.lock_cmpxchgl(temp, Operand(mem));
break;
default:
MOZ_CRASH();
}
};
// Add trap instruction directly before the load.
if (access) {
masm.append(*access, WasmTrapMachineInsn(arrayType, op),
FaultingCodeOffset(masm.currentOffset()));
}
switch (op) {
case AtomicOp::Add:
case AtomicOp::Sub:
// `add` and `sub` operations can be optimized with XADD.
lock_xadd();
ExtendTo32(masm, arrayType, output);
break;
case AtomicOp::And:
case AtomicOp::Or:
case AtomicOp::Xor: {
// Bitwise operations need a CAS loop.
// Load memory into eax.
load();
// Loop.
Label again;
masm.bind(&again);
masm.movl(eax, temp);
// temp = temp <op> value.
bitwiseOp();
// Compare and swap `temp` with memory.
lock_cmpxchg();
// Repeat if the comparison failed.
masm.j(MacroAssembler::NonZero, &again);
// Sign-extend the zero-extended load.
if (Scalar::isSignedIntType(arrayType)) {
ExtendTo32(masm, arrayType, eax);
}
break;
}
default:
MOZ_CRASH();
}
}
void MacroAssembler::atomicFetchOp(Scalar::Type arrayType, Synchronization,

View file

@ -9,58 +9,46 @@ const tzMapper = [
x => x.toLowerCase(),
];
// Link names derived from IANA Time Zone Database.
// Link names derived from IANA Time Zone Database, backward file.
const links = {
"Africa/Asmera": "Africa/Asmara",
"Africa/Timbuktu": "Africa/Bamako",
"America/Argentina/ComodRivadavia": "America/Argentina/Catamarca",
"America/Atka": "America/Adak",
"America/Buenos_Aires": "America/Argentina/Buenos_Aires",
"America/Catamarca": "America/Argentina/Catamarca",
"America/Coral_Harbour": "America/Atikokan",
"America/Cordoba": "America/Argentina/Cordoba",
"America/Ensenada": "America/Tijuana",
"America/Fort_Wayne": "America/Indiana/Indianapolis",
"America/Godthab": "America/Nuuk",
"America/Indianapolis": "America/Indiana/Indianapolis",
"America/Jujuy": "America/Argentina/Jujuy",
"America/Knox_IN": "America/Indiana/Knox",
"America/Kralendijk": "America/Curacao",
"America/Louisville": "America/Kentucky/Louisville",
"America/Lower_Princes": "America/Curacao",
"America/Marigot": "America/Port_of_Spain",
"America/Mendoza": "America/Argentina/Mendoza",
"America/Montreal": "America/Toronto",
"America/Nipigon": "America/Toronto",
"America/Pangnirtung": "America/Iqaluit",
"America/Porto_Acre": "America/Rio_Branco",
"America/Rainy_River": "America/Winnipeg",
"America/Rosario": "America/Argentina/Cordoba",
"America/Santa_Isabel": "America/Tijuana",
"America/Shiprock": "America/Denver",
"America/Thunder_Bay": "America/Toronto",
"America/St_Barthelemy": "America/Port_of_Spain",
"America/Virgin": "America/St_Thomas",
"America/Yellowknife": "America/Edmonton",
"Antarctica/South_Pole": "Antarctica/McMurdo",
"Arctic/Longyearbyen": "Europe/Oslo",
"Asia/Ashkhabad": "Asia/Ashgabat",
"Asia/Calcutta": "Asia/Kolkata",
"Asia/Choibalsan": "Asia/Ulaanbaatar",
"Asia/Chongqing": "Asia/Shanghai",
"Asia/Chungking": "Asia/Shanghai",
"Asia/Chungking": "Asia/Chongqing",
"Asia/Dacca": "Asia/Dhaka",
"Asia/Harbin": "Asia/Shanghai",
"Asia/Istanbul": "Europe/Istanbul",
"Asia/Kashgar": "Asia/Urumqi",
"Asia/Katmandu": "Asia/Kathmandu",
"Asia/Macao": "Asia/Macau",
"Asia/Rangoon": "Asia/Yangon",
"Asia/Saigon": "Asia/Ho_Chi_Minh",
"Asia/Tel_Aviv": "Asia/Jerusalem",
"Asia/Thimbu": "Asia/Thimphu",
"Asia/Ujung_Pandang": "Asia/Makassar",
"Asia/Ulan_Bator": "Asia/Ulaanbaatar",
"Atlantic/Faeroe": "Atlantic/Faroe",
"Atlantic/Jan_Mayen": "Arctic/Longyearbyen",
"Australia/ACT": "Australia/Sydney",
"Australia/Canberra": "Australia/Sydney",
"Australia/Currie": "Australia/Hobart",
"Australia/LHI": "Australia/Lord_Howe",
"Australia/NSW": "Australia/Sydney",
"Australia/North": "Australia/Darwin",
@ -74,8 +62,6 @@ const links = {
"Brazil/DeNoronha": "America/Noronha",
"Brazil/East": "America/Sao_Paulo",
"Brazil/West": "America/Manaus",
"CET": "Europe/Brussels",
"CST6CDT": "America/Chicago",
"Canada/Atlantic": "America/Halifax",
"Canada/Central": "America/Winnipeg",
"Canada/Eastern": "America/Toronto",
@ -87,34 +73,29 @@ const links = {
"Chile/Continental": "America/Santiago",
"Chile/EasterIsland": "Pacific/Easter",
"Cuba": "America/Havana",
"EET": "Europe/Athens",
"EST": "America/Panama",
"EST5EDT": "America/New_York",
"Egypt": "Africa/Cairo",
"Eire": "Europe/Dublin",
"Etc/GMT": "UTC",
"Etc/GMT+0": "UTC",
"Etc/GMT-0": "UTC",
"Etc/GMT0": "UTC",
"Etc/Greenwich": "UTC",
"Etc/UCT": "UTC",
"Etc/UTC": "UTC",
"Etc/Universal": "UTC",
"Etc/Zulu": "UTC",
"Europe/Belfast": "Europe/London",
"Etc/GMT+0": "Etc/GMT",
"Etc/GMT-0": "Etc/GMT",
"Etc/GMT0": "Etc/GMT",
"Etc/Greenwich": "Etc/GMT",
"Etc/UCT": "Etc/UTC",
"Etc/Universal": "Etc/UTC",
"Etc/Zulu": "Etc/UTC",
"Europe/Bratislava": "Europe/Prague",
"Europe/Busingen": "Europe/Zurich",
"Europe/Kiev": "Europe/Kyiv",
"Europe/Mariehamn": "Europe/Helsinki",
"Europe/Nicosia": "Asia/Nicosia",
"Europe/Tiraspol": "Europe/Chisinau",
"Europe/Uzhgorod": "Europe/Kyiv",
"Europe/Zaporozhye": "Europe/Kyiv",
"Europe/Podgorica": "Europe/Belgrade",
"Europe/San_Marino": "Europe/Rome",
"Europe/Vatican": "Europe/Rome",
"GB": "Europe/London",
"GB-Eire": "Europe/London",
"GMT": "UTC",
"GMT+0": "UTC",
"GMT-0": "UTC",
"GMT0": "UTC",
"Greenwich": "UTC",
"HST": "Pacific/Honolulu",
"GMT+0": "Etc/GMT",
"GMT-0": "Etc/GMT",
"GMT0": "Etc/GMT",
"Greenwich": "Etc/GMT",
"Hongkong": "Asia/Hong_Kong",
"Iceland": "Atlantic/Reykjavik",
"Iran": "Asia/Tehran",
@ -123,9 +104,6 @@ const links = {
"Japan": "Asia/Tokyo",
"Kwajalein": "Pacific/Kwajalein",
"Libya": "Africa/Tripoli",
"MET": "Europe/Brussels",
"MST": "America/Phoenix",
"MST7MDT": "America/Denver",
"Mexico/BajaNorte": "America/Tijuana",
"Mexico/BajaSur": "America/Mazatlan",
"Mexico/General": "America/Mexico_City",
@ -133,9 +111,6 @@ const links = {
"NZ-CHAT": "Pacific/Chatham",
"Navajo": "America/Denver",
"PRC": "Asia/Shanghai",
"PST8PDT": "America/Los_Angeles",
"Pacific/Enderbury": "Pacific/Kanton",
"Pacific/Johnston": "Pacific/Honolulu",
"Pacific/Ponape": "Pacific/Pohnpei",
"Pacific/Samoa": "Pacific/Pago_Pago",
"Pacific/Truk": "Pacific/Chuuk",
@ -146,7 +121,7 @@ const links = {
"ROK": "Asia/Seoul",
"Singapore": "Asia/Singapore",
"Turkey": "Europe/Istanbul",
"UCT": "UTC",
"UCT": "Etc/UTC",
"US/Alaska": "America/Anchorage",
"US/Aleutian": "America/Adak",
"US/Arizona": "America/Phoenix",
@ -159,10 +134,10 @@ const links = {
"US/Mountain": "America/Denver",
"US/Pacific": "America/Los_Angeles",
"US/Samoa": "Pacific/Pago_Pago",
"Universal": "UTC",
"UTC": "Etc/UTC",
"Universal": "Etc/UTC",
"W-SU": "Europe/Moscow",
"WET": "Europe/Lisbon",
"Zulu": "UTC",
"Zulu": "Etc/UTC",
};
for (let [linkName, target] of Object.entries(links)) {

View file

@ -0,0 +1,163 @@
// |reftest| skip-if(!this.hasOwnProperty("Intl"))
// Generated by make_intl_data.py. DO NOT EDIT.
// tzdata version = 2024b
const tzMapper = [
x => x,
x => x.toUpperCase(),
x => x.toLowerCase(),
];
// This file was generated with historical, pre-1970 backzone information
// respected. Therefore, every zone key listed below is its own Zone, not
// a Link to a modern-day target as IANA ignoring backzones would say.
// Backzone zones derived from IANA Time Zone Database.
const links = {
"Africa/Accra": "Africa/Accra",
"Africa/Addis_Ababa": "Africa/Addis_Ababa",
"Africa/Asmara": "Africa/Asmara",
"Africa/Bamako": "Africa/Bamako",
"Africa/Bangui": "Africa/Bangui",
"Africa/Banjul": "Africa/Banjul",
"Africa/Blantyre": "Africa/Blantyre",
"Africa/Brazzaville": "Africa/Brazzaville",
"Africa/Bujumbura": "Africa/Bujumbura",
"Africa/Conakry": "Africa/Conakry",
"Africa/Dakar": "Africa/Dakar",
"Africa/Dar_es_Salaam": "Africa/Dar_es_Salaam",
"Africa/Djibouti": "Africa/Djibouti",
"Africa/Douala": "Africa/Douala",
"Africa/Freetown": "Africa/Freetown",
"Africa/Gaborone": "Africa/Gaborone",
"Africa/Harare": "Africa/Harare",
"Africa/Kampala": "Africa/Kampala",
"Africa/Kigali": "Africa/Kigali",
"Africa/Kinshasa": "Africa/Kinshasa",
"Africa/Libreville": "Africa/Libreville",
"Africa/Lome": "Africa/Lome",
"Africa/Luanda": "Africa/Luanda",
"Africa/Lubumbashi": "Africa/Lubumbashi",
"Africa/Lusaka": "Africa/Lusaka",
"Africa/Malabo": "Africa/Malabo",
"Africa/Maseru": "Africa/Maseru",
"Africa/Mbabane": "Africa/Mbabane",
"Africa/Mogadishu": "Africa/Mogadishu",
"Africa/Niamey": "Africa/Niamey",
"Africa/Nouakchott": "Africa/Nouakchott",
"Africa/Ouagadougou": "Africa/Ouagadougou",
"Africa/Porto-Novo": "Africa/Porto-Novo",
"Africa/Timbuktu": "Africa/Timbuktu",
"America/Anguilla": "America/Anguilla",
"America/Antigua": "America/Antigua",
"America/Argentina/ComodRivadavia": "America/Argentina/ComodRivadavia",
"America/Aruba": "America/Aruba",
"America/Atikokan": "America/Atikokan",
"America/Blanc-Sablon": "America/Blanc-Sablon",
"America/Cayman": "America/Cayman",
"America/Coral_Harbour": "America/Coral_Harbour",
"America/Creston": "America/Creston",
"America/Curacao": "America/Curacao",
"America/Dominica": "America/Dominica",
"America/Ensenada": "America/Ensenada",
"America/Grenada": "America/Grenada",
"America/Guadeloupe": "America/Guadeloupe",
"America/Montreal": "America/Montreal",
"America/Montserrat": "America/Montserrat",
"America/Nassau": "America/Nassau",
"America/Nipigon": "America/Nipigon",
"America/Pangnirtung": "America/Pangnirtung",
"America/Port_of_Spain": "America/Port_of_Spain",
"America/Rainy_River": "America/Rainy_River",
"America/Rosario": "America/Rosario",
"America/St_Kitts": "America/St_Kitts",
"America/St_Lucia": "America/St_Lucia",
"America/St_Thomas": "America/St_Thomas",
"America/St_Vincent": "America/St_Vincent",
"America/Thunder_Bay": "America/Thunder_Bay",
"America/Tortola": "America/Tortola",
"America/Yellowknife": "America/Yellowknife",
"Antarctica/DumontDUrville": "Antarctica/DumontDUrville",
"Antarctica/McMurdo": "Antarctica/McMurdo",
"Antarctica/Syowa": "Antarctica/Syowa",
"Asia/Aden": "Asia/Aden",
"Asia/Bahrain": "Asia/Bahrain",
"Asia/Brunei": "Asia/Brunei",
"Asia/Chongqing": "Asia/Chongqing",
"Asia/Harbin": "Asia/Harbin",
"Asia/Kashgar": "Asia/Kashgar",
"Asia/Kuala_Lumpur": "Asia/Kuala_Lumpur",
"Asia/Kuwait": "Asia/Kuwait",
"Asia/Muscat": "Asia/Muscat",
"Asia/Phnom_Penh": "Asia/Phnom_Penh",
"Asia/Tel_Aviv": "Asia/Tel_Aviv",
"Asia/Vientiane": "Asia/Vientiane",
"Atlantic/Jan_Mayen": "Atlantic/Jan_Mayen",
"Atlantic/Reykjavik": "Atlantic/Reykjavik",
"Atlantic/St_Helena": "Atlantic/St_Helena",
"Australia/Currie": "Australia/Currie",
"CET": "CET",
"CST6CDT": "CST6CDT",
"EET": "EET",
"EST": "EST",
"EST5EDT": "EST5EDT",
"Europe/Amsterdam": "Europe/Amsterdam",
"Europe/Belfast": "Europe/Belfast",
"Europe/Copenhagen": "Europe/Copenhagen",
"Europe/Guernsey": "Europe/Guernsey",
"Europe/Isle_of_Man": "Europe/Isle_of_Man",
"Europe/Jersey": "Europe/Jersey",
"Europe/Ljubljana": "Europe/Ljubljana",
"Europe/Luxembourg": "Europe/Luxembourg",
"Europe/Monaco": "Europe/Monaco",
"Europe/Oslo": "Europe/Oslo",
"Europe/Sarajevo": "Europe/Sarajevo",
"Europe/Skopje": "Europe/Skopje",
"Europe/Stockholm": "Europe/Stockholm",
"Europe/Tiraspol": "Europe/Tiraspol",
"Europe/Uzhgorod": "Europe/Uzhgorod",
"Europe/Vaduz": "Europe/Vaduz",
"Europe/Zagreb": "Europe/Zagreb",
"Europe/Zaporozhye": "Europe/Zaporozhye",
"HST": "HST",
"Indian/Antananarivo": "Indian/Antananarivo",
"Indian/Christmas": "Indian/Christmas",
"Indian/Cocos": "Indian/Cocos",
"Indian/Comoro": "Indian/Comoro",
"Indian/Kerguelen": "Indian/Kerguelen",
"Indian/Mahe": "Indian/Mahe",
"Indian/Mayotte": "Indian/Mayotte",
"Indian/Reunion": "Indian/Reunion",
"MET": "MET",
"MST": "MST",
"MST7MDT": "MST7MDT",
"PST8PDT": "PST8PDT",
"Pacific/Chuuk": "Pacific/Chuuk",
"Pacific/Enderbury": "Pacific/Enderbury",
"Pacific/Funafuti": "Pacific/Funafuti",
"Pacific/Johnston": "Pacific/Johnston",
"Pacific/Majuro": "Pacific/Majuro",
"Pacific/Midway": "Pacific/Midway",
"Pacific/Pohnpei": "Pacific/Pohnpei",
"Pacific/Saipan": "Pacific/Saipan",
"Pacific/Wake": "Pacific/Wake",
"Pacific/Wallis": "Pacific/Wallis",
"WET": "WET",
};
for (let [linkName, target] of Object.entries(links)) {
if (target === "Etc/UTC" || target === "Etc/GMT")
target = "UTC";
for (let map of tzMapper) {
let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)});
let resolvedTimeZone = dtf.resolvedOptions().timeZone;
assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`);
}
}
if (typeof reportCompare === "function")
reportCompare(0, 0, "ok");

View file

@ -0,0 +1,48 @@
// |reftest| skip-if(!this.hasOwnProperty("Intl"))
// Generated by make_intl_data.py. DO NOT EDIT.
// tzdata version = 2024b
const tzMapper = [
x => x,
x => x.toUpperCase(),
x => x.toLowerCase(),
];
// This file was generated with historical, pre-1970 backzone information
// respected. Therefore, every zone key listed below points to a target
// in the backzone file and not to its modern-day target as IANA ignoring
// backzones would say.
// Backzone links derived from IANA Time Zone Database.
const links = {
"Africa/Asmera": "Africa/Asmara",
"America/Kralendijk": "America/Curacao",
"America/Lower_Princes": "America/Curacao",
"America/Marigot": "America/Port_of_Spain",
"America/St_Barthelemy": "America/Port_of_Spain",
"America/Virgin": "America/St_Thomas",
"Antarctica/South_Pole": "Antarctica/McMurdo",
"Arctic/Longyearbyen": "Europe/Oslo",
"Asia/Chungking": "Asia/Chongqing",
"Iceland": "Atlantic/Reykjavik",
"Pacific/Ponape": "Pacific/Pohnpei",
"Pacific/Truk": "Pacific/Chuuk",
"Pacific/Yap": "Pacific/Chuuk",
};
for (let [linkName, target] of Object.entries(links)) {
if (target === "Etc/UTC" || target === "Etc/GMT")
target = "UTC";
for (let map of tzMapper) {
let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)});
let resolvedTimeZone = dtf.resolvedOptions().timeZone;
assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`);
}
}
if (typeof reportCompare === "function")
reportCompare(0, 0, "ok");

View file

@ -0,0 +1,31 @@
// |reftest| skip-if(!this.hasOwnProperty("Intl"))
// Generated by make_intl_data.py. DO NOT EDIT.
// tzdata version = 2024b
const tzMapper = [
x => x,
x => x.toUpperCase(),
x => x.toLowerCase(),
];
// Link names derived from IANA Time Zone Database, excluding backward file.
const links = {
"GMT": "Etc/GMT",
};
for (let [linkName, target] of Object.entries(links)) {
if (target === "Etc/UTC" || target === "Etc/GMT")
target = "UTC";
for (let map of tzMapper) {
let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)});
let resolvedTimeZone = dtf.resolvedOptions().timeZone;
assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`);
}
}
if (typeof reportCompare === "function")
reportCompare(0, 0, "ok");

View file

@ -40,10 +40,10 @@ function inTimeZone(tzname, fn) {
}
const timeZones = [
{ id: "EST5EDT", normalized: "America/New_York" },
{ id: "CST6CDT", normalized: "America/Chicago" },
{ id: "MST7MDT", normalized: "America/Denver" },
{ id: "PST8PDT", normalized: "America/Los_Angeles" },
{ id: "EST5EDT" },
{ id: "CST6CDT" },
{ id: "MST7MDT" },
{ id: "PST8PDT" },
// ICU on non-Windows platforms doesn't accept these three time zone
// identifiers, cf. isValidOlsonID in $ICU/source/common/putil.cpp. We
// could add support for them, but it seems unlikely they're used in

View file

@ -2,6 +2,10 @@
// Generated by make_intl_data.py. DO NOT EDIT.
// tzdata version = 2024b
// This file was generated with historical, pre-1970 backzone information
// respected.
const zones = [
"Africa/Abidjan",
"Africa/Accra",
@ -52,6 +56,7 @@ const zones = [
"Africa/Ouagadougou",
"Africa/Porto-Novo",
"Africa/Sao_Tome",
"Africa/Timbuktu",
"Africa/Tripoli",
"Africa/Tunis",
"Africa/Windhoek",
@ -62,6 +67,7 @@ const zones = [
"America/Araguaina",
"America/Argentina/Buenos_Aires",
"America/Argentina/Catamarca",
"America/Argentina/ComodRivadavia",
"America/Argentina/Cordoba",
"America/Argentina/Jujuy",
"America/Argentina/La_Rioja",
@ -93,6 +99,7 @@ const zones = [
"America/Chicago",
"America/Chihuahua",
"America/Ciudad_Juarez",
"America/Coral_Harbour",
"America/Costa_Rica",
"America/Creston",
"America/Cuiaba",
@ -106,6 +113,7 @@ const zones = [
"America/Edmonton",
"America/Eirunepe",
"America/El_Salvador",
"America/Ensenada",
"America/Fort_Nelson",
"America/Fortaleza",
"America/Glace_Bay",
@ -133,15 +141,12 @@ const zones = [
"America/Juneau",
"America/Kentucky/Louisville",
"America/Kentucky/Monticello",
"America/Kralendijk",
"America/La_Paz",
"America/Lima",
"America/Los_Angeles",
"America/Lower_Princes",
"America/Maceio",
"America/Managua",
"America/Manaus",
"America/Marigot",
"America/Martinique",
"America/Matamoros",
"America/Mazatlan",
@ -153,9 +158,11 @@ const zones = [
"America/Moncton",
"America/Monterrey",
"America/Montevideo",
"America/Montreal",
"America/Montserrat",
"America/Nassau",
"America/New_York",
"America/Nipigon",
"America/Nome",
"America/Noronha",
"America/North_Dakota/Beulah",
@ -164,6 +171,7 @@ const zones = [
"America/Nuuk",
"America/Ojinaga",
"America/Panama",
"America/Pangnirtung",
"America/Paramaribo",
"America/Phoenix",
"America/Port-au-Prince",
@ -171,18 +179,19 @@ const zones = [
"America/Porto_Velho",
"America/Puerto_Rico",
"America/Punta_Arenas",
"America/Rainy_River",
"America/Rankin_Inlet",
"America/Recife",
"America/Regina",
"America/Resolute",
"America/Rio_Branco",
"America/Rosario",
"America/Santarem",
"America/Santiago",
"America/Santo_Domingo",
"America/Sao_Paulo",
"America/Scoresbysund",
"America/Sitka",
"America/St_Barthelemy",
"America/St_Johns",
"America/St_Kitts",
"America/St_Lucia",
@ -191,6 +200,7 @@ const zones = [
"America/Swift_Current",
"America/Tegucigalpa",
"America/Thule",
"America/Thunder_Bay",
"America/Tijuana",
"America/Toronto",
"America/Tortola",
@ -198,6 +208,7 @@ const zones = [
"America/Whitehorse",
"America/Winnipeg",
"America/Yakutat",
"America/Yellowknife",
"Antarctica/Casey",
"Antarctica/Davis",
"Antarctica/DumontDUrville",
@ -209,7 +220,6 @@ const zones = [
"Antarctica/Syowa",
"Antarctica/Troll",
"Antarctica/Vostok",
"Arctic/Longyearbyen",
"Asia/Aden",
"Asia/Almaty",
"Asia/Amman",
@ -227,6 +237,7 @@ const zones = [
"Asia/Bishkek",
"Asia/Brunei",
"Asia/Chita",
"Asia/Chongqing",
"Asia/Colombo",
"Asia/Damascus",
"Asia/Dhaka",
@ -235,6 +246,7 @@ const zones = [
"Asia/Dushanbe",
"Asia/Famagusta",
"Asia/Gaza",
"Asia/Harbin",
"Asia/Hebron",
"Asia/Ho_Chi_Minh",
"Asia/Hong_Kong",
@ -246,6 +258,7 @@ const zones = [
"Asia/Kabul",
"Asia/Kamchatka",
"Asia/Karachi",
"Asia/Kashgar",
"Asia/Kathmandu",
"Asia/Khandyga",
"Asia/Kolkata",
@ -280,6 +293,7 @@ const zones = [
"Asia/Tashkent",
"Asia/Tbilisi",
"Asia/Tehran",
"Asia/Tel_Aviv",
"Asia/Thimphu",
"Asia/Tokyo",
"Asia/Tomsk",
@ -297,6 +311,7 @@ const zones = [
"Atlantic/Canary",
"Atlantic/Cape_Verde",
"Atlantic/Faroe",
"Atlantic/Jan_Mayen",
"Atlantic/Madeira",
"Atlantic/Reykjavik",
"Atlantic/South_Georgia",
@ -305,6 +320,7 @@ const zones = [
"Australia/Adelaide",
"Australia/Brisbane",
"Australia/Broken_Hill",
"Australia/Currie",
"Australia/Darwin",
"Australia/Eucla",
"Australia/Hobart",
@ -313,6 +329,11 @@ const zones = [
"Australia/Melbourne",
"Australia/Perth",
"Australia/Sydney",
"CET",
"CST6CDT",
"EET",
"EST",
"EST5EDT",
"Etc/GMT+1",
"Etc/GMT+10",
"Etc/GMT+11",
@ -343,13 +364,12 @@ const zones = [
"Europe/Andorra",
"Europe/Astrakhan",
"Europe/Athens",
"Europe/Belfast",
"Europe/Belgrade",
"Europe/Berlin",
"Europe/Bratislava",
"Europe/Brussels",
"Europe/Bucharest",
"Europe/Budapest",
"Europe/Busingen",
"Europe/Chisinau",
"Europe/Copenhagen",
"Europe/Dublin",
@ -368,18 +388,15 @@ const zones = [
"Europe/Luxembourg",
"Europe/Madrid",
"Europe/Malta",
"Europe/Mariehamn",
"Europe/Minsk",
"Europe/Monaco",
"Europe/Moscow",
"Europe/Oslo",
"Europe/Paris",
"Europe/Podgorica",
"Europe/Prague",
"Europe/Riga",
"Europe/Rome",
"Europe/Samara",
"Europe/San_Marino",
"Europe/Sarajevo",
"Europe/Saratov",
"Europe/Simferopol",
@ -388,15 +405,19 @@ const zones = [
"Europe/Stockholm",
"Europe/Tallinn",
"Europe/Tirane",
"Europe/Tiraspol",
"Europe/Ulyanovsk",
"Europe/Uzhgorod",
"Europe/Vaduz",
"Europe/Vatican",
"Europe/Vienna",
"Europe/Vilnius",
"Europe/Volgograd",
"Europe/Warsaw",
"Europe/Zagreb",
"Europe/Zaporozhye",
"Europe/Zurich",
"Factory",
"HST",
"Indian/Antananarivo",
"Indian/Chagos",
"Indian/Christmas",
@ -408,6 +429,10 @@ const zones = [
"Indian/Mauritius",
"Indian/Mayotte",
"Indian/Reunion",
"MET",
"MST",
"MST7MDT",
"PST8PDT",
"Pacific/Apia",
"Pacific/Auckland",
"Pacific/Bougainville",
@ -415,6 +440,7 @@ const zones = [
"Pacific/Chuuk",
"Pacific/Easter",
"Pacific/Efate",
"Pacific/Enderbury",
"Pacific/Fakaofo",
"Pacific/Fiji",
"Pacific/Funafuti",
@ -423,6 +449,7 @@ const zones = [
"Pacific/Guadalcanal",
"Pacific/Guam",
"Pacific/Honolulu",
"Pacific/Johnston",
"Pacific/Kanton",
"Pacific/Kiritimati",
"Pacific/Kosrae",
@ -447,6 +474,7 @@ const zones = [
"Pacific/Wake",
"Pacific/Wallis",
"UTC",
"WET",
];
let supported = Intl.supportedValuesOf("timeZone");

View file

@ -33,6 +33,7 @@
#include "js/GCVector.h" // JS::GCVector
#include "js/Id.h" // jsid
#include "js/JSON.h" // JS::IsValidJSON
#include "js/PropertyAndElement.h" // JS_SetPropertyById
#include "js/RootingAPI.h" // JS::Handle, JS::MutableHandle, MutableWrappedPtrOperations
#include "js/TypeDecls.h" // Latin1Char
#include "js/Utility.h" // js_delete
@ -1108,7 +1109,11 @@ template class js::JSONParser<char16_t>;
template <typename CharT>
inline bool JSONReviveHandler<CharT>::objectOpen(Vector<StackEntry, 10>& stack,
PropertyVector** properties) {
if (!parseRecordStack.append(ParseRecordEntry{context()})) {
ParseRecordEntry* newParseEntry = NewPlainObject(context());
if (!newParseEntry) {
return false;
}
if (!parseRecordStack.append(newParseEntry)) {
return false;
}
@ -1122,9 +1127,10 @@ inline bool JSONReviveHandler<CharT>::finishObjectMember(
if (!Base::finishObjectMember(stack, value, properties)) {
return false;
}
parseRecord.value = value;
return finishMemberParseRecord((*properties)->back().id,
parseRecordStack.back());
parseRecord->setValue(value);
Rooted<JS::PropertyKey> key(context(), (*properties)->back().id);
Rooted<ParseRecordEntry*> parseRecordBack(context(), parseRecordStack.back());
return finishMemberParseRecord(key, parseRecordBack);
}
template <typename CharT>
@ -1134,7 +1140,8 @@ inline bool JSONReviveHandler<CharT>::finishObject(
if (!Base::finishObject(stack, vp, properties)) {
return false;
}
if (!finishCompoundParseRecord(vp, parseRecordStack.back())) {
Rooted<ParseRecordEntry*> parseRecordBack(context(), parseRecordStack.back());
if (!finishCompoundParseRecord(vp, parseRecordBack)) {
return false;
}
parseRecordStack.popBack();
@ -1145,7 +1152,11 @@ inline bool JSONReviveHandler<CharT>::finishObject(
template <typename CharT>
inline bool JSONReviveHandler<CharT>::arrayOpen(Vector<StackEntry, 10>& stack,
ElementVector** elements) {
if (!parseRecordStack.append(ParseRecordEntry{context()})) {
ParseRecordEntry* newParseEntry = NewPlainObject(context());
if (!newParseEntry) {
return false;
}
if (!parseRecordStack.append(newParseEntry)) {
return false;
}
@ -1160,8 +1171,12 @@ inline bool JSONReviveHandler<CharT>::arrayElement(
return false;
}
size_t index = (*elements)->length() - 1;
JS::PropertyKey key = js::PropertyKey::Int(index);
return finishMemberParseRecord(key, parseRecordStack.back());
// The JSON string is limited to JS::MaxStringLength, so there should be no
// way to get more than IntMax elements
MOZ_ASSERT(index <= js::PropertyKey::IntMax);
Rooted<JS::PropertyKey> key(context(), js::PropertyKey::Int(int32_t(index)));
Rooted<ParseRecordEntry*> parseRecordBack(context(), parseRecordStack.back());
return finishMemberParseRecord(key, parseRecordBack);
}
template <typename CharT>
@ -1171,7 +1186,8 @@ inline bool JSONReviveHandler<CharT>::finishArray(
if (!Base::finishArray(stack, vp, elements)) {
return false;
}
if (!finishCompoundParseRecord(vp, parseRecordStack.back())) {
Rooted<ParseRecordEntry*> parseRecordBack(context(), parseRecordStack.back());
if (!finishCompoundParseRecord(vp, parseRecordBack)) {
return false;
}
parseRecordStack.popBack();
@ -1181,17 +1197,21 @@ inline bool JSONReviveHandler<CharT>::finishArray(
template <typename CharT>
inline bool JSONReviveHandler<CharT>::finishMemberParseRecord(
JS::PropertyKey& key, ParseRecordEntry& objectEntry) {
parseRecord.key = key;
return objectEntry.put(key, std::move(parseRecord));
Handle<JS::PropertyKey> key, Handle<ParseRecordEntry*> parseEntry) {
parseRecord->setKey(context(), key.get());
Rooted<Value> pro(context(), ObjectValue(*parseRecord));
parseRecord = nullptr;
return JS_SetPropertyById(context(), parseEntry, key, pro);
}
template <typename CharT>
inline bool JSONReviveHandler<CharT>::finishCompoundParseRecord(
const Value& value, ParseRecordEntry& objectEntry) {
Rooted<JSONParseNode*> parseNode(context());
parseRecord = ParseRecordObject(parseNode, value);
return parseRecord.addEntries(context(), std::move(objectEntry));
const Value& value, Handle<ParseRecordEntry*> parseEntry) {
parseRecord = ParseRecordObject::create(context(), value);
if (!parseRecord) {
return false;
}
return parseRecord->setEntries(context(), parseEntry);
}
template <typename CharT>
@ -1203,30 +1223,33 @@ inline bool JSONReviveHandler<CharT>::finishPrimitiveParseRecord(
if (!parseNode) {
return false;
}
parseRecord = ParseRecordObject(parseNode, value);
return true;
parseRecord = ParseRecordObject::create(context(), parseNode, value);
return !!parseRecord;
}
template <typename CharT>
void JSONReviveHandler<CharT>::trace(JSTracer* trc) {
Base::trace(trc);
parseRecord.trace(trc);
for (auto& entry : this->parseRecordStack) {
entry.trace(trc);
if (parseRecord) {
TraceRoot(trc, &parseRecord, "parse record");
}
this->parseRecordStack.trace(trc);
}
template <typename CharT>
bool JSONReviveParser<CharT>::parse(JS::MutableHandle<JS::Value> vp,
JS::MutableHandle<ParseRecordObject> pro) {
JS::MutableHandle<ParseRecordObject*> pro) {
JS::Rooted<JS::Value> tempValue(this->handler.cx);
vp.setUndefined();
bool result = this->parseImpl(
tempValue, [&](JS::Handle<JS::Value> value) { vp.set(value); });
pro.set(std::move(this->handler.parseRecord));
return result;
if (!this->parseImpl(tempValue,
[&](JS::Handle<JS::Value> value) { vp.set(value); })) {
return false;
}
MOZ_ASSERT(this->handler.parseRecord);
pro.set(this->handler.parseRecord);
return true;
}
template <typename CharT>

View file

@ -409,16 +409,16 @@ class MOZ_STACK_CLASS JSONReviveHandler : public JSONFullParseHandler<CharT> {
void trace(JSTracer* trc);
private:
inline bool finishMemberParseRecord(JS::PropertyKey& key,
ParseRecordEntry& objectEntry);
inline bool finishMemberParseRecord(Handle<JS::PropertyKey> key,
Handle<ParseRecordEntry*> parseEntry);
inline bool finishCompoundParseRecord(const Value& value,
ParseRecordEntry& objectEntry);
Handle<ParseRecordEntry*> parseEntry);
inline bool finishPrimitiveParseRecord(const Value& value, SourceT source);
Vector<ParseRecordEntry, 10> parseRecordStack;
GCVector<ParseRecordEntry*, 10> parseRecordStack;
public:
ParseRecordObject parseRecord;
ParseRecordObject* parseRecord = nullptr;
};
template <typename CharT>
@ -652,7 +652,7 @@ class MOZ_STACK_CLASS JSONReviveParser
* set to |undefined|.
*/
bool parse(JS::MutableHandle<JS::Value> vp,
JS::MutableHandle<ParseRecordObject> pro);
JS::MutableHandle<ParseRecordObject*> pro);
void trace(JSTracer* trc);
};

View file

@ -2795,11 +2795,12 @@ class GetObjectSlotNameFunctor : public JS::TracingContext::Functor {
public:
explicit GetObjectSlotNameFunctor(JSObject* ctx) : obj(ctx) {}
virtual void operator()(JS::TracingContext* trc, char* buf,
virtual void operator()(JS::TracingContext* trc, const char* name, char* buf,
size_t bufsize) override;
};
void GetObjectSlotNameFunctor::operator()(JS::TracingContext* tcx, char* buf,
void GetObjectSlotNameFunctor::operator()(JS::TracingContext* tcx,
const char* name, char* buf,
size_t bufsize) {
MOZ_ASSERT(tcx->index() != JS::TracingContext::InvalidIndex);

View file

@ -2553,6 +2553,8 @@ nsresult nsLayoutUtils::GetFramesForArea(RelativeTo aRelativeTo,
nsDisplayItem::HitTestState hitTestState;
list.HitTest(&builder, aRect, &hitTestState, &aOutFrames);
builder.SetIsDestroying();
list.DeleteAll(&builder);
builder.EndFrame();
return NS_OK;
@ -2807,7 +2809,10 @@ struct TemporaryDisplayListBuilder {
const bool aBuildCaret)
: mBuilder(aFrame, aBuilderMode, aBuildCaret), mList(&mBuilder) {}
~TemporaryDisplayListBuilder() { mList.DeleteAll(&mBuilder); }
~TemporaryDisplayListBuilder() {
mBuilder.SetIsDestroying();
mList.DeleteAll(&mBuilder);
}
nsDisplayListBuilder mBuilder;
nsDisplayList mList;

View file

@ -164,7 +164,10 @@ class RetainedDisplayListBuilder {
RetainedDisplayListBuilder(nsIFrame* aReferenceFrame,
nsDisplayListBuilderMode aMode, bool aBuildCaret)
: mBuilder(aReferenceFrame, aMode, aBuildCaret, true), mList(&mBuilder) {}
~RetainedDisplayListBuilder() { mList.DeleteAll(&mBuilder); }
~RetainedDisplayListBuilder() {
mBuilder.SetIsDestroying();
mList.DeleteAll(&mBuilder);
}
nsDisplayListBuilder* Builder() { return &mBuilder; }

View file

@ -731,7 +731,8 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mBuildAsyncZoomContainer(false),
mIsRelativeToLayoutViewport(false),
mUseOverlayScrollbars(false),
mAlwaysLayerizeScrollbars(false) {
mAlwaysLayerizeScrollbars(false),
mIsDestroying(false) {
MOZ_COUNT_CTOR(nsDisplayListBuilder);
mBuildCompositorHitTestInfo = mAsyncPanZoomEnabled && IsForPainting();

View file

@ -918,10 +918,12 @@ class nsDisplayListBuilder {
}
void Destroy(DisplayListArenaObjectId aId, void* aPtr) {
return mPool.Free(aId, aPtr);
if (!mIsDestroying) {
mPool.Free(aId, aPtr);
}
}
void Destroy(DisplayItemType aType, void* aPtr) {
return Destroy(DisplayListArenaObjectId(size_t(aType)), aPtr);
Destroy(DisplayListArenaObjectId(size_t(aType)), aPtr);
}
/**
@ -1691,6 +1693,9 @@ class nsDisplayListBuilder {
*/
void ReuseDisplayItem(nsDisplayItem* aItem);
void SetIsDestroying() { mIsDestroying = true; }
bool IsDestroying() const { return mIsDestroying; }
private:
bool MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
const nsRect& aVisibleRect,
@ -1890,6 +1895,7 @@ class nsDisplayListBuilder {
bool mAlwaysLayerizeScrollbars;
bool mIsReusingStackingContextItems;
bool mIsDestroying;
Maybe<layers::ScrollDirection> mCurrentScrollbarDirection;
};

View file

@ -317,10 +317,23 @@ float Gecko_GetScrollbarInlineSize(const nsPresContext* aPc) {
return aPc->DevPixelsToFloatCSSPixels(size);
}
PseudoStyleType Gecko_GetImplementedPseudo(const Element* aElement) {
PseudoStyleType Gecko_GetImplementedPseudoType(const Element* aElement) {
return aElement->GetPseudoElementType();
}
nsAtom* Gecko_GetImplementedPseudoIdentifier(const Element* aElement) {
if (!PseudoStyle::IsNamedViewTransitionPseudoElement(
aElement->GetPseudoElementType())) {
return nullptr;
}
if (!aElement->HasName()) {
return nullptr;
}
return aElement->GetParsedAttr(nsGkAtoms::name)->GetAtomValue();
}
uint32_t Gecko_CalcStyleDifference(const ComputedStyle* aOldStyle,
const ComputedStyle* aNewStyle,
bool* aAnyStyleStructChanged,

View file

@ -333,9 +333,11 @@ bool Gecko_AnimationNameMayBeReferencedFromStyle(const nsPresContext*,
float Gecko_GetScrollbarInlineSize(const nsPresContext*);
// Incremental restyle.
mozilla::PseudoStyleType Gecko_GetImplementedPseudo(
// Retrive pseudo type from an element.
mozilla::PseudoStyleType Gecko_GetImplementedPseudoType(
const mozilla::dom::Element*);
// Retrive pseudo identifier from an element if any.
nsAtom* Gecko_GetImplementedPseudoIdentifier(const mozilla::dom::Element*);
// We'd like to return `nsChangeHint` here, but bindgen bitfield enums don't
// work as return values with the Linux 32-bit ABI at the moment because

View file

@ -114,12 +114,16 @@ class PseudoStyle final {
aType < Type::WrapperAnonBoxesEnd;
}
static bool IsViewTransitionPseudoElement(Type aType) {
return aType == Type::viewTransition ||
aType == Type::viewTransitionGroup ||
static bool IsNamedViewTransitionPseudoElement(Type aType) {
return aType == Type::viewTransitionGroup ||
aType == Type::viewTransitionImagePair ||
aType == Type::viewTransitionOld || aType == Type::viewTransitionNew;
}
static bool IsViewTransitionPseudoElement(Type aType) {
return aType == Type::viewTransition ||
IsNamedViewTransitionPseudoElement(aType);
}
};
/*

Some files were not shown because too many files have changed in this diff Show more