Merge mozilla-central to autoland

This commit is contained in:
arthur.iakab 2018-02-27 12:02:38 +02:00
Родитель ac779f9004 9bffb6aa72
Коммит 8f11c1f438
76 изменённых файлов: 1502 добавлений и 918 удалений

Просмотреть файл

@ -0,0 +1,3 @@
. "$topsrcdir/browser/config/mozconfigs/linux64/nightly"
ac_add_options --enable-stylo=only

Просмотреть файл

@ -0,0 +1,3 @@
. "$topsrcdir/browser/config/mozconfigs/linux64/debug"
ac_add_options --enable-stylo=only

Просмотреть файл

@ -1,20 +0,0 @@
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
ifdef MOZTTDIR
# Install the Firefox OS fonts.
include $(MOZTTDIR)/fonts.mk
MOZTT_DEST = $(FINAL_TARGET)/fonts
MOZTT_FILES = $(patsubst external/moztt/%,$(MOZTTDIR)/%,$(filter external/moztt/%,$(subst :, ,$(PRODUCT_COPY_FILES))))
INSTALL_TARGETS += MOZTT
endif
include $(topsrcdir)/config/rules.mk
TARGET_DEPTH = ..
include $(srcdir)/automation-build.mk
libs:: automation.py

Просмотреть файл

@ -1,98 +0,0 @@
# -*- makefile -*-
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
STANDALONE_MAKEFILE := 1
USE_AUTOTARGETS_MK = 1
MAKEUTILS_UNIT_TEST = 1
include $(topsrcdir)/config/makefiles/makeutils.mk
dir-ts = .deps/test
check-arglist = $(dir-ts)/arglist.ts
check-autotargets = $(dir-ts)/autotargets_mk.ts
check-XinY = $(dir-ts)/check_XinY_mk.ts
check-tests =\
$(check-arglist) \
$(check-autotargets) \
$(check-XinY) \
$(NULL)
##------------------_##
##---] TARGETS [---##
##------------------_##
all::
clean:
$(RM) $(check-tests)
###########################################################################
## Logic processed at compile time so be selective about when to test
## $(MAKE) check VERBOSE=1
ifneq ($(NULL),$(findstring check,$(MAKECMDGOALS))) #
check-preqs =\
$(call mkdir_deps,$(dir-ts)) \
$(check-tests) \
$(NULL)
check:: $(check-preqs)
@true
ifdef VERBOSE #{ gmake check VERBOSE=1
$(info ===========================================================================)
$(info Running test: $(MAKECMDGOALS): pwd=$(CURDIR))
$(info ===========================================================================)
endif #}
ifndef requiredfunction
$(error requiredfunction is not defined)
endif
##################
check-XinY-preqs=\
$(call mkdir_deps,$(dir-ts)) \
$(topsrcdir)/config/makefiles/makeutils.mk \
$(srcdir)/check_XinY.mk \
$(eval include $(srcdir)/check_XinY.mk) \
$(NULL)
$(check-XinY): $(check-XinY-preqs)
@$(TOUCH) $@
# </check-XinY.mk>
###########################################################################
## check-arglist.mk always invoked as a compile time test
## maintain real file dependencies for use later on.
check-arglist-preqs=\
$(call mkdir_deps,$(dir-ts)) \
$(topsrcdir)/config/makefiles/makeutils.mk \
$(srcdir)/check-arglist.mk \
$(eval include $(srcdir)/check-arglist.mk) \
$(NULL)
$(check-arglist): $(check-arglist-preqs)
@$(TOUCH) $@
# </check-arglist.mk>
###########################################################################
# <CHECK: autotargets.mk>
check-autotargets-preqs=\
$(call mkdir_deps,$(dir-ts)) \
$(topsrcdir)/config/makefiles/makeutils.mk \
$(topsrcdir)/config/makefiles/autotargets.mk \
$(srcdir)/check-autotargets.mk \
$(eval include $(srcdir)/check-autotargets.mk) \
$(NULL)
$(check-autotargets): $(check-autotargets-preqs)
@$(TOUCH) $@
# </CHECK: autotargets.mk>
endif #} findstring MAKECMDGOAL

Просмотреть файл

@ -1,100 +0,0 @@
# -*- makefile -*-
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
ifdef VERBOSE
$(warning loading test)
endif
$(call requiredfunction,getargv)
$(call requiredfunction,subargv)
$(call requiredfunction,istype isval isvar)
# arg_scalar = [scalar|literal]
arg_list = foo bar
arg_ref = arg_list
## Identify type of function argument(s)
########################################
ifneq (scalar,$(call istype,arg_scalar))
$(error istype(arg_scalar)=scalar, found [$(call istype,arg_scalar)])
endif
ifneq (list,$(call istype,arg_list))
$(error istype(arg_list)=list, found [$(call istype,arg_list)])
endif
ifneq (list,$(call istype,arg_ref))
$(error istype(arg_ref)=list, found [$(call istype,arg_ref)])
endif
## Type == scalar or a list of values
#####################################
ifneq (true,$(call isval,scalar))
$(error isval(scalar)=true, found [$(call isval,scalar)])
endif
ifneq ($(NULL),$(call isval,arg_list))
$(error isval(arg_list)=null, found [$(call isval,arg_list)])
endif
## type == reference: macro=>macro => $($(1))
#############################################
ifneq ($(NULL),$(call isvar,scalar))
$(error isvar(scalar)=$(NULL), found [$(call isvar,scalar)])
endif
ifneq (true,$(call isvar,arg_list))
$(error isvar(arg_list)=true, found [$(call isvar,arg_list)])
endif
ifneq (true,$(call isvar,arg_ref))
$(error isvar(arg_ref)=true, found [$(call isvar,arg_ref)])
endif
# Verify getargv expansion
##########################
ifneq (scalar,$(call getargv,scalar))
$(error getargv(scalar)=scalar, found [$(call getargv,scalar)])
endif
ifneq ($(arg_list),$(call getargv,arg_list))
$(error getargv(arg_list)=list, found [$(call getargv,arg_list)])
endif
ifneq (arg_list,$(call getargv,arg_ref))
$(error getargv(arg_ref)=list, found [$(call getargv,arg_ref)])
endif
###########################################################################
##
###########################################################################
ifdef MANUAL_TEST #{
# For automated testing a callback is needed that can set an external status
# variable that can be tested. Syntax is tricky to get correct functionality.
ifdef VERBOSE
$(info )
$(info ===========================================================================)
$(info Running test: checkIfEmpty)
$(info ===========================================================================)
endif
#status =
#setTRUE =status=true
#setFALSE =status=$(NULL)
#$(call checkIfEmpty,setFALSE NULL)
#$(if $(status),$(error checkIfEmpty(xyz) failed))
#$(call checkIfEmpty,setTRUE xyz)
#$(if $(status),$(error checkIfEmpty(xyz) failed))
xyz=abc
$(info STATUS: warnIfEmpty - two vars)
$(call warnIfEmpty,foo xyz bar)
$(info STATUS: errorIfEmpty - on first var)
$(call errorIfEmpty,foo xyz bar)
$(error TEST FAILED: processing should not reach this point)
endif #}
# Verify subargv expansion
##########################
subargs=foo bar tans fans
subargs_exp=tans fans
subargs_found=$(call subargv,4,$(subargs))
ifneq ($(subargs_exp),$(subargs_found))
$(error subargv(4,$(subargs)): expected [$(subargs_exp)] found [$(subargs_found)])
endif

Просмотреть файл

