68.14.0 - everything else

This commit is contained in:
Fedor 2024-04-22 21:07:01 +03:00
parent 2da2788848
commit 5e12393c9d
865 changed files with 25466 additions and 31443 deletions

View File

@ -3,25 +3,24 @@
# Always ignore crashtests - specially crafted files that originally caused a # Always ignore crashtests - specially crafted files that originally caused a
# crash. # crash.
**/crashtests/** **/crashtests/
# Also ignore reftest - specially crafted to produce expected output. # Also ignore reftest - specially crafted to produce expected output.
**/reftest/** **/reftest/
**/reftests/** **/reftests/
# Exclude expected objdirs. # Exclude expected objdirs.
obj*/** obj*/
# dom/ exclusions which should be removed (aka ESLint enabled) # dom/ exclusions which should be removed (aka ESLint enabled)
dom/base/*.* dom/media/test/
dom/media/test/**
!dom/media/test/marionette/yttest/*.js !dom/media/test/marionette/yttest/*.js
dom/xhr/** dom/xhr/
# build/ third-party code # build/ third-party code
build/pgo/js-input/** build/pgo/js-input/
# browser/ exclusions # browser/ exclusions
browser/app/** browser/app/
browser/branding/**/firefox-branding.js browser/branding/**/firefox-branding.js
# Gzipped test file. # Gzipped test file.
browser/base/content/test/general/gZipOfflineChild.html browser/base/content/test/general/gZipOfflineChild.html
@ -34,27 +33,26 @@ browser/components/sessionstore/test/unit/data/sessionstore_invalid.js
# code as a .jsm (schema.jsm) # code as a .jsm (schema.jsm)
browser/components/enterprisepolicies/schemas/schema.jsm browser/components/enterprisepolicies/schemas/schema.jsm
# generated & special files in cld2 # generated & special files in cld2
browser/components/translation/cld2/** browser/components/translation/cld2/
# Screenshots is imported as a system add-on and has # Screenshots is imported as a system add-on and has
# their own lint rules currently. # their own lint rules currently.
browser/extensions/screenshots/** browser/extensions/screenshots/
browser/extensions/pdfjs/content/build** browser/extensions/pdfjs/content/build
browser/extensions/pdfjs/content/web** browser/extensions/pdfjs/content/web
# generated or library files in pocket # generated or library files in pocket
browser/components/pocket/content/panels/js/tmpl.js browser/components/pocket/content/panels/js/tmpl.js
browser/components/pocket/content/panels/js/vendor/** browser/components/pocket/content/panels/js/vendor/
# Ignore newtab files # Ignore newtab files
# Kept in sync with browser/components/newtab/.eslintignore # Kept in sync with browser/components/newtab/.eslintignore
browser/components/newtab/data/ browser/components/newtab/data/
browser/components/newtab/logs/ browser/components/newtab/logs/
browser/components/newtab/prerendered/
browser/components/newtab/vendor/ browser/components/newtab/vendor/
# The only file in browser/locales/ is pre-processed. # The only file in browser/locales/ is pre-processed.
browser/locales/** browser/locales/
# imported from chromium # imported from chromium
browser/extensions/mortar/** browser/extensions/mortar/
# Generated data files # Generated data files
browser/extensions/formautofill/phonenumberutils/PhoneNumberMetaData.jsm browser/extensions/formautofill/phonenumberutils/PhoneNumberMetaData.jsm
@ -80,63 +78,61 @@ devtools/client/shared/webpack/shims/test/test_clipboard.html
devtools/shared/qrcode/tests/mochitest/test_decode.html devtools/shared/qrcode/tests/mochitest/test_decode.html
devtools/shared/tests/mochitest/*.html devtools/shared/tests/mochitest/*.html
devtools/shared/webconsole/test/test_*.html devtools/shared/webconsole/test/test_*.html
devtools/server/tests/mochitest/test_inspector-inactive-property-helper.html
# Ignore devtools debugger files # Ignore devtools debugger files
# Keep in sync with devtools/client/debugger/.eslintignore # Keep in sync with devtools/client/debugger/.eslintignore
devtools/client/debugger/assets/* devtools/client/debugger/assets/*
devtools/client/debugger/src/test/examples/** devtools/client/debugger/src/test/examples/
devtools/client/debugger/src/test/integration/** devtools/client/debugger/src/test/integration/
devtools/client/debugger/src/test/unit-sources/** devtools/client/debugger/src/test/unit-sources/
devtools/client/debugger/src/**/fixtures/** devtools/client/debugger/src/**/fixtures/
devtools/client/debugger/src/test/mochitest/** devtools/client/debugger/src/test/mochitest/
devtools/client/debugger/bin/ devtools/client/debugger/bin/
devtools/client/debugger/packages/**/fixtures/** devtools/client/debugger/packages/**/fixtures/
devtools/client/debugger/node_modules devtools/client/debugger/node_modules
devtools/client/debugger/out devtools/client/debugger/out
# Ignore devtools debugger files which aren't intended for linting, and also # Ignore devtools debugger files which aren't intended for linting, and also
# aren't included in any .eslintignore or .prettierignore file. # aren't included in any .eslintignore or .prettierignore file.
# See https://github.com/firefox-devtools/debugger/blob/master/package.json#L24 # See https://github.com/firefox-devtools/debugger/blob/master/package.json#L24
devtools/client/debugger/configs/** devtools/client/debugger/configs/
devtools/client/debugger/dist/** devtools/client/debugger/dist/
devtools/client/debugger/flow-typed/** devtools/client/debugger/flow-typed/
devtools/client/debugger/images/** devtools/client/debugger/images/
devtools/client/debugger/test/** devtools/client/debugger/test/
devtools/client/debugger/index.html devtools/client/debugger/index.html
# Ignore devtools imported repositories # Ignore devtools imported repositories
devtools/client/shared/components/reps/** devtools/client/shared/components/reps/
# Ignore devtools preferences files # Ignore devtools preferences files
devtools/client/preferences/** devtools/client/preferences/
devtools/client/webide/preferences/**
devtools/shared/preferences/**
devtools/startup/preferences/devtools-startup.js
# Ignore devtools generated code # Ignore devtools generated code
devtools/shared/css/generated/properties-db.js devtools/shared/css/generated/properties-db.js
devtools/client/webconsole/test/fixtures/stubs/*.js devtools/client/webconsole/test/node/fixtures/stubs/*.js
!devtools/client/webconsole/test/fixtures/stubs/index.js !devtools/client/webconsole/test/node/fixtures/stubs/index.js
# Ignore devtools third-party libs # Ignore devtools third-party libs
devtools/shared/jsbeautify/* devtools/shared/jsbeautify/
devtools/shared/acorn/* devtools/shared/acorn/
devtools/shared/node-properties/* devtools/shared/node-properties/
devtools/shared/pretty-fast/* devtools/shared/pretty-fast/
devtools/shared/sourcemap/* devtools/shared/sourcemap/
devtools/shared/sprintfjs/* devtools/shared/sprintfjs/
devtools/shared/qrcode/decoder/* devtools/shared/qrcode/decoder/
devtools/shared/qrcode/encoder/* devtools/shared/qrcode/encoder/
devtools/client/inspector/markup/test/lib_* devtools/client/inspector/markup/test/lib_*
devtools/client/jsonview/lib/require.js devtools/client/jsonview/lib/require.js
devtools/client/shared/demangle.js devtools/client/shared/demangle.js
devtools/client/shared/source-map/* devtools/client/shared/source-map/
devtools/client/shared/vendor/* devtools/client/shared/vendor/
devtools/client/shared/sourceeditor/codemirror/*.js devtools/client/shared/sourceeditor/codemirror/*.js
devtools/client/shared/sourceeditor/codemirror/**/*.js devtools/client/shared/sourceeditor/codemirror/**/*.js
devtools/client/shared/sourceeditor/tern/* devtools/client/shared/sourceeditor/tern/
devtools/client/shared/sourceeditor/test/cm_mode_ruby.js devtools/client/shared/sourceeditor/test/cm_mode_ruby.js
devtools/client/shared/sourceeditor/test/codemirror/* devtools/client/shared/sourceeditor/test/codemirror/
devtools/server/actors/utils/automation-timeline.js devtools/server/actors/utils/automation-timeline.js
# Ignore devtools files testing sourcemaps / code style # Ignore devtools files testing sourcemaps / code style
@ -144,20 +140,23 @@ devtools/client/debugger/test/mochitest/code_*.js
devtools/client/framework/test/code_* devtools/client/framework/test/code_*
devtools/client/inspector/markup/test/events_bundle.js devtools/client/inspector/markup/test/events_bundle.js
devtools/client/netmonitor/test/xhr_bundle.js devtools/client/netmonitor/test/xhr_bundle.js
devtools/client/webconsole/test/mochitest/code_bundle_nosource.js devtools/client/webconsole/test/browser/code_bundle_nosource.js
devtools/client/webconsole/test/mochitest/code_bundle_invalidmap.js devtools/client/webconsole/test/browser/code_bundle_invalidmap.js
devtools/server/tests/unit/babel_and_browserify_script_with_source_map.js devtools/server/tests/unit/babel_and_browserify_script_with_source_map.js
devtools/server/tests/unit/setBreakpoint* devtools/server/tests/unit/setBreakpoint*
devtools/server/tests/unit/sourcemapped.js devtools/server/tests/unit/sourcemapped.js
# Testing syntax error
devtools/client/webconsole/test/browser/test-syntaxerror-worklet.js
# devtools specific format test file # devtools specific format test file
devtools/server/tests/unit/xpcshell_debugging_script.js devtools/server/tests/unit/xpcshell_debugging_script.js
# Third-party # Third-party
dom/canvas/test/webgl-conf/** dom/canvas/test/webgl-conf/
dom/imptests/** dom/imptests/
dom/media/webaudio/test/blink/** dom/media/webaudio/test/blink/
dom/media/webvtt/** dom/media/webvtt/
dom/svg/test/test_nonAnimStrings.xhtml dom/svg/test/test_nonAnimStrings.xhtml
dom/svg/test/test_SVG_namespace_ids.html dom/svg/test/test_SVG_namespace_ids.html
@ -193,39 +192,39 @@ dom/workers/test/invalid.js
dom/workers/test/threadErrors_worker1.js dom/workers/test/threadErrors_worker1.js
# Third-party # Third-party
editor/libeditor/tests/browserscope/** editor/libeditor/tests/browserscope/
# Third-party # Third-party
gfx/ots/** gfx/ots/
gfx/skia/** gfx/skia/
gfx/wr/** gfx/wr/
# intl/ exclusions # intl/ exclusions
intl/icu/** intl/icu/
# Bug 1527075: This directory is linted in github repository # Bug 1527075: This directory is linted in github repository
intl/l10n/** intl/l10n/
# Third-party # Third-party
layout/mathml/imptests/** layout/mathml/imptests/
# Exclude everything but self-hosted JS # Exclude everything but self-hosted JS
js/ductwork/** js/ductwork/
js/examples/** js/examples/
js/ipc/** js/ipc/
js/public/** js/public/
js/xpconnect/** js/xpconnect/
js/src/devtools/** js/src/devtools/
js/src/octane/** js/src/octane/
js/src/jit-test/** js/src/jit-test/
js/src/jsapi-tests/binast/** js/src/jsapi-tests/binast/
js/src/tests/** js/src/tests/
js/src/Y.js js/src/Y.js
# Third-party # Third-party
media/webrtc/trunk/** media/webrtc/trunk/
# mobile/android/ exclusions # mobile/android/ exclusions
mobile/android/tests/browser/chrome/tp5/** mobile/android/tests/browser/chrome/tp5/
# Uses `#filter substitution` # Uses `#filter substitution`
mobile/android/app/mobile.js mobile/android/app/mobile.js
@ -241,10 +240,10 @@ mobile/android/locales/
# Pre-processed/pref files # Pre-processed/pref files
modules/libpref/greprefs.js modules/libpref/greprefs.js
modules/libpref/init/all.js modules/libpref/init/all.js
modules/libpref/test/unit/*data/** modules/libpref/test/unit/*data/
# Only contains non-standard test files. # Only contains non-standard test files.
python/** python/
# Remote agent # Remote agent
remote/Protocol.jsm remote/Protocol.jsm
@ -256,7 +255,7 @@ remote/test/browser/chrome-remote-interface.js
remote/test/demo.js remote/test/demo.js
# NSS / taskcluster only. # NSS / taskcluster only.
security/nss/** security/nss/
# services/ exclusions # services/ exclusions
@ -271,7 +270,7 @@ services/fxaccounts/FxAccountsPairingChannel.js
services/sync/modules/constants.js services/sync/modules/constants.js
# Servo is imported. # Servo is imported.
servo/** servo/
# Remote protocol exclusions # Remote protocol exclusions
testing/marionette/atom.js testing/marionette/atom.js
@ -282,35 +281,37 @@ testing/marionette/harness
# other testing/ exclusions # other testing/ exclusions
# third party modules # third party modules
testing/mochitest/tests/Harness_sanity/** testing/mochitest/tests/Harness_sanity/
testing/mochitest/MochiKit/** testing/mochitest/MochiKit/
testing/mochitest/tests/MochiKit-1.4.2/** testing/mochitest/tests/MochiKit-1.4.2/
testing/mochitest/tests/SimpleTest/** testing/mochitest/tests/SimpleTest/
testing/modules/ajv-4.1.1.js testing/modules/ajv-4.1.1.js
testing/modules/sinon-7.2.7.js testing/modules/sinon-7.2.7.js
# octothorpe used for pref file comment causes parsing error # octothorpe used for pref file comment causes parsing error
testing/mozbase/mozprofile/tests/files/prefs_with_comments.js testing/mozbase/mozprofile/tests/files/prefs_with_comments.js
# Mozproxy third party
testing/mozbase/mozproxy/mozproxy/backends/mitm/scripts/catapult/
testing/talos/talos/scripts/jszip.min.js testing/talos/talos/scripts/jszip.min.js
testing/talos/talos/startup_test/sessionrestore/profile/sessionstore.js testing/talos/talos/startup_test/sessionrestore/profile/sessionstore.js
testing/talos/talos/startup_test/sessionrestore/profile-manywindows/sessionstore.js testing/talos/talos/startup_test/sessionrestore/profile-manywindows/sessionstore.js
testing/talos/talos/tests/devtools/addon/content/pages/** testing/talos/talos/tests/devtools/addon/content/pages/
testing/talos/talos/tests/dromaeo/** testing/talos/talos/tests/dromaeo/
testing/talos/talos/tests/v8_7/** testing/talos/talos/tests/v8_7/
testing/talos/talos/tests/kraken/** testing/talos/talos/tests/kraken/
# Runing Talos may extract data here, see bug 1435677. # Runing Talos may extract data here, see bug 1435677.
testing/talos/talos/tests/tp5n/** testing/talos/talos/tests/tp5n/
# Raptor third party
testing/raptor/raptor/playback/scripts/catapult/**
testing/web-platform/** testing/web-platform/
testing/xpcshell/moz-http2/** testing/xpcshell/moz-http2/
testing/xpcshell/node-http2/** testing/xpcshell/node-http2/
testing/xpcshell/dns-packet/** testing/xpcshell/dns-packet/
testing/xpcshell/node-ip/** testing/xpcshell/node-ip/
# Third party. # Third party.
third_party/** third_party/
# toolkit/ exclusions # toolkit/ exclusions
@ -338,7 +339,7 @@ toolkit/modules/AppConstants.jsm
toolkit/modules/tests/xpcshell/test_task.js toolkit/modules/tests/xpcshell/test_task.js
# Third party # Third party
toolkit/modules/third_party/** toolkit/modules/third_party/
tools/tryselect/selectors/chooser/templates/chooser.html tools/tryselect/selectors/chooser/templates/chooser.html

View File

@ -194,23 +194,18 @@ module.exports = {
"mozilla/reject-importGlobalProperties": "off", "mozilla/reject-importGlobalProperties": "off",
"mozilla/no-arbitrary-setTimeout": "off", "mozilla/no-arbitrary-setTimeout": "off",
"mozilla/no-define-cc-etc": "off", "mozilla/no-define-cc-etc": "off",
"mozilla/no-useless-parameters": "off",
"mozilla/no-useless-run-test": "off",
"mozilla/use-chromeutils-generateqi": "off", "mozilla/use-chromeutils-generateqi": "off",
"mozilla/use-chromeutils-import": "off",
"mozilla/use-default-preference-values": "off", "mozilla/use-default-preference-values": "off",
"mozilla/use-includes-instead-of-indexOf": "off", "mozilla/use-includes-instead-of-indexOf": "off",
"mozilla/use-services": "off", "mozilla/use-services": "off",
"mozilla/use-ownerGlobal": "off", "mozilla/use-ownerGlobal": "off",
"complexity": "off", "complexity": "off",
"consistent-return": "off", "consistent-return": "off",
"dot-notation": "off",
"no-array-constructor": "off", "no-array-constructor": "off",
"no-caller": "off", "no-caller": "off",
"no-cond-assign": "off", "no-cond-assign": "off",
"no-extra-boolean-cast": "off", "no-extra-boolean-cast": "off",
"no-eval": "off", "no-eval": "off",
"no-else-return": "off",
"no-func-assign": "off", "no-func-assign": "off",
"no-global-assign": "off", "no-global-assign": "off",
"no-implied-eval": "off", "no-implied-eval": "off",
@ -326,5 +321,49 @@ module.exports = {
"no-useless-return": "off", "no-useless-return": "off",
"no-with": "off", "no-with": "off",
} }
}, {
"files": [
"browser/components/extensions/ExtensionControlledPopup.jsm",
"browser/components/extensions/test/browser/browser_ext_devtools_network.js",
"browser/components/extensions/test/browser/browser_ext_tabs_zoom.js",
"browser/components/places/tests/browser/browser_bookmarksProperties.js",
"browser/components/preferences/in-content/tests/browser_extension_controlled.js",
"browser/extensions/formautofill/FormAutofillParent.jsm",
"browser/tools/mozscreenshots/head.js",
"devtools/client/aboutdebugging/test/browser/helper-addons.js",
"devtools/client/inspector/animation/animation.js",
"devtools/client/inspector/changes/ChangesView.js",
"devtools/client/inspector/markup/test/helper_screenshot_node.js",
"devtools/client/performance/modules/widgets/graphs.js",
"devtools/client/scratchpad/scratchpad.js",
"devtools/client/webconsole/webconsole-wrapper.js",
"devtools/server/tests/unit/test_breakpoint-17.js",
"devtools/shared/adb/adb-process.js",
"devtools/shared/fronts/webconsole.js",
"dom/l10n/tests/mochitest/document_l10n/non-system-principal/test.html",
"dom/payments/test/test_basiccard.html",
"dom/payments/test/test_bug1478740.html",
"dom/payments/test/test_canMakePayment.html",
"dom/payments/test/test_closePayment.html",
"dom/payments/test/test_showPayment.html",
"dom/tests/browser/browser_persist_cookies.js",
"dom/tests/browser/browser_persist_mixed_content_image.js",
"netwerk/test/unit/test_http2-proxy.js",
"toolkit/components/contentprefs/ContentPrefService2.jsm",
"toolkit/components/extensions/ExtensionShortcuts.jsm",
"toolkit/components/extensions/ExtensionTestCommon.jsm",
"toolkit/components/extensions/test/browser/browser_ext_themes_dynamic_getCurrent.js",
"toolkit/components/extensions/test/browser/browser_ext_themes_warnings.js",
"toolkit/components/passwordmgr/test/browser/browser_autocomplete_footer.js",
"toolkit/components/remotebrowserutils/tests/browser/browser_httpResponseProcessSelection.js",
"toolkit/components/satchel/FormHistory.jsm",
"toolkit/content/tests/browser/browser_findbar.js",
"toolkit/modules/NewTabUtils.jsm",
"toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js",
"toolkit/mozapps/extensions/test/browser/head.js",
],
"rules": {
"no-async-promise-executor": "off",
}
}] }]
}; };

2
.gitignore vendored
View File

@ -44,8 +44,6 @@ security/manager/.nss.checkout
/gecko.log /gecko.log
# Ignore newtab component build assets # Ignore newtab component build assets
browser/components/newtab/bin/prerender.js
browser/components/newtab/bin/prerender.js.map
browser/components/newtab/data/locales.json browser/components/newtab/data/locales.json
browser/components/newtab/logs/ browser/components/newtab/logs/

View File

@ -15,10 +15,6 @@ browser/branding/nightly/pref/firefox-branding.js
browser/branding/official/pref/firefox-branding.js browser/branding/official/pref/firefox-branding.js
browser/branding/unofficial/pref/firefox-branding.js browser/branding/unofficial/pref/firefox-branding.js
devtools/client/preferences/debugger.js devtools/client/preferences/debugger.js
devtools/client/preferences/devtools-client.js
devtools/client/webide/preferences/webide.js
devtools/shared/preferences/devtools-shared.js
devtools/startup/preferences/devtools-startup.js
extensions/pref/autoconfig/test/unit/autoconfig.js extensions/pref/autoconfig/test/unit/autoconfig.js
mobile/android/app/geckoview-prefs.js mobile/android/app/geckoview-prefs.js
mobile/android/app/mobile.js mobile/android/app/mobile.js

82
Cargo.lock generated
View File

@ -1,15 +1,5 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]]
name = "Inflector"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
dependencies = [
"lazy_static",
"regex",
]
[[package]] [[package]]
name = "adler32" name = "adler32"
version = "1.0.3" version = "1.0.3"
@ -25,15 +15,6 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi 0.3.7",
]
[[package]] [[package]]
name = "app_units" name = "app_units"
version = "0.7.0" version = "0.7.0"
@ -212,19 +193,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff" checksum = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff"
[[package]]
name = "binast"
version = "0.2.0"
dependencies = [
"Inflector",
"binjs_meta",
"clap",
"env_logger",
"itertools",
"log",
"yaml-rust",
]
[[package]] [[package]]
name = "bincode" name = "bincode"
version = "1.2.1" version = "1.2.1"
@ -255,18 +223,6 @@ dependencies = [
"shlex", "shlex",
] ]
[[package]]
name = "binjs_meta"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d535cc5246fd9035268770420afd76c05f87e68b83ebed0ac94e8258e88fc353"
dependencies = [
"Inflector",
"itertools",
"log",
"weedle",
]
[[package]] [[package]]
name = "bit-vec" name = "bit-vec"
version = "0.5.1" version = "0.5.1"
@ -516,14 +472,11 @@ version = "2.31.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" checksum = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
dependencies = [ dependencies = [
"ansi_term",
"atty",
"bitflags", "bitflags",
"strsim", "strsim",
"term_size", "term_size",
"textwrap", "textwrap",
"unicode-width", "unicode-width",
"vec_map",
] ]
[[package]] [[package]]
@ -750,9 +703,9 @@ dependencies = [
[[package]] [[package]]
name = "cssparser" name = "cssparser"
version = "0.27.2" version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" checksum = "809d22aba9ffd53e9028f2d37261f1826ef613d0e96b1a5ddeefa97cde82bcca"
dependencies = [ dependencies = [
"cssparser-macros", "cssparser-macros",
"dtoa-short", "dtoa-short",
@ -1726,12 +1679,6 @@ dependencies = [
"safemem", "safemem",
] ]
[[package]]
name = "linked-hash-map"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e"
[[package]] [[package]]
name = "lmdb-rkv" name = "lmdb-rkv"
version = "0.14.0" version = "0.14.0"
@ -2476,6 +2423,7 @@ dependencies = [
"goblin", "goblin",
"memmap", "memmap",
"object", "object",
"rustc-demangle",
"thin-vec", "thin-vec",
"uuid", "uuid",
] ]
@ -3733,12 +3681,6 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" checksum = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
[[package]]
name = "vec_map"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.1" version = "0.9.1"
@ -3922,15 +3864,6 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "weedle"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7d4f9feb723a800d8f7b74edc9fa44ff35cb0b2ec64886714362f423427f37"
dependencies = [
"nom",
]
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.2.8" version = "0.2.8"
@ -4086,15 +4019,6 @@ dependencies = [
"xpcom", "xpcom",
] ]
[[package]]
name = "yaml-rust"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95acf0db5515d07da9965ec0e0ba6cc2d825e2caeb7303b66ca441729801254e"
dependencies = [
"linked-hash-map",
]
[[package]] [[package]]
name = "zip" name = "zip"
version = "0.4.2" version = "0.4.2"

View File

@ -9,7 +9,6 @@ members = [
"js/src/rust", "js/src/rust",
"js/src/wasm/cranelift", "js/src/wasm/cranelift",
"js/rust", "js/rust",
"js/src/frontend/binast", # Code generator.
"testing/geckodriver", "testing/geckodriver",
"toolkit/crashreporter/rust", "toolkit/crashreporter/rust",
"toolkit/library/gtest/rust", "toolkit/library/gtest/rust",

View File

@ -35,3 +35,10 @@ Then report like for site 'x' is missing feature 'y'
**YOU MAY DONATE** **YOU MAY DONATE**
But only by crypto [Look here](https://github.com/Feodor2/Mypal68/issues/84) But only by crypto [Look here](https://github.com/Feodor2/Mypal68/issues/84)
**MY MIRROR PAGES**
https://codeberg.org/Theodor2/Mypal68
https://notabug.org/Theodor/Mypal68

View File

@ -267,8 +267,7 @@ void EventQueue::CoalesceSelChangeEvents(AccSelChangeEvent* aTailEvent,
void EventQueue::ProcessEventQueue() { void EventQueue::ProcessEventQueue() {
// Process only currently queued events. // Process only currently queued events.
nsTArray<RefPtr<AccEvent> > events; const nsTArray<RefPtr<AccEvent> > events = std::move(mEvents);
events.SwapElements(mEvents);
uint32_t eventCount = events.Length(); uint32_t eventCount = events.Length();
#ifdef A11Y_LOG #ifdef A11Y_LOG

View File

@ -830,7 +830,7 @@ nsresult Accessible::HandleAccEvent(AccEvent* aEvent) {
nsAutoCString strMarker; nsAutoCString strMarker;
strMarker.AppendLiteral("A11y Event - "); strMarker.AppendLiteral("A11y Event - ");
strMarker.Append(strEventType); strMarker.Append(strEventType);
profiler_add_marker(strMarker.get(), JS::ProfilingCategoryPair::OTHER); PROFILER_ADD_MARKER(strMarker.get(), OTHER);
} }
#endif #endif

View File

@ -173,7 +173,7 @@ static void AddRelation(Accessible* aAcc, RelationType aType,
if (!targets.IsEmpty()) { if (!targets.IsEmpty()) {
RelationTargets* newRelation = aTargets->AppendElement( RelationTargets* newRelation = aTargets->AppendElement(
RelationTargets(static_cast<uint32_t>(aType), nsTArray<uint64_t>())); RelationTargets(static_cast<uint32_t>(aType), nsTArray<uint64_t>()));
newRelation->Targets().SwapElements(targets); newRelation->Targets() = std::move(targets);
} }
} }

View File

@ -586,9 +586,17 @@ class ContextMenuChild extends ActorChild {
let referrerInfo = Cc["@mozilla.org/referrer-info;1"].createInstance( let referrerInfo = Cc["@mozilla.org/referrer-info;1"].createInstance(
Ci.nsIReferrerInfo Ci.nsIReferrerInfo
); );
referrerInfo.initWithElement( referrerInfo.initWithElement(aEvent.composedTarget);
context.onLink ? context.link : aEvent.composedTarget
); // In the case "onLink" we may have to send link referrerInfo to use in
// _openLinkInParameters
let linkReferrerInfo = null;
if (context.onLink) {
linkReferrerInfo = Cc["@mozilla.org/referrer-info;1"].createInstance(
Ci.nsIReferrerInfo
);
linkReferrerInfo.initWithElement(context.link);
}
let targetAsCPOW = context.target; let targetAsCPOW = context.target;
if (targetAsCPOW) { if (targetAsCPOW) {
@ -652,17 +660,12 @@ class ContextMenuChild extends ActorChild {
); );
} }
// In the case "onLink" we may have to send target referrerInfo. This object if (linkReferrerInfo) {
// may be used to in saveMedia function. if (isRemote) {
if (context.onLink) { data.linkReferrerInfo = E10SUtils.serializeReferrerInfo(linkReferrerInfo);
let targetReferrerInfo = Cc[ } else {
"@mozilla.org/referrer-info;1" data.linkReferrerInfo = linkReferrerInfo;
].createInstance(Ci.nsIReferrerInfo); }
targetReferrerInfo.initWithElement(aEvent.composedTarget);
data.targetReferrerInfo = E10SUtils.serializeReferrerInfo(
targetReferrerInfo
);
} }
Services.obs.notifyObservers( Services.obs.notifyObservers(

View File

@ -1715,3 +1715,413 @@ pref("identity.fxaccounts.toolbar.accessed", false);
#else #else
pref("corroborator.enabled", true); pref("corroborator.enabled", true);
#endif #endif
// Disable WebIDE and ConnectPage by default (Bug 1539451)
pref("devtools.webide.enabled", false);
pref("devtools.connectpage.enabled", false);
// Toolbox preferences
pref("devtools.toolbox.footer.height", 250);
pref("devtools.toolbox.sidebar.width", 500);
pref("devtools.toolbox.host", "bottom");
pref("devtools.toolbox.previousHost", "right");
pref("devtools.toolbox.selectedTool", "inspector");
pref("devtools.toolbox.sideEnabled", true);
pref("devtools.toolbox.zoomValue", "1");
pref("devtools.toolbox.splitconsoleEnabled", false);
pref("devtools.toolbox.splitconsoleHeight", 100);
pref("devtools.toolbox.tabsOrder", "");
// Toolbox Button preferences
pref("devtools.command-button-pick.enabled", true);
pref("devtools.command-button-frames.enabled", true);
pref("devtools.command-button-splitconsole.enabled", true);
pref("devtools.command-button-paintflashing.enabled", false);
pref("devtools.command-button-scratchpad.enabled", false);
pref("devtools.command-button-responsive.enabled", true);
pref("devtools.command-button-screenshot.enabled", false);
pref("devtools.command-button-rulers.enabled", false);
pref("devtools.command-button-measure.enabled", false);
pref("devtools.command-button-noautohide.enabled", false);
// Inspector preferences
// Enable the Inspector
pref("devtools.inspector.enabled", true);
// What was the last active sidebar in the inspector
pref("devtools.inspector.activeSidebar", "layoutview");
pref("devtools.inspector.remote", false);
// Enable the 3 pane mode in the inspector
pref("devtools.inspector.three-pane-enabled", true);
// Enable the 3 pane mode in the chrome inspector
pref("devtools.inspector.chrome.three-pane-enabled", false);
// Collapse pseudo-elements by default in the rule-view
pref("devtools.inspector.show_pseudo_elements", false);
// The default size for image preview tooltips in the rule-view/computed-view/markup-view
pref("devtools.inspector.imagePreviewTooltipSize", 300);
// Enable user agent style inspection in rule-view
pref("devtools.inspector.showUserAgentStyles", false);
// Show all native anonymous content
pref("devtools.inspector.showAllAnonymousContent", false);
// Show user agent shadow roots
pref("devtools.inspector.showUserAgentShadowRoots", false);
// Enable the new Rules View
pref("devtools.inspector.new-rulesview.enabled", false);
// Grid highlighter preferences
pref("devtools.gridinspector.gridOutlineMaxColumns", 50);
pref("devtools.gridinspector.gridOutlineMaxRows", 50);
pref("devtools.gridinspector.showGridAreas", false);
pref("devtools.gridinspector.showGridLineNumbers", false);
pref("devtools.gridinspector.showInfiniteLines", false);
// Max number of grid highlighters that can be displayed
pref("devtools.gridinspector.maxHighlighters", 3);
// Whether or not the box model panel is opened in the layout view
pref("devtools.layout.boxmodel.opened", true);
// Whether or not the flexbox panel is opened in the layout view
pref("devtools.layout.flexbox.opened", true);
// Whether or not the grid inspector panel is opened in the layout view
pref("devtools.layout.grid.opened", true);
// Enable hovering Box Model values and jumping to their source CSS rule in the
// rule-view.
#if defined(NIGHTLY_BUILD)
pref("devtools.layout.boxmodel.highlightProperty", true);
#else
pref("devtools.layout.boxmodel.highlightProperty", false);
#endif
// By how many times eyedropper will magnify pixels
pref("devtools.eyedropper.zoom", 6);
// Enable to collapse attributes that are too long.
pref("devtools.markup.collapseAttributes", true);
// Length to collapse attributes
pref("devtools.markup.collapseAttributeLength", 120);
// Whether to auto-beautify the HTML on copy.
pref("devtools.markup.beautifyOnCopy", false);
// Whether or not the DOM mutation breakpoints context menu are enabled in the
// markup view.
pref("devtools.markup.mutationBreakpoints.enabled", true);
// DevTools default color unit
pref("devtools.defaultColorUnit", "authored");
// Enable the Memory tools
pref("devtools.memory.enabled", true);
pref("devtools.memory.custom-census-displays", "{}");
pref("devtools.memory.custom-label-displays", "{}");
pref("devtools.memory.custom-tree-map-displays", "{}");
pref("devtools.memory.max-individuals", 1000);
pref("devtools.memory.max-retaining-paths", 10);
// Enable the Performance tools
pref("devtools.performance.enabled", true);
// The default Performance UI settings
pref("devtools.performance.memory.sample-probability", "0.05");
// Can't go higher than this without causing internal allocation overflows while
// serializing the allocations data over the RDP.
pref("devtools.performance.memory.max-log-length", 125000);
pref("devtools.performance.timeline.hidden-markers",
"[\"Composite\",\"CompositeForwardTransaction\"]");
pref("devtools.performance.profiler.buffer-size", 10000000);
pref("devtools.performance.profiler.sample-frequency-hz", 1000);
pref("devtools.performance.ui.invert-call-tree", true);
pref("devtools.performance.ui.invert-flame-graph", false);
pref("devtools.performance.ui.flatten-tree-recursion", true);
pref("devtools.performance.ui.show-platform-data", false);
pref("devtools.performance.ui.show-idle-blocks", true);
pref("devtools.performance.ui.enable-memory", false);
pref("devtools.performance.ui.enable-allocations", false);
pref("devtools.performance.ui.enable-framerate", true);
pref("devtools.performance.ui.show-jit-optimizations", false);
pref("devtools.performance.ui.show-triggers-for-gc-types",
"TOO_MUCH_MALLOC ALLOC_TRIGGER LAST_DITCH EAGER_ALLOC_TRIGGER");
// Temporary pref disabling memory flame views
// TODO remove once we have flame charts via bug 1148663
pref("devtools.performance.ui.enable-memory-flame", false);
// Enable experimental options in the UI only in Nightly
#if defined(NIGHTLY_BUILD)
pref("devtools.performance.ui.experimental", true);
#else
pref("devtools.performance.ui.experimental", false);
#endif
// Preferences for the new performance panel. This pref configures the base URL
// for the profiler.firefox.com instance to use. This is useful so that a
// developer can change it while working on profiler.firefox.com, or in tests.
// This isn't exposed directly to the user.
pref("devtools.performance.recording.ui-base-url", "https://profiler.firefox.com");
// A JSON array of strings, where each string is a file path to an objdir on
// the host machine. This is used in order to look up symbol information from
// build artifacts of local builds.
pref("devtools.performance.recording.objdirs", "[]");
// The default cache UI setting
pref("devtools.cache.disabled", false);
// The default service workers UI setting
pref("devtools.serviceWorkers.testing.enabled", false);
// Enable the Network Monitor
pref("devtools.netmonitor.enabled", true);
// Enable the Application panel
pref("devtools.application.enabled", false);
// The default Network Monitor UI settings
pref("devtools.netmonitor.panes-network-details-width", 550);
pref("devtools.netmonitor.panes-network-details-height", 450);
pref("devtools.netmonitor.filters", "[\"all\"]");
pref("devtools.netmonitor.visibleColumns",
"[\"status\",\"method\",\"domain\",\"file\",\"cause\",\"type\",\"transferred\",\"contentSize\",\"waterfall\"]"
);
pref("devtools.netmonitor.columnsData",
'[{"name":"status","minWidth":30,"width":5}, {"name":"method","minWidth":30,"width":5}, {"name":"domain","minWidth":30,"width":10}, {"name":"file","minWidth":30,"width":25}, {"name":"url","minWidth":30,"width":25}, {"name":"cause","minWidth":30,"width":10},{"name":"type","minWidth":30,"width":5},{"name":"transferred","minWidth":30,"width":10},{"name":"contentSize","minWidth":30,"width":5},{"name":"waterfall","minWidth":150,"width":25}]');
pref("devtools.netmonitor.ws.payload-preview-height", 128);
pref("devtools.netmonitor.ws.visibleColumns",
'["data", "time"]'
);
pref("devtools.netmonitor.ws.displayed-frames.limit", 500);
pref("devtools.netmonitor.response.ui.limit", 10240);
// Save request/response bodies yes/no.
pref("devtools.netmonitor.saveRequestAndResponseBodies", true);
// The default Network monitor HAR export setting
pref("devtools.netmonitor.har.defaultLogDir", "");
pref("devtools.netmonitor.har.defaultFileName", "%hostname_Archive [%date]");
pref("devtools.netmonitor.har.jsonp", false);
pref("devtools.netmonitor.har.jsonpCallback", "");
pref("devtools.netmonitor.har.includeResponseBodies", true);
pref("devtools.netmonitor.har.compress", false);
pref("devtools.netmonitor.har.forceExport", false);
pref("devtools.netmonitor.har.pageLoadedTimeout", 1500);
pref("devtools.netmonitor.har.enableAutoExportToFile", false);
// Enable WebSocket monitoring in Nightly builds.
#if defined(NIGHTLY_BUILD)
pref("devtools.netmonitor.features.webSockets", true);
#else
pref("devtools.netmonitor.features.webSockets", false);
#endif
// Scratchpad settings
// - recentFileMax: The maximum number of recently-opened files
// stored. Setting this preference to 0 will not
// clear any recent files, but rather hide the
// 'Open Recent'-menu.
// - lineNumbers: Whether to show line numbers or not.
// - wrapText: Whether to wrap text or not.
// - showTrailingSpace: Whether to highlight trailing space or not.
// - editorFontSize: Editor font size configuration.
// - enableAutocompletion: Whether to enable JavaScript autocompletion.
pref("devtools.scratchpad.recentFilesMax", 10);
pref("devtools.scratchpad.lineNumbers", true);
pref("devtools.scratchpad.wrapText", false);
pref("devtools.scratchpad.showTrailingSpace", false);
pref("devtools.scratchpad.editorFontSize", 12);
pref("devtools.scratchpad.enableAutocompletion", true);
// Enable the Storage Inspector
pref("devtools.storage.enabled", true);
// Enable the Style Editor.
pref("devtools.styleeditor.enabled", true);
pref("devtools.styleeditor.autocompletion-enabled", true);
pref("devtools.styleeditor.showMediaSidebar", true);
pref("devtools.styleeditor.mediaSidebarWidth", 238);
pref("devtools.styleeditor.navSidebarWidth", 245);
pref("devtools.styleeditor.transitions", true);
// Screenshot Option Settings.
pref("devtools.screenshot.clipboard.enabled", false);
pref("devtools.screenshot.audio.enabled", true);
// Enable Scratchpad
pref("devtools.scratchpad.enabled", false);
// Make sure the DOM panel is hidden by default
pref("devtools.dom.enabled", false);
// Enable the Accessibility panel.
pref("devtools.accessibility.enabled", true);
// Web console filters
pref("devtools.webconsole.filter.error", true);
pref("devtools.webconsole.filter.warn", true);
pref("devtools.webconsole.filter.info", true);
pref("devtools.webconsole.filter.log", true);
pref("devtools.webconsole.filter.debug", true);
pref("devtools.webconsole.filter.css", false);
pref("devtools.webconsole.filter.net", false);
pref("devtools.webconsole.filter.netxhr", false);
// Webconsole autocomplete preference
pref("devtools.webconsole.input.autocomplete",true);
// Browser console filters
pref("devtools.browserconsole.filter.error", true);
pref("devtools.browserconsole.filter.warn", true);
pref("devtools.browserconsole.filter.info", true);
pref("devtools.browserconsole.filter.log", true);
pref("devtools.browserconsole.filter.debug", true);
pref("devtools.browserconsole.filter.css", false);
pref("devtools.browserconsole.filter.net", false);
pref("devtools.browserconsole.filter.netxhr", false);
// Max number of inputs to store in web console history.
pref("devtools.webconsole.inputHistoryCount", 300);
// Persistent logging: |true| if you want the relevant tool to keep all of the
// logged messages after reloading the page, |false| if you want the output to
// be cleared each time page navigation happens.
pref("devtools.webconsole.persistlog", false);
pref("devtools.netmonitor.persistlog", false);
// Web Console timestamp: |true| if you want the logs and instructions
// in the Web Console to display a timestamp, or |false| to not display
// any timestamps.
pref("devtools.webconsole.timestampMessages", false);
// Enable the webconsole sidebar toggle in Nightly builds.
#if defined(NIGHTLY_BUILD)
pref("devtools.webconsole.sidebarToggle", true);
#else
pref("devtools.webconsole.sidebarToggle", false);
#endif
// Enable editor mode in the console in Nightly builds.
#if defined(NIGHTLY_BUILD)
pref("devtools.webconsole.features.editor", true);
#else
pref("devtools.webconsole.features.editor", false);
#endif
// Saved editor mode state in the console.
pref("devtools.webconsole.input.editor", false);
// Editor width for webconsole and browserconsole
pref("devtools.webconsole.input.editorWidth", 0);
pref("devtools.browserconsole.input.editorWidth", 0);
// Disable the new performance recording panel by default
pref("devtools.performance.new-panel-enabled", false);
// Enable message grouping in the console, true by default
pref("devtools.webconsole.groupWarningMessages", true);
// Saved state of the Display content messages checkbox in the browser console.
pref("devtools.browserconsole.contentMessages", false);
// Enable client-side mapping service for source maps
pref("devtools.source-map.client-service.enabled", true);
// The number of lines that are displayed in the web console.
pref("devtools.hud.loglimit", 10000);
// The developer tools editor configuration:
// - tabsize: how many spaces to use when a Tab character is displayed.
// - expandtab: expand Tab characters to spaces.
// - keymap: which keymap to use (can be 'default', 'emacs' or 'vim')
// - autoclosebrackets: whether to permit automatic bracket/quote closing.
// - detectindentation: whether to detect the indentation from the file
// - enableCodeFolding: Whether to enable code folding or not.
pref("devtools.editor.tabsize", 2);
pref("devtools.editor.expandtab", true);
pref("devtools.editor.keymap", "default");
pref("devtools.editor.autoclosebrackets", true);
pref("devtools.editor.detectindentation", true);
pref("devtools.editor.enableCodeFolding", true);
pref("devtools.editor.autocomplete", true);
// The angle of the viewport.
pref("devtools.responsive.viewport.angle", 0);
// The width of the viewport.
pref("devtools.responsive.viewport.width", 320);
// The height of the viewport.
pref("devtools.responsive.viewport.height", 480);
// The pixel ratio of the viewport.
pref("devtools.responsive.viewport.pixelRatio", 0);
// Whether or not the viewports are left aligned.
pref("devtools.responsive.leftAlignViewport.enabled", false);
// Whether to reload when touch simulation is toggled
pref("devtools.responsive.reloadConditions.touchSimulation", false);
// Whether to reload when user agent is changed
pref("devtools.responsive.reloadConditions.userAgent", false);
// Whether to show the notification about reloading to apply emulation
pref("devtools.responsive.reloadNotification.enabled", true);
// Whether or not touch simulation is enabled.
pref("devtools.responsive.touchSimulation.enabled", false);
// Whether or not meta viewport is enabled, if and only if touchSimulation
// is also enabled.
pref("devtools.responsive.metaViewport.enabled", false);
// The user agent of the viewport.
pref("devtools.responsive.userAgent", "");
// Whether to show the settings onboarding tooltip only in release or beta
// builds.
#if defined(RELEASE_OR_BETA)
pref("devtools.responsive.show-setting-tooltip", true);
#else
pref("devtools.responsive.show-setting-tooltip", false);
#endif
// Show the custom user agent input in Nightly builds.
#if defined(NIGHTLY_BUILD)
pref("devtools.responsive.showUserAgentInput", true);
#else
pref("devtools.responsive.showUserAgentInput", false);
#endif
// Show tab debug targets for This Firefox (on by default for local builds).
#ifdef MOZILLA_OFFICIAL
pref("devtools.aboutdebugging.local-tab-debugging", false);
#else
pref("devtools.aboutdebugging.local-tab-debugging", true);
#endif
// Show process debug targets.
pref("devtools.aboutdebugging.process-debugging", true);
// Stringified array of network locations that users can connect to.
pref("devtools.aboutdebugging.network-locations", "[]");
// Debug target pane collapse/expand settings.
pref("devtools.aboutdebugging.collapsibilities.installedExtension", false);
pref("devtools.aboutdebugging.collapsibilities.otherWorker", false);
pref("devtools.aboutdebugging.collapsibilities.serviceWorker", false);
pref("devtools.aboutdebugging.collapsibilities.sharedWorker", false);
pref("devtools.aboutdebugging.collapsibilities.tab", false);
pref("devtools.aboutdebugging.collapsibilities.temporaryExtension", false);
// about:debugging: only show system and hidden extensions in local builds by
// default.
#ifdef MOZILLA_OFFICIAL
pref("devtools.aboutdebugging.showHiddenAddons", false);
#else
pref("devtools.aboutdebugging.showHiddenAddons", true);
#endif
// Map top-level await expressions in the console
pref("devtools.debugger.features.map-await-expression", true);
// Disable autohide for DevTools popups and tooltips.
// This is currently not exposed by any UI to avoid making
// about:devtools-toolbox tabs unusable by mistake.
pref("devtools.popup.disable_autohide", false);
pref("devtools.webide.templatesURL", "https://code.cdn.mozilla.net/templates/list.json");
pref("devtools.webide.autoinstallADBExtension", true);
pref("devtools.webide.autoConnectRuntime", true);
pref("devtools.webide.restoreLastProject", true);
pref("devtools.webide.enableLocalRuntime", false);
pref("devtools.webide.lastConnectedRuntime", "");
pref("devtools.webide.lastSelectedProject", "");
pref("devtools.webide.zoom", "1");
pref("devtools.webide.busyTimeout", 10000);

View File

@ -25,6 +25,3 @@ if CONFIG['CC_TYPE'] in ('gcc', 'clang'):
LDFLAGS += [ LDFLAGS += [
'-municode', '-municode',
] ]
if CONFIG['CC_TYPE'] == 'clang-cl':
AllowCompilerWarnings() # workaround for bug 1090497

View File

@ -32,3 +32,8 @@ var AboutRestartRequired = {
}; };
AboutRestartRequired.init(); AboutRestartRequired.init();
let restartButton = document.getElementById("restart");
restartButton.onclick = function() {
AboutRestartRequired.restart();
};

View File

@ -6,6 +6,7 @@
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
<meta http-equiv="Content-Security-Policy" content="default-src chrome:" />
<title data-l10n-id="restart-required-title"></title> <title data-l10n-id="restart-required-title"></title>
<link rel="stylesheet" type="text/css" media="all" <link rel="stylesheet" type="text/css" media="all"
href="chrome://browser/skin/aboutRestartRequired.css"/> href="chrome://browser/skin/aboutRestartRequired.css"/>
@ -33,8 +34,7 @@
</div> </div>
<!-- Restart Button --> <!-- Restart Button -->
<div id="restartButtonContainer" class="button-container"> <div id="restartButtonContainer" class="button-container">
<button id="restart" data-l10n-id="restart-button-label" class="primary" autocomplete="off" <button id="restart" data-l10n-id="restart-button-label" class="primary" autocomplete="off"></button>
onclick="AboutRestartRequired.restart();"></button>
</div> </div>
</div> </div>
</body> </body>

View File

@ -3381,6 +3381,7 @@ function losslessDecodeURI(aURI) {
// This includes all bidirectional formatting characters. // This includes all bidirectional formatting characters.
// (RFC 3987 sections 3.2 and 4.1 paragraph 6) // (RFC 3987 sections 3.2 and 4.1 paragraph 6)
value = value.replace( value = value.replace(
// eslint-disable-next-line no-misleading-character-class
/[\u00ad\u034f\u061c\u115f-\u1160\u17b4-\u17b5\u180b-\u180d\u200b\u200e-\u200f\u202a-\u202e\u2060-\u206f\u3164\ufe00-\ufe0f\ufeff\uffa0\ufff0-\ufff8]|\ud834[\udd73-\udd7a]|[\udb40-\udb43][\udc00-\udfff]/g, /[\u00ad\u034f\u061c\u115f-\u1160\u17b4-\u17b5\u180b-\u180d\u200b\u200e-\u200f\u202a-\u202e\u2060-\u206f\u3164\ufe00-\ufe0f\ufeff\uffa0\ufff0-\ufff8]|\ud834[\udd73-\udd7a]|[\udb40-\udb43][\udc00-\udfff]/g,
encodeURIComponent encodeURIComponent
); );
@ -9276,7 +9277,7 @@ var RestoreLastSessionObserver = {
) { ) {
Services.obs.addObserver(this, "sessionstore-last-session-cleared", true); Services.obs.addObserver(this, "sessionstore-last-session-cleared", true);
goSetCommandEnabled("Browser:RestoreLastSession", true); goSetCommandEnabled("Browser:RestoreLastSession", true);
} else if (SessionStartup.isAutomaticRestoreEnabled()) { } else if (SessionStore.willAutoRestore) {
document document
.getElementById("Browser:RestoreLastSession") .getElementById("Browser:RestoreLastSession")
.setAttribute("hidden", true); .setAttribute("hidden", true);

View File

@ -44,7 +44,7 @@ function openContextMenu(aMessage) {
let browser = aMessage.target; let browser = aMessage.target;
let spellInfo = data.spellInfo; let spellInfo = data.spellInfo;
let frameReferrerInfo = data.frameReferrerInfo; let frameReferrerInfo = data.frameReferrerInfo;
let targetReferrerInfo = data.targetReferrerInfo; let linkReferrerInfo = data.linkReferrerInfo;
// ContextMenu.jsm sends us the target as a CPOW only so that // ContextMenu.jsm sends us the target as a CPOW only so that
// we can send that CPOW back down to the content process and // we can send that CPOW back down to the content process and
@ -68,8 +68,8 @@ function openContextMenu(aMessage) {
E10SUtils.deserializeReferrerInfo(frameReferrerInfo); E10SUtils.deserializeReferrerInfo(frameReferrerInfo);
} }
if (targetReferrerInfo) { if (linkReferrerInfo && data.isRemote) {
targetReferrerInfo = E10SUtils.deserializeReferrerInfo(targetReferrerInfo); linkReferrerInfo = E10SUtils.deserializeReferrerInfo(linkReferrerInfo);
} }
gContextMenuContentData = { gContextMenuContentData = {
@ -86,7 +86,7 @@ function openContextMenu(aMessage) {
charSet: data.charSet, charSet: data.charSet,
referrerInfo: E10SUtils.deserializeReferrerInfo(data.referrerInfo), referrerInfo: E10SUtils.deserializeReferrerInfo(data.referrerInfo),
frameReferrerInfo, frameReferrerInfo,
targetReferrerInfo, linkReferrerInfo,
contentType: data.contentType, contentType: data.contentType,
contentDisposition: data.contentDisposition, contentDisposition: data.contentDisposition,
frameOuterWindowID: data.frameOuterWindowID, frameOuterWindowID: data.frameOuterWindowID,
@ -1094,7 +1094,9 @@ nsContextMenu.prototype = {
params.frameOuterWindowID = this.frameOuterWindowID; params.frameOuterWindowID = this.frameOuterWindowID;
} }
let referrerInfo = gContextMenuContentData.referrerInfo; let referrerInfo = this.onLink
? gContextMenuContentData.linkReferrerInfo
: gContextMenuContentData.referrerInfo;
// If we want to change userContextId, we must be sure that we don't // If we want to change userContextId, we must be sure that we don't
// propagate the referrer. // propagate the referrer.
if ( if (
@ -1371,7 +1373,7 @@ nsContextMenu.prototype = {
); );
// Cache this because we fetch the data async // Cache this because we fetch the data async
let { targetReferrerInfo } = gContextMenuContentData; let referrerInfo = gContextMenuContentData.referrerInfo;
let onMessage = message => { let onMessage = message => {
mm.removeMessageListener( mm.removeMessageListener(
@ -1386,7 +1388,7 @@ nsContextMenu.prototype = {
"SaveImageTitle", "SaveImageTitle",
true, // bypass cache true, // bypass cache
false, // don't skip prompt for where to save false, // don't skip prompt for where to save
targetReferrerInfo, // referrer info referrerInfo, // referrer info
null, // document null, // document
null, // content type null, // content type
null, // content disposition null, // content disposition
@ -1672,6 +1674,10 @@ nsContextMenu.prototype = {
// Save URL of clicked-on link. // Save URL of clicked-on link.
saveLink() { saveLink() {
let referrerInfo = this.onLink
? gContextMenuContentData.linkReferrerInfo
: gContextMenuContentData.referrerInfo;
let isContentWindowPrivate = this.isRemote let isContentWindowPrivate = this.isRemote
? this.ownerDoc.isPrivate ? this.ownerDoc.isPrivate
: undefined; : undefined;
@ -1681,7 +1687,7 @@ nsContextMenu.prototype = {
null, null,
true, true,
this.ownerDoc, this.ownerDoc,
gContextMenuContentData.referrerInfo, referrerInfo,
this.frameOuterWindowID, this.frameOuterWindowID,
this.linkDownload, this.linkDownload,
isContentWindowPrivate isContentWindowPrivate
@ -1701,7 +1707,7 @@ nsContextMenu.prototype = {
let isContentWindowPrivate = this.isRemote let isContentWindowPrivate = this.isRemote
? this.ownerDoc.isPrivate ? this.ownerDoc.isPrivate
: undefined; : undefined;
let referrerInfo = gContextMenuContentData.targetReferrerInfo; let referrerInfo = gContextMenuContentData.referrerInfo;
let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(this.browser); let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(this.browser);
if (this.onCanvas) { if (this.onCanvas) {
// Bypass cache, since it's a data: URL. // Bypass cache, since it's a data: URL.

View File

@ -19,7 +19,7 @@ XPCOMUtils.defineLazyServiceGetters(this, {
// Various tests in this directory may define gTestBrowser, to use as the // Various tests in this directory may define gTestBrowser, to use as the
// default browser under test in some of the functions below. // default browser under test in some of the functions below.
/* global gTestBrowser */ /* global gTestBrowser:true */
/** /**
* Waits a specified number of miliseconds. * Waits a specified number of miliseconds.

View File

@ -32,8 +32,6 @@ var gExceptionPaths = [
// https://github.com/mozilla/activity-stream/issues/3053 // https://github.com/mozilla/activity-stream/issues/3053
"resource://activity-stream/data/content/tippytop/images/", "resource://activity-stream/data/content/tippytop/images/",
// https://github.com/mozilla/activity-stream/issues/3758
"resource://activity-stream/prerendered/",
// browser/extensions/pdfjs/content/build/pdf.js#1999 // browser/extensions/pdfjs/content/build/pdf.js#1999
"resource://pdf.js/web/images/", "resource://pdf.js/web/images/",
@ -266,6 +264,11 @@ if (!isDevtools) {
]) { ]) {
whitelist.add("resource://services-sync/engines/" + module); whitelist.add("resource://services-sync/engines/" + module);
} }
// resource://devtools/shared/worker/loader.js,
// resource://devtools/shared/builtin-modules.js
if (!AppConstants.ENABLE_REMOTE_AGENT) {
whitelist.add("resource://gre/modules/jsdebugger.jsm");
}
} }
if (AppConstants.MOZ_CODE_COVERAGE) { if (AppConstants.MOZ_CODE_COVERAGE) {

View File

@ -281,13 +281,13 @@ add_task(async function checkAllTheFluents() {
domParser.forceEnableDTD(); domParser.forceEnableDTD();
for (let uri of uris) { for (let uri of uris) {
let rawContents = await fetchFile(uri.spec); let rawContents = await fetchFile(uri.spec);
let resource = FluentResource.fromString(rawContents); let resource = new FluentResource(rawContents);
if (!resource) { if (!resource) {
return; return;
} }
for (let [key, val] of resource) { for (let message of resource.body) {
CheckError(domParser, uri, key, val); CheckError(domParser, uri, message.id, message);
} }
} }
}); });

View File

@ -482,9 +482,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
RemotePrompt: "resource:///modules/RemotePrompt.jsm", RemotePrompt: "resource:///modules/RemotePrompt.jsm",
}); });
/* global ContentPrefServiceParent:false, ContentSearch:false,
UpdateListener:false, webrtcUI:false */
/** /**
* IF YOU ADD OR REMOVE FROM THIS LIST, PLEASE UPDATE THE LIST ABOVE AS WELL. * IF YOU ADD OR REMOVE FROM THIS LIST, PLEASE UPDATE THE LIST ABOVE AS WELL.
* XXX Bug 1325373 is for making eslint detect these automatically. * XXX Bug 1325373 is for making eslint detect these automatically.

View File

@ -327,8 +327,14 @@ this.DownloadsViewUI.DownloadElementShell.prototype = {
* Downloads View. * Downloads View.
*/ */
showStatusWithDetails(stateLabel, hoverStatus) { showStatusWithDetails(stateLabel, hoverStatus) {
let referrer =
this.download.source.referrerInfo &&
this.download.source.referrerInfo.originalReferrer
? this.download.source.referrerInfo.originalReferrer.spec
: null;
let [displayHost] = DownloadUtils.getURIHost( let [displayHost] = DownloadUtils.getURIHost(
this.download.source.referrer || this.download.source.url referrer || this.download.source.url
); );
let [displayDate] = DownloadUtils.getReadableDates( let [displayDate] = DownloadUtils.getReadableDates(
new Date(this.download.endTime) new Date(this.download.endTime)

View File

@ -16,3 +16,4 @@ skip-if = (os == 'win' && os_version == '10.0' && ccov) # Bug 1306510
skip-if = true # Bug 1352792 skip-if = true # Bug 1352792
[browser_downloads_panel_height.js] [browser_downloads_panel_height.js]
[browser_downloads_autohide.js] [browser_downloads_autohide.js]
[browser_go_to_download_page.js]

View File

@ -0,0 +1,93 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const ReferrerInfo = Components.Constructor(
"@mozilla.org/referrer-info;1",
"nsIReferrerInfo",
"init"
);
const TEST_REFERRER = "https://example.com/";
registerCleanupFunction(async function() {
await task_resetState();
await PlacesUtils.history.clear();
});
async function addDownload(referrerInfo) {
let startTimeMs = Date.now();
let publicList = await Downloads.getList(Downloads.PUBLIC);
let downloadData = {
source: {
url: "http://www.example.com/test-download.txt",
referrerInfo,
},
target: {
path: gTestTargetFile.path,
},
startTime: new Date(startTimeMs++),
};
let download = await Downloads.createDownload(downloadData);
await publicList.add(download);
await download.start();
}
/**
* Make sure "Go To Download Page" is enabled and works as expected.
*/
add_task(async function test_go_to_download_page() {
let referrerInfo = new ReferrerInfo(
Ci.nsIReferrerInfo.NO_REFERRER,
true,
NetUtil.newURI(TEST_REFERRER)
);
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, TEST_REFERRER);
// Wait for focus first
await promiseFocus();
// Ensure that state is reset in case previous tests didn't finish.
await task_resetState();
// Populate the downloads database with the data required by this test.
await addDownload(referrerInfo);
// Open the user interface and wait for data to be fully loaded.
await task_openPanel();
let win = await openLibrary("Downloads");
registerCleanupFunction(function() {
win.close();
});
let listbox = win.document.getElementById("downloadsRichListBox");
ok(listbox, "download list box present");
// Select one of the downloads.
listbox.itemChildren[0].click();
let contextMenu = win.document.getElementById("downloadsContextMenu");
let popupShownPromise = BrowserTestUtils.waitForEvent(
contextMenu,
"popupshown"
);
EventUtils.synthesizeMouseAtCenter(
listbox.itemChildren[0],
{ type: "contextmenu", button: 2 },
win
);
await popupShownPromise;
// Find and click "Go To Download Page"
let goToDownloadButton = [...contextMenu.children].find(
child => child.command == "downloadsCmd_openReferrer"
);
goToDownloadButton.click();
let newTab = await tabPromise;
ok(newTab, "Go To Download Page opened a new tab");
gBrowser.removeTab(newTab);
});

View File

@ -337,7 +337,7 @@ function generateDocumentation() {
} }
let gInited = false; let gInited = false;
function init() { window.onload = function() {
if (gInited) { if (gInited) {
return; return;
} }
@ -371,7 +371,7 @@ function init() {
sectionButton.click(); sectionButton.click();
} }
}); });
} };
function show(button) { function show(button) {
let current_tab = document.querySelector(".active"); let current_tab = document.querySelector(".active");

View File

@ -8,6 +8,7 @@
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
<meta http-equiv="Content-Security-Policy" content="default-src chrome:" />
<title data-l10n-id="about-policies-title"/> <title data-l10n-id="about-policies-title"/>
<link rel="stylesheet" href="chrome://browser/content/policies/aboutPolicies.css" type="text/css" /> <link rel="stylesheet" href="chrome://browser/content/policies/aboutPolicies.css" type="text/css" />
<link rel="localization" href="branding/brand.ftl"/> <link rel="localization" href="branding/brand.ftl"/>
@ -16,7 +17,7 @@
<link rel="localization" href="browser/policies/policies-descriptions.ftl"/> <link rel="localization" href="browser/policies/policies-descriptions.ftl"/>
<script src="chrome://browser/content/policies/aboutPolicies.js" /> <script src="chrome://browser/content/policies/aboutPolicies.js" />
</head> </head>
<body id="body" onload="init()"> <body id="body">
<div id="categories"> <div id="categories">
<div class="category" selected="true" id="category-active"> <div class="category" selected="true" id="category-active">
<img class="category-icon" src="chrome://browser/content/policies/policies-active.svg"></img> <img class="category-icon" src="chrome://browser/content/policies/policies-active.svg"></img>

View File

@ -166,7 +166,7 @@ const clearLocalStorage = async function(options) {
Services.obs.notifyObservers(null, "extension:purge-localStorage"); Services.obs.notifyObservers(null, "extension:purge-localStorage");
} }
if (Services.lsm.nextGenLocalStorageEnabled) { if (Services.domStorageManager.nextGenLocalStorageEnabled) {
// Ideally we could reuse the logic in Sanitizer.jsm or nsIClearDataService, // Ideally we could reuse the logic in Sanitizer.jsm or nsIClearDataService,
// but this API exposes an ability to wipe data at a much finger granularity // but this API exposes an ability to wipe data at a much finger granularity
// than those APIs. So custom logic is used here to wipe only the QM // than those APIs. So custom logic is used here to wipe only the QM

View File

@ -3,7 +3,7 @@
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm"); const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
const { DebuggerClient } = require("devtools/shared/client/debugger-client"); const { DebuggerClient } = require("devtools/shared/client/debugger-client");
const { DebuggerServer } = require("devtools/server/main"); const { DebuggerServer } = require("devtools/server/debugger-server");
const { gDevTools } = require("devtools/client/framework/devtools"); const { gDevTools } = require("devtools/client/framework/devtools");
const { Toolbox } = require("devtools/client/framework/toolbox"); const { Toolbox } = require("devtools/client/framework/toolbox");
@ -28,9 +28,7 @@ async function setupToolboxTest(extensionId) {
} }
} }
const console = await toolbox.selectTool("webconsole"); const consoleFront = await toolbox.target.getFront("console");
const { hud } = console;
const { jsterm } = hud;
const netmonitor = await toolbox.selectTool("netmonitor"); const netmonitor = await toolbox.selectTool("netmonitor");
@ -38,7 +36,7 @@ async function setupToolboxTest(extensionId) {
// Call a function defined in the target extension to make it // Call a function defined in the target extension to make it
// fetch from an expected http url. // fetch from an expected http url.
await jsterm.execute(`doFetchHTTPRequest("${expectedURL}");`); await consoleFront.evaluateJSAsync(`doFetchHTTPRequest("${expectedURL}");`);
await waitFor(() => { await waitFor(() => {
return !netmonitor.panelWin.document.querySelector( return !netmonitor.panelWin.document.querySelector(
@ -68,7 +66,7 @@ async function setupToolboxTest(extensionId) {
// Call a function defined in the target extension to make assertions // Call a function defined in the target extension to make assertions
// on the network requests collected by the netmonitor panel. // on the network requests collected by the netmonitor panel.
await jsterm.execute( await consoleFront.evaluateJSAsync(
`testNetworkRequestReceived(${JSON.stringify(requests)});` `testNetworkRequestReceived(${JSON.stringify(requests)});`
); );

View File

@ -4,8 +4,7 @@ Services.scriptloader.loadSubScript(
"chrome://mochitests/content/browser/browser/components/places/tests/browser/head.js", "chrome://mochitests/content/browser/browser/components/places/tests/browser/head.js",
this this
); );
/* globals withSidebarTree, synthesizeClickOnSelectedTreeCell, /* globals withSidebarTree, synthesizeClickOnSelectedTreeCell, promiseLibrary, promiseLibraryClosed
* promiseLibrary, promiseLibraryClosed
*/ */
const PAGE = const PAGE =

View File

@ -11,7 +11,6 @@ add_task(async function testPageActionPopupResize() {
}, },
}, },
background: function() { background: function() {
/* global browser */
browser.tabs.query({ active: true, currentWindow: true }, tabs => { browser.tabs.query({ active: true, currentWindow: true }, tabs => {
const tabId = tabs[0].id; const tabId = tabs[0].id;

View File

@ -1,4 +1,4 @@
/* global gBrowser SessionStore */ /* global gBrowser */
"use strict"; "use strict";
add_task(async function test_discarded() { add_task(async function test_discarded() {

View File

@ -1,4 +1,4 @@
/* global gBrowser SessionStore */ /* global gBrowser */
"use strict"; "use strict";
add_task(async function test_highlighted() { add_task(async function test_highlighted() {

View File

@ -1,4 +1,3 @@
data/ data/
logs/ logs/
prerendered/
vendor/ vendor/

View File

@ -19,7 +19,7 @@ module.exports = {
// Temporarily disabled since they aren't vendored into in mozilla central yet // Temporarily disabled since they aren't vendored into in mozilla central yet
// "react-hooks", // require("react-hooks") // "react-hooks", // require("react-hooks")
// "fetch-options", // require("eslint-plugin-fetch-options") "fetch-options", // require("eslint-plugin-fetch-options")
], ],
"settings": { "settings": {
"react": { "react": {
@ -76,7 +76,7 @@ module.exports = {
"rules": { "rules": {
// "react-hooks/rules-of-hooks": 2, // "react-hooks/rules-of-hooks": 2,
// "fetch-options/no-fetch-credentials": 2, "fetch-options/no-fetch-credentials": 2,
"react/jsx-boolean-value": [2, "always"], "react/jsx-boolean-value": [2, "always"],
"react/jsx-closing-bracket-location": [2, "after-props"], "react/jsx-closing-bracket-location": [2, "after-props"],

View File

@ -14,13 +14,8 @@ ChromeUtils.defineModuleGetter(this, "AboutNewTab",
"resource:///modules/AboutNewTab.jsm"); "resource:///modules/AboutNewTab.jsm");
const TOPIC_APP_QUIT = "quit-application-granted"; const TOPIC_APP_QUIT = "quit-application-granted";
const TOPIC_LOCALES_CHANGE = "intl:app-locales-changed";
const TOPIC_CONTENT_DOCUMENT_INTERACTIVE = "content-document-interactive"; const TOPIC_CONTENT_DOCUMENT_INTERACTIVE = "content-document-interactive";
// Automated tests ensure packaged locales are in this list. Copied output of:
// https://github.com/mozilla/activity-stream/blob/master/bin/render-activity-stream-html.js
const ACTIVITY_STREAM_BCP47 = "en-US".split(" ");
const ABOUT_URL = "about:newtab"; const ABOUT_URL = "about:newtab";
const BASE_URL = "resource://activity-stream/"; const BASE_URL = "resource://activity-stream/";
const ACTIVITY_STREAM_PAGES = new Set(["home", "newtab", "welcome"]); const ACTIVITY_STREAM_PAGES = new Set(["home", "newtab", "welcome"]);
@ -35,7 +30,6 @@ const PREF_ACTIVITY_STREAM_DEBUG = "browser.newtabpage.activity-stream.debug";
function AboutNewTabService() { function AboutNewTabService() {
Services.obs.addObserver(this, TOPIC_APP_QUIT); Services.obs.addObserver(this, TOPIC_APP_QUIT);
Services.obs.addObserver(this, TOPIC_LOCALES_CHANGE);
Services.prefs.addObserver(PREF_SEPARATE_PRIVILEGED_CONTENT_PROCESS, this); Services.prefs.addObserver(PREF_SEPARATE_PRIVILEGED_CONTENT_PROCESS, this);
if (!IS_RELEASE_OR_BETA) { if (!IS_RELEASE_OR_BETA) {
Services.prefs.addObserver(PREF_ACTIVITY_STREAM_DEBUG, this); Services.prefs.addObserver(PREF_ACTIVITY_STREAM_DEBUG, this);
@ -71,7 +65,7 @@ function AboutNewTabService() {
* *
* When the URL loaded is about:newtab, the default behavior, or when entered in the * When the URL loaded is about:newtab, the default behavior, or when entered in the
* URL bar, the redirector is hit. The service is then called to return the * URL bar, the redirector is hit. The service is then called to return the
* appropriate activity stream url based on prefs and locales. * appropriate activity stream url based on prefs.
* *
* NOTE: "about:newtab" will always result in a default newtab page, and never an overridden URL. * NOTE: "about:newtab" will always result in a default newtab page, and never an overridden URL.
* *
@ -88,7 +82,6 @@ AboutNewTabService.prototype = {
_newTabURL: ABOUT_URL, _newTabURL: ABOUT_URL,
_activityStreamEnabled: false, _activityStreamEnabled: false,
_activityStreamPath: "",
_activityStreamDebug: false, _activityStreamDebug: false,
_privilegedContentProcess: false, _privilegedContentProcess: false,
_overridden: false, _overridden: false,
@ -105,11 +98,9 @@ AboutNewTabService.prototype = {
case "nsPref:changed": case "nsPref:changed":
if (data === PREF_SEPARATE_PRIVILEGED_CONTENT_PROCESS) { if (data === PREF_SEPARATE_PRIVILEGED_CONTENT_PROCESS) {
this._privilegedContentProcess = Services.prefs.getBoolPref(PREF_SEPARATE_PRIVILEGED_CONTENT_PROCESS); this._privilegedContentProcess = Services.prefs.getBoolPref(PREF_SEPARATE_PRIVILEGED_CONTENT_PROCESS);
this.updatePrerenderedPath();
this.notifyChange(); this.notifyChange();
} else if (!IS_RELEASE_OR_BETA && data === PREF_ACTIVITY_STREAM_DEBUG) { } else if (!IS_RELEASE_OR_BETA && data === PREF_ACTIVITY_STREAM_DEBUG) {
this._activityStreamDebug = Services.prefs.getBoolPref(PREF_ACTIVITY_STREAM_DEBUG, false); this._activityStreamDebug = Services.prefs.getBoolPref(PREF_ACTIVITY_STREAM_DEBUG, false);
this.updatePrerenderedPath();
this.notifyChange(); this.notifyChange();
} }
break; break;
@ -145,10 +136,8 @@ AboutNewTabService.prototype = {
`${BASE_URL}vendor/react${debugString}.js`, `${BASE_URL}vendor/react${debugString}.js`,
`${BASE_URL}vendor/react-dom${debugString}.js`, `${BASE_URL}vendor/react-dom${debugString}.js`,
`${BASE_URL}vendor/prop-types.js`, `${BASE_URL}vendor/prop-types.js`,
`${BASE_URL}vendor/react-intl.js`,
`${BASE_URL}vendor/redux.js`, `${BASE_URL}vendor/redux.js`,
`${BASE_URL}vendor/react-redux.js`, `${BASE_URL}vendor/react-redux.js`,
`${BASE_URL}prerendered/${this.activityStreamLocale}/activity-stream-strings.js`,
`${BASE_URL}data/content/activity-stream.bundle.js`, `${BASE_URL}data/content/activity-stream.bundle.js`,
]; ];
@ -175,10 +164,6 @@ AboutNewTabService.prototype = {
Services.obs.removeObserver(this, TOPIC_CONTENT_DOCUMENT_INTERACTIVE); Services.obs.removeObserver(this, TOPIC_CONTENT_DOCUMENT_INTERACTIVE);
} }
break; break;
case TOPIC_LOCALES_CHANGE:
this.updatePrerenderedPath();
this.notifyChange();
break;
} }
}, },
@ -210,34 +195,23 @@ AboutNewTabService.prototype = {
if (!IS_RELEASE_OR_BETA) { if (!IS_RELEASE_OR_BETA) {
this._activityStreamDebug = Services.prefs.getBoolPref(PREF_ACTIVITY_STREAM_DEBUG, false); this._activityStreamDebug = Services.prefs.getBoolPref(PREF_ACTIVITY_STREAM_DEBUG, false);
} }
this.updatePrerenderedPath();
this._newtabURL = ABOUT_URL; this._newtabURL = ABOUT_URL;
return true; return true;
}, },
/**
* Figure out what path under prerendered to use based on current state.
*/
updatePrerenderedPath() {
// Debug files are specially packaged in a non-localized directory, but with
// dynamic script loading, localized debug is supported.
this._activityStreamPath = `${this._activityStreamDebug &&
!this._privilegedContentProcess ? "static" : this.activityStreamLocale}/`;
},
/* /*
* Returns the default URL. * Returns the default URL.
* *
* This URL depends on various activity stream prefs and locales. Overriding * This URL depends on various activity stream prefs. Overriding
* the newtab page has no effect on the result of this function. * the newtab page has no effect on the result of this function.
*/ */
get defaultURL() { get defaultURL() {
// Generate the desired activity stream resource depending on state, e.g., // Generate the desired activity stream resource depending on state, e.g.,
// resource://activity-stream/prerendered/ar/activity-stream.html // "resource://activity-stream/prerendered/activity-stream.html"
// resource://activity-stream/prerendered/static/activity-stream-debug.html // "resource://activity-stream/prerendered/activity-stream-debug.html"
// "resource://activity-stream/prerendered/activity-stream-noscripts.html"
return [ return [
"resource://activity-stream/prerendered/", "resource://activity-stream/prerendered/",
this._activityStreamPath,
"activity-stream", "activity-stream",
// Debug version loads dev scripts but noscripts separately loads scripts // Debug version loads dev scripts but noscripts separately loads scripts
this._activityStreamDebug && !this._privilegedContentProcess ? "-debug" : "", this._activityStreamDebug && !this._privilegedContentProcess ? "-debug" : "",
@ -287,21 +261,6 @@ AboutNewTabService.prototype = {
return this._activityStreamDebug; return this._activityStreamDebug;
}, },
get activityStreamLocale() {
// Pick the best available locale to match the app locales
return Services.locale.negotiateLanguages(
// Fix up incorrect BCP47 that are actually lang tags as a workaround for
// bug 1479606 returning the wrong values in the content process
Services.locale.appLocalesAsBCP47.map(l => l.replace(/^(ja-JP-mac)$/, "$1os")),
ACTIVITY_STREAM_BCP47,
// defaultLocale's strings aren't necessarily packaged, but en-US' are
"en-US",
Services.locale.langNegStrategyLookup
// Convert the BCP47 to lang tag, which is what is used in our paths, as a
// workaround for bug 1478930 negotiating incorrectly with lang tags
)[0].replace(/^(ja-JP-mac)os$/, "$1");
},
resetNewTabURL() { resetNewTabURL() {
this._overridden = false; this._overridden = false;
this._newTabURL = ABOUT_URL; this._newTabURL = ABOUT_URL;
@ -328,7 +287,6 @@ AboutNewTabService.prototype = {
return; return;
} }
Services.obs.removeObserver(this, TOPIC_APP_QUIT); Services.obs.removeObserver(this, TOPIC_APP_QUIT);
Services.obs.removeObserver(this, TOPIC_LOCALES_CHANGE);
Services.prefs.removeObserver(PREF_SEPARATE_PRIVILEGED_CONTENT_PROCESS, this); Services.prefs.removeObserver(PREF_SEPARATE_PRIVILEGED_CONTENT_PROCESS, this);
if (!IS_RELEASE_OR_BETA) { if (!IS_RELEASE_OR_BETA) {
Services.prefs.removeObserver(PREF_ACTIVITY_STREAM_DEBUG, this); Services.prefs.removeObserver(PREF_ACTIVITY_STREAM_DEBUG, this);

View File

@ -3,8 +3,6 @@ const fs = require("fs");
const {mkdir} = require("shelljs"); const {mkdir} = require("shelljs");
const path = require("path"); const path = require("path");
const {CENTRAL_LOCALES, DEFAULT_LOCALE} = require("./locales");
// Note: DEFAULT_OPTIONS.baseUrl should match BASE_URL in aboutNewTabService.js // Note: DEFAULT_OPTIONS.baseUrl should match BASE_URL in aboutNewTabService.js
// in mozilla-central. // in mozilla-central.
const DEFAULT_OPTIONS = { const DEFAULT_OPTIONS = {
@ -12,52 +10,11 @@ const DEFAULT_OPTIONS = {
baseUrl: "resource://activity-stream/", baseUrl: "resource://activity-stream/",
}; };
// Locales that should be displayed RTL
const RTL_LIST = ["ar", "he", "fa", "ur"];
/**
* Get the language part of the locale.
*/
function getLanguage(locale) {
return locale.split("-")[0];
}
/**
* Get the best strings for a single provided locale using similar locales and
* DEFAULT_LOCALE as fallbacks.
*/
function getStrings(locale, allStrings) {
const availableLocales = Object.keys(allStrings);
const language = getLanguage(locale);
const similarLocales = availableLocales.filter(other =>
other !== locale && getLanguage(other) === language);
// Rank locales from least desired to most desired
const localeFallbacks = [DEFAULT_LOCALE, ...similarLocales, locale];
// Get strings from each locale replacing with those from more desired ones
const desired = Object.assign({}, ...localeFallbacks.map(l => allStrings[l]));
// Only include strings that are currently used (defined by default locale)
return Object.assign({}, ...Object.keys(allStrings[DEFAULT_LOCALE]).map(
key => ({[key]: desired[key]})));
}
/**
* Get the text direction of the locale.
*/
function getTextDirection(locale) {
return RTL_LIST.includes(locale.split("-")[0]) ? "rtl" : "ltr";
}
/** /**
* templateHTML - Generates HTML for activity stream, given some options and * templateHTML - Generates HTML for activity stream, given some options and
* prerendered HTML if necessary. * prerendered HTML if necessary.
* *
* @param {obj} options * @param {obj} options
* {str} options.locale The locale to render in lang="" attribute
* {str} options.direction The language direction to render in dir="" attribute
* {str} options.baseUrl The base URL for all local assets * {str} options.baseUrl The base URL for all local assets
* {bool} options.debug Should we use dev versions of JS libraries? * {bool} options.debug Should we use dev versions of JS libraries?
* {bool} options.noscripts Should we include scripts in the prerendered files? * {bool} options.noscripts Should we include scripts in the prerendered files?
@ -71,10 +28,8 @@ function templateHTML(options) {
`${options.baseUrl}vendor/react${debugString}.js`, `${options.baseUrl}vendor/react${debugString}.js`,
`${options.baseUrl}vendor/react-dom${debugString}.js`, `${options.baseUrl}vendor/react-dom${debugString}.js`,
`${options.baseUrl}vendor/prop-types.js`, `${options.baseUrl}vendor/prop-types.js`,
`${options.baseUrl}vendor/react-intl.js`,
`${options.baseUrl}vendor/redux.js`, `${options.baseUrl}vendor/redux.js`,
`${options.baseUrl}vendor/react-redux.js`, `${options.baseUrl}vendor/react-redux.js`,
`${options.baseUrl}prerendered/${options.locale}/activity-stream-strings.js`,
`${options.baseUrl}data/content/activity-stream.bundle.js`, `${options.baseUrl}data/content/activity-stream.bundle.js`,
]; ];
@ -82,7 +37,7 @@ function templateHTML(options) {
const scriptRender = `\n${scripts.map(script => ` <script src="${script}"></script>`).join("\n")}`; const scriptRender = `\n${scripts.map(script => ` <script src="${script}"></script>`).join("\n")}`;
return `<!doctype html> return `<!doctype html>
<html lang="${options.locale}" dir="${options.direction}"> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; object-src 'none'; script-src resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';"> <meta http-equiv="Content-Security-Policy" content="default-src 'none'; object-src 'none'; script-src resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';">
@ -102,49 +57,24 @@ function templateHTML(options) {
`; `;
} }
/**
* templateJs - Generates a js file that passes the initial state of the prerendered
* DOM to the React version. This is necessary to ensure the checksum matches when
* React mounts so that it can attach to the prerendered elements instead of blowing
* them away.
*
* Note that this may no longer be necessary in React 16 and we should review whether
* it is still necessary.
*
* @param {string} name The name of the global to expose
* @param {string} desc Extra description to include in a js comment
* @param {obj} state The data to expose as a window global
* @return {str} The js file as a string
*/
function templateJs(name, desc, state) {
return `// Note - this is a generated ${desc} file.
window.${name} = ${JSON.stringify(state, null, 2)};
`;
}
/** /**
* writeFiles - Writes to the desired files the result of a template given * writeFiles - Writes to the desired files the result of a template given
* various prerendered data and options. * various prerendered data and options.
* *
* @param {string} name Something to identify in the console
* @param {string} destPath Path to write the files to * @param {string} destPath Path to write the files to
* @param {Map} filesMap Mapping of a string file name to templater * @param {Map} filesMap Mapping of a string file name to templater
* @param {Object} options Various options for the templater * @param {Object} options Various options for the templater
*/ */
function writeFiles(name, destPath, filesMap, options) { function writeFiles(destPath, filesMap, options) {
for (const [file, templater] of filesMap) { for (const [file, templater] of filesMap) {
console.log("\x1b[32m", `${file}`, "\x1b[0m");
fs.writeFileSync(path.join(destPath, file), templater({options})); fs.writeFileSync(path.join(destPath, file), templater({options}));
} }
console.log("\x1b[32m", `${name}`, "\x1b[0m");
} }
const STATIC_FILES = new Map([ const STATIC_FILES = new Map([
["activity-stream-debug.html", ({options}) => templateHTML(options)],
]);
const LOCALIZED_FILES = new Map([
["activity-stream-strings.js", ({options: {locale, strings}}) => templateJs("gActivityStreamStrings", locale, strings)],
["activity-stream.html", ({options}) => templateHTML(options)], ["activity-stream.html", ({options}) => templateHTML(options)],
["activity-stream-debug.html", ({options}) => templateHTML(Object.assign({}, options, {debug: true}))],
["activity-stream-noscripts.html", ({options}) => templateHTML(Object.assign({}, options, {noscripts: true}))], ["activity-stream-noscripts.html", ({options}) => templateHTML(Object.assign({}, options, {noscripts: true}))],
]); ]);
@ -163,74 +93,13 @@ function main() { // eslint-disable-line max-statements
}, },
}); });
const baseOptions = Object.assign({debug: false}, DEFAULT_OPTIONS, args || {}); const options = Object.assign({debug: false}, DEFAULT_OPTIONS, args || {});
const addonPath = path.resolve(__dirname, baseOptions.addonPath); const addonPath = path.resolve(__dirname, options.addonPath);
const allStrings = require(`${baseOptions.addonPath}/data/locales.json`);
const extraLocales = Object.keys(allStrings).filter(locale =>
locale !== DEFAULT_LOCALE && !CENTRAL_LOCALES.includes(locale));
const prerenderedPath = path.join(addonPath, "prerendered"); const prerenderedPath = path.join(addonPath, "prerendered");
console.log(`Writing prerendered files to individual directories under ${prerenderedPath}:`); console.log(`Writing prerendered files to ${prerenderedPath}:`);
// Save default locale's strings to compare against other locales' strings mkdir("-p", prerenderedPath);
let defaultStrings; writeFiles(prerenderedPath, STATIC_FILES, options);
let langStrings;
const isSubset = (strings, existing) => existing &&
Object.keys(strings).every(key => strings[key] === existing[key]);
// Process the default locale first then all the ones from mozilla-central
const localizedLocales = [];
const skippedLocales = [];
for (const locale of [DEFAULT_LOCALE, ...CENTRAL_LOCALES]) {
// Skip the locale if it would have resulted in duplicate packaged files
const strings = getStrings(locale, allStrings);
if (isSubset(strings, defaultStrings) || isSubset(strings, langStrings)) {
skippedLocales.push(locale);
continue;
}
const options = Object.assign({}, baseOptions, {
direction: getTextDirection(locale),
locale,
strings,
});
// Put locale-specific files in their own directory
const localePath = path.join(prerenderedPath, "locales", locale);
mkdir("-p", localePath);
writeFiles(locale, localePath, LOCALIZED_FILES, options);
// Only write static files once for the default locale
if (locale === DEFAULT_LOCALE) {
const staticPath = path.join(prerenderedPath, "static");
mkdir("-p", staticPath);
writeFiles(`${locale} (static)`, staticPath, STATIC_FILES,
Object.assign({}, options, {debug: true}));
// Save the default strings to compare against other locales' strings
defaultStrings = strings;
}
// Save the language's strings to maybe reuse for the next similar locales
if (getLanguage(locale) === locale) {
langStrings = strings;
}
localizedLocales.push(locale);
}
if (skippedLocales.length) {
console.log("\x1b[33m", `Skipped the following locales because they use the same strings as ${DEFAULT_LOCALE} or its language locale: ${skippedLocales.join(", ")}`, "\x1b[0m");
}
if (extraLocales.length) {
console.log("\x1b[33m", `Skipped the following locales because they are not in CENTRAL_LOCALES: ${extraLocales.join(", ")}`, "\x1b[0m");
}
// Convert ja-JP-mac lang tag to ja-JP-macos bcp47 to work around bug 1478930
const bcp47String = localizedLocales.join(" ").replace(/(ja-JP-mac)/, "$1os");
// Provide some help to copy/paste locales if tests are failing
console.log(`\nIf aboutNewTabService tests are failing for unexpected locales, make sure its list is updated:\nconst ACTIVITY_STREAM_BCP47 = "${bcp47String}".split(" ");`);
} }
main(); main();

View File

@ -13,8 +13,6 @@ const filesToVendor = {
"react/umd/react.development.js": "react-dev.js", "react/umd/react.development.js": "react-dev.js",
"react-dom/umd/react-dom.production.min.js": "react-dom.js", "react-dom/umd/react-dom.production.min.js": "react-dom.js",
"react-dom/umd/react-dom.development.js": "react-dom-dev.js", "react-dom/umd/react-dom.development.js": "react-dom-dev.js",
"react-intl/LICENSE.md": "REACT_INTL_LICENSE",
"react-intl/dist/react-intl.min.js": "react-intl.js",
"react-redux/LICENSE.md": "REACT_REDUX_LICENSE", "react-redux/LICENSE.md": "REACT_REDUX_LICENSE",
"react-redux/dist/react-redux.min.js": "react-redux.js", "react-redux/dist/react-redux.min.js": "react-redux.js",
}; };

View File

@ -14,7 +14,6 @@ browser.jar:
res/activity-stream/vendor/react-dom-dev.js (./vendor/react-dom-dev.js) res/activity-stream/vendor/react-dom-dev.js (./vendor/react-dom-dev.js)
#endif #endif
res/activity-stream/vendor/prop-types.js (./vendor/prop-types.js) res/activity-stream/vendor/prop-types.js (./vendor/prop-types.js)
res/activity-stream/vendor/react-intl.js (./vendor/react-intl.js)
res/activity-stream/vendor/redux.js (./vendor/redux.js) res/activity-stream/vendor/redux.js (./vendor/redux.js)
res/activity-stream/vendor/react-redux.js (./vendor/react-redux.js) res/activity-stream/vendor/react-redux.js (./vendor/react-redux.js)
res/activity-stream/data/content/assets/ (./data/content/assets/*) res/activity-stream/data/content/assets/ (./data/content/assets/*)
@ -27,7 +26,8 @@ browser.jar:
#else #else
res/activity-stream/css/activity-stream.css (./css/activity-stream-linux.css) res/activity-stream/css/activity-stream.css (./css/activity-stream-linux.css)
#endif #endif
res/activity-stream/prerendered/activity-stream.html (./prerendered/activity-stream.html)
#ifndef RELEASE_OR_BETA #ifndef RELEASE_OR_BETA
res/activity-stream/prerendered/static/activity-stream-debug.html (./prerendered/static/activity-stream-debug.html) res/activity-stream/prerendered/activity-stream-debug.html (./prerendered/activity-stream-debug.html)
#endif #endif
res/activity-stream/prerendered/ (./prerendered/locales/*) res/activity-stream/prerendered/activity-stream-noscripts.html (./prerendered/activity-stream-noscripts.html)

View File

@ -6,8 +6,8 @@
const { AboutNewTab } = ChromeUtils.import( const { AboutNewTab } = ChromeUtils.import(
"resource:///modules/AboutNewTab.jsm" "resource:///modules/AboutNewTab.jsm"
); // Remove when updating eslint-plugin-mozilla 0.14.0+ );
/* globals RemotePages */ const { RemotePages } = ChromeUtils.import( const { RemotePages } = ChromeUtils.import(
"resource://gre/modules/remotepagemanager/RemotePageManagerParent.jsm" "resource://gre/modules/remotepagemanager/RemotePageManagerParent.jsm"
); );

View File

@ -49,11 +49,6 @@ interface nsIAboutNewTabService : nsISupports
*/ */
readonly attribute bool activityStreamDebug; readonly attribute bool activityStreamDebug;
/**
* Returns the locale of the activity stream interface
*/
readonly attribute ACString activityStreamLocale;
/** /**
* Resets to the default resource and also resets the * Resets to the default resource and also resets the
* overridden attribute to false. * overridden attribute to false.

View File

@ -5361,32 +5361,6 @@
"integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
"dev": true "dev": true
}, },
"intl-format-cache": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/intl-format-cache/-/intl-format-cache-2.2.2.tgz",
"integrity": "sha512-B5XmTTcF7Yz5VACwVLmAUkqK27RnOCvgi0kwA6Al/vzVPHy+h+G8J7SCyzZDMjb/UB8fqBEyrzecyn1ksRIi9A=="
},
"intl-messageformat": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-2.2.0.tgz",
"integrity": "sha1-NFvNRt5jC3aDMwwuUhd/9eq0hPw=",
"requires": {
"intl-messageformat-parser": "1.4.0"
}
},
"intl-messageformat-parser": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.4.0.tgz",
"integrity": "sha1-tD1FqXRoytvkQzHXS7Ho3qRPwHU="
},
"intl-relativeformat": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/intl-relativeformat/-/intl-relativeformat-2.1.1.tgz",
"integrity": "sha512-bAhhgiCiN+MVjQeK2v9YqCRJQ8FfV0tk9WVh1RYkRJerpYhmpBe2I4XxpneY232Cp9ujHVl3Q465UJkHQEQdmQ==",
"requires": {
"intl-messageformat": "^2.0.0"
}
},
"invariant": { "invariant": {
"version": "2.2.4", "version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
@ -8718,18 +8692,6 @@
} }
} }
}, },
"react-intl": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/react-intl/-/react-intl-2.9.0.tgz",
"integrity": "sha512-27jnDlb/d2A7mSJwrbOBnUgD+rPep+abmoJE511Tf8BnoONIAUehy/U1zZCHGO17mnOwMWxqN4qC0nW11cD6rA==",
"requires": {
"hoist-non-react-statics": "^3.3.0",
"intl-format-cache": "^2.0.5",
"intl-messageformat": "^2.1.0",
"intl-relativeformat": "^2.1.0",
"invariant": "^2.1.1"
}
},
"react-is": { "react-is": {
"version": "16.8.4", "version": "16.8.4",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.4.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.4.tgz",

View File

@ -11,7 +11,6 @@
"fluent-react": "0.8.4", "fluent-react": "0.8.4",
"react": "16.8.6", "react": "16.8.6",
"react-dom": "16.8.6", "react-dom": "16.8.6",
"react-intl": "2.9.0",
"react-redux": "7.0.3", "react-redux": "7.0.3",
"redux": "4.0.1", "redux": "4.0.1",
"reselect": "4.0.0" "reselect": "4.0.0"

View File

@ -1,5 +1,5 @@
<!doctype html> <!doctype html>
<html lang="en-US" dir="ltr"> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; object-src 'none'; script-src resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';"> <meta http-equiv="Content-Security-Policy" content="default-src 'none'; object-src 'none'; script-src resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';">
@ -19,10 +19,8 @@
<script src="resource://activity-stream/vendor/react-dev.js"></script> <script src="resource://activity-stream/vendor/react-dev.js"></script>
<script src="resource://activity-stream/vendor/react-dom-dev.js"></script> <script src="resource://activity-stream/vendor/react-dom-dev.js"></script>
<script src="resource://activity-stream/vendor/prop-types.js"></script> <script src="resource://activity-stream/vendor/prop-types.js"></script>
<script src="resource://activity-stream/vendor/react-intl.js"></script>
<script src="resource://activity-stream/vendor/redux.js"></script> <script src="resource://activity-stream/vendor/redux.js"></script>
<script src="resource://activity-stream/vendor/react-redux.js"></script> <script src="resource://activity-stream/vendor/react-redux.js"></script>
<script src="resource://activity-stream/prerendered/en-US/activity-stream-strings.js"></script>
<script src="resource://activity-stream/data/content/activity-stream.bundle.js"></script> <script src="resource://activity-stream/data/content/activity-stream.bundle.js"></script>
</body> </body>
</html> </html>

View File

@ -1,5 +1,5 @@
<!doctype html> <!doctype html>
<html lang="en-US" dir="ltr"> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; object-src 'none'; script-src resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';"> <meta http-equiv="Content-Security-Policy" content="default-src 'none'; object-src 'none'; script-src resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';">

View File

@ -1,5 +1,5 @@
<!doctype html> <!doctype html>
<html lang="en-US" dir="ltr"> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; object-src 'none'; script-src resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';"> <meta http-equiv="Content-Security-Policy" content="default-src 'none'; object-src 'none'; script-src resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';">
@ -19,10 +19,8 @@
<script src="resource://activity-stream/vendor/react.js"></script> <script src="resource://activity-stream/vendor/react.js"></script>
<script src="resource://activity-stream/vendor/react-dom.js"></script> <script src="resource://activity-stream/vendor/react-dom.js"></script>
<script src="resource://activity-stream/vendor/prop-types.js"></script> <script src="resource://activity-stream/vendor/prop-types.js"></script>
<script src="resource://activity-stream/vendor/react-intl.js"></script>
<script src="resource://activity-stream/vendor/redux.js"></script> <script src="resource://activity-stream/vendor/redux.js"></script>
<script src="resource://activity-stream/vendor/react-redux.js"></script> <script src="resource://activity-stream/vendor/react-redux.js"></script>
<script src="resource://activity-stream/prerendered/en-US/activity-stream-strings.js"></script>
<script src="resource://activity-stream/data/content/activity-stream.bundle.js"></script> <script src="resource://activity-stream/data/content/activity-stream.bundle.js"></script>
</body> </body>
</html> </html>

View File

@ -1,2 +0,0 @@
// Note - this is a generated en-US file.
window.gActivityStreamStrings = {};

View File

@ -1,27 +0,0 @@
Copyright 2014 Yahoo 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:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of the Yahoo Inc. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 YAHOO! INC. 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.

File diff suppressed because one or more lines are too long

View File

@ -49,7 +49,6 @@ module.exports = (env = {}) => ({
"prop-types": "PropTypes", "prop-types": "PropTypes",
"react": "React", "react": "React",
"react-dom": "ReactDOM", "react-dom": "ReactDOM",
"react-intl": "ReactIntl",
"redux": "Redux", "redux": "Redux",
"react-redux": "ReactRedux", "react-redux": "ReactRedux",
}, },

View File

@ -1,2 +1 @@
[test_registerHandler.html] [test_registerHandler.html]
[test_registerHandler_disabled.html]

View File

@ -1,38 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=402788
-->
<head>
<title>Test for Bug 1398169</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1398169">Mozilla Bug 1398169</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
async function tests() {
await SpecialPowers.pushPrefEnv({
set: [
["dom.registerContentHandler.enabled", false],
["dom.registerProtocolHandler.insecure.enabled", false],
],
});
ok(!navigator.registerContentHandler, "navigator.registerContentHandler should be undefined");
ok(!navigator.registerProtocolHandler, "navigator.registerProtocolHandler should be undefined");
SimpleTest.finish();
}
tests();
</script>
</pre>
</body>
</html>

View File

@ -43,7 +43,6 @@ XPCOMUtils.defineLazyServiceGetter(
XPCOMUtils.defineLazyModuleGetters(this, { XPCOMUtils.defineLazyModuleGetters(this, {
RunState: "resource:///modules/sessionstore/RunState.jsm", RunState: "resource:///modules/sessionstore/RunState.jsm",
SessionStartup: "resource:///modules/sessionstore/SessionStartup.jsm",
SessionStore: "resource:///modules/sessionstore/SessionStore.jsm", SessionStore: "resource:///modules/sessionstore/SessionStore.jsm",
SessionWorker: "resource:///modules/sessionstore/SessionWorker.jsm", SessionWorker: "resource:///modules/sessionstore/SessionWorker.jsm",
}); });
@ -442,8 +441,7 @@ var SessionFileInternal = {
RunState.setClosed(); RunState.setClosed();
} }
let performShutdownCleanup = let performShutdownCleanup = isFinalWrite && !SessionStore.willAutoRestore;
isFinalWrite && !SessionStartup.isAutomaticRestoreEnabled();
this._attempts++; this._attempts++;
let options = { isFinalWrite, performShutdownCleanup }; let options = { isFinalWrite, performShutdownCleanup };

View File

@ -66,15 +66,15 @@ const TYPE_DEFER_SESSION = 3;
// 'browser.startup.page' preference value to resume the previous session. // 'browser.startup.page' preference value to resume the previous session.
const BROWSER_STARTUP_RESUME_SESSION = 3; const BROWSER_STARTUP_RESUME_SESSION = 3;
function warning(aMsg, aException) { function warning(msg, exception) {
let consoleMsg = Cc["@mozilla.org/scripterror;1"].createInstance( let consoleMsg = Cc["@mozilla.org/scripterror;1"].createInstance(
Ci.nsIScriptError Ci.nsIScriptError
); );
consoleMsg.init( consoleMsg.init(
aMsg, msg,
aException.fileName, exception.fileName,
null, null,
aException.lineNumber, exception.lineNumber,
0, 0,
Ci.nsIScriptError.warningFlag, Ci.nsIScriptError.warningFlag,
"component javascript" "component javascript"
@ -101,9 +101,9 @@ var SessionStartup = {
RESUME_SESSION: TYPE_RESUME_SESSION, RESUME_SESSION: TYPE_RESUME_SESSION,
DEFER_SESSION: TYPE_DEFER_SESSION, DEFER_SESSION: TYPE_DEFER_SESSION,
// the state to restore at startup // The state to restore at startup.
_initialState: null, _initialState: null,
_sessionType: TYPE_NO_SESSION, _sessionType: null,
_initialized: false, _initialized: false,
// Stores whether the previous session crashed. // Stores whether the previous session crashed.
@ -116,7 +116,7 @@ var SessionStartup = {
/** /**
* Initialize the component * Initialize the component
*/ */
init: function sss_init() { init() {
Services.obs.notifyObservers(null, "sessionstore-init-started"); Services.obs.notifyObservers(null, "sessionstore-init-started");
StartupPerformance.init(); StartupPerformance.init();
@ -148,25 +148,20 @@ var SessionStartup = {
); );
} }
this._resumeSessionEnabled =
Services.prefs.getBoolPref("browser.sessionstore.resume_session_once") ||
Services.prefs.getIntPref("browser.startup.page") ==
BROWSER_STARTUP_RESUME_SESSION;
SessionFile.read().then(this._onSessionFileRead.bind(this), console.error); SessionFile.read().then(this._onSessionFileRead.bind(this), console.error);
}, },
// Wrap a string as a nsISupports // Wrap a string as a nsISupports.
_createSupportsString: function ssfi_createSupportsString(aData) { _createSupportsString(data) {
let string = Cc["@mozilla.org/supports-string;1"].createInstance( let string = Cc["@mozilla.org/supports-string;1"].createInstance(
Ci.nsISupportsString Ci.nsISupportsString
); );
string.data = aData; string.data = data;
return string; return string;
}, },
/** /**
* Complete initialization once the Session File has been read * Complete initialization once the Session File has been read.
* *
* @param source The Session State string read from disk. * @param source The Session State string read from disk.
* @param parsed The object obtained by parsing |source| as JSON. * @param parsed The object obtained by parsing |source| as JSON.
@ -220,15 +215,11 @@ var SessionStartup = {
); );
}, 60000); }, 60000);
// If this is a normal restore then throw away any previous session // If this is a normal restore then throw away any previous session.
if (!this._resumeSessionEnabled && this._initialState) { if (!this.isAutomaticRestoreEnabled() && this._initialState) {
delete this._initialState.lastSessionState; delete this._initialState.lastSessionState;
} }
let resumeFromCrash = Services.prefs.getBoolPref(
"browser.sessionstore.resume_from_crash"
);
CrashMonitor.previousCheckpoints.then(checkpoints => { CrashMonitor.previousCheckpoints.then(checkpoints => {
if (checkpoints) { if (checkpoints) {
// If the previous session finished writing the final state, we'll // If the previous session finished writing the final state, we'll
@ -242,7 +233,7 @@ var SessionStartup = {
// a version including the Crash Monitor, or if the checkpoints file // a version including the Crash Monitor, or if the checkpoints file
// was removed, or on first startup with this profile, or after Firefox Reset. // was removed, or on first startup with this profile, or after Firefox Reset.
// There was no checkpoints file and no sessionstore.js or its backups // There was no checkpoints file and no sessionstore.js or its backups,
// so we will assume that this was a fresh profile. // so we will assume that this was a fresh profile.
this._previousSessionCrashed = false; this._previousSessionCrashed = false;
} else { } else {
@ -270,19 +261,11 @@ var SessionStartup = {
.getHistogramById("SHUTDOWN_OK") .getHistogramById("SHUTDOWN_OK")
.add(!this._previousSessionCrashed); .add(!this._previousSessionCrashed);
// set the startup type
if (this._previousSessionCrashed && resumeFromCrash) {
this._sessionType = this.RECOVER_SESSION;
} else if (!this._previousSessionCrashed && this._resumeSessionEnabled) {
this._sessionType = this.RESUME_SESSION;
} else if (this._initialState) {
this._sessionType = this.DEFER_SESSION;
} else {
this._initialState = null;
} // reset the state
Services.obs.addObserver(this, "sessionstore-windows-restored", true); Services.obs.addObserver(this, "sessionstore-windows-restored", true);
if (this._sessionType != this.NO_SESSION) { if (this.sessionType == this.NO_SESSION) {
this._initialState = null; // Reset the state.
} else {
Services.obs.addObserver(this, "browser:purge-session-history", true); Services.obs.addObserver(this, "browser:purge-session-history", true);
} }
@ -296,17 +279,17 @@ var SessionStartup = {
/** /**
* Handle notifications * Handle notifications
*/ */
observe: function sss_observe(aSubject, aTopic, aData) { observe(subject, topic, data) {
switch (aTopic) { switch (topic) {
case "sessionstore-windows-restored": case "sessionstore-windows-restored":
Services.obs.removeObserver(this, "sessionstore-windows-restored"); Services.obs.removeObserver(this, "sessionstore-windows-restored");
// free _initialState after nsSessionStore is done with it // Free _initialState after nsSessionStore is done with it.
this._initialState = null; this._initialState = null;
this._didRestore = true; this._didRestore = true;
break; break;
case "browser:purge-session-history": case "browser:purge-session-history":
Services.obs.removeObserver(this, "browser:purge-session-history"); Services.obs.removeObserver(this, "browser:purge-session-history");
// reset all state on sanitization // Reset all state on sanitization.
this._sessionType = this.NO_SESSION; this._sessionType = this.NO_SESSION;
break; break;
} }
@ -325,15 +308,6 @@ var SessionStartup = {
return this._initialState; return this._initialState;
}, },
/**
* Determines whether there is a pending session restore. Should only be
* called after initialization has completed.
* @returns bool
*/
doRestore: function sss_doRestore() {
return this._willRestore();
},
/** /**
* Determines whether automatic session restoration is enabled for this * Determines whether automatic session restoration is enabled for this
* launch of the browser. This does not include crash restoration. In * launch of the browser. This does not include crash restoration. In
@ -342,28 +316,39 @@ var SessionStartup = {
* @returns bool * @returns bool
*/ */
isAutomaticRestoreEnabled() { isAutomaticRestoreEnabled() {
if (PrivateBrowsingUtils.permanentPrivateBrowsing) { if (this._resumeSessionEnabled === null) {
return false; this._resumeSessionEnabled =
!PrivateBrowsingUtils.permanentPrivateBrowsing &&
(Services.prefs.getBoolPref(
"browser.sessionstore.resume_session_once"
) ||
Services.prefs.getIntPref("browser.startup.page") ==
BROWSER_STARTUP_RESUME_SESSION);
} }
return ( return this._resumeSessionEnabled;
Services.prefs.getBoolPref("browser.sessionstore.resume_session_once") ||
Services.prefs.getIntPref("browser.startup.page") ==
BROWSER_STARTUP_RESUME_SESSION
);
}, },
/** /**
* Determines whether there is a pending session restore. * Determines whether there is a pending session restore.
* @returns bool * @returns bool
*/ */
_willRestore() { willRestore() {
return ( return (
this._sessionType == this.RECOVER_SESSION || this.sessionType == this.RECOVER_SESSION ||
this._sessionType == this.RESUME_SESSION this.sessionType == this.RESUME_SESSION
); );
}, },
/**
* Determines whether there is a pending session restore and if that will refer
* back to a crash.
* @returns bool
*/
willRestoreAsCrashed() {
return this.sessionType == this.RECOVER_SESSION;
},
/** /**
* Returns a boolean or a promise that resolves to a boolean, indicating * Returns a boolean or a promise that resolves to a boolean, indicating
* whether we will restore a session that ends up replacing the homepage. * whether we will restore a session that ends up replacing the homepage.
@ -378,7 +363,7 @@ var SessionStartup = {
// it when recovering from a crash, which we'll only know after reading the // it when recovering from a crash, which we'll only know after reading the
// session file, but waiting for that would delay loading the homepage in // session file, but waiting for that would delay loading the homepage in
// the non-crash case. // the non-crash case.
if (!this._initialState && !this._resumeSessionEnabled) { if (!this._initialState && !this.isAutomaticRestoreEnabled()) {
return false; return false;
} }
// If we've already restored the session, we won't override again. // If we've already restored the session, we won't override again.
@ -391,7 +376,7 @@ var SessionStartup = {
// If there are valid windows with not only pinned tabs, signal that we // If there are valid windows with not only pinned tabs, signal that we
// will override the default homepage by restoring a session. // will override the default homepage by restoring a session.
resolve( resolve(
this._willRestore() && this.willRestore() &&
this._initialState && this._initialState &&
this._initialState.windows && this._initialState.windows &&
this._initialState.windows.some(w => w.tabs.some(t => !t.pinned)) this._initialState.windows.some(w => w.tabs.some(t => !t.pinned))
@ -404,6 +389,22 @@ var SessionStartup = {
* Get the type of pending session store, if any. * Get the type of pending session store, if any.
*/ */
get sessionType() { get sessionType() {
if (this._sessionType === null) {
let resumeFromCrash = Services.prefs.getBoolPref(
"browser.sessionstore.resume_from_crash"
);
// Set the startup type.
if (this.isAutomaticRestoreEnabled()) {
this._sessionType = this.RESUME_SESSION;
} else if (this._previousSessionCrashed && resumeFromCrash) {
this._sessionType = this.RECOVER_SESSION;
} else if (this._initialState) {
this._sessionType = this.DEFER_SESSION;
} else {
this._sessionType = this.NO_SESSION;
}
}
return this._sessionType; return this._sessionType;
}, },
@ -414,6 +415,11 @@ var SessionStartup = {
return this._previousSessionCrashed; return this._previousSessionCrashed;
}, },
resetForTest() {
this._resumeSessionEnabled = null;
this._sessionType = null;
},
QueryInterface: ChromeUtils.generateQI([ QueryInterface: ChromeUtils.generateQI([
Ci.nsIObserver, Ci.nsIObserver,
Ci.nsISupportsWeakReference, Ci.nsISupportsWeakReference,

View File

@ -172,6 +172,9 @@ const RESTORE_TAB_CONTENT_REASON = {
NAVIGATE_AND_RESTORE: 1, NAVIGATE_AND_RESTORE: 1,
}; };
// 'browser.startup.page' preference value to resume the previous session.
const BROWSER_STARTUP_RESUME_SESSION = 3;
ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm", this); ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm", this);
ChromeUtils.import("resource://gre/modules/Services.jsm", this); ChromeUtils.import("resource://gre/modules/Services.jsm", this);
ChromeUtils.import("resource://gre/modules/TelemetryTimestamps.jsm", this); ChromeUtils.import("resource://gre/modules/TelemetryTimestamps.jsm", this);
@ -250,6 +253,10 @@ var SessionStore = {
return SessionStoreInternal.lastClosedObjectType; return SessionStoreInternal.lastClosedObjectType;
}, },
get willAutoRestore() {
return SessionStoreInternal.willAutoRestore;
},
init: function ss_init() { init: function ss_init() {
SessionStoreInternal.init(); SessionStoreInternal.init();
}, },
@ -655,6 +662,19 @@ var SessionStoreInternal = {
return "tab"; return "tab";
}, },
/**
* Returns a boolean that determines whether the session will be automatically
* restored upon the _next_ startup or a restart.
*/
get willAutoRestore() {
return (
!PrivateBrowsingUtils.permanentPrivateBrowsing &&
(Services.prefs.getBoolPref("browser.sessionstore.resume_session_once") ||
Services.prefs.getIntPref("browser.startup.page") ==
BROWSER_STARTUP_RESUME_SESSION)
);
},
/** /**
* Initialize the sessionstore service. * Initialize the sessionstore service.
*/ */
@ -684,7 +704,7 @@ var SessionStoreInternal = {
let state; let state;
let ss = SessionStartup; let ss = SessionStartup;
if (ss.doRestore() || ss.sessionType == ss.DEFER_SESSION) { if (ss.willRestore() || ss.sessionType == ss.DEFER_SESSION) {
state = ss.state; state = ss.state;
} }
@ -716,7 +736,7 @@ var SessionStoreInternal = {
// restore it // restore it
LastSession.setState(state.lastSessionState); LastSession.setState(state.lastSessionState);
if (ss.previousSessionCrashed) { if (ss.willRestoreAsCrashed()) {
this._recentCrashes = this._recentCrashes =
((state.session && state.session.recentCrashes) || 0) + 1; ((state.session && state.session.recentCrashes) || 0) + 1;
@ -1372,7 +1392,10 @@ var SessionStoreInternal = {
if (closedWindowState) { if (closedWindowState) {
let newWindowState; let newWindowState;
if (AppConstants.platform == "macosx" || !this._doResumeSession()) { if (
AppConstants.platform == "macosx" ||
!SessionStartup.willRestore()
) {
// We want to split the window up into pinned tabs and unpinned tabs. // We want to split the window up into pinned tabs and unpinned tabs.
// Pinned tabs should be restored. If there are any remaining tabs, // Pinned tabs should be restored. If there are any remaining tabs,
// they should be added back to _closedWindows. // they should be added back to _closedWindows.
@ -5164,17 +5187,6 @@ var SessionStoreInternal = {
return window; return window;
}, },
/**
* Whether or not to resume session, if not recovering from a crash.
* @returns bool
*/
_doResumeSession: function ssi_doResumeSession() {
return (
this._prefBranch.getIntPref("startup.page") == 3 ||
this._prefBranch.getBoolPref("sessionstore.resume_session_once")
);
},
/** /**
* whether the user wants to load any other page at startup * whether the user wants to load any other page at startup
* (except the homepage) - needed for determining whether to overwrite the current tabs * (except the homepage) - needed for determining whether to overwrite the current tabs

View File

@ -24,6 +24,7 @@
* notifications. The latter won't. * notifications. The latter won't.
*/ */
ChromeUtils.import("resource:///modules/sessionstore/SessionStartup.jsm", this);
// The rejection "BrowserWindowTracker.getTopWindow(...) is null" is left // The rejection "BrowserWindowTracker.getTopWindow(...) is null" is left
// unhandled in some cases. This bug should be fixed, but for the moment this // unhandled in some cases. This bug should be fixed, but for the moment this
// file is whitelisted. // file is whitelisted.
@ -115,6 +116,9 @@ let setupTest = async function(options, testFunction) {
["browser.startup.page", 3], ["browser.startup.page", 3],
["browser.tabs.warnOnClose", false] ["browser.tabs.warnOnClose", false]
); );
// SessionStartup caches pref values, but as this test tries to simulate a
// startup scenario, we'll reset them here.
SessionStartup.resetForTest();
// Observe these, and also use to count the number of hits // Observe these, and also use to count the number of hits
let observing = { let observing = {
@ -156,6 +160,8 @@ let setupTest = async function(options, testFunction) {
} }
await popPrefs(); await popPrefs();
// Act like nothing ever happened.
SessionStartup.resetForTest();
}; };
/** /**

View File

@ -244,7 +244,7 @@ add_task(async function test_preload_crash() {
NewTabPagePreloading.removePreloadedBrowser(window); NewTabPagePreloading.removePreloadedBrowser(window);
// Create a fresh preloaded browser // Create a fresh preloaded browser
NewTabPagePreloading.maybeCreatePreloadedBrowser(window); await BrowserTestUtils.maybeCreatePreloadedBrowser(gBrowser);
await BrowserTestUtils.crashBrowser(gBrowser.preloadedBrowser, false); await BrowserTestUtils.crashBrowser(gBrowser.preloadedBrowser, false);

View File

@ -1 +1 @@
68.13.9 68.14.0

View File

@ -1 +1 @@
68.13.9b 68.14.0b

View File

@ -167,9 +167,6 @@
; JavaScript components ; JavaScript components
@RESPATH@/browser/components/BrowserComponents.manifest @RESPATH@/browser/components/BrowserComponents.manifest
@RESPATH@/components/EnterprisePolicies.js
@RESPATH@/components/EnterprisePoliciesContent.js
@RESPATH@/components/EnterprisePolicies.manifest
@RESPATH@/components/extensions.manifest @RESPATH@/components/extensions.manifest
#ifdef MOZ_UPDATER #ifdef MOZ_UPDATER
@RESPATH@/components/nsUpdateService.manifest @RESPATH@/components/nsUpdateService.manifest
@ -263,17 +260,14 @@
; [Webide Files] ; [Webide Files]
@RESPATH@/browser/chrome/webide@JAREXT@ @RESPATH@/browser/chrome/webide@JAREXT@
@RESPATH@/browser/chrome/webide.manifest @RESPATH@/browser/chrome/webide.manifest
@RESPATH@/browser/@PREF_DIR@/webide.js
; [DevTools Startup Files] ; [DevTools Startup Files]
@RESPATH@/browser/chrome/devtools-startup@JAREXT@ @RESPATH@/browser/chrome/devtools-startup@JAREXT@
@RESPATH@/browser/chrome/devtools-startup.manifest @RESPATH@/browser/chrome/devtools-startup.manifest
@RESPATH@/browser/@PREF_DIR@/devtools-startup.js
; DevTools ; DevTools
@RESPATH@/browser/chrome/devtools@JAREXT@ @RESPATH@/browser/chrome/devtools@JAREXT@
@RESPATH@/browser/chrome/devtools.manifest @RESPATH@/browser/chrome/devtools.manifest
@RESPATH@/browser/@PREF_DIR@/devtools-client.js
@RESPATH@/browser/@PREF_DIR@/debugger.js @RESPATH@/browser/@PREF_DIR@/debugger.js
; shell icons ; shell icons

View File

@ -915,6 +915,21 @@ BasePrincipal::GetLocalStorageQuotaKey(nsACString& aKey) {
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
BasePrincipal::GetIsScriptAllowedByPolicy(bool* aIsScriptAllowedByPolicy) {
*aIsScriptAllowedByPolicy = false;
nsCOMPtr<nsIURI> prinURI;
nsresult rv = GetURI(getter_AddRefs(prinURI));
if (NS_FAILED(rv) || !prinURI) {
return NS_OK;
}
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
if (!ssm) {
return NS_ERROR_UNEXPECTED;
}
return ssm->PolicyAllowsScript(prinURI, aIsScriptAllowedByPolicy);
}
bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const { bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const {
MOZ_ASSERT(IsInitialized()); MOZ_ASSERT(IsInitialized());
MOZ_ASSERT(aOther.IsInitialized()); MOZ_ASSERT(aOther.IsInitialized());

View File

@ -146,7 +146,9 @@ class BasePrincipal : public nsJSPrincipals {
NS_IMETHOD AllowsRelaxStrictFileOriginPolicy(nsIURI* aURI, NS_IMETHOD AllowsRelaxStrictFileOriginPolicy(nsIURI* aURI,
bool* aRes) override; bool* aRes) override;
NS_IMETHOD CreateReferrerInfo(mozilla::dom::ReferrerPolicy aReferrerPolicy, NS_IMETHOD CreateReferrerInfo(mozilla::dom::ReferrerPolicy aReferrerPolicy,
nsIReferrerInfo** _retval) override; nsIReferrerInfo** _retval) override;
NS_IMETHOD GetIsScriptAllowedByPolicy(
bool* aIsScriptAllowedByPolicy) override;
nsresult ToJSON(nsACString& aJSON); nsresult ToJSON(nsACString& aJSON);
static already_AddRefed<BasePrincipal> FromJSON(const nsACString& aJSON); static already_AddRefed<BasePrincipal> FromJSON(const nsACString& aJSON);
// Method populates a passed Json::Value with serializable fields // Method populates a passed Json::Value with serializable fields

View File

@ -353,14 +353,17 @@ ContentPrincipal::SetDomain(nsIURI* aDomain) {
// Set the changed-document-domain flag on compartments containing realms // Set the changed-document-domain flag on compartments containing realms
// using this principal. // using this principal.
auto cb = [](JSContext*, void*, JS::Handle<JS::Realm*> aRealm) { auto cb = [](JSContext*, void*, JS::Realm* aRealm,
const JS::AutoRequireNoGC& nogc) {
JS::Compartment* comp = JS::GetCompartmentForRealm(aRealm); JS::Compartment* comp = JS::GetCompartmentForRealm(aRealm);
xpc::SetCompartmentChangedDocumentDomain(comp); xpc::SetCompartmentChangedDocumentDomain(comp);
}; };
JSPrincipals* principals = JSPrincipals* principals =
nsJSPrincipals::get(static_cast<nsIPrincipal*>(this)); nsJSPrincipals::get(static_cast<nsIPrincipal*>(this));
AutoSafeJSContext cx;
JS::IterateRealmsWithPrincipals(cx, principals, nullptr, cb); dom::AutoJSAPI jsapi;
jsapi.Init();
JS::IterateRealmsWithPrincipals(jsapi.cx(), principals, nullptr, cb);
return NS_OK; return NS_OK;
} }

View File

@ -430,6 +430,12 @@ interface nsIPrincipal : nsISerializable
* Returns true if the URI is an Onion URI * Returns true if the URI is an Onion URI
*/ */
[infallible] readonly attribute boolean isOnion; [infallible] readonly attribute boolean isOnion;
/*
* Returns true if the Domain Policy allows js execution
* for the Principals URI
*/
readonly attribute boolean isScriptAllowedByPolicy;
}; };
/** /**

View File

@ -60,6 +60,7 @@ included_inclnames_to_ignore = set([
'double-conversion/double-conversion.h', # strange MFBT case 'double-conversion/double-conversion.h', # strange MFBT case
'javascript-trace.h', # generated in $OBJDIR if HAVE_DTRACE is defined 'javascript-trace.h', # generated in $OBJDIR if HAVE_DTRACE is defined
'frontend/ReservedWordsGenerated.h', # generated in $OBJDIR 'frontend/ReservedWordsGenerated.h', # generated in $OBJDIR
'frontend/smoosh_generated.h', # generated in $OBJDIR
'gc/StatsPhasesGenerated.h', # generated in $OBJDIR 'gc/StatsPhasesGenerated.h', # generated in $OBJDIR
'gc/StatsPhasesGenerated.inc', # generated in $OBJDIR 'gc/StatsPhasesGenerated.inc', # generated in $OBJDIR
'jit/CacheIROpsGenerated.h', # generated in $OBJDIR 'jit/CacheIROpsGenerated.h', # generated in $OBJDIR
@ -96,6 +97,7 @@ included_inclnames_to_ignore = set([
'unicode/ucurr.h', # ICU 'unicode/ucurr.h', # ICU
'unicode/udat.h', # ICU 'unicode/udat.h', # ICU
'unicode/udata.h', # ICU 'unicode/udata.h', # ICU
'unicode/udateintervalformat.h', # ICU
'unicode/udatpg.h', # ICU 'unicode/udatpg.h', # ICU
'unicode/udisplaycontext.h', # ICU 'unicode/udisplaycontext.h', # ICU
'unicode/uenum.h', # ICU 'unicode/uenum.h', # ICU
@ -301,7 +303,7 @@ def check_style(enable_fixup):
js_public_root = os.path.join('js', 'public') js_public_root = os.path.join('js', 'public')
for dirpath, dirnames, filenames in os.walk(js_public_root): for dirpath, dirnames, filenames in os.walk(js_public_root):
for filename in filenames: for filename in filenames:
if filename.endswith('.h'): if filename.endswith(('.h', '.msg')):
filepath = os.path.join(dirpath, filename).replace('\\', '/') filepath = os.path.join(dirpath, filename).replace('\\', '/')
inclname = 'js/' + filepath[len('js/public/'):] inclname = 'js/' + filepath[len('js/public/'):]
js_names[filepath] = inclname js_names[filepath] = inclname
@ -362,12 +364,21 @@ def is_module_header(enclosing_inclname, header_inclname):
module = module_name(enclosing_inclname) module = module_name(enclosing_inclname)
# Normal case, e.g. module == "foo/Bar", header_inclname == "foo/Bar.h". # Normal case, for example:
# module == "vm/Runtime", header_inclname == "vm/Runtime.h".
if module == module_name(header_inclname): if module == module_name(header_inclname):
return True return True
# A public header, e.g. module == "foo/Bar", header_inclname == "js/Bar.h". # A public header, for example:
m = re.match(r'js\/(.*)\.h', header_inclname) #
# module == "vm/CharacterEncoding",
# header_inclname == "js/CharacterEncoding.h"
#
# or (for implementation files for js/public/*/*.h headers)
#
# module == "vm/SourceHook",
# header_inclname == "js/experimental/SourceHook.h"
m = re.match(r'js\/.*?([^\/]+)\.h', header_inclname)
if m is not None and module.endswith('/' + m.group(1)): if m is not None and module.endswith('/' + m.group(1)):
return True return True
@ -400,7 +411,7 @@ class Include(object):
4. foo/Bar.h 4. foo/Bar.h
5. jsfooinlines.h 5. jsfooinlines.h
6. foo/Bar-inl.h 6. foo/Bar-inl.h
7. non-.h, e.g. *.tbl, *.msg 7. non-.h, e.g. *.tbl, *.msg (these can be scattered throughout files)
''' '''
if self.is_system: if self.is_system:

View File

@ -157,6 +157,7 @@ SOURCES += [
'/intl/icu/source/i18n/ucol_sit.cpp', '/intl/icu/source/i18n/ucol_sit.cpp',
'/intl/icu/source/i18n/ucoleitr.cpp', '/intl/icu/source/i18n/ucoleitr.cpp',
'/intl/icu/source/i18n/udat.cpp', '/intl/icu/source/i18n/udat.cpp',
'/intl/icu/source/i18n/udateintervalformat.cpp',
'/intl/icu/source/i18n/udatpg.cpp', '/intl/icu/source/i18n/udatpg.cpp',
'/intl/icu/source/i18n/ufieldpositer.cpp', '/intl/icu/source/i18n/ufieldpositer.cpp',
'/intl/icu/source/i18n/uitercollationiterator.cpp', '/intl/icu/source/i18n/uitercollationiterator.cpp',

View File

@ -29,8 +29,11 @@ idl_deps_dir := .deps
dist_idl_dir := $(DIST)/idl dist_idl_dir := $(DIST)/idl
dist_include_dir := $(DIST)/include dist_include_dir := $(DIST)/include
dist_xpcrs_dir := $(DIST)/xpcrs dist_xpcrs_dir := $(DIST)/xpcrs
stub_file := xptdata.stub
process_py := $(topsrcdir)/python/mozbuild/mozbuild/action/xpidl-process.py process_py := $(topsrcdir)/python/mozbuild/mozbuild/action/xpidl-process.py
generated_file := $(topobjdir)/xpcom/reflect/xptinfo/xptdata.cpp target_file := $(topobjdir)/xpcom/reflect/xptinfo/xptdata.cpp
xptdata_h := $(dist_include_dir)/xptdata.h
generated_files := $(target_file) $(xptdata_h)
code_gen_py := $(topsrcdir)/xpcom/reflect/xptinfo/xptcodegen.py code_gen_py := $(topsrcdir)/xpcom/reflect/xptinfo/xptcodegen.py
code_gen_deps := $(topsrcdir)/xpcom/ds/tools/perfecthash.py code_gen_deps := $(topsrcdir)/xpcom/ds/tools/perfecthash.py
@ -60,17 +63,21 @@ xpt_files := $(addsuffix .xpt,$(xpidl_modules))
depends_files := $(foreach root,$(xpidl_modules),$(idl_deps_dir)/$(root).pp) depends_files := $(foreach root,$(xpidl_modules),$(idl_deps_dir)/$(root).pp)
GARBAGE += $(xpt_files) $(depends_files) $(generated_file) GARBAGE += $(stub_file) $(xpt_files) $(depends_files) $(target_file)
ifdef COMPILE_ENVIRONMENT ifdef COMPILE_ENVIRONMENT
xpidl:: $(generated_file) xpidl:: $(generated_files)
endif endif
# See bug 1420119 for why we need the semicolon.
$(target_file) $(xptdata_h) : $(stub_file) ;
$(xpt_files): $(process_py) $(call mkdir_deps,$(idl_deps_dir) $(dist_include_dir) $(dist_xpcrs_dir)) $(xpt_files): $(process_py) $(call mkdir_deps,$(idl_deps_dir) $(dist_include_dir) $(dist_xpcrs_dir))
$(generated_file): $(xpt_files) $(code_gen_py) $(code_gen_deps) $(stub_file) : $(xpt_files) $(code_gen_py) $(code_gen_deps)
$(REPORT_BUILD) $(REPORT_BUILD)
$(PYTHON_PATH) $(PLY_INCLUDE) $(code_gen_py) $(generated_file) $(xpt_files) $(PYTHON_PATH) $(PLY_INCLUDE) $(code_gen_py) $(generated_files) $(xpt_files)
@touch $@
-include $(depends_files) -include $(depends_files)

View File

@ -182,12 +182,17 @@ xpcom/xpidl/export: xpcom/idl-parser/xpidl/export
dom/bindings/export: layout/style/export dom/bindings/export: layout/style/export
ifdef ENABLE_CLANG_PLUGIN ifdef ENABLE_CLANG_PLUGIN
$(filter-out config/host build/unix/stdc++compat/% build/clang-plugin/%,$(compile_targets)): build/clang-plugin/host build/clang-plugin/tests/target-objects # Only target rules use the clang plugin.
$(filter %/target %/target-objects,$(filter-out config/export config/host build/unix/stdc++compat/% build/clang-plugin/%,$(compile_targets))): build/clang-plugin/host build/clang-plugin/tests/target-objects
build/clang-plugin/tests/target-objects: build/clang-plugin/host build/clang-plugin/tests/target-objects: build/clang-plugin/host
# clang-plugin tests require js-confdefs.h on js standalone builds and mozilla-config.h on # clang-plugin tests require js-confdefs.h on js standalone builds and mozilla-config.h on
# other builds, because they are -include'd. # other builds, because they are -include'd.
ifdef JS_STANDALONE ifdef JS_STANDALONE
# The js/src/export target only exists when CURRENT_TIER is export. If we're in a later tier,
# we can assume js/src/export has happened anyways.
ifeq ($(CURRENT_TIER),export)
build/clang-plugin/tests/target-objects: js/src/export build/clang-plugin/tests/target-objects: js/src/export
endif
else else
build/clang-plugin/tests/target-objects: mozilla-config.h build/clang-plugin/tests/target-objects: mozilla-config.h
endif endif

View File

@ -1327,6 +1327,7 @@ if CONFIG['MOZ_SYSTEM_ICU']:
'unicode/ucurr.h', 'unicode/ucurr.h',
'unicode/udat.h', 'unicode/udat.h',
'unicode/udata.h', 'unicode/udata.h',
'unicode/udateintervalformat.h',
'unicode/udatpg.h', 'unicode/udatpg.h',
'unicode/udisplaycontext.h', 'unicode/udisplaycontext.h',
'unicode/uldnames.h', 'unicode/uldnames.h',

View File

@ -599,7 +599,7 @@ class RemoteLocationProxy
auto location = auto location =
static_cast<BrowsingContext::LocationProxy*>(GetNative(aProxy)); static_cast<BrowsingContext::LocationProxy*>(GetNative(aProxy));
CycleCollectionNoteChild(aCb, location->GetBrowsingContext(), CycleCollectionNoteChild(aCb, location->GetBrowsingContext(),
"js::GetObjectPrivate(obj)->GetBrowsingContext()"); "JS::GetPrivate(obj)->GetBrowsingContext()");
} }
}; };

View File

@ -711,13 +711,13 @@ bool nsDefaultURIFixup::PossiblyHostPortUrl(const nsACString& aUrl) {
++iter; ++iter;
// Count the number of digits after the colon and before the // Count the number of digits after the colon and before the
// next forward slash (or end of string) // next forward slash, question mark, hash sign, or end of string.
uint32_t digitCount = 0; uint32_t digitCount = 0;
while (iter != iterEnd && digitCount <= 5) { while (iter != iterEnd && digitCount <= 5) {
if (IsAsciiDigit(*iter)) { if (IsAsciiDigit(*iter)) {
digitCount++; digitCount++;
} else if (*iter == '/') { } else if (*iter == '/' || *iter == '?' || *iter == '#') {
break; break;
} else { } else {
// Whatever it is, it ain't a port! // Whatever it is, it ain't a port!

View File

@ -11,9 +11,8 @@ namespace mozilla {
AutoGlobalTimelineMarker::AutoGlobalTimelineMarker( AutoGlobalTimelineMarker::AutoGlobalTimelineMarker(
const char* aName, MarkerStackRequest aStackRequest /* = STACK */ const char* aName, MarkerStackRequest aStackRequest /* = STACK */
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL) )
: mName(aName), mStackRequest(aStackRequest) { : mName(aName), mStackRequest(aStackRequest) {
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get(); RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();

View File

@ -5,7 +5,6 @@
#ifndef mozilla_AutoGlobalTimelineMarker_h_ #ifndef mozilla_AutoGlobalTimelineMarker_h_
#define mozilla_AutoGlobalTimelineMarker_h_ #define mozilla_AutoGlobalTimelineMarker_h_
#include "mozilla/GuardObjects.h"
#include "TimelineMarkerEnums.h" #include "TimelineMarkerEnums.h"
namespace mozilla { namespace mozilla {
@ -26,7 +25,6 @@ namespace mozilla {
// ... // ...
// } // }
class MOZ_RAII AutoGlobalTimelineMarker { class MOZ_RAII AutoGlobalTimelineMarker {
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
// The name of the marker we are adding. // The name of the marker we are adding.
const char* mName; const char* mName;
@ -36,8 +34,7 @@ class MOZ_RAII AutoGlobalTimelineMarker {
public: public:
explicit AutoGlobalTimelineMarker( explicit AutoGlobalTimelineMarker(
const char* aName, const char* aName,
MarkerStackRequest aStackRequest = MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
MarkerStackRequest::STACK MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
~AutoGlobalTimelineMarker(); ~AutoGlobalTimelineMarker();
AutoGlobalTimelineMarker(const AutoGlobalTimelineMarker& aOther) = delete; AutoGlobalTimelineMarker(const AutoGlobalTimelineMarker& aOther) = delete;

View File

@ -159,7 +159,7 @@ void ObservedDocShell::PopMarkers(
} }
} }
mTimelineMarkers.SwapElements(keptStartMarkers); mTimelineMarkers = std::move(keptStartMarkers);
} }
} // namespace mozilla } // namespace mozilla

View File

@ -58,8 +58,10 @@ Classes = [
}, },
{ {
'name': 'URIFixup', 'name': 'URIFixup',
'js_name': 'uriFixup',
'cid': '{214c48a0-b57f-11d4-959c-0020183bf181}', 'cid': '{214c48a0-b57f-11d4-959c-0020183bf181}',
'contract_ids': ['@mozilla.org/docshell/urifixup;1'], 'contract_ids': ['@mozilla.org/docshell/urifixup;1'],
'interfaces': ['nsIURIFixup'],
'type': 'nsDefaultURIFixup', 'type': 'nsDefaultURIFixup',
'headers': ['/docshell/base/nsDefaultURIFixup.h'], 'headers': ['/docshell/base/nsDefaultURIFixup.h'],
}, },

View File

@ -41,7 +41,11 @@ var TESTS = [
}, },
]; ];
if (Services.prefs.getBoolPref("javascript.options.asyncstack")) { if (
!Services.prefs.getBoolPref(
"javascript.options.asyncstack_capture_debuggee_only"
)
) {
TESTS.push( TESTS.push(
{ {
desc: "Async stack trace on Javascript marker", desc: "Async stack trace on Javascript marker",

View File

@ -97,7 +97,11 @@ var TESTS = [
}, },
]; ];
if (Services.prefs.getBoolPref("javascript.options.asyncstack")) { if (
!Services.prefs.getBoolPref(
"javascript.options.asyncstack_capture_debuggee_only"
)
) {
TESTS.push({ TESTS.push({
desc: "Async stack trace on Promise", desc: "Async stack trace on Promise",
searchFor: "ConsoleTime", searchFor: "ConsoleTime",

View File

@ -71,6 +71,18 @@ var data = [
wrong: "://user:pass@example.com:8080/this/is/a/test.html", wrong: "://user:pass@example.com:8080/this/is/a/test.html",
fixed: "http://user:pass@example.com:8080/this/is/a/test.html", fixed: "http://user:pass@example.com:8080/this/is/a/test.html",
}, },
{
wrong: "localhost:8080/?param=1",
fixed: "http://localhost:8080/?param=1",
},
{
wrong: "localhost:8080?param=1",
fixed: "http://localhost:8080/?param=1",
},
{
wrong: "localhost:8080#somewhere",
fixed: "http://localhost:8080/#somewhere",
},
{ {
wrong: "whatever://this/is/a@b/test.html", wrong: "whatever://this/is/a@b/test.html",
fixed: kSearchEngineURL.replace( fixed: kSearchEngineURL.replace(

View File

@ -29,7 +29,6 @@
#include "mozilla/BasePrincipal.h" // for BasePrincipal #include "mozilla/BasePrincipal.h" // for BasePrincipal
#include "mozilla/CheckedInt.h" // for CheckedInt #include "mozilla/CheckedInt.h" // for CheckedInt
#include "mozilla/ComposerCommandsUpdater.h" // for ComposerCommandsUpdater #include "mozilla/ComposerCommandsUpdater.h" // for ComposerCommandsUpdater
#include "mozilla/ComputedStyle.h" // for ComputedStyle
#include "mozilla/CSSEditUtils.h" // for CSSEditUtils #include "mozilla/CSSEditUtils.h" // for CSSEditUtils
#include "mozilla/EditAction.h" // for EditSubAction #include "mozilla/EditAction.h" // for EditSubAction
#include "mozilla/EditorDOMPoint.h" // for EditorDOMPoint #include "mozilla/EditorDOMPoint.h" // for EditorDOMPoint
@ -78,7 +77,6 @@
#include "nsCaseTreatment.h" #include "nsCaseTreatment.h"
#include "nsCharTraits.h" // for NS_IS_HIGH_SURROGATE, etc. #include "nsCharTraits.h" // for NS_IS_HIGH_SURROGATE, etc.
#include "nsComponentManagerUtils.h" // for do_CreateInstance #include "nsComponentManagerUtils.h" // for do_CreateInstance
#include "nsComputedDOMStyle.h" // for nsComputedDOMStyle
#include "nsContentUtils.h" // for nsContentUtils #include "nsContentUtils.h" // for nsContentUtils
#include "nsDOMString.h" // for DOMStringIsNull #include "nsDOMString.h" // for DOMStringIsNull
#include "nsDebug.h" // for NS_WARNING, etc. #include "nsDebug.h" // for NS_WARNING, etc.
@ -126,6 +124,8 @@ namespace mozilla {
using namespace dom; using namespace dom;
using namespace widget; using namespace widget;
using ChildBlockBoundary = HTMLEditUtils::ChildBlockBoundary;
/***************************************************************************** /*****************************************************************************
* mozilla::EditorBase * mozilla::EditorBase
*****************************************************************************/ *****************************************************************************/
@ -2585,7 +2585,8 @@ nsINode* EditorBase::GetFirstEditableNode(nsINode* aRoot) {
MOZ_ASSERT(aRoot); MOZ_ASSERT(aRoot);
EditorType editorType = GetEditorType(); EditorType editorType = GetEditorType();
nsIContent* content = GetLeftmostChild(aRoot); nsIContent* content =
HTMLEditUtils::GetFirstLeafChild(*aRoot, ChildBlockBoundary::TreatAsLeaf);
if (content && !EditorUtils::IsEditableContent(*content, editorType)) { if (content && !EditorUtils::IsEditableContent(*content, editorType)) {
content = GetNextEditableNode(*content); content = GetNextEditableNode(*content);
} }
@ -2815,7 +2816,7 @@ nsresult EditorBase::DeleteTextWithTransaction(Text& aTextNode,
return rv; return rv;
} }
nsIContent* EditorBase::GetPreviousNodeInternal(nsINode& aNode, nsIContent* EditorBase::GetPreviousNodeInternal(const nsINode& aNode,
bool aFindEditableNode, bool aFindEditableNode,
bool aFindAnyDataNode, bool aFindAnyDataNode,
bool aNoBlockCrossing) const { bool aNoBlockCrossing) const {
@ -2856,24 +2857,25 @@ nsIContent* EditorBase::GetPreviousNodeInternal(const EditorRawDOMPoint& aPoint,
// unless there isn't one, in which case we are at the end of the node // unless there isn't one, in which case we are at the end of the node
// and want the deep-right child. // and want the deep-right child.
nsIContent* rightMostContent = nsIContent* lastLeafContent = HTMLEditUtils::GetLastLeafChild(
GetRightmostChild(aPoint.GetContainer(), aNoBlockCrossing); *aPoint.GetContainer(), aNoBlockCrossing ? ChildBlockBoundary::TreatAsLeaf
if (!rightMostContent) { : ChildBlockBoundary::Ignore);
if (!lastLeafContent) {
return nullptr; return nullptr;
} }
if ((!aFindEditableNode || if ((!aFindEditableNode ||
EditorUtils::IsEditableContent(*rightMostContent, GetEditorType())) && EditorUtils::IsEditableContent(*lastLeafContent, GetEditorType())) &&
(aFindAnyDataNode || EditorUtils::IsElementOrText(*rightMostContent))) { (aFindAnyDataNode || EditorUtils::IsElementOrText(*lastLeafContent))) {
return rightMostContent; return lastLeafContent;
} }
// restart the search from the non-editable node we just found // restart the search from the non-editable node we just found
return GetPreviousNodeInternal(*rightMostContent, aFindEditableNode, return GetPreviousNodeInternal(*lastLeafContent, aFindEditableNode,
aFindAnyDataNode, aNoBlockCrossing); aFindAnyDataNode, aNoBlockCrossing);
} }
nsIContent* EditorBase::GetNextNodeInternal(nsINode& aNode, nsIContent* EditorBase::GetNextNodeInternal(const nsINode& aNode,
bool aFindEditableNode, bool aFindEditableNode,
bool aFindAnyDataNode, bool aFindAnyDataNode,
bool aNoBlockCrossing) const { bool aNoBlockCrossing) const {
@ -2909,24 +2911,25 @@ nsIContent* EditorBase::GetNextNodeInternal(const EditorRawDOMPoint& aPoint,
return point.GetChild(); return point.GetChild();
} }
nsIContent* leftMostContent = nsIContent* firstLeafContent = HTMLEditUtils::GetFirstLeafChild(
GetLeftmostChild(point.GetChild(), aNoBlockCrossing); *point.GetChild(), aNoBlockCrossing ? ChildBlockBoundary::TreatAsLeaf
if (!leftMostContent) { : ChildBlockBoundary::Ignore);
if (!firstLeafContent) {
return point.GetChild(); return point.GetChild();
} }
if (!IsDescendantOfEditorRoot(leftMostContent)) { if (!IsDescendantOfEditorRoot(firstLeafContent)) {
return nullptr; return nullptr;
} }
if ((!aFindEditableNode || if ((!aFindEditableNode ||
EditorUtils::IsEditableContent(*leftMostContent, GetEditorType())) && EditorUtils::IsEditableContent(*firstLeafContent, GetEditorType())) &&
(aFindAnyDataNode || EditorUtils::IsElementOrText(*leftMostContent))) { (aFindAnyDataNode || EditorUtils::IsElementOrText(*firstLeafContent))) {
return leftMostContent; return firstLeafContent;
} }
// restart the search from the non-editable node we just found // restart the search from the non-editable node we just found
return GetNextNodeInternal(*leftMostContent, aFindEditableNode, return GetNextNodeInternal(*firstLeafContent, aFindEditableNode,
aFindAnyDataNode, aNoBlockCrossing); aFindAnyDataNode, aNoBlockCrossing);
} }
@ -2942,14 +2945,15 @@ nsIContent* EditorBase::GetNextNodeInternal(const EditorRawDOMPoint& aPoint,
aFindAnyDataNode, aNoBlockCrossing); aFindAnyDataNode, aNoBlockCrossing);
} }
nsIContent* EditorBase::FindNextLeafNode(nsINode* aCurrentNode, bool aGoForward, nsIContent* EditorBase::FindNextLeafNode(const nsINode* aCurrentNode,
bool aGoForward,
bool bNoBlockCrossing) const { bool bNoBlockCrossing) const {
// called only by GetPriorNode so we don't need to check params. // called only by GetPriorNode so we don't need to check params.
MOZ_ASSERT( MOZ_ASSERT(
IsDescendantOfEditorRoot(aCurrentNode) && !IsEditorRoot(aCurrentNode), IsDescendantOfEditorRoot(aCurrentNode) && !IsEditorRoot(aCurrentNode),
"Bogus arguments"); "Bogus arguments");
nsINode* cur = aCurrentNode; const nsINode* cur = aCurrentNode;
for (;;) { for (;;) {
// if aCurrentNode has a sibling in the right direction, return // if aCurrentNode has a sibling in the right direction, return
// that sibling's closest child (or itself if it has no children) // that sibling's closest child (or itself if it has no children)
@ -2960,14 +2964,14 @@ nsIContent* EditorBase::FindNextLeafNode(nsINode* aCurrentNode, bool aGoForward,
// don't look inside prevsib, since it is a block // don't look inside prevsib, since it is a block
return sibling; return sibling;
} }
nsIContent* leaf = aGoForward ChildBlockBoundary childBlockBoundary =
? GetLeftmostChild(sibling, bNoBlockCrossing) bNoBlockCrossing ? ChildBlockBoundary::TreatAsLeaf
: GetRightmostChild(sibling, bNoBlockCrossing); : ChildBlockBoundary::Ignore;
if (!leaf) { nsIContent* leafContent =
return sibling; aGoForward
} ? HTMLEditUtils::GetFirstLeafChild(*sibling, childBlockBoundary)
: HTMLEditUtils::GetLastLeafChild(*sibling, childBlockBoundary);
return leaf; return leafContent ? leafContent : sibling;
} }
nsINode* parent = cur->GetParentNode(); nsINode* parent = cur->GetParentNode();
@ -2992,7 +2996,7 @@ nsIContent* EditorBase::FindNextLeafNode(nsINode* aCurrentNode, bool aGoForward,
return nullptr; return nullptr;
} }
nsIContent* EditorBase::FindNode(nsINode* aCurrentNode, bool aGoForward, nsIContent* EditorBase::FindNode(const nsINode* aCurrentNode, bool aGoForward,
bool aEditableNode, bool aFindAnyDataNode, bool aEditableNode, bool aFindAnyDataNode,
bool bNoBlockCrossing) const { bool bNoBlockCrossing) const {
if (IsEditorRoot(aCurrentNode)) { if (IsEditorRoot(aCurrentNode)) {
@ -3020,55 +3024,7 @@ nsIContent* EditorBase::FindNode(nsINode* aCurrentNode, bool aGoForward,
bNoBlockCrossing); bNoBlockCrossing);
} }
nsIContent* EditorBase::GetRightmostChild(nsINode* aCurrentNode, bool EditorBase::IsRoot(const nsINode* inNode) const {
bool bNoBlockCrossing) const {
if (NS_WARN_IF(!aCurrentNode)) {
return nullptr;
}
nsIContent* content = aCurrentNode->GetLastChild();
if (!content) {
return nullptr;
}
for (;;) {
if (bNoBlockCrossing && HTMLEditUtils::IsBlockElement(*content)) {
return content;
}
nsIContent* nextContent = content->GetLastChild();
if (!nextContent) {
return content;
}
content = nextContent;
}
MOZ_ASSERT_UNREACHABLE("What part of for(;;) do you not understand?");
return nullptr;
}
nsIContent* EditorBase::GetLeftmostChild(nsINode* aCurrentNode,
bool bNoBlockCrossing) const {
if (NS_WARN_IF(!aCurrentNode)) {
return nullptr;
}
nsIContent* content = aCurrentNode->GetFirstChild();
if (!content) {
return nullptr;
}
for (;;) {
if (bNoBlockCrossing && HTMLEditUtils::IsBlockElement(*content)) {
return content;
}
nsIContent* next = content->GetFirstChild();
if (!next) {
return content;
}
content = next;
}
MOZ_ASSERT_UNREACHABLE("What part of for(;;) do you not understand?");
return nullptr;
}
bool EditorBase::IsRoot(nsINode* inNode) const {
if (NS_WARN_IF(!inNode)) { if (NS_WARN_IF(!inNode)) {
return false; return false;
} }
@ -3076,7 +3032,7 @@ bool EditorBase::IsRoot(nsINode* inNode) const {
return inNode == rootNode; return inNode == rootNode;
} }
bool EditorBase::IsEditorRoot(nsINode* aNode) const { bool EditorBase::IsEditorRoot(const nsINode* aNode) const {
if (NS_WARN_IF(!aNode)) { if (NS_WARN_IF(!aNode)) {
return false; return false;
} }
@ -3084,7 +3040,7 @@ bool EditorBase::IsEditorRoot(nsINode* aNode) const {
return aNode == rootNode; return aNode == rootNode;
} }
bool EditorBase::IsDescendantOfRoot(nsINode* inNode) const { bool EditorBase::IsDescendantOfRoot(const nsINode* inNode) const {
if (NS_WARN_IF(!inNode)) { if (NS_WARN_IF(!inNode)) {
return false; return false;
} }
@ -3096,7 +3052,7 @@ bool EditorBase::IsDescendantOfRoot(nsINode* inNode) const {
return inNode->IsInclusiveDescendantOf(root); return inNode->IsInclusiveDescendantOf(root);
} }
bool EditorBase::IsDescendantOfEditorRoot(nsINode* aNode) const { bool EditorBase::IsDescendantOfEditorRoot(const nsINode* aNode) const {
if (NS_WARN_IF(!aNode)) { if (NS_WARN_IF(!aNode)) {
return false; return false;
} }
@ -3225,36 +3181,6 @@ nsresult EditorBase::GetEndChildNode(const Selection& aSelection,
return NS_OK; return NS_OK;
} }
/**
* IsPreformatted() checks the style info for the node for the preformatted
* text style.
*/
// static
bool EditorBase::IsPreformatted(nsINode* aNode) {
if (NS_WARN_IF(!aNode)) {
return false;
}
// Look at the node (and its parent if it's not an element), and grab its
// ComputedStyle.
Element* element = aNode->GetAsElementOrParentElement();
if (!element) {
return false;
}
RefPtr<ComputedStyle> elementStyle =
nsComputedDOMStyle::GetComputedStyleNoFlush(element, nullptr);
if (!elementStyle) {
// Consider nodes without a ComputedStyle to be NOT preformatted:
// For instance, this is true of JS tags inside the body (which show
// up as #text nodes but have no ComputedStyle).
return false;
}
const nsStyleText* styleText = elementStyle->StyleText();
return styleText->WhiteSpaceIsSignificant();
}
nsresult EditorBase::EnsureNoPaddingBRElementForEmptyEditor() { nsresult EditorBase::EnsureNoPaddingBRElementForEmptyEditor() {
MOZ_ASSERT(IsEditActionDataAvailable()); MOZ_ASSERT(IsEditActionDataAvailable());
@ -4260,23 +4186,10 @@ nsresult EditorBase::DeleteSelectionWithTransaction(
return rv; return rv;
} }
nsresult EditorBase::CreateRange(nsINode* aStartContainer, int32_t aStartOffset,
nsINode* aEndContainer, int32_t aEndOffset,
nsRange** aRange) {
RefPtr<nsRange> range = nsRange::Create(
aStartContainer, aStartOffset, aEndContainer, aEndOffset, IgnoreErrors());
if (!range) {
NS_WARNING("nsRange::Create() failed");
return NS_ERROR_FAILURE;
}
range.forget(aRange);
return NS_OK;
}
nsresult EditorBase::AppendNodeToSelectionAsRange(nsINode* aNode) { nsresult EditorBase::AppendNodeToSelectionAsRange(nsINode* aNode) {
MOZ_ASSERT(IsEditActionDataAvailable()); MOZ_ASSERT(IsEditActionDataAvailable());
if (NS_WARN_IF(!aNode) && NS_WARN_IF(!aNode->IsContent())) { if (NS_WARN_IF(!aNode) || NS_WARN_IF(!aNode->IsContent())) {
return NS_ERROR_INVALID_ARG; return NS_ERROR_INVALID_ARG;
} }
@ -4285,15 +4198,11 @@ nsresult EditorBase::AppendNodeToSelectionAsRange(nsINode* aNode) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
RefPtr<nsRange> range; RefPtr<nsRange> range = nsRange::Create(
nsresult rv = CreateRange(atContent.GetContainer(), atContent.Offset(), atContent.ToRawRangeBoundary(),
atContent.GetContainer(), atContent.Offset() + 1, atContent.NextPoint().ToRawRangeBoundary(), IgnoreErrors());
getter_AddRefs(range));
if (NS_FAILED(rv)) {
NS_WARNING("EditorBase::CreateRange() failed");
return rv;
}
if (NS_WARN_IF(!range)) { if (NS_WARN_IF(!range)) {
NS_WARNING("nsRange::Create() failed");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }

View File

@ -1601,22 +1601,22 @@ class EditorBase : public nsIEditor,
const EditorRawDOMPoint& aPoint) const { const EditorRawDOMPoint& aPoint) const {
return GetPreviousNodeInternal(aPoint, true, true, true); return GetPreviousNodeInternal(aPoint, true, true, true);
} }
nsIContent* GetPreviousNode(nsINode& aNode) const { nsIContent* GetPreviousNode(const nsINode& aNode) const {
return GetPreviousNodeInternal(aNode, false, true, false); return GetPreviousNodeInternal(aNode, false, true, false);
} }
nsIContent* GetPreviousElementOrText(nsINode& aNode) const { nsIContent* GetPreviousElementOrText(const nsINode& aNode) const {
return GetPreviousNodeInternal(aNode, false, false, false); return GetPreviousNodeInternal(aNode, false, false, false);
} }
nsIContent* GetPreviousEditableNode(nsINode& aNode) const { nsIContent* GetPreviousEditableNode(const nsINode& aNode) const {
return GetPreviousNodeInternal(aNode, true, true, false); return GetPreviousNodeInternal(aNode, true, true, false);
} }
nsIContent* GetPreviousNodeInBlock(nsINode& aNode) const { nsIContent* GetPreviousNodeInBlock(const nsINode& aNode) const {
return GetPreviousNodeInternal(aNode, false, true, true); return GetPreviousNodeInternal(aNode, false, true, true);
} }
nsIContent* GetPreviousElementOrTextInBlock(nsINode& aNode) const { nsIContent* GetPreviousElementOrTextInBlock(const nsINode& aNode) const {
return GetPreviousNodeInternal(aNode, false, false, true); return GetPreviousNodeInternal(aNode, false, false, true);
} }
nsIContent* GetPreviousEditableNodeInBlock(nsINode& aNode) const { nsIContent* GetPreviousEditableNodeInBlock(const nsINode& aNode) const {
return GetPreviousNodeInternal(aNode, true, true, true); return GetPreviousNodeInternal(aNode, true, true, true);
} }
@ -1675,50 +1675,36 @@ class EditorBase : public nsIEditor,
const EditorDOMPointBase<PT, CT>& aPoint) const { const EditorDOMPointBase<PT, CT>& aPoint) const {
return GetNextNodeInternal(aPoint, true, true, true); return GetNextNodeInternal(aPoint, true, true, true);
} }
nsIContent* GetNextNode(nsINode& aNode) const { nsIContent* GetNextNode(const nsINode& aNode) const {
return GetNextNodeInternal(aNode, false, true, false); return GetNextNodeInternal(aNode, false, true, false);
} }
nsIContent* GetNextElementOrText(nsINode& aNode) const { nsIContent* GetNextElementOrText(const nsINode& aNode) const {
return GetNextNodeInternal(aNode, false, false, false); return GetNextNodeInternal(aNode, false, false, false);
} }
nsIContent* GetNextEditableNode(nsINode& aNode) const { nsIContent* GetNextEditableNode(const nsINode& aNode) const {
return GetNextNodeInternal(aNode, true, true, false); return GetNextNodeInternal(aNode, true, true, false);
} }
nsIContent* GetNextNodeInBlock(nsINode& aNode) const { nsIContent* GetNextNodeInBlock(const nsINode& aNode) const {
return GetNextNodeInternal(aNode, false, true, true); return GetNextNodeInternal(aNode, false, true, true);
} }
nsIContent* GetNextElementOrTextInBlock(nsINode& aNode) const { nsIContent* GetNextElementOrTextInBlock(const nsINode& aNode) const {
return GetNextNodeInternal(aNode, false, false, true); return GetNextNodeInternal(aNode, false, false, true);
} }
nsIContent* GetNextEditableNodeInBlock(nsINode& aNode) const { nsIContent* GetNextEditableNodeInBlock(const nsINode& aNode) const {
return GetNextNodeInternal(aNode, true, true, true); return GetNextNodeInternal(aNode, true, true, true);
} }
/**
* Get the rightmost child of aCurrentNode;
* return nullptr if aCurrentNode has no children.
*/
nsIContent* GetRightmostChild(nsINode* aCurrentNode,
bool bNoBlockCrossing = false) const;
/**
* Get the leftmost child of aCurrentNode;
* return nullptr if aCurrentNode has no children.
*/
nsIContent* GetLeftmostChild(nsINode* aCurrentNode,
bool bNoBlockCrossing = false) const;
/** /**
* Returns true if aNode is our root node. * Returns true if aNode is our root node.
*/ */
bool IsRoot(nsINode* inNode) const; bool IsRoot(const nsINode* inNode) const;
bool IsEditorRoot(nsINode* aNode) const; bool IsEditorRoot(const nsINode* aNode) const;
/** /**
* Returns true if aNode is a descendant of our root node. * Returns true if aNode is a descendant of our root node.
*/ */
bool IsDescendantOfRoot(nsINode* inNode) const; bool IsDescendantOfRoot(const nsINode* inNode) const;
bool IsDescendantOfEditorRoot(nsINode* aNode) const; bool IsDescendantOfEditorRoot(const nsINode* aNode) const;
/** /**
* Counts number of editable child nodes. * Counts number of editable child nodes.
@ -1757,16 +1743,6 @@ class EditorBase : public nsIEditor,
*/ */
nsresult CollapseSelectionToEnd(); nsresult CollapseSelectionToEnd();
/**
* Helpers to add a node to the selection.
* Used by table cell selection methods.
*/
nsresult CreateRange(nsINode* aStartContainer, int32_t aStartOffset,
nsINode* aEndContainer, int32_t aEndOffset,
nsRange** aRange);
static bool IsPreformatted(nsINode* aNode);
/** /**
* AllowsTransactionsToChangeSelection() returns true if editor allows any * AllowsTransactionsToChangeSelection() returns true if editor allows any
* transactions to change Selection. Otherwise, transactions shouldn't * transactions to change Selection. Otherwise, transactions shouldn't
@ -2050,9 +2026,9 @@ class EditorBase : public nsIEditor,
/** /**
* Helper for GetPreviousNodeInternal() and GetNextNodeInternal(). * Helper for GetPreviousNodeInternal() and GetNextNodeInternal().
*/ */
nsIContent* FindNextLeafNode(nsINode* aCurrentNode, bool aGoForward, nsIContent* FindNextLeafNode(const nsINode* aCurrentNode, bool aGoForward,
bool bNoBlockCrossing) const; bool bNoBlockCrossing) const;
nsIContent* FindNode(nsINode* aCurrentNode, bool aGoForward, nsIContent* FindNode(const nsINode* aCurrentNode, bool aGoForward,
bool aEditableNode, bool aFindAnyDataNode, bool aEditableNode, bool aFindAnyDataNode,
bool bNoBlockCrossing) const; bool bNoBlockCrossing) const;
@ -2069,7 +2045,8 @@ class EditorBase : public nsIEditor,
* aFindEditableNode is true. If there is no * aFindEditableNode is true. If there is no
* previous node, returns nullptr. * previous node, returns nullptr.
*/ */
nsIContent* GetPreviousNodeInternal(nsINode& aNode, bool aFindEditableNode, nsIContent* GetPreviousNodeInternal(const nsINode& aNode,
bool aFindEditableNode,
bool aFindAnyDataNode, bool aFindAnyDataNode,
bool aNoBlockCrossing) const; bool aNoBlockCrossing) const;
@ -2094,9 +2071,9 @@ class EditorBase : public nsIEditor,
* aFindEditableNode is true. If there is no * aFindEditableNode is true. If there is no
* next node, returns nullptr. * next node, returns nullptr.
*/ */
nsIContent* GetNextNodeInternal(nsINode& aNode, bool aFindEditableNode, nsIContent* GetNextNodeInternal(const nsINode& aNode, bool aFindEditableNode,
bool aFindAnyDataNode, bool aFindAnyDataNode,
bool bNoBlockCrossing) const; bool aNoBlockCrossing) const;
/** /**
* And another version that takes a point in DOM tree rather than a node. * And another version that takes a point in DOM tree rather than a node.

View File

@ -2,22 +2,25 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/EditorUtils.h" #include "EditorUtils.h"
#include "mozilla/ComputedStyle.h"
#include "mozilla/ContentIterator.h" #include "mozilla/ContentIterator.h"
#include "mozilla/EditorDOMPoint.h" #include "mozilla/EditorDOMPoint.h"
#include "mozilla/OwningNonNull.h" #include "mozilla/OwningNonNull.h"
#include "mozilla/TextEditor.h" #include "mozilla/TextEditor.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/HTMLBRElement.h" #include "mozilla/dom/HTMLBRElement.h"
#include "mozilla/dom/Selection.h" #include "mozilla/dom/Selection.h"
#include "mozilla/dom/Text.h" #include "mozilla/dom/Text.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "nsComputedDOMStyle.h"
#include "nsError.h" #include "nsError.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "mozilla/dom/Document.h"
#include "nsIInterfaceRequestorUtils.h" #include "nsIInterfaceRequestorUtils.h"
#include "nsINode.h" #include "nsINode.h"
#include "nsStyleStruct.h"
class nsISupports; class nsISupports;
class nsRange; class nsRange;
@ -229,4 +232,25 @@ void EditorUtils::MaskString(nsString& aString, Text* aText,
} }
} }
// static
bool EditorUtils::IsContentPreformatted(nsIContent& aContent) {
// Look at the node (and its parent if it's not an element), and grab its
// ComputedStyle.
Element* element = aContent.GetAsElementOrParentElement();
if (!element) {
return false;
}
RefPtr<ComputedStyle> elementStyle =
nsComputedDOMStyle::GetComputedStyleNoFlush(element, nullptr);
if (!elementStyle) {
// Consider nodes without a ComputedStyle to be NOT preformatted:
// For instance, this is true of JS tags inside the body (which show
// up as #text nodes but have no ComputedStyle).
return false;
}
return elementStyle->StyleText()->WhiteSpaceIsSignificant();
}
} // namespace mozilla } // namespace mozilla

View File

@ -854,6 +854,12 @@ class EditorUtils final {
!EditorUtils::IsPaddingBRElementForEmptyEditor(aContent); !EditorUtils::IsPaddingBRElementForEmptyEditor(aContent);
} }
/**
* IsContentPreformatted() checks the style info for the node for the
* preformatted text style. This does NOT flush layout.
*/
static bool IsContentPreformatted(nsIContent& aContent);
/** /**
* Helper method for `AppendString()` and `AppendSubString()`. This should * Helper method for `AppendString()` and `AppendSubString()`. This should
* be called only when `aText` is in a password field. This method masks * be called only when `aText` is in a password field. This method masks

View File

@ -80,7 +80,7 @@ HTMLEditor::GetAbsolutelyPositionedSelectionContainer() const {
AutoTArray<RefPtr<Element>, 24> arrayOfParentElements; AutoTArray<RefPtr<Element>, 24> arrayOfParentElements;
for (Element* element : for (Element* element :
InclusiveAncestorsOfType<Element>(*selectionContainerElement)) { selectionContainerElement->InclusiveAncestorsOfType<Element>()) {
arrayOfParentElements.AppendElement(element); arrayOfParentElements.AppendElement(element);
} }

View File

@ -67,6 +67,7 @@ namespace mozilla {
using namespace dom; using namespace dom;
using StyleDifference = HTMLEditUtils::StyleDifference; using StyleDifference = HTMLEditUtils::StyleDifference;
using ChildBlockBoundary = HTMLEditUtils::ChildBlockBoundary;
enum { kLonely = 0, kPrevSib = 1, kNextSib = 2, kBothSibs = 3 }; enum { kLonely = 0, kPrevSib = 1, kNextSib = 2, kBothSibs = 3 };
@ -97,14 +98,11 @@ static bool IsStyleCachePreservingSubAction(EditSubAction aEditSubAction) {
} }
class MOZ_RAII AutoSetTemporaryAncestorLimiter final { class MOZ_RAII AutoSetTemporaryAncestorLimiter final {
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
public: public:
explicit AutoSetTemporaryAncestorLimiter( explicit AutoSetTemporaryAncestorLimiter(HTMLEditor& aHTMLEditor,
HTMLEditor& aHTMLEditor, Selection& aSelection, Selection& aSelection,
nsINode& aStartPointNode MOZ_GUARD_OBJECT_NOTIFIER_PARAM) { nsINode& aStartPointNode) {
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
MOZ_ASSERT(aSelection.GetType() == SelectionType::eNormal); MOZ_ASSERT(aSelection.GetType() == SelectionType::eNormal);
if (aSelection.GetAncestorLimiter()) { if (aSelection.GetAncestorLimiter()) {
@ -1009,7 +1007,7 @@ AlignStateAtSelection::AlignStateAtSelection(HTMLEditor& aHTMLEditor,
} }
for (nsIContent* containerContent : for (nsIContent* containerContent :
InclusiveAncestorsOfType<nsIContent>(*editTargetContent)) { editTargetContent->InclusiveAncestorsOfType<nsIContent>()) {
// If the node is a parent `<table>` element of edit target, let's break // If the node is a parent `<table>` element of edit target, let's break
// here to materialize the 'inline-block' behaviour of html tables // here to materialize the 'inline-block' behaviour of html tables
// regarding to text alignment. // regarding to text alignment.
@ -1453,7 +1451,8 @@ EditActionResult HTMLEditor::HandleInsertText(
} }
EditorDOMPoint pointToInsert(firstRange->StartRef()); EditorDOMPoint pointToInsert(firstRange->StartRef());
if (NS_WARN_IF(!pointToInsert.IsSet())) { if (NS_WARN_IF(!pointToInsert.IsSet()) ||
NS_WARN_IF(!pointToInsert.IsInContentNode())) {
return EditActionHandled(NS_ERROR_FAILURE); return EditActionHandled(NS_ERROR_FAILURE);
} }
MOZ_ASSERT(pointToInsert.IsSetAndValid()); MOZ_ASSERT(pointToInsert.IsSetAndValid());
@ -1521,7 +1520,8 @@ EditActionResult HTMLEditor::HandleInsertText(
// is our text going to be PREformatted? // is our text going to be PREformatted?
// We remember this so that we know how to handle tabs. // We remember this so that we know how to handle tabs.
bool isPRE = EditorBase::IsPreformatted(pointToInsert.GetContainer()); bool isPRE =
EditorUtils::IsContentPreformatted(*pointToInsert.ContainerAsContent());
// turn off the edit listener: we know how to // turn off the edit listener: we know how to
// build the "doc changed range" ourselves, and it's // build the "doc changed range" ourselves, and it's
@ -7825,8 +7825,9 @@ nsresult HTMLEditor::MaybeExtendSelectionToHardLineEdgesForBlockEditAction() {
// of going "down" into a block and "up" out of a block. // of going "down" into a block and "up" out of a block.
if (wsScannerAtEnd.StartsFromOtherBlockElement()) { if (wsScannerAtEnd.StartsFromOtherBlockElement()) {
// endpoint is just after the close of a block. // endpoint is just after the close of a block.
nsINode* child = GetRightmostChild( nsIContent* child = HTMLEditUtils::GetLastLeafChild(
wsScannerAtEnd.StartReasonOtherBlockElementPtr(), true); *wsScannerAtEnd.StartReasonOtherBlockElementPtr(),
ChildBlockBoundary::TreatAsLeaf);
if (child) { if (child) {
newEndPoint.SetAfter(child); newEndPoint.SetAfter(child);
} }
@ -7853,8 +7854,9 @@ nsresult HTMLEditor::MaybeExtendSelectionToHardLineEdgesForBlockEditAction() {
// of going "down" into a block and "up" out of a block. // of going "down" into a block and "up" out of a block.
if (wsScannerAtStart.EndsByOtherBlockElement()) { if (wsScannerAtStart.EndsByOtherBlockElement()) {
// startpoint is just before the start of a block. // startpoint is just before the start of a block.
nsINode* child = GetLeftmostChild( nsINode* child = HTMLEditUtils::GetFirstLeafChild(
wsScannerAtStart.EndReasonOtherBlockElementPtr(), true); *wsScannerAtStart.EndReasonOtherBlockElementPtr(),
ChildBlockBoundary::TreatAsLeaf);
if (child) { if (child) {
newStartPoint.Set(child); newStartPoint.Set(child);
} }
@ -8072,8 +8074,8 @@ EditorDOMPoint HTMLEditor::GetCurrentHardLineEndPoint(
} }
// Check for newlines in pre-formatted text nodes. // Check for newlines in pre-formatted text nodes.
if (EditorBase::IsPreformatted(nextEditableContent) && if (nextEditableContent->IsText() &&
nextEditableContent->IsText()) { EditorUtils::IsContentPreformatted(*nextEditableContent)) {
nsAutoString textContent; nsAutoString textContent;
nextEditableContent->GetAsText()->GetData(textContent); nextEditableContent->GetAsText()->GetData(textContent);
int32_t newlinePos = textContent.FindChar(nsCRT::LF); int32_t newlinePos = textContent.FindChar(nsCRT::LF);
@ -8793,8 +8795,7 @@ nsIContent* HTMLEditor::GetMostAncestorInlineElement(nsINode& aNode) const {
// Looks for the highest inline parent in the editing host. // Looks for the highest inline parent in the editing host.
nsIContent* topMostInlineContent = aNode.AsContent(); nsIContent* topMostInlineContent = aNode.AsContent();
for (nsIContent* content : for (nsIContent* content : aNode.AncestorsOfType<nsIContent>()) {
InclusiveAncestorsOfType<nsIContent>(*aNode.GetParent())) {
if (content == host || !HTMLEditUtils::IsInlineElement(*content)) { if (content == host || !HTMLEditUtils::IsInlineElement(*content)) {
break; break;
} }
@ -9237,7 +9238,8 @@ nsresult HTMLEditor::SplitParagraph(
// selection to beginning of right hand para; // selection to beginning of right hand para;
// look inside any containers that are up front. // look inside any containers that are up front.
nsCOMPtr<nsIContent> child = GetLeftmostChild(&aParentDivOrP, true); nsCOMPtr<nsIContent> child = HTMLEditUtils::GetFirstLeafChild(
aParentDivOrP, ChildBlockBoundary::TreatAsLeaf);
if (child && (child->IsText() || HTMLEditUtils::IsContainerNode(*child))) { if (child && (child->IsText() || HTMLEditUtils::IsContainerNode(*child))) {
nsresult rv = CollapseSelectionToStartOf(*child); nsresult rv = CollapseSelectionToStartOf(*child);
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) { if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {

View File

@ -193,6 +193,280 @@ class HTMLEditUtils final {
static bool IsNonListSingleLineContainer(nsINode& aNode); static bool IsNonListSingleLineContainer(nsINode& aNode);
static bool IsSingleLineContainer(nsINode& aNode); static bool IsSingleLineContainer(nsINode& aNode);
/**
* GetLastLeafChild() returns rightmost leaf content in aNode. It depends on
* aChildBlockBoundary whether this scans into a block child or treat
* block as a leaf.
*/
enum class ChildBlockBoundary {
// Even if there is a child block, keep scanning a leaf content in it.
Ignore,
// If there is a child block, return it.
TreatAsLeaf,
};
static nsIContent* GetLastLeafChild(nsINode& aNode,
ChildBlockBoundary aChildBlockBoundary) {
for (nsIContent* content = aNode.GetLastChild(); content;
content = content->GetLastChild()) {
if (aChildBlockBoundary == ChildBlockBoundary::TreatAsLeaf &&
HTMLEditUtils::IsBlockElement(*content)) {
return content;
}
if (!content->HasChildren()) {
return content;
}
}
return nullptr;
}
/**
* GetFirstLeafChild() returns leftmost leaf content in aNode. It depends on
* aChildBlockBoundary whether this scans into a block child or treat
* block as a leaf.
*/
static nsIContent* GetFirstLeafChild(nsINode& aNode,
ChildBlockBoundary aChildBlockBoundary) {
for (nsIContent* content = aNode.GetFirstChild(); content;
content = content->GetFirstChild()) {
if (aChildBlockBoundary == ChildBlockBoundary::TreatAsLeaf &&
HTMLEditUtils::IsBlockElement(*content)) {
return content;
}
if (!content->HasChildren()) {
return content;
}
}
return nullptr;
}
/**
* GetNextLeafContentOrNextBlockElement() returns next leaf content or
* next block element of aStartContent inside aAncestorLimiter.
* Note that the result may be a contet outside aCurrentBlock if
* aStartContent equals aCurrentBlock.
*
* @param aStartContent The start content to scan next content.
* @param aCurrentBlock Must be ancestor of aStartContent. Dispite
* the name, inline content is allowed if
* aStartContent is in an inline editing host.
* @param aAncestorLimiter Optional, setting this guarantees the
* result is in aAncestorLimiter unless
* aStartContent is not a descendant of this.
*/
static nsIContent* GetNextLeafContentOrNextBlockElement(
nsIContent& aStartContent, nsIContent& aCurrentBlock,
Element* aAncestorLimiter = nullptr) {
if (&aStartContent == aAncestorLimiter) {
return nullptr;
}
nsIContent* nextContent = aStartContent.GetNextSibling();
if (!nextContent) {
if (!aStartContent.GetParentElement()) {
NS_WARNING("Reached orphan node while climbing up the DOM tree");
return nullptr;
}
for (Element* parentElement : aStartContent.AncestorsOfType<Element>()) {
if (parentElement == &aCurrentBlock) {
return nullptr;
}
if (parentElement == aAncestorLimiter) {
NS_WARNING("Reached editing host while climbing up the DOM tree");
return nullptr;
}
nextContent = parentElement->GetNextSibling();
if (nextContent) {
break;
}
if (!parentElement->GetParentElement()) {
NS_WARNING("Reached orphan node while climbing up the DOM tree");
return nullptr;
}
}
MOZ_ASSERT(nextContent);
}
// We have a next content. If it's a block, return it.
if (HTMLEditUtils::IsBlockElement(*nextContent)) {
return nextContent;
}
if (HTMLEditUtils::IsContainerNode(*nextContent)) {
// Else if it's a container, get deep leftmost child
if (nsIContent* child = HTMLEditUtils::GetFirstLeafChild(
*nextContent, ChildBlockBoundary::Ignore)) {
return child;
}
}
// Else return the next content itself.
return nextContent;
}
/**
* Similar to the above method, but take a DOM point to specify scan start
* point.
*/
template <typename PT, typename CT>
static nsIContent* GetNextLeafContentOrNextBlockElement(
const EditorDOMPointBase<PT, CT>& aStartPoint, nsIContent& aCurrentBlock,
Element* aAncestorLimiter = nullptr) {
MOZ_ASSERT(aStartPoint.IsSet());
if (!aStartPoint.IsInContentNode()) {
return nullptr;
}
if (aStartPoint.IsInTextNode()) {
return HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
*aStartPoint.ContainerAsText(), aCurrentBlock, aAncestorLimiter);
}
if (!HTMLEditUtils::IsContainerNode(*aStartPoint.ContainerAsContent())) {
return HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
*aStartPoint.ContainerAsContent(), aCurrentBlock, aAncestorLimiter);
}
nsCOMPtr<nsIContent> nextContent = aStartPoint.GetChild();
if (!nextContent) {
if (aStartPoint.GetContainer() == &aCurrentBlock) {
// We are at end of the block.
return nullptr;
}
// We are at end of non-block container
return HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
*aStartPoint.ContainerAsContent(), aCurrentBlock, aAncestorLimiter);
}
// We have a next node. If it's a block, return it.
if (HTMLEditUtils::IsBlockElement(*nextContent)) {
return nextContent;
}
if (HTMLEditUtils::IsContainerNode(*nextContent)) {
// else if it's a container, get deep leftmost child
if (nsIContent* child = HTMLEditUtils::GetFirstLeafChild(
*nextContent, ChildBlockBoundary::Ignore)) {
return child;
}
}
// Else return the node itself
return nextContent;
}
/**
* GetPreviousLeafContentOrPreviousBlockElement() returns previous leaf
* content or previous block element of aStartContent inside
* aAncestorLimiter.
* Note that the result may be a contet outside aCurrentBlock if
* aStartContent equals aCurrentBlock.
*
* @param aStartContent The start content to scan previous content.
* @param aCurrentBlock Must be ancestor of aStartContent. Dispite
* the name, inline content is allowed if
* aStartContent is in an inline editing host.
* @param aAncestorLimiter Optional, setting this guarantees the
* result is in aAncestorLimiter unless
* aStartContent is not a descendant of this.
*/
static nsIContent* GetPreviousLeafContentOrPreviousBlockElement(
nsIContent& aStartContent, nsIContent& aCurrentBlock,
Element* aAncestorLimiter = nullptr) {
if (&aStartContent == aAncestorLimiter) {
return nullptr;
}
nsIContent* previousContent = aStartContent.GetPreviousSibling();
if (!previousContent) {
if (!aStartContent.GetParentElement()) {
NS_WARNING("Reached orphan node while climbing up the DOM tree");
return nullptr;
}
for (Element* parentElement : aStartContent.AncestorsOfType<Element>()) {
if (parentElement == &aCurrentBlock) {
return nullptr;
}
if (parentElement == aAncestorLimiter) {
NS_WARNING("Reached editing host while climbing up the DOM tree");
return nullptr;
}
previousContent = parentElement->GetPreviousSibling();
if (previousContent) {
break;
}
if (!parentElement->GetParentElement()) {
NS_WARNING("Reached orphan node while climbing up the DOM tree");
return nullptr;
}
}
MOZ_ASSERT(previousContent);
}
// We have a next content. If it's a block, return it.
if (HTMLEditUtils::IsBlockElement(*previousContent)) {
return previousContent;
}
if (HTMLEditUtils::IsContainerNode(*previousContent)) {
// Else if it's a container, get deep rightmost child
if (nsIContent* child = HTMLEditUtils::GetLastLeafChild(
*previousContent, ChildBlockBoundary::Ignore)) {
return child;
}
}
// Else return the next content itself.
return previousContent;
}
/**
* Similar to the above method, but take a DOM point to specify scan start
* point.
*/
template <typename PT, typename CT>
static nsIContent* GetPreviousLeafContentOrPreviousBlockElement(
const EditorDOMPointBase<PT, CT>& aStartPoint, nsIContent& aCurrentBlock,
Element* aAncestorLimiter = nullptr) {
MOZ_ASSERT(aStartPoint.IsSet());
if (!aStartPoint.IsInContentNode()) {
return nullptr;
}
if (aStartPoint.IsInTextNode()) {
return HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
*aStartPoint.ContainerAsText(), aCurrentBlock, aAncestorLimiter);
}
if (!HTMLEditUtils::IsContainerNode(*aStartPoint.ContainerAsContent())) {
return HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
*aStartPoint.ContainerAsContent(), aCurrentBlock, aAncestorLimiter);
}
if (aStartPoint.IsStartOfContainer()) {
if (aStartPoint.GetContainer() == &aCurrentBlock) {
// We are at start of the block.
return nullptr;
}
// We are at start of non-block container
return HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
*aStartPoint.ContainerAsContent(), aCurrentBlock, aAncestorLimiter);
}
nsCOMPtr<nsIContent> previousContent =
aStartPoint.GetPreviousSiblingOfChild();
if (NS_WARN_IF(!previousContent)) {
return nullptr;
}
// We have a prior node. If it's a block, return it.
if (HTMLEditUtils::IsBlockElement(*previousContent)) {
return previousContent;
}
if (HTMLEditUtils::IsContainerNode(*previousContent)) {
// Else if it's a container, get deep rightmost child
if (nsIContent* child = HTMLEditUtils::GetLastLeafChild(
*previousContent, ChildBlockBoundary::Ignore)) {
return child;
}
}
// Else return the node itself
return previousContent;
}
/** /**
* GetAncestorBlockElement() returns parent or nearest ancestor of aContent * GetAncestorBlockElement() returns parent or nearest ancestor of aContent
* which is a block element. If aAncestorLimiter is not nullptr, * which is a block element. If aAncestorLimiter is not nullptr,
@ -209,12 +483,7 @@ class HTMLEditUtils final {
return nullptr; return nullptr;
} }
if (!aContent.GetParent()) { for (Element* element : aContent.AncestorsOfType<Element>()) {
return nullptr;
}
for (Element* element : dom::InclusiveAncestorsOfType<Element>(
const_cast<nsIContent&>(*aContent.GetParent()))) {
if (HTMLEditUtils::IsBlockElement(*element)) { if (HTMLEditUtils::IsBlockElement(*element)) {
return element; return element;
} }
@ -257,8 +526,7 @@ class HTMLEditUtils final {
if (!aContent.GetParent()) { if (!aContent.GetParent()) {
return nullptr; return nullptr;
} }
for (Element* element : dom::InclusiveAncestorsOfType<Element>( for (Element* element : aContent.InclusiveAncestorsOfType<Element>()) {
const_cast<nsIContent&>(aContent))) {
if (HTMLEditUtils::IsTable(element)) { if (HTMLEditUtils::IsTable(element)) {
return element; return element;
} }

View File

@ -63,6 +63,8 @@ namespace mozilla {
using namespace dom; using namespace dom;
using namespace widget; using namespace widget;
using ChildBlockBoundary = HTMLEditUtils::ChildBlockBoundary;
const char16_t kNBSP = 160; const char16_t kNBSP = 160;
// Some utilities to handle overloading of "A" tag for link and named anchor. // Some utilities to handle overloading of "A" tag for link and named anchor.
@ -855,7 +857,7 @@ void HTMLEditor::IsPrevCharInNodeWhitespace(nsIContent* aContent,
} }
} }
bool HTMLEditor::IsVisibleBRElement(nsINode* aNode) { bool HTMLEditor::IsVisibleBRElement(const nsINode* aNode) {
MOZ_ASSERT(aNode); MOZ_ASSERT(aNode);
if (!aNode->IsHTMLElement(nsGkAtoms::br)) { if (!aNode->IsHTMLElement(nsGkAtoms::br)) {
return false; return false;
@ -2519,7 +2521,7 @@ Element* HTMLEditor::GetInclusiveAncestorByTagNameInternal(
bool lookForLink = IsLinkTag(aTagName); bool lookForLink = IsLinkTag(aTagName);
bool lookForNamedAnchor = IsNamedAnchorTag(aTagName); bool lookForNamedAnchor = IsNamedAnchorTag(aTagName);
for (Element* element : InclusiveAncestorsOfType<Element>(*currentElement)) { for (Element* element : currentElement->InclusiveAncestorsOfType<Element>()) {
// Stop searching if parent is a body element. Note: Originally used // Stop searching if parent is a body element. Note: Originally used
// IsRoot() to/ stop at table cells, but that's too messy when you are // IsRoot() to/ stop at table cells, but that's too messy when you are
// trying to find the parent table. // trying to find the parent table.
@ -2739,9 +2741,21 @@ already_AddRefed<Element> HTMLEditor::GetSelectedElement(const nsAtom* aTagName,
// - <p><b>[def</b>}<br></p> // - <p><b>[def</b>}<br></p>
// Note that we don't need special handling for <a href> because double // Note that we don't need special handling for <a href> because double
// clicking it selects the element and we use the first path to handle it. // clicking it selects the element and we use the first path to handle it.
if (lastElementInRange->GetNextSibling() && // Additionally, we have this case too:
lastElementInRange->GetNextSibling()->IsHTMLElement(nsGkAtoms::br)) { // - <p><b>[def</b><b>}<br></b></p>
return nullptr; // In these cases, the <br> element is not listed up by PostContentIterator.
// So, we should return nullptr if next sibling is a `<br>` element or
// next sibling starts with `<br>` element.
if (nsIContent* nextSibling = lastElementInRange->GetNextSibling()) {
if (nextSibling->IsHTMLElement(nsGkAtoms::br)) {
return nullptr;
}
nsIContent* firstEditableLeaf = HTMLEditUtils::GetFirstLeafChild(
*nextSibling, ChildBlockBoundary::Ignore);
if (firstEditableLeaf &&
firstEditableLeaf->IsHTMLElement(nsGkAtoms::br)) {
return nullptr;
}
} }
if (!aTagName) { if (!aTagName) {
@ -3057,8 +3071,7 @@ nsresult HTMLEditor::RemoveEmptyInclusiveAncestorInlineElements(
} }
OwningNonNull<nsIContent> content = aContent; OwningNonNull<nsIContent> content = aContent;
for (nsIContent* parentContent : for (nsIContent* parentContent : aContent.AncestorsOfType<nsIContent>()) {
InclusiveAncestorsOfType<nsIContent>(*aContent.GetParent())) {
if (HTMLEditUtils::IsBlockElement(*parentContent) || if (HTMLEditUtils::IsBlockElement(*parentContent) ||
parentContent->Length() != 1 || parentContent->Length() != 1 ||
!HTMLEditUtils::IsSimplyEditableNode(*parentContent) || !HTMLEditUtils::IsSimplyEditableNode(*parentContent) ||
@ -4836,7 +4849,7 @@ nsIContent* HTMLEditor::GetNextHTMLSibling(nsINode* aNode,
} }
nsIContent* HTMLEditor::GetPreviousHTMLElementOrTextInternal( nsIContent* HTMLEditor::GetPreviousHTMLElementOrTextInternal(
nsINode& aNode, bool aNoBlockCrossing) const { const nsINode& aNode, bool aNoBlockCrossing) const {
if (NS_WARN_IF(!GetActiveEditingHost())) { if (NS_WARN_IF(!GetActiveEditingHost())) {
return nullptr; return nullptr;
} }
@ -4874,7 +4887,7 @@ nsIContent* HTMLEditor::GetPreviousEditableHTMLNodeInternal(
} }
nsIContent* HTMLEditor::GetNextHTMLElementOrTextInternal( nsIContent* HTMLEditor::GetNextHTMLElementOrTextInternal(
nsINode& aNode, bool aNoBlockCrossing) const { const nsINode& aNode, bool aNoBlockCrossing) const {
if (NS_WARN_IF(!GetActiveEditingHost())) { if (NS_WARN_IF(!GetActiveEditingHost())) {
return nullptr; return nullptr;
} }
@ -4948,7 +4961,8 @@ nsIContent* HTMLEditor::GetLastEditableChild(nsINode& aNode) const {
} }
nsIContent* HTMLEditor::GetFirstEditableLeaf(nsINode& aNode) const { nsIContent* HTMLEditor::GetFirstEditableLeaf(nsINode& aNode) const {
nsIContent* child = GetLeftmostChild(&aNode); nsIContent* child =
HTMLEditUtils::GetFirstLeafChild(aNode, ChildBlockBoundary::Ignore);
while (child && (!EditorUtils::IsEditableContent(*child, EditorType::HTML) || while (child && (!EditorUtils::IsEditableContent(*child, EditorType::HTML) ||
child->HasChildren())) { child->HasChildren())) {
child = GetNextEditableHTMLNode(*child); child = GetNextEditableHTMLNode(*child);
@ -4963,7 +4977,8 @@ nsIContent* HTMLEditor::GetFirstEditableLeaf(nsINode& aNode) const {
} }
nsIContent* HTMLEditor::GetLastEditableLeaf(nsINode& aNode) const { nsIContent* HTMLEditor::GetLastEditableLeaf(nsINode& aNode) const {
nsCOMPtr<nsIContent> child = GetRightmostChild(&aNode, false); nsIContent* child =
HTMLEditUtils::GetLastLeafChild(aNode, ChildBlockBoundary::Ignore);
while (child && (!EditorUtils::IsEditableContent(*child, EditorType::HTML) || while (child && (!EditorUtils::IsEditableContent(*child, EditorType::HTML) ||
child->HasChildren())) { child->HasChildren())) {
child = GetPreviousEditableHTMLNode(*child); child = GetPreviousEditableHTMLNode(*child);

View File

@ -919,7 +919,7 @@ class HTMLEditor final : public TextEditor,
/** /**
* Small utility routine to test if a break node is visible to user. * Small utility routine to test if a break node is visible to user.
*/ */
bool IsVisibleBRElement(nsINode* aNode); bool IsVisibleBRElement(const nsINode* aNode);
/** /**
* Helper routines for font size changing. * Helper routines for font size changing.
@ -999,10 +999,10 @@ class HTMLEditor final : public TextEditor,
* EditorBase::GetPreviousElementOrText*() but this won't return nodes * EditorBase::GetPreviousElementOrText*() but this won't return nodes
* outside active editing host. * outside active editing host.
*/ */
nsIContent* GetPreviousHTMLElementOrText(nsINode& aNode) const { nsIContent* GetPreviousHTMLElementOrText(const nsINode& aNode) const {
return GetPreviousHTMLElementOrTextInternal(aNode, false); return GetPreviousHTMLElementOrTextInternal(aNode, false);
} }
nsIContent* GetPreviousHTMLElementOrTextInBlock(nsINode& aNode) const { nsIContent* GetPreviousHTMLElementOrTextInBlock(const nsINode& aNode) const {
return GetPreviousHTMLElementOrTextInternal(aNode, true); return GetPreviousHTMLElementOrTextInternal(aNode, true);
} }
template <typename PT, typename CT> template <typename PT, typename CT>
@ -1020,7 +1020,7 @@ class HTMLEditor final : public TextEditor,
* GetPreviousHTMLElementOrTextInternal() methods are common implementation * GetPreviousHTMLElementOrTextInternal() methods are common implementation
* of above methods. Please don't use this method directly. * of above methods. Please don't use this method directly.
*/ */
nsIContent* GetPreviousHTMLElementOrTextInternal(nsINode& aNode, nsIContent* GetPreviousHTMLElementOrTextInternal(const nsINode& aNode,
bool aNoBlockCrossing) const; bool aNoBlockCrossing) const;
template <typename PT, typename CT> template <typename PT, typename CT>
nsIContent* GetPreviousHTMLElementOrTextInternal( nsIContent* GetPreviousHTMLElementOrTextInternal(
@ -1068,10 +1068,10 @@ class HTMLEditor final : public TextEditor,
* On the other hand, methods which take |nsINode&| start to search from * On the other hand, methods which take |nsINode&| start to search from
* next node of aNode. * next node of aNode.
*/ */
nsIContent* GetNextHTMLElementOrText(nsINode& aNode) const { nsIContent* GetNextHTMLElementOrText(const nsINode& aNode) const {
return GetNextHTMLElementOrTextInternal(aNode, false); return GetNextHTMLElementOrTextInternal(aNode, false);
} }
nsIContent* GetNextHTMLElementOrTextInBlock(nsINode& aNode) const { nsIContent* GetNextHTMLElementOrTextInBlock(const nsINode& aNode) const {
return GetNextHTMLElementOrTextInternal(aNode, true); return GetNextHTMLElementOrTextInternal(aNode, true);
} }
template <typename PT, typename CT> template <typename PT, typename CT>
@ -1089,7 +1089,7 @@ class HTMLEditor final : public TextEditor,
* GetNextHTMLNodeInternal() methods are common implementation * GetNextHTMLNodeInternal() methods are common implementation
* of above methods. Please don't use this method directly. * of above methods. Please don't use this method directly.
*/ */
nsIContent* GetNextHTMLElementOrTextInternal(nsINode& aNode, nsIContent* GetNextHTMLElementOrTextInternal(const nsINode& aNode,
bool aNoBlockCrossing) const; bool aNoBlockCrossing) const;
template <typename PT, typename CT> template <typename PT, typename CT>
nsIContent* GetNextHTMLElementOrTextInternal( nsIContent* GetNextHTMLElementOrTextInternal(

View File

@ -45,6 +45,8 @@ namespace mozilla {
using namespace dom; using namespace dom;
using ChildBlockBoundary = HTMLEditUtils::ChildBlockBoundary;
nsresult HTMLEditor::SetInlinePropertyAsAction(nsAtom& aProperty, nsresult HTMLEditor::SetInlinePropertyAsAction(nsAtom& aProperty,
nsAtom* aAttribute, nsAtom* aAttribute,
const nsAString& aValue, const nsAString& aValue,
@ -757,7 +759,7 @@ SplitNodeResult HTMLEditor::SplitAncestorStyledInlineElementsAt(
AutoTArray<OwningNonNull<nsIContent>, 24> arrayOfParents; AutoTArray<OwningNonNull<nsIContent>, 24> arrayOfParents;
for (nsIContent* content : for (nsIContent* content :
InclusiveAncestorsOfType<nsIContent>(*aPointToSplit.GetContainer())) { aPointToSplit.GetContainer()->InclusiveAncestorsOfType<nsIContent>()) {
if (HTMLEditUtils::IsBlockElement(*content) || !content->GetParent() || if (HTMLEditUtils::IsBlockElement(*content) || !content->GetParent() ||
!EditorUtils::IsEditableContent(*content->GetParent(), !EditorUtils::IsEditableContent(*content->GetParent(),
EditorType::HTML)) { EditorType::HTML)) {
@ -882,10 +884,10 @@ EditResult HTMLEditor::ClearStyleAt(const EditorDOMPoint& aPoint,
// the next node. The first example should become // the next node. The first example should become
// `<p><b><i>a</i></b><b><i></i></b><b><i>bc</i></b></p>`. // `<p><b><i>a</i></b><b><i></i></b><b><i>bc</i></b></p>`.
// ^^^^^^^^^^^^^^ // ^^^^^^^^^^^^^^
nsIContent* leftmostChildOfNextNode = nsIContent* firstLeafChildOfNextNode = HTMLEditUtils::GetFirstLeafChild(
GetLeftmostChild(splitResult.GetNextNode()); *splitResult.GetNextNode(), ChildBlockBoundary::Ignore);
EditorDOMPoint atStartOfNextNode(leftmostChildOfNextNode EditorDOMPoint atStartOfNextNode(firstLeafChildOfNextNode
? leftmostChildOfNextNode ? firstLeafChildOfNextNode
: splitResult.GetNextNode(), : splitResult.GetNextNode(),
0); 0);
RefPtr<HTMLBRElement> brElement; RefPtr<HTMLBRElement> brElement;
@ -940,11 +942,13 @@ EditResult HTMLEditor::ClearStyleAt(const EditorDOMPoint& aPoint,
// Now, we want to put `<br>` element into the empty split node if // Now, we want to put `<br>` element into the empty split node if
// it was in next node of the first split. // it was in next node of the first split.
// E.g., `<p><b><i>a</i></b><b><i><br></i></b><b><i>bc</i></b></p>` // E.g., `<p><b><i>a</i></b><b><i><br></i></b><b><i>bc</i></b></p>`
nsIContent* leftmostChild = nsIContent* firstLeafChildOfPreviousNode = HTMLEditUtils::GetFirstLeafChild(
GetLeftmostChild(splitResultAtStartOfNextNode.GetPreviousNode()); *splitResultAtStartOfNextNode.GetPreviousNode(),
ChildBlockBoundary::Ignore);
EditorDOMPoint pointToPutCaret( EditorDOMPoint pointToPutCaret(
leftmostChild ? leftmostChild firstLeafChildOfPreviousNode
: splitResultAtStartOfNextNode.GetPreviousNode(), ? firstLeafChildOfPreviousNode
: splitResultAtStartOfNextNode.GetPreviousNode(),
0); 0);
// If the right node starts with a `<br>`, suck it out of right node and into // If the right node starts with a `<br>`, suck it out of right node and into
// the left node left node. This is so we you don't revert back to the // the left node left node. This is so we you don't revert back to the
@ -1184,7 +1188,7 @@ nsresult HTMLEditor::PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange) {
} }
EditorRawDOMPoint newRangeStart(aRange.StartRef()); EditorRawDOMPoint newRangeStart(aRange.StartRef());
for (Element* element : for (Element* element :
InclusiveAncestorsOfType<Element>(*aRange.GetStartContainer())) { aRange.GetStartContainer()->InclusiveAncestorsOfType<Element>()) {
if (element->IsHTMLElement(nsGkAtoms::body)) { if (element->IsHTMLElement(nsGkAtoms::body)) {
break; break;
} }
@ -1204,7 +1208,7 @@ nsresult HTMLEditor::PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange) {
EditorRawDOMPoint newRangeEnd(aRange.EndRef()); EditorRawDOMPoint newRangeEnd(aRange.EndRef());
for (Element* element : for (Element* element :
InclusiveAncestorsOfType<Element>(*aRange.GetEndContainer())) { aRange.GetEndContainer()->InclusiveAncestorsOfType<Element>()) {
if (element->IsHTMLElement(nsGkAtoms::body)) { if (element->IsHTMLElement(nsGkAtoms::body)) {
break; break;
} }
@ -1239,7 +1243,7 @@ nsresult HTMLEditor::PromoteInlineRange(nsRange& aRange) {
} }
EditorRawDOMPoint newRangeStart(aRange.StartRef()); EditorRawDOMPoint newRangeStart(aRange.StartRef());
for (nsIContent* content : for (nsIContent* content :
InclusiveAncestorsOfType<nsIContent>(*aRange.GetStartContainer())) { aRange.GetStartContainer()->InclusiveAncestorsOfType<nsIContent>()) {
MOZ_ASSERT(newRangeStart.GetContainer() == content); MOZ_ASSERT(newRangeStart.GetContainer() == content);
if (content->IsHTMLElement(nsGkAtoms::body) || if (content->IsHTMLElement(nsGkAtoms::body) ||
!EditorUtils::IsEditableContent(*content, EditorType::HTML) || !EditorUtils::IsEditableContent(*content, EditorType::HTML) ||
@ -1257,7 +1261,7 @@ nsresult HTMLEditor::PromoteInlineRange(nsRange& aRange) {
EditorRawDOMPoint newRangeEnd(aRange.EndRef()); EditorRawDOMPoint newRangeEnd(aRange.EndRef());
for (nsIContent* content : for (nsIContent* content :
InclusiveAncestorsOfType<nsIContent>(*aRange.GetEndContainer())) { aRange.GetEndContainer()->InclusiveAncestorsOfType<nsIContent>()) {
MOZ_ASSERT(newRangeEnd.GetContainer() == content); MOZ_ASSERT(newRangeEnd.GetContainer() == content);
if (content->IsHTMLElement(nsGkAtoms::body) || if (content->IsHTMLElement(nsGkAtoms::body) ||
!EditorUtils::IsEditableContent(*content, EditorType::HTML) || !EditorUtils::IsEditableContent(*content, EditorType::HTML) ||

View File

@ -7,6 +7,7 @@
#include <algorithm> #include <algorithm>
#include "EditAggregateTransaction.h" #include "EditAggregateTransaction.h"
#include "HTMLEditUtils.h"
#include "InternetCiter.h" #include "InternetCiter.h"
#include "PlaceholderTransaction.h" #include "PlaceholderTransaction.h"
#include "gfxFontUtils.h" #include "gfxFontUtils.h"
@ -68,6 +69,8 @@ namespace mozilla {
using namespace dom; using namespace dom;
using ChildBlockBoundary = HTMLEditUtils::ChildBlockBoundary;
TextEditor::TextEditor() TextEditor::TextEditor()
: mMaxTextLength(-1), : mMaxTextLength(-1),
mUnmaskedStart(UINT32_MAX), mUnmaskedStart(UINT32_MAX),
@ -1004,11 +1007,12 @@ nsresult TextEditor::UndoAsAction(uint32_t aCount, nsIPrincipal* aPrincipal) {
// at redo, or doing it everywhere else that might care. Since undo // at redo, or doing it everywhere else that might care. Since undo
// and redo are relatively rare, it makes sense to take the (small) // and redo are relatively rare, it makes sense to take the (small)
// performance hit here. // performance hit here.
nsIContent* leftMostChild = GetLeftmostChild(mRootElement); nsIContent* firstLeafChild = HTMLEditUtils::GetFirstLeafChild(
if (leftMostChild && *mRootElement, ChildBlockBoundary::Ignore);
EditorUtils::IsPaddingBRElementForEmptyEditor(*leftMostChild)) { if (firstLeafChild &&
EditorUtils::IsPaddingBRElementForEmptyEditor(*firstLeafChild)) {
mPaddingBRElementForEmptyEditor = mPaddingBRElementForEmptyEditor =
static_cast<HTMLBRElement*>(leftMostChild); static_cast<HTMLBRElement*>(firstLeafChild);
} else { } else {
mPaddingBRElementForEmptyEditor = nullptr; mPaddingBRElementForEmptyEditor = nullptr;
} }

View File

@ -206,15 +206,9 @@ void TypeInState::ClearProp(nsAtom* aProp, nsAtom* aAttr) {
* Caller assumes ownership of PropItem and must delete it. * Caller assumes ownership of PropItem and must delete it.
*/ */
UniquePtr<PropItem> TypeInState::TakeClearProperty() { UniquePtr<PropItem> TypeInState::TakeClearProperty() {
size_t count = mClearedArray.Length(); return mClearedArray.Length()
if (!count) { ? UniquePtr<PropItem>{mClearedArray.PopLastElement()}
return nullptr; : nullptr;
}
--count; // indices are zero based
PropItem* propItem = mClearedArray[count];
mClearedArray.RemoveElementAt(count);
return UniquePtr<PropItem>(propItem);
} }
/** /**
@ -222,14 +216,8 @@ UniquePtr<PropItem> TypeInState::TakeClearProperty() {
* Caller assumes ownership of PropItem and must delete it. * Caller assumes ownership of PropItem and must delete it.
*/ */
UniquePtr<PropItem> TypeInState::TakeSetProperty() { UniquePtr<PropItem> TypeInState::TakeSetProperty() {
size_t count = mSetArray.Length(); return mSetArray.Length() ? UniquePtr<PropItem>{mSetArray.PopLastElement()}
if (!count) { : nullptr;
return nullptr;
}
count--; // indices are zero based
PropItem* propItem = mSetArray[count];
mSetArray.RemoveElementAt(count);
return UniquePtr<PropItem>(propItem);
} }
/** /**

View File

@ -32,6 +32,8 @@ namespace mozilla {
using namespace dom; using namespace dom;
using ChildBlockBoundary = HTMLEditUtils::ChildBlockBoundary;
const char16_t kNBSP = 160; const char16_t kNBSP = 160;
template WSRunScanner::WSRunScanner(const HTMLEditor* aHTMLEditor, template WSRunScanner::WSRunScanner(const HTMLEditor* aHTMLEditor,
@ -674,7 +676,7 @@ nsIContent* WSRunScanner::GetEditableBlockParentOrTopmotEditableInlineContent(
// it's not collapsed only when inserting composition string so that // it's not collapsed only when inserting composition string so that
// it's possible but shouldn't occur actually. // it's possible but shouldn't occur actually.
nsIContent* editableBlockParentOrTopmotEditableInlineContent = nullptr; nsIContent* editableBlockParentOrTopmotEditableInlineContent = nullptr;
for (nsIContent* content : InclusiveAncestorsOfType<nsIContent>(*aContent)) { for (nsIContent* content : aContent->InclusiveAncestorsOfType<nsIContent>()) {
if (!EditorUtils::IsEditableContent(*content, EditorType::HTML)) { if (!EditorUtils::IsEditableContent(*content, EditorType::HTML)) {
break; break;
} }
@ -743,16 +745,19 @@ nsresult WSRunScanner::GetWSNodes() {
while (!mStartNode) { while (!mStartNode) {
// we haven't found the start of ws yet. Keep looking // we haven't found the start of ws yet. Keep looking
nsCOMPtr<nsIContent> priorNode = GetPreviousWSNode( nsIContent* previousLeafContentOrBlock =
start, editableBlockParentOrTopmotEditableInlineContent); HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
if (priorNode) { start, *editableBlockParentOrTopmotEditableInlineContent,
if (HTMLEditUtils::IsBlockElement(*priorNode)) { mEditingHost);
if (previousLeafContentOrBlock) {
if (HTMLEditUtils::IsBlockElement(*previousLeafContentOrBlock)) {
mStartNode = start.GetContainer(); mStartNode = start.GetContainer();
mStartOffset = start.Offset(); mStartOffset = start.Offset();
mStartReason = WSType::OtherBlockBoundary; mStartReason = WSType::OtherBlockBoundary;
mStartReasonContent = priorNode; mStartReasonContent = previousLeafContentOrBlock;
} else if (priorNode->IsText() && priorNode->IsEditable()) { } else if (previousLeafContentOrBlock->IsText() &&
RefPtr<Text> textNode = priorNode->AsText(); previousLeafContentOrBlock->IsEditable()) {
RefPtr<Text> textNode = previousLeafContentOrBlock->AsText();
mNodeArray.InsertElementAt(0, textNode); mNodeArray.InsertElementAt(0, textNode);
const nsTextFragment* textFrag = &textNode->TextFragment(); const nsTextFragment* textFrag = &textNode->TextFragment();
uint32_t len = textNode->TextLength(); uint32_t len = textNode->TextLength();
@ -760,7 +765,7 @@ nsresult WSRunScanner::GetWSNodes() {
if (len < 1) { if (len < 1) {
// Zero length text node. Set start point to it // Zero length text node. Set start point to it
// so we can get past it! // so we can get past it!
start.Set(priorNode, 0); start.Set(previousLeafContentOrBlock, 0);
} else { } else {
for (int32_t pos = len - 1; pos >= 0; pos--) { for (int32_t pos = len - 1; pos >= 0; pos--) {
// sanity bounds check the char position. bug 136165 // sanity bounds check the char position. bug 136165
@ -794,12 +799,12 @@ nsresult WSRunScanner::GetWSNodes() {
// not a break but still serves as a terminator to ws runs. // not a break but still serves as a terminator to ws runs.
mStartNode = start.GetContainer(); mStartNode = start.GetContainer();
mStartOffset = start.Offset(); mStartOffset = start.Offset();
if (priorNode->IsHTMLElement(nsGkAtoms::br)) { if (previousLeafContentOrBlock->IsHTMLElement(nsGkAtoms::br)) {
mStartReason = WSType::BRElement; mStartReason = WSType::BRElement;
} else { } else {
mStartReason = WSType::SpecialContent; mStartReason = WSType::SpecialContent;
} }
mStartReasonContent = priorNode; mStartReasonContent = previousLeafContentOrBlock;
} }
} else { } else {
// no prior node means we exhausted // no prior node means we exhausted
@ -849,17 +854,20 @@ nsresult WSRunScanner::GetWSNodes() {
while (!mEndNode) { while (!mEndNode) {
// we haven't found the end of ws yet. Keep looking // we haven't found the end of ws yet. Keep looking
nsCOMPtr<nsIContent> nextNode = nsIContent* nextLeafContentOrBlock =
GetNextWSNode(end, editableBlockParentOrTopmotEditableInlineContent); HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
if (nextNode) { end, *editableBlockParentOrTopmotEditableInlineContent,
if (HTMLEditUtils::IsBlockElement(*nextNode)) { mEditingHost);
if (nextLeafContentOrBlock) {
if (HTMLEditUtils::IsBlockElement(*nextLeafContentOrBlock)) {
// we encountered a new block. therefore no more ws. // we encountered a new block. therefore no more ws.
mEndNode = end.GetContainer(); mEndNode = end.GetContainer();
mEndOffset = end.Offset(); mEndOffset = end.Offset();
mEndReason = WSType::OtherBlockBoundary; mEndReason = WSType::OtherBlockBoundary;
mEndReasonContent = nextNode; mEndReasonContent = nextLeafContentOrBlock;
} else if (nextNode->IsText() && nextNode->IsEditable()) { } else if (nextLeafContentOrBlock->IsText() &&
RefPtr<Text> textNode = nextNode->AsText(); nextLeafContentOrBlock->IsEditable()) {
RefPtr<Text> textNode = nextLeafContentOrBlock->AsText();
mNodeArray.AppendElement(textNode); mNodeArray.AppendElement(textNode);
const nsTextFragment* textFrag = &textNode->TextFragment(); const nsTextFragment* textFrag = &textNode->TextFragment();
uint32_t len = textNode->TextLength(); uint32_t len = textNode->TextLength();
@ -902,12 +910,12 @@ nsresult WSRunScanner::GetWSNodes() {
// serves as a terminator to ws runs. // serves as a terminator to ws runs.
mEndNode = end.GetContainer(); mEndNode = end.GetContainer();
mEndOffset = end.Offset(); mEndOffset = end.Offset();
if (nextNode->IsHTMLElement(nsGkAtoms::br)) { if (nextLeafContentOrBlock->IsHTMLElement(nsGkAtoms::br)) {
mEndReason = WSType::BRElement; mEndReason = WSType::BRElement;
} else { } else {
mEndReason = WSType::SpecialContent; mEndReason = WSType::SpecialContent;
} }
mEndReasonContent = nextNode; mEndReasonContent = nextLeafContentOrBlock;
} }
} else { } else {
// no next node means we exhausted // no next node means we exhausted
@ -931,7 +939,9 @@ void WSRunScanner::GetRuns() {
// the scan range isn't in preformatted element, we need to check only the // the scan range isn't in preformatted element, we need to check only the
// style at mScanStartPoint since the range would be replaced and the start // style at mScanStartPoint since the range would be replaced and the start
// style will be applied to all new string. // style will be applied to all new string.
mPRE = EditorBase::IsPreformatted(mScanStartPoint.GetContainer()); mPRE =
mScanStartPoint.IsInContentNode() &&
EditorUtils::IsContentPreformatted(*mScanStartPoint.ContainerAsContent());
// if it's preformatedd, or if we are surrounded by text or special, it's all // if it's preformatedd, or if we are surrounded by text or special, it's all
// one big normal ws run // one big normal ws run
if (mPRE || if (mPRE ||
@ -1085,212 +1095,6 @@ void WSRunScanner::InitializeWithSingleFragment(
mEndRun = mStartRun; mEndRun = mStartRun;
} }
nsIContent* WSRunScanner::GetPreviousWSNodeInner(nsINode* aStartNode,
nsINode* aBlockParent) const {
// Can't really recycle various getnext/prior routines because we have
// special needs here. Need to step into inline containers but not block
// containers.
MOZ_ASSERT(aStartNode && aBlockParent);
if (aStartNode == mEditingHost) {
NS_WARNING(
"WSRunScanner::GetPreviousWSNodeInner() was called with editing host");
return nullptr;
}
nsCOMPtr<nsIContent> previousContent = aStartNode->GetPreviousSibling();
OwningNonNull<nsINode> curNode = *aStartNode;
while (!previousContent) {
// We have exhausted nodes in parent of aStartNode.
nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
if (!curParent) {
NS_WARNING("Reached orphan node while climbing up the DOM tree");
return nullptr;
}
if (curParent == aBlockParent) {
// We have exhausted nodes in the block parent. The convention here is
// to return null.
return nullptr;
}
if (curParent == mEditingHost) {
NS_WARNING("Reached editing host while climbing up the DOM tree");
return nullptr;
}
// We have a parent: look for previous sibling
previousContent = curParent->GetPreviousSibling();
curNode = curParent;
}
if (!previousContent) {
return nullptr;
}
// We have a prior node. If it's a block, return it.
if (HTMLEditUtils::IsBlockElement(*previousContent)) {
return previousContent;
}
if (HTMLEditUtils::IsContainerNode(*previousContent)) {
// Else if it's a container, get deep rightmost child
nsCOMPtr<nsIContent> child =
mHTMLEditor->GetRightmostChild(previousContent);
if (child) {
return child;
}
}
// Else return the node itself
return previousContent;
}
nsIContent* WSRunScanner::GetPreviousWSNode(const EditorDOMPoint& aPoint,
nsINode* aBlockParent) const {
// Can't really recycle various getnext/prior routines because we
// have special needs here. Need to step into inline containers but
// not block containers.
MOZ_ASSERT(aPoint.IsSet() && aBlockParent);
if (aPoint.IsInTextNode()) {
return GetPreviousWSNodeInner(aPoint.GetContainer(), aBlockParent);
}
if (!aPoint.IsInContentNode() ||
!HTMLEditUtils::IsContainerNode(*aPoint.ContainerAsContent())) {
return GetPreviousWSNodeInner(aPoint.GetContainer(), aBlockParent);
}
if (!aPoint.Offset()) {
if (aPoint.GetContainer() == aBlockParent) {
// We are at start of the block.
return nullptr;
}
// We are at start of non-block container
return GetPreviousWSNodeInner(aPoint.GetContainer(), aBlockParent);
}
if (NS_WARN_IF(!aPoint.IsInContentNode())) {
return nullptr;
}
nsCOMPtr<nsIContent> previousContent = aPoint.GetPreviousSiblingOfChild();
if (NS_WARN_IF(!previousContent)) {
return nullptr;
}
// We have a prior node. If it's a block, return it.
if (HTMLEditUtils::IsBlockElement(*previousContent)) {
return previousContent;
}
if (HTMLEditUtils::IsContainerNode(*previousContent)) {
// Else if it's a container, get deep rightmost child
nsCOMPtr<nsIContent> child =
mHTMLEditor->GetRightmostChild(previousContent);
if (child) {
return child;
}
}
// Else return the node itself
return previousContent;
}
nsIContent* WSRunScanner::GetNextWSNodeInner(nsINode* aStartNode,
nsINode* aBlockParent) const {
// Can't really recycle various getnext/prior routines because we have
// special needs here. Need to step into inline containers but not block
// containers.
MOZ_ASSERT(aStartNode && aBlockParent);
if (aStartNode == mEditingHost) {
NS_WARNING(
"WSRunScanner::GetNextWSNodeInner() was called with editing host");
return nullptr;
}
nsCOMPtr<nsIContent> nextContent = aStartNode->GetNextSibling();
nsCOMPtr<nsINode> curNode = aStartNode;
while (!nextContent) {
// We have exhausted nodes in parent of aStartNode.
nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
if (!curParent) {
NS_WARNING("Reached orphan node while climbing up the DOM tree");
return nullptr;
}
if (curParent == aBlockParent) {
// We have exhausted nodes in the block parent. The convention here is
// to return null.
return nullptr;
}
if (curParent == mEditingHost) {
NS_WARNING("Reached editing host while climbing up the DOM tree");
return nullptr;
}
// We have a parent: look for next sibling
nextContent = curParent->GetNextSibling();
curNode = curParent;
}
if (!nextContent) {
return nullptr;
}
// We have a next node. If it's a block, return it.
if (HTMLEditUtils::IsBlockElement(*nextContent)) {
return nextContent;
}
if (HTMLEditUtils::IsContainerNode(*nextContent)) {
// Else if it's a container, get deep leftmost child
nsCOMPtr<nsIContent> child = mHTMLEditor->GetLeftmostChild(nextContent);
if (child) {
return child;
}
}
// Else return the node itself
return nextContent;
}
nsIContent* WSRunScanner::GetNextWSNode(const EditorDOMPoint& aPoint,
nsINode* aBlockParent) const {
// Can't really recycle various getnext/prior routines because we have
// special needs here. Need to step into inline containers but not block
// containers.
MOZ_ASSERT(aPoint.IsSet() && aBlockParent);
if (aPoint.IsInTextNode()) {
return GetNextWSNodeInner(aPoint.GetContainer(), aBlockParent);
}
if (!aPoint.IsInContentNode() ||
!HTMLEditUtils::IsContainerNode(*aPoint.ContainerAsContent())) {
return GetNextWSNodeInner(aPoint.GetContainer(), aBlockParent);
}
if (NS_WARN_IF(!aPoint.IsInContentNode())) {
return nullptr;
}
nsCOMPtr<nsIContent> nextContent = aPoint.GetChild();
if (!nextContent) {
if (aPoint.GetContainer() == aBlockParent) {
// We are at end of the block.
return nullptr;
}
// We are at end of non-block container
return GetNextWSNodeInner(aPoint.GetContainer(), aBlockParent);
}
// We have a next node. If it's a block, return it.
if (HTMLEditUtils::IsBlockElement(*nextContent)) {
return nextContent;
}
if (HTMLEditUtils::IsContainerNode(*nextContent)) {
// else if it's a container, get deep leftmost child
nsCOMPtr<nsIContent> child = mHTMLEditor->GetLeftmostChild(nextContent);
if (child) {
return child;
}
}
// Else return the node itself
return nextContent;
}
nsresult WSRunObject::PrepareToDeleteRangePriv(WSRunObject* aEndObject) { nsresult WSRunObject::PrepareToDeleteRangePriv(WSRunObject* aEndObject) {
// this routine adjust whitespace before *this* and after aEndObject // this routine adjust whitespace before *this* and after aEndObject
// in preperation for the two areas to become adjacent after the // in preperation for the two areas to become adjacent after the

View File

@ -574,15 +574,6 @@ class MOZ_STACK_CLASS WSRunScanner {
nsIContent* GetEditableBlockParentOrTopmotEditableInlineContent( nsIContent* GetEditableBlockParentOrTopmotEditableInlineContent(
nsIContent* aContent) const; nsIContent* aContent) const;
nsIContent* GetPreviousWSNodeInner(nsINode* aStartNode,
nsINode* aBlockParent) const;
nsIContent* GetPreviousWSNode(const EditorDOMPoint& aPoint,
nsINode* aBlockParent) const;
nsIContent* GetNextWSNodeInner(nsINode* aStartNode,
nsINode* aBlockParent) const;
nsIContent* GetNextWSNode(const EditorDOMPoint& aPoint,
nsINode* aBlockParent) const;
/** /**
* GetPreviousCharPoint() and GetPreviousCharPointFromPointInText() return * GetPreviousCharPoint() and GetPreviousCharPointFromPointInText() return
* previous character's point of of aPoint. If there is no character before * previous character's point of of aPoint. If there is no character before

View File

@ -13,29 +13,23 @@ SimpleTest.waitForFocus(async () => {
let input = document.getElementsByTagName("input")[0]; let input = document.getElementsByTagName("input")[0];
let editor = SpecialPowers.wrap(input).editor; let editor = SpecialPowers.wrap(input).editor;
const kMask = editor.passwordMask; const kMask = editor.passwordMask;
function copyToClipboard(aExpectedValue) { async function copyToClipboard(aExpectedValue) {
return new Promise(async resolve => { try {
try { await SimpleTest.promiseClipboardChange(
await SimpleTest.promiseClipboardChange( aExpectedValue, () => { SpecialPowers.doCommand(window, "cmd_copy"); },
aExpectedValue, () => { SpecialPowers.doCommand(window, "cmd_copy"); }, undefined, undefined, aExpectedValue === null);
undefined, undefined, aExpectedValue === null); } catch (e) {
} catch (e) { console.error(e);
console.error(e); }
}
resolve();
});
} }
function cutToClipboard(aExpectedValue) { async function cutToClipboard(aExpectedValue) {
return new Promise(async resolve => { try {
try { await SimpleTest.promiseClipboardChange(
await SimpleTest.promiseClipboardChange( aExpectedValue, () => { SpecialPowers.doCommand(window, "cmd_cut"); },
aExpectedValue, () => { SpecialPowers.doCommand(window, "cmd_cut"); }, undefined, undefined, aExpectedValue === null);
undefined, undefined, aExpectedValue === null); } catch (e) {
} catch (e) { console.error(e);
console.error(e); }
}
resolve();
});
} }
input.value = "abcdef"; input.value = "abcdef";
input.focus(); input.focus();

View File

@ -779,6 +779,27 @@ SimpleTest.waitForFocus(async function() {
null, null,
"#9-1 nsIHTMLEditor::getSelectedElement(\"anchor\") should return null when Selection starts from a text node in <b> element and ends before the following <br> element"); "#9-1 nsIHTMLEditor::getSelectedElement(\"anchor\") should return null when Selection starts from a text node in <b> element and ends before the following <br> element");
editor.innerHTML = "<p><b>b1</b><b><br></b><b>b2</b></p>";
editor.focus();
// <p><b>[b1</b><b>}<br></b><b>b2</b></p>
// This is usual case of double-clicking in the first <b> element.
range = document.createRange();
range.setStart(editor.firstChild.firstChild.firstChild, 0);
range.setEnd(editor.firstChild.firstChild.nextSibling, 0);
selection.removeAllRanges();
selection.addRange(range);
is(SpecialPowers.unwrap(getHTMLEditor().getSelectedElement("")),
null,
"#10-1 nsIHTMLEditor::getSelectedElement(\"\") should return null when Selection starts from a text node in <b> element and ends before the following <br> element in another <b> element");
is(SpecialPowers.unwrap(getHTMLEditor().getSelectedElement("href")),
null,
"#10-1 nsIHTMLEditor::getSelectedElement(\"href\") should return null when Selection starts from a text node in <b> element and ends before the following <br> element in another <b> element");
is(SpecialPowers.unwrap(getHTMLEditor().getSelectedElement("anchor")),
null,
"#10-1 nsIHTMLEditor::getSelectedElement(\"anchor\") should return null when Selection starts from a text node in <b> element and ends before the following <br> element in another <b> element");
SimpleTest.finish(); SimpleTest.finish();
}); });

View File

@ -12,8 +12,10 @@ Classes = [
'categories': {'content-policy': '@mozilla.org/permissions/contentblocker;1'}, 'categories': {'content-policy': '@mozilla.org/permissions/contentblocker;1'},
}, },
{ {
'js_name': 'perms',
'cid': '{4f6b5e00-0c36-11d5-a535-0010a401eb10}', 'cid': '{4f6b5e00-0c36-11d5-a535-0010a401eb10}',
'contract_ids': ['@mozilla.org/permissionmanager;1'], 'contract_ids': ['@mozilla.org/permissionmanager;1'],
'interfaces': ['nsIPermissionManager'],
'singleton': True, 'singleton': True,
'type': 'nsIPermissionManager', 'type': 'nsIPermissionManager',
'constructor': 'nsPermissionManager::GetXPCOMSingleton', 'constructor': 'nsPermissionManager::GetXPCOMSingleton',

View File

@ -8,7 +8,6 @@
#include "mozilla/BasePrincipal.h" #include "mozilla/BasePrincipal.h"
#include "mozilla/ContentPrincipal.h" #include "mozilla/ContentPrincipal.h"
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "mozilla/Pair.h"
#include "mozilla/Services.h" #include "mozilla/Services.h"
#include "mozilla/SystemGroup.h" #include "mozilla/SystemGroup.h"
#include "nsPermissionManager.h" #include "nsPermissionManager.h"
@ -2130,7 +2129,7 @@ nsPermissionManager::RemoveAllSince(int64_t aSince) {
template <class T> template <class T>
nsresult nsPermissionManager::RemovePermissionEntries(T aCondition) { nsresult nsPermissionManager::RemovePermissionEntries(T aCondition) {
Vector<Pair<nsCOMPtr<nsIPrincipal>, nsCString>, 10> array; Vector<std::pair<nsCOMPtr<nsIPrincipal>, nsCString>, 10> array;
for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) { for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
PermissionHashKey* entry = iter.Get(); PermissionHashKey* entry = iter.Get();
for (const auto& permEntry : entry->GetPermissions()) { for (const auto& permEntry : entry->GetPermissions()) {
@ -2153,7 +2152,7 @@ nsresult nsPermissionManager::RemovePermissionEntries(T aCondition) {
for (auto& i : array) { for (auto& i : array) {
// AddInternal handles removal, so let it do the work... // AddInternal handles removal, so let it do the work...
AddInternal(i.first(), i.second(), nsIPermissionManager::UNKNOWN_ACTION, 0, AddInternal(i.first, i.second, nsIPermissionManager::UNKNOWN_ACTION, 0,
nsIPermissionManager::EXPIRE_NEVER, 0, 0, nsIPermissionManager::EXPIRE_NEVER, 0, 0,
nsPermissionManager::eNotify, nsPermissionManager::eWriteToDB); nsPermissionManager::eNotify, nsPermissionManager::eWriteToDB);
} }
@ -2679,7 +2678,7 @@ nsresult nsPermissionManager::RemovePermissionsWithAttributes(
nsresult nsPermissionManager::RemovePermissionsWithAttributes( nsresult nsPermissionManager::RemovePermissionsWithAttributes(
mozilla::OriginAttributesPattern& aPattern) { mozilla::OriginAttributesPattern& aPattern) {
Vector<Pair<nsCOMPtr<nsIPrincipal>, nsCString>, 10> permissions; Vector<std::pair<nsCOMPtr<nsIPrincipal>, nsCString>, 10> permissions;
for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) { for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
PermissionHashKey* entry = iter.Get(); PermissionHashKey* entry = iter.Get();
@ -2702,7 +2701,7 @@ nsresult nsPermissionManager::RemovePermissionsWithAttributes(
} }
for (auto& i : permissions) { for (auto& i : permissions) {
AddInternal(i.first(), i.second(), nsIPermissionManager::UNKNOWN_ACTION, 0, AddInternal(i.first, i.second, nsIPermissionManager::UNKNOWN_ACTION, 0,
nsIPermissionManager::EXPIRE_NEVER, 0, 0, nsIPermissionManager::EXPIRE_NEVER, 0, 0,
nsPermissionManager::eNotify, nsPermissionManager::eWriteToDB); nsPermissionManager::eNotify, nsPermissionManager::eWriteToDB);
} }

View File

@ -7,6 +7,7 @@
#include <cmath> #include <cmath>
#include <ostream> #include <ostream>
#include <type_traits>
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/FloatingPoint.h" #include "mozilla/FloatingPoint.h"
#include "mozilla/TypeTraits.h" #include "mozilla/TypeTraits.h"
@ -93,8 +94,8 @@ struct BasePoint {
// "Finite" means not inf and not NaN // "Finite" means not inf and not NaN
bool IsFinite() const { bool IsFinite() const {
typedef typename mozilla::Conditional<mozilla::IsSame<T, float>::value, using FloatType =
float, double>::Type FloatType; std::conditional_t<mozilla::IsSame<T, float>::value, float, double>;
return (mozilla::IsFinite(FloatType(x)) && mozilla::IsFinite(FloatType(y))); return (mozilla::IsFinite(FloatType(x)) && mozilla::IsFinite(FloatType(y)));
return true; return true;
} }

View File

@ -8,6 +8,7 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <ostream> #include <ostream>
#include <type_traits>
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/FloatingPoint.h" #include "mozilla/FloatingPoint.h"
@ -62,8 +63,8 @@ struct BaseRect {
// "Finite" means not inf and not NaN // "Finite" means not inf and not NaN
bool IsFinite() const { bool IsFinite() const {
typedef typename mozilla::Conditional<mozilla::IsSame<T, float>::value, using FloatType =
float, double>::Type FloatType; std::conditional_t<mozilla::IsSame<T, float>::value, float, double>;
return (mozilla::IsFinite(FloatType(x)) && return (mozilla::IsFinite(FloatType(x)) &&
mozilla::IsFinite(FloatType(y)) && mozilla::IsFinite(FloatType(y)) &&
mozilla::IsFinite(FloatType(width)) && mozilla::IsFinite(FloatType(width)) &&

View File

@ -9,6 +9,8 @@
#ifndef MOZILLA_GENERICREFCOUNTED_H_ #ifndef MOZILLA_GENERICREFCOUNTED_H_
#define MOZILLA_GENERICREFCOUNTED_H_ #define MOZILLA_GENERICREFCOUNTED_H_
#include <type_traits>
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/RefCounted.h" #include "mozilla/RefCounted.h"
@ -99,8 +101,9 @@ class GenericRefCounted : public GenericRefCountedBase {
} }
private: private:
typename Conditional<Atomicity == AtomicRefCount, Atomic<MozRefCountType>, std::conditional_t<Atomicity == AtomicRefCount, Atomic<MozRefCountType>,
MozRefCountType>::Type refCnt; MozRefCountType>
refCnt;
}; };
} // namespace detail } // namespace detail

View File

@ -181,6 +181,9 @@ class GPUProcessManager final : public GPUProcessHost::Listener {
// Returns whether or not a GPU process was ever launched. // Returns whether or not a GPU process was ever launched.
bool AttemptedGPUProcess() const { return mNumProcessAttempts > 0; } bool AttemptedGPUProcess() const { return mNumProcessAttempts > 0; }
// Returns the process host
GPUProcessHost* Process() { return mProcess; }
private: private:
// Called from our xpcom-shutdown observer. // Called from our xpcom-shutdown observer.
void OnXPCOMShutdown(); void OnXPCOMShutdown();

View File

@ -131,7 +131,7 @@ void AnimationInfo::TransferMutatedFlagToLayer(Layer* aLayer) {
bool AnimationInfo::ApplyPendingUpdatesForThisTransaction() { bool AnimationInfo::ApplyPendingUpdatesForThisTransaction() {
if (mPendingAnimations) { if (mPendingAnimations) {
mPendingAnimations->SwapElements(mAnimations); mAnimations = std::move(*mPendingAnimations);
mPendingAnimations = nullptr; mPendingAnimations = nullptr;
return true; return true;
} }

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