зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound
--HG-- extra : rebase_source : 8265ad85fc5376a71af7ed3afe8463b7178286f3
This commit is contained in:
Коммит
e10cc6aac4
|
@ -176,7 +176,7 @@
|
|||
<div id="certErrorAndCaptivePortalButtonContainer" class="button-container">
|
||||
<button id="returnButton" class="primary" autocomplete="off">&returnToPreviousPage1.label;</button>
|
||||
<button id="openPortalLoginPageButton" class="primary" autocomplete="off">&openPortalLoginPage.label2;</button>
|
||||
<button id="advancedButton" autocomplete="off">&continue.label;</button>
|
||||
<button id="advancedButton" autocomplete="off">&continue1.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -56,8 +56,6 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(PaymentRe
|
|||
let url = "formautofill/editCreditCard.xhtml";
|
||||
this.promiseReady = this._fetchMarkup(url).then(doc => {
|
||||
this.form = doc.getElementById("form");
|
||||
this.form.addEventListener("input", this);
|
||||
this.form.addEventListener("invalid", this);
|
||||
return this.form;
|
||||
});
|
||||
}
|
||||
|
@ -88,6 +86,12 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(PaymentRe
|
|||
getAddressLabel: PaymentDialogUtils.getAddressLabel,
|
||||
});
|
||||
|
||||
// The EditCreditCard constructor adds input event listeners on the same element,
|
||||
// which update field validity. By adding our event listeners after this constructor,
|
||||
// validity will be updated before our handlers get the event
|
||||
form.addEventListener("input", this);
|
||||
form.addEventListener("invalid", this);
|
||||
|
||||
let fragment = document.createDocumentFragment();
|
||||
fragment.append(this.addressAddLink);
|
||||
fragment.append(" ");
|
||||
|
|
|
@ -300,6 +300,8 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
|
|||
this.dataset[shippingType + "AddressTitleEdit"];
|
||||
let addressPickerLabel = this._shippingAddressPicker.dataset[shippingType + "AddressLabel"];
|
||||
this._shippingAddressPicker.setAttribute("label", addressPickerLabel);
|
||||
let optionPickerLabel = this._shippingOptionPicker.dataset[shippingType + "OptionsLabel"];
|
||||
this._shippingOptionPicker.setAttribute("label", optionPickerLabel);
|
||||
|
||||
let totalItem = paymentRequest.getTotalItem(state);
|
||||
let totalAmountEl = this.querySelector("#total > currency-amount");
|
||||
|
@ -311,7 +313,13 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
|
|||
this._header.hidden = !state.page.onboardingWizard && state.page.id != "payment-summary";
|
||||
|
||||
this._orderDetailsOverlay.hidden = !state.orderDetailsShowing;
|
||||
this._errorText.textContent = paymentDetails.error;
|
||||
let genericError = "";
|
||||
if (this._shippingAddressPicker.value &&
|
||||
(!request.paymentDetails.shippingOptions ||
|
||||
!request.paymentDetails.shippingOptions.length)) {
|
||||
genericError = this._errorText.dataset[shippingType + "GenericError"];
|
||||
}
|
||||
this._errorText.textContent = paymentDetails.error || genericError;
|
||||
|
||||
let paymentOptions = request.paymentOptions;
|
||||
for (let element of this._shippingRelatedEls) {
|
||||
|
|
|
@ -17,6 +17,11 @@
|
|||
<!ENTITY deliveryAddressLabel "Delivery Address">
|
||||
<!ENTITY pickupAddressLabel "Pickup Address">
|
||||
<!ENTITY shippingOptionsLabel "Shipping Options">
|
||||
<!ENTITY deliveryOptionsLabel "Delivery Options">
|
||||
<!ENTITY pickupOptionsLabel "Pickup Options">
|
||||
<!ENTITY shippingGenericError "Can't ship to this address. Select a different address.">
|
||||
<!ENTITY deliveryGenericError "Can't deliver to this address. Select a different address.">
|
||||
<!ENTITY pickupGenericError "Can't pick up from this address. Select a different address.">
|
||||
<!ENTITY paymentMethodsLabel "Payment Method">
|
||||
<!ENTITY address.addLink.label "Add">
|
||||
<!ENTITY address.editLink.label "Edit">
|
||||
|
@ -100,7 +105,11 @@
|
|||
|
||||
<template id="payment-dialog-template">
|
||||
<header>
|
||||
<div class="page-error" aria-live="polite"></div>
|
||||
<div class="page-error"
|
||||
data-shipping-generic-error="&shippingGenericError;"
|
||||
data-delivery-generic-error="&deliveryGenericError;"
|
||||
data-pickup-generic-error="&pickupGenericError;"
|
||||
aria-live="polite"></div>
|
||||
<div id="total">
|
||||
<currency-amount display-code="display-code"></currency-amount>
|
||||
<div>&header.payTo; <span id="host-name"></span></div>
|
||||
|
@ -122,7 +131,9 @@
|
|||
selected-state-key="selectedShippingAddress"></address-picker>
|
||||
|
||||
<shipping-option-picker class="shipping-related"
|
||||
label="&shippingOptionsLabel;"></shipping-option-picker>
|
||||
data-shipping-options-label="&shippingOptionsLabel;"
|
||||
data-delivery-options-label="&deliveryOptionsLabel;"
|
||||
data-pickup-options-label="&pickupOptionsLabel;"></shipping-option-picker>
|
||||
|
||||
<payment-method-picker selected-state-key="selectedPaymentCard"
|
||||
data-add-link-label="&basicCard.addLink.label;"
|
||||
|
|
|
@ -347,6 +347,53 @@ add_task(async function test_edit() {
|
|||
|
||||
form.remove();
|
||||
});
|
||||
|
||||
add_task(async function test_field_validity_updates() {
|
||||
let form = new BasicCardForm();
|
||||
form.dataset.updateButtonLabel = "Add";
|
||||
await form.promiseReady;
|
||||
display.appendChild(form);
|
||||
await asyncElementRendered();
|
||||
|
||||
let ccNumber = form.form.querySelector("#cc-number");
|
||||
let nameInput = form.form.querySelector("#cc-name");
|
||||
|
||||
info("test with valid cc-number but missing cc-name");
|
||||
ccNumber.focus();
|
||||
sendString("4111111111111111");
|
||||
ok(ccNumber.checkValidity(), "cc-number field is valid with good input");
|
||||
ok(!nameInput.checkValidity(), "cc-name field is invalid when empty");
|
||||
ok(form.saveButton.disabled, "Save button should be disabled with incomplete input");
|
||||
|
||||
info("correct by adding cc-name value");
|
||||
nameInput.focus();
|
||||
sendString("First");
|
||||
ok(ccNumber.checkValidity(), "cc-number field is valid with good input");
|
||||
ok(nameInput.checkValidity(), "cc-name field is valid with a value");
|
||||
ok(!form.saveButton.disabled, "Save button should not be disabled with good input");
|
||||
|
||||
info("edit to make the cc-number invalid");
|
||||
ccNumber.focus();
|
||||
sendString("aa");
|
||||
nameInput.focus();
|
||||
sendString("Surname");
|
||||
|
||||
ok(!ccNumber.checkValidity(), "cc-number field becomes invalid with bad input");
|
||||
ok(nameInput.checkValidity(), "cc-name field is valid with a value");
|
||||
ok(form.saveButton.disabled, "Save button becomes disabled with bad input");
|
||||
|
||||
info("fix the cc-number to make it all valid again");
|
||||
ccNumber.focus();
|
||||
sendKey("BACK_SPACE");
|
||||
sendKey("BACK_SPACE");
|
||||
info("after backspaces, ccNumber.value: " + ccNumber.value);
|
||||
|
||||
ok(ccNumber.checkValidity(), "cc-number field becomes valid with corrected input");
|
||||
ok(nameInput.checkValidity(), "cc-name field is valid with a value");
|
||||
ok(!form.saveButton.disabled, "Save button is no longer disabled with corrected input");
|
||||
|
||||
form.remove();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -144,6 +144,43 @@ add_task(async function test_initial_completeStatus() {
|
|||
ok(payButton.disabled, "Button is disabled by default");
|
||||
});
|
||||
|
||||
add_task(async function test_generic_errors() {
|
||||
await setup();
|
||||
const SHIPPING_GENERIC_ERROR = "Can't ship to that address";
|
||||
el1._errorText.dataset.shippingGenericError = SHIPPING_GENERIC_ERROR;
|
||||
el1.requestStore.setState({
|
||||
savedAddresses: {
|
||||
"48bnds6854t": {
|
||||
"address-level1": "MI",
|
||||
"address-level2": "Some City",
|
||||
"country": "US",
|
||||
"guid": "48bnds6854t",
|
||||
"name": "Mr. Foo",
|
||||
"postal-code": "90210",
|
||||
"street-address": "123 Sesame Street,\nApt 40",
|
||||
"tel": "+1 519 555-5555",
|
||||
},
|
||||
"68gjdh354j": {
|
||||
"address-level1": "CA",
|
||||
"address-level2": "Mountain View",
|
||||
"country": "US",
|
||||
"guid": "68gjdh354j",
|
||||
"name": "Mrs. Bar",
|
||||
"postal-code": "94041",
|
||||
"street-address": "P.O. Box 123",
|
||||
"tel": "+1 650 555-5555",
|
||||
},
|
||||
},
|
||||
selectedShippingAddress: "48bnds6854t",
|
||||
});
|
||||
await asyncElementRendered();
|
||||
|
||||
let picker = el1._shippingAddressPicker;
|
||||
ok(picker.value, "Address picker should have a selected value");
|
||||
is(el1._errorText.textContent, SHIPPING_GENERIC_ERROR,
|
||||
"Generic error message should be shown when no shipping options or error are provided");
|
||||
});
|
||||
|
||||
add_task(async function test_processing_completeStatus() {
|
||||
// "processing": has overlay. Check button visibility
|
||||
await setup();
|
||||
|
@ -234,6 +271,34 @@ add_task(async function test_scrollPaymentRequestPage() {
|
|||
el1.parentElement.style.height = "";
|
||||
});
|
||||
|
||||
add_task(async function test_picker_labels() {
|
||||
await setup();
|
||||
let picker = el1._shippingOptionPicker;
|
||||
|
||||
const SHIPPING_OPTIONS_LABEL = "Shipping options";
|
||||
const DELIVERY_OPTIONS_LABEL = "Delivery options";
|
||||
const PICKUP_OPTIONS_LABEL = "Pickup options";
|
||||
picker.dataset.shippingOptionsLabel = SHIPPING_OPTIONS_LABEL;
|
||||
picker.dataset.deliveryOptionsLabel = DELIVERY_OPTIONS_LABEL;
|
||||
picker.dataset.pickupOptionsLabel = PICKUP_OPTIONS_LABEL;
|
||||
|
||||
for (let [shippingType, label] of [
|
||||
["shipping", SHIPPING_OPTIONS_LABEL],
|
||||
["delivery", DELIVERY_OPTIONS_LABEL],
|
||||
["pickup", PICKUP_OPTIONS_LABEL],
|
||||
]) {
|
||||
let request = deepClone(el1.requestStore.getState().request);
|
||||
request.paymentOptions.requestShipping = true;
|
||||
request.paymentOptions.shippingType = shippingType;
|
||||
await el1.requestStore.setState({ request });
|
||||
await asyncElementRendered();
|
||||
is(picker.labelElement.textContent, label,
|
||||
`Label should be appropriate for ${shippingType}`);
|
||||
info(JSON.stringify(el1.requestStore.getState(), null, 2));
|
||||
info(picker.outerHTML);
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_disconnect() {
|
||||
await setup();
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<!ENTITY returnToPreviousPage.label "Go Back">
|
||||
<!ENTITY returnToPreviousPage1.label "Go Back (Recommended)">
|
||||
<!ENTITY advanced.label "Advanced">
|
||||
<!ENTITY continue.label "Continue">
|
||||
<!ENTITY continue1.label "Continue…">
|
||||
|
||||
<!-- Specific error messages -->
|
||||
|
||||
|
|
|
@ -800,6 +800,10 @@
|
|||
box-shadow: inset 4px 0 var(--blue-40);
|
||||
}
|
||||
|
||||
.all-tabs-item[selected]:-moz-locale-dir(rtl) {
|
||||
box-shadow: inset -4px 0 var(--blue-40);
|
||||
}
|
||||
|
||||
.all-tabs-secondary-button > label {
|
||||
display: none;
|
||||
margin: 0 5.5px;
|
||||
|
|
|
@ -667,7 +667,7 @@ static void adjust_eh_frame(ElfSection* eh_frame, unsigned int origAddr, Elf* el
|
|||
|
||||
// Decoding of eh_frame based on https://www.airs.com/blog/archives/460
|
||||
while (size) {
|
||||
if (size < 2 * sizeof(uint32_t)) goto malformed;
|
||||
if (size < sizeof(uint32_t)) goto malformed;
|
||||
|
||||
serializable<FixedSizeData<uint32_t>> entryLength(data, size, elf->getClass(), elf->getData());
|
||||
if (!advance_buffer(&data, &size, sizeof(uint32_t))) goto malformed;
|
||||
|
@ -675,6 +675,12 @@ static void adjust_eh_frame(ElfSection* eh_frame, unsigned int origAddr, Elf* el
|
|||
char* cursor = data;
|
||||
size_t length = entryLength.value;
|
||||
|
||||
if (length == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (size < sizeof(uint32_t)) goto malformed;
|
||||
|
||||
serializable<FixedSizeData<uint32_t>> id(data, size, elf->getClass(), elf->getData());
|
||||
if (!advance_buffer(&cursor, &length, sizeof(uint32_t))) goto malformed;
|
||||
|
||||
|
|
|
@ -12,10 +12,16 @@ const { require } = BrowserLoader({
|
|||
});
|
||||
const Services = require("Services");
|
||||
|
||||
const { bindActionCreators } = require("devtools/client/shared/vendor/redux");
|
||||
const { createFactory } =
|
||||
require("devtools/client/shared/vendor/react");
|
||||
const { render, unmountComponentAtNode } =
|
||||
require("devtools/client/shared/vendor/react-dom");
|
||||
const Provider =
|
||||
createFactory(require("devtools/client/shared/vendor/react-redux").Provider);
|
||||
|
||||
const actions = require("./src/actions/index");
|
||||
const { configureStore } = require("./src/create-store");
|
||||
|
||||
const App = createFactory(require("./src/components/App"));
|
||||
|
||||
|
@ -27,7 +33,10 @@ const AboutDebugging = {
|
|||
return;
|
||||
}
|
||||
|
||||
render(App(), this.mount);
|
||||
this.store = configureStore();
|
||||
this.actions = bindActionCreators(actions, this.store.dispatch);
|
||||
|
||||
render(Provider({ store: this.store }, App()), this.mount);
|
||||
},
|
||||
|
||||
destroy() {
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const ui = require("./ui");
|
||||
|
||||
Object.assign(exports, ui);
|
|
@ -0,0 +1,8 @@
|
|||
# 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/.
|
||||
|
||||
DevToolsModules(
|
||||
'index.js',
|
||||
'ui.js',
|
||||
)
|
|
@ -0,0 +1,20 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
PAGE_SELECTED,
|
||||
} = require("../constants");
|
||||
|
||||
function selectPage(page) {
|
||||
return {
|
||||
type: PAGE_SELECTED,
|
||||
page,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
selectPage,
|
||||
};
|
|
@ -4,22 +4,58 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
const { PAGES } = require("../constants");
|
||||
|
||||
const RuntimePage = createFactory(require("./RuntimePage"));
|
||||
const Sidebar = createFactory(require("./Sidebar"));
|
||||
|
||||
class App extends PureComponent {
|
||||
static get propTypes() {
|
||||
return {
|
||||
// The "dispatch" helper is forwarded to the App component via connect.
|
||||
// From that point, components are responsible for forwarding the dispatch
|
||||
// property to all components who need to dispatch actions.
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
selectedPage: PropTypes.string.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
getSelectedPageComponent() {
|
||||
switch (this.props.selectedPage) {
|
||||
case PAGES.THIS_FIREFOX:
|
||||
return RuntimePage();
|
||||
default:
|
||||
// Invalid page, blank.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { dispatch, selectedPage } = this.props;
|
||||
|
||||
return dom.div(
|
||||
{
|
||||
className: "app",
|
||||
},
|
||||
Sidebar(),
|
||||
RuntimePage(),
|
||||
Sidebar({ dispatch, selectedPage }),
|
||||
this.getSelectedPageComponent(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = App;
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
selectedPage: state.ui.selectedPage,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
dispatch,
|
||||
});
|
||||
|
||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(App);
|
||||
|
|
|
@ -6,23 +6,44 @@
|
|||
|
||||
const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
const { PAGES } = require("../constants");
|
||||
|
||||
const SidebarItem = createFactory(require("./SidebarItem"));
|
||||
|
||||
const FIREFOX_ICON = "chrome://devtools/skin/images/firefox-logo-glyph.svg";
|
||||
const MOBILE_ICON = "chrome://devtools/skin/images/firefox-logo-glyph.svg";
|
||||
|
||||
class Sidebar extends PureComponent {
|
||||
static get propTypes() {
|
||||
return {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
selectedPage: PropTypes.string.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return dom.section(
|
||||
const { dispatch, selectedPage } = this.props;
|
||||
|
||||
return dom.aside(
|
||||
{
|
||||
className: "sidebar",
|
||||
},
|
||||
dom.ul(
|
||||
{},
|
||||
SidebarItem({
|
||||
id: PAGES.THIS_FIREFOX,
|
||||
dispatch,
|
||||
icon: FIREFOX_ICON,
|
||||
isSelected: true,
|
||||
isSelected: PAGES.THIS_FIREFOX === selectedPage,
|
||||
name: "This Firefox",
|
||||
}),
|
||||
SidebarItem({
|
||||
id: PAGES.CONNECT,
|
||||
dispatch,
|
||||
icon: MOBILE_ICON,
|
||||
isSelected: PAGES.CONNECT === selectedPage,
|
||||
name: "Connect",
|
||||
})
|
||||
)
|
||||
);
|
||||
|
|
|
@ -8,24 +8,33 @@ const { PureComponent } = require("devtools/client/shared/vendor/react");
|
|||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
const Actions = require("../actions/index");
|
||||
|
||||
/**
|
||||
* This component displays an item of the Sidebar component.
|
||||
*/
|
||||
class SidebarItem extends PureComponent {
|
||||
static get propTypes() {
|
||||
return {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
icon: PropTypes.string.isRequired,
|
||||
id: PropTypes.string.isRequired,
|
||||
isSelected: PropTypes.bool.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
onItemClick() {
|
||||
this.props.dispatch(Actions.selectPage(this.props.id));
|
||||
}
|
||||
|
||||
render() {
|
||||
const { icon, isSelected, name } = this.props;
|
||||
|
||||
return dom.li(
|
||||
{
|
||||
className: "sidebar-item" + (isSelected ? " sidebar-item--selected" : ""),
|
||||
onClick: () => this.onItemClick()
|
||||
},
|
||||
dom.img({
|
||||
className: "sidebar-item__icon" +
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const actionTypes = {
|
||||
PAGE_SELECTED: "PAGE_SELECTED",
|
||||
};
|
||||
|
||||
const PAGES = {
|
||||
THIS_FIREFOX: "this-firefox",
|
||||
CONNECT: "connect",
|
||||
};
|
||||
|
||||
// flatten constants
|
||||
module.exports = Object.assign({}, { PAGES }, actionTypes);
|
|
@ -0,0 +1,18 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { createStore } = require("devtools/client/shared/vendor/redux");
|
||||
|
||||
const rootReducer = require("./reducers/index");
|
||||
const { UiState } = require("./reducers/ui-state");
|
||||
|
||||
exports.configureStore = function() {
|
||||
const initialState = {
|
||||
ui: new UiState()
|
||||
};
|
||||
|
||||
return createStore(rootReducer, initialState);
|
||||
};
|
|
@ -3,5 +3,12 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += [
|
||||
'actions',
|
||||
'components',
|
||||
'reducers',
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'constants.js',
|
||||
'create-store.js',
|
||||
)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { combineReducers } = require("devtools/client/shared/vendor/redux");
|
||||
const { uiReducer } = require("./ui-state");
|
||||
|
||||
module.exports = combineReducers({
|
||||
ui: uiReducer
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
# 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/.
|
||||
|
||||
DevToolsModules(
|
||||
'index.js',
|
||||
'ui-state.js',
|
||||
)
|
|
@ -0,0 +1,33 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
PAGE_SELECTED,
|
||||
PAGES
|
||||
} = require("../constants");
|
||||
|
||||
function UiState() {
|
||||
return {
|
||||
selectedPage: PAGES.THIS_FIREFOX
|
||||
};
|
||||
}
|
||||
|
||||
function uiReducer(state = UiState(), action) {
|
||||
switch (action.type) {
|
||||
case PAGE_SELECTED: {
|
||||
const { page } = action;
|
||||
return { selectedPage: page };
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
UiState,
|
||||
uiReducer,
|
||||
};
|
|
@ -36,16 +36,14 @@ add_task(async function() {
|
|||
|
||||
info("Click the event icon for the first element");
|
||||
let onShown = tooltip.once("shown");
|
||||
EventUtils.synthesizeMouseAtCenter(evHolder1, {},
|
||||
inspector.markup.doc.defaultView);
|
||||
EventUtils.synthesizeMouseAtCenter(evHolder1, {}, inspector.markup.win);
|
||||
await onShown;
|
||||
info("event tooltip for the first div is shown");
|
||||
|
||||
info("Click the event icon for the second element");
|
||||
const onHidden = tooltip.once("hidden");
|
||||
let onHidden = tooltip.once("hidden");
|
||||
onShown = tooltip.once("shown");
|
||||
EventUtils.synthesizeMouseAtCenter(evHolder2, {},
|
||||
inspector.markup.doc.defaultView);
|
||||
EventUtils.synthesizeMouseAtCenter(evHolder2, {}, inspector.markup.win);
|
||||
|
||||
await onHidden;
|
||||
info("previous tooltip hidden");
|
||||
|
@ -53,6 +51,21 @@ add_task(async function() {
|
|||
await onShown;
|
||||
info("event tooltip for the second div is shown");
|
||||
|
||||
info("Check that clicking on evHolder2 again hides the tooltip");
|
||||
onHidden = tooltip.once("hidden");
|
||||
EventUtils.synthesizeMouseAtCenter(evHolder2, {}, inspector.markup.win);
|
||||
await onHidden;
|
||||
|
||||
info("Check that the tooltip does not reappear immediately after");
|
||||
await waitForTime(1000);
|
||||
is(tooltip.isVisible(), false,
|
||||
"The tooltip is still hidden after waiting for one second");
|
||||
|
||||
info("Open the tooltip on evHolder2 again");
|
||||
onShown = tooltip.once("shown");
|
||||
EventUtils.synthesizeMouseAtCenter(evHolder2, {}, inspector.markup.win);
|
||||
await onShown;
|
||||
|
||||
info("Click on the computed view tab");
|
||||
const onHighlighterHidden = toolbox.once("node-unhighlight");
|
||||
const onTabComputedViewSelected = inspector.sidebar.once("computedview-selected");
|
||||
|
|
|
@ -101,7 +101,6 @@ MarkupElementContainer.prototype = extend(MarkupContainer.prototype, {
|
|||
|
||||
async _buildEventTooltipContent(target) {
|
||||
const tooltip = this.markup.eventDetailsTooltip;
|
||||
|
||||
await tooltip.hide();
|
||||
|
||||
const listenerInfo = await this.node.getEventListenerInfo();
|
||||
|
@ -114,7 +113,20 @@ MarkupElementContainer.prototype = extend(MarkupContainer.prototype, {
|
|||
tooltip.once("hidden", () => {
|
||||
// Enable the image preview tooltip after closing the event details
|
||||
this.markup._enableImagePreviewTooltip();
|
||||
|
||||
// Allow clicks on the event badge to display the event popup again
|
||||
// (but allow the currently queued click event to run first).
|
||||
this.markup.win.setTimeout(() => {
|
||||
if (this.editor._eventBadge) {
|
||||
this.editor._eventBadge.style.pointerEvents = "auto";
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
|
||||
// Prevent clicks on the event badge to display the event popup again.
|
||||
if (this.editor._eventBadge) {
|
||||
this.editor._eventBadge.style.pointerEvents = "none";
|
||||
}
|
||||
tooltip.show(target);
|
||||
},
|
||||
|
||||
|
|
|
@ -330,6 +330,7 @@ function HTMLTooltip(toolboxDoc, {
|
|||
this._position = null;
|
||||
|
||||
this._onClick = this._onClick.bind(this);
|
||||
this._onMouseup = this._onMouseup.bind(this);
|
||||
this._onXulPanelHidden = this._onXulPanelHidden.bind(this);
|
||||
|
||||
this._toggle = new TooltipToggle(this);
|
||||
|
@ -456,6 +457,7 @@ HTMLTooltip.prototype = {
|
|||
// Update the top window reference each time in case the host changes.
|
||||
this.topWindow = this._getTopWindow();
|
||||
this.topWindow.addEventListener("click", this._onClick, true);
|
||||
this.topWindow.addEventListener("mouseup", this._onMouseup, true);
|
||||
this.emit("shown");
|
||||
}, 0);
|
||||
},
|
||||
|
@ -694,14 +696,21 @@ HTMLTooltip.prototype = {
|
|||
* Hide the current tooltip. The event "hidden" will be fired when the tooltip
|
||||
* is hidden.
|
||||
*/
|
||||
async hide() {
|
||||
async hide({ fromMouseup = false } = {}) {
|
||||
this.doc.defaultView.clearTimeout(this.attachEventsTimer);
|
||||
if (!this.isVisible()) {
|
||||
this.emit("hidden");
|
||||
return;
|
||||
}
|
||||
|
||||
this.topWindow.removeEventListener("click", this._onClick, true);
|
||||
// If the tooltip is hidden from a mouseup event, wait for a potential click event
|
||||
// to be consumed before removing event listeners.
|
||||
if (fromMouseup) {
|
||||
await new Promise(resolve => this.topWindow.setTimeout(resolve, 0));
|
||||
}
|
||||
|
||||
this.removeEventListeners();
|
||||
|
||||
this.container.classList.remove("tooltip-visible");
|
||||
if (this.useXulWrapper) {
|
||||
await this._hideXulWrapper();
|
||||
|
@ -716,6 +725,11 @@ HTMLTooltip.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
removeEventListeners: function() {
|
||||
this.topWindow.removeEventListener("click", this._onClick, true);
|
||||
this.topWindow.removeEventListener("mouseup", this._onMouseup, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the tooltip is currently displayed.
|
||||
* @return {Boolean} true if the tooltip is visible
|
||||
|
@ -730,6 +744,7 @@ HTMLTooltip.prototype = {
|
|||
*/
|
||||
destroy: function() {
|
||||
this.hide();
|
||||
this.removeEventListeners();
|
||||
this.container.remove();
|
||||
if (this.xulPanelWrapper) {
|
||||
this.xulPanelWrapper.remove();
|
||||
|
@ -766,12 +781,6 @@ HTMLTooltip.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
// If the disable autohide setting is in effect, ignore.
|
||||
if (Services.prefs.getBoolPref("ui.popup.disable_autohide", false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.hide();
|
||||
if (this.consumeOutsideClicks && e.button === 0) {
|
||||
// Consume only left click events (button === 0).
|
||||
e.preventDefault();
|
||||
|
@ -779,6 +788,25 @@ HTMLTooltip.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the tooltip on mouseup rather than on click because the surrounding markup
|
||||
* may change on mousedown in a way that prevents a "click" event from being fired.
|
||||
* If the element that received the mousedown and the mouseup are different, click
|
||||
* will not be fired.
|
||||
*/
|
||||
_onMouseup: function(e) {
|
||||
if (this._isInTooltipContainer(e.target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the disable autohide setting is in effect, ignore.
|
||||
if (Services.prefs.getBoolPref("ui.popup.disable_autohide", false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.hide({ fromMouseup: true });
|
||||
},
|
||||
|
||||
_isInTooltipContainer: function(node) {
|
||||
// Check if the target is the tooltip arrow.
|
||||
if (this.arrow && this.arrow === node) {
|
||||
|
|
|
@ -364,6 +364,7 @@ skip-if = verify
|
|||
[browser_webconsole_strict_mode_errors.js]
|
||||
[browser_webconsole_string.js]
|
||||
[browser_webconsole_telemetry_filters_changed.js]
|
||||
[browser_webconsole_telemetry_jump_to_definition.js]
|
||||
[browser_webconsole_time_methods.js]
|
||||
[browser_webconsole_timestamps.js]
|
||||
[browser_webconsole_trackingprotection_errors.js]
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests the jump_to_definition telemetry event.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = `data:text/html,<meta charset=utf8><script>
|
||||
function x(){}
|
||||
console.log("test message", x);
|
||||
</script>`;
|
||||
|
||||
const OPTOUT = Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT;
|
||||
|
||||
add_task(async function() {
|
||||
// Let's reset the counts.
|
||||
Services.telemetry.clearEvents();
|
||||
|
||||
// Ensure no events have been logged
|
||||
const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
|
||||
ok(!snapshot.parent, "No events have been logged for the main process");
|
||||
|
||||
const hud = await openNewTabAndConsole(TEST_URI);
|
||||
|
||||
const message = await waitFor(() => findMessage(hud, "test message"));
|
||||
info("Click on the 'jump to definition' button");
|
||||
const jumpIcon = message.querySelector(".jump-definition");
|
||||
jumpIcon.click();
|
||||
|
||||
const events = getJumpToDefinitionEventsExtra();
|
||||
is(events.length, 1, "There was 1 event logged");
|
||||
const [event] = events;
|
||||
ok(event.session_id > 0, "There is a valid session_id in the logged event");
|
||||
});
|
||||
|
||||
function getJumpToDefinitionEventsExtra() {
|
||||
// Retrieve and clear telemetry events.
|
||||
const snapshot = Services.telemetry.snapshotEvents(OPTOUT, true);
|
||||
|
||||
const events = snapshot.parent.filter(event =>
|
||||
event[1] === "devtools.main" &&
|
||||
event[2] === "jump_to_definition" &&
|
||||
event[3] === "webconsole"
|
||||
);
|
||||
|
||||
// Since we already know we have the correct event, we only return the `extra` field
|
||||
// that was passed to it (which is event[5] here).
|
||||
return events.map(event => event[5]);
|
||||
}
|
|
@ -4897,19 +4897,6 @@ nsGlobalWindowInner::GetIndexedDB(ErrorResult& aError)
|
|||
return mIndexedDB;
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindowInner::AddPendingPromise(mozilla::dom::Promise* aPromise)
|
||||
{
|
||||
mPendingPromises.AppendElement(aPromise);
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindowInner::RemovePendingPromise(mozilla::dom::Promise* aPromise)
|
||||
{
|
||||
DebugOnly<bool> foundIt = mPendingPromises.RemoveElement(aPromise);
|
||||
MOZ_ASSERT(foundIt, "tried to remove a non-existent element from mPendingPromises");
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// nsGlobalWindowInner::nsIInterfaceRequestor
|
||||
//*****************************************************************************
|
||||
|
|
|
@ -1208,10 +1208,6 @@ public:
|
|||
// Inner windows only.
|
||||
void UpdateCanvasFocus(bool aFocusChanged, nsIContent* aNewContent);
|
||||
|
||||
// See PromiseWindowProxy.h for an explanation.
|
||||
void AddPendingPromise(mozilla::dom::Promise* aPromise);
|
||||
void RemovePendingPromise(mozilla::dom::Promise* aPromise);
|
||||
|
||||
public:
|
||||
virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() override;
|
||||
|
||||
|
|
|
@ -1619,7 +1619,8 @@ GetDirectoryPath(const char *aPath) {
|
|||
#endif // DEBUG
|
||||
|
||||
extern "C" {
|
||||
void CGSSetDenyWindowServerConnections(bool);
|
||||
CGError
|
||||
CGSSetDenyWindowServerConnections(bool);
|
||||
void CGSShutdownServerConnections();
|
||||
};
|
||||
|
||||
|
@ -1631,13 +1632,15 @@ StartMacOSContentSandbox()
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!XRE_UseNativeEventProcessing()) {
|
||||
if (Preferences::GetBool(
|
||||
"security.sandbox.content.mac.disconnect-windowserver")) {
|
||||
// If we've opened a connection to the window server, shut it down now. Forbid
|
||||
// future connections as well. We do this for sandboxing, but it also ensures
|
||||
// that the Activity Monitor will not label the content process as "Not
|
||||
// responding" because it's not running a native event loop. See bug 1384336.
|
||||
CGSSetDenyWindowServerConnections(true);
|
||||
CGSShutdownServerConnections();
|
||||
CGError result = CGSSetDenyWindowServerConnections(true);
|
||||
MOZ_DIAGNOSTIC_ASSERT(result == kCGErrorSuccess);
|
||||
}
|
||||
|
||||
nsAutoCString appPath, appBinaryPath, appDir;
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/PromiseWindowProxy.h"
|
||||
|
||||
#include "nsGlobalWindowInner.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIWeakReference.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace dom;
|
||||
|
||||
|
||||
PromiseWindowProxy::PromiseWindowProxy(nsPIDOMWindowInner* aWindow, Promise* aPromise)
|
||||
: mPromise(aPromise)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWindow && aPromise);
|
||||
auto* window = nsGlobalWindowInner::Cast(aWindow);
|
||||
window->GetWeakReference(getter_AddRefs(mWindow));
|
||||
window->AddPendingPromise(aPromise);
|
||||
}
|
||||
|
||||
PromiseWindowProxy::~PromiseWindowProxy()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = GetWindow();
|
||||
if (window && mPromise) {
|
||||
nsGlobalWindowInner::Cast(window)->RemovePendingPromise(mPromise);
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<Promise>
|
||||
PromiseWindowProxy::Get() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mPromise) {
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<Promise> promise(mPromise);
|
||||
return promise;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner>
|
||||
PromiseWindowProxy::GetWindow() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mWindow);
|
||||
return window;
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_PromiseWindowProxy_h
|
||||
#define mozilla_dom_PromiseWindowProxy_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
|
||||
class nsIWeakReference;
|
||||
class nsPIDOMWindowInner;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Promise;
|
||||
|
||||
// When a data structure is waiting to resolve a promise from a
|
||||
// window, but that data structure is not owned by that window, there
|
||||
// exists a dilemma:
|
||||
//
|
||||
// 1) If the promise is never resolved, and the non-window data
|
||||
// structure is keeping alive the promise, the promise's window will
|
||||
// be leaked.
|
||||
//
|
||||
// 2) Something has to keep the promise alive from native code in case
|
||||
// script has dropped all direct references to it, but the promise is
|
||||
// later resolved.
|
||||
//
|
||||
// PromiseWindowProxy solves this dilemma for the non-window data
|
||||
// structure. It solves (1) by only keeping a weak reference to the
|
||||
// promise. It solves (2) by adding a strong reference to the promise
|
||||
// on the window itself. This ensures that as long as both the
|
||||
// PromiseWindowProxy and the window are still alive that the promise
|
||||
// will remain alive. This strong reference is cycle collected, so it
|
||||
// won't cause the window to leak.
|
||||
class PromiseWindowProxy final
|
||||
{
|
||||
public:
|
||||
PromiseWindowProxy(nsPIDOMWindowInner* aWindow, mozilla::dom::Promise* aPromise);
|
||||
~PromiseWindowProxy();
|
||||
|
||||
RefPtr<Promise> Get() const;
|
||||
nsCOMPtr<nsPIDOMWindowInner> GetWindow() const;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIWeakReference> mWindow;
|
||||
WeakPtr<Promise> mPromise;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PromiseWindowProxy_h
|
|
@ -11,14 +11,12 @@ EXPORTS.mozilla.dom += [
|
|||
'Promise.h',
|
||||
'PromiseDebugging.h',
|
||||
'PromiseNativeHandler.h',
|
||||
'PromiseWindowProxy.h',
|
||||
'PromiseWorkerProxy.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'Promise.cpp',
|
||||
'PromiseDebugging.cpp',
|
||||
'PromiseWindowProxy.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
#include "mozilla/dom/Navigator.h"
|
||||
#include "mozilla/dom/NotificationEvent.h"
|
||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||
#include "mozilla/dom/PromiseWindowProxy.h"
|
||||
#include "mozilla/dom/Request.h"
|
||||
#include "mozilla/dom/RootedDictionary.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
|
|
|
@ -105,7 +105,7 @@ CreateElementTransaction::DoTransaction()
|
|||
}
|
||||
|
||||
// Only set selection to insertion point if editor gives permission
|
||||
if (!mEditorBase->GetShouldTxnSetSelection()) {
|
||||
if (!mEditorBase->AllowsTransactionsToChangeSelection()) {
|
||||
// Do nothing - DOM range gravity will adjust selection
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ bool
|
|||
DeleteNodeTransaction::CanDoIt() const
|
||||
{
|
||||
if (NS_WARN_IF(!mNodeToDelete) || NS_WARN_IF(!mEditorBase) ||
|
||||
!mParentNode || !mEditorBase->IsModifiableNode(mParentNode)) {
|
||||
!mParentNode || !mEditorBase->IsModifiableNode(*mParentNode)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -90,20 +90,18 @@ DeleteRangeTransaction::DoTransaction()
|
|||
return rv;
|
||||
}
|
||||
|
||||
// only set selection to deletion point if editor gives permission
|
||||
bool bAdjustSelection;
|
||||
mEditorBase->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
if (bAdjustSelection) {
|
||||
RefPtr<Selection> selection = mEditorBase->GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
rv = selection->Collapse(startRef.AsRaw());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (!mEditorBase->AllowsTransactionsToChangeSelection()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<Selection> selection = mEditorBase->GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
rv = selection->Collapse(startRef.AsRaw());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
// else do nothing - dom range gravity will adjust selection
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ DeleteTextTransaction::CanDoIt() const
|
|||
if (NS_WARN_IF(!mCharData) || NS_WARN_IF(!mEditorBase)) {
|
||||
return false;
|
||||
}
|
||||
return mEditorBase->IsModifiableNode(mCharData);
|
||||
return mEditorBase->IsModifiableNode(*mCharData);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -137,19 +137,19 @@ DeleteTextTransaction::DoTransaction()
|
|||
mEditorBase->RangeUpdaterRef().
|
||||
SelAdjDeleteText(mCharData, mOffset, mLengthToDelete);
|
||||
|
||||
// Only set selection to deletion point if editor gives permission
|
||||
if (mEditorBase->GetShouldTxnSetSelection()) {
|
||||
RefPtr<Selection> selection = mEditorBase->GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
ErrorResult error;
|
||||
selection->Collapse(EditorRawDOMPoint(mCharData, mOffset), error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
if (!mEditorBase->AllowsTransactionsToChangeSelection()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<Selection> selection = mEditorBase->GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
ErrorResult error;
|
||||
selection->Collapse(EditorRawDOMPoint(mCharData, mOffset), error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
// Else do nothing - DOM Range gravity will adjust selection
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -163,7 +163,7 @@ EditorBase::EditorBase()
|
|||
, mDirection(eNone)
|
||||
, mDocDirtyState(-1)
|
||||
, mSpellcheckCheckboxState(eTriUnset)
|
||||
, mShouldTxnSetSelection(true)
|
||||
, mAllowsTransactionsToChangeSelection(true)
|
||||
, mDidPreDestroy(false)
|
||||
, mDidPostCreate(false)
|
||||
, mDispatchInputEvent(true)
|
||||
|
@ -982,18 +982,10 @@ EditorBase::EndPlaceholderTransaction()
|
|||
mPlaceholderBatch--;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
EditorBase::ShouldTxnSetSelection(bool* aResult)
|
||||
{
|
||||
NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER);
|
||||
*aResult = mShouldTxnSetSelection;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
EditorBase::SetShouldTxnSetSelection(bool aShould)
|
||||
{
|
||||
mShouldTxnSetSelection = aShould;
|
||||
MakeThisAllowTransactionsToChangeSelection(aShould);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1732,7 +1724,7 @@ EditorBase::ReplaceContainerWithTransactionInternal(
|
|||
AutoReplaceContainerSelNotify selStateNotify(mRangeUpdater, &aOldContainer,
|
||||
newContainer);
|
||||
{
|
||||
AutoTransactionsConserveSelection conserveSelection(this);
|
||||
AutoTransactionsConserveSelection conserveSelection(*this);
|
||||
// Move all children from the old container to the new container.
|
||||
while (aOldContainer.HasChildren()) {
|
||||
nsCOMPtr<nsIContent> child = aOldContainer.GetFirstChild();
|
||||
|
@ -1861,7 +1853,7 @@ EditorBase::InsertContainerWithTransactionInternal(
|
|||
}
|
||||
|
||||
{
|
||||
AutoTransactionsConserveSelection conserveSelection(this);
|
||||
AutoTransactionsConserveSelection conserveSelection(*this);
|
||||
rv = InsertNodeWithTransaction(aContent,
|
||||
EditorRawDOMPoint(newContainer, 0));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
@ -2661,9 +2653,10 @@ EditorBase::InsertTextWithTransaction(
|
|||
const EditorRawDOMPoint& aPointToInsert,
|
||||
EditorRawDOMPoint* aPointAfterInsertedString)
|
||||
{
|
||||
// NOTE: caller *must* have already used AutoTransactionsConserveSelection
|
||||
// stack-based class to turn off txn selection updating. Caller also turned
|
||||
// on rules sniffing if desired.
|
||||
MOZ_ASSERT(ShouldHandleIMEComposition() ||
|
||||
!AllowsTransactionsToChangeSelection(),
|
||||
"caller must have already used AutoTransactionsConserveSelection "
|
||||
"if this is not for updating composition string");
|
||||
|
||||
if (NS_WARN_IF(!aPointToInsert.IsSet())) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -3162,7 +3155,8 @@ EditorBase::DoSplitNode(const EditorDOMPoint& aStartOfRightNode,
|
|||
NS_WARNING_ASSERTION(!Destroyed(),
|
||||
"The editor is destroyed during splitting a node");
|
||||
|
||||
bool shouldSetSelection = GetShouldTxnSetSelection();
|
||||
bool allowedTransactionsToChangeSelection =
|
||||
AllowsTransactionsToChangeSelection();
|
||||
|
||||
RefPtr<Selection> previousSelection;
|
||||
for (size_t i = 0; i < savedRanges.Length(); ++i) {
|
||||
|
@ -3180,8 +3174,8 @@ EditorBase::DoSplitNode(const EditorDOMPoint& aStartOfRightNode,
|
|||
|
||||
// XXX Looks like that we don't need to modify normal selection here
|
||||
// because selection will be modified by the caller if
|
||||
// GetShouldTxnSetSelection() will return true.
|
||||
if (shouldSetSelection &&
|
||||
// AllowsTransactionsToChangeSelection() will return true.
|
||||
if (allowedTransactionsToChangeSelection &&
|
||||
range.mSelection->Type() == SelectionType::eNormal) {
|
||||
// If the editor should adjust the selection, don't bother restoring
|
||||
// the ranges for the normal selection here.
|
||||
|
@ -3320,7 +3314,8 @@ EditorBase::DoJoinNodes(nsINode* aNodeToKeep,
|
|||
ErrorResult err;
|
||||
aParent->RemoveChild(*aNodeToJoin, err);
|
||||
|
||||
bool shouldSetSelection = GetShouldTxnSetSelection();
|
||||
bool allowedTransactionsToChangeSelection =
|
||||
AllowsTransactionsToChangeSelection();
|
||||
|
||||
RefPtr<Selection> previousSelection;
|
||||
for (size_t i = 0; i < savedRanges.Length(); ++i) {
|
||||
|
@ -3337,7 +3332,7 @@ EditorBase::DoJoinNodes(nsINode* aNodeToKeep,
|
|||
previousSelection = range.mSelection;
|
||||
}
|
||||
|
||||
if (shouldSetSelection &&
|
||||
if (allowedTransactionsToChangeSelection &&
|
||||
range.mSelection->Type() == SelectionType::eNormal) {
|
||||
// If the editor should adjust the selection, don't bother restoring
|
||||
// the ranges for the normal selection here.
|
||||
|
@ -3372,10 +3367,12 @@ EditorBase::DoJoinNodes(nsINode* aNodeToKeep,
|
|||
}
|
||||
}
|
||||
|
||||
if (shouldSetSelection) {
|
||||
if (allowedTransactionsToChangeSelection) {
|
||||
// Editor wants us to set selection at join point.
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
selection->Collapse(aNodeToKeep, AssertedCast<int32_t>(firstNodeLength));
|
||||
}
|
||||
|
||||
|
@ -4162,12 +4159,6 @@ EditorBase::EndUpdateViewBatch()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
EditorBase::GetShouldTxnSetSelection()
|
||||
{
|
||||
return mShouldTxnSetSelection;
|
||||
}
|
||||
|
||||
TextComposition*
|
||||
EditorBase::GetComposition() const
|
||||
{
|
||||
|
@ -4963,9 +4954,9 @@ EditorBase::SetTextDirectionTo(TextDirection aTextDirection)
|
|||
}
|
||||
|
||||
bool
|
||||
EditorBase::IsModifiableNode(nsINode* aNode)
|
||||
EditorBase::IsModifiableNode(const nsINode& aNode) const
|
||||
{
|
||||
return true;
|
||||
return !AsHTMLEditor() || aNode.IsEditable();
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
|
|
|
@ -60,6 +60,7 @@ class CompositionTransaction;
|
|||
class CreateElementTransaction;
|
||||
class CSSEditUtils;
|
||||
class DeleteNodeTransaction;
|
||||
class DeleteRangeTransaction;
|
||||
class DeleteTextTransaction;
|
||||
class EditAggregateTransaction;
|
||||
class EditorEventListener;
|
||||
|
@ -1440,10 +1441,12 @@ protected: // May be called by friends.
|
|||
*/
|
||||
bool IsEditable(nsINode* aNode)
|
||||
{
|
||||
NS_ENSURE_TRUE(aNode, false);
|
||||
if (NS_WARN_IF(!aNode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aNode->IsContent() || IsMozEditorBogusNode(aNode) ||
|
||||
!IsModifiableNode(aNode)) {
|
||||
!IsModifiableNode(*aNode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1510,7 +1513,10 @@ protected: // May be called by friends.
|
|||
return aNode->NodeType() == nsINode::TEXT_NODE;
|
||||
}
|
||||
|
||||
virtual bool IsModifiableNode(nsINode* aNode);
|
||||
/**
|
||||
* IsModifiableNode() checks whether the node is editable or not.
|
||||
*/
|
||||
bool IsModifiableNode(const nsINode& aNode) const;
|
||||
|
||||
/**
|
||||
* GetNodeAtRangeOffsetPoint() returns the node at this position in a range,
|
||||
|
@ -1545,7 +1551,25 @@ protected: // May be called by friends.
|
|||
|
||||
static bool IsPreformatted(nsINode* aNode);
|
||||
|
||||
bool GetShouldTxnSetSelection();
|
||||
/**
|
||||
* AllowsTransactionsToChangeSelection() returns true if editor allows any
|
||||
* transactions to change Selection. Otherwise, transactions shouldn't
|
||||
* change Selection.
|
||||
*/
|
||||
inline bool AllowsTransactionsToChangeSelection() const
|
||||
{
|
||||
return mAllowsTransactionsToChangeSelection;
|
||||
}
|
||||
|
||||
/**
|
||||
* MakeThisAllowTransactionsToChangeSelection() with true makes this editor
|
||||
* allow transactions to change Selection. Otherwise, i.e., with false,
|
||||
* makes this editor not allow transactions to change Selection.
|
||||
*/
|
||||
inline void MakeThisAllowTransactionsToChangeSelection(bool aAllow)
|
||||
{
|
||||
mAllowsTransactionsToChangeSelection = aAllow;
|
||||
}
|
||||
|
||||
nsresult HandleInlineSpellCheck(EditSubAction aEditSubAction,
|
||||
Selection& aSelection,
|
||||
|
@ -1946,8 +1970,9 @@ protected:
|
|||
// A Tristate value.
|
||||
uint8_t mSpellcheckCheckboxState;
|
||||
|
||||
// Turn off for conservative selection adjustment by transactions.
|
||||
bool mShouldTxnSetSelection;
|
||||
// If false, transactions should not change Selection even after modifying
|
||||
// the DOM tree.
|
||||
bool mAllowsTransactionsToChangeSelection;
|
||||
// Whether PreDestroy has been called.
|
||||
bool mDidPreDestroy;
|
||||
// Whether PostCreate has been called.
|
||||
|
@ -1971,6 +1996,7 @@ protected:
|
|||
friend class CreateElementTransaction;
|
||||
friend class CSSEditUtils;
|
||||
friend class DeleteNodeTransaction;
|
||||
friend class DeleteRangeTransaction;
|
||||
friend class DeleteTextTransaction;
|
||||
friend class HTMLEditRules;
|
||||
friend class HTMLEditUtils;
|
||||
|
|
|
@ -572,28 +572,25 @@ protected:
|
|||
class MOZ_RAII AutoTransactionsConserveSelection final
|
||||
{
|
||||
public:
|
||||
explicit AutoTransactionsConserveSelection(EditorBase* aEditorBase
|
||||
explicit AutoTransactionsConserveSelection(EditorBase& aEditorBase
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mEditorBase(aEditorBase)
|
||||
, mOldState(true)
|
||||
, mAllowedTransactionsToChangeSelection(
|
||||
aEditorBase.AllowsTransactionsToChangeSelection())
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
if (mEditorBase) {
|
||||
mOldState = mEditorBase->GetShouldTxnSetSelection();
|
||||
mEditorBase->SetShouldTxnSetSelection(false);
|
||||
}
|
||||
mEditorBase.MakeThisAllowTransactionsToChangeSelection(false);
|
||||
}
|
||||
|
||||
~AutoTransactionsConserveSelection()
|
||||
{
|
||||
if (mEditorBase) {
|
||||
mEditorBase->SetShouldTxnSetSelection(mOldState);
|
||||
}
|
||||
mEditorBase.MakeThisAllowTransactionsToChangeSelection(
|
||||
mAllowedTransactionsToChangeSelection);
|
||||
}
|
||||
|
||||
protected:
|
||||
EditorBase* mEditorBase;
|
||||
bool mOldState;
|
||||
EditorBase& mEditorBase;
|
||||
bool mAllowedTransactionsToChangeSelection;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
|
|
|
@ -378,7 +378,7 @@ HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection)
|
|||
nsIContent* hostContent = GetActiveEditingHost();
|
||||
|
||||
if (mIsObjectResizingEnabled && focusElement &&
|
||||
IsModifiableNode(focusElement) && focusElement != hostContent) {
|
||||
IsModifiableNode(*focusElement) && focusElement != hostContent) {
|
||||
if (nsGkAtoms::img == focusTagAtom) {
|
||||
mResizedObjectIsAnImage = true;
|
||||
}
|
||||
|
@ -396,7 +396,7 @@ HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection)
|
|||
}
|
||||
|
||||
if (mIsAbsolutelyPositioningEnabled && absPosElement &&
|
||||
IsModifiableNode(absPosElement) && absPosElement != hostContent) {
|
||||
IsModifiableNode(*absPosElement) && absPosElement != hostContent) {
|
||||
if (mAbsolutelyPositionedObject) {
|
||||
nsresult rv = RefreshGrabber();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
@ -411,7 +411,7 @@ HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection)
|
|||
}
|
||||
|
||||
if (mIsInlineTableEditingEnabled && cellElement &&
|
||||
IsModifiableNode(cellElement) && cellElement != hostContent) {
|
||||
IsModifiableNode(*cellElement) && cellElement != hostContent) {
|
||||
if (mInlineEditedCell) {
|
||||
nsresult rv = RefreshInlineTableEditingUI();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
|
|
@ -491,7 +491,7 @@ HTMLEditRules::AfterEditInner(EditSubAction aEditSubAction,
|
|||
(aEditSubAction == EditSubAction::eRedo))) {
|
||||
// don't let any txns in here move the selection around behind our back.
|
||||
// Note that this won't prevent explicit selection setting from working.
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(HTMLEditorRef());
|
||||
|
||||
// expand the "changed doc range" as needed
|
||||
PromoteRange(*mDocChangeRange, aEditSubAction);
|
||||
|
@ -660,22 +660,31 @@ HTMLEditRules::WillDoAction(Selection* aSelection,
|
|||
|
||||
RefPtr<nsRange> range = SelectionRef().GetRangeAt(0);
|
||||
nsCOMPtr<nsINode> selStartNode = range->GetStartContainer();
|
||||
if (NS_WARN_IF(!selStartNode)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!HTMLEditorRef().IsModifiableNode(selStartNode)) {
|
||||
if (!HTMLEditorRef().IsModifiableNode(*selStartNode)) {
|
||||
*aCancel = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> selEndNode = range->GetEndContainer();
|
||||
if (NS_WARN_IF(!selEndNode)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (selStartNode != selEndNode) {
|
||||
if (!HTMLEditorRef().IsModifiableNode(selEndNode)) {
|
||||
if (!HTMLEditorRef().IsModifiableNode(*selEndNode)) {
|
||||
*aCancel = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
if (!HTMLEditorRef().IsModifiableNode(range->GetCommonAncestor())) {
|
||||
nsINode* commonAncestor = range->GetCommonAncestor();
|
||||
if (NS_WARN_IF(!commonAncestor)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!HTMLEditorRef().IsModifiableNode(*commonAncestor)) {
|
||||
*aCancel = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1449,7 +1458,7 @@ HTMLEditRules::WillInsertText(EditSubAction aEditSubAction,
|
|||
AutoLockListener lockit(&mListenerEnabled);
|
||||
|
||||
// don't change my selection in subtransactions
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(HTMLEditorRef());
|
||||
nsAutoString tString(*inString);
|
||||
const char16_t *unicodeBuf = tString.get();
|
||||
int32_t pos = 0;
|
||||
|
@ -1749,7 +1758,7 @@ HTMLEditRules::WillInsertBreak(bool* aCancel,
|
|||
MOZ_ASSERT(atStartOfSelection.IsSetAndValid());
|
||||
|
||||
// Do nothing if the node is read-only
|
||||
if (!HTMLEditorRef().IsModifiableNode(atStartOfSelection.GetContainer())) {
|
||||
if (!HTMLEditorRef().IsModifiableNode(*atStartOfSelection.GetContainer())) {
|
||||
*aCancel = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2967,7 +2976,7 @@ HTMLEditRules::WillDeleteSelection(nsIEditor::EDirection aAction,
|
|||
// Figure out if the endpoints are in nodes that can be merged. Adjust
|
||||
// surrounding whitespace in preparation to delete selection.
|
||||
if (!IsPlaintextEditor()) {
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(HTMLEditorRef());
|
||||
rv = WSRunObject::PrepareToDeleteRange(&HTMLEditorRef(),
|
||||
address_of(startNode), &startOffset,
|
||||
address_of(endNode), &endOffset);
|
||||
|
@ -3383,7 +3392,7 @@ HTMLEditRules::TryToJoinBlocksWithTransaction(nsIContent& aLeftNode,
|
|||
}
|
||||
}
|
||||
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(HTMLEditorRef());
|
||||
|
||||
// offset below is where you find yourself in rightBlock when you traverse
|
||||
// upwards from leftBlock
|
||||
|
@ -4506,7 +4515,7 @@ HTMLEditRules::MakeBasicBlock(nsAtom& blockType)
|
|||
}
|
||||
|
||||
AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(HTMLEditorRef());
|
||||
|
||||
// Contruct a list of nodes to act on.
|
||||
nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
|
||||
|
@ -5921,7 +5930,7 @@ HTMLEditRules::CreateStyleForInsertText(nsIDocument& aDocument)
|
|||
|
||||
{
|
||||
// Transactions may set selection, but we will set selection if necessary.
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(HTMLEditorRef());
|
||||
|
||||
while (item && node != rootElement) {
|
||||
// XXX If we redesign ClearStyle(), we can use EditorDOMPoint in this
|
||||
|
@ -7548,7 +7557,7 @@ HTMLEditRules::GetListActionNodes(
|
|||
|
||||
{
|
||||
// We don't like other people messing with our selection!
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(HTMLEditorRef());
|
||||
|
||||
// contruct a list of nodes to act on.
|
||||
nsresult rv = GetNodesFromSelection(EditSubAction::eCreateOrChangeList,
|
||||
|
|
|
@ -3190,7 +3190,7 @@ HTMLEditor::DeleteNodeWithTransaction(nsINode& aNode)
|
|||
// Do nothing if the node is read-only.
|
||||
// XXX This is not a override method of EditorBase's method. This might
|
||||
// cause not called accidentally. We need to investigate this issue.
|
||||
if (NS_WARN_IF(!IsModifiableNode(aNode.AsContent()) &&
|
||||
if (NS_WARN_IF(!IsModifiableNode(*aNode.AsContent()) &&
|
||||
!IsMozEditorBogusNode(aNode.AsContent()))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -3220,7 +3220,7 @@ HTMLEditor::DeleteTextWithTransaction(CharacterData& aCharData,
|
|||
uint32_t aLength)
|
||||
{
|
||||
// Do nothing if the node is read-only
|
||||
if (!IsModifiableNode(&aCharData)) {
|
||||
if (!IsModifiableNode(aCharData)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -3239,7 +3239,7 @@ HTMLEditor::InsertTextWithTransaction(
|
|||
}
|
||||
|
||||
// Do nothing if the node is read-only
|
||||
if (!IsModifiableNode(aPointToInsert.GetContainer())) {
|
||||
if (!IsModifiableNode(*aPointToInsert.GetContainer())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -3358,12 +3358,6 @@ HTMLEditor::ContentRemoved(nsIContent* aChild,
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLEditor::IsModifiableNode(nsINode* aNode)
|
||||
{
|
||||
return !aNode || aNode->IsEditable();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLEditor::DebugUnitTests(int32_t* outNumTests,
|
||||
int32_t* outNumTestsFailed)
|
||||
|
@ -3612,7 +3606,7 @@ nsresult
|
|||
HTMLEditor::CollapseAdjacentTextNodes(nsRange* aInRange)
|
||||
{
|
||||
NS_ENSURE_TRUE(aInRange, NS_ERROR_NULL_POINTER);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
nsTArray<nsCOMPtr<nsINode>> textNodes;
|
||||
// we can't actually do anything during iteration, so store the text nodes in an array
|
||||
// don't bother ref counting them because we know we can hold them for the
|
||||
|
@ -4276,7 +4270,7 @@ HTMLEditor::SetCSSBackgroundColorWithTransaction(const nsAString& aColor)
|
|||
*this, EditSubAction::eInsertElement,
|
||||
nsIEditor::eNext);
|
||||
AutoSelectionRestorer selectionRestorer(selection, this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
// XXX Although, this method may set background color of ancestor block
|
||||
// element, using EditSubAction::eSetTextProperty.
|
||||
|
|
|
@ -447,8 +447,6 @@ protected: // May be called by friends.
|
|||
nsresult RelativeChangeElementZIndex(Element& aElement, int32_t aChange,
|
||||
int32_t* aReturn);
|
||||
|
||||
virtual bool IsModifiableNode(nsINode* aNode) override;
|
||||
|
||||
virtual bool IsBlockNode(nsINode *aNode) override;
|
||||
using EditorBase::IsBlockNode;
|
||||
|
||||
|
|
|
@ -1111,7 +1111,7 @@ HTMLEditor::InsertFromTransferable(nsITransferable* transferable,
|
|||
transferable->GetAnyTransferData(bestFlavor,
|
||||
getter_AddRefs(genericDataObj),
|
||||
&len))) {
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
nsAutoString flavor;
|
||||
CopyASCIItoUTF16(bestFlavor, flavor);
|
||||
nsAutoString stuffToPaste;
|
||||
|
|
|
@ -89,7 +89,7 @@ HTMLEditor::SetInlineProperty(nsAtom* aProperty,
|
|||
*this, EditSubAction::eInsertElement,
|
||||
nsIEditor::eNext);
|
||||
AutoSelectionRestorer selectionRestorer(selection, this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
bool cancel, handled;
|
||||
EditSubActionInfo subActionInfo(EditSubAction::eSetTextProperty);
|
||||
|
@ -1244,7 +1244,7 @@ HTMLEditor::RemoveInlineProperty(nsAtom* aProperty,
|
|||
*this, EditSubAction::eRemoveTextProperty,
|
||||
nsIEditor::eNext);
|
||||
AutoSelectionRestorer selectionRestorer(selection, this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
bool cancel, handled;
|
||||
EditSubActionInfo subActionInfo(EditSubAction::eRemoveTextProperty);
|
||||
|
@ -1405,7 +1405,7 @@ HTMLEditor::RelativeFontChange(FontSize aDir)
|
|||
*this, EditSubAction::eSetTextProperty,
|
||||
nsIEditor::eNext);
|
||||
AutoSelectionRestorer selectionRestorer(selection, this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
// Loop through the ranges in the selection
|
||||
AutoRangeArray arrayOfRanges(selection);
|
||||
|
|
|
@ -139,7 +139,7 @@ HTMLEditor::InsertCell(Element* aCell,
|
|||
}
|
||||
|
||||
// Don't let Rules System change the selection.
|
||||
AutoTransactionsConserveSelection dontChangeSelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeSelection(*this);
|
||||
return InsertNodeWithTransaction(*newCell, pointToInsert);
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,7 @@ HTMLEditor::InsertTableCell(int32_t aNumber,
|
|||
newCellIndex, ePreviousColumn,
|
||||
false);
|
||||
//...so suppress Rules System selection munging
|
||||
AutoTransactionsConserveSelection dontChangeSelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeSelection(*this);
|
||||
|
||||
for (int32_t i = 0; i < aNumber; i++) {
|
||||
RefPtr<Element> newCell;
|
||||
|
@ -400,7 +400,7 @@ HTMLEditor::InsertTableColumn(int32_t aNumber,
|
|||
startColIndex, ePreviousRow,
|
||||
false);
|
||||
//.. so suppress Rules System selection munging
|
||||
AutoTransactionsConserveSelection dontChangeSelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeSelection(*this);
|
||||
|
||||
// If we are inserting after all existing columns
|
||||
// Make sure table is "well formed"
|
||||
|
@ -532,7 +532,7 @@ HTMLEditor::InsertTableRow(int32_t aNumber,
|
|||
startColIndex, ePreviousColumn,
|
||||
false);
|
||||
//...so suppress Rules System selection munging
|
||||
AutoTransactionsConserveSelection dontChangeSelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeSelection(*this);
|
||||
|
||||
RefPtr<Element> cellForRowParent;
|
||||
int32_t cellsInRow = 0;
|
||||
|
@ -749,7 +749,7 @@ HTMLEditor::DeleteTableCell(int32_t aNumber)
|
|||
AutoSelectionSetterAfterTableEdit setCaret(*this, table, startRowIndex,
|
||||
startColIndex, ePreviousColumn,
|
||||
false);
|
||||
AutoTransactionsConserveSelection dontChangeSelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeSelection(*this);
|
||||
|
||||
bool checkToDeleteRow = true;
|
||||
bool checkToDeleteColumn = true;
|
||||
|
@ -878,7 +878,7 @@ HTMLEditor::DeleteTableCell(int32_t aNumber)
|
|||
AutoSelectionSetterAfterTableEdit setCaret(*this, table, startRowIndex,
|
||||
startColIndex, ePreviousColumn,
|
||||
false);
|
||||
AutoTransactionsConserveSelection dontChangeSelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeSelection(*this);
|
||||
rv = DeleteNodeWithTransaction(*cell);
|
||||
// If we fail, don't try to delete any more cells???
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
@ -913,7 +913,7 @@ HTMLEditor::DeleteTableCellContents()
|
|||
*this, EditSubAction::eDeleteNode,
|
||||
nsIEditor::eNext);
|
||||
//Don't let Rules System change the selection
|
||||
AutoTransactionsConserveSelection dontChangeSelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeSelection(*this);
|
||||
|
||||
|
||||
RefPtr<Element> firstCell;
|
||||
|
@ -1177,7 +1177,7 @@ HTMLEditor::DeleteTableRow(int32_t aNumber)
|
|||
startColIndex, ePreviousRow,
|
||||
false);
|
||||
// Don't change selection during deletions
|
||||
AutoTransactionsConserveSelection dontChangeSelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeSelection(*this);
|
||||
|
||||
if (firstCell && rangeCount > 1) {
|
||||
// Use selected cells to determine what rows to delete
|
||||
|
@ -1688,7 +1688,7 @@ HTMLEditor::SplitTableCell()
|
|||
startColIndex, ePreviousColumn,
|
||||
false);
|
||||
//...so suppress Rules System selection munging
|
||||
AutoTransactionsConserveSelection dontChangeSelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeSelection(*this);
|
||||
|
||||
RefPtr<Element> newCell;
|
||||
int32_t rowIndex = startRowIndex;
|
||||
|
@ -1973,7 +1973,7 @@ HTMLEditor::JoinTableCells(bool aMergeNonContiguousContents)
|
|||
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
//Don't let Rules System change the selection
|
||||
AutoTransactionsConserveSelection dontChangeSelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeSelection(*this);
|
||||
|
||||
// Note: We dont' use AutoSelectionSetterAfterTableEdit here so the selection
|
||||
// is retained after joining. This leaves the target cell selected
|
||||
|
|
|
@ -113,21 +113,23 @@ InsertNodeTransaction::DoTransaction()
|
|||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
// Only set selection to insertion point if editor gives permission
|
||||
if (mEditorBase->GetShouldTxnSetSelection()) {
|
||||
RefPtr<Selection> selection = mEditorBase->GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Place the selection just after the inserted element
|
||||
EditorRawDOMPoint afterInsertedNode(mContentToInsert);
|
||||
DebugOnly<bool> advanced = afterInsertedNode.AdvanceOffset();
|
||||
NS_WARNING_ASSERTION(advanced,
|
||||
"Failed to advance offset after the inserted node");
|
||||
selection->Collapse(afterInsertedNode, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
error.SuppressException();
|
||||
}
|
||||
if (!mEditorBase->AllowsTransactionsToChangeSelection()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<Selection> selection = mEditorBase->GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Place the selection just after the inserted element.
|
||||
EditorRawDOMPoint afterInsertedNode(mContentToInsert);
|
||||
DebugOnly<bool> advanced = afterInsertedNode.AdvanceOffset();
|
||||
NS_WARNING_ASSERTION(advanced,
|
||||
"Failed to advance offset after the inserted node");
|
||||
selection->Collapse(afterInsertedNode, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
error.SuppressException();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ InsertTextTransaction::DoTransaction()
|
|||
}
|
||||
|
||||
// Only set selection to insertion point if editor gives permission
|
||||
if (mEditorBase->GetShouldTxnSetSelection()) {
|
||||
if (mEditorBase->AllowsTransactionsToChangeSelection()) {
|
||||
RefPtr<Selection> selection = mEditorBase->GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -82,6 +82,8 @@ InsertTextTransaction::DoTransaction()
|
|||
} else {
|
||||
// Do nothing - DOM Range gravity will adjust selection
|
||||
}
|
||||
// XXX Other transactions do not do this but its callers do.
|
||||
// Why do this transaction do this by itself?
|
||||
mEditorBase->RangeUpdaterRef().
|
||||
SelAdjInsertText(*mTextNode, mOffset, mStringToInsert);
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "nsDebug.h" // for NS_ASSERTION, etc.
|
||||
#include "nsError.h" // for NS_ERROR_NULL_POINTER, etc.
|
||||
#include "nsIContent.h" // for nsIContent
|
||||
#include "nsIEditor.h" // for EditorBase::IsModifiableNode
|
||||
#include "nsISupportsImpl.h" // for QueryInterface, etc.
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -60,7 +59,7 @@ JoinNodeTransaction::CanDoIt() const
|
|||
!mLeftNode->GetParentNode()) {
|
||||
return false;
|
||||
}
|
||||
return mEditorBase->IsModifiableNode(mLeftNode->GetParentNode());
|
||||
return mEditorBase->IsModifiableNode(*mLeftNode->GetParentNode());
|
||||
}
|
||||
|
||||
// After DoTransaction() and RedoTransaction(), the left node is removed from
|
||||
|
|
|
@ -96,27 +96,32 @@ SplitNodeTransaction::DoTransaction()
|
|||
// Insert the new node
|
||||
mEditorBase->DoSplitNode(EditorDOMPoint(mStartOfRightNode),
|
||||
*mNewLeftNode, error);
|
||||
|
||||
if (!mEditorBase->AllowsTransactionsToChangeSelection()) {
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX Really odd. The result of DoSplitNode() is respected only when
|
||||
// we shouldn't set selection. Otherwise, it's overridden by the
|
||||
// result of Selection.Collapse().
|
||||
if (mEditorBase->GetShouldTxnSetSelection()) {
|
||||
NS_WARNING_ASSERTION(!mEditorBase->Destroyed(),
|
||||
"The editor has gone but SplitNodeTransaction keeps trying to modify "
|
||||
"Selection");
|
||||
RefPtr<Selection> selection = mEditorBase->GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
// XXX This must be a bug.
|
||||
error.SuppressException();
|
||||
}
|
||||
MOZ_ASSERT(mStartOfRightNode.Offset() == mNewLeftNode->Length());
|
||||
EditorRawDOMPoint atEndOfLeftNode;
|
||||
atEndOfLeftNode.SetToEndOf(mNewLeftNode);
|
||||
selection->Collapse(atEndOfLeftNode, error);
|
||||
NS_WARNING_ASSERTION(!mEditorBase->Destroyed(),
|
||||
"The editor has gone but SplitNodeTransaction keeps trying to modify "
|
||||
"Selection");
|
||||
RefPtr<Selection> selection = mEditorBase->GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
// XXX This must be a bug.
|
||||
error.SuppressException();
|
||||
}
|
||||
MOZ_ASSERT(mStartOfRightNode.Offset() == mNewLeftNode->Length());
|
||||
EditorRawDOMPoint atEndOfLeftNode;
|
||||
atEndOfLeftNode.SetToEndOf(mNewLeftNode);
|
||||
selection->Collapse(atEndOfLeftNode, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
|
|
@ -378,7 +378,7 @@ TextEditRules::DidDoAction(Selection* aSelection,
|
|||
|
||||
// don't let any txns in here move the selection around behind our back.
|
||||
// Note that this won't prevent explicit selection setting from working.
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(&TextEditorRef());
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(TextEditorRef());
|
||||
|
||||
switch (aInfo.mEditSubAction) {
|
||||
case EditSubAction::eDeleteSelectedContent:
|
||||
|
@ -849,7 +849,7 @@ TextEditRules::WillInsertText(EditSubAction aEditSubAction,
|
|||
// aEditSubAction == EditSubAction::eInsertText
|
||||
|
||||
// don't change my selection in subtransactions
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(&TextEditorRef());
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(TextEditorRef());
|
||||
|
||||
EditorRawDOMPoint pointAfterStringInserted;
|
||||
rv = TextEditorRef().InsertTextWithTransaction(*doc, *outString,
|
||||
|
@ -1477,7 +1477,7 @@ TextEditRules::CreateTrailingBRIfNeeded()
|
|||
}
|
||||
|
||||
if (!lastChild->IsHTMLElement(nsGkAtoms::br)) {
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(&TextEditorRef());
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(TextEditorRef());
|
||||
EditorRawDOMPoint endOfRoot;
|
||||
endOfRoot.SetToEndOf(rootElement);
|
||||
CreateElementResult createMozBrResult = CreateMozBR(endOfRoot);
|
||||
|
@ -1545,7 +1545,7 @@ TextEditRules::CreateBogusNodeIfNeeded()
|
|||
}
|
||||
|
||||
// Skip adding the bogus node if body is read-only.
|
||||
if (!TextEditorRef().IsModifiableNode(rootElement)) {
|
||||
if (!TextEditorRef().IsModifiableNode(*rootElement)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1095,7 +1095,7 @@ TextEditor::InsertParagraphSeparatorAsAction()
|
|||
}
|
||||
|
||||
// don't change my selection in subtransactions
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
// insert a linefeed character
|
||||
EditorRawDOMPoint pointAfterInsertedLineBreak;
|
||||
|
|
|
@ -115,7 +115,7 @@ TextEditor::InsertTextFromTransferable(nsITransferable* aTransferable)
|
|||
&len)) &&
|
||||
(bestFlavor.EqualsLiteral(kUnicodeMime) ||
|
||||
bestFlavor.EqualsLiteral(kMozTextInternal))) {
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(this);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
nsCOMPtr<nsISupportsString> textDataObj ( do_QueryInterface(genericDataObj) );
|
||||
if (textDataObj && len > 0) {
|
||||
nsAutoString stuffToPaste;
|
||||
|
|
|
@ -1547,12 +1547,17 @@ WSRunObject::InsertNBSPAndRemoveFollowingASCIIWhitespaces(WSPoint aPoint)
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
// First, insert an NBSP.
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(mHTMLEditor);
|
||||
if (NS_WARN_IF(!mHTMLEditor)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
|
||||
|
||||
// First, insert an NBSP.
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
|
||||
nsresult rv =
|
||||
mHTMLEditor->InsertTextIntoTextNodeWithTransaction(
|
||||
nsDependentSubstring(&kNBSP, 1),
|
||||
*aPoint.mTextNode, aPoint.mOffset, true);
|
||||
htmlEditor->InsertTextIntoTextNodeWithTransaction(
|
||||
nsDependentSubstring(&kNBSP, 1),
|
||||
*aPoint.mTextNode, aPoint.mOffset, true);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1891,14 +1896,16 @@ WSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun)
|
|||
}
|
||||
if (leftCheck && rightCheck) {
|
||||
// Now replace nbsp with space. First, insert a space
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(htmlEditor);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
|
||||
nsAutoString spaceStr(char16_t(32));
|
||||
nsresult rv =
|
||||
htmlEditor->InsertTextIntoTextNodeWithTransaction(spaceStr,
|
||||
*thePoint.mTextNode,
|
||||
thePoint.mOffset,
|
||||
true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Finally, delete that nbsp
|
||||
rv = DeleteRange(EditorRawDOMPoint(thePoint.mTextNode,
|
||||
|
@ -1933,12 +1940,14 @@ WSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun)
|
|||
}
|
||||
|
||||
// Finally, insert that nbsp before the ASCII ws run
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(htmlEditor);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
|
||||
rv =
|
||||
htmlEditor->InsertTextIntoTextNodeWithTransaction(
|
||||
nsDependentSubstring(&kNBSP, 1),
|
||||
*startNode, startOffset, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -1985,13 +1994,18 @@ WSRunObject::ReplacePreviousNBSPIfUnncessary(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!mHTMLEditor)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
|
||||
|
||||
// First, insert a space before the previous NBSP.
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(mHTMLEditor);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
|
||||
nsAutoString spaceStr(char16_t(32));
|
||||
nsresult rv =
|
||||
mHTMLEditor->InsertTextIntoTextNodeWithTransaction(spaceStr,
|
||||
*thePoint.mTextNode,
|
||||
thePoint.mOffset, true);
|
||||
htmlEditor->InsertTextIntoTextNodeWithTransaction(spaceStr,
|
||||
*thePoint.mTextNode,
|
||||
thePoint.mOffset, true);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -2034,15 +2048,22 @@ WSRunObject::CheckLeadingNBSP(WSFragment* aRun,
|
|||
}
|
||||
}
|
||||
if (canConvert) {
|
||||
if (NS_WARN_IF(!mHTMLEditor)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
|
||||
|
||||
// First, insert a space
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(mHTMLEditor);
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
|
||||
nsAutoString spaceStr(char16_t(32));
|
||||
nsresult rv =
|
||||
mHTMLEditor->InsertTextIntoTextNodeWithTransaction(spaceStr,
|
||||
*thePoint.mTextNode,
|
||||
thePoint.mOffset,
|
||||
true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
htmlEditor->InsertTextIntoTextNodeWithTransaction(spaceStr,
|
||||
*thePoint.mTextNode,
|
||||
thePoint.mOffset,
|
||||
true);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Finally, delete that nbsp
|
||||
rv = DeleteRange(EditorRawDOMPoint(thePoint.mTextNode,
|
||||
|
|
|
@ -216,16 +216,23 @@ interface nsIEditor : nsISupports
|
|||
*/
|
||||
void endTransaction();
|
||||
|
||||
boolean shouldTxnSetSelection();
|
||||
|
||||
/** Set the flag that prevents insertElementTxn from changing the selection
|
||||
* @param should Set false to suppress changing the selection;
|
||||
* i.e., before using InsertElement() to insert
|
||||
* under <head> element
|
||||
* WARNING: You must be very careful to reset back to PR_TRUE after
|
||||
* setting PR_FALSE, else selection/caret is trashed
|
||||
* for further editing.
|
||||
*/
|
||||
/**
|
||||
* While setting the flag with this method to false, CreateElementTransaction,
|
||||
* DeleteRangeTransaction, DeleteTextTransaction, InsertNodeTransaction,
|
||||
* InsertTextTransaction and SplitNodeTransaction won't change Selection
|
||||
* after modifying the DOM tree.
|
||||
* Note that calling this with false does not guarantee that Selection won't
|
||||
* be changed because other transaction may ignore this flag, editor itself
|
||||
* may change selection, and current selection may become invalid after
|
||||
* changing the DOM tree, etc.
|
||||
* After calling this method with true, the caller should guarantee that
|
||||
* Selection should be positioned where user expects.
|
||||
*
|
||||
* @param should false if you don't want above transactions to modify
|
||||
* Selection automatically after modifying the DOM tree.
|
||||
* Note that calling this with false does not guarantee
|
||||
* that Selection is never changed.
|
||||
*/
|
||||
void setShouldTxnSetSelection(in boolean should);
|
||||
|
||||
/* ------------ Inline Spell Checking methods -------------- */
|
||||
|
|
|
@ -1358,6 +1358,15 @@ ScrollFrameHelper::WantAsyncScroll() const
|
|||
ScrollStyles styles = GetScrollStylesFromFrame();
|
||||
nscoord oneDevPixel = GetScrolledFrame()->PresContext()->AppUnitsPerDevPixel();
|
||||
nsRect scrollRange = GetScrollRange();
|
||||
|
||||
// If the page has a visual viewport size that's different from
|
||||
// the layout viewport size at the current zoom level, we need to be
|
||||
// able to scroll the visual viewport inside the layout viewport
|
||||
// even if the page is not zoomable.
|
||||
if (!GetScrollRangeForClamping().IsEqualInterior(scrollRange)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isVScrollable = (scrollRange.height >= oneDevPixel) &&
|
||||
(styles.mVertical != NS_STYLE_OVERFLOW_HIDDEN);
|
||||
bool isHScrollable = (scrollRange.width >= oneDevPixel) &&
|
||||
|
|
|
@ -8558,6 +8558,7 @@ nsTextFrame::AddInlineMinISizeForFlow(gfxContext *aRenderingContext,
|
|||
aData->mCurrentLine +=
|
||||
textRun->GetMinAdvanceWidth(Range(start, flowEndInTextRun));
|
||||
aData->mTrailingWhitespace = 0;
|
||||
aData->mAtStartOfLine = false;
|
||||
aData->OptionallyBreak();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3254,7 +3254,7 @@ pref("dom.ipc.processCount.privileged", 1);
|
|||
pref("dom.ipc.keepProcessesAlive.privileged", 1);
|
||||
|
||||
// Whether a native event loop should be used in the content process.
|
||||
#if defined(XP_WIN)
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
pref("dom.ipc.useNativeEventProcessing.content", false);
|
||||
#else
|
||||
pref("dom.ipc.useNativeEventProcessing.content", true);
|
||||
|
@ -4989,7 +4989,11 @@ pref("extensions.webextensions.tabhide.enabled", true);
|
|||
pref("extensions.webextensions.background-delayed-startup", false);
|
||||
|
||||
// Whether or not the installed extensions should be migrated to the storage.local IndexedDB backend.
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("extensions.webextensions.ExtensionStorageIDB.enabled", true);
|
||||
#else
|
||||
pref("extensions.webextensions.ExtensionStorageIDB.enabled", false);
|
||||
#endif
|
||||
|
||||
// if enabled, store execution times for API calls
|
||||
pref("extensions.webextensions.enablePerformanceCounters", false);
|
||||
|
|
|
@ -29,6 +29,13 @@ bench-ares6:
|
|||
run:
|
||||
mach: jsshell-bench --binary $JSSHELL --perfherder ares6
|
||||
|
||||
bench-asmjsapps:
|
||||
description: asm.js Apps shell benchmark suite
|
||||
treeherder:
|
||||
symbol: js-bench(asm.js-apps)
|
||||
run:
|
||||
mach: jsshell-bench --binary $JSSHELL --perfherder asmjs-apps
|
||||
|
||||
bench-sixspeed:
|
||||
description: Six-Speed JavaScript shell benchmark suite
|
||||
treeherder:
|
||||
|
@ -36,9 +43,9 @@ bench-sixspeed:
|
|||
run:
|
||||
mach: jsshell-bench --binary $JSSHELL --perfherder six-speed
|
||||
|
||||
bench-asmjsapps:
|
||||
description: asm.js Apps shell benchmark suite
|
||||
bench-sunspider:
|
||||
description: SunSpider JavaScript shell benchmark suite
|
||||
treeherder:
|
||||
symbol: js-bench(asm.js-apps)
|
||||
symbol: js-bench(sunspider)
|
||||
run:
|
||||
mach: jsshell-bench --binary $JSSHELL --perfherder asmjs-apps
|
||||
mach: jsshell-bench --binary $JSSHELL --perfherder sunspider
|
||||
|
|
|
@ -101,6 +101,19 @@ class Benchmark(object):
|
|||
return proc.wait()
|
||||
|
||||
|
||||
class RunOnceBenchmark(Benchmark):
|
||||
def collect_results(self):
|
||||
bench_total = 0
|
||||
# NOTE: for this benchmark we run the test once, so we have a single value array
|
||||
for bench, scores in self.scores.items():
|
||||
for score, values in scores.items():
|
||||
test_name = "{}-{}".format(self.name, score)
|
||||
total = sum(values) / len(values)
|
||||
self.suite['subtests'].append({'name': test_name, 'value': total})
|
||||
bench_total += int(sum(values))
|
||||
self.suite['value'] = bench_total
|
||||
|
||||
|
||||
class Ares6(Benchmark):
|
||||
name = 'ares6'
|
||||
path = os.path.join('third_party', 'webkit', 'PerformanceTests', 'ARES-6')
|
||||
|
@ -159,7 +172,51 @@ class Ares6(Benchmark):
|
|||
self.suite['value'] = self.last_summary
|
||||
|
||||
|
||||
class SixSpeed(Benchmark):
|
||||
class AsmJSApps(RunOnceBenchmark):
|
||||
name = 'asmjsapps'
|
||||
path = os.path.join('third_party', 'webkit', 'PerformanceTests', 'asmjs-apps')
|
||||
units = 'ms'
|
||||
|
||||
@property
|
||||
def command(self):
|
||||
if not self.args:
|
||||
self.args = []
|
||||
full_args = ['bash', 'harness.sh', self.shell + " " + " ".join(self.args)]
|
||||
return full_args
|
||||
|
||||
def reset(self):
|
||||
super(AsmJSApps, self).reset()
|
||||
|
||||
# Scores are of the form:
|
||||
# {<bench_name>: {<score_name>: [<values>]}}
|
||||
self.scores = defaultdict(lambda: defaultdict(list))
|
||||
|
||||
def process_results(self, output):
|
||||
total = 0.0
|
||||
tests = []
|
||||
for line in output.splitlines():
|
||||
m = re.search("(.+) - (\d+(\.\d+)?)", line)
|
||||
if not m:
|
||||
continue
|
||||
name = m.group(1)
|
||||
score = m.group(2)
|
||||
total += float(score)
|
||||
tests.append({ 'name': name, 'time': score })
|
||||
tests.append({ 'name': '__total__', 'time': total })
|
||||
return tests
|
||||
|
||||
def process_line(self, output):
|
||||
m = re.search("(.+) - (\d+(\.\d+)?)", output)
|
||||
if not m:
|
||||
return
|
||||
subtest = m.group(1)
|
||||
score = m.group(2)
|
||||
if subtest not in self.scores[self.name]:
|
||||
self.scores[self.name][subtest] = []
|
||||
self.scores[self.name][subtest].append(int(score))
|
||||
|
||||
|
||||
class SixSpeed(RunOnceBenchmark):
|
||||
name = 'six-speed'
|
||||
path = os.path.join('third_party', 'webkit', 'PerformanceTests', 'six-speed')
|
||||
units = 'ms'
|
||||
|
@ -176,89 +233,50 @@ class SixSpeed(Benchmark):
|
|||
# {<bench_name>: {<score_name>: [<values>]}}
|
||||
self.scores = defaultdict(lambda: defaultdict(list))
|
||||
|
||||
def process_line(self, output):
|
||||
m = re.search("(.+): (\d+)", output)
|
||||
if not m:
|
||||
return
|
||||
subtest = m.group(1)
|
||||
score = m.group(2)
|
||||
if subtest not in self.scores[self.name]:
|
||||
self.scores[self.name][subtest] = []
|
||||
self.scores[self.name][subtest].append(int(score))
|
||||
def process_line(self, output):
|
||||
m = re.search("(.+): (\d+)", output)
|
||||
if not m:
|
||||
return
|
||||
subtest = m.group(1)
|
||||
score = m.group(2)
|
||||
if subtest not in self.scores[self.name]:
|
||||
self.scores[self.name][subtest] = []
|
||||
self.scores[self.name][subtest].append(int(score))
|
||||
|
||||
|
||||
def collect_results(self):
|
||||
bench_total = 0
|
||||
# NOTE: for this benchmark we run the test once, so we have a single value array
|
||||
for bench, scores in self.scores.items():
|
||||
for score, values in scores.items():
|
||||
test_name = "{}-{}".format(self.name, score)
|
||||
total = sum(values) / len(values)
|
||||
self.suite['subtests'].append({'name': test_name, 'value': total})
|
||||
bench_total += int(sum(values))
|
||||
self.suite['value'] = bench_total
|
||||
|
||||
|
||||
class AsmJSApps(Benchmark):
|
||||
name = 'asmjsapps'
|
||||
path = os.path.join('third_party', 'webkit', 'PerformanceTests', 'asmjs-apps')
|
||||
class SunSpider(RunOnceBenchmark):
|
||||
name = 'sunspider'
|
||||
path = os.path.join('third_party', 'webkit', 'PerformanceTests', 'SunSpider', 'sunspider-0.9.1')
|
||||
units = 'ms'
|
||||
|
||||
|
||||
@property
|
||||
def command(self):
|
||||
if not self.args:
|
||||
self.args = []
|
||||
full_args = ['bash', 'harness.sh', self.shell + " " + " ".join(self.args)]
|
||||
return full_args
|
||||
cmd = super(SunSpider, self).command
|
||||
return cmd + ['sunspider-standalone-driver.js']
|
||||
|
||||
def reset(self):
|
||||
super(AsmJSApps, self).reset()
|
||||
super(SunSpider, self).reset()
|
||||
|
||||
# Scores are of the form:
|
||||
# {<bench_name>: {<score_name>: [<values>]}}
|
||||
self.scores = defaultdict(lambda: defaultdict(list))
|
||||
|
||||
def process_results(self, output):
|
||||
total = 0.0
|
||||
tests = []
|
||||
for line in output.splitlines():
|
||||
m = re.search("(.+) - (\d+(\.\d+)?)", line)
|
||||
if not m:
|
||||
continue
|
||||
name = m.group(1)
|
||||
score = m.group(2)
|
||||
total += float(score)
|
||||
tests.append({ 'name': name, 'time': score })
|
||||
tests.append({ 'name': '__total__', 'time': total })
|
||||
return tests
|
||||
|
||||
def process_line(self, output):
|
||||
m = re.search("(.+) - (\d+(\.\d+)?)", output)
|
||||
if not m:
|
||||
return
|
||||
subtest = m.group(1)
|
||||
score = m.group(2)
|
||||
if subtest not in self.scores[self.name]:
|
||||
self.scores[self.name][subtest] = []
|
||||
self.scores[self.name][subtest].append(int(score))
|
||||
|
||||
|
||||
def collect_results(self):
|
||||
bench_total = 0
|
||||
# NOTE: for this benchmark we run the test once, so we have a single value array
|
||||
for bench, scores in self.scores.items():
|
||||
for score, values in scores.items():
|
||||
test_name = "{}-{}".format(self.name, score)
|
||||
total = sum(values) / len(values)
|
||||
self.suite['subtests'].append({'name': test_name, 'value': total})
|
||||
bench_total += int(sum(values))
|
||||
self.suite['value'] = bench_total
|
||||
def process_line(self, output):
|
||||
m = re.search("(.+): (\d+)", output)
|
||||
if not m:
|
||||
return
|
||||
subtest = m.group(1)
|
||||
score = m.group(2)
|
||||
if subtest not in self.scores[self.name]:
|
||||
self.scores[self.name][subtest] = []
|
||||
self.scores[self.name][subtest].append(int(score))
|
||||
|
||||
|
||||
all_benchmarks = {
|
||||
'asmjs-apps': AsmJSApps,
|
||||
'ares6': Ares6,
|
||||
'six-speed': SixSpeed,
|
||||
'asmjs-apps': AsmJSApps,
|
||||
'sunspider': SunSpider
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
[DEFAULT]
|
||||
|
||||
[browser_baselinecoverage.js]
|
||||
run-if = ccov && verify
|
||||
[browser_baselinecoverage_browser-chrome.js]
|
||||
run-if = ccov && verify
|
|
@ -0,0 +1,22 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint-disable mozilla/no-arbitrary-setTimeout */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { setTimeout } = ChromeUtils.import("resource://gre/modules/Timer.jsm", {});
|
||||
|
||||
add_task(async function() {
|
||||
requestLongerTimeout(2);
|
||||
let newWin = await BrowserTestUtils.openNewBrowserWindow();
|
||||
|
||||
await BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: "about:blank"
|
||||
}, async function(browser) {
|
||||
ok(true, "Collecting baseline coverage for browser-chrome tests.");
|
||||
await new Promise((c) => setTimeout(c, 30 * 1000));
|
||||
});
|
||||
|
||||
await BrowserTestUtils.closeWindow(newWin);
|
||||
});
|
|
@ -193,7 +193,7 @@ class CodeCoverageMixin(SingleTestMixin):
|
|||
# TODO: Add tests that haven't been run for a while (a week? N pushes?)
|
||||
|
||||
# Add baseline code coverage collection tests
|
||||
baseline_tests = {
|
||||
baseline_tests_by_ext = {
|
||||
'.html': {
|
||||
'test': 'testing/mochitest/baselinecoverage/plain/test_baselinecoverage.html',
|
||||
'suite': 'plain'
|
||||
|
@ -208,6 +208,11 @@ class CodeCoverageMixin(SingleTestMixin):
|
|||
}
|
||||
}
|
||||
|
||||
baseline_tests_by_suite = {
|
||||
'browser-chrome': 'testing/mochitest/baselinecoverage/browser_chrome/'
|
||||
'browser_baselinecoverage_browser-chrome.js'
|
||||
}
|
||||
|
||||
wpt_baseline_test = 'tests/web-platform/mozilla/tests/baselinecoverage/wpt_baselinecoverage.html' # NOQA: E501
|
||||
if self.config.get('per_test_category') == "web-platform":
|
||||
if 'testharness' not in self.suites:
|
||||
|
@ -220,15 +225,24 @@ class CodeCoverageMixin(SingleTestMixin):
|
|||
# the baseline tests that are needed.
|
||||
tests_to_add = {}
|
||||
for suite in self.suites:
|
||||
if len(self.suites[suite]) == 0:
|
||||
continue
|
||||
if suite in baseline_tests_by_suite:
|
||||
if suite not in tests_to_add:
|
||||
tests_to_add[suite] = []
|
||||
tests_to_add[suite].append(baseline_tests_by_suite[suite])
|
||||
continue
|
||||
|
||||
# Default to file types if the suite has no baseline
|
||||
for test in self.suites[suite]:
|
||||
_, test_ext = os.path.splitext(test)
|
||||
|
||||
if test_ext not in baseline_tests:
|
||||
if test_ext not in baseline_tests_by_ext:
|
||||
# Add the '.js' test as a default baseline
|
||||
# if none other exists.
|
||||
test_ext = '.js'
|
||||
baseline_test_suite = baseline_tests[test_ext]['suite']
|
||||
baseline_test_name = baseline_tests[test_ext]['test']
|
||||
baseline_test_suite = baseline_tests_by_ext[test_ext]['suite']
|
||||
baseline_test_name = baseline_tests_by_ext[test_ext]['test']
|
||||
|
||||
if baseline_test_suite not in tests_to_add:
|
||||
tests_to_add[baseline_test_suite] = []
|
||||
|
@ -401,7 +415,8 @@ class CodeCoverageMixin(SingleTestMixin):
|
|||
return
|
||||
|
||||
# Get the baseline tests that were run.
|
||||
baseline_tests_cov = {}
|
||||
baseline_tests_ext_cov = {}
|
||||
baseline_tests_suite_cov = {}
|
||||
for suite, data in self.per_test_reports.items():
|
||||
for test, grcov_file in data.items():
|
||||
if 'baselinecoverage' not in test:
|
||||
|
@ -410,9 +425,14 @@ class CodeCoverageMixin(SingleTestMixin):
|
|||
# TODO: Optimize this part which loads JSONs
|
||||
# with a size of about 40Mb into memory for diffing later.
|
||||
# Bug 1460064 is filed for this.
|
||||
_, baseline_filetype = os.path.splitext(test)
|
||||
with open(grcov_file, 'r') as f:
|
||||
baseline_tests_cov[baseline_filetype] = json.load(f)
|
||||
data = json.load(f)
|
||||
|
||||
if suite in test:
|
||||
baseline_tests_suite_cov[suite] = data
|
||||
else:
|
||||
_, baseline_filetype = os.path.splitext(test)
|
||||
baseline_tests_ext_cov[baseline_filetype] = data
|
||||
|
||||
dest = os.path.join(dirs['abs_blob_upload_dir'], 'per-test-coverage-reports.zip')
|
||||
with zipfile.ZipFile(dest, 'w', zipfile.ZIP_DEFLATED) as z:
|
||||
|
@ -433,19 +453,21 @@ class CodeCoverageMixin(SingleTestMixin):
|
|||
|
||||
# Get baseline coverage
|
||||
baseline_coverage = {}
|
||||
if self.config.get('per_test_category') == "web-platform":
|
||||
baseline_coverage = baseline_tests_cov['.html']
|
||||
if suite in baseline_tests_suite_cov:
|
||||
baseline_coverage = baseline_tests_suite_cov[suite]
|
||||
elif self.config.get('per_test_category') == "web-platform":
|
||||
baseline_coverage = baseline_tests_ext_cov['.html']
|
||||
else:
|
||||
for file_type in baseline_tests_cov:
|
||||
for file_type in baseline_tests_ext_cov:
|
||||
if not test.endswith(file_type):
|
||||
continue
|
||||
baseline_coverage = baseline_tests_cov[file_type]
|
||||
baseline_coverage = baseline_tests_ext_cov[file_type]
|
||||
break
|
||||
|
||||
if not baseline_coverage:
|
||||
# Default to the '.js' baseline as it is the largest
|
||||
self.info("Did not find a baseline test for: " + test)
|
||||
baseline_coverage = baseline_tests_cov['.js']
|
||||
baseline_coverage = baseline_tests_ext_cov['.js']
|
||||
|
||||
unique_coverage = rm_baseline_cov(baseline_coverage, report)
|
||||
|
||||
|
|
|
@ -135433,6 +135433,18 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"css/css-text/overflow-wrap/overflow-wrap-min-content-size-003.html": [
|
||||
[
|
||||
"/css/css-text/overflow-wrap/overflow-wrap-min-content-size-003.html",
|
||||
[
|
||||
[
|
||||
"/css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-003-ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/css-text/overflow-wrap/word-wrap-001.html": [
|
||||
[
|
||||
"/css/css-text/overflow-wrap/word-wrap-001.html",
|
||||
|
@ -258273,6 +258285,11 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-003-ref.html": [
|
||||
[
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/css-text/support/1x1-green.png": [
|
||||
[
|
||||
{}
|
||||
|
@ -543200,6 +543217,10 @@
|
|||
"5b3b1f19d7ae6374224da75567b3ba5279d16127",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-text/overflow-wrap/overflow-wrap-min-content-size-003.html": [
|
||||
"d1af28ffad4161c1dba7567cacb3b06098b155fa",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-text/overflow-wrap/reference/overflow-wrap-break-word-001-ref.html": [
|
||||
"0e0300a72dc920a5ffb54cda6fbe84a2f517d010",
|
||||
"support"
|
||||
|
@ -543224,6 +543245,10 @@
|
|||
"055ffbf3ca1377aaa502ffa02c52c8e49604a286",
|
||||
"support"
|
||||
],
|
||||
"css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-003-ref.html": [
|
||||
"a71b3a34d6920a5404cf7c954fa1c8ab66b788b4",
|
||||
"support"
|
||||
],
|
||||
"css/css-text/overflow-wrap/word-wrap-001.html": [
|
||||
"dd5f0f2bf132de85c7a1045e88aa3ad2b72616c1",
|
||||
"reftest"
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Text Test: overflow-wrap: break-word and intrinsic sizing</title>
|
||||
<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org/">
|
||||
<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-text-3/#overflow-wrap-property">
|
||||
<meta name="flags" content="ahem">
|
||||
<link rel="match" href="reference/overflow-wrap-min-content-size-003-ref.html">
|
||||
<meta name="assert" content="overflow-wrap:break-word breaks at edge of inline elements.">
|
||||
<style>
|
||||
#wrapper {
|
||||
width: 0px;
|
||||
font: 16px / 1 Ahem;
|
||||
overflow-wrap: break-word;
|
||||
color: green;
|
||||
}
|
||||
#test {
|
||||
float: left;
|
||||
}
|
||||
#reference {
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 128px;
|
||||
background: red;
|
||||
z-index: -1;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a vertical green bar below.
|
||||
<div id="wrapper">
|
||||
<div id="reference"></div>
|
||||
<div id="test"><span>X</span><span>X</span><span>X</span><span>X</span><span>X</span><span>X</span><span>X</span><span>X</span></div>
|
||||
</div>
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Text Test reference</title>
|
||||
<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org/">
|
||||
<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
|
||||
<meta name="flags" content="ahem">
|
||||
<style>
|
||||
#wrapper {
|
||||
width: 0px;
|
||||
font: 16px / 1 Ahem;
|
||||
color: green;
|
||||
}
|
||||
#test {
|
||||
float: left;
|
||||
}
|
||||
#reference {
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 128px;
|
||||
background: red;
|
||||
z-index: -1;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a vertical green bar below.
|
||||
<div id="wrapper">
|
||||
<div id="reference"></div>
|
||||
<div id="test">X<br>X<br>X<br>X<br>X<br>X<br>X<br>X</div>
|
||||
</div>
|
337
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/3d-cube.js
поставляемый
Normal file
337
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/3d-cube.js
поставляемый
Normal file
|
@ -0,0 +1,337 @@
|
|||
// 3D Cube Rotation
|
||||
// http://www.speich.net/computer/moztesting/3d.htm
|
||||
// Created by Simon Speich
|
||||
|
||||
var Q = new Array();
|
||||
var MTrans = new Array(); // transformation matrix
|
||||
var MQube = new Array(); // position information of qube
|
||||
var I = new Array(); // entity matrix
|
||||
var Origin = new Object();
|
||||
var Testing = new Object();
|
||||
var LoopTimer;
|
||||
|
||||
var DisplArea = new Object();
|
||||
DisplArea.Width = 300;
|
||||
DisplArea.Height = 300;
|
||||
|
||||
function DrawLine(From, To) {
|
||||
var x1 = From.V[0];
|
||||
var x2 = To.V[0];
|
||||
var y1 = From.V[1];
|
||||
var y2 = To.V[1];
|
||||
var dx = Math.abs(x2 - x1);
|
||||
var dy = Math.abs(y2 - y1);
|
||||
var x = x1;
|
||||
var y = y1;
|
||||
var IncX1, IncY1;
|
||||
var IncX2, IncY2;
|
||||
var Den;
|
||||
var Num;
|
||||
var NumAdd;
|
||||
var NumPix;
|
||||
|
||||
if (x2 >= x1) { IncX1 = 1; IncX2 = 1; }
|
||||
else { IncX1 = -1; IncX2 = -1; }
|
||||
if (y2 >= y1) { IncY1 = 1; IncY2 = 1; }
|
||||
else { IncY1 = -1; IncY2 = -1; }
|
||||
if (dx >= dy) {
|
||||
IncX1 = 0;
|
||||
IncY2 = 0;
|
||||
Den = dx;
|
||||
Num = dx / 2;
|
||||
NumAdd = dy;
|
||||
NumPix = dx;
|
||||
}
|
||||
else {
|
||||
IncX2 = 0;
|
||||
IncY1 = 0;
|
||||
Den = dy;
|
||||
Num = dy / 2;
|
||||
NumAdd = dx;
|
||||
NumPix = dy;
|
||||
}
|
||||
|
||||
NumPix = Math.round(Q.LastPx + NumPix);
|
||||
|
||||
var i = Q.LastPx;
|
||||
for (; i < NumPix; i++) {
|
||||
Num += NumAdd;
|
||||
if (Num >= Den) {
|
||||
Num -= Den;
|
||||
x += IncX1;
|
||||
y += IncY1;
|
||||
}
|
||||
x += IncX2;
|
||||
y += IncY2;
|
||||
}
|
||||
Q.LastPx = NumPix;
|
||||
}
|
||||
|
||||
function CalcCross(V0, V1) {
|
||||
var Cross = new Array();
|
||||
Cross[0] = V0[1]*V1[2] - V0[2]*V1[1];
|
||||
Cross[1] = V0[2]*V1[0] - V0[0]*V1[2];
|
||||
Cross[2] = V0[0]*V1[1] - V0[1]*V1[0];
|
||||
return Cross;
|
||||
}
|
||||
|
||||
function CalcNormal(V0, V1, V2) {
|
||||
var A = new Array(); var B = new Array();
|
||||
for (var i = 0; i < 3; i++) {
|
||||
A[i] = V0[i] - V1[i];
|
||||
B[i] = V2[i] - V1[i];
|
||||
}
|
||||
A = CalcCross(A, B);
|
||||
var Length = Math.sqrt(A[0]*A[0] + A[1]*A[1] + A[2]*A[2]);
|
||||
for (var i = 0; i < 3; i++) A[i] = A[i] / Length;
|
||||
A[3] = 1;
|
||||
return A;
|
||||
}
|
||||
|
||||
function CreateP(X,Y,Z) {
|
||||
this.V = [X,Y,Z,1];
|
||||
}
|
||||
|
||||
// multiplies two matrices
|
||||
function MMulti(M1, M2) {
|
||||
var M = [[],[],[],[]];
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
for (; i < 4; i++) {
|
||||
j = 0;
|
||||
for (; j < 4; j++) M[i][j] = M1[i][0] * M2[0][j] + M1[i][1] * M2[1][j] + M1[i][2] * M2[2][j] + M1[i][3] * M2[3][j];
|
||||
}
|
||||
return M;
|
||||
}
|
||||
|
||||
//multiplies matrix with vector
|
||||
function VMulti(M, V) {
|
||||
var Vect = new Array();
|
||||
var i = 0;
|
||||
for (;i < 4; i++) Vect[i] = M[i][0] * V[0] + M[i][1] * V[1] + M[i][2] * V[2] + M[i][3] * V[3];
|
||||
return Vect;
|
||||
}
|
||||
|
||||
function VMulti2(M, V) {
|
||||
var Vect = new Array();
|
||||
var i = 0;
|
||||
for (;i < 3; i++) Vect[i] = M[i][0] * V[0] + M[i][1] * V[1] + M[i][2] * V[2];
|
||||
return Vect;
|
||||
}
|
||||
|
||||
// add to matrices
|
||||
function MAdd(M1, M2) {
|
||||
var M = [[],[],[],[]];
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
for (; i < 4; i++) {
|
||||
j = 0;
|
||||
for (; j < 4; j++) M[i][j] = M1[i][j] + M2[i][j];
|
||||
}
|
||||
return M;
|
||||
}
|
||||
|
||||
function Translate(M, Dx, Dy, Dz) {
|
||||
var T = [
|
||||
[1,0,0,Dx],
|
||||
[0,1,0,Dy],
|
||||
[0,0,1,Dz],
|
||||
[0,0,0,1]
|
||||
];
|
||||
return MMulti(T, M);
|
||||
}
|
||||
|
||||
function RotateX(M, Phi) {
|
||||
var a = Phi;
|
||||
a *= Math.PI / 180;
|
||||
var Cos = Math.cos(a);
|
||||
var Sin = Math.sin(a);
|
||||
var R = [
|
||||
[1,0,0,0],
|
||||
[0,Cos,-Sin,0],
|
||||
[0,Sin,Cos,0],
|
||||
[0,0,0,1]
|
||||
];
|
||||
return MMulti(R, M);
|
||||
}
|
||||
|
||||
function RotateY(M, Phi) {
|
||||
var a = Phi;
|
||||
a *= Math.PI / 180;
|
||||
var Cos = Math.cos(a);
|
||||
var Sin = Math.sin(a);
|
||||
var R = [
|
||||
[Cos,0,Sin,0],
|
||||
[0,1,0,0],
|
||||
[-Sin,0,Cos,0],
|
||||
[0,0,0,1]
|
||||
];
|
||||
return MMulti(R, M);
|
||||
}
|
||||
|
||||
function RotateZ(M, Phi) {
|
||||
var a = Phi;
|
||||
a *= Math.PI / 180;
|
||||
var Cos = Math.cos(a);
|
||||
var Sin = Math.sin(a);
|
||||
var R = [
|
||||
[Cos,-Sin,0,0],
|
||||
[Sin,Cos,0,0],
|
||||
[0,0,1,0],
|
||||
[0,0,0,1]
|
||||
];
|
||||
return MMulti(R, M);
|
||||
}
|
||||
|
||||
function DrawQube() {
|
||||
// calc current normals
|
||||
var CurN = new Array();
|
||||
var i = 5;
|
||||
Q.LastPx = 0;
|
||||
for (; i > -1; i--) CurN[i] = VMulti2(MQube, Q.Normal[i]);
|
||||
if (CurN[0][2] < 0) {
|
||||
if (!Q.Line[0]) { DrawLine(Q[0], Q[1]); Q.Line[0] = true; };
|
||||
if (!Q.Line[1]) { DrawLine(Q[1], Q[2]); Q.Line[1] = true; };
|
||||
if (!Q.Line[2]) { DrawLine(Q[2], Q[3]); Q.Line[2] = true; };
|
||||
if (!Q.Line[3]) { DrawLine(Q[3], Q[0]); Q.Line[3] = true; };
|
||||
}
|
||||
if (CurN[1][2] < 0) {
|
||||
if (!Q.Line[2]) { DrawLine(Q[3], Q[2]); Q.Line[2] = true; };
|
||||
if (!Q.Line[9]) { DrawLine(Q[2], Q[6]); Q.Line[9] = true; };
|
||||
if (!Q.Line[6]) { DrawLine(Q[6], Q[7]); Q.Line[6] = true; };
|
||||
if (!Q.Line[10]) { DrawLine(Q[7], Q[3]); Q.Line[10] = true; };
|
||||
}
|
||||
if (CurN[2][2] < 0) {
|
||||
if (!Q.Line[4]) { DrawLine(Q[4], Q[5]); Q.Line[4] = true; };
|
||||
if (!Q.Line[5]) { DrawLine(Q[5], Q[6]); Q.Line[5] = true; };
|
||||
if (!Q.Line[6]) { DrawLine(Q[6], Q[7]); Q.Line[6] = true; };
|
||||
if (!Q.Line[7]) { DrawLine(Q[7], Q[4]); Q.Line[7] = true; };
|
||||
}
|
||||
if (CurN[3][2] < 0) {
|
||||
if (!Q.Line[4]) { DrawLine(Q[4], Q[5]); Q.Line[4] = true; };
|
||||
if (!Q.Line[8]) { DrawLine(Q[5], Q[1]); Q.Line[8] = true; };
|
||||
if (!Q.Line[0]) { DrawLine(Q[1], Q[0]); Q.Line[0] = true; };
|
||||
if (!Q.Line[11]) { DrawLine(Q[0], Q[4]); Q.Line[11] = true; };
|
||||
}
|
||||
if (CurN[4][2] < 0) {
|
||||
if (!Q.Line[11]) { DrawLine(Q[4], Q[0]); Q.Line[11] = true; };
|
||||
if (!Q.Line[3]) { DrawLine(Q[0], Q[3]); Q.Line[3] = true; };
|
||||
if (!Q.Line[10]) { DrawLine(Q[3], Q[7]); Q.Line[10] = true; };
|
||||
if (!Q.Line[7]) { DrawLine(Q[7], Q[4]); Q.Line[7] = true; };
|
||||
}
|
||||
if (CurN[5][2] < 0) {
|
||||
if (!Q.Line[8]) { DrawLine(Q[1], Q[5]); Q.Line[8] = true; };
|
||||
if (!Q.Line[5]) { DrawLine(Q[5], Q[6]); Q.Line[5] = true; };
|
||||
if (!Q.Line[9]) { DrawLine(Q[6], Q[2]); Q.Line[9] = true; };
|
||||
if (!Q.Line[1]) { DrawLine(Q[2], Q[1]); Q.Line[1] = true; };
|
||||
}
|
||||
Q.Line = [false,false,false,false,false,false,false,false,false,false,false,false];
|
||||
Q.LastPx = 0;
|
||||
}
|
||||
|
||||
function Loop() {
|
||||
if (Testing.LoopCount > Testing.LoopMax) return;
|
||||
var TestingStr = String(Testing.LoopCount);
|
||||
while (TestingStr.length < 3) TestingStr = "0" + TestingStr;
|
||||
MTrans = Translate(I, -Q[8].V[0], -Q[8].V[1], -Q[8].V[2]);
|
||||
MTrans = RotateX(MTrans, 1);
|
||||
MTrans = RotateY(MTrans, 3);
|
||||
MTrans = RotateZ(MTrans, 5);
|
||||
MTrans = Translate(MTrans, Q[8].V[0], Q[8].V[1], Q[8].V[2]);
|
||||
MQube = MMulti(MTrans, MQube);
|
||||
var i = 8;
|
||||
for (; i > -1; i--) {
|
||||
Q[i].V = VMulti(MTrans, Q[i].V);
|
||||
}
|
||||
DrawQube();
|
||||
Testing.LoopCount++;
|
||||
Loop();
|
||||
}
|
||||
|
||||
function Init(CubeSize) {
|
||||
// init/reset vars
|
||||
Origin.V = [150,150,20,1];
|
||||
Testing.LoopCount = 0;
|
||||
Testing.LoopMax = 50;
|
||||
Testing.TimeMax = 0;
|
||||
Testing.TimeAvg = 0;
|
||||
Testing.TimeMin = 0;
|
||||
Testing.TimeTemp = 0;
|
||||
Testing.TimeTotal = 0;
|
||||
Testing.Init = false;
|
||||
|
||||
// transformation matrix
|
||||
MTrans = [
|
||||
[1,0,0,0],
|
||||
[0,1,0,0],
|
||||
[0,0,1,0],
|
||||
[0,0,0,1]
|
||||
];
|
||||
|
||||
// position information of qube
|
||||
MQube = [
|
||||
[1,0,0,0],
|
||||
[0,1,0,0],
|
||||
[0,0,1,0],
|
||||
[0,0,0,1]
|
||||
];
|
||||
|
||||
// entity matrix
|
||||
I = [
|
||||
[1,0,0,0],
|
||||
[0,1,0,0],
|
||||
[0,0,1,0],
|
||||
[0,0,0,1]
|
||||
];
|
||||
|
||||
// create qube
|
||||
Q[0] = new CreateP(-CubeSize,-CubeSize, CubeSize);
|
||||
Q[1] = new CreateP(-CubeSize, CubeSize, CubeSize);
|
||||
Q[2] = new CreateP( CubeSize, CubeSize, CubeSize);
|
||||
Q[3] = new CreateP( CubeSize,-CubeSize, CubeSize);
|
||||
Q[4] = new CreateP(-CubeSize,-CubeSize,-CubeSize);
|
||||
Q[5] = new CreateP(-CubeSize, CubeSize,-CubeSize);
|
||||
Q[6] = new CreateP( CubeSize, CubeSize,-CubeSize);
|
||||
Q[7] = new CreateP( CubeSize,-CubeSize,-CubeSize);
|
||||
|
||||
// center of gravity
|
||||
Q[8] = new CreateP(0, 0, 0);
|
||||
|
||||
// anti-clockwise edge check
|
||||
Q.Edge = [[0,1,2],[3,2,6],[7,6,5],[4,5,1],[4,0,3],[1,5,6]];
|
||||
|
||||
// calculate squad normals
|
||||
Q.Normal = new Array();
|
||||
for (var i = 0; i < Q.Edge.length; i++) Q.Normal[i] = CalcNormal(Q[Q.Edge[i][0]].V, Q[Q.Edge[i][1]].V, Q[Q.Edge[i][2]].V);
|
||||
|
||||
// line drawn ?
|
||||
Q.Line = [false,false,false,false,false,false,false,false,false,false,false,false];
|
||||
|
||||
// create line pixels
|
||||
Q.NumPx = 9 * 2 * CubeSize;
|
||||
for (var i = 0; i < Q.NumPx; i++) CreateP(0,0,0);
|
||||
|
||||
MTrans = Translate(MTrans, Origin.V[0], Origin.V[1], Origin.V[2]);
|
||||
MQube = MMulti(MTrans, MQube);
|
||||
|
||||
var i = 0;
|
||||
for (; i < 9; i++) {
|
||||
Q[i].V = VMulti(MTrans, Q[i].V);
|
||||
}
|
||||
DrawQube();
|
||||
Testing.Init = true;
|
||||
Loop();
|
||||
}
|
||||
|
||||
for ( var i = 20; i <= 160; i *= 2 ) {
|
||||
Init(i);
|
||||
}
|
||||
|
||||
Q = null;
|
||||
MTrans = null;
|
||||
MQube = null;
|
||||
I = null;
|
||||
Origin = null;
|
||||
Testing = null;
|
||||
LoopTime = null;
|
||||
DisplArea = null;
|
54
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/3d-morph.js
поставляемый
Normal file
54
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/3d-morph.js
поставляемый
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
var loops = 15
|
||||
var nx = 120
|
||||
var nz = 120
|
||||
|
||||
function morph(a, f) {
|
||||
var PI2nx = Math.PI * 8/nx
|
||||
var sin = Math.sin
|
||||
var f30 = -(50 * sin(f*Math.PI*2))
|
||||
|
||||
for (var i = 0; i < nz; ++i) {
|
||||
for (var j = 0; j < nx; ++j) {
|
||||
a[3*(i*nx+j)+1] = sin((j-1) * PI2nx ) * -f30
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var a = Array()
|
||||
for (var i=0; i < nx*nz*3; ++i)
|
||||
a[i] = 0
|
||||
|
||||
for (var i = 0; i < loops; ++i) {
|
||||
morph(a, i/loops)
|
||||
}
|
||||
|
||||
testOutput = 0;
|
||||
for (var i = 0; i < nx; i++)
|
||||
testOutput += a[3*(i*nx+i)+1];
|
||||
a = null;
|
441
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/3d-raytrace.js
поставляемый
Normal file
441
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/3d-raytrace.js
поставляемый
Normal file
|
@ -0,0 +1,441 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
function createVector(x,y,z) {
|
||||
return new Array(x,y,z);
|
||||
}
|
||||
|
||||
function sqrLengthVector(self) {
|
||||
return self[0] * self[0] + self[1] * self[1] + self[2] * self[2];
|
||||
}
|
||||
|
||||
function lengthVector(self) {
|
||||
return Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
|
||||
}
|
||||
|
||||
function addVector(self, v) {
|
||||
self[0] += v[0];
|
||||
self[1] += v[1];
|
||||
self[2] += v[2];
|
||||
return self;
|
||||
}
|
||||
|
||||
function subVector(self, v) {
|
||||
self[0] -= v[0];
|
||||
self[1] -= v[1];
|
||||
self[2] -= v[2];
|
||||
return self;
|
||||
}
|
||||
|
||||
function scaleVector(self, scale) {
|
||||
self[0] *= scale;
|
||||
self[1] *= scale;
|
||||
self[2] *= scale;
|
||||
return self;
|
||||
}
|
||||
|
||||
function normaliseVector(self) {
|
||||
var len = Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
|
||||
self[0] /= len;
|
||||
self[1] /= len;
|
||||
self[2] /= len;
|
||||
return self;
|
||||
}
|
||||
|
||||
function add(v1, v2) {
|
||||
return new Array(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]);
|
||||
}
|
||||
|
||||
function sub(v1, v2) {
|
||||
return new Array(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]);
|
||||
}
|
||||
|
||||
function scalev(v1, v2) {
|
||||
return new Array(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]);
|
||||
}
|
||||
|
||||
function dot(v1, v2) {
|
||||
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
|
||||
}
|
||||
|
||||
function scale(v, scale) {
|
||||
return [v[0] * scale, v[1] * scale, v[2] * scale];
|
||||
}
|
||||
|
||||
function cross(v1, v2) {
|
||||
return [v1[1] * v2[2] - v1[2] * v2[1],
|
||||
v1[2] * v2[0] - v1[0] * v2[2],
|
||||
v1[0] * v2[1] - v1[1] * v2[0]];
|
||||
|
||||
}
|
||||
|
||||
function normalise(v) {
|
||||
var len = lengthVector(v);
|
||||
return [v[0] / len, v[1] / len, v[2] / len];
|
||||
}
|
||||
|
||||
function transformMatrix(self, v) {
|
||||
var vals = self;
|
||||
var x = vals[0] * v[0] + vals[1] * v[1] + vals[2] * v[2] + vals[3];
|
||||
var y = vals[4] * v[0] + vals[5] * v[1] + vals[6] * v[2] + vals[7];
|
||||
var z = vals[8] * v[0] + vals[9] * v[1] + vals[10] * v[2] + vals[11];
|
||||
return [x, y, z];
|
||||
}
|
||||
|
||||
function invertMatrix(self) {
|
||||
var temp = new Array(16);
|
||||
var tx = -self[3];
|
||||
var ty = -self[7];
|
||||
var tz = -self[11];
|
||||
for (h = 0; h < 3; h++)
|
||||
for (v = 0; v < 3; v++)
|
||||
temp[h + v * 4] = self[v + h * 4];
|
||||
for (i = 0; i < 11; i++)
|
||||
self[i] = temp[i];
|
||||
self[3] = tx * self[0] + ty * self[1] + tz * self[2];
|
||||
self[7] = tx * self[4] + ty * self[5] + tz * self[6];
|
||||
self[11] = tx * self[8] + ty * self[9] + tz * self[10];
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
// Triangle intersection using barycentric coord method
|
||||
function Triangle(p1, p2, p3) {
|
||||
var edge1 = sub(p3, p1);
|
||||
var edge2 = sub(p2, p1);
|
||||
var normal = cross(edge1, edge2);
|
||||
if (Math.abs(normal[0]) > Math.abs(normal[1]))
|
||||
if (Math.abs(normal[0]) > Math.abs(normal[2]))
|
||||
this.axis = 0;
|
||||
else
|
||||
this.axis = 2;
|
||||
else
|
||||
if (Math.abs(normal[1]) > Math.abs(normal[2]))
|
||||
this.axis = 1;
|
||||
else
|
||||
this.axis = 2;
|
||||
var u = (this.axis + 1) % 3;
|
||||
var v = (this.axis + 2) % 3;
|
||||
var u1 = edge1[u];
|
||||
var v1 = edge1[v];
|
||||
|
||||
var u2 = edge2[u];
|
||||
var v2 = edge2[v];
|
||||
this.normal = normalise(normal);
|
||||
this.nu = normal[u] / normal[this.axis];
|
||||
this.nv = normal[v] / normal[this.axis];
|
||||
this.nd = dot(normal, p1) / normal[this.axis];
|
||||
var det = u1 * v2 - v1 * u2;
|
||||
this.eu = p1[u];
|
||||
this.ev = p1[v];
|
||||
this.nu1 = u1 / det;
|
||||
this.nv1 = -v1 / det;
|
||||
this.nu2 = v2 / det;
|
||||
this.nv2 = -u2 / det;
|
||||
this.material = [0.7, 0.7, 0.7];
|
||||
}
|
||||
|
||||
Triangle.prototype.intersect = function(orig, dir, near, far) {
|
||||
var u = (this.axis + 1) % 3;
|
||||
var v = (this.axis + 2) % 3;
|
||||
var d = dir[this.axis] + this.nu * dir[u] + this.nv * dir[v];
|
||||
var t = (this.nd - orig[this.axis] - this.nu * orig[u] - this.nv * orig[v]) / d;
|
||||
if (t < near || t > far)
|
||||
return null;
|
||||
var Pu = orig[u] + t * dir[u] - this.eu;
|
||||
var Pv = orig[v] + t * dir[v] - this.ev;
|
||||
var a2 = Pv * this.nu1 + Pu * this.nv1;
|
||||
if (a2 < 0)
|
||||
return null;
|
||||
var a3 = Pu * this.nu2 + Pv * this.nv2;
|
||||
if (a3 < 0)
|
||||
return null;
|
||||
|
||||
if ((a2 + a3) > 1)
|
||||
return null;
|
||||
return t;
|
||||
}
|
||||
|
||||
function Scene(a_triangles) {
|
||||
this.triangles = a_triangles;
|
||||
this.lights = [];
|
||||
this.ambient = [0,0,0];
|
||||
this.background = [0.8,0.8,1];
|
||||
}
|
||||
var zero = new Array(0,0,0);
|
||||
|
||||
Scene.prototype.intersect = function(origin, dir, near, far) {
|
||||
var closest = null;
|
||||
for (i = 0; i < this.triangles.length; i++) {
|
||||
var triangle = this.triangles[i];
|
||||
var d = triangle.intersect(origin, dir, near, far);
|
||||
if (d == null || d > far || d < near)
|
||||
continue;
|
||||
far = d;
|
||||
closest = triangle;
|
||||
}
|
||||
|
||||
if (!closest)
|
||||
return [this.background[0],this.background[1],this.background[2]];
|
||||
|
||||
var normal = closest.normal;
|
||||
var hit = add(origin, scale(dir, far));
|
||||
if (dot(dir, normal) > 0)
|
||||
normal = [-normal[0], -normal[1], -normal[2]];
|
||||
|
||||
var colour = null;
|
||||
if (closest.shader) {
|
||||
colour = closest.shader(closest, hit, dir);
|
||||
} else {
|
||||
colour = closest.material;
|
||||
}
|
||||
|
||||
// do reflection
|
||||
var reflected = null;
|
||||
if (colour.reflection > 0.001) {
|
||||
var reflection = addVector(scale(normal, -2*dot(dir, normal)), dir);
|
||||
reflected = this.intersect(hit, reflection, 0.0001, 1000000);
|
||||
if (colour.reflection >= 0.999999)
|
||||
return reflected;
|
||||
}
|
||||
|
||||
var l = [this.ambient[0], this.ambient[1], this.ambient[2]];
|
||||
for (var i = 0; i < this.lights.length; i++) {
|
||||
var light = this.lights[i];
|
||||
var toLight = sub(light, hit);
|
||||
var distance = lengthVector(toLight);
|
||||
scaleVector(toLight, 1.0/distance);
|
||||
distance -= 0.0001;
|
||||
if (this.blocked(hit, toLight, distance))
|
||||
continue;
|
||||
var nl = dot(normal, toLight);
|
||||
if (nl > 0)
|
||||
addVector(l, scale(light.colour, nl));
|
||||
}
|
||||
l = scalev(l, colour);
|
||||
if (reflected) {
|
||||
l = addVector(scaleVector(l, 1 - colour.reflection), scaleVector(reflected, colour.reflection));
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
Scene.prototype.blocked = function(O, D, far) {
|
||||
var near = 0.0001;
|
||||
var closest = null;
|
||||
for (i = 0; i < this.triangles.length; i++) {
|
||||
var triangle = this.triangles[i];
|
||||
var d = triangle.intersect(O, D, near, far);
|
||||
if (d == null || d > far || d < near)
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// this camera code is from notes i made ages ago, it is from *somewhere* -- i cannot remember where
|
||||
// that somewhere is
|
||||
function Camera(origin, lookat, up) {
|
||||
var zaxis = normaliseVector(subVector(lookat, origin));
|
||||
var xaxis = normaliseVector(cross(up, zaxis));
|
||||
var yaxis = normaliseVector(cross(xaxis, subVector([0,0,0], zaxis)));
|
||||
var m = new Array(16);
|
||||
m[0] = xaxis[0]; m[1] = xaxis[1]; m[2] = xaxis[2];
|
||||
m[4] = yaxis[0]; m[5] = yaxis[1]; m[6] = yaxis[2];
|
||||
m[8] = zaxis[0]; m[9] = zaxis[1]; m[10] = zaxis[2];
|
||||
invertMatrix(m);
|
||||
m[3] = 0; m[7] = 0; m[11] = 0;
|
||||
this.origin = origin;
|
||||
this.directions = new Array(4);
|
||||
this.directions[0] = normalise([-0.7, 0.7, 1]);
|
||||
this.directions[1] = normalise([ 0.7, 0.7, 1]);
|
||||
this.directions[2] = normalise([ 0.7, -0.7, 1]);
|
||||
this.directions[3] = normalise([-0.7, -0.7, 1]);
|
||||
this.directions[0] = transformMatrix(m, this.directions[0]);
|
||||
this.directions[1] = transformMatrix(m, this.directions[1]);
|
||||
this.directions[2] = transformMatrix(m, this.directions[2]);
|
||||
this.directions[3] = transformMatrix(m, this.directions[3]);
|
||||
}
|
||||
|
||||
Camera.prototype.generateRayPair = function(y) {
|
||||
rays = new Array(new Object(), new Object());
|
||||
rays[0].origin = this.origin;
|
||||
rays[1].origin = this.origin;
|
||||
rays[0].dir = addVector(scale(this.directions[0], y), scale(this.directions[3], 1 - y));
|
||||
rays[1].dir = addVector(scale(this.directions[1], y), scale(this.directions[2], 1 - y));
|
||||
return rays;
|
||||
}
|
||||
|
||||
function renderRows(camera, scene, pixels, width, height, starty, stopy) {
|
||||
for (var y = starty; y < stopy; y++) {
|
||||
var rays = camera.generateRayPair(y / height);
|
||||
for (var x = 0; x < width; x++) {
|
||||
var xp = x / width;
|
||||
var origin = addVector(scale(rays[0].origin, xp), scale(rays[1].origin, 1 - xp));
|
||||
var dir = normaliseVector(addVector(scale(rays[0].dir, xp), scale(rays[1].dir, 1 - xp)));
|
||||
var l = scene.intersect(origin, dir);
|
||||
pixels[y][x] = l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Camera.prototype.render = function(scene, pixels, width, height) {
|
||||
var cam = this;
|
||||
var row = 0;
|
||||
renderRows(cam, scene, pixels, width, height, 0, height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function raytraceScene()
|
||||
{
|
||||
var startDate = new Date().getTime();
|
||||
var numTriangles = 2 * 6;
|
||||
var triangles = new Array();//numTriangles);
|
||||
var tfl = createVector(-10, 10, -10);
|
||||
var tfr = createVector( 10, 10, -10);
|
||||
var tbl = createVector(-10, 10, 10);
|
||||
var tbr = createVector( 10, 10, 10);
|
||||
var bfl = createVector(-10, -10, -10);
|
||||
var bfr = createVector( 10, -10, -10);
|
||||
var bbl = createVector(-10, -10, 10);
|
||||
var bbr = createVector( 10, -10, 10);
|
||||
|
||||
// cube!!!
|
||||
// front
|
||||
var i = 0;
|
||||
|
||||
triangles[i++] = new Triangle(tfl, tfr, bfr);
|
||||
triangles[i++] = new Triangle(tfl, bfr, bfl);
|
||||
// back
|
||||
triangles[i++] = new Triangle(tbl, tbr, bbr);
|
||||
triangles[i++] = new Triangle(tbl, bbr, bbl);
|
||||
// triangles[i-1].material = [0.7,0.2,0.2];
|
||||
// triangles[i-1].material.reflection = 0.8;
|
||||
// left
|
||||
triangles[i++] = new Triangle(tbl, tfl, bbl);
|
||||
// triangles[i-1].reflection = 0.6;
|
||||
triangles[i++] = new Triangle(tfl, bfl, bbl);
|
||||
// triangles[i-1].reflection = 0.6;
|
||||
// right
|
||||
triangles[i++] = new Triangle(tbr, tfr, bbr);
|
||||
triangles[i++] = new Triangle(tfr, bfr, bbr);
|
||||
// top
|
||||
triangles[i++] = new Triangle(tbl, tbr, tfr);
|
||||
triangles[i++] = new Triangle(tbl, tfr, tfl);
|
||||
// bottom
|
||||
triangles[i++] = new Triangle(bbl, bbr, bfr);
|
||||
triangles[i++] = new Triangle(bbl, bfr, bfl);
|
||||
|
||||
//Floor!!!!
|
||||
var green = createVector(0.0, 0.4, 0.0);
|
||||
var grey = createVector(0.4, 0.4, 0.4);
|
||||
grey.reflection = 1.0;
|
||||
var floorShader = function(tri, pos, view) {
|
||||
var x = ((pos[0]/32) % 2 + 2) % 2;
|
||||
var z = ((pos[2]/32 + 0.3) % 2 + 2) % 2;
|
||||
if (x < 1 != z < 1) {
|
||||
//in the real world we use the fresnel term...
|
||||
// var angle = 1-dot(view, tri.normal);
|
||||
// angle *= angle;
|
||||
// angle *= angle;
|
||||
// angle *= angle;
|
||||
//grey.reflection = angle;
|
||||
return grey;
|
||||
} else
|
||||
return green;
|
||||
}
|
||||
var ffl = createVector(-1000, -30, -1000);
|
||||
var ffr = createVector( 1000, -30, -1000);
|
||||
var fbl = createVector(-1000, -30, 1000);
|
||||
var fbr = createVector( 1000, -30, 1000);
|
||||
triangles[i++] = new Triangle(fbl, fbr, ffr);
|
||||
triangles[i-1].shader = floorShader;
|
||||
triangles[i++] = new Triangle(fbl, ffr, ffl);
|
||||
triangles[i-1].shader = floorShader;
|
||||
|
||||
var _scene = new Scene(triangles);
|
||||
_scene.lights[0] = createVector(20, 38, -22);
|
||||
_scene.lights[0].colour = createVector(0.7, 0.3, 0.3);
|
||||
_scene.lights[1] = createVector(-23, 40, 17);
|
||||
_scene.lights[1].colour = createVector(0.7, 0.3, 0.3);
|
||||
_scene.lights[2] = createVector(23, 20, 17);
|
||||
_scene.lights[2].colour = createVector(0.7, 0.7, 0.7);
|
||||
_scene.ambient = createVector(0.1, 0.1, 0.1);
|
||||
// _scene.background = createVector(0.7, 0.7, 1.0);
|
||||
|
||||
var size = 30;
|
||||
var pixels = new Array();
|
||||
for (var y = 0; y < size; y++) {
|
||||
pixels[y] = new Array();
|
||||
for (var x = 0; x < size; x++) {
|
||||
pixels[y][x] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
var _camera = new Camera(createVector(-40, 40, 40), createVector(0, 0, 0), createVector(0, 1, 0));
|
||||
_camera.render(_scene, pixels, size, size);
|
||||
|
||||
return pixels;
|
||||
}
|
||||
|
||||
function arrayToCanvasCommands(pixels)
|
||||
{
|
||||
var s = '<canvas id="renderCanvas" width="30px" height="30px"></canvas><scr' + 'ipt>\nvar pixels = [';
|
||||
var size = 30;
|
||||
for (var y = 0; y < size; y++) {
|
||||
s += "[";
|
||||
for (var x = 0; x < size; x++) {
|
||||
s += "[" + pixels[y][x] + "],";
|
||||
}
|
||||
s+= "],";
|
||||
}
|
||||
s += '];\n var canvas = document.getElementById("renderCanvas").getContext("2d");\n\
|
||||
\n\
|
||||
\n\
|
||||
var size = 30;\n\
|
||||
canvas.fillStyle = "red";\n\
|
||||
canvas.fillRect(0, 0, size, size);\n\
|
||||
canvas.scale(1, -1);\n\
|
||||
canvas.translate(0, -size);\n\
|
||||
\n\
|
||||
if (!canvas.setFillColor)\n\
|
||||
canvas.setFillColor = function(r, g, b, a) {\n\
|
||||
this.fillStyle = "rgb("+[Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]+")";\n\
|
||||
}\n\
|
||||
\n\
|
||||
for (var y = 0; y < size; y++) {\n\
|
||||
for (var x = 0; x < size; x++) {\n\
|
||||
var l = pixels[y][x];\n\
|
||||
canvas.setFillColor(l[0], l[1], l[2], 1);\n\
|
||||
canvas.fillRect(x, y, 1, 1);\n\
|
||||
}\n\
|
||||
}</scr' + 'ipt>';
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
testOutput = arrayToCanvasCommands(raytraceScene());
|
50
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/access-binary-trees.js
поставляемый
Normal file
50
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/access-binary-trees.js
поставляемый
Normal file
|
@ -0,0 +1,50 @@
|
|||
/* The Great Computer Language Shootout
|
||||
http://shootout.alioth.debian.org/
|
||||
contributed by Isaac Gouy */
|
||||
|
||||
function TreeNode(left,right,item){
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
TreeNode.prototype.itemCheck = function(){
|
||||
if (this.left==null) return this.item;
|
||||
else return this.item + this.left.itemCheck() - this.right.itemCheck();
|
||||
}
|
||||
|
||||
function bottomUpTree(item,depth){
|
||||
if (depth>0){
|
||||
return new TreeNode(
|
||||
bottomUpTree(2*item-1, depth-1)
|
||||
,bottomUpTree(2*item, depth-1)
|
||||
,item
|
||||
);
|
||||
}
|
||||
else {
|
||||
return new TreeNode(null,null,item);
|
||||
}
|
||||
}
|
||||
|
||||
var ret;
|
||||
|
||||
for ( var n = 4; n <= 7; n += 1 ) {
|
||||
var minDepth = 4;
|
||||
var maxDepth = Math.max(minDepth + 2, n);
|
||||
var stretchDepth = maxDepth + 1;
|
||||
|
||||
var check = bottomUpTree(0,stretchDepth).itemCheck();
|
||||
|
||||
var longLivedTree = bottomUpTree(0,maxDepth);
|
||||
for (var depth=minDepth; depth<=maxDepth; depth+=2){
|
||||
var iterations = 1 << (maxDepth - depth + minDepth);
|
||||
|
||||
check = 0;
|
||||
for (var i=1; i<=iterations; i++){
|
||||
check += bottomUpTree(i,depth).itemCheck();
|
||||
check += bottomUpTree(-i,depth).itemCheck();
|
||||
}
|
||||
}
|
||||
|
||||
ret = longLivedTree.itemCheck();
|
||||
}
|
66
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/access-fannkuch.js
поставляемый
Normal file
66
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/access-fannkuch.js
поставляемый
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* The Great Computer Language Shootout
|
||||
http://shootout.alioth.debian.org/
|
||||
contributed by Isaac Gouy */
|
||||
|
||||
function fannkuch(n) {
|
||||
var check = 0;
|
||||
var perm = Array(n);
|
||||
var perm1 = Array(n);
|
||||
var count = Array(n);
|
||||
var maxPerm = Array(n);
|
||||
var maxFlipsCount = 0;
|
||||
var m = n - 1;
|
||||
|
||||
for (var i = 0; i < n; i++) perm1[i] = i;
|
||||
var r = n;
|
||||
|
||||
while (true) {
|
||||
// write-out the first 30 permutations
|
||||
if (check < 30){
|
||||
var s = "";
|
||||
for(var i=0; i<n; i++) s += (perm1[i]+1).toString();
|
||||
check++;
|
||||
}
|
||||
|
||||
while (r != 1) { count[r - 1] = r; r--; }
|
||||
if (!(perm1[0] == 0 || perm1[m] == m)) {
|
||||
for (var i = 0; i < n; i++) perm[i] = perm1[i];
|
||||
|
||||
var flipsCount = 0;
|
||||
var k;
|
||||
|
||||
while (!((k = perm[0]) == 0)) {
|
||||
var k2 = (k + 1) >> 1;
|
||||
for (var i = 0; i < k2; i++) {
|
||||
var temp = perm[i]; perm[i] = perm[k - i]; perm[k - i] = temp;
|
||||
}
|
||||
flipsCount++;
|
||||
}
|
||||
|
||||
if (flipsCount > maxFlipsCount) {
|
||||
maxFlipsCount = flipsCount;
|
||||
for (var i = 0; i < n; i++) maxPerm[i] = perm1[i];
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (r == n) return maxFlipsCount;
|
||||
var perm0 = perm1[0];
|
||||
var i = 0;
|
||||
while (i < r) {
|
||||
var j = i + 1;
|
||||
perm1[i] = perm1[j];
|
||||
i = j;
|
||||
}
|
||||
perm1[r] = perm0;
|
||||
|
||||
count[r] = count[r] - 1;
|
||||
if (count[r] > 0) break;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var n = 8;
|
||||
var ret = fannkuch(n);
|
||||
|
169
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/access-nbody.js
поставляемый
Normal file
169
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/access-nbody.js
поставляемый
Normal file
|
@ -0,0 +1,169 @@
|
|||
/* The Great Computer Language Shootout
|
||||
http://shootout.alioth.debian.org/
|
||||
contributed by Isaac Gouy */
|
||||
|
||||
var PI = 3.141592653589793;
|
||||
var SOLAR_MASS = 4 * PI * PI;
|
||||
var DAYS_PER_YEAR = 365.24;
|
||||
|
||||
function Body(x,y,z,vx,vy,vz,mass){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.vx = vx;
|
||||
this.vy = vy;
|
||||
this.vz = vz;
|
||||
this.mass = mass;
|
||||
}
|
||||
|
||||
Body.prototype.offsetMomentum = function(px,py,pz) {
|
||||
this.vx = -px / SOLAR_MASS;
|
||||
this.vy = -py / SOLAR_MASS;
|
||||
this.vz = -pz / SOLAR_MASS;
|
||||
return this;
|
||||
}
|
||||
|
||||
function Jupiter(){
|
||||
return new Body(
|
||||
4.84143144246472090e+00,
|
||||
-1.16032004402742839e+00,
|
||||
-1.03622044471123109e-01,
|
||||
1.66007664274403694e-03 * DAYS_PER_YEAR,
|
||||
7.69901118419740425e-03 * DAYS_PER_YEAR,
|
||||
-6.90460016972063023e-05 * DAYS_PER_YEAR,
|
||||
9.54791938424326609e-04 * SOLAR_MASS
|
||||
);
|
||||
}
|
||||
|
||||
function Saturn(){
|
||||
return new Body(
|
||||
8.34336671824457987e+00,
|
||||
4.12479856412430479e+00,
|
||||
-4.03523417114321381e-01,
|
||||
-2.76742510726862411e-03 * DAYS_PER_YEAR,
|
||||
4.99852801234917238e-03 * DAYS_PER_YEAR,
|
||||
2.30417297573763929e-05 * DAYS_PER_YEAR,
|
||||
2.85885980666130812e-04 * SOLAR_MASS
|
||||
);
|
||||
}
|
||||
|
||||
function Uranus(){
|
||||
return new Body(
|
||||
1.28943695621391310e+01,
|
||||
-1.51111514016986312e+01,
|
||||
-2.23307578892655734e-01,
|
||||
2.96460137564761618e-03 * DAYS_PER_YEAR,
|
||||
2.37847173959480950e-03 * DAYS_PER_YEAR,
|
||||
-2.96589568540237556e-05 * DAYS_PER_YEAR,
|
||||
4.36624404335156298e-05 * SOLAR_MASS
|
||||
);
|
||||
}
|
||||
|
||||
function Neptune(){
|
||||
return new Body(
|
||||
1.53796971148509165e+01,
|
||||
-2.59193146099879641e+01,
|
||||
1.79258772950371181e-01,
|
||||
2.68067772490389322e-03 * DAYS_PER_YEAR,
|
||||
1.62824170038242295e-03 * DAYS_PER_YEAR,
|
||||
-9.51592254519715870e-05 * DAYS_PER_YEAR,
|
||||
5.15138902046611451e-05 * SOLAR_MASS
|
||||
);
|
||||
}
|
||||
|
||||
function Sun(){
|
||||
return new Body(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS);
|
||||
}
|
||||
|
||||
|
||||
function NBodySystem(bodies){
|
||||
this.bodies = bodies;
|
||||
var px = 0.0;
|
||||
var py = 0.0;
|
||||
var pz = 0.0;
|
||||
var size = this.bodies.length;
|
||||
for (var i=0; i<size; i++){
|
||||
var b = this.bodies[i];
|
||||
var m = b.mass;
|
||||
px += b.vx * m;
|
||||
py += b.vy * m;
|
||||
pz += b.vz * m;
|
||||
}
|
||||
this.bodies[0].offsetMomentum(px,py,pz);
|
||||
}
|
||||
|
||||
NBodySystem.prototype.advance = function(dt){
|
||||
var dx, dy, dz, distance, mag;
|
||||
var size = this.bodies.length;
|
||||
|
||||
for (var i=0; i<size; i++) {
|
||||
var bodyi = this.bodies[i];
|
||||
for (var j=i+1; j<size; j++) {
|
||||
var bodyj = this.bodies[j];
|
||||
dx = bodyi.x - bodyj.x;
|
||||
dy = bodyi.y - bodyj.y;
|
||||
dz = bodyi.z - bodyj.z;
|
||||
|
||||
distance = Math.sqrt(dx*dx + dy*dy + dz*dz);
|
||||
mag = dt / (distance * distance * distance);
|
||||
|
||||
bodyi.vx -= dx * bodyj.mass * mag;
|
||||
bodyi.vy -= dy * bodyj.mass * mag;
|
||||
bodyi.vz -= dz * bodyj.mass * mag;
|
||||
|
||||
bodyj.vx += dx * bodyi.mass * mag;
|
||||
bodyj.vy += dy * bodyi.mass * mag;
|
||||
bodyj.vz += dz * bodyi.mass * mag;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i=0; i<size; i++) {
|
||||
var body = this.bodies[i];
|
||||
body.x += dt * body.vx;
|
||||
body.y += dt * body.vy;
|
||||
body.z += dt * body.vz;
|
||||
}
|
||||
}
|
||||
|
||||
NBodySystem.prototype.energy = function(){
|
||||
var dx, dy, dz, distance;
|
||||
var e = 0.0;
|
||||
var size = this.bodies.length;
|
||||
|
||||
for (var i=0; i<size; i++) {
|
||||
var bodyi = this.bodies[i];
|
||||
|
||||
e += 0.5 * bodyi.mass *
|
||||
( bodyi.vx * bodyi.vx
|
||||
+ bodyi.vy * bodyi.vy
|
||||
+ bodyi.vz * bodyi.vz );
|
||||
|
||||
for (var j=i+1; j<size; j++) {
|
||||
var bodyj = this.bodies[j];
|
||||
dx = bodyi.x - bodyj.x;
|
||||
dy = bodyi.y - bodyj.y;
|
||||
dz = bodyi.z - bodyj.z;
|
||||
|
||||
distance = Math.sqrt(dx*dx + dy*dy + dz*dz);
|
||||
e -= (bodyi.mass * bodyj.mass) / distance;
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
var ret;
|
||||
|
||||
for ( var n = 3; n <= 24; n *= 2 ) {
|
||||
(function(){
|
||||
var bodies = new NBodySystem( Array(
|
||||
Sun(),Jupiter(),Saturn(),Uranus(),Neptune()
|
||||
));
|
||||
var max = n * 100;
|
||||
|
||||
ret = bodies.energy();
|
||||
for (var i=0; i<max; i++){
|
||||
bodies.advance(0.01);
|
||||
}
|
||||
ret = bodies.energy();
|
||||
})();
|
||||
}
|
38
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/access-nsieve.js
поставляемый
Normal file
38
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/access-nsieve.js
поставляемый
Normal file
|
@ -0,0 +1,38 @@
|
|||
// The Great Computer Language Shootout
|
||||
// http://shootout.alioth.debian.org/
|
||||
//
|
||||
// modified by Isaac Gouy
|
||||
|
||||
function pad(number,width){
|
||||
var s = number.toString();
|
||||
var prefixWidth = width - s.length;
|
||||
if (prefixWidth>0){
|
||||
for (var i=1; i<=prefixWidth; i++) s = " " + s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function nsieve(m, isPrime){
|
||||
var i, k, count;
|
||||
|
||||
for (i=2; i<=m; i++) { isPrime[i] = true; }
|
||||
count = 0;
|
||||
|
||||
for (i=2; i<=m; i++){
|
||||
if (isPrime[i]) {
|
||||
for (k=i+i; k<=m; k+=i) isPrime[k] = false;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
function sieve() {
|
||||
for (var i = 1; i <= 3; i++ ) {
|
||||
var m = (1<<i)*10000;
|
||||
var flags = Array(m+1);
|
||||
nsieve(m, flags);
|
||||
}
|
||||
}
|
||||
|
||||
sieve();
|
32
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/bitops-3bit-bits-in-byte.js
поставляемый
Normal file
32
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/bitops-3bit-bits-in-byte.js
поставляемый
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2004 by Arthur Langereis (arthur_ext at domain xfinitegames, tld com
|
||||
|
||||
// 1 op = 6 ANDs, 3 SHRs, 3 SHLs, 4 assigns, 2 ADDs
|
||||
// O(1)
|
||||
function fast3bitlookup(b) {
|
||||
var c, bi3b = 0xE994; // 0b1110 1001 1001 0100; // 3 2 2 1 2 1 1 0
|
||||
c = 3 & (bi3b >> ((b << 1) & 14));
|
||||
c += 3 & (bi3b >> ((b >> 2) & 14));
|
||||
c += 3 & (bi3b >> ((b >> 5) & 6));
|
||||
return c;
|
||||
|
||||
/*
|
||||
lir4,0xE994; 9 instructions, no memory access, minimal register dependence, 6 shifts, 2 adds, 1 inline assign
|
||||
rlwinmr5,r3,1,28,30
|
||||
rlwinmr6,r3,30,28,30
|
||||
rlwinmr7,r3,27,29,30
|
||||
rlwnmr8,r4,r5,30,31
|
||||
rlwnmr9,r4,r6,30,31
|
||||
rlwnmr10,r4,r7,30,31
|
||||
addr3,r8,r9
|
||||
addr3,r3,r10
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
function TimeFunc(func) {
|
||||
var x, y, t;
|
||||
for(var x=0; x<500; x++)
|
||||
for(var y=0; y<256; y++) func(y);
|
||||
}
|
||||
|
||||
TimeFunc(fast3bitlookup);
|
21
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/bitops-bits-in-byte.js
поставляемый
Normal file
21
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/bitops-bits-in-byte.js
поставляемый
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) 2004 by Arthur Langereis (arthur_ext at domain xfinitegames, tld com)
|
||||
|
||||
|
||||
// 1 op = 2 assigns, 16 compare/branches, 8 ANDs, (0-8) ADDs, 8 SHLs
|
||||
// O(n)
|
||||
function bitsinbyte(b) {
|
||||
var m = 1, c = 0;
|
||||
while(m<0x100) {
|
||||
if(b & m) c++;
|
||||
m <<= 1;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
function TimeFunc(func) {
|
||||
var x, y, t;
|
||||
for(var x=0; x<350; x++)
|
||||
for(var y=0; y<256; y++) func(y);
|
||||
}
|
||||
|
||||
TimeFunc(bitsinbyte);
|
28
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/bitops-bitwise-and.js
поставляемый
Normal file
28
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/bitops-bitwise-and.js
поставляемый
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
bitwiseAndValue = 4294967296;
|
||||
for (var i = 0; i < 600000; i++)
|
||||
bitwiseAndValue = bitwiseAndValue & i;
|
32
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/bitops-nsieve-bits.js
поставляемый
Normal file
32
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/bitops-nsieve-bits.js
поставляемый
Normal file
|
@ -0,0 +1,32 @@
|
|||
// The Great Computer Language Shootout
|
||||
// http://shootout.alioth.debian.org
|
||||
//
|
||||
// Contributed by Ian Osgood
|
||||
|
||||
function pad(n,width) {
|
||||
var s = n.toString();
|
||||
while (s.length < width) s = ' ' + s;
|
||||
return s;
|
||||
}
|
||||
|
||||
function primes(isPrime, n) {
|
||||
var i, count = 0, m = 10000<<n, size = m+31>>5;
|
||||
|
||||
for (i=0; i<size; i++) isPrime[i] = 0xffffffff;
|
||||
|
||||
for (i=2; i<m; i++)
|
||||
if (isPrime[i>>5] & 1<<(i&31)) {
|
||||
for (var j=i+i; j<m; j+=i)
|
||||
isPrime[j>>5] &= ~(1<<(j&31));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
function sieve() {
|
||||
for (var i = 4; i <= 4; i++) {
|
||||
var isPrime = new Array((10000<<i)+31>>5);
|
||||
primes(isPrime, i);
|
||||
}
|
||||
}
|
||||
|
||||
sieve();
|
25
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/controlflow-recursive.js
поставляемый
Normal file
25
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/controlflow-recursive.js
поставляемый
Normal file
|
@ -0,0 +1,25 @@
|
|||
// The Computer Language Shootout
|
||||
// http://shootout.alioth.debian.org/
|
||||
// contributed by Isaac Gouy
|
||||
|
||||
function ack(m,n){
|
||||
if (m==0) { return n+1; }
|
||||
if (n==0) { return ack(m-1,1); }
|
||||
return ack(m-1, ack(m,n-1) );
|
||||
}
|
||||
|
||||
function fib(n) {
|
||||
if (n < 2){ return 1; }
|
||||
return fib(n-2) + fib(n-1);
|
||||
}
|
||||
|
||||
function tak(x,y,z) {
|
||||
if (y >= x) return z;
|
||||
return tak(tak(x-1,y,z), tak(y-1,z,x), tak(z-1,x,y));
|
||||
}
|
||||
|
||||
for ( var i = 3; i <= 5; i++ ) {
|
||||
ack(3,i);
|
||||
fib(17.0+i);
|
||||
tak(3*i+3,2*i+2,i+1);
|
||||
}
|
422
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/crypto-aes.js
поставляемый
Normal file
422
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/crypto-aes.js
поставляемый
Normal file
|
@ -0,0 +1,422 @@
|
|||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/*
|
||||
* AES Cipher function: encrypt 'input' with Rijndael algorithm
|
||||
*
|
||||
* takes byte-array 'input' (16 bytes)
|
||||
* 2D byte-array key schedule 'w' (Nr+1 x Nb bytes)
|
||||
*
|
||||
* applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage
|
||||
*
|
||||
* returns byte-array encrypted value (16 bytes)
|
||||
*/
|
||||
function Cipher(input, w) { // main Cipher function [§5.1]
|
||||
var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
|
||||
var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
|
||||
|
||||
var state = [[],[],[],[]]; // initialise 4xNb byte-array 'state' with input [§3.4]
|
||||
for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i];
|
||||
|
||||
state = AddRoundKey(state, w, 0, Nb);
|
||||
|
||||
for (var round=1; round<Nr; round++) {
|
||||
state = SubBytes(state, Nb);
|
||||
state = ShiftRows(state, Nb);
|
||||
state = MixColumns(state, Nb);
|
||||
state = AddRoundKey(state, w, round, Nb);
|
||||
}
|
||||
|
||||
state = SubBytes(state, Nb);
|
||||
state = ShiftRows(state, Nb);
|
||||
state = AddRoundKey(state, w, Nr, Nb);
|
||||
|
||||
var output = new Array(4*Nb); // convert state to 1-d array before returning [§3.4]
|
||||
for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)];
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
function SubBytes(s, Nb) { // apply SBox to state S [§5.1.1]
|
||||
for (var r=0; r<4; r++) {
|
||||
for (var c=0; c<Nb; c++) s[r][c] = Sbox[s[r][c]];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
function ShiftRows(s, Nb) { // shift row r of state S left by r bytes [§5.1.2]
|
||||
var t = new Array(4);
|
||||
for (var r=1; r<4; r++) {
|
||||
for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb]; // shift into temp copy
|
||||
for (var c=0; c<4; c++) s[r][c] = t[c]; // and copy back
|
||||
} // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
|
||||
return s; // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
|
||||
}
|
||||
|
||||
|
||||
function MixColumns(s, Nb) { // combine bytes of each col of state S [§5.1.3]
|
||||
for (var c=0; c<4; c++) {
|
||||
var a = new Array(4); // 'a' is a copy of the current column from 's'
|
||||
var b = new Array(4); // 'b' is a•{02} in GF(2^8)
|
||||
for (var i=0; i<4; i++) {
|
||||
a[i] = s[i][c];
|
||||
b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1;
|
||||
}
|
||||
// a[n] ^ b[n] is a•{03} in GF(2^8)
|
||||
s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // 2*a0 + 3*a1 + a2 + a3
|
||||
s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 * 2*a1 + 3*a2 + a3
|
||||
s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + 2*a2 + 3*a3
|
||||
s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // 3*a0 + a1 + a2 + 2*a3
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
function AddRoundKey(state, w, rnd, Nb) { // xor Round Key into state S [§5.1.4]
|
||||
for (var r=0; r<4; r++) {
|
||||
for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r];
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
function KeyExpansion(key) { // generate Key Schedule (byte-array Nr+1 x Nb) from Key [§5.2]
|
||||
var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
|
||||
var Nk = key.length/4 // key length (in words): 4/6/8 for 128/192/256-bit keys
|
||||
var Nr = Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys
|
||||
|
||||
var w = new Array(Nb*(Nr+1));
|
||||
var temp = new Array(4);
|
||||
|
||||
for (var i=0; i<Nk; i++) {
|
||||
var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]];
|
||||
w[i] = r;
|
||||
}
|
||||
|
||||
for (var i=Nk; i<(Nb*(Nr+1)); i++) {
|
||||
w[i] = new Array(4);
|
||||
for (var t=0; t<4; t++) temp[t] = w[i-1][t];
|
||||
if (i % Nk == 0) {
|
||||
temp = SubWord(RotWord(temp));
|
||||
for (var t=0; t<4; t++) temp[t] ^= Rcon[i/Nk][t];
|
||||
} else if (Nk > 6 && i%Nk == 4) {
|
||||
temp = SubWord(temp);
|
||||
}
|
||||
for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t];
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
function SubWord(w) { // apply SBox to 4-byte word w
|
||||
for (var i=0; i<4; i++) w[i] = Sbox[w[i]];
|
||||
return w;
|
||||
}
|
||||
|
||||
function RotWord(w) { // rotate 4-byte word w left by one byte
|
||||
w[4] = w[0];
|
||||
for (var i=0; i<4; i++) w[i] = w[i+1];
|
||||
return w;
|
||||
}
|
||||
|
||||
|
||||
// Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [§5.1.1]
|
||||
var Sbox = [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
|
||||
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
|
||||
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
|
||||
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
|
||||
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
|
||||
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
|
||||
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
|
||||
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
|
||||
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
|
||||
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
|
||||
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
|
||||
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
|
||||
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
|
||||
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
|
||||
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
|
||||
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16];
|
||||
|
||||
// Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2]
|
||||
var Rcon = [ [0x00, 0x00, 0x00, 0x00],
|
||||
[0x01, 0x00, 0x00, 0x00],
|
||||
[0x02, 0x00, 0x00, 0x00],
|
||||
[0x04, 0x00, 0x00, 0x00],
|
||||
[0x08, 0x00, 0x00, 0x00],
|
||||
[0x10, 0x00, 0x00, 0x00],
|
||||
[0x20, 0x00, 0x00, 0x00],
|
||||
[0x40, 0x00, 0x00, 0x00],
|
||||
[0x80, 0x00, 0x00, 0x00],
|
||||
[0x1b, 0x00, 0x00, 0x00],
|
||||
[0x36, 0x00, 0x00, 0x00] ];
|
||||
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/*
|
||||
* Use AES to encrypt 'plaintext' with 'password' using 'nBits' key, in 'Counter' mode of operation
|
||||
* - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||
* for each block
|
||||
* - outputblock = cipher(counter, key)
|
||||
* - cipherblock = plaintext xor outputblock
|
||||
*/
|
||||
function AESEncryptCtr(plaintext, password, nBits) {
|
||||
if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys
|
||||
|
||||
// for this example script, generate the key by applying Cipher to 1st 16/24/32 chars of password;
|
||||
// for real-world applications, a more secure approach would be to hash the password e.g. with SHA-1
|
||||
var nBytes = nBits/8; // no bytes in key
|
||||
var pwBytes = new Array(nBytes);
|
||||
for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
|
||||
var key = Cipher(pwBytes, KeyExpansion(pwBytes));
|
||||
key = key.concat(key.slice(0, nBytes-16)); // key is now 16/24/32 bytes long
|
||||
|
||||
// initialise counter block (NIST SP800-38A §B.2): millisecond time-stamp for nonce in 1st 8 bytes,
|
||||
// block counter in 2nd 8 bytes
|
||||
var blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
|
||||
var counterBlock = new Array(blockSize); // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
|
||||
var nonce = (new Date()).getTime(); // milliseconds since 1-Jan-1970
|
||||
|
||||
// encode nonce in two stages to cater for JavaScript 32-bit limit on bitwise ops
|
||||
for (var i=0; i<4; i++) counterBlock[i] = (nonce >>> i*8) & 0xff;
|
||||
for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff;
|
||||
|
||||
// generate key schedule - an expansion of the key into distinct Key Rounds for each round
|
||||
var keySchedule = KeyExpansion(key);
|
||||
|
||||
var blockCount = Math.ceil(plaintext.length/blockSize);
|
||||
var ciphertext = new Array(blockCount); // ciphertext as array of strings
|
||||
|
||||
for (var b=0; b<blockCount; b++) {
|
||||
// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
|
||||
// again done in two stages for 32-bit ops
|
||||
for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff;
|
||||
for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8)
|
||||
|
||||
var cipherCntr = Cipher(counterBlock, keySchedule); // -- encrypt counter block --
|
||||
|
||||
// calculate length of final block:
|
||||
var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1;
|
||||
|
||||
var ct = '';
|
||||
for (var i=0; i<blockLength; i++) { // -- xor plaintext with ciphered counter byte-by-byte --
|
||||
var plaintextByte = plaintext.charCodeAt(b*blockSize+i);
|
||||
var cipherByte = plaintextByte ^ cipherCntr[i];
|
||||
ct += String.fromCharCode(cipherByte);
|
||||
}
|
||||
// ct is now ciphertext for this block
|
||||
|
||||
ciphertext[b] = escCtrlChars(ct); // escape troublesome characters in ciphertext
|
||||
}
|
||||
|
||||
// convert the nonce to a string to go on the front of the ciphertext
|
||||
var ctrTxt = '';
|
||||
for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]);
|
||||
ctrTxt = escCtrlChars(ctrTxt);
|
||||
|
||||
// use '-' to separate blocks, use Array.join to concatenate arrays of strings for efficiency
|
||||
return ctrTxt + '-' + ciphertext.join('-');
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Use AES to decrypt 'ciphertext' with 'password' using 'nBits' key, in Counter mode of operation
|
||||
*
|
||||
* for each block
|
||||
* - outputblock = cipher(counter, key)
|
||||
* - cipherblock = plaintext xor outputblock
|
||||
*/
|
||||
function AESDecryptCtr(ciphertext, password, nBits) {
|
||||
if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys
|
||||
|
||||
var nBytes = nBits/8; // no bytes in key
|
||||
var pwBytes = new Array(nBytes);
|
||||
for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
|
||||
var pwKeySchedule = KeyExpansion(pwBytes);
|
||||
var key = Cipher(pwBytes, pwKeySchedule);
|
||||
key = key.concat(key.slice(0, nBytes-16)); // key is now 16/24/32 bytes long
|
||||
|
||||
var keySchedule = KeyExpansion(key);
|
||||
|
||||
ciphertext = ciphertext.split('-'); // split ciphertext into array of block-length strings
|
||||
|
||||
// recover nonce from 1st element of ciphertext
|
||||
var blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
|
||||
var counterBlock = new Array(blockSize);
|
||||
var ctrTxt = unescCtrlChars(ciphertext[0]);
|
||||
for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i);
|
||||
|
||||
var plaintext = new Array(ciphertext.length-1);
|
||||
|
||||
for (var b=1; b<ciphertext.length; b++) {
|
||||
// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
|
||||
for (var c=0; c<4; c++) counterBlock[15-c] = ((b-1) >>> c*8) & 0xff;
|
||||
for (var c=0; c<4; c++) counterBlock[15-c-4] = ((b/0x100000000-1) >>> c*8) & 0xff;
|
||||
|
||||
var cipherCntr = Cipher(counterBlock, keySchedule); // encrypt counter block
|
||||
|
||||
ciphertext[b] = unescCtrlChars(ciphertext[b]);
|
||||
|
||||
var pt = '';
|
||||
for (var i=0; i<ciphertext[b].length; i++) {
|
||||
// -- xor plaintext with ciphered counter byte-by-byte --
|
||||
var ciphertextByte = ciphertext[b].charCodeAt(i);
|
||||
var plaintextByte = ciphertextByte ^ cipherCntr[i];
|
||||
pt += String.fromCharCode(plaintextByte);
|
||||
}
|
||||
// pt is now plaintext for this block
|
||||
|
||||
plaintext[b-1] = pt; // b-1 'cos no initial nonce block in plaintext
|
||||
}
|
||||
|
||||
return plaintext.join('');
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
function escCtrlChars(str) { // escape control chars which might cause problems handling ciphertext
|
||||
return str.replace(/[\0\t\n\v\f\r\xa0'"!-]/g, function(c) { return '!' + c.charCodeAt(0) + '!'; });
|
||||
} // \xa0 to cater for bug in Firefox; include '-' to leave it free for use as a block marker
|
||||
|
||||
function unescCtrlChars(str) { // unescape potentially problematic control characters
|
||||
return str.replace(/!\d\d?\d?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); });
|
||||
}
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/*
|
||||
* if escCtrlChars()/unescCtrlChars() still gives problems, use encodeBase64()/decodeBase64() instead
|
||||
*/
|
||||
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
function encodeBase64(str) { // http://tools.ietf.org/html/rfc4648
|
||||
var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';
|
||||
|
||||
str = encodeUTF8(str); // encode multi-byte chars into UTF-8 for byte-array
|
||||
|
||||
do { // pack three octets into four hexets
|
||||
o1 = str.charCodeAt(i++);
|
||||
o2 = str.charCodeAt(i++);
|
||||
o3 = str.charCodeAt(i++);
|
||||
|
||||
bits = o1<<16 | o2<<8 | o3;
|
||||
|
||||
h1 = bits>>18 & 0x3f;
|
||||
h2 = bits>>12 & 0x3f;
|
||||
h3 = bits>>6 & 0x3f;
|
||||
h4 = bits & 0x3f;
|
||||
|
||||
// end of string? index to '=' in b64
|
||||
if (isNaN(o3)) h4 = 64;
|
||||
if (isNaN(o2)) h3 = 64;
|
||||
|
||||
// use hexets to index into b64, and append result to encoded string
|
||||
enc += b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
|
||||
} while (i < str.length);
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
function decodeBase64(str) {
|
||||
var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';
|
||||
|
||||
do { // unpack four hexets into three octets using index points in b64
|
||||
h1 = b64.indexOf(str.charAt(i++));
|
||||
h2 = b64.indexOf(str.charAt(i++));
|
||||
h3 = b64.indexOf(str.charAt(i++));
|
||||
h4 = b64.indexOf(str.charAt(i++));
|
||||
|
||||
bits = h1<<18 | h2<<12 | h3<<6 | h4;
|
||||
|
||||
o1 = bits>>16 & 0xff;
|
||||
o2 = bits>>8 & 0xff;
|
||||
o3 = bits & 0xff;
|
||||
|
||||
if (h3 == 64) enc += String.fromCharCode(o1);
|
||||
else if (h4 == 64) enc += String.fromCharCode(o1, o2);
|
||||
else enc += String.fromCharCode(o1, o2, o3);
|
||||
} while (i < str.length);
|
||||
|
||||
return decodeUTF8(enc); // decode UTF-8 byte-array back to Unicode
|
||||
}
|
||||
|
||||
function encodeUTF8(str) { // encode multi-byte string into utf-8 multiple single-byte characters
|
||||
str = str.replace(
|
||||
/[\u0080-\u07ff]/g, // U+0080 - U+07FF = 2-byte chars
|
||||
function(c) {
|
||||
var cc = c.charCodeAt(0);
|
||||
return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); }
|
||||
);
|
||||
str = str.replace(
|
||||
/[\u0800-\uffff]/g, // U+0800 - U+FFFF = 3-byte chars
|
||||
function(c) {
|
||||
var cc = c.charCodeAt(0);
|
||||
return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); }
|
||||
);
|
||||
return str;
|
||||
}
|
||||
|
||||
function decodeUTF8(str) { // decode utf-8 encoded string back into multi-byte characters
|
||||
str = str.replace(
|
||||
/[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars
|
||||
function(c) {
|
||||
var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f;
|
||||
return String.fromCharCode(cc); }
|
||||
);
|
||||
str = str.replace(
|
||||
/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars
|
||||
function(c) {
|
||||
var cc = (c.charCodeAt(0)&0x0f)<<12 | (c.charCodeAt(1)&0x3f<<6) | c.charCodeAt(2)&0x3f;
|
||||
return String.fromCharCode(cc); }
|
||||
);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
function byteArrayToHexStr(b) { // convert byte array to hex string for displaying test vectors
|
||||
var s = '';
|
||||
for (var i=0; i<b.length; i++) s += b[i].toString(16) + ' ';
|
||||
return s;
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
var plainText = "ROMEO: But, soft! what light through yonder window breaks?\n\
|
||||
It is the east, and Juliet is the sun.\n\
|
||||
Arise, fair sun, and kill the envious moon,\n\
|
||||
Who is already sick and pale with grief,\n\
|
||||
That thou her maid art far more fair than she:\n\
|
||||
Be not her maid, since she is envious;\n\
|
||||
Her vestal livery is but sick and green\n\
|
||||
And none but fools do wear it; cast it off.\n\
|
||||
It is my lady, O, it is my love!\n\
|
||||
O, that she knew she were!\n\
|
||||
She speaks yet she says nothing: what of that?\n\
|
||||
Her eye discourses; I will answer it.\n\
|
||||
I am too bold, 'tis not to me she speaks:\n\
|
||||
Two of the fairest stars in all the heaven,\n\
|
||||
Having some business, do entreat her eyes\n\
|
||||
To twinkle in their spheres till they return.\n\
|
||||
What if her eyes were there, they in her head?\n\
|
||||
The brightness of her cheek would shame those stars,\n\
|
||||
As daylight doth a lamp; her eyes in heaven\n\
|
||||
Would through the airy region stream so bright\n\
|
||||
That birds would sing and think it were not night.\n\
|
||||
See, how she leans her cheek upon her hand!\n\
|
||||
O, that I were a glove upon that hand,\n\
|
||||
That I might touch that cheek!\n\
|
||||
JULIET: Ay me!\n\
|
||||
ROMEO: She speaks:\n\
|
||||
O, speak again, bright angel! for thou art\n\
|
||||
As glorious to this night, being o'er my head\n\
|
||||
As is a winged messenger of heaven\n\
|
||||
Unto the white-upturned wondering eyes\n\
|
||||
Of mortals that fall back to gaze on him\n\
|
||||
When he bestrides the lazy-pacing clouds\n\
|
||||
And sails upon the bosom of the air.";
|
||||
|
||||
var password = "O Romeo, Romeo! wherefore art thou Romeo?";
|
||||
|
||||
var cipherText = AESEncryptCtr(plainText, password, 256);
|
||||
var decryptedText = AESDecryptCtr(cipherText, password, 256);
|
286
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/crypto-md5.js
поставляемый
Normal file
286
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/crypto-md5.js
поставляемый
Normal file
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
||||
* Digest Algorithm, as defined in RFC 1321.
|
||||
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
|
||||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
||||
* Distributed under the BSD License
|
||||
* See http://pajhome.org.uk/crypt/md5 for more info.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Configurable variables. You may need to tweak these to be compatible with
|
||||
* the server-side, but the defaults work in most cases.
|
||||
*/
|
||||
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
|
||||
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
|
||||
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
|
||||
|
||||
/*
|
||||
* These are the functions you'll usually want to call
|
||||
* They take string arguments and return either hex or base-64 encoded strings
|
||||
*/
|
||||
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
|
||||
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
|
||||
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
|
||||
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
|
||||
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
|
||||
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
|
||||
|
||||
/*
|
||||
* Perform a simple self-test to see if the VM is working
|
||||
*/
|
||||
function md5_vm_test()
|
||||
{
|
||||
return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the MD5 of an array of little-endian words, and a bit length
|
||||
*/
|
||||
function core_md5(x, len)
|
||||
{
|
||||
/* append padding */
|
||||
x[len >> 5] |= 0x80 << ((len) % 32);
|
||||
x[(((len + 64) >>> 9) << 4) + 14] = len;
|
||||
|
||||
var a = 1732584193;
|
||||
var b = -271733879;
|
||||
var c = -1732584194;
|
||||
var d = 271733878;
|
||||
|
||||
for(var i = 0; i < x.length; i += 16)
|
||||
{
|
||||
var olda = a;
|
||||
var oldb = b;
|
||||
var oldc = c;
|
||||
var oldd = d;
|
||||
|
||||
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
|
||||
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
|
||||
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
|
||||
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
|
||||
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
|
||||
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
|
||||
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
|
||||
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
|
||||
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
|
||||
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
|
||||
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
|
||||
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
|
||||
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
|
||||
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
|
||||
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
|
||||
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
|
||||
|
||||
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
|
||||
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
|
||||
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
|
||||
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
|
||||
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
|
||||
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
|
||||
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
|
||||
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
|
||||
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
|
||||
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
|
||||
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
|
||||
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
|
||||
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
|
||||
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
|
||||
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
|
||||
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
|
||||
|
||||
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
|
||||
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
|
||||
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
|
||||
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
|
||||
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
|
||||
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
|
||||
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
|
||||
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
|
||||
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
|
||||
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
|
||||
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
|
||||
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
|
||||
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
|
||||
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
|
||||
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
|
||||
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
|
||||
|
||||
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
|
||||
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
|
||||
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
|
||||
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
|
||||
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
|
||||
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
|
||||
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
|
||||
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
|
||||
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
|
||||
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
|
||||
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
|
||||
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
|
||||
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
|
||||
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
|
||||
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
|
||||
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
|
||||
|
||||
a = safe_add(a, olda);
|
||||
b = safe_add(b, oldb);
|
||||
c = safe_add(c, oldc);
|
||||
d = safe_add(d, oldd);
|
||||
}
|
||||
return Array(a, b, c, d);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions implement the four basic operations the algorithm uses.
|
||||
*/
|
||||
function md5_cmn(q, a, b, x, s, t)
|
||||
{
|
||||
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
|
||||
}
|
||||
function md5_ff(a, b, c, d, x, s, t)
|
||||
{
|
||||
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
|
||||
}
|
||||
function md5_gg(a, b, c, d, x, s, t)
|
||||
{
|
||||
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
|
||||
}
|
||||
function md5_hh(a, b, c, d, x, s, t)
|
||||
{
|
||||
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
|
||||
}
|
||||
function md5_ii(a, b, c, d, x, s, t)
|
||||
{
|
||||
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the HMAC-MD5, of a key and some data
|
||||
*/
|
||||
function core_hmac_md5(key, data)
|
||||
{
|
||||
var bkey = str2binl(key);
|
||||
if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
|
||||
|
||||
var ipad = Array(16), opad = Array(16);
|
||||
for(var i = 0; i < 16; i++)
|
||||
{
|
||||
ipad[i] = bkey[i] ^ 0x36363636;
|
||||
opad[i] = bkey[i] ^ 0x5C5C5C5C;
|
||||
}
|
||||
|
||||
var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
|
||||
return core_md5(opad.concat(hash), 512 + 128);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
||||
* to work around bugs in some JS interpreters.
|
||||
*/
|
||||
function safe_add(x, y)
|
||||
{
|
||||
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
||||
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
||||
return (msw << 16) | (lsw & 0xFFFF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bitwise rotate a 32-bit number to the left.
|
||||
*/
|
||||
function bit_rol(num, cnt)
|
||||
{
|
||||
return (num << cnt) | (num >>> (32 - cnt));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a string to an array of little-endian words
|
||||
* If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
|
||||
*/
|
||||
function str2binl(str)
|
||||
{
|
||||
var bin = Array();
|
||||
var mask = (1 << chrsz) - 1;
|
||||
for(var i = 0; i < str.length * chrsz; i += chrsz)
|
||||
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
|
||||
return bin;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of little-endian words to a string
|
||||
*/
|
||||
function binl2str(bin)
|
||||
{
|
||||
var str = "";
|
||||
var mask = (1 << chrsz) - 1;
|
||||
for(var i = 0; i < bin.length * 32; i += chrsz)
|
||||
str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of little-endian words to a hex string.
|
||||
*/
|
||||
function binl2hex(binarray)
|
||||
{
|
||||
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||
var str = "";
|
||||
for(var i = 0; i < binarray.length * 4; i++)
|
||||
{
|
||||
str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
|
||||
hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of little-endian words to a base-64 string
|
||||
*/
|
||||
function binl2b64(binarray)
|
||||
{
|
||||
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
var str = "";
|
||||
for(var i = 0; i < binarray.length * 4; i += 3)
|
||||
{
|
||||
var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
|
||||
| (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
|
||||
| ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
|
||||
for(var j = 0; j < 4; j++)
|
||||
{
|
||||
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
|
||||
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
var plainText = "Rebellious subjects, enemies to peace,\n\
|
||||
Profaners of this neighbour-stained steel,--\n\
|
||||
Will they not hear? What, ho! you men, you beasts,\n\
|
||||
That quench the fire of your pernicious rage\n\
|
||||
With purple fountains issuing from your veins,\n\
|
||||
On pain of torture, from those bloody hands\n\
|
||||
Throw your mistemper'd weapons to the ground,\n\
|
||||
And hear the sentence of your moved prince.\n\
|
||||
Three civil brawls, bred of an airy word,\n\
|
||||
By thee, old Capulet, and Montague,\n\
|
||||
Have thrice disturb'd the quiet of our streets,\n\
|
||||
And made Verona's ancient citizens\n\
|
||||
Cast by their grave beseeming ornaments,\n\
|
||||
To wield old partisans, in hands as old,\n\
|
||||
Canker'd with peace, to part your canker'd hate:\n\
|
||||
If ever you disturb our streets again,\n\
|
||||
Your lives shall pay the forfeit of the peace.\n\
|
||||
For this time, all the rest depart away:\n\
|
||||
You Capulet; shall go along with me:\n\
|
||||
And, Montague, come you this afternoon,\n\
|
||||
To know our further pleasure in this case,\n\
|
||||
To old Free-town, our common judgment-place.\n\
|
||||
Once more, on pain of death, all men depart."
|
||||
|
||||
for (var i = 0; i <4; i++) {
|
||||
plainText += plainText;
|
||||
}
|
||||
|
||||
var md5Output = hex_md5(plainText);
|
224
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/crypto-sha1.js
поставляемый
Normal file
224
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/crypto-sha1.js
поставляемый
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
|
||||
* in FIPS PUB 180-1
|
||||
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
|
||||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
||||
* Distributed under the BSD License
|
||||
* See http://pajhome.org.uk/crypt/md5 for details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Configurable variables. You may need to tweak these to be compatible with
|
||||
* the server-side, but the defaults work in most cases.
|
||||
*/
|
||||
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
|
||||
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
|
||||
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
|
||||
|
||||
/*
|
||||
* These are the functions you'll usually want to call
|
||||
* They take string arguments and return either hex or base-64 encoded strings
|
||||
*/
|
||||
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
|
||||
function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
|
||||
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
|
||||
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
|
||||
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
|
||||
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
|
||||
|
||||
/*
|
||||
* Perform a simple self-test to see if the VM is working
|
||||
*/
|
||||
function sha1_vm_test()
|
||||
{
|
||||
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the SHA-1 of an array of big-endian words, and a bit length
|
||||
*/
|
||||
function core_sha1(x, len)
|
||||
{
|
||||
/* append padding */
|
||||
x[len >> 5] |= 0x80 << (24 - len % 32);
|
||||
x[((len + 64 >> 9) << 4) + 15] = len;
|
||||
|
||||
var w = Array(80);
|
||||
var a = 1732584193;
|
||||
var b = -271733879;
|
||||
var c = -1732584194;
|
||||
var d = 271733878;
|
||||
var e = -1009589776;
|
||||
|
||||
for(var i = 0; i < x.length; i += 16)
|
||||
{
|
||||
var olda = a;
|
||||
var oldb = b;
|
||||
var oldc = c;
|
||||
var oldd = d;
|
||||
var olde = e;
|
||||
|
||||
for(var j = 0; j < 80; j++)
|
||||
{
|
||||
if(j < 16) w[j] = x[i + j];
|
||||
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
|
||||
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
|
||||
safe_add(safe_add(e, w[j]), sha1_kt(j)));
|
||||
e = d;
|
||||
d = c;
|
||||
c = rol(b, 30);
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
|
||||
a = safe_add(a, olda);
|
||||
b = safe_add(b, oldb);
|
||||
c = safe_add(c, oldc);
|
||||
d = safe_add(d, oldd);
|
||||
e = safe_add(e, olde);
|
||||
}
|
||||
return Array(a, b, c, d, e);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the appropriate triplet combination function for the current
|
||||
* iteration
|
||||
*/
|
||||
function sha1_ft(t, b, c, d)
|
||||
{
|
||||
if(t < 20) return (b & c) | ((~b) & d);
|
||||
if(t < 40) return b ^ c ^ d;
|
||||
if(t < 60) return (b & c) | (b & d) | (c & d);
|
||||
return b ^ c ^ d;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the appropriate additive constant for the current iteration
|
||||
*/
|
||||
function sha1_kt(t)
|
||||
{
|
||||
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
|
||||
(t < 60) ? -1894007588 : -899497514;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the HMAC-SHA1 of a key and some data
|
||||
*/
|
||||
function core_hmac_sha1(key, data)
|
||||
{
|
||||
var bkey = str2binb(key);
|
||||
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
|
||||
|
||||
var ipad = Array(16), opad = Array(16);
|
||||
for(var i = 0; i < 16; i++)
|
||||
{
|
||||
ipad[i] = bkey[i] ^ 0x36363636;
|
||||
opad[i] = bkey[i] ^ 0x5C5C5C5C;
|
||||
}
|
||||
|
||||
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
|
||||
return core_sha1(opad.concat(hash), 512 + 160);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
||||
* to work around bugs in some JS interpreters.
|
||||
*/
|
||||
function safe_add(x, y)
|
||||
{
|
||||
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
||||
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
||||
return (msw << 16) | (lsw & 0xFFFF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bitwise rotate a 32-bit number to the left.
|
||||
*/
|
||||
function rol(num, cnt)
|
||||
{
|
||||
return (num << cnt) | (num >>> (32 - cnt));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an 8-bit or 16-bit string to an array of big-endian words
|
||||
* In 8-bit function, characters >255 have their hi-byte silently ignored.
|
||||
*/
|
||||
function str2binb(str)
|
||||
{
|
||||
var bin = Array();
|
||||
var mask = (1 << chrsz) - 1;
|
||||
for(var i = 0; i < str.length * chrsz; i += chrsz)
|
||||
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
|
||||
return bin;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of big-endian words to a string
|
||||
*/
|
||||
function binb2str(bin)
|
||||
{
|
||||
var str = "";
|
||||
var mask = (1 << chrsz) - 1;
|
||||
for(var i = 0; i < bin.length * 32; i += chrsz)
|
||||
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of big-endian words to a hex string.
|
||||
*/
|
||||
function binb2hex(binarray)
|
||||
{
|
||||
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||
var str = "";
|
||||
for(var i = 0; i < binarray.length * 4; i++)
|
||||
{
|
||||
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
|
||||
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of big-endian words to a base-64 string
|
||||
*/
|
||||
function binb2b64(binarray)
|
||||
{
|
||||
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
var str = "";
|
||||
for(var i = 0; i < binarray.length * 4; i += 3)
|
||||
{
|
||||
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
|
||||
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
|
||||
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
|
||||
for(var j = 0; j < 4; j++)
|
||||
{
|
||||
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
|
||||
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
var plainText = "Two households, both alike in dignity,\n\
|
||||
In fair Verona, where we lay our scene,\n\
|
||||
From ancient grudge break to new mutiny,\n\
|
||||
Where civil blood makes civil hands unclean.\n\
|
||||
From forth the fatal loins of these two foes\n\
|
||||
A pair of star-cross'd lovers take their life;\n\
|
||||
Whole misadventured piteous overthrows\n\
|
||||
Do with their death bury their parents' strife.\n\
|
||||
The fearful passage of their death-mark'd love,\n\
|
||||
And the continuance of their parents' rage,\n\
|
||||
Which, but their children's end, nought could remove,\n\
|
||||
Is now the two hours' traffic of our stage;\n\
|
||||
The which if you with patient ears attend,\n\
|
||||
What here shall miss, our toil shall strive to mend.";
|
||||
|
||||
for (var i = 0; i <4; i++) {
|
||||
plainText += plainText;
|
||||
}
|
||||
|
||||
var sha1Output = hex_sha1(plainText);
|
299
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/date-format-tofte.js
поставляемый
Normal file
299
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/date-format-tofte.js
поставляемый
Normal file
|
@ -0,0 +1,299 @@
|
|||
function arrayExists(array, x) {
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
if (array[i] == x) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Date.prototype.formatDate = function (input,time) {
|
||||
// formatDate :
|
||||
// a PHP date like function, for formatting date strings
|
||||
// See: http://www.php.net/date
|
||||
//
|
||||
// input : format string
|
||||
// time : epoch time (seconds, and optional)
|
||||
//
|
||||
// if time is not passed, formatting is based on
|
||||
// the current "this" date object's set time.
|
||||
//
|
||||
// supported:
|
||||
// a, A, B, d, D, F, g, G, h, H, i, j, l (lowercase L), L,
|
||||
// m, M, n, O, r, s, S, t, U, w, W, y, Y, z
|
||||
//
|
||||
// unsupported:
|
||||
// I (capital i), T, Z
|
||||
|
||||
var switches = ["a", "A", "B", "d", "D", "F", "g", "G", "h", "H",
|
||||
"i", "j", "l", "L", "m", "M", "n", "O", "r", "s",
|
||||
"S", "t", "U", "w", "W", "y", "Y", "z"];
|
||||
var daysLong = ["Sunday", "Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday"];
|
||||
var daysShort = ["Sun", "Mon", "Tue", "Wed",
|
||||
"Thu", "Fri", "Sat"];
|
||||
var monthsShort = ["Jan", "Feb", "Mar", "Apr",
|
||||
"May", "Jun", "Jul", "Aug", "Sep",
|
||||
"Oct", "Nov", "Dec"];
|
||||
var monthsLong = ["January", "February", "March", "April",
|
||||
"May", "June", "July", "August", "September",
|
||||
"October", "November", "December"];
|
||||
var daysSuffix = ["st", "nd", "rd", "th", "th", "th", "th", // 1st - 7th
|
||||
"th", "th", "th", "th", "th", "th", "th", // 8th - 14th
|
||||
"th", "th", "th", "th", "th", "th", "st", // 15th - 21st
|
||||
"nd", "rd", "th", "th", "th", "th", "th", // 22nd - 28th
|
||||
"th", "th", "st"]; // 29th - 31st
|
||||
|
||||
function a() {
|
||||
// Lowercase Ante meridiem and Post meridiem
|
||||
return self.getHours() > 11? "pm" : "am";
|
||||
}
|
||||
function A() {
|
||||
// Uppercase Ante meridiem and Post meridiem
|
||||
return self.getHours() > 11? "PM" : "AM";
|
||||
}
|
||||
|
||||
function B(){
|
||||
// Swatch internet time. code simply grabbed from ppk,
|
||||
// since I was feeling lazy:
|
||||
// http://www.xs4all.nl/~ppk/js/beat.html
|
||||
var off = (self.getTimezoneOffset() + 60)*60;
|
||||
var theSeconds = (self.getHours() * 3600) +
|
||||
(self.getMinutes() * 60) +
|
||||
self.getSeconds() + off;
|
||||
var beat = Math.floor(theSeconds/86.4);
|
||||
if (beat > 1000) beat -= 1000;
|
||||
if (beat < 0) beat += 1000;
|
||||
if ((""+beat).length == 1) beat = "00"+beat;
|
||||
if ((""+beat).length == 2) beat = "0"+beat;
|
||||
return beat;
|
||||
}
|
||||
|
||||
function d() {
|
||||
// Day of the month, 2 digits with leading zeros
|
||||
return new String(self.getDate()).length == 1?
|
||||
"0"+self.getDate() : self.getDate();
|
||||
}
|
||||
function D() {
|
||||
// A textual representation of a day, three letters
|
||||
return daysShort[self.getDay()];
|
||||
}
|
||||
function F() {
|
||||
// A full textual representation of a month
|
||||
return monthsLong[self.getMonth()];
|
||||
}
|
||||
function g() {
|
||||
// 12-hour format of an hour without leading zeros
|
||||
return self.getHours() > 12? self.getHours()-12 : self.getHours();
|
||||
}
|
||||
function G() {
|
||||
// 24-hour format of an hour without leading zeros
|
||||
return self.getHours();
|
||||
}
|
||||
function h() {
|
||||
// 12-hour format of an hour with leading zeros
|
||||
if (self.getHours() > 12) {
|
||||
var s = new String(self.getHours()-12);
|
||||
return s.length == 1?
|
||||
"0"+ (self.getHours()-12) : self.getHours()-12;
|
||||
} else {
|
||||
var s = new String(self.getHours());
|
||||
return s.length == 1?
|
||||
"0"+self.getHours() : self.getHours();
|
||||
}
|
||||
}
|
||||
function H() {
|
||||
// 24-hour format of an hour with leading zeros
|
||||
return new String(self.getHours()).length == 1?
|
||||
"0"+self.getHours() : self.getHours();
|
||||
}
|
||||
function i() {
|
||||
// Minutes with leading zeros
|
||||
return new String(self.getMinutes()).length == 1?
|
||||
"0"+self.getMinutes() : self.getMinutes();
|
||||
}
|
||||
function j() {
|
||||
// Day of the month without leading zeros
|
||||
return self.getDate();
|
||||
}
|
||||
function l() {
|
||||
// A full textual representation of the day of the week
|
||||
return daysLong[self.getDay()];
|
||||
}
|
||||
function L() {
|
||||
// leap year or not. 1 if leap year, 0 if not.
|
||||
// the logic should match iso's 8601 standard.
|
||||
var y_ = Y();
|
||||
if (
|
||||
(y_ % 4 == 0 && y_ % 100 != 0) ||
|
||||
(y_ % 4 == 0 && y_ % 100 == 0 && y_ % 400 == 0)
|
||||
) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
function m() {
|
||||
// Numeric representation of a month, with leading zeros
|
||||
return self.getMonth() < 9?
|
||||
"0"+(self.getMonth()+1) :
|
||||
self.getMonth()+1;
|
||||
}
|
||||
function M() {
|
||||
// A short textual representation of a month, three letters
|
||||
return monthsShort[self.getMonth()];
|
||||
}
|
||||
function n() {
|
||||
// Numeric representation of a month, without leading zeros
|
||||
return self.getMonth()+1;
|
||||
}
|
||||
function O() {
|
||||
// Difference to Greenwich time (GMT) in hours
|
||||
var os = Math.abs(self.getTimezoneOffset());
|
||||
var h = ""+Math.floor(os/60);
|
||||
var m = ""+(os%60);
|
||||
h.length == 1? h = "0"+h:1;
|
||||
m.length == 1? m = "0"+m:1;
|
||||
return self.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m;
|
||||
}
|
||||
function r() {
|
||||
// RFC 822 formatted date
|
||||
var r; // result
|
||||
// Thu , 21 Dec 2000
|
||||
r = D() + ", " + j() + " " + M() + " " + Y() +
|
||||
// 16 : 01 : 07 +0200
|
||||
" " + H() + ":" + i() + ":" + s() + " " + O();
|
||||
return r;
|
||||
}
|
||||
function S() {
|
||||
// English ordinal suffix for the day of the month, 2 characters
|
||||
return daysSuffix[self.getDate()-1];
|
||||
}
|
||||
function s() {
|
||||
// Seconds, with leading zeros
|
||||
return new String(self.getSeconds()).length == 1?
|
||||
"0"+self.getSeconds() : self.getSeconds();
|
||||
}
|
||||
function t() {
|
||||
|
||||
// thanks to Matt Bannon for some much needed code-fixes here!
|
||||
var daysinmonths = [null,31,28,31,30,31,30,31,31,30,31,30,31];
|
||||
if (L()==1 && n()==2) return 29; // leap day
|
||||
return daysinmonths[n()];
|
||||
}
|
||||
function U() {
|
||||
// Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
|
||||
return Math.round(self.getTime()/1000);
|
||||
}
|
||||
function W() {
|
||||
// Weeknumber, as per ISO specification:
|
||||
// http://www.cl.cam.ac.uk/~mgk25/iso-time.html
|
||||
|
||||
// if the day is three days before newyears eve,
|
||||
// there's a chance it's "week 1" of next year.
|
||||
// here we check for that.
|
||||
var beforeNY = 364+L() - z();
|
||||
var afterNY = z();
|
||||
var weekday = w()!=0?w()-1:6; // makes sunday (0), into 6.
|
||||
if (beforeNY <= 2 && weekday <= 2-beforeNY) {
|
||||
return 1;
|
||||
}
|
||||
// similarly, if the day is within threedays of newyears
|
||||
// there's a chance it belongs in the old year.
|
||||
var ny = new Date("January 1 " + Y() + " 00:00:00");
|
||||
var nyDay = ny.getDay()!=0?ny.getDay()-1:6;
|
||||
if (
|
||||
(afterNY <= 2) &&
|
||||
(nyDay >=4) &&
|
||||
(afterNY >= (6-nyDay))
|
||||
) {
|
||||
// Since I'm not sure we can just always return 53,
|
||||
// i call the function here again, using the last day
|
||||
// of the previous year, as the date, and then just
|
||||
// return that week.
|
||||
var prevNY = new Date("December 31 " + (Y()-1) + " 00:00:00");
|
||||
return prevNY.formatDate("W");
|
||||
}
|
||||
|
||||
// week 1, is the week that has the first thursday in it.
|
||||
// note that this value is not zero index.
|
||||
if (nyDay <= 3) {
|
||||
// first day of the year fell on a thursday, or earlier.
|
||||
return 1 + Math.floor( ( z() + nyDay ) / 7 );
|
||||
} else {
|
||||
// first day of the year fell on a friday, or later.
|
||||
return 1 + Math.floor( ( z() - ( 7 - nyDay ) ) / 7 );
|
||||
}
|
||||
}
|
||||
function w() {
|
||||
// Numeric representation of the day of the week
|
||||
return self.getDay();
|
||||
}
|
||||
|
||||
function Y() {
|
||||
// A full numeric representation of a year, 4 digits
|
||||
|
||||
// we first check, if getFullYear is supported. if it
|
||||
// is, we just use that. ppks code is nice, but wont
|
||||
// work with dates outside 1900-2038, or something like that
|
||||
if (self.getFullYear) {
|
||||
var newDate = new Date("January 1 2001 00:00:00 +0000");
|
||||
var x = newDate .getFullYear();
|
||||
if (x == 2001) {
|
||||
// i trust the method now
|
||||
return self.getFullYear();
|
||||
}
|
||||
}
|
||||
// else, do this:
|
||||
// codes thanks to ppk:
|
||||
// http://www.xs4all.nl/~ppk/js/introdate.html
|
||||
var x = self.getYear();
|
||||
var y = x % 100;
|
||||
y += (y < 38) ? 2000 : 1900;
|
||||
return y;
|
||||
}
|
||||
function y() {
|
||||
// A two-digit representation of a year
|
||||
var y = Y()+"";
|
||||
return y.substring(y.length-2,y.length);
|
||||
}
|
||||
function z() {
|
||||
// The day of the year, zero indexed! 0 through 366
|
||||
var t = new Date("January 1 " + Y() + " 00:00:00");
|
||||
var diff = self.getTime() - t.getTime();
|
||||
return Math.floor(diff/1000/60/60/24);
|
||||
}
|
||||
|
||||
var self = this;
|
||||
if (time) {
|
||||
// save time
|
||||
var prevTime = self.getTime();
|
||||
self.setTime(time);
|
||||
}
|
||||
|
||||
var ia = input.split("");
|
||||
var ij = 0;
|
||||
while (ia[ij]) {
|
||||
if (ia[ij] == "\\") {
|
||||
// this is our way of allowing users to escape stuff
|
||||
ia.splice(ij,1);
|
||||
} else {
|
||||
if (arrayExists(switches,ia[ij])) {
|
||||
ia[ij] = eval(ia[ij] + "()");
|
||||
}
|
||||
}
|
||||
ij++;
|
||||
}
|
||||
// reset time, back to what it was
|
||||
if (prevTime) {
|
||||
self.setTime(prevTime);
|
||||
}
|
||||
return ia.join("");
|
||||
}
|
||||
|
||||
var date = new Date("1/1/2007 1:11:11");
|
||||
|
||||
for (i = 0; i < 500; ++i) {
|
||||
var shortFormat = date.formatDate("Y-m-d");
|
||||
var longFormat = date.formatDate("l, F d, Y g:i:s A");
|
||||
date.setTime(date.getTime() + 84266956);
|
||||
}
|
||||
|
417
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/date-format-xparb.js
поставляемый
Normal file
417
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/date-format-xparb.js
поставляемый
Normal file
|
@ -0,0 +1,417 @@
|
|||
/*
|
||||
* Copyright (C) 2004 Baron Schwartz <baron at sequent dot org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, version 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
Date.parseFunctions = {count:0};
|
||||
Date.parseRegexes = [];
|
||||
Date.formatFunctions = {count:0};
|
||||
|
||||
Date.prototype.dateFormat = function(format) {
|
||||
if (Date.formatFunctions[format] == null) {
|
||||
Date.createNewFormat(format);
|
||||
}
|
||||
var func = Date.formatFunctions[format];
|
||||
return this[func]();
|
||||
}
|
||||
|
||||
Date.createNewFormat = function(format) {
|
||||
var funcName = "format" + Date.formatFunctions.count++;
|
||||
Date.formatFunctions[format] = funcName;
|
||||
var code = "Date.prototype." + funcName + " = function(){return ";
|
||||
var special = false;
|
||||
var ch = '';
|
||||
for (var i = 0; i < format.length; ++i) {
|
||||
ch = format.charAt(i);
|
||||
if (!special && ch == "\\") {
|
||||
special = true;
|
||||
}
|
||||
else if (special) {
|
||||
special = false;
|
||||
code += "'" + String.escape(ch) + "' + ";
|
||||
}
|
||||
else {
|
||||
code += Date.getFormatCode(ch);
|
||||
}
|
||||
}
|
||||
eval(code.substring(0, code.length - 3) + ";}");
|
||||
}
|
||||
|
||||
Date.getFormatCode = function(character) {
|
||||
switch (character) {
|
||||
case "d":
|
||||
return "String.leftPad(this.getDate(), 2, '0') + ";
|
||||
case "D":
|
||||
return "Date.dayNames[this.getDay()].substring(0, 3) + ";
|
||||
case "j":
|
||||
return "this.getDate() + ";
|
||||
case "l":
|
||||
return "Date.dayNames[this.getDay()] + ";
|
||||
case "S":
|
||||
return "this.getSuffix() + ";
|
||||
case "w":
|
||||
return "this.getDay() + ";
|
||||
case "z":
|
||||
return "this.getDayOfYear() + ";
|
||||
case "W":
|
||||
return "this.getWeekOfYear() + ";
|
||||
case "F":
|
||||
return "Date.monthNames[this.getMonth()] + ";
|
||||
case "m":
|
||||
return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
|
||||
case "M":
|
||||
return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
|
||||
case "n":
|
||||
return "(this.getMonth() + 1) + ";
|
||||
case "t":
|
||||
return "this.getDaysInMonth() + ";
|
||||
case "L":
|
||||
return "(this.isLeapYear() ? 1 : 0) + ";
|
||||
case "Y":
|
||||
return "this.getFullYear() + ";
|
||||
case "y":
|
||||
return "('' + this.getFullYear()).substring(2, 4) + ";
|
||||
case "a":
|
||||
return "(this.getHours() < 12 ? 'am' : 'pm') + ";
|
||||
case "A":
|
||||
return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
|
||||
case "g":
|
||||
return "((this.getHours() %12) ? this.getHours() % 12 : 12) + ";
|
||||
case "G":
|
||||
return "this.getHours() + ";
|
||||
case "h":
|
||||
return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + ";
|
||||
case "H":
|
||||
return "String.leftPad(this.getHours(), 2, '0') + ";
|
||||
case "i":
|
||||
return "String.leftPad(this.getMinutes(), 2, '0') + ";
|
||||
case "s":
|
||||
return "String.leftPad(this.getSeconds(), 2, '0') + ";
|
||||
case "O":
|
||||
return "this.getGMTOffset() + ";
|
||||
case "T":
|
||||
return "this.getTimezone() + ";
|
||||
case "Z":
|
||||
return "(this.getTimezoneOffset() * -60) + ";
|
||||
default:
|
||||
return "'" + String.escape(character) + "' + ";
|
||||
}
|
||||
}
|
||||
|
||||
Date.parseDate = function(input, format) {
|
||||
if (Date.parseFunctions[format] == null) {
|
||||
Date.createParser(format);
|
||||
}
|
||||
var func = Date.parseFunctions[format];
|
||||
return Date[func](input);
|
||||
}
|
||||
|
||||
Date.createParser = function(format) {
|
||||
var funcName = "parse" + Date.parseFunctions.count++;
|
||||
var regexNum = Date.parseRegexes.length;
|
||||
var currentGroup = 1;
|
||||
Date.parseFunctions[format] = funcName;
|
||||
|
||||
var code = "Date." + funcName + " = function(input){\n"
|
||||
+ "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1;\n"
|
||||
+ "var d = new Date();\n"
|
||||
+ "y = d.getFullYear();\n"
|
||||
+ "m = d.getMonth();\n"
|
||||
+ "d = d.getDate();\n"
|
||||
+ "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
|
||||
+ "if (results && results.length > 0) {"
|
||||
var regex = "";
|
||||
|
||||
var special = false;
|
||||
var ch = '';
|
||||
for (var i = 0; i < format.length; ++i) {
|
||||
ch = format.charAt(i);
|
||||
if (!special && ch == "\\") {
|
||||
special = true;
|
||||
}
|
||||
else if (special) {
|
||||
special = false;
|
||||
regex += String.escape(ch);
|
||||
}
|
||||
else {
|
||||
obj = Date.formatCodeToRegex(ch, currentGroup);
|
||||
currentGroup += obj.g;
|
||||
regex += obj.s;
|
||||
if (obj.g && obj.c) {
|
||||
code += obj.c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
code += "if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
|
||||
+ "{return new Date(y, m, d, h, i, s);}\n"
|
||||
+ "else if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
|
||||
+ "{return new Date(y, m, d, h, i);}\n"
|
||||
+ "else if (y > 0 && m >= 0 && d > 0 && h >= 0)\n"
|
||||
+ "{return new Date(y, m, d, h);}\n"
|
||||
+ "else if (y > 0 && m >= 0 && d > 0)\n"
|
||||
+ "{return new Date(y, m, d);}\n"
|
||||
+ "else if (y > 0 && m >= 0)\n"
|
||||
+ "{return new Date(y, m);}\n"
|
||||
+ "else if (y > 0)\n"
|
||||
+ "{return new Date(y);}\n"
|
||||
+ "}return null;}";
|
||||
|
||||
Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
|
||||
eval(code);
|
||||
}
|
||||
|
||||
Date.formatCodeToRegex = function(character, currentGroup) {
|
||||
switch (character) {
|
||||
case "D":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
|
||||
case "j":
|
||||
case "d":
|
||||
return {g:1,
|
||||
c:"d = parseInt(results[" + currentGroup + "], 10);\n",
|
||||
s:"(\\d{1,2})"};
|
||||
case "l":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"(?:" + Date.dayNames.join("|") + ")"};
|
||||
case "S":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"(?:st|nd|rd|th)"};
|
||||
case "w":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"\\d"};
|
||||
case "z":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"(?:\\d{1,3})"};
|
||||
case "W":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"(?:\\d{2})"};
|
||||
case "F":
|
||||
return {g:1,
|
||||
c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
|
||||
s:"(" + Date.monthNames.join("|") + ")"};
|
||||
case "M":
|
||||
return {g:1,
|
||||
c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
|
||||
s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
|
||||
case "n":
|
||||
case "m":
|
||||
return {g:1,
|
||||
c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
|
||||
s:"(\\d{1,2})"};
|
||||
case "t":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"\\d{1,2}"};
|
||||
case "L":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"(?:1|0)"};
|
||||
case "Y":
|
||||
return {g:1,
|
||||
c:"y = parseInt(results[" + currentGroup + "], 10);\n",
|
||||
s:"(\\d{4})"};
|
||||
case "y":
|
||||
return {g:1,
|
||||
c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
|
||||
+ "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
|
||||
s:"(\\d{1,2})"};
|
||||
case "a":
|
||||
return {g:1,
|
||||
c:"if (results[" + currentGroup + "] == 'am') {\n"
|
||||
+ "if (h == 12) { h = 0; }\n"
|
||||
+ "} else { if (h < 12) { h += 12; }}",
|
||||
s:"(am|pm)"};
|
||||
case "A":
|
||||
return {g:1,
|
||||
c:"if (results[" + currentGroup + "] == 'AM') {\n"
|
||||
+ "if (h == 12) { h = 0; }\n"
|
||||
+ "} else { if (h < 12) { h += 12; }}",
|
||||
s:"(AM|PM)"};
|
||||
case "g":
|
||||
case "G":
|
||||
case "h":
|
||||
case "H":
|
||||
return {g:1,
|
||||
c:"h = parseInt(results[" + currentGroup + "], 10);\n",
|
||||
s:"(\\d{1,2})"};
|
||||
case "i":
|
||||
return {g:1,
|
||||
c:"i = parseInt(results[" + currentGroup + "], 10);\n",
|
||||
s:"(\\d{2})"};
|
||||
case "s":
|
||||
return {g:1,
|
||||
c:"s = parseInt(results[" + currentGroup + "], 10);\n",
|
||||
s:"(\\d{2})"};
|
||||
case "O":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"[+-]\\d{4}"};
|
||||
case "T":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"[A-Z]{3}"};
|
||||
case "Z":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"[+-]\\d{1,5}"};
|
||||
default:
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:String.escape(character)};
|
||||
}
|
||||
}
|
||||
|
||||
Date.prototype.getTimezone = function() {
|
||||
return this.toString().replace(
|
||||
/^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace(
|
||||
/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3");
|
||||
}
|
||||
|
||||
Date.prototype.getGMTOffset = function() {
|
||||
return (this.getTimezoneOffset() > 0 ? "-" : "+")
|
||||
+ String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, "0")
|
||||
+ String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
|
||||
}
|
||||
|
||||
Date.prototype.getDayOfYear = function() {
|
||||
var num = 0;
|
||||
Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
|
||||
for (var i = 0; i < this.getMonth(); ++i) {
|
||||
num += Date.daysInMonth[i];
|
||||
}
|
||||
return num + this.getDate() - 1;
|
||||
}
|
||||
|
||||
Date.prototype.getWeekOfYear = function() {
|
||||
// Skip to Thursday of this week
|
||||
var now = this.getDayOfYear() + (4 - this.getDay());
|
||||
// Find the first Thursday of the year
|
||||
var jan1 = new Date(this.getFullYear(), 0, 1);
|
||||
var then = (7 - jan1.getDay() + 4);
|
||||
document.write(then);
|
||||
return String.leftPad(((now - then) / 7) + 1, 2, "0");
|
||||
}
|
||||
|
||||
Date.prototype.isLeapYear = function() {
|
||||
var year = this.getFullYear();
|
||||
return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
|
||||
}
|
||||
|
||||
Date.prototype.getFirstDayOfMonth = function() {
|
||||
var day = (this.getDay() - (this.getDate() - 1)) % 7;
|
||||
return (day < 0) ? (day + 7) : day;
|
||||
}
|
||||
|
||||
Date.prototype.getLastDayOfMonth = function() {
|
||||
var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
|
||||
return (day < 0) ? (day + 7) : day;
|
||||
}
|
||||
|
||||
Date.prototype.getDaysInMonth = function() {
|
||||
Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
|
||||
return Date.daysInMonth[this.getMonth()];
|
||||
}
|
||||
|
||||
Date.prototype.getSuffix = function() {
|
||||
switch (this.getDate()) {
|
||||
case 1:
|
||||
case 21:
|
||||
case 31:
|
||||
return "st";
|
||||
case 2:
|
||||
case 22:
|
||||
return "nd";
|
||||
case 3:
|
||||
case 23:
|
||||
return "rd";
|
||||
default:
|
||||
return "th";
|
||||
}
|
||||
}
|
||||
|
||||
String.escape = function(string) {
|
||||
return string.replace(/('|\\)/g, "\\$1");
|
||||
}
|
||||
|
||||
String.leftPad = function (val, size, ch) {
|
||||
var result = new String(val);
|
||||
if (ch == null) {
|
||||
ch = " ";
|
||||
}
|
||||
while (result.length < size) {
|
||||
result = ch + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
|
||||
Date.monthNames =
|
||||
["January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December"];
|
||||
Date.dayNames =
|
||||
["Sunday",
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday"];
|
||||
Date.y2kYear = 50;
|
||||
Date.monthNumbers = {
|
||||
Jan:0,
|
||||
Feb:1,
|
||||
Mar:2,
|
||||
Apr:3,
|
||||
May:4,
|
||||
Jun:5,
|
||||
Jul:6,
|
||||
Aug:7,
|
||||
Sep:8,
|
||||
Oct:9,
|
||||
Nov:10,
|
||||
Dec:11};
|
||||
Date.patterns = {
|
||||
ISO8601LongPattern:"Y-m-d H:i:s",
|
||||
ISO8601ShortPattern:"Y-m-d",
|
||||
ShortDatePattern: "n/j/Y",
|
||||
LongDatePattern: "l, F d, Y",
|
||||
FullDateTimePattern: "l, F d, Y g:i:s A",
|
||||
MonthDayPattern: "F d",
|
||||
ShortTimePattern: "g:i A",
|
||||
LongTimePattern: "g:i:s A",
|
||||
SortableDateTimePattern: "Y-m-d\\TH:i:s",
|
||||
UniversalSortableDateTimePattern: "Y-m-d H:i:sO",
|
||||
YearMonthPattern: "F, Y"};
|
||||
|
||||
var date = new Date("1/1/2007 1:11:11");
|
||||
|
||||
for (i = 0; i < 4000; ++i) {
|
||||
var shortFormat = date.dateFormat("Y-m-d");
|
||||
var longFormat = date.dateFormat("l, F d, Y g:i:s A");
|
||||
date.setTime(date.getTime() + 84266956);
|
||||
}
|
95
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/math-cordic.js
поставляемый
Normal file
95
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/math-cordic.js
поставляемый
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (C) Rich Moore. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/////. Start CORDIC
|
||||
|
||||
var AG_CONST = 0.6072529350;
|
||||
|
||||
function FIXED(X)
|
||||
{
|
||||
return X * 65536.0;
|
||||
}
|
||||
|
||||
function FLOAT(X)
|
||||
{
|
||||
return X / 65536.0;
|
||||
}
|
||||
|
||||
function DEG2RAD(X)
|
||||
{
|
||||
return 0.017453 * (X);
|
||||
}
|
||||
|
||||
var Angles = [
|
||||
FIXED(45.0), FIXED(26.565), FIXED(14.0362), FIXED(7.12502),
|
||||
FIXED(3.57633), FIXED(1.78991), FIXED(0.895174), FIXED(0.447614),
|
||||
FIXED(0.223811), FIXED(0.111906), FIXED(0.055953),
|
||||
FIXED(0.027977)
|
||||
];
|
||||
|
||||
|
||||
function cordicsincos() {
|
||||
var X;
|
||||
var Y;
|
||||
var TargetAngle;
|
||||
var CurrAngle;
|
||||
var Step;
|
||||
|
||||
X = FIXED(AG_CONST); /* AG_CONST * cos(0) */
|
||||
Y = 0; /* AG_CONST * sin(0) */
|
||||
|
||||
TargetAngle = FIXED(28.027);
|
||||
CurrAngle = 0;
|
||||
for (Step = 0; Step < 12; Step++) {
|
||||
var NewX;
|
||||
if (TargetAngle > CurrAngle) {
|
||||
NewX = X - (Y >> Step);
|
||||
Y = (X >> Step) + Y;
|
||||
X = NewX;
|
||||
CurrAngle += Angles[Step];
|
||||
} else {
|
||||
NewX = X + (Y >> Step);
|
||||
Y = -(X >> Step) + Y;
|
||||
X = NewX;
|
||||
CurrAngle -= Angles[Step];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///// End CORDIC
|
||||
|
||||
function cordic( runs ) {
|
||||
var start = new Date();
|
||||
|
||||
for ( var i = 0 ; i < runs ; i++ ) {
|
||||
cordicsincos();
|
||||
}
|
||||
|
||||
var end = new Date();
|
||||
|
||||
return end.getTime() - start.getTime();
|
||||
}
|
||||
|
||||
cordic(25000);
|
33
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/math-partial-sums.js
поставляемый
Normal file
33
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/math-partial-sums.js
поставляемый
Normal file
|
@ -0,0 +1,33 @@
|
|||
// The Computer Language Shootout
|
||||
// http://shootout.alioth.debian.org/
|
||||
// contributed by Isaac Gouy
|
||||
|
||||
function partial(n){
|
||||
var a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0.0;
|
||||
var twothirds = 2.0/3.0;
|
||||
var alt = -1.0;
|
||||
var k2 = k3 = sk = ck = 0.0;
|
||||
|
||||
for (var k = 1; k <= n; k++){
|
||||
k2 = k*k;
|
||||
k3 = k2*k;
|
||||
sk = Math.sin(k);
|
||||
ck = Math.cos(k);
|
||||
alt = -alt;
|
||||
|
||||
a1 += Math.pow(twothirds,k-1);
|
||||
a2 += Math.pow(k,-0.5);
|
||||
a3 += 1.0/(k*(k+1.0));
|
||||
a4 += 1.0/(k3 * sk*sk);
|
||||
a5 += 1.0/(k3 * ck*ck);
|
||||
a6 += 1.0/k;
|
||||
a7 += 1.0/k2;
|
||||
a8 += alt/k;
|
||||
a9 += alt/(2*k -1);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 1024; i <= 16384; i *= 2) {
|
||||
partial(i);
|
||||
}
|
||||
|
51
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/math-spectral-norm.js
поставляемый
Normal file
51
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/math-spectral-norm.js
поставляемый
Normal file
|
@ -0,0 +1,51 @@
|
|||
// The Great Computer Language Shootout
|
||||
// http://shootout.alioth.debian.org/
|
||||
//
|
||||
// contributed by Ian Osgood
|
||||
|
||||
function A(i,j) {
|
||||
return 1/((i+j)*(i+j+1)/2+i+1);
|
||||
}
|
||||
|
||||
function Au(u,v) {
|
||||
for (var i=0; i<u.length; ++i) {
|
||||
var t = 0;
|
||||
for (var j=0; j<u.length; ++j)
|
||||
t += A(i,j) * u[j];
|
||||
v[i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
function Atu(u,v) {
|
||||
for (var i=0; i<u.length; ++i) {
|
||||
var t = 0;
|
||||
for (var j=0; j<u.length; ++j)
|
||||
t += A(j,i) * u[j];
|
||||
v[i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
function AtAu(u,v,w) {
|
||||
Au(u,w);
|
||||
Atu(w,v);
|
||||
}
|
||||
|
||||
function spectralnorm(n) {
|
||||
var i, u=[], v=[], w=[], vv=0, vBv=0;
|
||||
for (i=0; i<n; ++i) {
|
||||
u[i] = 1; v[i] = w[i] = 0;
|
||||
}
|
||||
for (i=0; i<10; ++i) {
|
||||
AtAu(u,v,w);
|
||||
AtAu(v,u,w);
|
||||
}
|
||||
for (i=0; i<n; ++i) {
|
||||
vBv += u[i]*v[i];
|
||||
vv += v[i]*v[i];
|
||||
}
|
||||
return Math.sqrt(vBv/vv);
|
||||
}
|
||||
|
||||
for (var i = 6; i <= 48; i *= 2) {
|
||||
spectralnorm(i);
|
||||
}
|
1712
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/regexp-dna.js
поставляемый
Normal file
1712
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/regexp-dna.js
поставляемый
Normal file
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
135
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-base64.js
поставляемый
Normal file
135
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-base64.js
поставляемый
Normal file
|
@ -0,0 +1,135 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla XML-RPC Client component.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Digital Creations 2, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Martijn Pieters <mj@digicool.com> (original author)
|
||||
* Samuel Sieb <samuel@sieb.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// From: http://lxr.mozilla.org/mozilla/source/extensions/xml-rpc/src/nsXmlRpcClient.js#956
|
||||
|
||||
/* Convert data (an array of integers) to a Base64 string. */
|
||||
var toBase64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||
var base64Pad = '=';
|
||||
|
||||
function toBase64(data) {
|
||||
var result = '';
|
||||
var length = data.length;
|
||||
var i;
|
||||
// Convert every three bytes to 4 ascii characters.
|
||||
for (i = 0; i < (length - 2); i += 3) {
|
||||
result += toBase64Table[data.charCodeAt(i) >> 2];
|
||||
result += toBase64Table[((data.charCodeAt(i) & 0x03) << 4) + (data.charCodeAt(i+1) >> 4)];
|
||||
result += toBase64Table[((data.charCodeAt(i+1) & 0x0f) << 2) + (data.charCodeAt(i+2) >> 6)];
|
||||
result += toBase64Table[data.charCodeAt(i+2) & 0x3f];
|
||||
}
|
||||
|
||||
// Convert the remaining 1 or 2 bytes, pad out to 4 characters.
|
||||
if (length%3) {
|
||||
i = length - (length%3);
|
||||
result += toBase64Table[data.charCodeAt(i) >> 2];
|
||||
if ((length%3) == 2) {
|
||||
result += toBase64Table[((data.charCodeAt(i) & 0x03) << 4) + (data.charCodeAt(i+1) >> 4)];
|
||||
result += toBase64Table[(data.charCodeAt(i+1) & 0x0f) << 2];
|
||||
result += base64Pad;
|
||||
} else {
|
||||
result += toBase64Table[(data.charCodeAt(i) & 0x03) << 4];
|
||||
result += base64Pad + base64Pad;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Convert Base64 data to a string */
|
||||
var toBinaryTable = [
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
|
||||
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
|
||||
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
|
||||
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
|
||||
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
|
||||
];
|
||||
|
||||
function base64ToString(data) {
|
||||
var result = '';
|
||||
var leftbits = 0; // number of bits decoded, but yet to be appended
|
||||
var leftdata = 0; // bits decoded, but yet to be appended
|
||||
|
||||
// Convert one by one.
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var c = toBinaryTable[data.charCodeAt(i) & 0x7f];
|
||||
var padding = (data.charCodeAt(i) == base64Pad.charCodeAt(0));
|
||||
// Skip illegal characters and whitespace
|
||||
if (c == -1) continue;
|
||||
|
||||
// Collect data into leftdata, update bitcount
|
||||
leftdata = (leftdata << 6) | c;
|
||||
leftbits += 6;
|
||||
|
||||
// If we have 8 or more bits, append 8 bits to the result
|
||||
if (leftbits >= 8) {
|
||||
leftbits -= 8;
|
||||
// Append if not padding.
|
||||
if (!padding)
|
||||
result += String.fromCharCode((leftdata >> leftbits) & 0xff);
|
||||
leftdata &= (1 << leftbits) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are any bits left, the base64 string was corrupted
|
||||
if (leftbits)
|
||||
throw Components.Exception('Corrupted base64 string');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var str = "";
|
||||
|
||||
for ( var i = 0; i < 8192; i++ )
|
||||
str += String.fromCharCode( (25 * Math.random()) + 97 );
|
||||
|
||||
for ( var i = 8192; i <= 16384; i *= 2 ) {
|
||||
|
||||
var base64;
|
||||
|
||||
base64 = toBase64(str);
|
||||
base64ToString(base64);
|
||||
|
||||
// Double the string
|
||||
str += str;
|
||||
}
|
||||
|
||||
toBinaryTable = null;
|
85
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-fasta.js
поставляемый
Normal file
85
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-fasta.js
поставляемый
Normal file
|
@ -0,0 +1,85 @@
|
|||
// The Great Computer Language Shootout
|
||||
// http://shootout.alioth.debian.org
|
||||
//
|
||||
// Contributed by Ian Osgood
|
||||
|
||||
var last = 42, A = 3877, C = 29573, M = 139968;
|
||||
|
||||
function rand(max) {
|
||||
last = (last * A + C) % M;
|
||||
return max * last / M;
|
||||
}
|
||||
|
||||
var ALU =
|
||||
"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
|
||||
"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
|
||||
"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
|
||||
"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
|
||||
"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
|
||||
"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
|
||||
"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
|
||||
|
||||
var IUB = {
|
||||
a:0.27, c:0.12, g:0.12, t:0.27,
|
||||
B:0.02, D:0.02, H:0.02, K:0.02,
|
||||
M:0.02, N:0.02, R:0.02, S:0.02,
|
||||
V:0.02, W:0.02, Y:0.02
|
||||
}
|
||||
|
||||
var HomoSap = {
|
||||
a: 0.3029549426680,
|
||||
c: 0.1979883004921,
|
||||
g: 0.1975473066391,
|
||||
t: 0.3015094502008
|
||||
}
|
||||
|
||||
function makeCumulative(table) {
|
||||
var last = null;
|
||||
for (var c in table) {
|
||||
if (last) table[c] += table[last];
|
||||
last = c;
|
||||
}
|
||||
}
|
||||
|
||||
function fastaRepeat(n, seq) {
|
||||
var seqi = 0, lenOut = 60;
|
||||
while (n>0) {
|
||||
if (n<lenOut) lenOut = n;
|
||||
if (seqi + lenOut < seq.length) {
|
||||
ret = seq.substring(seqi, seqi+lenOut);
|
||||
seqi += lenOut;
|
||||
} else {
|
||||
var s = seq.substring(seqi);
|
||||
seqi = lenOut - s.length;
|
||||
ret = s + seq.substring(0, seqi);
|
||||
}
|
||||
n -= lenOut;
|
||||
}
|
||||
}
|
||||
|
||||
function fastaRandom(n, table) {
|
||||
var line = new Array(60);
|
||||
makeCumulative(table);
|
||||
while (n>0) {
|
||||
if (n<line.length) line = new Array(n);
|
||||
for (var i=0; i<line.length; i++) {
|
||||
var r = rand(1);
|
||||
for (var c in table) {
|
||||
if (r < table[c]) {
|
||||
line[i] = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = line.join('');
|
||||
n -= line.length;
|
||||
}
|
||||
}
|
||||
|
||||
var ret;
|
||||
|
||||
var count = 7;
|
||||
ret = fastaRepeat(2*count*100000, ALU);
|
||||
ret = fastaRandom(3*count*1000, IUB);
|
||||
ret = fastaRandom(5*count*1000, HomoSap);
|
||||
|
265
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-tagcloud.js
поставляемый
Normal file
265
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-tagcloud.js
поставляемый
Normal file
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
68
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-unpack-code.js
поставляемый
Normal file
68
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-unpack-code.js
поставляемый
Normal file
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
89
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-validate-input.js
поставляемый
Normal file
89
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/string-validate-input.js
поставляемый
Normal file
|
@ -0,0 +1,89 @@
|
|||
letters = new Array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z");
|
||||
numbers = new Array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26);
|
||||
colors = new Array("FF","CC","99","66","33","00");
|
||||
|
||||
var endResult;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
endResult = "";
|
||||
|
||||
// make up email address
|
||||
for (var k=0;k<4000;k++)
|
||||
{
|
||||
name = makeName(6);
|
||||
(k%2)?email=name+"@mac.com":email=name+"(at)mac.com";
|
||||
|
||||
// validate the email address
|
||||
var pattern = /^[a-zA-Z0-9\-\._]+@[a-zA-Z0-9\-_]+(\.?[a-zA-Z0-9\-_]*)\.[a-zA-Z]{2,3}$/;
|
||||
|
||||
if(pattern.test(email))
|
||||
{
|
||||
var r = email + " appears to be a valid email address.";
|
||||
addResult(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = email + " does NOT appear to be a valid email address.";
|
||||
addResult(r);
|
||||
}
|
||||
}
|
||||
|
||||
// make up ZIP codes
|
||||
for (var s=0;s<4000;s++)
|
||||
{
|
||||
var zipGood = true;
|
||||
var zip = makeNumber(4);
|
||||
(s%2)?zip=zip+"xyz":zip=zip.concat("7");
|
||||
|
||||
// validate the zip code
|
||||
for (var i = 0; i < zip.length; i++) {
|
||||
var ch = zip.charAt(i);
|
||||
if (ch < "0" || ch > "9") {
|
||||
zipGood = false;
|
||||
r = zip + " contains letters.";
|
||||
addResult(r);
|
||||
}
|
||||
}
|
||||
if (zipGood && zip.length>5)
|
||||
{
|
||||
zipGood = false;
|
||||
r = zip + " is longer than five characters.";
|
||||
addResult(r);
|
||||
}
|
||||
if (zipGood)
|
||||
{
|
||||
r = zip + " appears to be a valid ZIP code.";
|
||||
addResult(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeName(n)
|
||||
{
|
||||
var tmp = "";
|
||||
for (var i=0;i<n;i++)
|
||||
{
|
||||
var l = Math.floor(26*Math.random());
|
||||
tmp += letters[l];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
function makeNumber(n)
|
||||
{
|
||||
var tmp = "";
|
||||
for (var i=0;i<n;i++)
|
||||
{
|
||||
var l = Math.floor(9*Math.random());
|
||||
tmp = tmp.concat(l);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
function addResult(r)
|
||||
{
|
||||
endResult += "\n" + r;
|
||||
}
|
||||
|
||||
doTest();
|
71
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/sunspider-standalone-driver.js
поставляемый
Normal file
71
third_party/webkit/PerformanceTests/SunSpider/sunspider-0.9.1/sunspider-standalone-driver.js
поставляемый
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
(function(){
|
||||
|
||||
const testNames = [
|
||||
"3d-cube",
|
||||
"3d-morph",
|
||||
"3d-raytrace",
|
||||
"access-binary-trees",
|
||||
"access-fannkuch",
|
||||
"access-nbody",
|
||||
"access-nsieve",
|
||||
"bitops-3bit-bits-in-byte",
|
||||
"bitops-bits-in-byte",
|
||||
"bitops-bitwise-and",
|
||||
"bitops-nsieve-bits",
|
||||
"controlflow-recursive",
|
||||
"crypto-aes",
|
||||
"crypto-md5",
|
||||
"crypto-sha1",
|
||||
"date-format-tofte",
|
||||
"date-format-xparb",
|
||||
"math-cordic",
|
||||
"math-partial-sums",
|
||||
"math-spectral-norm",
|
||||
"regexp-dna",
|
||||
"string-base64",
|
||||
"string-fasta",
|
||||
"string-tagcloud",
|
||||
"string-unpack-code",
|
||||
"string-validate-input"
|
||||
];
|
||||
|
||||
for (let testName of testNames) {
|
||||
let testScript = testName + ".js";
|
||||
let startTime = new Date;
|
||||
if (testScript.indexOf('parse-only') >= 0)
|
||||
checkSyntax(testScript);
|
||||
else
|
||||
load(testScript);
|
||||
let duration = new Date() - startTime;
|
||||
gc();
|
||||
|
||||
print(testName+":", duration);
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
@ -7220,6 +7220,37 @@
|
|||
],
|
||||
"description": "Number of 'event' pings sent, by reason"
|
||||
},
|
||||
"TELEMETRY_EVENT_REGISTRATION_ERROR": {
|
||||
"record_in_processes": ["main"],
|
||||
"alert_emails": ["telemetry-client-dev@mozilla.com", "chutten@mozilla.com"],
|
||||
"bug_numbers": [1480204],
|
||||
"expires_in_version": "never",
|
||||
"kind": "categorical",
|
||||
"labels": [
|
||||
"Other",
|
||||
"Name",
|
||||
"Category",
|
||||
"Method",
|
||||
"Object",
|
||||
"ExtraKeys"
|
||||
],
|
||||
"description": "Number of event registration failures, by field causing the failure"
|
||||
},
|
||||
"TELEMETRY_EVENT_RECORDING_ERROR": {
|
||||
"record_in_processes": ["all"],
|
||||
"alert_emails": ["telemetry-client-dev@mozilla.com", "chutten@mozilla.com"],
|
||||
"bug_numbers": [1480204],
|
||||
"expires_in_version": "never",
|
||||
"kind": "categorical",
|
||||
"labels": [
|
||||
"UnknownEvent",
|
||||
"Expired",
|
||||
"ExtraKey",
|
||||
"Value",
|
||||
"Extra"
|
||||
],
|
||||
"description": "Number of event recording failures, by type of failure"
|
||||
},
|
||||
"TELEMETRY_TEST_FLAG": {
|
||||
"record_in_processes": ["main", "content"],
|
||||
"alert_emails": ["telemetry-client-dev@mozilla.com"],
|
||||
|
@ -9208,7 +9239,7 @@
|
|||
"MEDIA_RECORDER_RECORDING_DURATION": {
|
||||
"record_in_processes": ["main", "content"],
|
||||
"alert_emails": ["bvandyk@mozilla.com"],
|
||||
"expires_in_version": "64",
|
||||
"expires_in_version": "68",
|
||||
"kind": "exponential",
|
||||
"high": 3600,
|
||||
"n_buckets": 100,
|
||||
|
@ -9218,7 +9249,7 @@
|
|||
"MEDIA_RECORDER_TRACK_ENCODER_INIT_TIMEOUT_TYPE": {
|
||||
"record_in_processes": ["main", "content"],
|
||||
"alert_emails": ["bvandyk@mozilla.com"],
|
||||
"expires_in_version": "64",
|
||||
"expires_in_version": "68",
|
||||
"kind": "enumerated",
|
||||
"n_values": 4,
|
||||
"bug_numbers": [1400757],
|
||||
|
|
|
@ -769,7 +769,7 @@ mediarecorder:
|
|||
- 1400757
|
||||
description: >
|
||||
The number of times a MediaRecorder has been started. Recorded when a MediaRecorder starts
|
||||
expires: "64"
|
||||
expires: "68"
|
||||
kind: uint
|
||||
notification_emails:
|
||||
- bvandyk@mozilla.com
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "nsUTF8Utils.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
#include "Telemetry.h"
|
||||
#include "TelemetryCommon.h"
|
||||
#include "TelemetryEvent.h"
|
||||
#include "TelemetryEventData.h"
|
||||
|
@ -38,6 +39,8 @@ using mozilla::Maybe;
|
|||
using mozilla::Nothing;
|
||||
using mozilla::StaticAutoPtr;
|
||||
using mozilla::TimeStamp;
|
||||
using mozilla::Telemetry::LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR;
|
||||
using mozilla::Telemetry::LABELS_TELEMETRY_EVENT_RECORDING_ERROR;
|
||||
using mozilla::Telemetry::Common::AutoHashtable;
|
||||
using mozilla::Telemetry::Common::IsExpiredVersion;
|
||||
using mozilla::Telemetry::Common::CanRecordDataset;
|
||||
|
@ -455,6 +458,7 @@ RecordEvent(const StaticMutexAutoLock& lock, ProcessID processType,
|
|||
// Look up the event id.
|
||||
EventKey* eventKey = GetEventKey(lock, category, method, object);
|
||||
if (!eventKey) {
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_RECORDING_ERROR::UnknownEvent);
|
||||
return RecordEventResult::UnknownEvent;
|
||||
}
|
||||
|
||||
|
@ -463,6 +467,7 @@ RecordEvent(const StaticMutexAutoLock& lock, ProcessID processType,
|
|||
// have to be removed at a specific time or version.
|
||||
// Even logging warnings would become very noisy.
|
||||
if (IsExpired(*eventKey)) {
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_RECORDING_ERROR::Expired);
|
||||
return RecordEventResult::ExpiredEvent;
|
||||
}
|
||||
|
||||
|
@ -475,6 +480,7 @@ RecordEvent(const StaticMutexAutoLock& lock, ProcessID processType,
|
|||
|
||||
// Check whether the extra keys passed are valid.
|
||||
if (!CheckExtraKeysValid(*eventKey, extra)) {
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_RECORDING_ERROR::ExtraKey);
|
||||
return RecordEventResult::InvalidExtraKey;
|
||||
}
|
||||
|
||||
|
@ -804,6 +810,7 @@ TelemetryEvent::RecordEvent(const nsACString& aCategory, const nsACString& aMeth
|
|||
if ((optional_argc > 0) && !aValue.isNull() && !aValue.isString()) {
|
||||
LogToBrowserConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_STRING("Invalid type for value parameter."));
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_RECORDING_ERROR::Value);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -814,6 +821,7 @@ TelemetryEvent::RecordEvent(const nsACString& aCategory, const nsACString& aMeth
|
|||
if (!jsStr.init(cx, aValue)) {
|
||||
LogToBrowserConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_STRING("Invalid string value for value parameter."));
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_RECORDING_ERROR::Value);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -830,6 +838,7 @@ TelemetryEvent::RecordEvent(const nsACString& aCategory, const nsACString& aMeth
|
|||
if ((optional_argc > 1) && !aExtra.isNull() && !aExtra.isObject()) {
|
||||
LogToBrowserConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_STRING("Invalid type for extra parameter."));
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_RECORDING_ERROR::Extra);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -841,6 +850,7 @@ TelemetryEvent::RecordEvent(const nsACString& aCategory, const nsACString& aMeth
|
|||
if (!JS_Enumerate(cx, obj, &ids)) {
|
||||
LogToBrowserConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_STRING("Failed to enumerate object."));
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_RECORDING_ERROR::Extra);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -849,6 +859,7 @@ TelemetryEvent::RecordEvent(const nsACString& aCategory, const nsACString& aMeth
|
|||
if (!key.init(cx, ids[i])) {
|
||||
LogToBrowserConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_STRING("Extra dictionary should only contain string keys."));
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_RECORDING_ERROR::Extra);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -856,6 +867,7 @@ TelemetryEvent::RecordEvent(const nsACString& aCategory, const nsACString& aMeth
|
|||
if (!JS_GetPropertyById(cx, obj, ids[i], &value)) {
|
||||
LogToBrowserConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_STRING("Failed to get extra property."));
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_RECORDING_ERROR::Extra);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -863,6 +875,7 @@ TelemetryEvent::RecordEvent(const nsACString& aCategory, const nsACString& aMeth
|
|||
if (!value.isString() || !jsStr.init(cx, value)) {
|
||||
LogToBrowserConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_STRING("Extra properties should have string values."));
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_RECORDING_ERROR::Extra);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -993,17 +1006,20 @@ TelemetryEvent::RegisterEvents(const nsACString& aCategory,
|
|||
|
||||
if (!IsValidIdentifierString(aCategory, 30, true, true)) {
|
||||
JS_ReportErrorASCII(cx, "Category parameter should match the identifier pattern.");
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::Category);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!aEventData.isObject()) {
|
||||
JS_ReportErrorASCII(cx, "Event data parameter should be an object");
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::Other);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
JS::RootedObject obj(cx, &aEventData.toObject());
|
||||
JS::Rooted<JS::IdVector> eventPropertyIds(cx, JS::IdVector(cx));
|
||||
if (!JS_Enumerate(cx, obj, &eventPropertyIds)) {
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::Other);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -1015,16 +1031,19 @@ TelemetryEvent::RegisterEvents(const nsACString& aCategory,
|
|||
for (size_t i = 0, n = eventPropertyIds.length(); i < n; i++) {
|
||||
nsAutoJSString eventName;
|
||||
if (!eventName.init(cx, eventPropertyIds[i])) {
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::Other);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!IsValidIdentifierString(NS_ConvertUTF16toUTF8(eventName), kMaxMethodNameByteLength, false, true)) {
|
||||
JS_ReportErrorASCII(cx, "Event names should match the identifier pattern.");
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::Name);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
JS::RootedValue value(cx);
|
||||
if (!JS_GetPropertyById(cx, obj, eventPropertyIds[i], &value) || !value.isObject()) {
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::Other);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
JS::RootedObject eventObj(cx, &value.toObject());
|
||||
|
@ -1038,10 +1057,12 @@ TelemetryEvent::RegisterEvents(const nsACString& aCategory,
|
|||
|
||||
// The methods & objects properties are required.
|
||||
if (!GetArrayPropertyValues(cx, eventObj, "methods", &methods)) {
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::Other);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!GetArrayPropertyValues(cx, eventObj, "objects", &objects)) {
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::Other);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -1049,6 +1070,7 @@ TelemetryEvent::RegisterEvents(const nsACString& aCategory,
|
|||
bool hasProperty = false;
|
||||
if (JS_HasProperty(cx, eventObj, "extra_keys", &hasProperty) && hasProperty) {
|
||||
if (!GetArrayPropertyValues(cx, eventObj, "extra_keys", &extra_keys)) {
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::Other);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
@ -1057,6 +1079,7 @@ TelemetryEvent::RegisterEvents(const nsACString& aCategory,
|
|||
if (JS_HasProperty(cx, eventObj, "expired", &hasProperty) && hasProperty) {
|
||||
JS::RootedValue temp(cx);
|
||||
if (!JS_GetProperty(cx, eventObj, "expired", &temp) || !temp.isBoolean()) {
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::Other);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -1067,6 +1090,7 @@ TelemetryEvent::RegisterEvents(const nsACString& aCategory,
|
|||
if (JS_HasProperty(cx, eventObj, "record_on_release", &hasProperty) && hasProperty) {
|
||||
JS::RootedValue temp(cx);
|
||||
if (!JS_GetProperty(cx, eventObj, "record_on_release", &temp) || !temp.isBoolean()) {
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::Other);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -1077,6 +1101,7 @@ TelemetryEvent::RegisterEvents(const nsACString& aCategory,
|
|||
for (auto& method : methods) {
|
||||
if (!IsValidIdentifierString(method, kMaxMethodNameByteLength, false, true)) {
|
||||
JS_ReportErrorASCII(cx, "Method names should match the identifier pattern.");
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::Method);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
@ -1085,6 +1110,7 @@ TelemetryEvent::RegisterEvents(const nsACString& aCategory,
|
|||
for (auto& object : objects) {
|
||||
if (!IsValidIdentifierString(object, kMaxObjectNameByteLength, false, true)) {
|
||||
JS_ReportErrorASCII(cx, "Object names should match the identifier pattern.");
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::Object);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
@ -1092,11 +1118,13 @@ TelemetryEvent::RegisterEvents(const nsACString& aCategory,
|
|||
// Validate extra keys.
|
||||
if (extra_keys.Length() > kMaxExtraKeyCount) {
|
||||
JS_ReportErrorASCII(cx, "No more than 10 extra keys can be registered.");
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::ExtraKeys);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
for (auto& key : extra_keys) {
|
||||
if (!IsValidIdentifierString(key, kMaxExtraKeyNameByteLength, false, true)) {
|
||||
JS_ReportErrorASCII(cx, "Extra key names should match the identifier pattern.");
|
||||
mozilla::Telemetry::AccumulateCategorical(LABELS_TELEMETRY_EVENT_REGISTRATION_ERROR::ExtraKeys);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ function checkEventFormat(events) {
|
|||
*/
|
||||
function checkEventSummary(summaries, clearScalars) {
|
||||
let scalars = Telemetry.snapshotKeyedScalars(OPTOUT, clearScalars);
|
||||
dump(JSON.stringify(summaries));
|
||||
|
||||
for (let [process, [category, eObject, method], count] of summaries) {
|
||||
let uniqueEventName = `${category}#${eObject}#${method}`;
|
||||
let summaryCount;
|
||||
|
@ -58,6 +58,30 @@ function checkEventSummary(summaries, clearScalars) {
|
|||
}
|
||||
}
|
||||
|
||||
function checkRegistrationFailure(failureType) {
|
||||
let snapshot = Telemetry.snapshotHistograms(OPTIN, true);
|
||||
Assert.ok("parent" in snapshot,
|
||||
"There should be at least one parent histogram when checking for registration failures.");
|
||||
Assert.ok("TELEMETRY_EVENT_REGISTRATION_ERROR" in snapshot.parent,
|
||||
"TELEMETRY_EVENT_REGISTRATION_ERROR should exist when checking for registration failures.");
|
||||
let counts = snapshot.parent.TELEMETRY_EVENT_REGISTRATION_ERROR.counts;
|
||||
Assert.ok(!!counts,
|
||||
"TELEMETRY_EVENT_REGISTRATION_ERROR's counts should exist when checking for registration failures.");
|
||||
Assert.equal(counts[failureType], 1, `Event registration ought to have failed due to type ${failureType}`);
|
||||
}
|
||||
|
||||
function checkRecordingFailure(failureType) {
|
||||
let snapshot = Telemetry.snapshotHistograms(OPTIN, true);
|
||||
Assert.ok("parent" in snapshot,
|
||||
"There should be at least one parent histogram when checking for recording failures.");
|
||||
Assert.ok("TELEMETRY_EVENT_RECORDING_ERROR" in snapshot.parent,
|
||||
"TELEMETRY_EVENT_RECORDING_ERROR should exist when checking for recording failures.");
|
||||
let counts = snapshot.parent.TELEMETRY_EVENT_RECORDING_ERROR.counts;
|
||||
Assert.ok(!!counts,
|
||||
"TELEMETRY_EVENT_RECORDING_ERROR's counts should exist when checking for recording failures.");
|
||||
Assert.equal(counts[failureType], 1, `Event recording ought to have failed due to type ${failureType}`);
|
||||
}
|
||||
|
||||
add_task(async function test_event_summary_limit() {
|
||||
if (AppConstants.DEBUG) {
|
||||
// This test will intentionally assert in DEBUG builds
|
||||
|
@ -198,12 +222,15 @@ add_task(async function test_recording() {
|
|||
Assert.throws(() => Telemetry.recordEvent("unknown.category", "test1", "object1"),
|
||||
/Error: Unknown event: \["unknown.category", "test1", "object1"\]/,
|
||||
"Should throw on unknown category.");
|
||||
checkRecordingFailure(0 /* UnknownEvent */);
|
||||
Assert.throws(() => Telemetry.recordEvent("telemetry.test", "unknown", "object1"),
|
||||
/Error: Unknown event: \["telemetry.test", "unknown", "object1"\]/,
|
||||
"Should throw on unknown method.");
|
||||
checkRecordingFailure(0 /* UnknownEvent */);
|
||||
Assert.throws(() => Telemetry.recordEvent("telemetry.test", "test1", "unknown"),
|
||||
/Error: Unknown event: \["telemetry.test", "test1", "unknown"\]/,
|
||||
"Should throw on unknown object.");
|
||||
checkRecordingFailure(0 /* UnknownEvent */);
|
||||
|
||||
let checkEvents = (events, expectedEvents) => {
|
||||
checkEventFormat(events);
|
||||
|
@ -280,6 +307,7 @@ add_task(async function test_expiry() {
|
|||
|
||||
// Recording call with event that is expired by version.
|
||||
Telemetry.recordEvent("telemetry.test", "expired_version", "object1");
|
||||
checkRecordingFailure(1 /* Expired */);
|
||||
let snapshot = Telemetry.snapshotEvents(OPTIN, true);
|
||||
Assert.equal(Object.keys(snapshot).length, 0, "Should not record event with expired version.");
|
||||
|
||||
|
@ -297,21 +325,25 @@ add_task(async function test_invalidParams() {
|
|||
Telemetry.recordEvent("telemetry.test", "test1", "object1", 1);
|
||||
let snapshot = Telemetry.snapshotEvents(OPTIN, true);
|
||||
Assert.equal(Object.keys(snapshot).length, 0, "Should not record event when value argument with invalid type is passed.");
|
||||
checkRecordingFailure(3 /* Value */);
|
||||
|
||||
// Recording call with wrong type for extra argument.
|
||||
Telemetry.recordEvent("telemetry.test", "test1", "object1", null, "invalid");
|
||||
snapshot = Telemetry.snapshotEvents(OPTIN, true);
|
||||
Assert.equal(Object.keys(snapshot).length, 0, "Should not record event when extra argument with invalid type is passed.");
|
||||
checkRecordingFailure(4 /* Extra */);
|
||||
|
||||
// Recording call with unknown extra key.
|
||||
Telemetry.recordEvent("telemetry.test", "test1", "object1", null, {"key3": "x"});
|
||||
snapshot = Telemetry.snapshotEvents(OPTIN, true);
|
||||
Assert.equal(Object.keys(snapshot).length, 0, "Should not record event when extra argument with invalid key is passed.");
|
||||
checkRecordingFailure(2 /* ExtraKey */);
|
||||
|
||||
// Recording call with invalid value type.
|
||||
Telemetry.recordEvent("telemetry.test", "test1", "object1", null, {"key3": 1});
|
||||
snapshot = Telemetry.snapshotEvents(OPTIN, true);
|
||||
Assert.equal(Object.keys(snapshot).length, 0, "Should not record event when extra argument with invalid value type is passed.");
|
||||
checkRecordingFailure(4 /* Extra */);
|
||||
});
|
||||
|
||||
add_task(async function test_storageLimit() {
|
||||
|
@ -445,6 +477,7 @@ add_task(async function test_dynamicEvents() {
|
|||
Assert.throws(() => Telemetry.recordEvent("telemetry.test.dynamic", "unknown", "unknown"),
|
||||
/Error: Unknown event: \["telemetry\.test\.dynamic", "unknown", "unknown"\]/,
|
||||
"Should throw when recording an unknown dynamic event.");
|
||||
checkRecordingFailure(0 /* UnknownEvent */);
|
||||
|
||||
// Now check that the snapshot contains the expected data.
|
||||
let snapshot = Telemetry.snapshotEvents(OPTIN, false);
|
||||
|
@ -507,6 +540,7 @@ add_task(async function test_dynamicEventRegistrationValidation() {
|
|||
Telemetry.clearEvents();
|
||||
|
||||
// Test registration of invalid categories.
|
||||
Telemetry.snapshotHistograms(OPTIN, true); // Clear histograms before we begin.
|
||||
Assert.throws(() => Telemetry.registerEvents("telemetry+test+dynamic", {
|
||||
"test1": {
|
||||
methods: ["test1"],
|
||||
|
@ -515,6 +549,7 @@ add_task(async function test_dynamicEventRegistrationValidation() {
|
|||
}),
|
||||
/Category parameter should match the identifier pattern\./,
|
||||
"Should throw when registering category names with invalid characters.");
|
||||
checkRegistrationFailure(2 /* Category */);
|
||||
Assert.throws(() => Telemetry.registerEvents("telemetry.test.test.test.test.test.test.test.test", {
|
||||
"test1": {
|
||||
methods: ["test1"],
|
||||
|
@ -523,6 +558,7 @@ add_task(async function test_dynamicEventRegistrationValidation() {
|
|||
}),
|
||||
/Category parameter should match the identifier pattern\./,
|
||||
"Should throw when registering overly long category names.");
|
||||
checkRegistrationFailure(2 /* Category */);
|
||||
|
||||
// Test registration of invalid event names.
|
||||
Assert.throws(() => Telemetry.registerEvents("telemetry.test.dynamic1", {
|
||||
|
@ -533,6 +569,7 @@ add_task(async function test_dynamicEventRegistrationValidation() {
|
|||
}),
|
||||
/Event names should match the identifier pattern\./,
|
||||
"Should throw when registering event names with invalid characters.");
|
||||
checkRegistrationFailure(1 /* Name */);
|
||||
Assert.throws(() => Telemetry.registerEvents("telemetry.test.dynamic2", {
|
||||
"test1test1test1test1test1test1test1": {
|
||||
methods: ["test1"],
|
||||
|
@ -541,6 +578,7 @@ add_task(async function test_dynamicEventRegistrationValidation() {
|
|||
}),
|
||||
/Event names should match the identifier pattern\./,
|
||||
"Should throw when registering overly long event names.");
|
||||
checkRegistrationFailure(1 /* Name */);
|
||||
|
||||
// Test registration of invalid method names.
|
||||
Assert.throws(() => Telemetry.registerEvents("telemetry.test.dynamic3", {
|
||||
|
@ -551,6 +589,7 @@ add_task(async function test_dynamicEventRegistrationValidation() {
|
|||
}),
|
||||
/Method names should match the identifier pattern\./,
|
||||
"Should throw when registering method names with invalid characters.");
|
||||
checkRegistrationFailure(3 /* Method */);
|
||||
Assert.throws(() => Telemetry.registerEvents("telemetry.test.dynamic", {
|
||||
"test1": {
|
||||
methods: ["test1test1test1test1test1test1test1"],
|
||||
|
@ -559,6 +598,7 @@ add_task(async function test_dynamicEventRegistrationValidation() {
|
|||
}),
|
||||
/Method names should match the identifier pattern\./,
|
||||
"Should throw when registering overly long method names.");
|
||||
checkRegistrationFailure(3 /* Method */);
|
||||
|
||||
// Test registration of invalid object names.
|
||||
Assert.throws(() => Telemetry.registerEvents("telemetry.test.dynamic4", {
|
||||
|
@ -569,6 +609,7 @@ add_task(async function test_dynamicEventRegistrationValidation() {
|
|||
}),
|
||||
/Object names should match the identifier pattern\./,
|
||||
"Should throw when registering object names with invalid characters.");
|
||||
checkRegistrationFailure(4 /* Object */);
|
||||
Assert.throws(() => Telemetry.registerEvents("telemetry.test.dynamic5", {
|
||||
"test1": {
|
||||
methods: ["test1"],
|
||||
|
@ -577,6 +618,7 @@ add_task(async function test_dynamicEventRegistrationValidation() {
|
|||
}),
|
||||
/Object names should match the identifier pattern\./,
|
||||
"Should throw when registering overly long object names.");
|
||||
checkRegistrationFailure(4 /* Object */);
|
||||
|
||||
// Test validation of invalid key names.
|
||||
Assert.throws(() => Telemetry.registerEvents("telemetry.test.dynamic6", {
|
||||
|
@ -588,6 +630,7 @@ add_task(async function test_dynamicEventRegistrationValidation() {
|
|||
}),
|
||||
/Extra key names should match the identifier pattern\./,
|
||||
"Should throw when registering extra key names with invalid characters.");
|
||||
checkRegistrationFailure(5 /* ExtraKeys */);
|
||||
|
||||
// Test validation of key names that are too long - we allow a maximum of 15 characters.
|
||||
Assert.throws(() => Telemetry.registerEvents("telemetry.test.dynamic7", {
|
||||
|
@ -599,6 +642,7 @@ add_task(async function test_dynamicEventRegistrationValidation() {
|
|||
}),
|
||||
/Extra key names should match the identifier pattern\./,
|
||||
"Should throw when registering extra key names which are too long.");
|
||||
checkRegistrationFailure(5 /* ExtraKeys */);
|
||||
Telemetry.registerEvents("telemetry.test.dynamic8", {
|
||||
"test1": {
|
||||
methods: ["test1"],
|
||||
|
@ -617,6 +661,7 @@ add_task(async function test_dynamicEventRegistrationValidation() {
|
|||
}),
|
||||
/No more than 10 extra keys can be registered\./,
|
||||
"Should throw when registering too many extra keys.");
|
||||
checkRegistrationFailure(5 /* ExtraKeys */);
|
||||
Telemetry.registerEvents("telemetry.test.dynamic10", {
|
||||
"test1": {
|
||||
methods: ["test1"],
|
||||
|
|
|
@ -34,7 +34,9 @@ def normalize_osx_path(p):
|
|||
return p
|
||||
|
||||
def is_l10n_file(path):
|
||||
return '/locale/' in path or '/localization/' in path
|
||||
return ('/locale/' in path or
|
||||
'/localization/' in path or
|
||||
path.startswith('localization/'))
|
||||
|
||||
def normalize_path(p):
|
||||
return normalize_osx_path(p)
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче