patch 8.2.3605: cannot clear and unlinke a highlight group with hlset()

Problem:    Cannot clear and unlinke a highlight group with hlset() in a
            single call.
Solution:   Add the "force" option. (Yegappan Lakshmanan, closes #9117)
diff --git a/src/testdir/test_highlight.vim b/src/testdir/test_highlight.vim
index bc06118..37eeae8 100644
--- a/src/testdir/test_highlight.vim
+++ b/src/testdir/test_highlight.vim
@@ -1046,9 +1046,6 @@
 
 " Test for the hlset() function
 func Test_hlset()
-  let save_columns = &columns
-  let &columns = 80
-
   let lines =<< trim END
     call assert_equal(0, hlset(test_null_list()))
     call assert_equal(0, hlset([]))
@@ -1126,12 +1123,10 @@
                 \ 'standout': v:true, 'nocombine': v:true}
     call hlset([{'name': 'myhlg2', 'term': attr, 'cterm': attr, 'gui': attr}])
     VAR id2 = hlID('myhlg2')
-    VAR output =<< trim END
-      myhlg2         xxx term=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough
-                         cterm=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough
-                         gui=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough
-    END
-    call assert_equal(output, execute('highlight myhlg2')->split("\n"))
+    VAR expected = "myhlg2 xxx term=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough cterm=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough gui=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough"
+    VAR output = execute('highlight myhlg2')
+    LET output = output->split("\n")->join()->substitute('\s\+', ' ', 'g')
+    call assert_equal(expected, output)
     call assert_equal([{'id': id2, 'name': 'myhlg2', 'gui': attr,
                       \ 'term': attr, 'cterm': attr}], hlget('myhlg2'))
   END
@@ -1143,18 +1138,96 @@
     VAR attr = {'bold': v:false, 'underline': v:true, 'strikethrough': v:true}
     call hlset([{'name': 'myhlg2', 'term': attr, 'cterm': attr, 'gui': attr}])
     VAR id2 = hlID('myhlg2')
-    VAR output =<< trim END
-      myhlg2         xxx term=underline,strikethrough cterm=underline,strikethrough
-                         gui=underline,strikethrough
-    END
-    call assert_equal(output, execute('highlight myhlg2')->split("\n"))
+    VAR expected = "myhlg2 xxx term=underline,strikethrough cterm=underline,strikethrough gui=underline,strikethrough"
+    VAR output = execute('highlight myhlg2')
+    LET output = output->split("\n")->join()->substitute('\s\+', ' ', 'g')
+    call assert_equal(expected, output)
     LET attr = {'underline': v:true, 'strikethrough': v:true}
     call assert_equal([{'id': id2, 'name': 'myhlg2', 'gui': attr,
                       \ 'term': attr, 'cterm': attr}], hlget('myhlg2'))
   END
   call CheckLegacyAndVim9Success(lines)
 