@ -1,84 +0,0 @@
# -*- makefile -*-
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
ifdef VERBOSE
$(warning loading test)
endif
space=$(null) $(null)
GENERATED_DIRS = bogus # test data
undefine USE_AUTOTARGETS_MK
undefine INCLUDED_AUTOTARGETS_MK
include $(topsrcdir)/config/makefiles/autotargets.mk
ifndef INCLUDED_AUTOTARGETS_MK
$(error autotargets.mk was not included
endif
$(call requiredfunction,mkdir_deps)
# Verify test data populated makefile vars correctly
vars = AUTO_DEPS GARBAGE_DIRS GENERATED_DIRS_DEPS
$(foreach var,$(vars),$(call errorIfEmpty,$(var)))
# Data should also be valid
ifneq (bogus,$(findstring bogus,$(AUTO_DEPS)))
$(error AUTO_DEPS=[$(AUTO_DEPS)] is not set correctly)
endif
# relpath
path := foo/bar.c
exp := foo/.mkdir.done
found := $(call mkdir_deps,$(dir $(path)))
ifneq ($(exp),$(found))
$(error mkdir_deps($(path))=$(exp) not set correctly [$(found)])
endif
# abspath
path := /foo//bar/
exp := /foo/bar/.mkdir.done
found := $(call mkdir_deps,$(path))
ifneq ($(exp),$(found))
$(error mkdir_deps($(path))=$(exp) not set correctly [$(found)])
endif
## verify strip_slash
#####################
path := a/b//c///d////e/////
exp := a/b/c/d/e/.mkdir.done
found := $(call mkdir_deps,$(path))
ifneq ($(exp),$(found))
$(error mkdir_deps($(path))=$(exp) not set correctly [$(found)])
endif
## verify mkdir_stem()
######################
path := verify/mkdir_stem
pathD = $(call mkdir_deps,$(path))
pathS = $(call mkdir_stem,$(pathD))
exp := $(path)
ifeq ($(pathD),$(pathS))
$(error mkdir_deps and mkdir_stem should not match [$(pathD)])
endif
ifneq ($(pathS),$(exp))
$(error mkdir_stem=[$(pathS)] != exp=[$(exp)])
endif
## Verify embedded whitespace has been protected
path := a/b$(space)c//d
exp := a/b$(space)c/d
found := $(call slash_strip,$(path))
ifneq ($(exp),$(found))
$(error slash_strip($(path))=$(exp) not set correctly [$(found)])
endif

Просмотреть файл

@ -1,70 +0,0 @@
# -*- makefile -*-
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
# Verify dependencies are available
$(call requiredfunction,getargv subargv is_XinY errorifneq)
ifdef VERBOSE
$(warning loading test)
endif
zero := 0
one := 1
# Verify 'invalid' is not matched
val := invalid
$(call errorifneq,$(zero),$(words $(call is_XinY,foo,$(val))))
$(call errorifneq,$(zero),$(words $(call is_XinY,clean,$(val))))
$(call errorifneq,$(zero),$(words $(call is_XinY,clean%,$(val))))
# verify strcmp('clean')
val := clean
$(call errorifneq,$(zero),$(words $(call is_XinY,foo,$(val))))
$(call errorifneq,$(one),$(words $(call is_XinY,clean,$(val))))
$(call errorifneq,$(one),$(words $(call is_XinY,clean%,$(val))))
$(call errorifneq,$(one),$(words $(call is_XinY,%clean,$(val))))
# List match for 'clean'
val := blah clean distclean FcleanG clean-level-1
wanted := clean distclean clean-level-1
$(call errorifneq,$(zero),$(words $(call is_XinY_debug,foo,$(val))))
$(call errorifneq,$(one),$(words $(call is_XinY,clean,$(val))))
$(call errorifneq,$(one),$(words $(call is_XinY,distclean,$(val))))
# pattern match 'clean'
# match: clean, distclean, clean-level-1
# exclude: FcleanG
TEST_MAKECMDGOALS := $(val)
$(call errorifneq,3,$(words $(call isTargetStemClean)))
TEST_MAKECMDGOALS := invalid
$(call errorifneq,$(zero),$(words $(call isTargetStemClean)))
#############################
ifdef VERBOSE
$(call banner,Unit test: isTargetStem)
endif
# Verify list argument processing
TEST_MAKECMDGOALS := echo
$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
TEST_MAKECMDGOALS := echo-123
$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
TEST_MAKECMDGOALS := show
$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
TEST_MAKECMDGOALS := show-123
$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
TEST_MAKECMDGOALS := show-123-echo
$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
TEST_MAKECMDGOALS := invalid
$(call errorifneq,$(zero),$(words $(call isTargetStem,echo,show)))

Просмотреть файл

@ -1,6 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

Просмотреть файл

@ -16,7 +16,6 @@ DIST_INSTALL = False
NoVisibilityFlags()
CONFIGURE_SUBST_FILES += [
'makefiles/test/Makefile',
'tests/src-simple/Makefile',
]

Просмотреть файл

@ -1,8 +1,8 @@
This is the debugger.html project output.
See https://github.com/devtools-html/debugger.html
Version 18.0
Comparison: https://github.com/devtools-html/debugger.html/compare/release-17...release-18
Version 19.0
Comparison: https://github.com/devtools-html/debugger.html/compare/release-18...release-19
Packages:
- babel-plugin-transform-es2015-modules-commonjs @6.26.0

Просмотреть файл

@ -1928,6 +1928,9 @@ html .toggle-button.end.vertical svg {
.source-footer .mapped-source {
color: var(--theme-body-color);
padding: 2.5px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this

Просмотреть файл

@ -10102,7 +10102,7 @@ const prefs = new PrefsHelper("devtools", {
fileSearchWholeWord: ["Bool", "debugger.file-search-whole-word"],
fileSearchRegexMatch: ["Bool", "debugger.file-search-regex-match"],
debuggerPrefsSchemaVersion: ["Char", "debugger.prefs-schema-version"],
projectDirectoryRoot: ["Char", "project-directory-root", ""]
projectDirectoryRoot: ["Char", "debugger.project-directory-root", ""]
});
/* harmony export (immutable) */ __webpack_exports__["prefs"] = prefs;
@ -17921,7 +17921,7 @@ function createPendingBreakpoint(bp) {
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.replaceOriginalVariableName = exports.getFramework = exports.hasSyntaxError = exports.clearSources = exports.setSource = exports.hasSource = exports.getEmptyLines = exports.getNextStep = exports.clearASTs = exports.clearScopes = exports.clearSymbols = exports.findOutOfScopeLocations = exports.getVariablesInScope = exports.getScopes = exports.getSymbols = exports.getClosestExpression = exports.stopParserWorker = exports.startParserWorker = undefined;
exports.replaceOriginalVariableName = exports.getFramework = exports.hasSyntaxError = exports.clearSources = exports.setSource = exports.hasSource = exports.getEmptyLines = exports.isInvalidPauseLocation = exports.getNextStep = exports.clearASTs = exports.clearScopes = exports.clearSymbols = exports.findOutOfScopeLocations = exports.getVariablesInScope = exports.getScopes = exports.getSymbols = exports.getClosestExpression = exports.stopParserWorker = exports.startParserWorker = undefined;
var _devtoolsUtils = __webpack_require__(1363);
@ -17942,6 +17942,7 @@ const clearSymbols = exports.clearSymbols = dispatcher.task("clearSymbols");
const clearScopes = exports.clearScopes = dispatcher.task("clearScopes");
const clearASTs = exports.clearASTs = dispatcher.task("clearASTs");
const getNextStep = exports.getNextStep = dispatcher.task("getNextStep");
const isInvalidPauseLocation = exports.isInvalidPauseLocation = dispatcher.task("isInvalidPauseLocation");
const getEmptyLines = exports.getEmptyLines = dispatcher.task("getEmptyLines");
const hasSource = exports.hasSource = dispatcher.task("hasSource");
const setSource = exports.setSource = dispatcher.task("setSource");
@ -19160,6 +19161,16 @@ const arrowBtn = (onClick, type, className, tooltip) => {
class SearchInput extends _react.Component {
componentDidMount() {
this.setFocus();
}
componentDidUpdate(prevProps) {
if (this.props.shouldFocus && !prevProps.shouldFocus) {
this.setFocus();
}
}
setFocus() {
if (this.$input) {
const input = this.$input;
input.focus();
@ -19953,15 +19964,15 @@ var _selectors = __webpack_require__(1352);
var _ui = __webpack_require__(1421);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
var _source = __webpack_require__(1356);
function setContextMenu(type, event) {
return ({ dispatch }) => {
dispatch({ type: "SET_CONTEXT_MENU", contextMenu: { type, event } });
};
}
} /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
function setPrimaryPaneTab(tabName) {
return { type: "SET_PRIMARY_PANE_TAB", tabName };
@ -19981,6 +19992,10 @@ function setActiveSearch(activeSearch) {
return;
}
if ((0, _selectors.getQuickOpenEnabled)(getState())) {
dispatch({ type: "CLOSE_QUICK_OPEN" });
}
dispatch({
type: "TOGGLE_ACTIVE_SEARCH",
value: activeSearch
@ -20009,7 +20024,7 @@ function showSource(sourceId) {
dispatch({
type: "SHOW_SOURCE",
sourceUrl: source.get("url")
sourceUrl: (0, _source.getRawSourceURL)(source.get("url"))
});
};
}
@ -20330,6 +20345,7 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < argument
exports.getPauseReason = getPauseReason;
exports.isStepping = isStepping;
exports.isPaused = isPaused;
exports.getPreviousPauseFrameLocation = getPreviousPauseFrameLocation;
exports.isEvaluatingExpression = isEvaluatingExpression;
exports.getPopupObjectProperties = getPopupObjectProperties;
exports.getIsWaitingOnBreak = getIsWaitingOnBreak;
@ -20368,7 +20384,8 @@ const createPauseState = exports.createPauseState = () => ({
shouldIgnoreCaughtExceptions: _prefs.prefs.ignoreCaughtExceptions,
canRewind: false,
debuggeeUrl: "",
command: ""
command: "",
previousLocation: null
});
const emptyPauseState = {
@ -20379,7 +20396,8 @@ const emptyPauseState = {
original: {}
},
selectedFrameId: null,
loadedObjects: {}
loadedObjects: {},
previousLocation: null
};
function update(state = createPauseState(), action) {
@ -20485,7 +20503,12 @@ function update(state = createPauseState(), action) {
});
case "COMMAND":
return action.status === "start" ? _extends({}, state, emptyPauseState, { command: action.command }) : _extends({}, state, { command: "" });
{
return action.status === "start" ? _extends({}, state, emptyPauseState, {
command: action.command,
previousLocation: buildPreviousLocation(state, action)
}) : _extends({}, state, { command: "" });
}
case "RESUME":
// We clear why on resume because we need it to decide if
@ -20504,6 +20527,24 @@ function update(state = createPauseState(), action) {
return state;
}
function buildPreviousLocation(state, action) {
const { frames, previousLocation } = state;
if (action.command !== "stepOver") {
return null;
}
const frame = frames && frames.length > 0 ? frames[0] : null;
if (!frame) {
return previousLocation;
}
return {
location: frame.location,
generatedLocation: frame.generatedLocation
};
}
// Selectors
// Unfortunately, it's really hard to make these functions accept just
@ -20531,6 +20572,10 @@ function isPaused(state) {
return !!getFrames(state);
}
function getPreviousPauseFrameLocation(state) {
return state.pause.previousLocation;
}
function isEvaluatingExpression(state) {
return state.pause.command === "expression";
}
@ -21329,74 +21374,7 @@ function setOutOfScopeLocations() {
}
/***/ }),
/* 1400 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getPauseReason = getPauseReason;
exports.isException = isException;
exports.isInterrupted = isInterrupted;
exports.inDebuggerEval = inDebuggerEval;
// Map protocol pause "why" reason to a valid L10N key
// These are the known unhandled reasons:
// "breakpointConditionThrown", "clientEvaluated"
// "interrupted", "attached"
const reasons = {
debuggerStatement: "whyPaused.debuggerStatement",
breakpoint: "whyPaused.breakpoint",
exception: "whyPaused.exception",
resumeLimit: "whyPaused.resumeLimit",
pauseOnDOMEvents: "whyPaused.pauseOnDOMEvents",
breakpointConditionThrown: "whyPaused.breakpointConditionThrown",
// V8
DOM: "whyPaused.breakpoint",
EventListener: "whyPaused.pauseOnDOMEvents",
XHR: "whyPaused.xhr",
promiseRejection: "whyPaused.promiseRejection",
assert: "whyPaused.assert",
debugCommand: "whyPaused.debugCommand",
other: "whyPaused.other"
}; /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
function getPauseReason(why) {
if (!why) {
return null;
}
const reasonType = why.type;
if (!reasons[reasonType]) {
console.log("Please file an issue: reasonType=", reasonType);
}
return reasons[reasonType];
}
function isException(why) {
return why && why.type && why.type === "exception";
}
function isInterrupted(why) {
return why && why.type && why.type === "interrupted";
}
function inDebuggerEval(why) {
if (why && why.type === "exception" && why.exception && why.exception.preview && why.exception.preview.fileName) {
return why.exception.preview.fileName === "debugger eval code";
}
return false;
}
/***/ }),
/* 1400 */,
/* 1401 */
/***/ (function(module, exports, __webpack_require__) {
@ -35210,30 +35188,33 @@ class SearchBar extends _react.Component {
};
this.closeSearch = e => {
const { editor, searchOn } = this.props;
const { closeFileSearch, editor, searchOn } = this.props;
if (editor && searchOn) {
this.clearSearch();
this.props.closeFileSearch(editor);
closeFileSearch(editor);
e.stopPropagation();
e.preventDefault();
}
this.setState({ query: "", inputFocused: false });
};
this.toggleSearch = e => {
e.stopPropagation();
e.preventDefault();
const { editor } = this.props;
const { editor, searchOn, setActiveSearch } = this.props;
if (!this.props.searchOn) {
this.props.setActiveSearch("file");
if (!searchOn) {
setActiveSearch("file");
}
if (this.props.searchOn && editor) {
const selection = editor.codeMirror.getSelection();
this.setState({ query: selection });
if (selection !== "") {
this.doSearch(selection);
if (searchOn && editor) {
const query = editor.codeMirror.getSelection() || this.state.query;
if (query !== "") {
this.setState({ query, inputFocused: true });
this.doSearch(query);
} else {
this.setState({ query: "", inputFocused: true });
}
}
};
@ -35274,6 +35255,10 @@ class SearchBar extends _react.Component {
return this.doSearch(e.target.value);
};
this.onBlur = e => {
this.setState({ inputFocused: false });
};
this.onKeyDown = e => {
if (e.key !== "Enter" && e.key !== "F3") {
return;
@ -35338,7 +35323,8 @@ class SearchBar extends _react.Component {
query: props.query,
selectedResultIndex: 0,
count: 0,
index: -1
index: -1,
inputFocused: false
};
}
@ -35422,11 +35408,13 @@ class SearchBar extends _react.Component {
placeholder: L10N.getStr("sourceSearch.search.placeholder"),
summaryMsg: this.buildSummaryMsg(),
onChange: this.onChange,
onBlur: this.onBlur,
showErrorEmoji: this.shouldShowErrorEmoji(),
onKeyDown: this.onKeyDown,
handleNext: e => this.traverseResults(e, false),
handlePrev: e => this.traverseResults(e, true),
handleClose: this.closeSearch
handleClose: this.closeSearch,
shouldFocus: this.state.inputFocused
}),
_react2.default.createElement(
"div",
@ -39255,7 +39243,7 @@ var _editor = __webpack_require__(1358);
var _source = __webpack_require__(1356);
var _pause = __webpack_require__(1400);
var _pause = __webpack_require__(2419);
var _indentation = __webpack_require__(1438);
@ -39727,7 +39715,7 @@ function getMenuItems(event, {
id: "node-menu-show-source",
label: revealInTreeLabel,
accesskey: revealInTreeKey,
disabled: isPrettyPrinted,
disabled: false,
click: () => showSource(sourceId)
};
@ -40454,7 +40442,7 @@ var _source = __webpack_require__(1356);
var _selectors = __webpack_require__(1352);
var _pause = __webpack_require__(1400);
var _pause = __webpack_require__(2419);
var _breakpoint = __webpack_require__(1364);
@ -41221,7 +41209,7 @@ var _react = __webpack_require__(0);
var _react2 = _interopRequireDefault(_react);
var _pause = __webpack_require__(1400);
var _pause = __webpack_require__(2419);
__webpack_require__(1337);
@ -43363,7 +43351,9 @@ function hasAwait(source, pauseLocation) {
return false;
}
return source.text.split("\n")[line - 1].slice(column, column + 200).match(/(yield|await)/);
const snippet = source.text.split("\n")[line - 1].slice(column - 50, column + 50);
return !!snippet.match(/(yield|await)/);
}
/**
@ -43382,6 +43372,7 @@ function astCommand(stepType) {
// This type definition is ambiguous:
const frame = (0, _selectors.getTopFrame)(getState());
const source = (0, _selectors.getSelectedSource)(getState()).toJS();
if (source && hasAwait(source, frame.location)) {
const nextLocation = await (0, _parser.getNextStep)(source.id, frame.location);
if (nextLocation) {
@ -43593,8 +43584,17 @@ var _sources = __webpack_require__(1797);
var _ui = __webpack_require__(1385);
var _commands = __webpack_require__(1637);
var _pause = __webpack_require__(2419);
var _mapFrames = __webpack_require__(1804);
var _fetchScopes = __webpack_require__(1655);
async function getOriginalSourceForFrame(state, frame) {
return (0, _selectors.getSources)(state).get(frame.location.sourceId);
}
/**
* Debugger has just paused
*
@ -43609,12 +43609,26 @@ var _fetchScopes = __webpack_require__(1655);
function paused(pauseInfo) {
return async function ({ dispatch, getState, client, sourceMaps }) {
const { frames, why, loadedObjects } = pauseInfo;
const rootFrame = frames.length > 0 ? frames[0] : null;
if (rootFrame) {
const mappedFrame = await (0, _mapFrames.updateFrameLocation)(rootFrame, sourceMaps);
const source = await getOriginalSourceForFrame(getState(), mappedFrame);
// Ensure that the original file has loaded if there is one.
await dispatch((0, _sources.loadSourceText)(source));
if (await (0, _pause.shouldStep)(mappedFrame, getState(), sourceMaps)) {
dispatch((0, _commands.command)("stepOver"));
return;
}
}
dispatch({
type: "PAUSED",
why,
frames,
selectedFrameId: frames[0] ? frames[0].id : undefined,
selectedFrameId: rootFrame ? rootFrame.id : undefined,
loadedObjects: loadedObjects || []
});
@ -43657,7 +43671,7 @@ var _selectors = __webpack_require__(1352);
var _expressions = __webpack_require__(1398);
var _pause = __webpack_require__(1400);
var _pause = __webpack_require__(2419);
/**
* Debugger has just resumed
@ -44001,7 +44015,7 @@ class QuickOpenModal extends _react.Component {
return;
}
if (query == "") {
if (query == "" && !this.isShortcutQuery()) {
return this.showTopSources();
}
@ -48484,6 +48498,7 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < argument
* @module actions/sources
*/
exports.loadSourceMap = loadSourceMap;
exports.newSource = newSource;
exports.newSources = newSources;
@ -48510,25 +48525,25 @@ function createOriginalSource(originalUrl, generatedSource, sourceMaps) {
};
}
// TODO: It would be nice to make getOriginalURLs a safer api
async function loadOriginalSourceUrls(sourceMaps, generatedSource) {
try {
return await sourceMaps.getOriginalURLs(generatedSource);
} catch (e) {
console.error(e);
return null;
}
}
/**
* @memberof actions/sources
* @static
*/
function loadSourceMap(generatedSource) {
return async function ({ dispatch, getState, sourceMaps }) {
const urls = await loadOriginalSourceUrls(sourceMaps, generatedSource);
let urls;
try {
urls = await sourceMaps.getOriginalURLs(generatedSource);
} catch (e) {
console.error(e);
urls = null;
}
if (!urls) {
// If this source doesn't have a sourcemap, do nothing.
// If this source doesn't have a sourcemap, enable it for pretty printing
dispatch({
type: "UPDATE_SOURCE",
source: _extends({}, generatedSource, { sourceMapURL: "" })
});
return;
}
@ -48836,6 +48851,7 @@ Object.defineProperty(exports, "__esModule", {
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
exports.updateFrameLocation = updateFrameLocation;
exports.mapFrames = mapFrames;
var _selectors = __webpack_require__(1352);
@ -50361,6 +50377,7 @@ class ProjectSearch extends _react.Component {
if (this.isProjectSearchEnabled()) {
return closeProjectSearch();
}
return setActiveSearch("project");
};
@ -50880,11 +50897,11 @@ class Tab extends _react.PureComponent {
})
}];
if (!isPrettySource) {
items.push({
item: _extends({}, tabMenuItems.showSource, { click: () => showSource(tab) })
});
items.push({
item: _extends({}, tabMenuItems.showSource, { click: () => showSource(tab) })
});
if (!isPrettySource) {
items.push({
item: _extends({}, tabMenuItems.prettyPrint, {
click: () => togglePrettyPrint(tab)
@ -52110,6 +52127,213 @@ function getExpressionFromCoords(cm, coord) {
return { expression, location };
}
/***/ }),
/* 2361 */,
/* 2362 */,
/* 2363 */,
/* 2364 */,
/* 2365 */,
/* 2366 */,
/* 2367 */,
/* 2368 */,
/* 2369 */,
/* 2370 */,
/* 2371 */,
/* 2372 */,
/* 2373 */,
/* 2374 */,
/* 2375 */,
/* 2376 */,
/* 2377 */,
/* 2378 */,
/* 2379 */,
/* 2380 */,
/* 2381 */,
/* 2382 */,
/* 2383 */,
/* 2384 */,
/* 2385 */,
/* 2386 */,
/* 2387 */,
/* 2388 */,
/* 2389 */,
/* 2390 */,
/* 2391 */,
/* 2392 */,
/* 2393 */,
/* 2394 */,
/* 2395 */,
/* 2396 */,
/* 2397 */,
/* 2398 */,
/* 2399 */,
/* 2400 */,
/* 2401 */,
/* 2402 */,
/* 2403 */,
/* 2404 */,
/* 2405 */,
/* 2406 */,
/* 2407 */,
/* 2408 */,
/* 2409 */,
/* 2410 */,
/* 2411 */,
/* 2412 */,
/* 2413 */,
/* 2414 */,
/* 2415 */,
/* 2416 */,
/* 2417 */,
/* 2418 */,
/* 2419 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _why = __webpack_require__(2420);
Object.keys(_why).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _why[key];
}
});
});
var _stepping = __webpack_require__(2421);
Object.keys(_stepping).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _stepping[key];
}
});
});
/***/ }),
/* 2420 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getPauseReason = getPauseReason;
exports.isException = isException;
exports.isInterrupted = isInterrupted;
exports.inDebuggerEval = inDebuggerEval;
// Map protocol pause "why" reason to a valid L10N key
// These are the known unhandled reasons:
// "breakpointConditionThrown", "clientEvaluated"
// "interrupted", "attached"
const reasons = {
debuggerStatement: "whyPaused.debuggerStatement",
breakpoint: "whyPaused.breakpoint",
exception: "whyPaused.exception",
resumeLimit: "whyPaused.resumeLimit",
pauseOnDOMEvents: "whyPaused.pauseOnDOMEvents",
breakpointConditionThrown: "whyPaused.breakpointConditionThrown",
// V8
DOM: "whyPaused.breakpoint",
EventListener: "whyPaused.pauseOnDOMEvents",
XHR: "whyPaused.xhr",
promiseRejection: "whyPaused.promiseRejection",
assert: "whyPaused.assert",
debugCommand: "whyPaused.debugCommand",
other: "whyPaused.other"
}; /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
function getPauseReason(why) {
if (!why) {
return null;
}
const reasonType = why.type;
if (!reasons[reasonType]) {
console.log("Please file an issue: reasonType=", reasonType);
}
return reasons[reasonType];
}
function isException(why) {
return why && why.type && why.type === "exception";
}
function isInterrupted(why) {
return why && why.type && why.type === "interrupted";
}
function inDebuggerEval(why) {
if (why && why.type === "exception" && why.exception && why.exception.preview && why.exception.preview.fileName) {
return why.exception.preview.fileName === "debugger eval code";
}
return false;
}
/***/ }),
/* 2421 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.shouldStep = shouldStep;
var _lodash = __webpack_require__(2);
var _devtoolsSourceMap = __webpack_require__(1360);
var _selectors = __webpack_require__(1352);
var _parser = __webpack_require__(1365);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
async function shouldStep(rootFrame, state, sourceMaps) {
if (!rootFrame) {
return false;
}
const selectedSource = (0, _selectors.getSelectedSource)(state);
const previousFrameInfo = (0, _selectors.getPreviousPauseFrameLocation)(state);
let previousFrameLoc;
let currentFrameLoc;
if (selectedSource && (0, _devtoolsSourceMap.isOriginalId)(selectedSource.get("id"))) {
currentFrameLoc = rootFrame.location;
previousFrameLoc = previousFrameInfo && previousFrameInfo.location;
} else {
currentFrameLoc = rootFrame.generatedLocation;
previousFrameLoc = previousFrameInfo && previousFrameInfo.generatedLocation;
}
return (0, _devtoolsSourceMap.isOriginalId)(currentFrameLoc.sourceId) && (previousFrameLoc && (0, _lodash.isEqual)(previousFrameLoc, currentFrameLoc) || (await (0, _parser.isInvalidPauseLocation)(currentFrameLoc)));
}
/***/ })
/******/ ]);
});

Просмотреть файл

@ -34597,15 +34597,15 @@ var _validate = __webpack_require__(1629);
var _frameworks = __webpack_require__(1703);
var _pauseLocation = __webpack_require__(2422);
var _devtoolsUtils = __webpack_require__(1363);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
const { workerHandler } = _devtoolsUtils.workerUtils;
const { workerHandler } = _devtoolsUtils.workerUtils; /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
self.onmessage = workerHandler({
getClosestExpression: _closest.getClosestExpression,
@ -34618,6 +34618,7 @@ self.onmessage = workerHandler({
hasSource: _sources.hasSource,
setSource: _sources.setSource,
clearSources: _sources.clearSources,
isInvalidPauseLocation: _pauseLocation.isInvalidPauseLocation,
getVariablesInScope: _scopes.getVariablesInScope,
getNextStep: _steps.getNextStep,
getEmptyLines: _getEmptyLines2.default,
@ -60818,6 +60819,82 @@ function stripModuleScope(rootScope) {
});
}
/***/ }),
/* 2415 */,
/* 2416 */,
/* 2417 */,
/* 2418 */,
/* 2419 */,
/* 2420 */,
/* 2421 */,
/* 2422 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isInvalidPauseLocation = isInvalidPauseLocation;
var _types = __webpack_require__(2268);
var t = _interopRequireWildcard(_types);
var _ast = __webpack_require__(1375);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
const STOP = {};
function isInvalidPauseLocation(location) {
const state = {
invalid: false,
location
};
try {
(0, _ast.fastTraverseAst)(location.sourceId, { enter: invalidLocationVisitor }, state);
} catch (e) {
if (e !== STOP) {
throw e;
}
}
return state.invalid;
}
function invalidLocationVisitor(node, ancestors, state) {
const { location } = state;
if (node.loc.end.line < location.line) {
return;
}
if (node.loc.start.line > location.line) {
throw STOP;
}
if (location.line === node.loc.start.line && location.column >= node.loc.start.column && t.isFunction(node) && !t.isArrowFunctionExpression(node) && (location.line < node.body.loc.start.line || location.line === node.body.loc.start.line && location.column <= node.body.loc.start.column)) {
// Disallow pausing _inside_ in function arguments to avoid pausing inside
// of destructuring and other logic.
state.invalid = true;
throw STOP;
}
if (location.line === node.loc.start.line && location.column === node.loc.start.column && t.isBlockStatement(node)) {
// Disallow pausing directly before the opening curly of a block statement.
// Babel occasionally maps statements with unknown original positions to
// this location.
state.invalid = true;
throw STOP;
}
}
/***/ })
/******/ ]);
});

Просмотреть файл

