Fix bug when using built-in list field as listField parameter to checkbox widget (#6897)

* Fix bug with checkbox widget and `list` field

The `list` field is stored as a list and frozen against modifications,
and getFieldList() returns it directly without creating a copy. So
before we modify it, we need to make a copy so we're not modifying a
frozen list. This bug doesn't manifest with custom fields, which are
stored as strings, only with the built-in `list` field.

* Fix checkboxes referencing non-existent tiddlers

This fixes the "tiddler is undefined" error when a checkbox's listField
property references a tiddler that doesn't (yet) exist.

* Better logic for checkbox listField handling

If the field contains an array, then it's almost certainly referenced
elsewhere and needs a defensive copy made. If it contained a string,
then it's safe to modify without making a defensive copy.
This commit is contained in:
Robin Munn
2022-09-22 18:52:55 +01:00
committed by GitHub
parent 50f54ba6ca
commit 51bdf60ee8
2 changed files with 47 additions and 6 deletions
+12 -5
View File
@@ -66,14 +66,14 @@ CheckboxWidget.prototype.render = function(parent,nextSibling) {
CheckboxWidget.prototype.getValue = function() {
var tiddler = this.wiki.getTiddler(this.checkboxTitle);
if(tiddler || this.checkboxFilter) {
if(this.checkboxTag) {
if(tiddler && this.checkboxTag) {
if(this.checkboxInvertTag === "yes") {
return !tiddler.hasTag(this.checkboxTag);
} else {
return tiddler.hasTag(this.checkboxTag);
}
}
if(this.checkboxField || this.checkboxIndex) {
if(tiddler && (this.checkboxField || this.checkboxIndex)) {
// Same logic applies to fields and indexes
var value;
if(this.checkboxField) {
@@ -206,11 +206,18 @@ CheckboxWidget.prototype.handleChangeEvent = function(event) {
}
// Set the list field (or index) if specified
if(this.checkboxListField || this.checkboxListIndex) {
var listContents, oldPos, newPos;
var fieldContents, listContents, oldPos, newPos;
if(this.checkboxListField) {
listContents = tiddler.getFieldList(this.checkboxListField);
fieldContents = tiddler ? tiddler.fields[this.checkboxListField] : undefined;
} else {
listContents = $tw.utils.parseStringArray(this.wiki.extractTiddlerDataItem(this.checkboxTitle,this.checkboxListIndex) || "") || [];
fieldContents = this.wiki.extractTiddlerDataItem(this.checkboxTitle,this.checkboxListIndex);
}
if($tw.utils.isArray(fieldContents)) {
// Make a copy so we can modify it without changing original that's refrenced elsewhere
listContents = fieldContents.slice(0);
} else {
listContents = $tw.utils.parseStringArray(fieldContents) || [];
// No need to copy since parseStringArray returns a fresh array, not refrenced elsewhere
}
oldPos = notValue ? listContents.indexOf(notValue) : -1;
newPos = value ? listContents.indexOf(value) : -1;