diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-02-28 10:10:27 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-02-28 10:10:27 -0300 |
commit | 127a8e80fe0d74efd26994b3877cdc77b712ea56 (patch) | |
tree | 12b8b3be0660884f4a1075af37e0f58cbd43a3d3 /lfunc.c | |
parent | f9e35627ed26dff4114a1d01ff113d8b4cc91ab5 (diff) | |
download | lua-127a8e80fe0d74efd26994b3877cdc77b712ea56.tar.gz lua-127a8e80fe0d74efd26994b3877cdc77b712ea56.tar.bz2 lua-127a8e80fe0d74efd26994b3877cdc77b712ea56.zip |
'__close' gets no error object if there is no error
Instead of receiving nil as a second argument, __close metamethods are
called with just one argument when there are no errors.
Diffstat (limited to 'lfunc.c')
-rw-r--r-- | lfunc.c | 32 |
1 files changed, 20 insertions, 12 deletions
@@ -100,21 +100,23 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { | |||
100 | 100 | ||
101 | 101 | ||
102 | /* | 102 | /* |
103 | ** Call closing method for object 'obj' with error message 'err'. The | 103 | ** Call closing method for object 'obj' with error object 'err'. The |
104 | ** boolean 'yy' controls whether the call is yieldable. | 104 | ** boolean 'yy' controls whether the call is yieldable. |
105 | ** (This function assumes EXTRA_STACK.) | 105 | ** (This function assumes EXTRA_STACK.) |
106 | */ | 106 | */ |
107 | static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { | 107 | static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { |
108 | StkId top = L->top.p; | 108 | StkId top = L->top.p; |
109 | StkId func = top; | ||
109 | const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); | 110 | const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); |
110 | setobj2s(L, top, tm); /* will call metamethod... */ | 111 | setobj2s(L, top++, tm); /* will call metamethod... */ |
111 | setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ | 112 | setobj2s(L, top++, obj); /* with 'self' as the 1st argument */ |
112 | setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ | 113 | if (err != NULL) /* if there was an error... */ |
113 | L->top.p = top + 3; /* add function and arguments */ | 114 | setobj2s(L, top++, err); /* then error object will be 2nd argument */ |
115 | L->top.p = top; /* add function and arguments */ | ||
114 | if (yy) | 116 | if (yy) |
115 | luaD_call(L, top, 0); | 117 | luaD_call(L, func, 0); |
116 | else | 118 | else |
117 | luaD_callnoyield(L, top, 0); | 119 | luaD_callnoyield(L, func, 0); |
118 | } | 120 | } |
119 | 121 | ||
120 | 122 | ||
@@ -144,11 +146,17 @@ static void prepcallclosemth (lua_State *L, StkId level, TStatus status, | |||
144 | int yy) { | 146 | int yy) { |
145 | TValue *uv = s2v(level); /* value being closed */ | 147 | TValue *uv = s2v(level); /* value being closed */ |
146 | TValue *errobj; | 148 | TValue *errobj; |
147 | if (status == CLOSEKTOP) | 149 | switch (status) { |
148 | errobj = &G(L)->nilvalue; /* error object is nil */ | 150 | case LUA_OK: |
149 | else { /* 'luaD_seterrorobj' will set top to level + 2 */ | 151 | L->top.p = level + 1; /* call will be at this level */ |
150 | errobj = s2v(level + 1); /* error object goes after 'uv' */ | 152 | /* FALLTHROUGH */ |
151 | luaD_seterrorobj(L, status, level + 1); /* set error object */ | 153 | case CLOSEKTOP: /* don't need to change top */ |
154 | errobj = NULL; /* no error object */ | ||
155 | break; | ||
156 | default: /* 'luaD_seterrorobj' will set top to level + 2 */ | ||
157 | errobj = s2v(level + 1); /* error object goes after 'uv' */ | ||
158 | luaD_seterrorobj(L, status, level + 1); /* set error object */ | ||
159 | break; | ||
152 | } | 160 | } |
153 | callclosemethod(L, uv, errobj, yy); | 161 | callclosemethod(L, uv, errobj, yy); |
154 | } | 162 | } |