@ -117,8 +117,9 @@ support-files =
[browser_dbg-asm.js]
[browser_dbg-async-stepping.js]
[browser_dbg-babel.js]
[browser_dbg-babel-scopes.js]
skip-if = (os == "win" && ccov) # bug 1438797
[browser_dbg-babel-stepping.js]
[browser_dbg-breaking.js]
[browser_dbg-breaking-from-console.js]
[browser_dbg-breakpoints.js]

Просмотреть файл

@ -0,0 +1,154 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests for stepping through Babel's compile output.
async function breakpointSteps(dbg, fixture, { line, column }, steps) {
const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
const filename = `fixtures/${fixture}/input.js`;
await waitForSources(dbg, filename);
ok(true, "Original sources exist");
const source = findSource(dbg, filename);
await selectSource(dbg, source);
// Test that breakpoint is not off by a line.
await addBreakpoint(dbg, source, line);
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
ok(
getBreakpoint(getState(), { sourceId: source.id, line, column }),
"Breakpoint has correct line"
);
const fnName = fixture.replace(/-([a-z])/g, (s, c) => c.toUpperCase());
const invokeResult = invokeInTab(fnName);
let invokeFailed = await Promise.race([
waitForPaused(dbg),
invokeResult.then(() => new Promise(() => {}), () => true)
]);
if (invokeFailed) {
return invokeResult;
}
assertPausedLocation(dbg);
await removeBreakpoint(dbg, source.id, line, column);
is(getBreakpoints(getState()).size, 0, "Breakpoint reverted");
await runSteps(dbg, source, steps);
await resume(dbg);
// If the invoke errored later somehow, capture here so the error is
// reported nicely.
await invokeResult;
ok(true, `Ran tests for ${fixture} at line ${line} column ${column}`);
}
async function runSteps(dbg, source, steps) {
const { selectors: { getVisibleSelectedFrame }, getState } = dbg;
for (const [i, [type, position]] of steps.entries()) {
switch (type) {
case "stepOver":
await stepOver(dbg);
break;
case "stepIn":
await stepIn(dbg);
break;
default:
throw new Error("Unknown stepping type");
}
const { location } = getVisibleSelectedFrame(getState());
is(location.sourceId, source.id, `Step ${i} has correct sourceId`);
is(location.line, position.line, `Step ${i} has correct line`);
is(location.column, position.column, `Step ${i} has correct column`);
assertPausedLocation(dbg);
}
}
add_task(async function() {
requestLongerTimeout(4);
const dbg = await initDebugger("doc-babel.html");
await breakpointSteps(dbg, "step-over-for-of", { line: 4, column: 2 }, [
["stepOver", { line: 6, column: 2 }],
["stepOver", { line: 7, column: 4 }],
["stepOver", { line: 6, column: 2 }],
["stepOver", { line: 7, column: 4 }],
["stepOver", { line: 6, column: 2 }],
["stepOver", { line: 10, column: 2 }]
]);
// This codifies the current behavior, but stepping twice over the for
// header isn't ideal.
await breakpointSteps(dbg, "step-over-for-of-array", { line: 3, column: 2 }, [
["stepOver", { line: 5, column: 2 }],
["stepOver", { line: 5, column: 7 }],
["stepOver", { line: 6, column: 4 }],
["stepOver", { line: 5, column: 2 }],
["stepOver", { line: 5, column: 7 }],
["stepOver", { line: 6, column: 4 }],
["stepOver", { line: 5, column: 2 }],
["stepOver", { line: 9, column: 2 }]
]);
// The closure means it isn't actually possible to step into the for body,
// and Babel doesn't map the _loop() call, so we step past it automatically.
await breakpointSteps(
dbg,
"step-over-for-of-closure",
{ line: 6, column: 2 },
[
["stepOver", { line: 8, column: 2 }],
["stepOver", { line: 12, column: 2 }]
]
);
// Same as the previous, not possible to step into the body. The less
// complicated array logic makes it possible to step into the header at least,
// but this does end up double-visiting the for head.
await breakpointSteps(
dbg,
"step-over-for-of-array-closure",
{ line: 3, column: 2 },
[
["stepOver", { line: 5, column: 2 }],
["stepOver", { line: 5, column: 7 }],
["stepOver", { line: 5, column: 2 }],
["stepOver", { line: 5, column: 7 }],
["stepOver", { line: 5, column: 2 }],
["stepOver", { line: 9, column: 2 }]
]
);
await breakpointSteps(
dbg,
"step-over-function-params",
{ line: 6, column: 2 },
[["stepOver", { line: 7, column: 2 }], ["stepIn", { line: 2, column: 2 }]]
);
await breakpointSteps(
dbg,
"step-over-regenerator-await",
{ line: 2, column: 2 },
[
// Won't work until a fix to regenerator lands and we rebuild.
// https://github.com/facebook/regenerator/issues/342
// ["stepOver", { line: 4, column: 2 }],
]
);
});

Просмотреть файл

@ -26,7 +26,7 @@ add_task(async function() {
const { selectors: { getSelectedSource }, getState } = dbg;
// Make sure the thread is paused in the right source and location
await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
await waitForPaused(dbg);
is(dbg.win.cm.getValue(), "debugger");
const source = getSelectedSource(getState()).toJS();
assertPausedLocation(dbg);

Просмотреть файл

@ -53,7 +53,6 @@ add_task(async function() {
await reload(dbg);
await waitForSource(dbg, "v1");
await syncBp;
await waitForSelectedSource(dbg, "v1");
is(getBreakpoints(dbg).length, 0, "No breakpoints");
});

Просмотреть файл

@ -5,7 +5,7 @@ code, and optionally help with indentation.
# Upgrade
Currently used version is 5.34.0. To upgrade: download a new version of
Currently used version is 5.35.0. To upgrade: download a new version of
CodeMirror from the project's page [1] and replace all JavaScript and
CSS files inside the codemirror directory [2].

Просмотреть файл

@ -90,7 +90,7 @@
var state = cm.state.matchHighlighter;
cm.addOverlay(state.overlay = makeOverlay(query, hasBoundary, style));
if (state.options.annotateScrollbar && cm.showMatchesOnScrollbar) {
var searchFor = hasBoundary ? new RegExp("\\b" + query + "\\b") : query;
var searchFor = hasBoundary ? new RegExp("\\b" + query.replace(/[\\\[+*?(){|^$]/g, "\\$&") + "\\b") : query;
state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, false,
{className: "CodeMirror-selection-highlight-scrollbar"});
}

Просмотреть файл

@ -19,8 +19,11 @@
+ (regexp.multiline ? "m" : "")
}
function ensureGlobal(regexp) {
return regexp.global ? regexp : new RegExp(regexp.source, regexpFlags(regexp) + "g")
function ensureFlags(regexp, flags) {
var current = regexpFlags(regexp), target = current
for (var i = 0; i < flags.length; i++) if (target.indexOf(flags.charAt(i)) == -1)
target += flags.charAt(i)
return current == target ? regexp : new RegExp(regexp.source, target)
}
function maybeMultiline(regexp) {
@ -28,7 +31,7 @@
}
function searchRegexpForward(doc, regexp, start) {
regexp = ensureGlobal(regexp)
regexp = ensureFlags(regexp, "g")
for (var line = start.line, ch = start.ch, last = doc.lastLine(); line <= last; line++, ch = 0) {
regexp.lastIndex = ch
var string = doc.getLine(line), match = regexp.exec(string)
@ -42,7 +45,7 @@
function searchRegexpForwardMultiline(doc, regexp, start) {
if (!maybeMultiline(regexp)) return searchRegexpForward(doc, regexp, start)
regexp = ensureGlobal(regexp)
regexp = ensureFlags(regexp, "gm")
var string, chunk = 1
for (var line = start.line, last = doc.lastLine(); line <= last;) {
// This grows the search buffer in exponentially-sized chunks
@ -51,6 +54,7 @@
// searching for something that has tons of matches), but at the
// same time, the amount of retries is limited.
for (var i = 0; i < chunk; i++) {
if (line > last) break
var curLine = doc.getLine(line++)
string = string == null ? curLine : string + "\n" + curLine
}
@ -81,7 +85,7 @@
}
function searchRegexpBackward(doc, regexp, start) {
regexp = ensureGlobal(regexp)
regexp = ensureFlags(regexp, "g")
for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) {
var string = doc.getLine(line)
if (ch > -1) string = string.slice(0, ch)
@ -94,7 +98,7 @@
}
function searchRegexpBackwardMultiline(doc, regexp, start) {
regexp = ensureGlobal(regexp)
regexp = ensureFlags(regexp, "gm")
var string, chunk = 1
for (var line = start.line, first = doc.firstLine(); line >= first;) {
for (var i = 0; i < chunk; i++) {
@ -213,7 +217,7 @@
return (reverse ? searchStringBackward : searchStringForward)(doc, query, pos, caseFold)
}
} else {
query = ensureGlobal(query)
query = ensureFlags(query, "gm")
if (!options || options.multiline !== false)
this.matches = function(reverse, pos) {
return (reverse ? searchRegexpBackwardMultiline : searchRegexpForwardMultiline)(doc, query, pos)

Просмотреть файл

@ -5454,7 +5454,8 @@ var CodeMirror =
// Revert a change stored in a document's history.
function makeChangeFromHistory(doc, type, allowSelectionOnly) {
if (doc.cm && doc.cm.state.suppressEdits && !allowSelectionOnly) { return }
var suppress = doc.cm && doc.cm.state.suppressEdits
if (suppress && !allowSelectionOnly) { return }
var hist = doc.history, event, selAfter = doc.sel
var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done
@ -5479,8 +5480,10 @@ var CodeMirror =
return
}
selAfter = event
}
else { break }
} else if (suppress) {
source.push(event)
return
} else { break }
}
// Build up a reverse change object to add to the opposite history
@ -5956,7 +5959,7 @@ var CodeMirror =
}
return true
})
signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle))
if (cm) { signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)) }
return widget
}
@ -9892,7 +9895,7 @@ var CodeMirror =
addLegacyProps(CodeMirror)
CodeMirror.version = "5.34.0"
CodeMirror.version = "5.35.0"
return CodeMirror;
@ -9923,8 +9926,11 @@ var CodeMirror =
+ (regexp.multiline ? "m" : "")
}
function ensureGlobal(regexp) {
return regexp.global ? regexp : new RegExp(regexp.source, regexpFlags(regexp) + "g")
function ensureFlags(regexp, flags) {
var current = regexpFlags(regexp), target = current
for (var i = 0; i < flags.length; i++) if (target.indexOf(flags.charAt(i)) == -1)
target += flags.charAt(i)
return current == target ? regexp : new RegExp(regexp.source, target)
}
function maybeMultiline(regexp) {
@ -9932,7 +9938,7 @@ var CodeMirror =
}
function searchRegexpForward(doc, regexp, start) {
regexp = ensureGlobal(regexp)
regexp = ensureFlags(regexp, "g")
for (var line = start.line, ch = start.ch, last = doc.lastLine(); line <= last; line++, ch = 0) {
regexp.lastIndex = ch
var string = doc.getLine(line), match = regexp.exec(string)
@ -9946,7 +9952,7 @@ var CodeMirror =
function searchRegexpForwardMultiline(doc, regexp, start) {
if (!maybeMultiline(regexp)) return searchRegexpForward(doc, regexp, start)
regexp = ensureGlobal(regexp)
regexp = ensureFlags(regexp, "gm")
var string, chunk = 1
for (var line = start.line, last = doc.lastLine(); line <= last;) {
// This grows the search buffer in exponentially-sized chunks
@ -9955,6 +9961,7 @@ var CodeMirror =
// searching for something that has tons of matches), but at the
// same time, the amount of retries is limited.
for (var i = 0; i < chunk; i++) {
if (line > last) break
var curLine = doc.getLine(line++)
string = string == null ? curLine : string + "\n" + curLine
}
@ -9985,7 +9992,7 @@ var CodeMirror =
}
function searchRegexpBackward(doc, regexp, start) {
regexp = ensureGlobal(regexp)
regexp = ensureFlags(regexp, "g")
for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) {
var string = doc.getLine(line)
if (ch > -1) string = string.slice(0, ch)
@ -9998,7 +10005,7 @@ var CodeMirror =
}
function searchRegexpBackwardMultiline(doc, regexp, start) {
regexp = ensureGlobal(regexp)
regexp = ensureFlags(regexp, "gm")
var string, chunk = 1
for (var line = start.line, first = doc.firstLine(); line >= first;) {
for (var i = 0; i < chunk; i++) {
@ -10117,7 +10124,7 @@ var CodeMirror =
return (reverse ? searchStringBackward : searchStringForward)(doc, query, pos, caseFold)
}
} else {
query = ensureGlobal(query)
query = ensureFlags(query, "gm")
if (!options || options.multiline !== false)
this.matches = function(reverse, pos) {
return (reverse ? searchRegexpBackwardMultiline : searchRegexpForwardMultiline)(doc, query, pos)
@ -11438,6 +11445,7 @@ var CodeMirror =
if (type == "{") return contCommasep(objprop, "}", null, maybeop);
if (type == "quasi") return pass(quasi, maybeop);
if (type == "new") return cont(maybeTarget(noComma));
if (type == "import") return cont(expression);
return cont();
}
function maybeexpression(type) {
@ -11632,7 +11640,7 @@ var CodeMirror =
}
function afterType(type, value) {
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
if (value == "|" || type == ".") return cont(typeexpr)
if (value == "|" || type == "." || value == "&") return cont(typeexpr)
if (type == "[") return cont(expect("]"), afterType)
if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) }
}
@ -11675,7 +11683,8 @@ var CodeMirror =
function maybeelse(type, value) {
if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
}
function forspec(type) {
function forspec(type, value) {
if (value == "await") return cont(forspec);
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
}
function forspec1(type) {
@ -11764,6 +11773,7 @@ var CodeMirror =
}
function afterImport(type) {
if (type == "string") return cont();
if (type == "(") return pass(expression);
return pass(importSpec, maybeMoreImports, maybeFrom);
}
function importSpec(type, value) {
@ -14416,7 +14426,7 @@ var CodeMirror =
blockKeywords: words("case do else for if switch while struct"),
defKeywords: words("struct"),
typeFirstDefinitions: true,
atoms: words("null true false"),
atoms: words("NULL true false"),
hooks: {"#": cppHook, "*": pointerHook},
modeProps: {fold: ["brace", "include"]}
});
@ -14432,7 +14442,7 @@ var CodeMirror =
blockKeywords: words("catch class do else finally for if struct switch try while"),
defKeywords: words("class namespace struct enum union"),
typeFirstDefinitions: true,
atoms: words("true false null"),
atoms: words("true false NULL"),
dontIndentStatements: /^template$/,
isIdentifierChar: /[\w\$_~\xa1-\uffff]/,
hooks: {
@ -14639,22 +14649,24 @@ var CodeMirror =
name: "clike",
keywords: words(
/*keywords*/
"package as typealias class interface this super val " +
"var fun for is in This throw return " +
"package as typealias class interface this super val operator " +
"var fun for is in This throw return annotation " +
"break continue object if else while do try when !in !is as? " +
/*soft keywords*/
"file import where by get set abstract enum open inner override private public internal " +
"protected catch finally out final vararg reified dynamic companion constructor init " +
"sealed field property receiver param sparam lateinit data inline noinline tailrec " +
"external annotation crossinline const operator infix suspend actual expect"
"external annotation crossinline const operator infix suspend actual expect setparam"
),
types: words(
/* package java.lang */
"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void Annotation Any BooleanArray " +
"ByteArray Char CharArray DeprecationLevel DoubleArray Enum FloatArray Function Int IntArray Lazy " +
"LazyThreadSafetyMode LongArray Nothing ShortArray Unit"
),
intendSwitch: false,
indentStatements: false,
@ -16448,7 +16460,7 @@ var CodeMirror =
}
function handleKeyNonInsertMode() {
if (handleMacroRecording() || handleEsc()) { return true; };
if (handleMacroRecording() || handleEsc()) { return true; }
var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key;
if (/^[1-9]\d*$/.test(keys)) { return true; }
@ -17033,7 +17045,7 @@ var CodeMirror =
} else {
if (vim.visualMode) {
showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>',
onKeyDown: onPromptKeyDown});
onKeyDown: onPromptKeyDown, selectValueOnOpen: false});
} else {
showPrompt(cm, { onClose: onPromptClose, prefix: ':',
onKeyDown: onPromptKeyDown});
@ -19290,7 +19302,15 @@ var CodeMirror =
}
}
function splitBySlash(argString) {
var slashes = findUnescapedSlashes(argString) || [];
return splitBySeparator(argString, '/');
}
function findUnescapedSlashes(argString) {
return findUnescapedSeparators(argString, '/');
}
function splitBySeparator(argString, separator) {
var slashes = findUnescapedSeparators(argString, separator) || [];
if (!slashes.length) return [];
var tokens = [];
// in case of strings like foo/bar
@ -19302,12 +19322,15 @@ var CodeMirror =
return tokens;
}
function findUnescapedSlashes(str) {
function findUnescapedSeparators(str, separator) {
if (!separator)
separator = '/';
var escapeNextChar = false;
var slashes = [];
for (var i = 0; i < str.length; i++) {
var c = str.charAt(i);
if (!escapeNextChar && c == '/') {
if (!escapeNextChar && c == separator) {
slashes.push(i);
}
escapeNextChar = !escapeNextChar && (c == '\\');
@ -20173,7 +20196,7 @@ var CodeMirror =
'any other getSearchCursor implementation.');
}
var argString = params.argString;
var tokens = argString ? splitBySlash(argString) : [];
var tokens = argString ? splitBySeparator(argString, argString[0]) : [];
var regexPart, replacePart = '', trailing, flagsPart, count;
var confirm = false; // Whether to confirm each replace.
var global = false; // True to replace all instances on a line, false to replace only 1.
@ -20217,7 +20240,7 @@ var CodeMirror =
global = true;
flagsPart.replace('g', '');
}
regexPart = regexPart + '/' + flagsPart;
regexPart = regexPart.replace(/\//g, "\\/") + '/' + flagsPart;
}
}
if (regexPart) {
@ -20433,7 +20456,7 @@ var CodeMirror =
}
if (!confirm) {
replaceAll();
if (callback) { callback(); };
if (callback) { callback(); }
return;
}
showPrompt(cm, {
@ -20569,7 +20592,7 @@ var CodeMirror =
exitInsertMode(cm);
}
}
};
}
macroModeState.isPlaying = false;
}
@ -20773,7 +20796,7 @@ var CodeMirror =
exitInsertMode(cm);
}
macroModeState.isPlaying = false;
};
}
function repeatInsertModeChanges(cm, changes, repeat) {
function keyHandler(binding) {
@ -20988,8 +21011,14 @@ var CodeMirror =
var ranges = cm.listSelections(), newRanges = [];
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i];
var newAnchor = cm.findPosV(range.anchor, dir, "line");
var newHead = cm.findPosV(range.head, dir, "line");
var newAnchor = cm.findPosV(
range.anchor, dir, "line", range.anchor.goalColumn);
var newHead = cm.findPosV(
range.head, dir, "line", range.head.goalColumn);
newAnchor.goalColumn = range.anchor.goalColumn != null ?
range.anchor.goalColumn : cm.cursorCoords(range.anchor, "div").left;
newHead.goalColumn = range.head.goalColumn != null ?
range.head.goalColumn : cm.cursorCoords(range.head, "div").left;
var newRange = {anchor: newAnchor, head: newHead};
newRanges.push(range);
newRanges.push(newRange);

Просмотреть файл

@ -156,8 +156,14 @@
var ranges = cm.listSelections(), newRanges = [];
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i];
var newAnchor = cm.findPosV(range.anchor, dir, "line");
var newHead = cm.findPosV(range.head, dir, "line");
var newAnchor = cm.findPosV(
range.anchor, dir, "line", range.anchor.goalColumn);
var newHead = cm.findPosV(
range.head, dir, "line", range.head.goalColumn);
newAnchor.goalColumn = range.anchor.goalColumn != null ?
range.anchor.goalColumn : cm.cursorCoords(range.anchor, "div").left;
newHead.goalColumn = range.head.goalColumn != null ?
range.head.goalColumn : cm.cursorCoords(range.head, "div").left;
var newRange = {anchor: newAnchor, head: newHead};
newRanges.push(range);
newRanges.push(newRange);

