patch 9.0.1357: using null_object results in an internal error

Problem:    Using null_object results in an internal error. (Ernie Rael)
Solution:   Add instructions for pushing an object and class. (closes #12044)
diff --git a/src/errors.h b/src/errors.h
index a5df8ed..f1c36ad 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -3449,3 +3449,7 @@
 #endif
 EXTERN char e_cannot_use_color_none_did_you_mean_none[]
 	INIT(= N_("E1361: Cannot use color \"none\", did you mean \"NONE\"?"));
+#ifdef FEAT_EVAL
+EXTERN char e_cannot_use_non_null_object[]
+	INIT(= N_("E1362: Cannot use a non-null object"));
+#endif
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index 87c1d4a..3bb289b 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -186,6 +186,23 @@
   source XclassTwice.vim
 enddef
 
+def Test_returning_null_object()
+  # this was causing an internal error
+  var lines =<< trim END
+      vim9script
+
+      class BufferList
+          def Current(): any
+              return null_object
+          enddef
+      endclass
+
+      var buffers = BufferList.new()
+      echo buffers.Current()
+  END
+  v9.CheckScriptSuccess(lines)
+enddef
+
 def Test_class_interface_wrong_end()
   var lines =<< trim END
       vim9script
diff --git a/src/version.c b/src/version.c
index ffe4a85..a85b81c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1357,
+/**/
     1356,
 /**/
     1355,
diff --git a/src/vim9.h b/src/vim9.h
index 4df97c6..d9b25da 100644
--- a/src/vim9.h
+++ b/src/vim9.h
@@ -101,6 +101,8 @@
     ISN_PUSHFUNC,	// push func isn_arg.string
     ISN_PUSHCHANNEL,	// push NULL channel
     ISN_PUSHJOB,	// push NULL job
+    ISN_PUSHOBJ,	// push NULL object
+    ISN_PUSHCLASS,	// push class, uses isn_arg.class
     ISN_NEWLIST,	// push list from stack items, size is isn_arg.number
 			// -1 for null_list
     ISN_NEWDICT,	// push dict from stack items, size is isn_arg.number
@@ -518,6 +520,7 @@
 	channel_T	    *channel;
 	job_T		    *job;
 	partial_T	    *partial;
+	class_T		    *class;
 	jump_T		    jump;
 	jumparg_T	    jumparg;
 	forloop_T	    forloop;
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 638dbc5..90594ef 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1944,8 +1944,7 @@
     source_cookie_T cookie;
 
     SOURCING_LNUM = iptr->isn_lnum;
-    // Pass getsourceline to get an error for a missing ":end"
-    // command.
+    // Pass getsourceline to get an error for a missing ":end" command.
     CLEAR_FIELD(cookie);
     cookie.sourcing_lnum = iptr->isn_lnum - 1;
     if (do_cmdline(iptr->isn_arg.string,
@@ -4018,6 +4017,8 @@
 	    case ISN_PUSHFUNC:
 	    case ISN_PUSHCHANNEL:
 	    case ISN_PUSHJOB:
+	    case ISN_PUSHOBJ:
+	    case ISN_PUSHCLASS:
 		if (GA_GROW_FAILS(&ectx->ec_stack, 1))
 		    goto theend;
 		tv = STACK_TV_BOT(0);
@@ -4064,6 +4065,14 @@
 			tv->vval.v_job = NULL;
 #endif
 			break;
+		    case ISN_PUSHOBJ:
+			tv->v_type = VAR_OBJECT;
+			tv->vval.v_object = NULL;
+			break;
+		    case ISN_PUSHCLASS:
+			tv->v_type = VAR_CLASS;
+			tv->vval.v_class = iptr->isn_arg.class;
+			break;
 		    default:
 			tv->v_type = VAR_STRING;
 			tv->vval.v_string = iptr->isn_arg.string == NULL
@@ -6662,6 +6671,14 @@
 		smsg("%s%4d PUSHJOB \"no process\"", pfx, current);
 #endif
 		break;
+	    case ISN_PUSHOBJ:
+		smsg("%s%4d PUSHOBJ null", pfx, current);
+		break;
+	    case ISN_PUSHCLASS:
+		smsg("%s%4d PUSHCLASS %s", pfx, current,
+			iptr->isn_arg.class == NULL ? "null"
+				    : (char *)iptr->isn_arg.class->class_name);
+		break;
 	    case ISN_PUSHEXC:
 		smsg("%s%4d PUSH v:exception", pfx, current);
 		break;
diff --git a/src/vim9instr.c b/src/vim9instr.c
index cdf0379..4f228e4 100644
--- a/src/vim9instr.c
+++ b/src/vim9instr.c
@@ -656,6 +656,35 @@
 }
 
 /*
+ * Generate an ISN_PUSHOBJ instruction.  Object is always NULL.
+ */
+    static int
+generate_PUSHOBJ(cctx_T *cctx)
+{
+    RETURN_OK_IF_SKIP(cctx);
+    if (generate_instr_type(cctx, ISN_PUSHOBJ, &t_any) == NULL)
+	return FAIL;
+    return OK;
+}
+
+/*
+ * Generate an ISN_PUSHCLASS instruction.  "class" can be NULL.
+ */
+    static int
+generate_PUSHCLASS(cctx_T *cctx, class_T *class)
+{
+    RETURN_OK_IF_SKIP(cctx);
+    isn_T *isn = generate_instr_type(cctx, ISN_PUSHCLASS,
+				  class == NULL ? &t_any : &class->class_type);
+    if (isn == NULL)
+	return FAIL;
+    isn->isn_arg.class = class;
+    if (class != NULL)
+	++class->class_refcount;
+    return OK;
+}
+
+/*
  * Generate a PUSH instruction for "tv".
  * "tv" will be consumed or cleared.
  */
@@ -718,6 +747,17 @@
 	    generate_PUSHS(cctx, &tv->vval.v_string);
 	    tv->vval.v_string = NULL;
 	    break;
+	case VAR_OBJECT:
+	    if (tv->vval.v_object != NULL)
+	    {
+		emsg(_(e_cannot_use_non_null_object));
+		return FAIL;
+	    }
+	    generate_PUSHOBJ(cctx);
+	    break;
+	case VAR_CLASS:
+	    generate_PUSHCLASS(cctx, tv->vval.v_class);
+	    break;
 	default:
 	    siemsg("constant type %d not supported", tv->v_type);
 	    clear_tv(tv);
@@ -1937,7 +1977,8 @@
 	ret_type = &t_any;
     else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
     {
-	if (check_func_args_from_type(cctx, type, argcount, at_top, name) == FAIL)
+	if (check_func_args_from_type(cctx, type, argcount, at_top, name)
+								       == FAIL)
 	    return FAIL;
 
 	ret_type = type->tt_member;
@@ -2467,6 +2508,10 @@
 	    blob_unref(isn->isn_arg.blob);
 	    break;
 
+	case ISN_PUSHCLASS:
+	    class_unref(isn->isn_arg.class);
+	    break;
+
 	case ISN_UCALL:
 	    vim_free(isn->isn_arg.ufunc.cuf_name);
 	    break;
@@ -2659,6 +2704,7 @@
 	case ISN_PUSHF:
 	case ISN_PUSHJOB:
 	case ISN_PUSHNR:
+	case ISN_PUSHOBJ:
 	case ISN_PUSHSPEC:
 	case ISN_PUT:
 	case ISN_REDIREND: