Update On Thu Nov 28 19:22:49 CET 2024
This commit is contained in:
parent
649568dd1a
commit
1542cc8cd0
1449 changed files with 19875 additions and 9246 deletions
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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(" ");
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 don’t 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 =
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
@ -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); }
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
#define StringOperations_h
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
std::string hash(const std::string &Str);
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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" },
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -100,4 +100,13 @@ function thisProperties() {
|
|||
debugger;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function explicitResourceManagement() {
|
||||
using erm = {
|
||||
[Symbol.dispose]() {},
|
||||
foo: 42
|
||||
};
|
||||
console.log(erm.foo);
|
||||
debugger;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, ©View);
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
|
@ -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"),
|
||||
|
|
|
@ -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".
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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});
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)) {
|
163
js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js
Normal file
163
js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js
Normal 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");
|
||||
|
|
@ -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");
|
||||
|
|
@ -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");
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue