зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. a=merge on a CLOSED TREE
This commit is contained in:
Коммит
cf9f54d811
|
@ -195,7 +195,7 @@ static const DllBlockInfo gBlockedInprocDlls[] = {
|
|||
* This is the blocklist for known "bad" remote clients that instantiate a11y.
|
||||
*/
|
||||
static const char* gBlockedRemoteClients[] = {
|
||||
"tbnnotifier.exe" // Ask.com Toolbar, bug 1421018
|
||||
"tbnotifier.exe" // Ask.com Toolbar, bug 1453876
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -4397,7 +4397,9 @@ EditorBase::DeleteSelectionAndPrepareToCreateNode()
|
|||
{
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
MOZ_ASSERT(selection->GetAnchorFocusRange());
|
||||
if (NS_WARN_IF(!selection->GetAnchorFocusRange())) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!selection->GetAnchorFocusRange()->Collapsed()) {
|
||||
nsresult rv = DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
|
||||
|
|
|
@ -7784,8 +7784,7 @@ HTMLEditRules::JoinNodesSmart(nsIContent& aNodeLeft,
|
|||
}
|
||||
}
|
||||
|
||||
EditorDOMPoint ret;
|
||||
ret.SetToEndOf(&aNodeRight);
|
||||
EditorDOMPoint ret(&aNodeRight, aNodeLeft.Length());
|
||||
|
||||
// Separate join rules for differing blocks
|
||||
if (HTMLEditUtils::IsList(&aNodeLeft) || aNodeLeft.GetAsText()) {
|
||||
|
|
|
@ -250,6 +250,7 @@ skip-if = toolkit == 'android' # bug 1315898
|
|||
[test_bug1355792.html]
|
||||
[test_bug1358025.html]
|
||||
[test_bug1361008.html]
|
||||
[test_bug1361052.html]
|
||||
[test_bug1368544.html]
|
||||
[test_bug1385905.html]
|
||||
[test_bug1390562.html]
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Bug 1361052</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1361052">Mozilla Bug 1361052</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SimpleTest.waitForFocus(() => {
|
||||
var strike = document.createElement('strike');
|
||||
strike.contentEditable = true;
|
||||
document.documentElement.appendChild(strike);
|
||||
|
||||
var textarea = document.createElement('textarea');
|
||||
document.documentElement.appendChild(textarea);
|
||||
|
||||
var h5 = document.createElement('h5');
|
||||
strike.appendChild(h5);
|
||||
|
||||
textarea.setCustomValidity("A");
|
||||
document.documentElement.dir = "rtl";
|
||||
document.designMode = "on";
|
||||
document.execCommand("styleWithCSS", false, true);
|
||||
document.designMode = "off";
|
||||
textarea.reportValidity();
|
||||
document.documentElement.dir = "ltr";
|
||||
|
||||
var range = document.createRange();
|
||||
range.selectNode(h5);
|
||||
window.getSelection().addRange(range);
|
||||
|
||||
document.execCommand("inserthorizontalrule", false, null);
|
||||
ok(true, "No crash");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -145,6 +145,17 @@ def arg_to_bool(arg):
|
|||
return arg == "True"
|
||||
|
||||
|
||||
def parse_property_aliases(alias_list):
|
||||
result = []
|
||||
if alias_list:
|
||||
for alias in alias_list.split():
|
||||
(name, _, pref) = alias.partition(":")
|
||||
if name.startswith("-webkit-") and not pref:
|
||||
pref = "layout.css.prefixes.webkit"
|
||||
result.append((name, pref))
|
||||
return result
|
||||
|
||||
|
||||
class Longhand(object):
|
||||
def __init__(self, style_struct, name, spec=None, animation_value_type=None, keyword=None,
|
||||
predefined_type=None, servo_pref=None, gecko_pref=None,
|
||||
|
@ -178,8 +189,8 @@ class Longhand(object):
|
|||
self.gecko_ffi_name = gecko_ffi_name or "m" + self.camel_case
|
||||
self.cast_type = cast_type
|
||||
self.logical = arg_to_bool(logical)
|
||||
self.alias = alias.split() if alias else []
|
||||
self.extra_prefixes = extra_prefixes.split() if extra_prefixes else []
|
||||
self.alias = parse_property_aliases(alias)
|
||||
self.extra_prefixes = parse_property_aliases(extra_prefixes)
|
||||
self.boxed = arg_to_bool(boxed)
|
||||
self.flags = flags.split() if flags else []
|
||||
self.allowed_in_page_rule = arg_to_bool(allowed_in_page_rule)
|
||||
|
@ -322,8 +333,8 @@ class Shorthand(object):
|
|||
self.sub_properties = sub_properties
|
||||
assert enabled_in in ["", "ua", "chrome", "content"]
|
||||
self.enabled_in = enabled_in
|
||||
self.alias = alias.split() if alias else []
|
||||
self.extra_prefixes = extra_prefixes.split() if extra_prefixes else []
|
||||
self.alias = parse_property_aliases(alias)
|
||||
self.extra_prefixes = parse_property_aliases(extra_prefixes)
|
||||
self.allowed_in_page_rule = arg_to_bool(allowed_in_page_rule)
|
||||
self.flags = flags.split() if flags else []
|
||||
|
||||
|
@ -373,13 +384,13 @@ class Shorthand(object):
|
|||
|
||||
|
||||
class Alias(object):
|
||||
def __init__(self, name, original):
|
||||
def __init__(self, name, original, gecko_pref):
|
||||
self.name = name
|
||||
self.ident = to_rust_ident(name)
|
||||
self.camel_case = to_camel_case(self.ident)
|
||||
self.enabled_in = original.enabled_in
|
||||
self.servo_pref = original.servo_pref
|
||||
self.gecko_pref = original.gecko_pref
|
||||
self.gecko_pref = gecko_pref
|
||||
self.allowed_in_page_rule = original.allowed_in_page_rule
|
||||
self.allowed_in_keyframe_block = original.allowed_in_keyframe_block
|
||||
|
||||
|
@ -462,8 +473,12 @@ class PropertiesData(object):
|
|||
# FIXME Servo's DOM architecture doesn't support vendor-prefixed properties.
|
||||
# See servo/servo#14941.
|
||||
if self.product == "gecko":
|
||||
for prefix in property.extra_prefixes:
|
||||
property.alias.append('-%s-%s' % (prefix, property.name))
|
||||
for (prefix, pref) in property.extra_prefixes:
|
||||
# All webkit prefixed properties are currently under
|
||||
# control of this pref in Gecko currently.
|
||||
if prefix == "webkit" and not pref:
|
||||
pref = "layout.css.prefixes.webkit"
|
||||
property.alias.append(('-%s-%s' % (prefix, property.name), pref))
|
||||
|
||||
def declare_longhand(self, name, products="gecko servo", **kwargs):
|
||||
products = products.split()
|
||||
|
@ -472,7 +487,7 @@ class PropertiesData(object):
|
|||
|
||||
longhand = Longhand(self.current_style_struct, name, **kwargs)
|
||||
self.add_prefixed_aliases(longhand)
|
||||
longhand.alias = list(map(lambda x: Alias(x, longhand), longhand.alias))
|
||||
longhand.alias = list(map(lambda (x, p): Alias(x, longhand, p), longhand.alias))
|
||||
self.longhand_aliases += longhand.alias
|
||||
self.current_style_struct.longhands.append(longhand)
|
||||
self.longhands.append(longhand)
|
||||
|
@ -488,7 +503,7 @@ class PropertiesData(object):
|
|||
sub_properties = [self.longhands_by_name[s] for s in sub_properties]
|
||||
shorthand = Shorthand(name, sub_properties, *args, **kwargs)
|
||||
self.add_prefixed_aliases(shorthand)
|
||||
shorthand.alias = list(map(lambda x: Alias(x, shorthand), shorthand.alias))
|
||||
shorthand.alias = list(map(lambda (x, p): Alias(x, shorthand, p), shorthand.alias))
|
||||
self.shorthand_aliases += shorthand.alias
|
||||
self.shorthands.append(shorthand)
|
||||
return shorthand
|
||||
|
|
|
@ -226,6 +226,8 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
pub use super::overflow_x::{SpecifiedValue, parse, get_initial_value, computed_value};
|
||||
</%helpers:longhand>
|
||||
|
||||
<% transition_extra_prefixes = "moz:layout.css.prefixes.transitions webkit" %>
|
||||
|
||||
${helpers.predefined_type("transition-duration",
|
||||
"Time",
|
||||
"computed::Time::zero()",
|
||||
|
@ -234,7 +236,7 @@ ${helpers.predefined_type("transition-duration",
|
|||
vector=True,
|
||||
need_index=True,
|
||||
animation_value_type="none",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=transition_extra_prefixes,
|
||||
spec="https://drafts.csswg.org/css-transitions/#propdef-transition-duration")}
|
||||
|
||||
${helpers.predefined_type("transition-timing-function",
|
||||
|
@ -244,7 +246,7 @@ ${helpers.predefined_type("transition-timing-function",
|
|||
vector=True,
|
||||
need_index=True,
|
||||
animation_value_type="none",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=transition_extra_prefixes,
|
||||
spec="https://drafts.csswg.org/css-transitions/#propdef-transition-timing-function")}
|
||||
|
||||
${helpers.predefined_type(
|
||||
|
@ -257,7 +259,7 @@ ${helpers.predefined_type(
|
|||
need_index=True,
|
||||
needs_context=False,
|
||||
animation_value_type="none",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=transition_extra_prefixes,
|
||||
spec="https://drafts.csswg.org/css-transitions/#propdef-transition-property",
|
||||
)}
|
||||
|
||||
|
@ -268,10 +270,12 @@ ${helpers.predefined_type("transition-delay",
|
|||
vector=True,
|
||||
need_index=True,
|
||||
animation_value_type="none",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=transition_extra_prefixes,
|
||||
spec="https://drafts.csswg.org/css-transitions/#propdef-transition-delay")}
|
||||
|
||||
|
||||
<% animation_extra_prefixes = "moz:layout.css.prefixes.animations webkit" %>
|
||||
|
||||
${helpers.predefined_type(
|
||||
"animation-name",
|
||||
"AnimationName",
|
||||
|
@ -280,7 +284,7 @@ ${helpers.predefined_type(
|
|||
vector=True,
|
||||
need_index=True,
|
||||
animation_value_type="none",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=animation_extra_prefixes,
|
||||
allowed_in_keyframe_block=False,
|
||||
spec="https://drafts.csswg.org/css-animations/#propdef-animation-name",
|
||||
)}
|
||||
|
@ -293,7 +297,7 @@ ${helpers.predefined_type("animation-duration",
|
|||
vector=True,
|
||||
need_index=True,
|
||||
animation_value_type="none",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=animation_extra_prefixes,
|
||||
spec="https://drafts.csswg.org/css-transitions/#propdef-transition-duration")}
|
||||
|
||||
// animation-timing-function is the exception to the rule for allowed_in_keyframe_block:
|
||||
|
@ -305,7 +309,7 @@ ${helpers.predefined_type("animation-timing-function",
|
|||
vector=True,
|
||||
need_index=True,
|
||||
animation_value_type="none",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=animation_extra_prefixes,
|
||||
allowed_in_keyframe_block=True,
|
||||
spec="https://drafts.csswg.org/css-transitions/#propdef-animation-timing-function")}
|
||||
|
||||
|
@ -317,7 +321,7 @@ ${helpers.predefined_type(
|
|||
vector=True,
|
||||
need_index=True,
|
||||
animation_value_type="none",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=animation_extra_prefixes,
|
||||
allowed_in_keyframe_block=False,
|
||||
spec="https://drafts.csswg.org/css-animations/#propdef-animation-iteration-count",
|
||||
)}
|
||||
|
@ -330,7 +334,7 @@ ${helpers.single_keyword("animation-direction",
|
|||
vector=True,
|
||||
gecko_enum_prefix="PlaybackDirection",
|
||||
custom_consts=animation_direction_custom_consts,
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=animation_extra_prefixes,
|
||||
spec="https://drafts.csswg.org/css-animations/#propdef-animation-direction",
|
||||
allowed_in_keyframe_block=False)}
|
||||
|
||||
|
@ -339,7 +343,7 @@ ${helpers.single_keyword("animation-play-state",
|
|||
need_index=True,
|
||||
animation_value_type="none",
|
||||
vector=True,
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=animation_extra_prefixes,
|
||||
spec="https://drafts.csswg.org/css-animations/#propdef-animation-play-state",
|
||||
allowed_in_keyframe_block=False)}
|
||||
|
||||
|
@ -349,7 +353,7 @@ ${helpers.single_keyword("animation-fill-mode",
|
|||
animation_value_type="none",
|
||||
vector=True,
|
||||
gecko_enum_prefix="FillMode",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=animation_extra_prefixes,
|
||||
spec="https://drafts.csswg.org/css-animations/#propdef-animation-fill-mode",
|
||||
allowed_in_keyframe_block=False)}
|
||||
|
||||
|
@ -360,7 +364,7 @@ ${helpers.predefined_type("animation-delay",
|
|||
vector=True,
|
||||
need_index=True,
|
||||
animation_value_type="none",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=animation_extra_prefixes,
|
||||
spec="https://drafts.csswg.org/css-animations/#propdef-animation-delay",
|
||||
allowed_in_keyframe_block=False)}
|
||||
|
||||
|
@ -397,9 +401,11 @@ ${helpers.predefined_type(
|
|||
allow_empty="NotInitial"
|
||||
)}
|
||||
|
||||
<% transform_extra_prefixes = "moz:layout.css.prefixes.transforms webkit" %>
|
||||
|
||||
${helpers.predefined_type("transform", "Transform",
|
||||
"generics::transform::Transform::none()",
|
||||
extra_prefixes="webkit moz",
|
||||
extra_prefixes=transform_extra_prefixes,
|
||||
animation_value_type="ComputedValue",
|
||||
gecko_ffi_name="mSpecifiedTransform",
|
||||
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
|
||||
|
@ -517,7 +523,7 @@ ${helpers.predefined_type(
|
|||
"computed::Perspective::none()",
|
||||
gecko_ffi_name="mChildPerspective",
|
||||
spec="https://drafts.csswg.org/css-transforms/#perspective",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=transform_extra_prefixes,
|
||||
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
|
||||
animation_value_type="AnimatedPerspective",
|
||||
servo_restyle_damage = "reflow_out_of_flow",
|
||||
|
@ -527,7 +533,7 @@ ${helpers.predefined_type("perspective-origin",
|
|||
"position::Position",
|
||||
"computed::position::Position::center()",
|
||||
boxed=True,
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=transform_extra_prefixes,
|
||||
spec="https://drafts.csswg.org/css-transforms-2/#perspective-origin-property",
|
||||
animation_value_type="ComputedValue",
|
||||
servo_restyle_damage = "reflow_out_of_flow")}
|
||||
|
@ -535,7 +541,7 @@ ${helpers.predefined_type("perspective-origin",
|
|||
${helpers.single_keyword("backface-visibility",
|
||||
"visible hidden",
|
||||
spec="https://drafts.csswg.org/css-transforms/#backface-visibility-property",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=transform_extra_prefixes,
|
||||
animation_value_type="discrete")}
|
||||
|
||||
${helpers.single_keyword("transform-box",
|
||||
|
@ -553,7 +559,7 @@ ${helpers.predefined_type(
|
|||
"computed::TransformStyle::" + ("Auto" if product == "servo" else "Flat"),
|
||||
spec="https://drafts.csswg.org/css-transforms-2/#transform-style-property",
|
||||
needs_context=False,
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=transform_extra_prefixes,
|
||||
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
|
||||
animation_value_type="discrete",
|
||||
servo_restyle_damage = "reflow_out_of_flow",
|
||||
|
@ -563,7 +569,7 @@ ${helpers.predefined_type("transform-origin",
|
|||
"TransformOrigin",
|
||||
"computed::TransformOrigin::initial_value()",
|
||||
animation_value_type="ComputedValue",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes=transform_extra_prefixes,
|
||||
gecko_ffi_name="mTransformOrigin",
|
||||
boxed=True,
|
||||
spec="https://drafts.csswg.org/css-transforms/#transform-origin-property",
|
||||
|
|
|
@ -73,7 +73,7 @@ ${helpers.single_keyword("column-span", "none all",
|
|||
products="gecko", animation_value_type="discrete",
|
||||
gecko_pref="layout.css.column-span.enabled",
|
||||
spec="https://drafts.csswg.org/css-multicol/#propdef-column-span",
|
||||
extra_prefixes="moz")}
|
||||
extra_prefixes="moz:layout.css.column-span.enabled")}
|
||||
|
||||
${helpers.single_keyword("column-rule-style",
|
||||
"none hidden dotted dashed solid double groove ridge inset outset",
|
||||
|
|
|
@ -150,7 +150,7 @@ ${helpers.predefined_type("font-feature-settings",
|
|||
products="gecko",
|
||||
initial_value="computed::FontFeatureSettings::normal()",
|
||||
initial_specified_value="specified::FontFeatureSettings::normal()",
|
||||
extra_prefixes="moz",
|
||||
extra_prefixes="moz:layout.css.prefixes.font-features",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings")}
|
||||
|
@ -178,7 +178,7 @@ ${helpers.predefined_type("font-language-override",
|
|||
initial_value="computed::FontLanguageOverride::zero()",
|
||||
initial_specified_value="specified::FontLanguageOverride::normal()",
|
||||
animation_value_type="discrete",
|
||||
extra_prefixes="moz",
|
||||
extra_prefixes="moz:layout.css.prefixes.font-features",
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override")}
|
||||
|
||||
|
|
|
@ -57,12 +57,14 @@ ${helpers.predefined_type(
|
|||
// Flex container properties
|
||||
${helpers.single_keyword("flex-direction", "row row-reverse column column-reverse",
|
||||
spec="https://drafts.csswg.org/css-flexbox/#flex-direction-property",
|
||||
extra_prefixes="webkit", animation_value_type="discrete",
|
||||
extra_prefixes="webkit",
|
||||
animation_value_type="discrete",
|
||||
servo_restyle_damage = "reflow")}
|
||||
|
||||
${helpers.single_keyword("flex-wrap", "nowrap wrap wrap-reverse",
|
||||
spec="https://drafts.csswg.org/css-flexbox/#flex-wrap-property",
|
||||
extra_prefixes="webkit", animation_value_type="discrete",
|
||||
extra_prefixes="webkit",
|
||||
animation_value_type="discrete",
|
||||
servo_restyle_damage = "reflow")}
|
||||
|
||||
% if product == "servo":
|
||||
|
@ -267,7 +269,7 @@ ${helpers.predefined_type(
|
|||
|
||||
${helpers.single_keyword("box-sizing",
|
||||
"content-box border-box",
|
||||
extra_prefixes="moz webkit",
|
||||
extra_prefixes="moz:layout.css.prefixes.box-sizing webkit",
|
||||
spec="https://drafts.csswg.org/css-ui/#propdef-box-sizing",
|
||||
gecko_enum_prefix="StyleBoxSizing",
|
||||
custom_consts={ "content-box": "Content", "border-box": "Border" },
|
||||
|
|
|
@ -246,7 +246,8 @@ pub fn parse_border<'i, 't>(
|
|||
|
||||
<%helpers:shorthand name="border-image" sub_properties="border-image-outset
|
||||
border-image-repeat border-image-slice border-image-source border-image-width"
|
||||
extra_prefixes="moz webkit" spec="https://drafts.csswg.org/css-backgrounds-3/#border-image">
|
||||
extra_prefixes="moz:layout.css.prefixes.border-image webkit"
|
||||
spec="https://drafts.csswg.org/css-backgrounds-3/#border-image">
|
||||
use properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
|
||||
use properties::longhands::{border_image_source, border_image_width};
|
||||
|
||||
|
|
|
@ -117,7 +117,8 @@ macro_rules! try_parse_one {
|
|||
};
|
||||
}
|
||||
|
||||
<%helpers:shorthand name="transition" extra_prefixes="moz webkit"
|
||||
<%helpers:shorthand name="transition"
|
||||
extra_prefixes="moz:layout.css.prefixes.transitions webkit"
|
||||
sub_properties="transition-property transition-duration
|
||||
transition-timing-function
|
||||
transition-delay"
|
||||
|
@ -257,7 +258,8 @@ macro_rules! try_parse_one {
|
|||
}
|
||||
</%helpers:shorthand>
|
||||
|
||||
<%helpers:shorthand name="animation" extra_prefixes="moz webkit"
|
||||
<%helpers:shorthand name="animation"
|
||||
extra_prefixes="moz:layout.css.prefixes.animations webkit"
|
||||
sub_properties="animation-name animation-duration
|
||||
animation-timing-function animation-delay
|
||||
animation-iteration-count animation-direction
|
||||
|
|
|
@ -475,6 +475,12 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"editor/joining_nodes.html": [
|
||||
[
|
||||
"/_mozilla/editor/joining_nodes.html",
|
||||
{}
|
||||
]
|
||||
],
|
||||
"fetch/api/redirect/redirect-referrer.https.html": [
|
||||
[
|
||||
"/_mozilla/fetch/api/redirect/redirect-referrer.https.html",
|
||||
|
@ -1032,6 +1038,10 @@
|
|||
"06948dbf72160a7de5a0baaa2f6cf1bb54fbeb8f",
|
||||
"testharness"
|
||||
],
|
||||
"editor/joining_nodes.html": [
|
||||
"048cf7d99acdecb927f97c4554c4d04ca8b15a8a",
|
||||
"testharness"
|
||||
],
|
||||
"fetch/api/redirect/redirect-referrer-mixed-content.js": [
|
||||
"f9d7ec9cf9fa8c847e45664b05482e3f8c191385",
|
||||
"support"
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
[joining_nodes.html]
|
||||
type: testharness
|
||||
[Joining <dt> and <dd> nodes, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <dt> and <dd> nodes, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <dd> and <dt> nodes, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <dd> and <dt> nodes, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <h1> and <p> elements, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <h1> and <p> elements, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <h2> and <p> elements, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <h2> and <p> elements, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <h3> and <p> elements, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <h3> and <p> elements, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <h4> and <p> elements, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <h4> and <p> elements, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <h5> and <p> elements, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <h5> and <p> elements, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <h6> and <p> elements, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <h6> and <p> elements, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <p> and <h1> elements, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <p> and <h1> elements, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <p> and <h2> elements, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <p> and <h2> elements, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <p> and <h3> elements, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <p> and <h3> elements, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <p> and <h4> elements, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <p> and <h4> elements, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <p> and <h5> elements, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <p> and <h5> elements, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <p> and <h6> elements, delete command]
|
||||
expected: FAIL
|
||||
|
||||
[Joining <p> and <h6> elements, forwarddelete command]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,256 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>Joining nodes with delete/forwardDelete command</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
(function() {
|
||||
const kTests = [
|
||||
{ description: "Joining text nodes separated by <br>",
|
||||
innerHTML: "<p>foo bar<br id=\"separator\">baz</p>",
|
||||
expectedInnerHTML: "<p>foo barbaz</p>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
// XXX Attributes of right <li> element are cloned but this may not be expected behavior.
|
||||
{ description: "Joining <li> nodes in <ul>",
|
||||
innerHTML: "<ul><li>foo bar</li><li id=\"separator\">baz</li></ul>",
|
||||
expectedInnerHTML: "<ul><li id=\"separator\">foo barbaz</li></ul>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
// XXX Attributes of right <li> element are cloned but this may not be expected behavior.
|
||||
{ description: "Joining <li> nodes in <ol>",
|
||||
innerHTML: "<ol><li>foo bar</li><li id=\"separator\">baz</li></ol>",
|
||||
expectedInnerHTML: "<ol><li id=\"separator\">foo barbaz</li></ol>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <dt> and <dd> nodes",
|
||||
innerHTML: "<dl><dt>foo bar</dt><dd id=\"separator\">baz</dd></dl>",
|
||||
expectedInnerHTML: "<dl><dt>foo barbaz</dt></dl>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <dd> and <dt> nodes",
|
||||
innerHTML: "<dl><dd>foo bar</dd><dt id=\"separator\">baz</dt></dl>",
|
||||
expectedInnerHTML: "<dl><dd>foo barbaz</dd></dl>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
// XXX Attributes of right <p> element are cloned but this may not be expected behavior.
|
||||
{ description: "Joining <p> elements",
|
||||
innerHTML: "<p>foo bar</p><p id=\"separator\">baz</p>",
|
||||
expectedInnerHTML: "<p id=\"separator\">foo barbaz</p>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
// XXX Attributes of right <div> element are cloned but this may not be expected behavior.
|
||||
{ description: "Joining <div> elements",
|
||||
innerHTML: "<div>foo bar</div><div id=\"separator\">baz</div>",
|
||||
expectedInnerHTML: "<div id=\"separator\">foo barbaz</div>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <h1> and <p> elements",
|
||||
innerHTML: "<h1>foo bar</h1><p id=\"separator\">baz</p>",
|
||||
expectedInnerHTML: "<h1>foo barbaz</h1>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <h2> and <p> elements",
|
||||
innerHTML: "<h2>foo bar</h2><p id=\"separator\">baz</p>",
|
||||
expectedInnerHTML: "<h2>foo barbaz</h2>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <h3> and <p> elements",
|
||||
innerHTML: "<h3>foo bar</h3><p id=\"separator\">baz</p>",
|
||||
expectedInnerHTML: "<h3>foo barbaz</h3>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <h4> and <p> elements",
|
||||
innerHTML: "<h4>foo bar</h4><p id=\"separator\">baz</p>",
|
||||
expectedInnerHTML: "<h4>foo barbaz</h4>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <h5> and <p> elements",
|
||||
innerHTML: "<h5>foo bar</h5><p id=\"separator\">baz</p>",
|
||||
expectedInnerHTML: "<h5>foo barbaz</h5>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <h6> and <p> elements",
|
||||
innerHTML: "<h6>foo bar</h6><p id=\"separator\">baz</p>",
|
||||
expectedInnerHTML: "<h6>foo barbaz</h6>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <p> and <h1> elements",
|
||||
innerHTML: "<p>foo bar</p><h1 id=\"separator\">baz</h1>",
|
||||
expectedInnerHTML: "<p>foo barbaz</p>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <p> and <h2> elements",
|
||||
innerHTML: "<p>foo bar</p><h2 id=\"separator\">baz</h2>",
|
||||
expectedInnerHTML: "<p>foo barbaz</p>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <p> and <h3> elements",
|
||||
innerHTML: "<p>foo bar</p><h3 id=\"separator\">baz</h3>",
|
||||
expectedInnerHTML: "<p>foo barbaz</p>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <p> and <h4> elements",
|
||||
innerHTML: "<p>foo bar</p><h4 id=\"separator\">baz</h4>",
|
||||
expectedInnerHTML: "<p>foo barbaz</p>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <p> and <h5> elements",
|
||||
innerHTML: "<p>foo bar</p><h5 id=\"separator\">baz</h5>",
|
||||
expectedInnerHTML: "<p>foo barbaz</p>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
{ description: "Joining <p> and <h6> elements",
|
||||
innerHTML: "<p>foo bar</p><h6 id=\"separator\">baz</h6>",
|
||||
expectedInnerHTML: "<p>foo barbar</p>",
|
||||
expectedSelectionRange: function (editor) {
|
||||
return { collapsed: true,
|
||||
startContainer: editor.firstChild.firstChild,
|
||||
startOffset: 7 };
|
||||
}, },
|
||||
];
|
||||
|
||||
document.body.innerHTML = "<div id=\"editor\" contenteditable></div>";
|
||||
let editor = document.getElementById("editor");
|
||||
editor.focus();
|
||||
let selection = document.getSelection();
|
||||
|
||||
for (const kTest of kTests) {
|
||||
editor.innerHTML = kTest.innerHTML;
|
||||
let separator = document.getElementById("separator");
|
||||
function getFirstLeafNode(node) {
|
||||
for (; node.firstChild; node = node.firstChild) {
|
||||
}
|
||||
return node;
|
||||
}
|
||||
if (separator.nodeName.toLowerCase() == "br") {
|
||||
if (separator.nextSibling) {
|
||||
selection.collapse(getFirstLeafNode(separator.nextSibling), 0);
|
||||
} else {
|
||||
selection.collapse(separator.parentNode,
|
||||
separator.parentNode.childNodes.length);
|
||||
}
|
||||
} else {
|
||||
selection.collapse(getFirstLeafNode(separator), 0);
|
||||
}
|
||||
test(function () {
|
||||
document.execCommand("delete", false);
|
||||
assert_equals(editor.innerHTML, kTest.expectedInnerHTML);
|
||||
const kExpectedSelectionRange = kTest.expectedSelectionRange(editor);
|
||||
let range = selection.getRangeAt(0);
|
||||
assert_equals(range.collapsed, kExpectedSelectionRange.collapsed);
|
||||
assert_equals(range.startContainer, kExpectedSelectionRange.startContainer);
|
||||
assert_equals(range.startOffset, kExpectedSelectionRange.startOffset);
|
||||
if (kExpectedSelectionRange.collapsed) {
|
||||
assert_equals(range.endContainer, kExpectedSelectionRange.startContainer);
|
||||
assert_equals(range.endOffset, kExpectedSelectionRange.startOffset);
|
||||
} else {
|
||||
assert_equals(range.endContainer, kExpectedSelectionRange.endContainer);
|
||||
assert_equals(range.endOffset, kExpectedSelectionRange.endOffset);
|
||||
}
|
||||
}, kTest.description + ", delete command");
|
||||
|
||||
editor.innerHTML = kTest.innerHTML;
|
||||
separator = document.getElementById("separator");
|
||||
function getLastLeafNode(node) {
|
||||
for (; node.lastChild; node = node.lastChild) {
|
||||
}
|
||||
return node;
|
||||
}
|
||||
function getLength(node) {
|
||||
if (node.length !== undefined) {
|
||||
return node.length;
|
||||
}
|
||||
return node.childNodes.length;
|
||||
}
|
||||
if (separator.previousSibling) {
|
||||
let lastLeafNode = getLastLeafNode(separator.previousSibling);
|
||||
selection.collapse(lastLeafNode, getLength(lastLeafNode));
|
||||
} else {
|
||||
selection.collapse(separator.parentNode, 0);
|
||||
}
|
||||
test(function () {
|
||||
try {
|
||||
document.execCommand("forwarddelete", false);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
assert_equals(editor.innerHTML, kTest.expectedInnerHTML);
|
||||
const kExpectedSelectionRange = kTest.expectedSelectionRange(editor);
|
||||
let range = selection.getRangeAt(0);
|
||||
assert_equals(range.collapsed, kExpectedSelectionRange.collapsed);
|
||||
assert_equals(range.startContainer, kExpectedSelectionRange.startContainer);
|
||||
assert_equals(range.startOffset, kExpectedSelectionRange.startOffset);
|
||||
if (kExpectedSelectionRange.collapsed) {
|
||||
assert_equals(range.endContainer, kExpectedSelectionRange.startContainer);
|
||||
assert_equals(range.endOffset, kExpectedSelectionRange.startOffset);
|
||||
} else {
|
||||
assert_equals(range.endContainer, kExpectedSelectionRange.endContainer);
|
||||
assert_equals(range.endOffset, kExpectedSelectionRange.endOffset);
|
||||
}
|
||||
}, kTest.description + ", forwarddelete command");
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче