Mercurial > vim
comparison src/if_lua.c @ 16028:8ad2cda3757d v8.1.1019
patch 8.1.1019: Lua: may garbage collect function reference in use
commit https://github.com/vim/vim/commit/4eefe47ea4b6bf958617e924f52bc7a409cfb0ed
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Mar 19 21:59:19 2019 +0100
patch 8.1.1019: Lua: may garbage collect function reference in use
Problem: Lua: may garbage collect function reference in use.
Solution: Keep the function name instead of the typeval. Make luaV_setref()
handle funcref objects. (Ozaki Kiichi, closes #4127)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 19 Mar 2019 22:00:07 +0100 |
parents | 3b524e8110ab |
children | a2f0e93a5857 |
comparison
equal
deleted
inserted
replaced
16027:d9cbab38f941 | 16028:8ad2cda3757d |
---|---|
27 typedef buf_T *luaV_Buffer; | 27 typedef buf_T *luaV_Buffer; |
28 typedef win_T *luaV_Window; | 28 typedef win_T *luaV_Window; |
29 typedef dict_T *luaV_Dict; | 29 typedef dict_T *luaV_Dict; |
30 typedef list_T *luaV_List; | 30 typedef list_T *luaV_List; |
31 typedef struct { | 31 typedef struct { |
32 typval_T tv; // funcref | 32 char_u *name; // funcref |
33 typval_T args; | |
34 dict_T *self; // selfdict | 33 dict_T *self; // selfdict |
35 } luaV_Funcref; | 34 } luaV_Funcref; |
36 typedef void (*msgfunc_T)(char_u *); | 35 typedef void (*msgfunc_T)(char_u *); |
37 | 36 |
38 static const char LUAVIM_DICT[] = "dict"; | 37 static const char LUAVIM_DICT[] = "dict"; |
67 luaL_error(L, msg ": cannot convert value"); \ | 66 luaL_error(L, msg ": cannot convert value"); \ |
68 } while (0) | 67 } while (0) |
69 | 68 |
70 static luaV_List *luaV_pushlist(lua_State *L, list_T *lis); | 69 static luaV_List *luaV_pushlist(lua_State *L, list_T *lis); |
71 static luaV_Dict *luaV_pushdict(lua_State *L, dict_T *dic); | 70 static luaV_Dict *luaV_pushdict(lua_State *L, dict_T *dic); |
72 static luaV_Funcref *luaV_pushfuncref(lua_State *L, typval_T *tv); | 71 static luaV_Funcref *luaV_pushfuncref(lua_State *L, char_u *name); |
73 | 72 |
74 #if LUA_VERSION_NUM <= 501 | 73 #if LUA_VERSION_NUM <= 501 |
75 #define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n) | 74 #define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n) |
76 #define luaL_typeerror luaL_typerror | 75 #define luaL_typeerror luaL_typerror |
77 #else | 76 #else |
441 } | 440 } |
442 #endif | 441 #endif |
443 | 442 |
444 #if LUA_VERSION_NUM > 501 | 443 #if LUA_VERSION_NUM > 501 |
445 static int | 444 static int |
446 luaL_typeerror (lua_State *L, int narg, const char *tname) | 445 luaL_typeerror(lua_State *L, int narg, const char *tname) |
447 { | 446 { |
448 const char *msg = lua_pushfstring(L, "%s expected, got %s", | 447 const char *msg = lua_pushfstring(L, "%s expected, got %s", |
449 tname, luaL_typename(L, narg)); | 448 tname, luaL_typename(L, narg)); |
450 return luaL_argerror(L, narg, msg); | 449 return luaL_argerror(L, narg, msg); |
451 } | 450 } |
538 lua_pushinteger(L, (int) tv->vval.v_number); | 537 lua_pushinteger(L, (int) tv->vval.v_number); |
539 else | 538 else |
540 lua_pushnil(L); | 539 lua_pushnil(L); |
541 break; | 540 break; |
542 case VAR_FUNC: | 541 case VAR_FUNC: |
543 luaV_pushfuncref(L, tv); | 542 luaV_pushfuncref(L, tv->vval.v_string); |
544 break; | 543 break; |
545 default: | 544 default: |
546 lua_pushnil(L); | 545 lua_pushnil(L); |
547 } | 546 } |
548 } | 547 } |
608 /* check funcref */ | 607 /* check funcref */ |
609 luaV_getfield(L, LUAVIM_FUNCREF); | 608 luaV_getfield(L, LUAVIM_FUNCREF); |
610 if (lua_rawequal(L, -1, -4)) | 609 if (lua_rawequal(L, -1, -4)) |
611 { | 610 { |
612 luaV_Funcref *f = (luaV_Funcref *) p; | 611 luaV_Funcref *f = (luaV_Funcref *) p; |
613 copy_tv(&f->tv, tv); | 612 func_ref(f->name); |
613 tv->v_type = VAR_FUNC; | |
614 tv->vval.v_string = vim_strsave(f->name); | |
614 lua_pop(L, 4); /* MTs */ | 615 lua_pop(L, 4); /* MTs */ |
615 break; | 616 break; |
616 } | 617 } |
617 lua_pop(L, 4); /* MTs */ | 618 lua_pop(L, 4); /* MTs */ |
618 } | 619 } |
691 lua_pop(L, 2); /* original and modified strings */ | 692 lua_pop(L, 2); /* original and modified strings */ |
692 } | 693 } |
693 | 694 |
694 #define luaV_newtype(typ,tname,luatyp,luatname) \ | 695 #define luaV_newtype(typ,tname,luatyp,luatname) \ |
695 static luatyp * \ | 696 static luatyp * \ |
696 luaV_new##tname (lua_State *L, typ *obj) \ | 697 luaV_new##tname(lua_State *L, typ *obj) \ |
697 { \ | 698 { \ |
698 luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \ | 699 luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \ |
699 *o = obj; \ | 700 *o = obj; \ |
700 luaV_setudata(L, obj); /* cache[obj] = udata */ \ | 701 luaV_setudata(L, obj); /* cache[obj] = udata */ \ |
701 luaV_getfield(L, luatname); \ | 702 luaV_getfield(L, luatname); \ |
723 return o; \ | 724 return o; \ |
724 } | 725 } |
725 | 726 |
726 #define luaV_type_tostring(tname,luatname) \ | 727 #define luaV_type_tostring(tname,luatname) \ |
727 static int \ | 728 static int \ |
728 luaV_##tname##_tostring (lua_State *L) \ | 729 luaV_##tname##_tostring(lua_State *L) \ |
729 { \ | 730 { \ |
730 lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \ | 731 lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \ |
731 return 1; \ | 732 return 1; \ |
732 } | 733 } |
733 | 734 |
734 /* ======= List type ======= */ | 735 /* ======= List type ======= */ |
735 | 736 |
736 static luaV_List * | 737 static luaV_List * |
737 luaV_newlist (lua_State *L, list_T *lis) | 738 luaV_newlist(lua_State *L, list_T *lis) |
738 { | 739 { |
739 luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List)); | 740 luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List)); |
740 *l = lis; | 741 *l = lis; |
741 lis->lv_refcount++; /* reference in Lua */ | 742 lis->lv_refcount++; /* reference in Lua */ |
742 luaV_setudata(L, lis); /* cache[lis] = udata */ | 743 luaV_setudata(L, lis); /* cache[lis] = udata */ |
747 | 748 |
748 luaV_pushtype(list_T, list, luaV_List) | 749 luaV_pushtype(list_T, list, luaV_List) |
749 luaV_type_tostring(list, LUAVIM_LIST) | 750 luaV_type_tostring(list, LUAVIM_LIST) |
750 | 751 |
751 static int | 752 static int |
752 luaV_list_len (lua_State *L) | 753 luaV_list_len(lua_State *L) |
753 { | 754 { |
754 list_T *l = luaV_unbox(L, luaV_List, 1); | 755 list_T *l = luaV_unbox(L, luaV_List, 1); |
755 lua_pushinteger(L, (l == NULL) ? 0 : (int) l->lv_len); | 756 lua_pushinteger(L, (l == NULL) ? 0 : (int) l->lv_len); |
756 return 1; | 757 return 1; |
757 } | 758 } |
758 | 759 |
759 static int | 760 static int |
760 luaV_list_iter (lua_State *L) | 761 luaV_list_iter(lua_State *L) |
761 { | 762 { |
762 listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2)); | 763 listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2)); |
763 if (li == NULL) return 0; | 764 if (li == NULL) return 0; |
764 luaV_pushtypval(L, &li->li_tv); | 765 luaV_pushtypval(L, &li->li_tv); |
765 lua_pushlightuserdata(L, (void *) li->li_next); | 766 lua_pushlightuserdata(L, (void *) li->li_next); |
766 lua_replace(L, lua_upvalueindex(2)); | 767 lua_replace(L, lua_upvalueindex(2)); |
767 return 1; | 768 return 1; |
768 } | 769 } |
769 | 770 |
770 static int | 771 static int |
771 luaV_list_call (lua_State *L) | 772 luaV_list_call(lua_State *L) |
772 { | 773 { |
773 list_T *l = luaV_unbox(L, luaV_List, 1); | 774 list_T *l = luaV_unbox(L, luaV_List, 1); |
774 lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ | 775 lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ |
775 lua_pushlightuserdata(L, (void *) l->lv_first); | 776 lua_pushlightuserdata(L, (void *) l->lv_first); |
776 lua_pushcclosure(L, luaV_list_iter, 2); | 777 lua_pushcclosure(L, luaV_list_iter, 2); |
777 return 1; | 778 return 1; |
778 } | 779 } |
779 | 780 |
780 static int | 781 static int |
781 luaV_list_index (lua_State *L) | 782 luaV_list_index(lua_State *L) |
782 { | 783 { |
783 list_T *l = luaV_unbox(L, luaV_List, 1); | 784 list_T *l = luaV_unbox(L, luaV_List, 1); |
784 if (lua_isnumber(L, 2)) /* list item? */ | 785 if (lua_isnumber(L, 2)) /* list item? */ |
785 { | 786 { |
786 listitem_T *li = list_find(l, (long) luaL_checkinteger(L, 2)); | 787 listitem_T *li = list_find(l, (long) luaL_checkinteger(L, 2)); |
805 lua_pushnil(L); | 806 lua_pushnil(L); |
806 return 1; | 807 return 1; |
807 } | 808 } |
808 | 809 |
809 static int | 810 static int |
810 luaV_list_newindex (lua_State *L) | 811 luaV_list_newindex(lua_State *L) |
811 { | 812 { |
812 list_T *l = luaV_unbox(L, luaV_List, 1); | 813 list_T *l = luaV_unbox(L, luaV_List, 1); |
813 long n = (long) luaL_checkinteger(L, 2); | 814 long n = (long) luaL_checkinteger(L, 2); |
814 listitem_T *li; | 815 listitem_T *li; |
815 if (l->lv_lock) | 816 if (l->lv_lock) |
832 } | 833 } |
833 return 0; | 834 return 0; |
834 } | 835 } |
835 | 836 |
836 static int | 837 static int |
837 luaV_list_add (lua_State *L) | 838 luaV_list_add(lua_State *L) |
838 { | 839 { |
839 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); | 840 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); |
840 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); | 841 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); |
841 typval_T v; | 842 typval_T v; |
842 if (l->lv_lock) | 843 if (l->lv_lock) |
849 lua_settop(L, 1); | 850 lua_settop(L, 1); |
850 return 1; | 851 return 1; |
851 } | 852 } |
852 | 853 |
853 static int | 854 static int |
854 luaV_list_insert (lua_State *L) | 855 luaV_list_insert(lua_State *L) |
855 { | 856 { |
856 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); | 857 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); |
857 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); | 858 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); |
858 long pos = (long) luaL_optinteger(L, 3, 0); | 859 long pos = (long) luaL_optinteger(L, 3, 0); |
859 listitem_T *li = NULL; | 860 listitem_T *li = NULL; |
888 | 889 |
889 | 890 |
890 /* ======= Dict type ======= */ | 891 /* ======= Dict type ======= */ |
891 | 892 |
892 static luaV_Dict * | 893 static luaV_Dict * |
893 luaV_newdict (lua_State *L, dict_T *dic) | 894 luaV_newdict(lua_State *L, dict_T *dic) |
894 { | 895 { |
895 luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict)); | 896 luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict)); |
896 *d = dic; | 897 *d = dic; |
897 dic->dv_refcount++; /* reference in Lua */ | 898 dic->dv_refcount++; /* reference in Lua */ |
898 luaV_setudata(L, dic); /* cache[dic] = udata */ | 899 luaV_setudata(L, dic); /* cache[dic] = udata */ |
903 | 904 |
904 luaV_pushtype(dict_T, dict, luaV_Dict) | 905 luaV_pushtype(dict_T, dict, luaV_Dict) |
905 luaV_type_tostring(dict, LUAVIM_DICT) | 906 luaV_type_tostring(dict, LUAVIM_DICT) |
906 | 907 |
907 static int | 908 static int |
908 luaV_dict_len (lua_State *L) | 909 luaV_dict_len(lua_State *L) |
909 { | 910 { |
910 dict_T *d = luaV_unbox(L, luaV_Dict, 1); | 911 dict_T *d = luaV_unbox(L, luaV_Dict, 1); |
911 lua_pushinteger(L, (d == NULL) ? 0 : (int) d->dv_hashtab.ht_used); | 912 lua_pushinteger(L, (d == NULL) ? 0 : (int) d->dv_hashtab.ht_used); |
912 return 1; | 913 return 1; |
913 } | 914 } |
914 | 915 |
915 static int | 916 static int |
916 luaV_dict_iter (lua_State *L UNUSED) | 917 luaV_dict_iter(lua_State *L UNUSED) |
917 { | 918 { |
918 #ifdef FEAT_EVAL | 919 #ifdef FEAT_EVAL |
919 hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2)); | 920 hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2)); |
920 int n = lua_tointeger(L, lua_upvalueindex(3)); | 921 int n = lua_tointeger(L, lua_upvalueindex(3)); |
921 dictitem_T *di; | 922 dictitem_T *di; |
933 return 0; | 934 return 0; |
934 #endif | 935 #endif |
935 } | 936 } |
936 | 937 |
937 static int | 938 static int |
938 luaV_dict_call (lua_State *L) | 939 luaV_dict_call(lua_State *L) |
939 { | 940 { |
940 dict_T *d = luaV_unbox(L, luaV_Dict, 1); | 941 dict_T *d = luaV_unbox(L, luaV_Dict, 1); |
941 hashtab_T *ht = &d->dv_hashtab; | 942 hashtab_T *ht = &d->dv_hashtab; |
942 lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ | 943 lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ |
943 lua_pushlightuserdata(L, (void *) ht->ht_array); | 944 lua_pushlightuserdata(L, (void *) ht->ht_array); |
1035 { | 1036 { |
1036 luaV_Funcref *f = (luaV_Funcref *)lua_newuserdata(L, sizeof(luaV_Funcref)); | 1037 luaV_Funcref *f = (luaV_Funcref *)lua_newuserdata(L, sizeof(luaV_Funcref)); |
1037 | 1038 |
1038 if (name != NULL) | 1039 if (name != NULL) |
1039 { | 1040 { |
1040 func_ref(name); /* as in copy_tv */ | 1041 func_ref(name); |
1041 f->tv.vval.v_string = vim_strsave(name); | 1042 f->name = vim_strsave(name); |
1042 } | 1043 } |
1043 f->tv.v_type = VAR_FUNC; | |
1044 f->args.v_type = VAR_LIST; | |
1045 f->self = NULL; | 1044 f->self = NULL; |
1046 luaV_getfield(L, LUAVIM_FUNCREF); | 1045 luaV_getfield(L, LUAVIM_FUNCREF); |
1047 lua_setmetatable(L, -2); | 1046 lua_setmetatable(L, -2); |
1048 return f; | 1047 return f; |
1049 } | 1048 } |
1050 | 1049 |
1051 static luaV_Funcref * | 1050 static luaV_Funcref * |
1052 luaV_pushfuncref(lua_State *L, typval_T *tv) | 1051 luaV_pushfuncref(lua_State *L, char_u *name) |
1053 { | 1052 { |
1054 luaV_Funcref *f = luaV_newfuncref(L, NULL); | 1053 return luaV_newfuncref(L, name); |
1055 copy_tv(tv, &f->tv); | |
1056 clear_tv(tv); | |
1057 return f; | |
1058 } | 1054 } |
1059 | 1055 |
1060 | 1056 |
1061 luaV_type_tostring(funcref, LUAVIM_FUNCREF) | 1057 luaV_type_tostring(funcref, LUAVIM_FUNCREF) |
1062 | 1058 |
1063 static int | 1059 static int |
1064 luaV_funcref_gc(lua_State *L) | 1060 luaV_funcref_gc(lua_State *L) |
1065 { | 1061 { |
1066 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1); | 1062 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1); |
1067 | 1063 |
1068 func_unref(f->tv.vval.v_string); | 1064 func_unref(f->name); |
1069 vim_free(f->tv.vval.v_string); | 1065 vim_free(f->name); |
1070 dict_unref(f->self); | 1066 // NOTE: Don't call "dict_unref(f->self)", because the dict of "f->self" |
1067 // will be (or has been already) freed by Vim's garbage collection. | |
1071 return 0; | 1068 return 0; |
1072 } | 1069 } |
1073 | 1070 |
1074 /* equivalent to string(funcref) */ | 1071 /* equivalent to string(funcref) */ |
1075 static int | 1072 static int |
1076 luaV_funcref_len(lua_State *L) | 1073 luaV_funcref_len(lua_State *L) |
1077 { | 1074 { |
1078 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1); | 1075 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1); |
1079 | 1076 |
1080 lua_pushstring(L, (const char *) f->tv.vval.v_string); | 1077 lua_pushstring(L, (const char *) f->name); |
1081 return 1; | 1078 return 1; |
1082 } | 1079 } |
1083 | 1080 |
1084 static int | 1081 static int |
1085 luaV_funcref_call(lua_State *L) | 1082 luaV_funcref_call(lua_State *L) |
1086 { | 1083 { |
1087 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1); | 1084 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1); |
1088 int i, n = lua_gettop(L) - 1; /* #args */ | 1085 int i, n = lua_gettop(L) - 1; // #args |
1089 int status; | 1086 int status = FAIL; |
1090 typval_T v, rettv; | 1087 typval_T args; |
1091 | 1088 typval_T rettv; |
1092 f->args.vval.v_list = list_alloc(); | 1089 |
1093 rettv.v_type = VAR_UNKNOWN; /* as in clear_tv */ | 1090 args.v_type = VAR_LIST; |
1094 if (f->args.vval.v_list == NULL) | 1091 args.vval.v_list = list_alloc(); |
1095 status = FAIL; | 1092 rettv.v_type = VAR_UNKNOWN; // as in clear_tv |
1096 else | 1093 if (args.vval.v_list != NULL) |
1097 { | 1094 { |
1095 typval_T v; | |
1096 | |
1098 for (i = 0; i < n; i++) | 1097 for (i = 0; i < n; i++) |
1099 { | 1098 { |
1100 luaV_checktypval(L, i + 2, &v, "calling funcref"); | 1099 luaV_checktypval(L, i + 2, &v, "calling funcref"); |
1101 list_append_tv(f->args.vval.v_list, &v); | 1100 list_append_tv(args.vval.v_list, &v); |
1102 clear_tv(&v); | 1101 clear_tv(&v); |
1103 } | 1102 } |
1104 status = func_call(f->tv.vval.v_string, &f->args, | 1103 status = func_call(f->name, &args, NULL, f->self, &rettv); |
1105 NULL, f->self, &rettv); | |
1106 if (status == OK) | 1104 if (status == OK) |
1107 luaV_pushtypval(L, &rettv); | 1105 luaV_pushtypval(L, &rettv); |
1108 clear_tv(&f->args); | 1106 clear_tv(&args); |
1109 clear_tv(&rettv); | 1107 clear_tv(&rettv); |
1110 } | 1108 } |
1111 if (status != OK) | 1109 if (status != OK) |
1112 luaL_error(L, "cannot call funcref"); | 1110 luaL_error(L, "cannot call funcref"); |
1113 return 1; | 1111 return 1; |
1366 lua_pushnil(L); | 1364 lua_pushnil(L); |
1367 return 1; | 1365 return 1; |
1368 } | 1366 } |
1369 | 1367 |
1370 static int | 1368 static int |
1371 luaV_window_newindex (lua_State *L) | 1369 luaV_window_newindex(lua_State *L) |
1372 { | 1370 { |
1373 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); | 1371 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); |
1374 const char *s = luaL_checkstring(L, 2); | 1372 const char *s = luaL_checkstring(L, 2); |
1375 int v = luaL_checkinteger(L, 3); | 1373 int v = luaL_checkinteger(L, 3); |
1376 if (strncmp(s, "line", 4) == 0) | 1374 if (strncmp(s, "line", 4) == 0) |
1766 luaV_setudata(L, lua_touserdata(L, 1)); | 1764 luaV_setudata(L, lua_touserdata(L, 1)); |
1767 return 0; | 1765 return 0; |
1768 } | 1766 } |
1769 | 1767 |
1770 static int | 1768 static int |
1771 luaV_luaeval (lua_State *L) | 1769 luaV_luaeval(lua_State *L) |
1772 { | 1770 { |
1773 luaL_Buffer b; | 1771 luaL_Buffer b; |
1774 size_t l; | 1772 size_t l; |
1775 const char *str = lua_tolstring(L, 1, &l); | 1773 const char *str = lua_tolstring(L, 1, &l); |
1776 typval_T *arg = (typval_T *) lua_touserdata(L, 2); | 1774 typval_T *arg = (typval_T *) lua_touserdata(L, 2); |
1795 emsg("luaeval: cannot convert value"); | 1793 emsg("luaeval: cannot convert value"); |
1796 return 0; | 1794 return 0; |
1797 } | 1795 } |
1798 | 1796 |
1799 static int | 1797 static int |
1800 luaV_setref (lua_State *L) | 1798 luaV_setref(lua_State *L) |
1801 { | 1799 { |
1802 int copyID = lua_tointeger(L, 1); | 1800 int copyID = lua_tointeger(L, 1); |
1803 int abort = FALSE; | 1801 int abort = FALSE; |
1804 typval_T tv; | |
1805 | 1802 |
1806 luaV_getfield(L, LUAVIM_LIST); | 1803 luaV_getfield(L, LUAVIM_LIST); |
1807 luaV_getfield(L, LUAVIM_DICT); | 1804 luaV_getfield(L, LUAVIM_DICT); |
1805 luaV_getfield(L, LUAVIM_FUNCREF); | |
1808 lua_pushnil(L); | 1806 lua_pushnil(L); |
1809 /* traverse cache table */ | 1807 // traverse cache table |
1810 while (!abort && lua_next(L, lua_upvalueindex(1)) != 0) | 1808 while (!abort && lua_next(L, lua_upvalueindex(1)) != 0) |
1811 { | 1809 { |
1812 lua_getmetatable(L, -1); | 1810 lua_getmetatable(L, -1); |
1813 if (lua_rawequal(L, -1, 2)) /* list? */ | 1811 if (lua_rawequal(L, -1, 2)) // list? |
1814 { | 1812 { |
1815 tv.v_type = VAR_LIST; | 1813 list_T *l = (list_T *)lua_touserdata(L, 5); // key |
1816 tv.vval.v_list = (list_T *) lua_touserdata(L, 4); /* key */ | 1814 |
1817 abort = set_ref_in_item(&tv, copyID, NULL, NULL); | 1815 if (l->lv_copyID != copyID) |
1818 } | 1816 { |
1819 else if (lua_rawequal(L, -1, 3)) /* dict? */ | 1817 l->lv_copyID = copyID; |
1820 { | 1818 abort = set_ref_in_list(l, copyID, NULL); |
1821 tv.v_type = VAR_DICT; | 1819 } |
1822 tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */ | 1820 } |
1823 abort = set_ref_in_item(&tv, copyID, NULL, NULL); | 1821 else if (lua_rawequal(L, -1, 3)) // dict? |
1824 } | 1822 { |
1825 lua_pop(L, 2); /* metatable and value */ | 1823 dict_T *d = (dict_T *)lua_touserdata(L, 5); // key |
1824 | |
1825 if (d->dv_copyID != copyID) | |
1826 { | |
1827 d->dv_copyID = copyID; | |
1828 abort = set_ref_in_ht(&d->dv_hashtab, copyID, NULL); | |
1829 } | |
1830 } | |
1831 else if (lua_rawequal(L, -1, 4)) // funcref? | |
1832 { | |
1833 luaV_Funcref *f = (luaV_Funcref *)lua_touserdata(L, 5); // key | |
1834 | |
1835 if (f->self != NULL && f->self->dv_copyID != copyID) | |
1836 { | |
1837 f->self->dv_copyID = copyID; | |
1838 abort = set_ref_in_ht(&f->self->dv_hashtab, copyID, NULL); | |
1839 } | |
1840 } | |
1841 lua_pop(L, 2); // metatable and value | |
1826 } | 1842 } |
1827 lua_pushinteger(L, abort); | 1843 lua_pushinteger(L, abort); |
1828 return 1; | 1844 return 1; |
1829 } | 1845 } |
1830 | 1846 |
2051 | 2067 |
2052 luaV_freetype(buf_T, buffer) | 2068 luaV_freetype(buf_T, buffer) |
2053 luaV_freetype(win_T, window) | 2069 luaV_freetype(win_T, window) |
2054 | 2070 |
2055 void | 2071 void |
2056 do_luaeval (char_u *str, typval_T *arg, typval_T *rettv) | 2072 do_luaeval(char_u *str, typval_T *arg, typval_T *rettv) |
2057 { | 2073 { |
2058 lua_init(); | 2074 lua_init(); |
2059 luaV_getfield(L, LUAVIM_LUAEVAL); | 2075 luaV_getfield(L, LUAVIM_LUAEVAL); |
2060 lua_pushstring(L, (char *) str); | 2076 lua_pushstring(L, (char *) str); |
2061 lua_pushlightuserdata(L, (void *) arg); | 2077 lua_pushlightuserdata(L, (void *) arg); |
2062 lua_pushlightuserdata(L, (void *) rettv); | 2078 lua_pushlightuserdata(L, (void *) rettv); |
2063 lua_call(L, 3, 0); | 2079 lua_call(L, 3, 0); |
2064 } | 2080 } |
2065 | 2081 |
2066 int | 2082 int |
2067 set_ref_in_lua (int copyID) | 2083 set_ref_in_lua(int copyID) |
2068 { | 2084 { |
2069 int aborted = 0; | 2085 int aborted = 0; |
2070 | 2086 |
2071 if (lua_isopen()) | 2087 if (lua_isopen()) |
2072 { | 2088 { |