Просмотреть файл

@ -841,7 +841,7 @@
}
function handleKeyNonInsertMode() {
if (handleMacroRecording() || handleEsc()) { return true; };
if (handleMacroRecording() || handleEsc()) { return true; }
var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key;
if (/^[1-9]\d*$/.test(keys)) { return true; }
@ -1426,7 +1426,7 @@
} else {
if (vim.visualMode) {
showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>',
onKeyDown: onPromptKeyDown});
onKeyDown: onPromptKeyDown, selectValueOnOpen: false});
} else {
showPrompt(cm, { onClose: onPromptClose, prefix: ':',
onKeyDown: onPromptKeyDown});
@ -3683,7 +3683,15 @@
}
}
function splitBySlash(argString) {
var slashes = findUnescapedSlashes(argString) || [];
return splitBySeparator(argString, '/');
}
function findUnescapedSlashes(argString) {
return findUnescapedSeparators(argString, '/');
}
function splitBySeparator(argString, separator) {
var slashes = findUnescapedSeparators(argString, separator) || [];
if (!slashes.length) return [];
var tokens = [];
// in case of strings like foo/bar
@ -3695,12 +3703,15 @@
return tokens;
}
function findUnescapedSlashes(str) {
function findUnescapedSeparators(str, separator) {
if (!separator)
separator = '/';
var escapeNextChar = false;
var slashes = [];
for (var i = 0; i < str.length; i++) {
var c = str.charAt(i);
if (!escapeNextChar && c == '/') {
if (!escapeNextChar && c == separator) {
slashes.push(i);
}
escapeNextChar = !escapeNextChar && (c == '\\');
@ -4566,7 +4577,7 @@
'any other getSearchCursor implementation.');
}
var argString = params.argString;
var tokens = argString ? splitBySlash(argString) : [];
var tokens = argString ? splitBySeparator(argString, argString[0]) : [];
var regexPart, replacePart = '', trailing, flagsPart, count;
var confirm = false; // Whether to confirm each replace.
var global = false; // True to replace all instances on a line, false to replace only 1.
@ -4610,7 +4621,7 @@
global = true;
flagsPart.replace('g', '');
}
regexPart = regexPart + '/' + flagsPart;
regexPart = regexPart.replace(/\//g, "\\/") + '/' + flagsPart;
}
}
if (regexPart) {
@ -4826,7 +4837,7 @@
}
if (!confirm) {
replaceAll();
if (callback) { callback(); };
if (callback) { callback(); }
return;
}
showPrompt(cm, {
@ -4962,7 +4973,7 @@
exitInsertMode(cm);
}
}
};
}
macroModeState.isPlaying = false;
}
@ -5166,7 +5177,7 @@
exitInsertMode(cm);
}
macroModeState.isPlaying = false;
};
}
function repeatInsertModeChanges(cm, changes, repeat) {
function keyHandler(binding) {

Просмотреть файл

@ -5212,7 +5212,8 @@ function makeChangeInner(doc, change) {
// Revert a change stored in a document's history.
function makeChangeFromHistory(doc, type, allowSelectionOnly) {
if (doc.cm && doc.cm.state.suppressEdits && !allowSelectionOnly) { return }
var suppress = doc.cm && doc.cm.state.suppressEdits
if (suppress && !allowSelectionOnly) { return }
var hist = doc.history, event, selAfter = doc.sel
var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done
@ -5237,8 +5238,10 @@ function makeChangeFromHistory(doc, type, allowSelectionOnly) {
return
}
selAfter = event
}
else { break }
} else if (suppress) {
source.push(event)
return
} else { break }
}
// Build up a reverse change object to add to the opposite history
@ -5714,7 +5717,7 @@ function addLineWidget(doc, handle, node, options) {
}
return true
})
signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle))
if (cm) { signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)) }
return widget
}
@ -9650,7 +9653,7 @@ CodeMirror.fromTextArea = fromTextArea
addLegacyProps(CodeMirror)
CodeMirror.version = "5.34.0"
CodeMirror.version = "5.35.0"
return CodeMirror;

Просмотреть файл