-  let &columns = save_columns
+  " Test for clearing the attributes and link of a highlight group
+  let lines =<< trim END
+    highlight myhlg3 ctermbg=green guibg=green
+    highlight! default link myhlg3 ErrorMsg
+    VAR id3 = hlID('myhlg3')
+    call hlset([{'name': 'myhlg3', 'cleared': v:true, 'linksto': 'NONE'}])
+    call assert_equal([{'id': id3, 'name': 'myhlg3', 'cleared': v:true}],
+                      \ hlget('myhlg3'))
+    highlight clear hlg3
+  END
+  call CheckLegacyAndVim9Success(lines)
+
+  " Test for setting default attributes for a highlight group
+  let lines =<< trim END
+    call hlset([{'name': 'hlg4', 'ctermfg': '8'}])
+    call hlset([{'name': 'hlg4', 'default': v:true, 'ctermfg': '9'}])
+    VAR id4 = hlID('hlg4')
+    call assert_equal([{'id': id4, 'name': 'hlg4', 'ctermfg': '8'}],
+                    \ hlget('hlg4'))
+    highlight clear hlg4
+
+    call hlset([{'name': 'hlg5', 'default': v:true, 'ctermbg': '2'}])
+    call hlset([{'name': 'hlg5', 'ctermbg': '4'}])
+    VAR id5 = hlID('hlg5')
+    call assert_equal([{'id': id5, 'name': 'hlg5', 'ctermbg': '4'}],
+                    \ hlget('hlg5'))
+    highlight clear hlg5
+
+    call hlset([{'name': 'hlg6', 'linksto': 'Error'}])
+    VAR id6 = hlID('hlg6')
+    call hlset([{'name': 'hlg6', 'default': v:true, 'ctermbg': '2'}])
+    call assert_equal([{'id': id6, 'name': 'hlg6', 'linksto': 'Error'}],
+                    \ hlget('hlg6'))
+    highlight clear hlg6
+  END
+  call CheckLegacyAndVim9Success(lines)
+
+  " Test for setting default links for a highlight group
+  let lines =<< trim END
+    call hlset([{'name': 'hlg7', 'ctermfg': '5'}])
+    call hlset([{'name': 'hlg7', 'default': v:true, 'linksto': 'Search'}])
+    VAR id7 = hlID('hlg7')
+    call assert_equal([{'id': id7, 'name': 'hlg7', 'ctermfg': '5'}],
+                    \ hlget('hlg7'))
+    highlight clear hlg7
+
+    call hlset([{'name': 'hlg8', 'default': v:true, 'linksto': 'Search'}])
+    VAR id8 = hlID('hlg8')
+    call assert_equal([{'id': id8, 'name': 'hlg8', 'default': v:true,
+                    \ 'linksto': 'Search'}], hlget('hlg8'))
+    call hlset([{'name': 'hlg8', 'ctermbg': '2'}])
+    call assert_equal([{'id': id8, 'name': 'hlg8', 'ctermbg': '2'}],
+                    \ hlget('hlg8'))
+    highlight clear hlg8
+
+    highlight default link hlg9 ErrorMsg
+    VAR hlg_save = hlget('hlg9')
+    LET hlg_save[0]['name'] = 'hlg9dup'
+    call hlset(hlg_save)
+    VAR id9 = hlID('hlg9dup')
+    highlight clear hlg9dup
+    call assert_equal([{'id': id9, 'name': 'hlg9dup', 'default': v:true,
+                    \ 'linksto': 'ErrorMsg'}], hlget('hlg9dup'))
+    highlight clear hlg9
+  END
+  call CheckLegacyAndVim9Success(lines)
+
+  " Test for force creating a link to a highlight group
+  let lines =<< trim END
+    call hlset([{'name': 'hlg10', 'ctermfg': '8'}])
+    call hlset([{'name': 'hlg10', 'linksto': 'Search'}])
+    VAR id10 = hlID('hlg10')
+    call assert_equal([{'id': id10, 'name': 'hlg10', 'ctermfg': '8'}],
+                    \ hlget('hlg10'))
+    call hlset([{'name': 'hlg10', 'linksto': 'Search', 'force': v:true}])
+    call assert_equal([{'id': id10, 'name': 'hlg10', 'ctermfg': '8',
+                    \ 'linksto': 'Search'}], hlget('hlg10'))
+    highlight clear hlg10
+  END
+  call CheckLegacyAndVim9Success(lines)
 endfunc
 
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index e2b91d4..b3890ce 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -3297,6 +3297,7 @@
   CheckDefAndScriptFailure2(['sign_placelist("x")'], 'E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1')
   CheckDefAndScriptFailure2(['sign_placelist({"a": 10})'], 'E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1211: List required for argument 1')
   CheckDefExecAndScriptFailure(['sign_placelist([{"name": "MySign", "buffer": bufnr(), "lnum": ""}])'], 'E1209: Invalid value for a line number: ""')
+  assert_fails('sign_placelist([{name: "MySign", buffer: "", lnum: 1}])', 'E155:')
 enddef
 
 def Test_sign_undefine()
diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim
index 9f1cdf1..ee381ed 100644
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -1570,8 +1570,8 @@
   CheckDefExecAndScriptFailure(lines, 'E486:', 1)
 enddef
 
-" Test for the 'popuppreview' option
-def Test_popuppreview()
+" Test for the 'previewpopup' option
+def Test_previewpopup()
   set previewpopup=height:10,width:60
   pedit Xfile
   var id = popup_findpreview()