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 | } |