@ -374,7 +374,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
blockKeywords: words("case do else for if switch while struct"),
defKeywords: words("struct"),
typeFirstDefinitions: true,
atoms: words("null true false"),
atoms: words("NULL true false"),
hooks: {"#": cppHook, "*": pointerHook},
modeProps: {fold: ["brace", "include"]}
});
@ -390,7 +390,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
blockKeywords: words("catch class do else finally for if struct switch try while"),
defKeywords: words("class namespace struct enum union"),
typeFirstDefinitions: true,
atoms: words("true false null"),
atoms: words("true false NULL"),
dontIndentStatements: /^template$/,
isIdentifierChar: /[\w\$_~\xa1-\uffff]/,
hooks: {
@ -597,22 +597,24 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
name: "clike",
keywords: words(
/*keywords*/
"package as typealias class interface this super val " +
"var fun for is in This throw return " +
"package as typealias class interface this super val operator " +
"var fun for is in This throw return annotation " +
"break continue object if else while do try when !in !is as? " +
/*soft keywords*/
"file import where by get set abstract enum open inner override private public internal " +
"protected catch finally out final vararg reified dynamic companion constructor init " +
"sealed field property receiver param sparam lateinit data inline noinline tailrec " +
"external annotation crossinline const operator infix suspend actual expect"
"external annotation crossinline const operator infix suspend actual expect setparam"
),
types: words(
/* package java.lang */
"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void Annotation Any BooleanArray " +
"ByteArray Char CharArray DeprecationLevel DoubleArray Enum FloatArray Function Int IntArray Lazy " +
"LazyThreadSafetyMode LongArray Nothing ShortArray Unit"
),
intendSwitch: false,
indentStatements: false,

Просмотреть файл

@ -400,6 +400,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "{") return contCommasep(objprop, "}", null, maybeop);
if (type == "quasi") return pass(quasi, maybeop);
if (type == "new") return cont(maybeTarget(noComma));
if (type == "import") return cont(expression);
return cont();
}
function maybeexpression(type) {
@ -594,7 +595,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
function afterType(type, value) {
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
if (value == "|" || type == ".") return cont(typeexpr)
if (value == "|" || type == "." || value == "&") return cont(typeexpr)
if (type == "[") return cont(expect("]"), afterType)
if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) }
}
@ -637,7 +638,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function maybeelse(type, value) {
if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
}
function forspec(type) {
function forspec(type, value) {
if (value == "await") return cont(forspec);
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
}
function forspec1(type) {
@ -726,6 +728,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
function afterImport(type) {
if (type == "string") return cont();
if (type == "(") return pass(expression);
return pass(importSpec, maybeMoreImports, maybeFrom);
}
function importSpec(type, value) {

Просмотреть файл

@ -63,6 +63,12 @@
MT("import_trailing_comma",
"[keyword import] {[def foo], [def bar],} [keyword from] [string 'baz']")
MT("import_dynamic",
"[keyword import]([string 'baz']).[property then]")
MT("import_dynamic",
"[keyword const] [def t] [operator =] [keyword import]([string 'baz']).[property then]")
MT("const",
"[keyword function] [def f]() {",
" [keyword const] [[ [def a], [def b] ]] [operator =] [[ [number 1], [number 2] ]];",
@ -71,6 +77,9 @@
MT("for/of",
"[keyword for]([keyword let] [def of] [keyword of] [variable something]) {}");
MT("for await",
"[keyword for] [keyword await]([keyword let] [def of] [keyword of] [variable something]) {}");
MT("generator",
"[keyword function*] [def repeat]([def n]) {",
" [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])",

Просмотреть файл

@ -2330,7 +2330,7 @@ testCM("lineSeparator", function(cm) {
lineSeparator: "\n"});
var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/
var getChar = function (noExtending) { var res; do {res = String.fromCharCode(Math.floor(Math.random()*0x8ac)); } while ([0x90].includes(res.charCodeAt(0)) || (noExtending && extendingChars.test(res))); return res }
var getChar = function (noExtending) { var res; do {res = String.fromCharCode(Math.floor(Math.random()*0x8ac)); } while ([0x90].indexOf(res.charCodeAt(0)) != -1 || (noExtending && extendingChars.test(res))); return res }
var getString = function (n) { var res = getChar(true); while (--n > 0) res += getChar(); return res }
function makeItWrapAfter(cm, pos) {
@ -2356,7 +2356,7 @@ function testMoveBidi(str) {
var steps = str.length - countIf(str.split(""), function(ch) { return extendingChars.test(ch) });
var lineBreaks = {}
lineBreaks[6 - countIf(str.substr(0, 5).split(""), function(ch) { return extendingChars.test(ch) })] = 'w';
if (str.includes("\n")) {
if (str.indexOf("\n") != -1) {
lineBreaks[steps - 2] = 'n';
}

Просмотреть файл

@ -153,7 +153,7 @@ function testVim(name, run, opts, expectedFail) {
// Record for insert mode.
if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') {
var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges;
if (lastChange && (key.includes('Delete') || key.includes('Backspace'))) {
if (lastChange && (key.indexOf('Delete') != -1 || key.indexOf('Backspace') != -1)) {
lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key));
}
}
@ -255,7 +255,7 @@ function testJumplist(name, keys, endPos, startPos, dialog) {
helpers.doKeys.apply(null, keys);
helpers.assertCursorAt(endPos);
}, {value: jumplistScene});
};
}
testJumplist('jumplist_H', ['H', '<C-o>'], [5,2], [5,2]);
testJumplist('jumplist_M', ['M', '<C-o>'], [2,2], [2,2]);
testJumplist('jumplist_L', ['L', '<C-o>'], [2,2], [2,2]);
@ -299,15 +299,15 @@ function testMotion(name, keys, endPos, startPos) {
helpers.doKeys(keys);
helpers.assertCursorAt(endPos);
});
};
}
function makeCursor(line, ch) {
return new Pos(line, ch);
};
}
function offsetCursor(cur, offsetLine, offsetCh) {
return new Pos(cur.line + offsetLine, cur.ch + offsetCh);
};
}
// Motion tests
testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4));
@ -3648,6 +3648,11 @@ testVim('ex_substitute_same_line', function(cm, vim, helpers) {
helpers.doEx('s/one/two/g');
eq('one one\n two two', cm.getValue());
}, { value: 'one one\n one one'});
testVim('ex_substitute_alternate_separator', function(cm, vim, helpers) {
cm.setCursor(1, 0);
helpers.doEx('s#o/e#two#g');
eq('o/e o/e\n two two', cm.getValue());
}, { value: 'o/e o/e\n o/e o/e'});
testVim('ex_substitute_full_file', function(cm, vim, helpers) {
cm.setCursor(1, 0);
helpers.doEx('%s/one/two/g');
@ -3904,7 +3909,7 @@ function testSubstituteConfirm(name, command, initialValue, expectedValue, keys,
cm.openDialog = savedOpenDialog;
}
}, { value: initialValue });
};
}
testSubstituteConfirm('ex_substitute_confirm_emptydoc',
'%s/x/b/c', '', '', '', makeCursor(0, 0));
testSubstituteConfirm('ex_substitute_confirm_nomatch',

Просмотреть файл

@ -96,7 +96,7 @@ function evalCode() {
/* eslint-disable */
Components.utils.evalInSandbox(
"" + function doStuff(k) { // line 1
let arg = 15; // line 2 - Step in here
var arg = 15; // line 2 - Step in here
k(arg); // line 3
}, // line 4
gDebuggee,

Просмотреть файл

@ -60,8 +60,8 @@ function evaluateTestCode() {
} // 4
// 5
function innerFunction() { // 6
let x = 0; // 7
let y = 72; // 8
var x = 0; // 7
var y = 72; // 8
return x+y; // 9
} // 10
outerFunction(); // 11

Просмотреть файл

@ -121,7 +121,7 @@ SOURCES += [
# rule stated in the test/ directory, but it's the only way this will work.
# Test classes are only built in debug mode, and all tests requiring use of
# them are only run in debug mode.
if CONFIG['MOZ_DEBUG']:
if CONFIG['MOZ_DEBUG'] and CONFIG['ENABLE_TESTS']:
EXPORTS.mozilla.dom += [
"test/TestFunctions.h",
"test/TestInterfaceIterableDouble.h",

Просмотреть файл

@ -70,6 +70,30 @@ function testKeys(browser) {
});
}
function testOpen_worker(browser) {
return ContentTask.spawn(browser, {}, function() {
let workerFunctionString = function () {
caches.open("pb-worker-cache").then(function(cacheObject) {
postMessage(cacheObject.toString());
}, function (reason) {
postMessage(reason.name);
});
}.toString();
let workerBlobURL = content.URL.createObjectURL(
new Blob(['(', workerFunctionString, ')()'],
{ type : 'application/javascript' }));
let worker = new content.Worker(workerBlobURL);
content.URL.revokeObjectURL(workerBlobURL);
return new Promise(function(resolve, reject) {
worker.addEventListener("message", function (e) {
let isGood = (e.data === "SecurityError");
ok(isGood, "caches.open() should throw SecurityError from worker");
isGood ? resolve() : reject();
});
});
});
}
function test() {
let privateWin, privateTab;
waitForExplicitFinish();
@ -88,6 +112,7 @@ function test() {
testOpen(privateTab.linkedBrowser),
testDelete(privateTab.linkedBrowser),
testKeys(privateTab.linkedBrowser),
testOpen_worker(privateTab.linkedBrowser),
]);
}).then(() => {
return BrowserTestUtils.closeWindow(privateWin);

Просмотреть файл

@ -797,6 +797,11 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
// In that case we will get a simulated OnStartRequest() and then the real
// channel will call in with an errored OnStartRequest().
if (!mChannel) {
MOZ_ASSERT(!mObserver);
return NS_BINDING_ABORTED;
}
nsresult rv;
aRequest->GetStatus(&rv);
if (NS_FAILED(rv)) {

Просмотреть файл

@ -1034,7 +1034,7 @@ WEBIDL_FILES += [
# We only expose our prefable test interfaces in debug builds, just to be on
# the safe side.
if CONFIG['MOZ_DEBUG']:
if CONFIG['MOZ_DEBUG'] and CONFIG['ENABLE_TESTS']:
WEBIDL_FILES += ['TestFunctions.webidl',
'TestInterfaceJS.webidl',
'TestInterfaceJSDictionaries.webidl',

Просмотреть файл

@ -108,27 +108,25 @@ NS_NewXULPrototypeDocument(nsXULPrototypeDocument** aResult)
NS_IMETHODIMP
nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
{
nsresult rv;
nsCOMPtr<nsISupports> supports;
rv = aStream->ReadObject(true, getter_AddRefs(supports));
nsresult rv = aStream->ReadObject(true, getter_AddRefs(supports));
if (NS_FAILED(rv)) {
return rv;
}
mURI = do_QueryInterface(supports);
uint32_t count, i;
nsCOMPtr<nsIURI> styleOverlayURI;
nsresult tmp = aStream->Read32(&count);
if (NS_FAILED(tmp)) {
return tmp;
}
rv = aStream->Read32(&count);
if (NS_FAILED(rv)) {
return rv;
}
for (i = 0; i < count; ++i) {
tmp = aStream->ReadObject(true, getter_AddRefs(supports));
if (NS_FAILED(tmp)) {
rv = tmp;
rv = aStream->ReadObject(true, getter_AddRefs(supports));
if (NS_FAILED(rv)) {
return rv;
}
styleOverlayURI = do_QueryInterface(supports);
mStyleSheetReferences.AppendObject(styleOverlayURI);
@ -136,12 +134,11 @@ nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
// nsIPrincipal mNodeInfoManager->mPrincipal
nsCOMPtr<nsIPrincipal> principal;
tmp = aStream->ReadObject(true, getter_AddRefs(supports));
principal = do_QueryInterface(supports);
if (NS_FAILED(tmp)) {
rv = tmp;
rv = aStream->ReadObject(true, getter_AddRefs(supports));
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(supports);
// Better safe than sorry....
mNodeInfoManager->SetDocumentPrincipal(principal);
@ -150,45 +147,45 @@ nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
// mozilla::dom::NodeInfo table
nsTArray<RefPtr<mozilla::dom::NodeInfo>> nodeInfos;
tmp = aStream->Read32(&count);
if (NS_FAILED(tmp)) {
rv = tmp;
rv = aStream->Read32(&count);
if (NS_FAILED(rv)) {
return rv;
}
nsAutoString namespaceURI, prefixStr, localName;
bool prefixIsNull;
RefPtr<nsAtom> prefix;
for (i = 0; i < count; ++i) {
tmp = aStream->ReadString(namespaceURI);
if (NS_FAILED(tmp)) {
rv = tmp;
rv = aStream->ReadString(namespaceURI);
if (NS_FAILED(rv)) {
return rv;
}
tmp = aStream->ReadBoolean(&prefixIsNull);
if (NS_FAILED(tmp)) {
rv = tmp;
rv = aStream->ReadBoolean(&prefixIsNull);
if (NS_FAILED(rv)) {
return rv;
}
if (prefixIsNull) {
prefix = nullptr;
} else {
tmp = aStream->ReadString(prefixStr);
if (NS_FAILED(tmp)) {
rv = tmp;
rv = aStream->ReadString(prefixStr);
if (NS_FAILED(rv)) {
return rv;
}
prefix = NS_Atomize(prefixStr);
}
tmp = aStream->ReadString(localName);
if (NS_FAILED(tmp)) {
rv = tmp;
rv = aStream->ReadString(localName);
if (NS_FAILED(rv)) {
return rv;
}
RefPtr<mozilla::dom::NodeInfo> nodeInfo;
// Using UINT16_MAX here as we don't know which nodeinfos will be
// used for attributes and which for elements. And that doesn't really
// matter.
tmp = mNodeInfoManager->GetNodeInfo(localName, prefix, namespaceURI,
UINT16_MAX,
getter_AddRefs(nodeInfo));
if (NS_FAILED(tmp)) {
rv = tmp;
rv = mNodeInfoManager->GetNodeInfo(localName, prefix, namespaceURI,
UINT16_MAX,
getter_AddRefs(nodeInfo));
if (NS_FAILED(rv)) {
return rv;
}
nodeInfos.AppendElement(nodeInfo);
}
@ -196,41 +193,36 @@ nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
// Document contents
uint32_t type;
while (NS_SUCCEEDED(rv)) {
tmp = aStream->Read32(&type);
if (NS_FAILED(tmp)) {
rv = tmp;
rv = aStream->Read32(&type);
if (NS_FAILED(rv)) {
return rv;
break;
}
if ((nsXULPrototypeNode::Type)type == nsXULPrototypeNode::eType_PI) {
RefPtr<nsXULPrototypePI> pi = new nsXULPrototypePI();
tmp = pi->Deserialize(aStream, this, mURI, &nodeInfos);
if (NS_FAILED(tmp)) {
rv = tmp;
rv = pi->Deserialize(aStream, this, mURI, &nodeInfos);
if (NS_FAILED(rv)) {
return rv;
}
tmp = AddProcessingInstruction(pi);
if (NS_FAILED(tmp)) {
rv = tmp;
rv = AddProcessingInstruction(pi);
if (NS_FAILED(rv)) {
return rv;
}
} else if ((nsXULPrototypeNode::Type)type == nsXULPrototypeNode::eType_Element) {
tmp = mRoot->Deserialize(aStream, this, mURI, &nodeInfos);
if (NS_FAILED(tmp)) {
rv = tmp;
rv = mRoot->Deserialize(aStream, this, mURI, &nodeInfos);
if (NS_FAILED(rv)) {
return rv;
}
break;
} else {
NS_NOTREACHED("Unexpected prototype node type");
rv = NS_ERROR_FAILURE;
break;
return NS_ERROR_FAILURE;
}
}
tmp = NotifyLoadDone();
if (NS_FAILED(tmp)) {
rv = tmp;
}
return rv;
return NotifyLoadDone();
}
static nsresult

Просмотреть файл

@ -20,16 +20,143 @@
#include "js/Value.h"
#include "js/Vector.h"
/*
* API for safe passing of structured data, HTML 2018 Feb 21 section 2.7.
* <https://html.spec.whatwg.org/multipage/structured-data.html>
*
* This is a serialization scheme for JS values, somewhat like JSON. It
* preserves some aspects of JS objects (strings, numbers, own data properties
* with string keys, array elements) but not others (methods, getters and
* setters, prototype chains). Unlike JSON, structured data:
*
* - can contain cyclic references.
*
* - handles Maps, Sets, and some other object types.
*
* - supports *transferring* objects of certain types from one realm to
* another, rather than cloning them.
*
* - is specified by a living standard, and continues to evolve.
*
* - is encoded in a nonstandard binary format, and is never exposed to Web
* content in its serialized form. It's used internally by the browser to
* send data from one thread/realm/domain to another, not across the
* network.
*/
struct JSStructuredCloneReader;
struct JSStructuredCloneWriter;
// API for the HTML5 internal structured cloning algorithm.
/**
* The structured-clone serialization format version number.
*
* When serialized data is stored as bytes, e.g. in your Firefox profile, later
* versions of the engine may have to read it. When you upgrade Firefox, we
* don't crawl through your whole profile converting all saved data from the
* previous version of the serialization format to the latest version. So it is
* normal to have data in old formats stored in your profile.
*
* The JS engine can *write* data only in the current format version.
*
* It can *read* any data written in the current version, and data written for
* DifferentProcess scope in earlier versions.
*
*
* ## When to bump this version number
*
* When making a change so drastic that the JS engine needs to know whether
* it's reading old or new serialized data in order to handle both correctly,
* increment this version number. Make sure the engine can still read all
* old data written with previous versions.
*
* If StructuredClone.cpp doesn't contain code that distinguishes between
* version 8 and version 9, there should not be a version 9.
*
* Do not increment for changes that only affect SameProcess encoding.
*
* Increment only for changes that would otherwise break old serialized data.
* Do not increment for new data types. (Rationale: Modulo bugs, older versions
* of the JS engine can already correctly throw errors when they encounter new,
* unrecognized features. A version number bump does not actually help them.)
*/
#define JS_STRUCTURED_CLONE_VERSION 8
namespace JS {
/**
* Indicates the "scope of validity" of serialized data.
*
* Writing plain JS data produces an array of bytes that can be copied and
* read in another process or whatever. The serialized data is Plain Old Data.
* However, HTML also supports `Transferable` objects, which, when cloned, can
* be moved from the source object into the clone, like when you take a
* photograph of someone and it steals their soul.
* See <https://developer.mozilla.org/en-US/docs/Web/API/Transferable>.
* We support cloning and transferring objects of many types.
*
* For example, when we transfer an ArrayBuffer (within a process), we "detach"
* the ArrayBuffer, embed the raw buffer pointer in the serialized data, and
* later install it in a new ArrayBuffer in the destination realm. Ownership
* of that buffer memory is transferred from the original ArrayBuffer to the
* serialized data and then to the clone.
*
* This only makes sense within a single address space. When we transfer an
* ArrayBuffer to another process, the contents of the buffer must be copied
* into the serialized data. (The original ArrayBuffer is still detached,
* though, for consistency; in some cases the caller shouldn't know or care if
* the recipient is in the same process.)
*
* ArrayBuffers are actually a lucky case; some objects (like MessagePorts)
* can't reasonably be stored by value in serialized data -- it's pointers or
* nothing.
*
* So there is a tradeoff between scope of validity -- how far away the
* serialized data may be sent and still make sense -- and efficiency or
* features. The read and write algorithms therefore take an argument of this
* type, allowing the user to control those trade-offs.
*/
enum class StructuredCloneScope : uint32_t {
/**
* The most restrictive scope, with greatest efficiency and features.
*
* When writing, this means we're writing for an audience in the same
* process and same thread. The caller promises that the serialized data
* will **not** be shipped off to a different thread/process or stored in a
* database. It's OK to produce serialized data that contains pointers. In
* Rust terms, the serialized data will be treated as `!Send`.
*
* When reading, this means: Accept transferred objects and buffers
* (pointers). The caller promises that the serialized data was written
* using this API (otherwise, the serialized data may contain bogus
* pointers, leading to undefined behavior).
*/
SameProcessSameThread,
/**
* When writing, this means: The caller promises that the serialized data
* will **not** be shipped off to a different process or stored in a
* database. However, it may be shipped to another thread. It's OK to
* produce serialized data that contains pointers to data that is safe to
* send across threads, such as array buffers. In Rust terms, the
* serialized data will be treated as `Send` but not `Copy`.
*
* When reading, this means the same thing as SameProcessSameThread;
* the distinction only matters when writing.
*/
SameProcessDifferentThread,
/**
* The broadest scope.
*
* When writing, this means we're writing for an audience in a different
* process. Produce serialized data that can be sent to other processes,
* bitwise copied, or even stored as bytes in a database and read by later
* versions of Firefox years from now. Transferable objects are limited to
* ArrayBuffers, whose contents are copied into the serialized data (rather
* than just writing a pointer).
*
* When reading, this means: Do not accept pointers.
*/
DifferentProcess
};
@ -168,12 +295,6 @@ typedef bool (*TransferStructuredCloneOp)(JSContext* cx,
typedef void (*FreeTransferStructuredCloneOp)(uint32_t tag, JS::TransferableOwnership ownership,
void* content, uint64_t extraData, void* closure);
// The maximum supported structured-clone serialization format version.
// Increment this when anything at all changes in the serialization format.
// (Note that this does not need to be bumped for Transferable-only changes,
// since they are never saved to persistent storage.)
#define JS_STRUCTURED_CLONE_VERSION 8
struct JSStructuredCloneCallbacks {
ReadStructuredCloneOp read;
WriteStructuredCloneOp write;
@ -257,7 +378,11 @@ public:
using BufferList::BufferList;
};
/** Note: if the *data contains transferable objects, it can be read only once. */
/**
* Implements StructuredDeserialize and StructuredDeserializeWithTransfer.
*
* Note: If `data` contains transferable objects, it can be read only once.
*/
JS_PUBLIC_API(bool)
JS_ReadStructuredClone(JSContext* cx, JSStructuredCloneData& data, uint32_t version,
JS::StructuredCloneScope scope,
@ -265,6 +390,9 @@ JS_ReadStructuredClone(JSContext* cx, JSStructuredCloneData& data, uint32_t vers
const JSStructuredCloneCallbacks* optionalCallbacks, void* closure);
/**
* Implements StructuredSerialize, StructuredSerializeForStorage, and
* StructuredSerializeWithTransfer.
*
* Note: If the scope is DifferentProcess then the cloneDataPolicy must deny
* shared-memory objects, or an error will be signaled if a shared memory object
* is seen.

Просмотреть файл

@ -23,6 +23,9 @@
// NB: keep this in sync with the copy in vm/ArgumentsObject.h.
#define MAX_ARGS_LENGTH (500 * 1000)
// NB: keep this in sync with the copy in vm/String.h.
#define MAX_STRING_LENGTH ((1 << 28) - 1)
// Spread non-empty argument list of up to 15 elements.
#define SPREAD(v, n) SPREAD_##n(v)
#define SPREAD_1(v) v[0]

Просмотреть файл

@ -68,8 +68,7 @@ function String_generic_match(thisValue, regexp) {
* A helper function implementing the logic for both String.prototype.padStart
* and String.prototype.padEnd as described in ES7 Draft March 29, 2016
*/
function String_pad(maxLength, fillString, padEnd = false) {
function String_pad(maxLength, fillString, padEnd) {
// Steps 1-2.
RequireObjectCoercible(this);
let str = ToString(this);
@ -83,21 +82,28 @@ function String_pad(maxLength, fillString, padEnd = false) {
return str;
// Steps 6-7.
let filler = fillString === undefined ? " " : ToString(fillString);
assert(fillString !== undefined, "never called when fillString is undefined");
let filler = ToString(fillString);
// Step 8.
if (filler === "")
return str;
// Throw an error if the final string length exceeds the maximum string
// length. Perform this check early so we can use int32 operations below.
if (intMaxLength > MAX_STRING_LENGTH)
ThrowRangeError(JSMSG_RESULTING_STRING_TOO_LARGE);
// Step 9.
let fillLen = intMaxLength - strLen;
// Step 10.
// Perform an int32 division to ensure String_repeat is not called with a
// double to avoid repeated bailouts in ToInteger.
let truncatedStringFiller = callFunction(String_repeat, filler,
fillLen / filler.length);
(fillLen / filler.length) | 0);
truncatedStringFiller += callFunction(String_substr, filler, 0,
fillLen % filler.length);
truncatedStringFiller += Substring(filler, 0, fillLen % filler.length);
// Step 11.
if (padEnd === true)
@ -503,11 +509,14 @@ function String_repeat(count) {
if (n < 0)
ThrowRangeError(JSMSG_NEGATIVE_REPETITION_COUNT);
if (!(n * S.length < (1 << 28)))
// Inverted condition to handle |Infinity * 0 = NaN| correctly.
if (!(n * S.length <= MAX_STRING_LENGTH))
ThrowRangeError(JSMSG_RESULTING_STRING_TOO_LARGE);
// Communicate |n|'s possible range to the compiler.
n = n & ((1 << 28) - 1);
assert((MAX_STRING_LENGTH & (MAX_STRING_LENGTH + 1)) === 0,
"MAX_STRING_LENGTH can be used as a bitmask");
n = n & MAX_STRING_LENGTH;
// Steps 8-9.
var T = "";

Просмотреть файл

@ -2911,7 +2911,7 @@ const Class CloneBufferObject::class_ = {
const JSPropertySpec CloneBufferObject::props_[] = {
JS_PSGS("clonebuffer", getCloneBuffer, setCloneBuffer, 0),
JS_PSG("arraybuffer", getCloneBufferAsArrayBuffer, 0),
JS_PSGS("arraybuffer", getCloneBufferAsArrayBuffer, setCloneBuffer, 0),
JS_PS_END
};

Просмотреть файл

@ -895,7 +895,7 @@ BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind
if (!ensureCache(bce))
return false;
// Marks all names as closed over if the the context requires it. This
// Marks all names as closed over if the context requires it. This
// cannot be done in the Parser as we may not know if the context requires
// all bindings to be closed over until after parsing is finished. For
// example, legacy generators require all bindings to be closed over but
@ -6831,24 +6831,12 @@ BytecodeEmitter::emitLexicalScope(ParseNode* pn)
if (pn->isEmptyScope())
return emitLexicalScopeBody(body);
// Update line number notes before emitting TDZ poison in
// EmitterScope::enterLexical to avoid spurious pausing on seemingly
// non-effectful lines in Debugger.
//
// For example, consider the following code.
//
// L1: {
// L2: let x = 42;
// L3: }
//
// If line number notes were not updated before the TDZ poison, the TDZ
// poison bytecode sequence of 'uninitialized; initlexical' will have line
// number L1, and the Debugger will pause there.
// We are about to emit some bytecode for what the spec calls "declaration
// instantiation". Assign these instructions to the opening `{` of the
// block. (Using the location of each declaration we're instantiating is
// too weird when stepping in the debugger.)
if (!ParseNodeRequiresSpecialLineNumberNotes(body)) {
ParseNode* pnForPos = body;
if (body->isKind(ParseNodeKind::StatementList) && body->pn_head)
pnForPos = body->pn_head;
if (!updateLineNumberNotes(pnForPos->pn_pos.begin))
if (!updateSourceCoordNotes(pn->pn_pos.begin))
return false;
}

Просмотреть файл

@ -0,0 +1,32 @@
// Test that stepping through a function stops at the expected lines.
// `script` is a string, some JS code that evaluates to a function.
// `expected` is the array of line numbers where stepping is expected to stop
// when we call the function.
function testStepping(script, expected) {
let g = newGlobal();
let f = g.eval(script);
let log = [];
function maybePause(frame) {
let previousLine = log[log.length - 1]; // note: may be undefined
let line = frame.script.getOffsetLocation(frame.offset).lineNumber;
if (line !== previousLine)
log.push(line);
}
let dbg = new Debugger(g);
dbg.onEnterFrame = frame => {
// Log this pause (before the first instruction of the function).
maybePause(frame);
// Log future pauses in the same stack frame.
frame.onStep = function() { maybePause(this); };
// Now disable this hook so that we step over function calls, not into them.
dbg.onEnterFrame = undefined;
};
f();
assertEq(log.join(","), expected.join(","));
}

Просмотреть файл

@ -6,48 +6,25 @@
// But users don't actually want to see that happen when they're stepping.
// It's super confusing.
function runTest(script, expected) {
let g = newGlobal();
g.eval(script);
load(libdir + "stepping.js");
let dbg = new Debugger(g);
let log = [];
dbg.onEnterFrame = frame => {
let previousLine = undefined;
frame.onStep = function() {
let line = this.script.getOffsetLocation(this.offset).lineNumber;
if (line != previousLine) {
log.push(line);
previousLine = line;
}
};
// Now disable this hook so that we step over function calls, not into them.
dbg.onEnterFrame = undefined;
};
g.f();
assertEq(log.join(","), expected.join(","));
}
runTest(
testStepping(
`\
var f = (function() { // line 1
(function() { // line 1
let x = 1; // line 2
funcb("funcb"); // line 3
function funcb(msg) { // line 4
console.log(msg)
}
}); // line 7
}) // line 7
`,
[2, 3, 7]);
[1, 2, 3, 7]);
// Stopping at the ClassDeclaration on line 8 is fine. For that matter,
// stopping on line 5 wouldn't be so bad if we did it after line 3 and before
// line 8; alas, the actual order of execution is 5, 2, 3, 8... which is too
// confusing.
runTest(
testStepping(
`\
function f() { // 1
var x = 0; // 2
@ -59,5 +36,6 @@ runTest(
class Car {} // 8
return x; // 9
} // 10
f
`,
[2, 3, 8, 9, 10]);
[1, 2, 3, 8, 9, 10]);

Просмотреть файл

@ -4532,9 +4532,16 @@ LIRGenerator::visitWasmBoundsCheck(MWasmBoundsCheck* ins)
MDefinition* boundsCheckLimit = ins->boundsCheckLimit();
MOZ_ASSERT(boundsCheckLimit->type() == MIRType::Int32);
auto* lir = new(alloc()) LWasmBoundsCheck(useRegisterAtStart(index),
useRegisterAtStart(boundsCheckLimit));
add(lir, ins);
if (JitOptions.spectreIndexMasking) {
auto* lir = new(alloc()) LWasmBoundsCheck(useRegisterAtStart(index),
useRegister(boundsCheckLimit));
defineReuseInput(lir, ins, 0);
} else {
auto* lir = new(alloc()) LWasmBoundsCheck(useRegisterAtStart(index),
useRegisterAtStart(boundsCheckLimit));
add(lir, ins);
}
#endif
}

Просмотреть файл

@ -14236,6 +14236,9 @@ class MWasmBoundsCheck
{
// Bounds check is effectful: it throws for OOB.
setGuard();
if (JitOptions.spectreIndexMasking)
setResultType(MIRType::Int32);
}
public:

Просмотреть файл

@ -1470,8 +1470,10 @@ class MacroAssembler : public MacroAssemblerSpecific
void wasmTrap(wasm::Trap trap, wasm::BytecodeOffset bytecodeOffset);
// Emit a bounds check against the wasm heap limit, jumping to 'label' if 'cond' holds.
// Required when WASM_HUGE_MEMORY is not defined.
// Emit a bounds check against the wasm heap limit, jumping to 'label' if
// 'cond' holds. Required when WASM_HUGE_MEMORY is not defined. If
// JitOptions.spectreMaskIndex is true, in speculative executions 'index' is
// saturated in-place to 'boundsCheckLimit'.
template <class L>
inline void wasmBoundsCheck(Condition cond, Register index, Register boundsCheckLimit, L label)
DEFINED_ON(arm, arm64, mips32, mips64, x86);

Просмотреть файл

@ -15,6 +15,8 @@ using namespace mozilla;
typedef js::HashMap<uint32_t, MDefinition*, DefaultHasher<uint32_t>, SystemAllocPolicy>
LastSeenMap;
unsigned redundantCount = 0;
// The Wasm Bounds Check Elimination (BCE) pass looks for bounds checks
// on SSA values that have already been checked. (in the same block or in a
// dominating block). These bounds checks are redundant and thus eliminated.
@ -60,13 +62,25 @@ jit::EliminateBoundsChecks(MIRGenerator* mir, MIRGraph& graph)
uint32_t(addr->toConstant()->toInt32()) < mir->minWasmHeapLength())
{
bc->setRedundant();
redundantCount++;
if (JitOptions.spectreIndexMasking)
bc->replaceAllUsesWith(addr);
else
MOZ_ASSERT(!bc->hasUses());
}
else
{
LastSeenMap::AddPtr ptr = lastSeen.lookupForAdd(addr->id());
if (ptr) {
if (ptr->value()->block()->dominates(block))
MDefinition* prevCheckOrPhi = ptr->value();
if (prevCheckOrPhi->block()->dominates(block)) {
bc->setRedundant();
redundantCount++;
if (JitOptions.spectreIndexMasking)
bc->replaceAllUsesWith(prevCheckOrPhi);
else
MOZ_ASSERT(!bc->hasUses());
}
} else {
if (!lastSeen.add(ptr, addr->id(), def))
return false;
@ -90,6 +104,13 @@ jit::EliminateBoundsChecks(MIRGenerator* mir, MIRGraph& graph)
for (int i = 0, nOps = phi->numOperands(); i < nOps; i++) {
MDefinition* src = phi->getOperand(i);
if (JitOptions.spectreIndexMasking) {
if (src->isWasmBoundsCheck())
src = src->toWasmBoundsCheck()->index();
} else {
MOZ_ASSERT(!src->isWasmBoundsCheck());
}
LastSeenMap::Ptr checkPtr = lastSeen.lookup(src->id());
if (!checkPtr || !checkPtr->value()->block()->dominates(block)) {
phiChecked = false;

Просмотреть файл

@ -2301,6 +2301,8 @@ MacroAssembler::wasmBoundsCheck(Condition cond, Register index, Register boundsC
{
as_cmp(index, O2Reg(boundsCheckLimit));
as_b(label, cond);
if (JitOptions.spectreIndexMasking)
ma_mov(boundsCheckLimit, index, LeaveCC, cond);
}
template <class L>
@ -2312,6 +2314,8 @@ MacroAssembler::wasmBoundsCheck(Condition cond, Register index, Address boundsCh
ma_ldr(DTRAddr(boundsCheckLimit.base, DtrOffImm(boundsCheckLimit.offset)), scratch);
as_cmp(index, O2Reg(scratch));
as_b(label, cond);
if (JitOptions.spectreIndexMasking)
ma_mov(scratch, index, LeaveCC, cond);
}
//}}} check_macroassembler_style

Просмотреть файл

@ -8428,7 +8428,7 @@ class LWasmAddOffset : public LInstructionHelper<1, 1, 0>
}
};
class LWasmBoundsCheck : public LInstructionHelper<0, 2, 0>
class LWasmBoundsCheck : public LInstructionHelper<1, 2, 0>
{
public:
LIR_HEADER(WasmBoundsCheck);

Просмотреть файл

@ -1109,6 +1109,8 @@ MacroAssembler::wasmBoundsCheck(Condition cond, Register index, Register boundsC
{
cmp32(index, boundsCheckLimit);
j(cond, label);
if (JitOptions.spectreIndexMasking)
cmovCCl(cond, Operand(boundsCheckLimit), index);
}
template <class L>
@ -1117,6 +1119,8 @@ MacroAssembler::wasmBoundsCheck(Condition cond, Register index, Address boundsCh
{
cmp32(index, Operand(boundsCheckLimit));
j(cond, label);
if (JitOptions.spectreIndexMasking)
cmovCCl(cond, Operand(boundsCheckLimit), index);
}
//}}} check_macroassembler_style

Просмотреть файл

@ -1683,11 +1683,11 @@ js::ReportInNotObjectError(JSContext* cx, HandleValue lref, int lindex,
HandleValue rref, int rindex)
{
auto uniqueCharsFromString = [](JSContext* cx, HandleValue ref) -> UniqueChars {
static const size_t MAX_STRING_LENGTH = 16;
static const size_t MaxStringLength = 16;
RootedString str(cx, ref.toString());
if (str->length() > MAX_STRING_LENGTH) {
if (str->length() > MaxStringLength) {
StringBuffer buf(cx);
if (!buf.appendSubstring(str, 0, MAX_STRING_LENGTH))
if (!buf.appendSubstring(str, 0, MaxStringLength))
return nullptr;
if (!buf.append("..."))
return nullptr;

Просмотреть файл

@ -42,6 +42,7 @@
#include "js/CharacterEncoding.h"
#include "js/Date.h"
#include "js/Wrapper.h"
#include "vm/ArgumentsObject.h"
#include "vm/Compression.h"
#include "vm/GeneratorObject.h"
#include "vm/Interpreter.h"
@ -3194,3 +3195,9 @@ js::GetSelfHostedFunctionName(JSFunction* fun)
static_assert(JSString::MAX_LENGTH <= INT32_MAX,
"StringIteratorNext in builtin/String.js assumes the stored index "
"into the string is an Int32Value");
static_assert(JSString::MAX_LENGTH == MAX_STRING_LENGTH,
"JSString::MAX_LENGTH matches self-hosted constant for maximum string length");
static_assert(ARGS_LENGTH_MAX == MAX_ARGS_LENGTH,
"ARGS_LENGTH_MAX matches self-hosted constant for maximum arguments length");

Просмотреть файл

@ -5,26 +5,25 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* This file implements the structured clone algorithm of
* http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#safe-passing-of-structured-data
* This file implements the structured data algorithms of
* https://html.spec.whatwg.org/multipage/structured-data.html
*
* The implementation differs slightly in that it uses an explicit stack, and
* the "memory" maps source objects to sequential integer indexes rather than
* directly pointing to destination objects. As a result, the order in which
* things are added to the memory must exactly match the order in which they
* are placed into 'allObjs', an analogous array of back-referenceable
* destination objects constructed while reading.
* The spec is in two parts:
*
* For the most part, this is easy: simply add objects to the memory when first
* encountering them. But reading in a typed array requires an ArrayBuffer for
* construction, so objects cannot just be added to 'allObjs' in the order they
* are created. If they were, ArrayBuffers would come before typed arrays when
* in fact the typed array was added to 'memory' first.
* - StructuredSerialize examines a JS value and produces a graph of Records.
* - StructuredDeserialize walks the Records and produces a new JS value.
*
* So during writing, we add objects to the memory when first encountering
* them. When reading a typed array, a placeholder is pushed onto allObjs until
* the ArrayBuffer has been read, then it is updated with the actual typed
* array object.
* The differences between our implementation and the spec are minor:
*
* - We call the two phases "write" and "read".
* - Our algorithms use an explicit work stack, rather than recursion.
* - Serialized data is a flat array of bytes, not a (possibly cyclic) graph
* of "Records".
* - As a consequence, we handle non-treelike object graphs differently.
* We serialize objects that appear in multiple places in the input as
* backreferences, using sequential integer indexes.
* See `JSStructuredCloneReader::allObjs`, our take on the "memory" map
* in the spec's StructuredDeserialize.
*/
#include "js/StructuredClone.h"
@ -71,7 +70,7 @@ using JS::CanonicalizeNaN;
// sizing data structures.
enum StructuredDataType : uint32_t {
/* Structured data types provided by the engine */
// Structured data types provided by the engine
SCTAG_FLOAT_MAX = 0xFFF00000,
SCTAG_HEADER = 0xFFF10000,
SCTAG_NULL = 0xFFFF0000,
@ -119,11 +118,9 @@ enum StructuredDataType : uint32_t {
SCTAG_TYPED_ARRAY_V1_UINT8_CLAMPED = SCTAG_TYPED_ARRAY_V1_MIN + Scalar::Uint8Clamped,
SCTAG_TYPED_ARRAY_V1_MAX = SCTAG_TYPED_ARRAY_V1_MIN + Scalar::MaxTypedArrayViewType - 1,
/*
* Define a separate range of numbers for Transferable-only tags, since
* they are not used for persistent clone buffers and therefore do not
* require bumping JS_STRUCTURED_CLONE_VERSION.
*/
// Define a separate range of numbers for Transferable-only tags, since
// they are not used for persistent clone buffers and therefore do not
// require bumping JS_STRUCTURED_CLONE_VERSION.
SCTAG_TRANSFER_MAP_HEADER = 0xFFFF0200,
SCTAG_TRANSFER_MAP_PENDING_ENTRY,
SCTAG_TRANSFER_MAP_ARRAY_BUFFER,
@ -380,7 +377,7 @@ class SCInput {
BufferIterator point;
};
} /* namespace js */
} // namespace js
struct JSStructuredCloneReader {
public:
@ -432,7 +429,17 @@ struct JSStructuredCloneReader {
// Stack of objects with properties remaining to be read.
AutoValueVector objs;
// Stack of all objects read during this deserialization
// Array of all objects read during this deserialization, for resolving
// backreferences.
//
// For backreferences to work correctly, objects must be added to this
// array in exactly the order expected by the version of the Writer that
// created the serialized data, even across years and format versions. This
// is usually no problem, since both algorithms do a single linear pass
// over the serialized data. There is one hitch; see readTypedArray.
//
// The values in this vector are objects, except it can temporarily have
// one `undefined` placeholder value (the readTypedArray hack).
AutoValueVector allObjs;
// The user defined callbacks that will be used for cloning.
@ -736,7 +743,7 @@ bool
SCInput::read(uint64_t* p)
{
if (!point.canPeek()) {
*p = 0; /* initialize to shut GCC up */
*p = 0; // initialize to shut GCC up
return reportTruncated();
}
*p = NativeEndian::swapFromLittleEndian(point.peek());
@ -748,7 +755,7 @@ bool
SCInput::readNativeEndian(uint64_t* p)
{
if (!point.canPeek()) {
*p = 0; /* initialize to shut GCC up */
*p = 0; // initialize to shut GCC up
return reportTruncated();
}
*p = point.peek();
@ -844,9 +851,7 @@ SCInput::readArray(T* p, size_t nelems)
JS_STATIC_ASSERT(sizeof(uint64_t) % sizeof(T) == 0);
/*
* Fail if nelems is so huge that computing the full size will overflow.
*/
// Fail if nelems is so huge that computing the full size will overflow.
mozilla::CheckedInt<size_t> size = mozilla::CheckedInt<size_t>(nelems) * sizeof(T);
if (!size.isValid())
return reportTruncated();
@ -915,15 +920,13 @@ SCOutput::write(uint64_t u)
bool
SCOutput::writePair(uint32_t tag, uint32_t data)
{
/*
* As it happens, the tag word appears after the data word in the output.
* This is because exponents occupy the last 2 bytes of doubles on the
* little-endian platforms we care most about.
*
* For example, TrueValue() is written using writePair(SCTAG_BOOLEAN, 1).
* PairToUInt64 produces the number 0xFFFF000200000001.
* That is written out as the bytes 01 00 00 00 02 00 FF FF.
*/
// As it happens, the tag word appears after the data word in the output.
// This is because exponents occupy the last 2 bytes of doubles on the
// little-endian platforms we care most about.
//
// For example, TrueValue() is written using writePair(SCTAG_BOOLEAN, 1).
// PairToUInt64 produces the number 0xFFFF000200000001.
// That is written out as the bytes 01 00 00 00 02 00 FF FF.
return write(PairToUInt64(tag, data));
}
@ -1031,7 +1034,7 @@ SCOutput::discardTransferables(const JSStructuredCloneCallbacks* cb, void* cbClo
DiscardTransferables(buf, cb, cbClosure);
}
} /* namespace js */
} // namespace js
JSStructuredCloneData::~JSStructuredCloneData()
{
@ -1152,7 +1155,7 @@ inline void
JSStructuredCloneWriter::checkStack()
{
#ifdef DEBUG
/* To avoid making serialization O(n^2), limit stack-checking at 10. */
// To avoid making serialization O(n^2), limit stack-checking at 10.
const size_t MAX = 10;
size_t limit = Min(counts.length(), MAX);
@ -1296,7 +1299,7 @@ JSStructuredCloneWriter::writeSharedWasmMemory(HandleObject obj)
bool
JSStructuredCloneWriter::startObject(HandleObject obj, bool* backref)
{
/* Handle cycles in the object graph. */
// Handle cycles in the object graph.
CloneMemory::AddPtr p = memory.lookupForAdd(obj);
if ((*backref = p.found()))
return out.writePair(SCTAG_BACK_REFERENCE_OBJECT, p->value());
@ -1317,10 +1320,8 @@ JSStructuredCloneWriter::startObject(HandleObject obj, bool* backref)
bool
JSStructuredCloneWriter::traverseObject(HandleObject obj)
{
/*
* Get enumerable property ids and put them in reverse order so that they
* will come off the stack in forward order.
*/
// Get enumerable property ids and put them in reverse order so that they
// will come off the stack in forward order.
AutoIdVector properties(context());
if (!GetPropertyKeys(context(), obj, JSITER_OWNONLY, &properties))
return false;
@ -1332,13 +1333,13 @@ JSStructuredCloneWriter::traverseObject(HandleObject obj)
return false;
}
/* Push obj and count to the stack. */
// Push obj and count to the stack.
if (!objs.append(ObjectValue(*obj)) || !counts.append(properties.length()))
return false;
checkStack();
/* Write the header for obj. */
// Write the header for obj.
ESClass cls;
if (!GetBuiltinClass(context(), obj, &cls))
return false;
@ -1365,13 +1366,13 @@ JSStructuredCloneWriter::traverseMap(HandleObject obj)
return false;
}
/* Push obj and count to the stack. */
// Push obj and count to the stack.
if (!objs.append(ObjectValue(*obj)) || !counts.append(newEntries.length()))
return false;
checkStack();
/* Write the header for obj. */
// Write the header for obj.
return out.writePair(SCTAG_MAP_OBJECT, 0);
}
@ -1395,13 +1396,13 @@ JSStructuredCloneWriter::traverseSet(HandleObject obj)
return false;
}
/* Push obj and count to the stack. */
// Push obj and count to the stack.
if (!objs.append(ObjectValue(*obj)) || !counts.append(keys.length()))
return false;
checkStack();
/* Write the header for obj. */
// Write the header for obj.
return out.writePair(SCTAG_SET_OBJECT, 0);
}
@ -1587,7 +1588,7 @@ JSStructuredCloneWriter::startWrite(HandleValue v)
if (callbacks && callbacks->write)
return callbacks->write(context(), this, obj, closure);
/* else fall through */
// else fall through
}
return reportDataCloneError(JS_SCERR_UNSUPPORTED_TYPE);
@ -1786,11 +1787,9 @@ JSStructuredCloneWriter::write(HandleValue v)
return false;
MOZ_ASSERT(JSID_IS_STRING(id) || JSID_IS_INT(id));
/*
* If obj still has an own property named id, write it out.
* The cost of re-checking could be avoided by using
* NativeIterators.
*/
// If obj still has an own property named id, write it out.
// The cost of re-checking could be avoided by using
// NativeIterators.
bool found;
if (!HasOwnProperty(context(), obj, id, &found))
return false;
@ -1852,7 +1851,7 @@ class Chars {
void forget() { p = nullptr; }
};
} /* anonymous namespace */
} // anonymous namespace
template <typename CharT>
JSString*
@ -1897,7 +1896,7 @@ JSStructuredCloneReader::readTypedArray(uint32_t arrayType, uint32_t nelems, Mut
return false;
}
// Push a placeholder onto the allObjs list to stand in for the typed array
// Push a placeholder onto the allObjs list to stand in for the typed array.
uint32_t placeholderIndex = allObjs.length();
Value dummy = UndefinedValue();
if (!allObjs.append(dummy))

Просмотреть файл

@ -414,6 +414,8 @@ InitialCompileFlags(const CompileArgs& args, Decoder& d, CompileMode* mode, Tier
*debug = debugEnabled ? DebugEnabled::True : DebugEnabled::False;
}
extern unsigned redundantCount;
SharedModule
wasm::CompileBuffer(const CompileArgs& args, const ShareableBytes& bytecode, UniqueChars* error)
{
@ -441,7 +443,11 @@ wasm::CompileBuffer(const CompileArgs& args, const ShareableBytes& bytecode, Uni
if (!DecodeModuleTail(d, &env))
return nullptr;
return mg.finishModule(bytecode);
auto module = mg.finishModule(bytecode);
printf("# redundant: %u\n", redundantCount);
return module;
}
bool

Просмотреть файл

@ -832,8 +832,12 @@ class FunctionCompiler
}
MWasmLoadTls* boundsCheckLimit = maybeLoadBoundsCheckLimit();
if (boundsCheckLimit)
curBlock_->add(MWasmBoundsCheck::New(alloc(), *base, boundsCheckLimit, bytecodeOffset()));
if (boundsCheckLimit) {
auto* ins = MWasmBoundsCheck::New(alloc(), *base, boundsCheckLimit, bytecodeOffset());
curBlock_->add(ins);
if (JitOptions.spectreIndexMasking)
*base = ins;
}
}
bool isSmallerAccessForI64(ValType result, const MemoryAccessDesc* access) {

Просмотреть файл

@ -184,7 +184,8 @@ android.libraryVariants.all { variant ->
classpath = files(variant.javaCompile.classpath.files)
source = files(variant.javaCompile.source)
exclude '**/R.java', '**/BuildConfig.java', 'com/google/**', 'org/webrtc/**'
exclude '**/R.java', '**/BuildConfig.java'
include 'org/mozilla/geckoview/**'
options.addPathOption('sourcepath', ':').setValue(
variant.sourceSets.collect({ it.javaDirectories }).flatten() +
variant.generateBuildConfig.sourceOutputDir)
@ -195,6 +196,7 @@ android.libraryVariants.all { variant ->
file("${System.properties['java.home']}/lib/rt.jar")] + android.bootClasspath
options.memberLevel = JavadocMemberLevel.PROTECTED
options.source = 7
options.links("https://d.android.com/reference/")
options.docTitle = "GeckoView ${mozconfig.substs.MOZ_APP_VERSION} API"
options.header = "GeckoView ${mozconfig.substs.MOZ_APP_VERSION} API"

Просмотреть файл

@ -353,7 +353,7 @@ public class GeckoSession extends LayerSession
private final Listener mListener = new Listener();
protected static final class Window extends JNIObject implements IInterface {
/* package */ static final class Window extends JNIObject implements IInterface {
private NativeQueue mNativeQueue;
private Binder mBinder;
@ -1405,17 +1405,6 @@ public class GeckoSession extends LayerSession
}
}
enum LoadUriResult {
HANDLED(0),
LOAD_IN_FRAME(1);
private int mValue;
private LoadUriResult(int value) {
mValue = value;
}
}
/**
* A request to open an URI.
* @param session The GeckoSession that initiated the callback.

Просмотреть файл

@ -107,7 +107,7 @@ public final class TextInputController {
mEditable.setDefaultEditableChild(mEditableChild);
}
public void onWindowChanged(final GeckoSession.Window window) {
/* package */ void onWindowChanged(final GeckoSession.Window window) {
if (mQueue.isReady()) {
window.attachEditable(mEditable, mEditableChild);
} else {

Просмотреть файл

@ -326,8 +326,9 @@ static ArenaAllocator<8192, 1> gPrefNameArena;
class Pref
{
public:
explicit Pref()
: mType(static_cast<uint32_t>(PrefType::None))
explicit Pref(const char* aName)
: mName(ArenaStrdup(aName, gPrefNameArena))
, mType(static_cast<uint32_t>(PrefType::None))
, mIsSticky(false)
, mIsLocked(false)
, mHasDefaultValue(false)
@ -340,10 +341,15 @@ public:
~Pref()
{
// There's no need to free mName because it's allocated in memory owned by
// gPrefNameArena.
mDefaultValue.Clear(Type());
mUserValue.Clear(Type());
}
const char* Name() { return mName; }
// Types.
PrefType Type() const { return static_cast<PrefType>(mType); }
@ -395,6 +401,15 @@ public:
// Other operations.
bool MatchEntry(const char* aPrefName)
{
if (!mName || !aPrefName) {
return false;
}
return strcmp(mName, aPrefName) == 0;
}
nsresult GetBoolValue(PrefValueKind aKind, bool* aResult)
{
if (!IsTypeBool()) {
@ -454,16 +469,11 @@ public:
return NS_OK;
}
// Fills out a dom pref with the values from this pref.
// @param aDomPref The pref to update.
// @param aName Optional. Override the dom pref's name with aName.
void ToDomPref(dom::Pref* aDomPref, const char* aName = nullptr)
void ToDomPref(dom::Pref* aDomPref)
{
MOZ_ASSERT(XRE_IsParentProcess());
if (aName) {
aDomPref->name() = aName;
}
aDomPref->name() = mName;
aDomPref->isLocked() = mIsLocked;
@ -492,6 +502,7 @@ public:
void FromDomPref(const dom::Pref& aDomPref, bool* aValueChanged)
{
MOZ_ASSERT(!XRE_IsParentProcess());
MOZ_ASSERT(strcmp(mName, aDomPref.name().get()) == 0);
mIsLocked = aDomPref.isLocked();
@ -677,6 +688,7 @@ public:
void AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, PrefsSizes& aSizes)
{
// Note: mName is allocated in gPrefNameArena, measured elsewhere.
aSizes.mPrefValues += aMallocSizeOf(this);
if (IsTypeString()) {
if (mHasDefaultValue) {
@ -689,6 +701,8 @@ public:
}
private:
const char* mName; // allocated in gPrefNameArena
uint32_t mType : 2;
uint32_t mIsSticky : 1;
uint32_t mIsLocked : 1;
@ -700,6 +714,36 @@ private:
PrefValue mUserValue;
};
class PrefEntry : public PLDHashEntryHdr
{
public:
Pref* mPref; // Note: this is never null in a live entry.
static bool MatchEntry(const PLDHashEntryHdr* aEntry, const void* aKey)
{
auto entry = static_cast<const PrefEntry*>(aEntry);
auto prefName = static_cast<const char*>(aKey);
return entry->mPref->MatchEntry(prefName);
}
static void InitEntry(PLDHashEntryHdr* aEntry, const void* aKey)
{
auto entry = static_cast<PrefEntry*>(aEntry);
auto prefName = static_cast<const char*>(aKey);
entry->mPref = new Pref(prefName);
}
static void ClearEntry(PLDHashTable* aTable, PLDHashEntryHdr* aEntry)
{
auto entry = static_cast<PrefEntry*>(aEntry);
delete entry->mPref;
entry->mPref = nullptr;
}
};
struct CallbackNode
{
CallbackNode(const char* aDomain,
@ -725,21 +769,7 @@ struct CallbackNode
CallbackNode* mNext;
};
// Hash key that allocates its string from the `gPrefNameArena`. The base class
// `nsDepCharHashKey` does not own the string data and no copies are made.
class StringArenaHashKey : public nsDepCharHashKey
{
public:
explicit StringArenaHashKey(const char* aKey)
: nsDepCharHashKey(ArenaStrdup(aKey, gPrefNameArena))
{
}
};
// Hashtable used to map names to pref objects. StringArenaHashKey is used to
// allocate the strings out of an arena.
using PrefsTable = nsClassHashtable<StringArenaHashKey, Pref>;
static PrefsTable* gHashTable;
static PLDHashTable* gHashTable;
// The callback list contains all the priority callbacks followed by the
// non-priority callbacks. gLastPriorityNode records where the first part ends.
@ -752,6 +782,14 @@ static bool gIsAnyPrefLocked = false;
static bool gCallbacksInProgress = false;
static bool gShouldCleanupDeadNodes = false;
static PLDHashTableOps pref_HashTableOps = {
PLDHashTable::HashStringKey,
PrefEntry::MatchEntry,
PLDHashTable::MoveEntryStub,
PrefEntry::ClearEntry,
PrefEntry::InitEntry,
};
static Pref*
pref_HashTableLookup(const char* aPrefName);
@ -765,10 +803,10 @@ pref_savePrefs()
{
MOZ_ASSERT(NS_IsMainThread());
PrefSaveData savedPrefs(gHashTable->Count());
PrefSaveData savedPrefs(gHashTable->EntryCount());
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
Pref* pref = iter.Data();
Pref* pref = static_cast<PrefEntry*>(iter.Get())->mPref;
nsAutoCString prefValueStr;
if (!pref->UserValueToStringForSaving(prefValueStr)) {
@ -776,7 +814,7 @@ pref_savePrefs()
}
nsAutoCString prefNameStr;
StrEscape(iter.Key(), prefNameStr);
StrEscape(pref->Name(), prefNameStr);
nsPrintfCString str(
"user_pref(%s, %s);", prefNameStr.get(), prefValueStr.get());
@ -827,7 +865,7 @@ IsEarlyPref(const char* aPrefName)
#endif // DEBUG
static PrefsTable::LookupResult
static PrefEntry*
pref_HashTableLookupInner(const char* aPrefName)
{
MOZ_ASSERT(NS_IsMainThread() || mozilla::ServoStyleSet::IsInServoTraversal());
@ -850,14 +888,14 @@ pref_HashTableLookupInner(const char* aPrefName)
}
#endif
return gHashTable->Lookup(aPrefName);
return static_cast<PrefEntry*>(gHashTable->Search(aPrefName));
}
static Pref*
pref_HashTableLookup(const char* aPrefName)
{
PrefsTable::LookupResult entry = pref_HashTableLookupInner(aPrefName);
return entry ? static_cast<Pref*>(entry.Data()) : nullptr;
PrefEntry* entry = pref_HashTableLookupInner(aPrefName);
return entry ? entry->mPref : nullptr;
}
static nsresult
@ -874,7 +912,12 @@ pref_SetPref(const char* aPrefName,
return NS_ERROR_OUT_OF_MEMORY;
}
Pref* pref = gHashTable->LookupOrAdd(aPrefName);
auto entry = static_cast<PrefEntry*>(gHashTable->Add(aPrefName, fallible));
if (!entry) {
return NS_ERROR_OUT_OF_MEMORY;
}
Pref* pref = entry->mPref;
if (pref->IsTypeNone()) {
// New entry. Set the type.
pref->SetType(aType);
@ -1987,11 +2030,13 @@ nsPrefBranch::DeleteBranch(const char* aStartingAt)
Substring(branchName, 0, branchName.Length() - 1);
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
Pref* pref = static_cast<PrefEntry*>(iter.Get())->mPref;
// The first disjunct matches branches: e.g. a branch name "foo.bar."
// matches a name "foo.bar.baz" (but it won't match "foo.barrel.baz").
// The second disjunct matches leaf nodes: e.g. a branch name "foo.bar."
// matches a name "foo.bar" (by ignoring the trailing '.').
nsDependentCString name(iter.Key());
nsDependentCString name(pref->Name());
if (StringBeginsWith(name, branchName) || name.Equals(branchNameNoDot)) {
iter.Remove();
}
@ -2026,8 +2071,9 @@ nsPrefBranch::GetChildList(const char* aStartingAt,
const PrefName& parent = GetPrefName(aStartingAt);
size_t parentLen = parent.Length();
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
if (strncmp(iter.Key(), parent.get(), parentLen) == 0) {
prefArray.AppendElement(iter.Key());
Pref* pref = static_cast<PrefEntry*>(iter.Get())->mPref;
if (strncmp(pref->Name(), parent.get(), parentLen) == 0) {
prefArray.AppendElement(pref->Name());
}
}
@ -2639,7 +2685,7 @@ PreferenceServiceReporter::CollectReports(
if (gHashTable) {
sizes.mHashTable += gHashTable->ShallowSizeOfIncludingThis(mallocSizeOf);
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
Pref* pref = iter.Data();
Pref* pref = static_cast<PrefEntry*>(iter.Get())->mPref;
pref->AddSizeOfIncludingThis(mallocSizeOf, sizes);
}
}
@ -2832,7 +2878,8 @@ Preferences::GetInstanceForService()
sPreferences = new Preferences();
MOZ_ASSERT(!gHashTable);
gHashTable = new PrefsTable(PREF_HASHTABLE_INITIAL_LENGTH);
gHashTable = new PLDHashTable(
&pref_HashTableOps, sizeof(PrefEntry), PREF_HASHTABLE_INITIAL_LENGTH);
gTelemetryLoadData =
new nsDataHashtable<nsCStringHashKey, TelemetryLoadData>();
@ -3087,7 +3134,7 @@ Preferences::ResetPrefs()
{
ENSURE_PARENT_PROCESS("Preferences::ResetPrefs", "all prefs");
gHashTable->Clear();
gHashTable->ClearAndPrepareForLength(PREF_HASHTABLE_INITIAL_LENGTH);
gPrefNameArena.Clear();
return InitInitialObjects().isOk() ? NS_OK : NS_ERROR_FAILURE;
@ -3102,10 +3149,10 @@ Preferences::ResetUserPrefs()
Vector<const char*> prefNames;
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
Pref* pref = iter.Data();
Pref* pref = static_cast<PrefEntry*>(iter.Get())->mPref;
if (pref->HasUserValue()) {
if (!prefNames.append(iter.Key())) {
if (!prefNames.append(pref->Name())) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -3179,7 +3226,12 @@ Preferences::SetPreference(const dom::Pref& aDomPref)
const char* prefName = aDomPref.name().get();
Pref* pref = gHashTable->LookupOrAdd(prefName);
auto entry = static_cast<PrefEntry*>(gHashTable->Add(prefName, fallible));
if (!entry) {
return;
}
Pref* pref = entry->mPref;
bool valueChanged = false;
pref->FromDomPref(aDomPref, &valueChanged);
@ -3195,7 +3247,7 @@ Preferences::SetPreference(const dom::Pref& aDomPref)
// needlessly, but that's ok because this case is rare.
//
if (!pref->HasDefaultValue() && !pref->HasUserValue()) {
gHashTable->Remove(prefName);
gHashTable->RemoveEntry(entry);
}
// Note: we don't have to worry about HandleDirty() because we are setting
@ -3223,9 +3275,9 @@ Preferences::GetPreferences(InfallibleTArray<dom::Pref>* aDomPrefs)
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
aDomPrefs->SetCapacity(gHashTable->Count());
aDomPrefs->SetCapacity(gHashTable->EntryCount());
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
Pref* pref = iter.Data();
Pref* pref = static_cast<PrefEntry*>(iter.Get())->mPref;
if (!pref->MustSendToContentProcesses()) {
// The pref value hasn't changed since it was initialized at startup.
@ -3236,7 +3288,7 @@ Preferences::GetPreferences(InfallibleTArray<dom::Pref>* aDomPrefs)
if (pref->HasAdvisablySizedValues()) {
dom::Pref* setting = aDomPrefs->AppendElement();
pref->ToDomPref(setting, iter.Key());
pref->ToDomPref(setting);
}
}
}
@ -4132,13 +4184,13 @@ Preferences::ClearUserInAnyProcess(const char* aPrefName)
{
NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
PrefsTable::LookupResult entry = pref_HashTableLookupInner(aPrefName);
PrefEntry* entry = pref_HashTableLookupInner(aPrefName);
Pref* pref;
if (entry && (pref = entry.Data()) && pref->HasUserValue()) {
if (entry && (pref = entry->mPref) && pref->HasUserValue()) {
pref->ClearUserValue();
if (!pref->HasDefaultValue()) {
entry.Remove();
gHashTable->RemoveEntry(entry);
}
NotifyCallbacks(aPrefName);

Просмотреть файл

@ -6012,3 +6012,8 @@ pref("layers.omtp.paint-workers", 1);
#endif
pref("layers.omtp.release-capture-on-main-thread", false);
pref("layers.omtp.dump-capture", false);
// Limits the depth of recursive conversion of data when opening
// a content to view. This is mostly intended to prevent infinite
// loops with faulty converters involved.
pref("general.document_open_conversion_depth_limit", 20);

Просмотреть файл

@ -12,6 +12,7 @@ transforms:
kind-dependencies:
- release-generate-checksums
- release-update-verify
job-defaults:
worker-type:

Просмотреть файл

@ -803,3 +803,65 @@ linux64-add-on-devel/opt:
- linux64-gcc
- linux64-rust
- linux64-sccache
linux64-stylo-only/opt:
description: "Linux64 Stylo Only Opt"
index:
product: firefox
job-name: linux64-stylo-only-opt
treeherder:
platform: linux64-stylo-only/opt
symbol: B
tier: 2
worker-type: aws-provisioner-v1/gecko-{level}-b-linux
worker:
max-run-time: 36000
run:
using: mozharness
actions: [get-secrets build check-test update]
config:
- builds/releng_base_firefox.py
- builds/releng_base_linux_64_builds.py
script: "mozharness/scripts/fx_desktop_build.py"
extra-config:
mozconfig_variant: 'stylo-only'
secrets: true
tooltool-downloads: public
need-xvfb: true
run-on-projects: ['mozilla-central', 'try', 'mozilla-inbound', 'autoland']
toolchains:
- linux64-clang
- linux64-gcc
- linux64-rust
- linux64-sccache
linux64-stylo-only/debug:
description: "Linux64 Stylo Only Debug"
index:
product: firefox
job-name: linux64-stylo-only-debug
treeherder:
platform: linux64-stylo-only/debug
symbol: B
tier: 2
worker-type: aws-provisioner-v1/gecko-{level}-b-linux
worker:
max-run-time: 36000
run:
using: mozharness
actions: [get-secrets build check-test update]
config:
- builds/releng_base_firefox.py
- builds/releng_base_linux_64_builds.py
script: "mozharness/scripts/fx_desktop_build.py"
extra-config:
mozconfig_variant: 'stylo-only-debug'
secrets: true
tooltool-downloads: public
need-xvfb: true
run-on-projects: ['mozilla-central', 'try', 'mozilla-inbound', 'autoland']
toolchains:
- linux64-clang
- linux64-gcc
- linux64-rust
- linux64-sccache

Просмотреть файл

@ -1018,8 +1018,8 @@ def make_job_description(config, tests):
if test.get('when'):
jobdesc['when'] = test['when']
elif config.params['project'] != 'try':
# for non-try branches, include SETA
elif config.params['project'] != 'try' and suite not in INCLUSIVE_COMPONENTS:
# for non-try branches and non-inclusive suites, include SETA
jobdesc['optimization'] = {'skip-unless-schedules-or-seta': schedules}
else:
# otherwise just use skip-unless-schedules

Просмотреть файл

@ -19,4 +19,9 @@ TEST(suite, test) { \
mozilla::GTestBench(#suite, #test, lambdaOrFunc); \
}
#define MOZ_GTEST_BENCH_F(suite, test, lambdaOrFunc) \
TEST_F(suite, test) { \
mozilla::GTestBench(#suite, #test, lambdaOrFunc); \
}
#endif // GTEST_MOZGTESTBENCH_H

Просмотреть файл

@ -7,7 +7,7 @@ automating user interface tests.
The in-tree test framework supports tests written in Python, using
Pythons [unittest] library. Test cases are written as a subclass
of [`MarionetteTestCase`], with child tests belonging to instance
of `MarionetteTestCase`, with child tests belonging to instance
methods that have a name starting with `test_`.
You can additionally define [`setUp`] and [`tearDown`] instance
@ -36,9 +36,8 @@ The test structure is illustrated here:
# code to execute after all tests are run
MarionetteTestCase.tearDown(self)
[remote protocol]: https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/Protocol
[remote protocol]: Protocol.html
[unittest]: https://docs.python.org/2.7/library/unittest.html
[`MarionetteTestCase`]: https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/MarionetteTestCase
[`setUp`]: https://docs.python.org/2.7/library/unittest.html#unittest.TestCase.setUp
[`setUpClass`]: https://docs.python.org/2.7/library/unittest.html#unittest.TestCase.setUpClass
[`tearDown`]: https://docs.python.org/2.7/library/unittest.html#unittest.TestCase.tearDown
@ -62,10 +61,9 @@ The API
-------
The full API documentation is found at
http://marionette-client.readthedocs.io/en/master/, but the key
objects are:
<http://marionette-client.readthedocs.io>, but the key objects are:
* [`MarionetteTestCase`]: a subclass for `unittest.TestCase`
* `MarionetteTestCase`: a subclass for `unittest.TestCase`
used as a base class for all tests to run.
* [`Marionette`]: client that speaks to Firefox.

Просмотреть файл

@ -1,75 +1,84 @@
# Selenium Atoms
Selenium atoms
==============
Marionette uses a small list of [Selenium atoms] to interact with web elements.
Initially those have been added to ensure a better reliablity due to a wider usage
inside the Selenium project. But by adding full support for the [WebDriver
specification] they will be removed step by step.
Marionette uses a small list of [Selenium atoms] to interact with
web elements. Initially those have been added to ensure a better
reliablity due to a wider usage inside the Selenium project. But
by adding full support for the [WebDriver specification] they will
be removed step by step.
Currently the following atoms are in use:
* clearElement
* getText
* isDisplayed
* isEnabled
* isSelected
- `getElementText`
- `isDisplayed`
To use one of those atoms Javascript modules will have to import [atom.js].
To use one of those atoms Javascript modules will have to import
[atom.js].
[Selenium atoms]: https://github.com/SeleniumHQ/selenium/tree/master/javascript/webdriver/atoms
[WebDriver specification]: https://w3c.github.io/webdriver/webdriver-spec.html
[atom.js]: ../atom.js
[atom.js]: https://searchfox.org/mozilla-central/source/testing/marionette/atom.js
## Update required Selenium Atoms
Update required Selenium atoms
------------------------------
In regular intervals the atoms, which are still in use, have to
be updated. Therefore they have to be exported from the Selenium
repository first, and then updated in [atom.js].
In regular intervals the atoms, which are still in use, have to be updated.
Therefore they have to be exported from the Selenium repository first, and then
updated in [atom.js].
### Export Selenium Atoms
The canonical GitHub repository for Selenium is
https://github.com/SeleniumHQ/selenium.git
https://github.com/SeleniumHQ/selenium.git
so make sure to have a local copy of it. For the cloning process it is
recommended to specify the `--depth=1` argument, so only the last changeset is
getting downloaded (which itself will already be more than 100 MB). Once the
clone is ready the export of the atoms can be triggered by running the following
commands:
so make sure to have a local copy of it. For the cloning process
it is recommended to specify the `--depth=1` argument, so only the
last changeset is getting downloaded (which itself will already be
more than 100 MB). Once the clone is ready the export of the atoms
can be triggered by running the following commands:
% cd selenium
% ./go
% python buck-out/crazy-fun/%changeset%/buck.pex build --show-output %atom%
% cd selenium
% ./go
% python buck-out/crazy-fun/%changeset%/buck.pex build --show-output %atom%
Hereby `%changeset%` corresponds to the currently used version of buck, and
`%atom%` to the atom to export. The following targets for exporting are available:
Hereby `%changeset%` corresponds to the currently used version of
buck, and `%atom%` to the atom to export. The following targets
for exporting are available:
* //javascript/webdriver/atoms:clear-element-firefox
* //javascript/webdriver/atoms:get-text-firefox
* //javascript/webdriver/atoms:is-displayed-firefox
* //javascript/webdriver/atoms:is-enabled-firefox
* //javascript/webdriver/atoms:is-selected-firefox
- `//javascript/webdriver/atoms:clear-element-firefox`
- `//javascript/webdriver/atoms:get-text-firefox`
- `//javascript/webdriver/atoms:is-displayed-firefox`
- `//javascript/webdriver/atoms:is-enabled-firefox`
- `//javascript/webdriver/atoms:is-selected-firefox`
For each of the exported atoms a file can now be found in the folder
`buck-out/gen/javascript/webdriver/atoms/`. They contain all the code including
dependencies for the atom wrapped into a single function.
`buck-out/gen/javascript/webdriver/atoms/`. They contain all the
code including dependencies for the atom wrapped into a single function.
### Update atom.js
To update the atoms for Marionette the `atoms.js` file has to be edited. For
each atom to be updated the steps as layed out below have to be performed:
1. Open the Javascript file of the exported atom. See above for its location.
2. Remove the contained license header, which can be found somewhere in the
middle of the file.
3. Update the parameters of the wrapper function (at the very top) so that those
are equal with the used parameters in `atom.js`.
4. Copy the whole content of the file, and replace the existing code for the atom
in `atom.js`.
1. Open the Javascript file of the exported atom. See above for
its location.
2. Remove the contained license header, which can be found somewhere
in the middle of the file.
3. Update the parameters of the wrapper function (at the very top)
so that those are equal with the used parameters in `atom.js`.
4. Copy the whole content of the file, and replace the existing
code for the atom in `atom.js`.
### Test the changes
To ensure that the update of the atoms doesn't cause a regression a try build
should be run including Marionette unit tests, Firefox ui tests, and all the
web-platform-tests.
To ensure that the update of the atoms doesn't cause a regression
a try build should be run including Marionette unit tests, Firefox
ui tests, and all the web-platform-tests.

Просмотреть файл

@ -5,11 +5,6 @@ Marionette
Marionette is the remote protocol that lets OOP programs communicate
with, instrument, and control Gecko.
Description
===========
Marionette is an automation driver for Mozillas Gecko engine.
It can remotely control either the UI or the internal JavaScript of
Gecko-based browsers, such as Firefox and Fennec. It can control
both the chrome and the content document, giving a high level of

Просмотреть файл

@ -15,12 +15,18 @@ from . import formatters
from .structuredlog import StructuredLogger, set_default_logger
log_formatters = {
'raw': (formatters.JSONFormatter, "Raw structured log messages"),
'unittest': (formatters.UnittestFormatter, "Unittest style output"),
'xunit': (formatters.XUnitFormatter, "xUnit compatible XML"),
'html': (formatters.HTMLFormatter, "HTML report"),
'mach': (formatters.MachFormatter, "Human-readable output"),
'tbpl': (formatters.TbplFormatter, "TBPL style log format"),
'raw': (formatters.JSONFormatter, "Raw structured log messages "
"(provided by mozlog)"),
'unittest': (formatters.UnittestFormatter, "Unittest style output "
"(provided by mozlog)"),
'xunit': (formatters.XUnitFormatter, "xUnit compatible XML "
"(povided by mozlog)"),
'html': (formatters.HTMLFormatter, "HTML report "
"(provided by mozlog)"),
'mach': (formatters.MachFormatter, "Human-readable output "
"(provided by mozlog)"),
'tbpl': (formatters.TbplFormatter, "TBPL style log format "
"(provided by mozlog)"),
'errorsummary': (formatters.ErrorSummaryFormatter, argparse.SUPPRESS),
}
@ -28,6 +34,9 @@ TEXT_FORMATTERS = ('raw', 'mach')
"""a subset of formatters for non test harnesses related applications"""
DOCS_URL = "https://firefox-source-docs.mozilla.org/mozbase/mozlog.html"
def level_filter_wrapper(formatter, level):
return handlers.LogLevelFilter(formatter, level)
@ -121,7 +130,9 @@ def add_logging_group(parser, include_formatters=None):
group_name = "Output Logging"
group_description = ("Each option represents a possible logging format "
"and takes a filename to write that format to, "
"or '-' to write to stdout.")
"or '-' to write to stdout. Some options are "
"provided by the mozlog utility; see %s "
"for extended documentation." % DOCS_URL)
if include_formatters is None:
include_formatters = list(log_formatters.keys())

Просмотреть файл

@ -0,0 +1,56 @@
<html>
<head>
<style>
div {
transform: translate(1px);
width:10px;
height:10px;
background-color:green;
display: inline-block;
}
</style>
</head>
<body id="body">
</body>
<script>
var start = null;
var divCount = 1000;
var maxIterations = 600;
for (var i = 0; i < divCount; i++) {
var div = document.createElement("div");
div.id = i;
document.getElementById("body").appendChild(div);
}
var iteration = 0;
function runFrame() {
if (document.getElementById(iteration).style.backgroundColor == "red") {
document.getElementById(iteration).style.backgroundColor = "green";
} else {
document.getElementById(iteration).style.backgroundColor = "red";
}
iteration++;
iteration = iteration % divCount;
if (--maxIterations == 0) {
var end = performance.now();
if (window.tpRecordTime) {
window.tpRecordTime(end - start, start);
}
return;
}
window.requestAnimationFrame(runFrame);
}
addEventListener("load", function() {
TalosContentProfiler.resume("displaylist_inactive_mutate.html loaded", true).then(() => {
start = performance.now();
window.requestAnimationFrame(runFrame);
});
});
</script>
<script type="text/javascript" src="chrome://talos-powers-content/content/TalosContentProfiler.js"></script>
</html>

Просмотреть файл

@ -37,9 +37,6 @@ function runFrame() {
if (window.tpRecordTime) {
window.tpRecordTime(end - start, start);
}
if (parent.reportResults) {
parent.reportResults(end - start, start);
}
return;
}

Просмотреть файл

@ -1 +1,2 @@
% http://localhost/tests/layout/benchmarks/displaylist_mutate.html
% http://localhost/tests/layout/benchmarks/displaylist_inactive_mutate.html

Просмотреть файл

@ -209,10 +209,6 @@ function RemoteFinderListener(global) {
this._finder = new Finder(global.docShell);
this._finder.addResultListener(this);
this._global = global;
this.KeyboardEvent =
global.docShell
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow).KeyboardEvent;
for (let msg of this.MESSAGES) {
global.addMessageListener(msg, this);
@ -318,7 +314,8 @@ RemoteFinderListener.prototype = {
break;
case "Finder:KeyPress":
this._finder.keyPress(new this.KeyboardEvent("keypress", data));
var KeyboardEvent = this._finder._getWindow().KeyboardEvent;
this._finder.keyPress(new KeyboardEvent("keypress", data));
break;
case "Finder:MatchesCount":

Просмотреть файл

@ -49,6 +49,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Preferences.h"
#include "mozilla/Unused.h"
#include "nsContentUtils.h"
mozilla::LazyLogModule nsURILoader::mLog("URILoader");
@ -60,6 +61,17 @@ mozilla::LazyLogModule nsURILoader::mLog("URILoader");
#define NS_PREF_DISABLE_BACKGROUND_HANDLING \
"security.exthelperapp.disable_background_handling"
static uint32_t sConvertDataLimit = 20;
static bool InitPreferences()
{
nsresult rv = mozilla::Preferences::AddUintVarCache(
&sConvertDataLimit,
"general.document_open_conversion_depth_limit",
20);
return NS_SUCCEEDED(rv);
}
/**
* The nsDocumentOpenInfo contains the state required when a single
* document is being opened in order to discover the content type...
@ -157,6 +169,11 @@ protected:
* nsIURIContentListeners.
*/
RefPtr<nsURILoader> mURILoader;
/**
* Limit of data conversion depth to prevent infinite conversion loops
*/
uint32_t mDataConversionDepthLimit;
};
NS_IMPL_ADDREF(nsDocumentOpenInfo)
@ -179,7 +196,8 @@ nsDocumentOpenInfo::nsDocumentOpenInfo(nsIInterfaceRequestor* aWindowContext,
nsURILoader* aURILoader)
: m_originalContext(aWindowContext),
mFlags(aFlags),
mURILoader(aURILoader)
mURILoader(aURILoader),
mDataConversionDepthLimit(sConvertDataLimit)
{
}
@ -625,6 +643,12 @@ nsDocumentOpenInfo::ConvertData(nsIRequest *request,
PromiseFlatCString(aSrcContentType).get(),
PromiseFlatCString(aOutContentType).get()));
if (mDataConversionDepthLimit == 0) {
LOG(("[0x%p] nsDocumentOpenInfo::ConvertData - reached the recursion limit!", this));
// This will fall back to external helper app handling.
return NS_ERROR_ABORT;
}
NS_PRECONDITION(aSrcContentType != aOutContentType,
"ConvertData called when the two types are the same!");
nsresult rv = NS_OK;
@ -648,6 +672,9 @@ nsDocumentOpenInfo::ConvertData(nsIRequest *request,
LOG((" Downstream DocumentOpenInfo would be: 0x%p", nextLink.get()));
// Decrease the conversion recursion limit by one to prevent infinite loops.
nextLink->mDataConversionDepthLimit = mDataConversionDepthLimit - 1;
// Make sure nextLink starts with the contentListener that said it wanted the
// results of this decode.
nextLink->m_contentListener = aListener;
@ -885,6 +912,9 @@ nsresult nsURILoader::OpenChannel(nsIChannel* channel,
}
}
static bool once = InitPreferences();
mozilla::Unused << once;
// we need to create a DocumentOpenInfo object which will go ahead and open
// the url and discover the content type....
RefPtr<nsDocumentOpenInfo> loader =

Просмотреть файл

@ -17,7 +17,7 @@ interface nsISerializable : nsISupports
* can't be set to default values must have been serialized by write,
* and should be read from aInputStream in the same order by this method.
*/
void read(in nsIObjectInputStream aInputStream);
[must_use] void read(in nsIObjectInputStream aInputStream);
/**
* Serialize the object implementing nsISerializable to aOutputStream, by

Просмотреть файл

@ -1188,7 +1188,7 @@ nsLocalFile::OpenNSPRFileDesc(int32_t aFlags, int32_t aMode,
NS_IMETHODIMP
nsLocalFile::OpenANSIFileDesc(const char* aMode, FILE** aResult)
{
nsresult rv = ResolveAndStat();
nsresult rv = Resolve();
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND) {
return rv;
}
@ -1210,7 +1210,7 @@ nsLocalFile::Create(uint32_t aType, uint32_t aAttributes)
return NS_ERROR_FILE_UNKNOWN_TYPE;
}
nsresult rv = ResolveAndStat();
nsresult rv = Resolve();
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND) {
return rv;
}
@ -1625,7 +1625,7 @@ typedef struct
NS_IMETHODIMP
nsLocalFile::GetVersionInfoField(const char* aField, nsAString& aResult)
{
nsresult rv = ResolveAndStat();
nsresult rv = Resolve();
if (NS_FAILED(rv)) {
return rv;
}
@ -2312,7 +2312,7 @@ nsLocalFile::SetLastModifiedTime(PRTime aLastModifiedTime)
// Check we are correctly initialized.
CHECK_mWorkingPath();
nsresult rv = ResolveAndStat();
nsresult rv = Resolve();
if (NS_FAILED(rv)) {
return rv;
}
@ -2458,7 +2458,7 @@ nsLocalFile::SetPermissions(uint32_t aPermissions)
// If true, then this will be for the target of the shortcut file,
// otherwise it will be for the shortcut file itself (i.e. the same
// results as SetPermissionsOfLink)
nsresult rv = ResolveAndStat();
nsresult rv = Resolve();
if (NS_FAILED(rv)) {
return rv;
}
@ -2547,7 +2547,7 @@ nsLocalFile::SetFileSize(int64_t aFileSize)
// Check we are correctly initialized.
CHECK_mWorkingPath();
nsresult rv = ResolveAndStat();
nsresult rv = Resolve();
if (NS_FAILED(rv)) {
return rv;
}
@ -3051,7 +3051,7 @@ nsLocalFile::GetTarget(nsAString& aResult)
return NS_ERROR_FILE_INVALID_PATH;
}
#endif
ResolveAndStat();
Resolve();
aResult = mResolvedPath;
return NS_OK;