import { Decoration } from '../decoration' ; import { LuaReturn , LuaState } from '../types' ; import Global from '../global' ; import Thread from '../thread' ; import TypeExtension from '../type-extension' ; class ErrorTypeExtension extends TypeExtension < Error > { private gcPointer : number ; public constructor ( thread , injectObject ) { super ( thread , 'js_error' ) ; this . gcPointer = thread . lua . module . addFunction ( ( functionStateAddress ) => { const userDataPointer = thread . lua . luaL_checkudata ( functionStateAddress , 1 , this . name ) ; const referencePointer = thread . lua . module . getValue ( userDataPointer , '*' ) ; thread . lua . unref ( referencePointer ) ; return LuaReturn . Ok ; } , 'ii' ) ; if ( thread . lua . luaL_newmetatable ( thread . address , this . name ) ) { const metatableIndex = thread . lua . lua_gettop ( thread . address ) ; thread . lua . lua_pushstring ( thread . address , 'protected metatable' ) ; thread . lua . lua_setfield ( thread . address , metatableIndex , '__metatable' ) ; thread . lua . lua_pushcclosure ( thread . address , this . gcPointer , 0 ) ; thread . lua . lua_setfield ( thread . address , metatableIndex , '__gc' ) ; thread . pushValue ( ( jsRefError , key ) => { if ( key === 'message' ) { return jsRefError . message ; } return null ; } ) ; thread . lua . lua_setfield ( thread . address , metatableIndex , '__index' ) ; thread . pushValue ( ( jsRefError ) => { return jsRefError . message ; } ) ; thread . lua . lua_setfield ( thread . address , metatableIndex , '__tostring' ) ; } thread . lua . lua_pop ( thread . address , 1 ) ; if ( injectObject ) { thread . set ( 'Error' , { create : ( message ) => { if ( message && typeof message !== 'string' ) { throw new Error ( 'message must be a string' ) ; } return new Error ( message ) ; } , } ) ; } } public pushValue ( thread , decoration ) { if ( ! ( decoration . target instanceof Error ) ) { return false ; } return super . pushValue ( thread , decoration ) ; } public close ( ) { this . thread . lua . module . removeFunction ( this . gcPointer ) ; } } export default function createTypeExtension ( thread , injectObject ) { return new ErrorTypeExtension ( thread , injectObject ) ; }