Merge pull request #2274 from keymanapp/web-2261-nul-context-replacement

[Web] Bounds-check on context deletion from keyboard rules
This commit is contained in:
Joshua Horton 2019-11-06 09:52:36 +07:00 • committed by GitHub
commit fde4881f34
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 47 additions and 1 deletions

View file

@ -144,6 +144,11 @@ namespace com.keyman.dom {
let start = this.getCarets().start;
// Bounds-check on the number of chars to delete.
if(dn > start.offset) {
dn = start.offset;
}
if(start.node.nodeType != 3) {
console.warn("Deletion of characters requested without available context!");
return; // No context to delete characters from.

View file

@ -150,6 +150,11 @@ namespace com.keyman.dom {
let start = this.getCarets().start;
// Bounds-check on the number of chars to delete.
if(dn > start.offset) {
dn = start.offset;
}
if(start.node.nodeType != 3) {
console.warn("Deletion of characters requested without available context!");
return; // No context to delete characters from.

View file

@ -113,6 +113,10 @@ namespace com.keyman.dom {
let curText = this.getTextBeforeCaret();
let caret = this.getCaret();
if(dn > caret) {
dn = caret;
}
this.adjustDeadkeys(-dn);
this.setTextBeforeCaret(curText.kmwSubstring(0, this.getCaret() - dn));
this.setCaret(caret - dn);

View file

@ -141,6 +141,10 @@ namespace com.keyman.dom {
let curText = this.getTextBeforeCaret();
let caret = this.getCaret();
if(dn > caret) {
dn = caret;
}
this.adjustDeadkeys(-dn);
this.setTextBeforeCaret(curText.kmwSubstring(0, this.getCaret() - dn));
this.setCaret(caret - dn);

View file

@ -50,6 +50,9 @@ namespace com.keyman.dom {
deleteCharsBeforeCaret(dn: number): void {
if(dn > 0) {
let curText = this.getTextBeforeCaret();
if(this.getDeadkeyCaret() < dn) {
dn = this.getDeadkeyCaret();
}
this.adjustDeadkeys(-dn);
this.root.setTextBeforeCaret(curText.kmwSubstring(0, this.root.getTextCaret() - dn));
}

View file

@ -842,7 +842,9 @@ namespace com.keyman.text {
// We want to control exactly which deadkeys get removed.
if(dn > 0) {
context = this._BuildExtendedContext(dn, dn, outputTarget);
for(var i=0; i < context.deadContext.length; i++) {
let nulCount = 0;
for(var i=0; i < context.valContext.length; i++) {
var dk = context.deadContext[i];
if(dk) {
@ -851,8 +853,18 @@ namespace com.keyman.text {
// Reduce our reported context size.
dn--;
} else if(context.valContext[i] == "\uFFFE") {
// Count any `nul` sentinels that would contribute to our deletion count.
nulCount++;
}
}
// Prevent attempts to delete nul sentinels, as they don't exist in the actual context.
// (Addresses regression from KMW v 12.0 paired with Developer bug through same version)
let contextLength = context.valContext.length - nulCount;
if(dn > contextLength) {
dn = contextLength;
}
}
// If a matched deadkey hasn't been deleted, we don't WANT to delete it.

View file

@ -329,6 +329,9 @@ namespace com.keyman.text {
deleteCharsBeforeCaret(dn: number): void {
if(dn >= 0) {
if(dn > this.caretIndex) {
dn = this.caretIndex;
}
this.text = this.text.kmwSubstr(0, this.caretIndex - dn) + this.getTextAfterCaret();
this.caretIndex -= dn;
}

View file

@ -31,6 +31,7 @@ if(typeof InterfaceTests == 'undefined') {
InterfaceTests.Input.resetWithText = function(pair, string) {
pair.elem.value = string;
pair.wrapper.invalidateSelection();
pair.elem.setSelectionRange(0, 0);
}
@ -76,6 +77,7 @@ if(typeof InterfaceTests == 'undefined') {
InterfaceTests.TextArea.resetWithText = function(pair, string) {
pair.elem.value = string;
pair.wrapper.invalidateSelection();
pair.elem.setSelectionRange(0, 0);
}
@ -803,6 +805,14 @@ if(typeof InterfaceTests == 'undefined') {
pair.wrapper.deleteCharsBeforeCaret(2);
assert.equal(pair.wrapper.getText(), Apple.mixed.substr(0, 1) + Apple.mixed.substr(4), "Error deleting context chars from a mixed SMP string");
String.kmwEnableSupplementaryPlane(false);
String.kmwEnableSupplementaryPlane(false);
testObj.resetWithText(pair, Apple.normal);
testObj.setCaret(pair, 4);
pair.wrapper.deleteCharsBeforeCaret(7);
assert.equal(pair.wrapper.getText(), "e", "Bounds-check on deletion range failed; context improperly deleted.");
String.kmwEnableSupplementaryPlane(false);
pair.wrapper.invalidateSelection();
}
InterfaceTests.Tests.deleteCharsBeforeCaretWithSelection = function(testObj) {