فهرست منبع

Formatted stuff in a format more appropriate for Urho. See previous commit message for build instructions.
Note that I quadrupled the default emscripten memory size as I found the 32 MB was all but always too small.

nathan 9 سال پیش
والد
کامیت
30f9d91bdd

+ 2 - 2
CMake/Modules/Urho3D-CMake-common.cmake

@@ -84,8 +84,8 @@ include (CheckCompilerToolchain)
 include (CMakeDependentOption)
 option (URHO3D_C++11 "Enable C++11 standard")
 cmake_dependent_option (IOS "Setup build for iOS platform" FALSE "XCODE" FALSE)
-cmake_dependent_option (URHO3D_64BIT "Enable 64-bit build, the default is set based on the native ABI of the chosen compiler toolchain" ${NATIVE_64BIT} "NOT MSVC AND NOT MINGW AND NOT ANDROID AND NOT RPI AND NOT POWERPC" ${NATIVE_64BIT})
-option (URHO3D_ANGELSCRIPT "Enable AngelScript scripting support") # TRUE "NOT WEB" FALSE)
+cmake_dependent_option (URHO3D_64BIT "Enable 64-bit build, the default is set based on the native ABI of the chosen compiler toolchain" ${NATIVE_64BIT} "NOT MSVC AND NOT MINGW AND NOT ANDROID AND NOT RPI AND NOT WEB AND NOT POWERPC" ${NATIVE_64BIT})
+option (URHO3D_ANGELSCRIPT "Enable AngelScript scripting support" TRUE)
 option (URHO3D_LUA "Enable additional Lua scripting support" TRUE)
 option (URHO3D_NAVIGATION "Enable navigation support" TRUE)
 cmake_dependent_option (URHO3D_NETWORK "Enable networking support" TRUE "NOT WEB" FALSE)

+ 12 - 6
Source/ThirdParty/AngelScript/include/angelscript.h

@@ -28,17 +28,16 @@
    [email protected]
 */
 
-// Modified by Lasse Oorni for Urho3D
+// Modified by Lasse Oorni and Nathanial Lydick for Urho3D
 
 //
 // angelscript.h
 //
 // The script engine interface
 //
-#ifdef EMSCRIPTEN
-#define AS_MAX_PORTABILITY
-#endif
-#ifdef FORCE_AS_PORTABLE
+
+// Urho3D: Define AS_MAX_PORTABILITY for Web builds and when specifically requested (This could be moved to the CMake files)
+#if defined(EMSCRIPTEN) || defined(FORCE_AS_PORTABLE)
 #define AS_MAX_PORTABILITY
 #endif
 
@@ -1934,8 +1933,15 @@ const asSBCInfo asBCInfo[256] =
 
 
 END_AS_NAMESPACE
+
+// Urho3D: Include the wrapper macros file but only after they have been defined above
+// This causes a large number of warnings, which could possibly be prevented with further 
+//  changes ot the library or the Urho Angelscript code
+// Only include this file if we request are NOT building the angelscript library itself, 
+// as Angelscript already provides generic wrappers for their classes 
+// (URHO_PROJECT_BUILD is defined in teh CMakeLists.txt file for the AngelScript (sub)library)
 #ifndef URHO_PROJECT_BUILD
-#include "mine.h"
+#include "wrapmacros.h"
 #endif
 
 #endif

+ 51 - 146
Source/ThirdParty/AngelScript/include/wrap.h

@@ -1,58 +1,44 @@
-/*
- * wrap.hpp
- *
- *  Created on: Apr 6, 2016
- *      Author: nathan
- */
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
 
 #pragma once
+
 #include <type_traits>
-//#include "AngelScript/angelscript.h"
+
 #include "angelscript.h"
-#include <boost/preprocessor.hpp>
 
+//only Boost.Preprocessor is needed, so it may be reasonable to include it in the Urho repository directly
+#include <boost/preprocessor.hpp>
 
 
 //Return void enable if: http://stackoverflow.com/questions/12002447/template-method-enable-if-specialization
 //# do with // http://stackoverflow.com/questions/5588855/standard-alternative-to-gccs-va-args-trick
 
-
 #define EV(...) __VA_ARGS__
 
-//inline asSFuncPtr asFunctionPtr<asGENFUNC_t>(asGENFUNC_t func)
-//{
-//	// Mark this as a generic function
-//	asSFuncPtr p(1);
-//	p.ptr.f.func = reinterpret_cast<asFUNCTION_t>(func);
-//	return p;
-//}
-typedef void (*asGENFUNC_t)(asIScriptGeneric *);
-
-
-//#define DO_2(_,a,b) GET(a,0), GET(b,1)//Proxy<a>::cast(gen->arguments[0])
-//#define DO_4(_,a,b,c,d) GET(a,0), GET(b,1),GET(c,2), GET(d,3)//(a*)(gen->arguments[0]),(b*)(gen->arguments[1]),(a*)(gen->arguments[2]),(b*)(gen->arguments[3])
-//#define DO_6(_,a,b,c,d,e,f) GET(a,0), GET(b,1),GET(c,2), GET(d,3),GET(e,4), GET(f,5)//(a*)(gen->arguments[0]),(b*)(gen->arguments[1]),(a*)(gen->arguments[2]),(b*)(gen->arguments[3]),(a*)(gen->arguments[4]),(b*)(gen->arguments[5])
-//
-////#define DO_1(_,a) static_cast<Proxy <a> *>(gen->arguments[0])->value
-//#define DO_1(_,a) Proxy<a>::cast(gen->arguments[0])
-//#define DO_3(_,a,b,c) GET(a,0), GET(b,1),GET(c,2)
-//#define DO_5(_,a,b,c,d,e) GET(a,0), GET(b,1),GET(c,2), GET(d,3),GET(e,4)
-//
-//#define DO_0(_)
-//
-//#define GET7TH(_,arg1, arg2, arg3, arg4, arg5, arg6, arg7,...) arg7
-//#define DO_CHOOSER(...) GET7TH(__VA_ARGS__,DO_6,DO_5,DO_4,DO_3,DO_2,DO_1,DO_0)
-//
-//#define DO(...) DO_CHOOSER(_,##__VA_ARGS__)(_,##__VA_ARGS__)
-//
-//#define CHOOSE(...)
-
-
 #define UNWRAP(...) __VA_ARGS__
 #define EXTRACT_CONST(...) (__VA_ARGS__),
 // from http://stackoverflow.com/questions/18851889/boost-preprocessor-skip-if-variadic-is-empty
 
-
 // based on the: http://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments
 #define __ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
 #define __HAS_COMMA(...) __ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
@@ -76,8 +62,7 @@ typedef void (*asGENFUNC_t)(asIScriptGeneric *);
 #define __GEN_EMPTY_ARGS(...)
 
 #define __GEN_NONEMPTY_ARGS_CB(unused, data, idx, elem) \
-	, static_cast<gw::Proxy <elem> *>(gen->GetAddressOfArg(idx))->value
-//	, Proxy<elem>::cast(gen->arguments[idx])
+    , static_cast<gw::Proxy <elem> *>(gen->GetAddressOfArg(idx))->value
 
 #define __GEN_NONEMPTY_ARGS(seq) \
     BOOST_PP_SEQ_FOR_EACH_I( \
@@ -86,146 +71,66 @@ typedef void (*asGENFUNC_t)(asIScriptGeneric *);
         ,seq \
     )
 
-
-
 #define CreateGenericFromMethod_2(...) EV(CreateGenericFromMethod_3(__VA_ARGS__))
 #define CreateGenericFromMethod_3(class_t,method,parameters,const,return_t) \
 asFunctionPtr<asGENFUNC_t>([] (asIScriptGeneric* gen) {\
-		BOOST_PP_CAT(wrap::call,const) <return_t,class_t BOOST_PP_COMMA_IF(BOOST_PP_IF(TUPLE_IS_EMPTY parameters ,0,1)) EV parameters>\
-				(gen,/*&(Proxy<class_t>::cast(gen->GetObject()))*/((class_t*)gen->GetObject()), static_cast<return_t (class_t::*) parameters const>(&class_t::method)\
-					BOOST_PP_IF( \
-						 TUPLE_IS_EMPTY parameters \
-						,__GEN_EMPTY_ARGS \
-						,__GEN_NONEMPTY_ARGS \
-					)(BOOST_PP_TUPLE_TO_SEQ( parameters )) \
-				);\
+        BOOST_PP_CAT(wrap::call,const) <return_t,class_t BOOST_PP_COMMA_IF(BOOST_PP_IF(TUPLE_IS_EMPTY parameters ,0,1)) EV parameters>\
+                (gen,/*&(Proxy<class_t>::cast(gen->GetObject()))*/((class_t*)gen->GetObject()), static_cast<return_t (class_t::*) parameters const>(&class_t::method)\
+                    BOOST_PP_IF( \
+                         TUPLE_IS_EMPTY parameters \
+                        ,__GEN_EMPTY_ARGS \
+                        ,__GEN_NONEMPTY_ARGS \
+                    )(BOOST_PP_TUPLE_TO_SEQ( parameters )) \
+                );\
 })
 
 #define WRAP_MFN_PR(class_t,method,parameters,return_t) EV(EV(EV(CreateGenericFromMethod_2(class_t,method,EXTRACT_CONST parameters,return_t))))
 
-//typedef asIScriptGeneric Gen;
-#include <Container/RefCounted.h> //<- needed for the AddRef stuff
-namespace wrap
-{
-
-template<class T>
-void AddRef(const void*)
-{
-	return;
-}
-template<class T>
-void AddRef(Urho3D::RefCounted** obj)
-{
-	if (*obj)
-	{
-		(*obj)->AddRef();
-	}
-}
-
-//void Add(::std::false_type, ...)
-//{
-//	return;
-//}
-//void Add(::std::true_type, void* obj)
-//{
-//	if (*obj)
-//	{
-//		((Urho3D::RefCounted*)obj)->AddRef();
-//	}
-//}
-//
-//template<class T, typename ...P>
-//void Deploy(T, ...P)
-//{
-//	Add(::std::is_base_of<Urho3D::RefCounted,)
-//}
-
 
-
-template<class T> void call(T t)
-{
-	gw::Proxy<T> ret(t);
-	AddRef<T>(&(ret.value));
-}
-template<typename ...T>
-void nill(T... args)
-{
-	(void)0;
-}
-/*
-template<class ...T>
-void calls(T... args)
+namespace wrap
 {
-	// from: http://stackoverflow.com/questions/17339789/how-to-call-a-function-on-all-variadic-template-args
-
-	    using expand_type = int[];
-
-
-	//#define SO_EXPAND_SIDE_EFFECTS(PATTERN) ::so::expand_type{ 0, ((PATTERN), 0)... }
-
-	expand_type{ 0, ((call<T>(args)), 0)... };
-}*/
 
 template<class R, class C, typename ...P>
 void call_helper(::std::false_type, asIScriptGeneric*g, C*obj, R (C::*fn)(P...), P... args)
 {
-//	cout << "do non-void";
-//	g->return_value = new R ((obj->*fn)(args...));
-//	(AddRef(args)...);
-	//calls<P...>(args...); // <- working one
-//	Add(::std::is_base_of<)
-	new (g->GetAddressOfReturnLocation()) gw::Proxy<R> ((obj->*fn)(args...));
-	gw::Proxy<R>* ret = static_cast<gw::Proxy<R>*>(g->GetAddressOfReturnLocation());
-	//AddRef<R>(&(ret->value));
+    new (g->GetAddressOfReturnLocation()) gw::Proxy<R> ((obj->*fn)(args...));
 }
 
 template<class R, class C, typename ...P>
 void call_helper(::std::true_type,asIScriptGeneric*g, C*obj, R (C::*fn)(P...), P... args)
 {
-//	cout << "do void";
-	//calls(args...);
-	(obj->*fn)(args...);
-//	g->return_value = nullptr;
-
+    (obj->*fn)(args...);
 }
 template<class R, class C, typename ...P>
 void call_helper(::std::false_type, asIScriptGeneric*g, C*obj, R (C::*fn)(P...)const, P... args)
 {
-//	cout << "do non-void const";
-//	g->return_value = new R ((obj->*fn)(args...));
-	//calls(args...);
-	new (g->GetAddressOfReturnLocation()) gw::Proxy<R> ((obj->*fn)(args...));
-	gw::Proxy<R>* ret = static_cast<gw::Proxy<R>*>(g->GetAddressOfReturnLocation());
-	//AddRef<R>(&(ret->value));
+    new (g->GetAddressOfReturnLocation()) gw::Proxy<R> ((obj->*fn)(args...));
 }
 
 template<class R, class C, typename ...P>
 void call_helper(::std::true_type,asIScriptGeneric*g, C*obj, R (C::*fn)(P...)const, P... args)
 {
-//	cout << "do void const";
-	//calls(args...);
-	(obj->*fn)(args...);
-//	g->return_value = nullptr;
-
+    (obj->*fn)(args...);
 }
 template<class R, class C, typename ...P>
 void call(asIScriptGeneric*g, C*obj, R (C::*fn)(P...), P... args)
 {
-	call_helper<R,C,P...>(::std::is_void<R>(),
-			g,
-			obj,
-			fn,
-			args...);
+    call_helper<R,C,P...>(::std::is_void<R>(),
+            g,
+            obj,
+            fn,
+            args...);
 }
 template<class R, class C, typename ...P>
 void callconst(asIScriptGeneric*g, C*obj, R (C::*fn)(P...)const, P... args)
 {
-	call_helper<R,C,P...>(std::is_void<R>(),
-			g,
-			obj,
-			fn,
-			args...);
-}
+    call_helper<R,C,P...>(std::is_void<R>(),
+            g,
+            obj,
+            fn,
+            args...);
 }
 
+} // namespace wrap
+
 

+ 5 - 0
Source/ThirdParty/AngelScript/include/wrap16.h

@@ -1,3 +1,6 @@
+// This file was generated by the angelscript autowrapper addon
+// Modified by Nathanial Lydick for Urho3D (including the addition of the above notice)
+
 #ifndef AS_GEN_WRAPPER_H
 #define AS_GEN_WRAPPER_H
 
@@ -2913,6 +2916,7 @@ Id<T> id(T fn_ptr) { return Id<T>(); }
 #define WRAP_OBJ_LAST(name)       (::gw::id(name).TMPL ol< name >())
 
 #define WRAP_FN_PR(name, Parameters, ReturnType)             asFunctionPtr((::gw::Wrapper<ReturnType (*)Parameters>::TMPL f< name >))
+// Urho3D: The template method did not compile for me (emscripten and gcc), hence the lambda stuff in the wrap.h file
 //#define WRAP_MFN_PR(ClassType, name, Parameters, ReturnType) asFunctionPtr<asGENFUNC_t>((::gw::Wrapper<ReturnType (ClassType::*)Parameters>::TMPL f< &ClassType::name >))
 #define WRAP_OBJ_FIRST_PR(name, Parameters, ReturnType)      asFunctionPtr((::gw::ObjFirst<ReturnType (*)Parameters>::TMPL f< name >))
 #define WRAP_OBJ_LAST_PR(name, Parameters, ReturnType)       asFunctionPtr((::gw::ObjLast<ReturnType (*)Parameters>::TMPL f< name >))
@@ -2922,6 +2926,7 @@ Id<T> id(T fn_ptr) { return Id<T>(); }
 
 } // end namespace gw
 
+// Urho3D: The template method did not compile for me (emscripten and gcc), hence the lambda stuff in the wrap.h file
 #include "wrap.h"
 
 #endif

+ 48 - 2
Source/ThirdParty/AngelScript/include/mine.h → Source/ThirdParty/AngelScript/include/wrapmacros.h

@@ -1,12 +1,56 @@
-#if  defined(EMSCRIPTEN) || defined(FORCE_AS_PORTABLE)
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+//only use this file if we are in a web build or the portable (wrapped) code has been specifically requested
+#if defined(EMSCRIPTEN) || defined(FORCE_AS_PORTABLE)
+
+//the template wrapper code
 #include "wrap16.h"
+
 //can help solve potential ... problems if we need it at the start: http://stackoverflow.com/questions/3046889/optional-parameters-with-c-macros
-#define asFUNCTION(f) F, f
 
+//Overview of the process:
+//take the original funciton that registers a function for the angelscript engine:
+//(RegisterGlobalFunction, RegisterObjectMethod, ...)
+//Define it as a macro. Redefine the asFUNCTION family of macros to extract the arguments passed to them 
+//and pass an F, M, FPR, or MPR depending on which macro was chosen as another argument before the original 
+//contents of the asFUNCTION macro
+//Use the ## operator to paste the F, M, FPR< or MPR allong with the asECallConvTypes name to form the name of another macro
+//This other macro will then bundle the arguments back into the original RegisterGlobalFunction... call, but will use the 
+//wrap macros from the wrap16.h and wrap.h files instead of the original asFUNCTION... call, and will specify the asCALL_GENERIC
+//calling convention
+//***NOTE***: not all of the possibly calling convention/method combinations have been finished, and those that Urho does not use are untested
+
+
+
+#define asFUNCTION(f) F, f
+//define a new macro (taken from angelscript.h) to use in place of the original asFUNCTION macro
 #define _asFUNCTION(f) asFunctionPtr(f)
 //#define asMETHOD(cls, f) cls, M, f
 #define asMETHOD(cls, f) M, (cls,f) //package class and function for UNWRAPping later
 #define UNWRAP(x,y) x,y// try -fmacro-backtrace-limit=0 on compile
+//define a new macro (taken from angelscript.h) to use in place of the original asMETHOD macro
 #define _asMETHOD(c,m) asSMethodPtr<sizeof(void (c::*)())>::Convert((void (c::*)())(&c::m))
 #define RegisterGlobalFunction(...) RegGlobalIndirect(__VA_ARGS__)
 #define RegGlobalIndirect(decl, F, func, kind) RegisterGlobalFunction##F##kind (decl,func) // ... = decl or it = decl, cls for asCall_ThisCall
@@ -55,6 +99,7 @@
 #define UNWRAP3(x,y,z) x,y,z
 #define UNWRAP4(x,y,z,w) x,y,z,w
 #define asMETHODPR(cls,f,p,r) MPR, (cls,f,p,r)
+//define a new macro (taken from angelscript.h) to use in place of the original asFUNCTIONPR macro
 #if (defined(_MSC_VER) && _MSC_VER <= 1200) || (defined(__BORLANDC__) && __BORLANDC__ < 0x590)
 // MSVC 6 has a bug that prevents it from properly compiling using the correct asFUNCTIONPR with operator >
 // so we need to use ordinary C style cast instead of static_cast. The drawback is that the compiler can't
@@ -67,6 +112,7 @@
 #else
 #define _asFUNCTIONPR(f,p,r) asFunctionPtr((void (*)())(static_cast<r (*)p>(f)))
 #endif
+//define a new macro (taken from angelscript.h) to use in place of the original asMETHODPR macro
 #define _asMETHODPR(c,m,p,r) asSMethodPtr<sizeof(void (c::*)())>::Convert(AS_METHOD_AMBIGUITY_CAST(r (c::*)p)(&c::m))
 
 

+ 5 - 4
Source/ThirdParty/AngelScript/source/as_context.cpp

@@ -28,6 +28,7 @@
    [email protected]
 */
 
+// Modified by Nathanial Lydick for Urho3D
 
 //
 // as_context.cpp
@@ -5129,16 +5130,16 @@ int asCContext::CallGeneric(asCScriptFunction *descr)
 	m_regs.objectRegister = gen.objectRegister;
 	m_regs.objectType = descr->returnType.GetObjectType();
 
-
-//ADDED from http://www.gamedev.net/topic/630414-autohandles-with-generic-callconv/
-//if ( m_callingSystemFunction->returnType.IsObject()	&& !m_callingSystemFunction->returnType.IsReference() && m_callingSystemFunction->returnType.IsObjectHandle()	&& m_callingSystemFunction->sysFuncIntf && m_callingSystemFunction->sysFuncIntf->returnAutoHandle	&& m_regs.objectRegister )
-//	m_engine->CallObjectMethod( m_regs.objectRegister, m_callingSystemFunction->returnType.GetObjectType()->beh.addref );
+// Urho3D: add autohandle support for the AS_MAX_PORTABILITY builds
+#if defined(EMSCRIPTEN) || defined(FORCE_AS_PORTABLE)
+//based on http://www.gamedev.net/topic/630414-autohandles-with-generic-callconv/
 if ( descr->returnType.IsObject()
 		&& !descr->returnType.IsReference()
 		&& descr->returnType.IsObjectHandle()
 		&& sysFunc->returnAutoHandle
 		&& m_regs.objectRegister )
 	m_engine->CallObjectMethod( m_regs.objectRegister, descr->returnType.GetObjectType()->beh.addref );
+#endif
 
 	// Clean up arguments
 	const asUINT cleanCount = sysFunc->cleanArgs.GetLength();

+ 16 - 0
Source/Urho3D/AngelScript/Script.cpp

@@ -85,11 +85,21 @@ Script::Script(Context* context) :
     scriptEngine_->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, (asPWORD)true);
     scriptEngine_->SetEngineProperty(asEP_ALLOW_IMPLICIT_HANDLE_TYPES, (asPWORD)true);
     scriptEngine_->SetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES, (asPWORD)true);
+//use the copy of the original asMETHOD macro in a web build (for some reason it still works, presumably because the signature of the function is known)
+#if defined(EMSCRIPTEN) || defined(FORCE_AS_PORTABLE)
     scriptEngine_->SetMessageCallback(_asMETHOD(Script, MessageCallback), this, asCALL_THISCALL);
+#else
+    scriptEngine_->SetMessageCallback(asMETHOD(Script, MessageCallback), this, asCALL_THISCALL);
+#endif
 
     // Create the context for immediate execution
     immediateContext_ = scriptEngine_->CreateContext();
+//use the copy of the original asMETHOD macro in a web build (for some reason it still works, presumably because the signature of the function is known)
+#if defined(EMSCRIPTEN) || defined(FORCE_AS_PORTABLE)
     immediateContext_->SetExceptionCallback(_asMETHOD(Script, ExceptionCallback), this, asCALL_THISCALL);
+#else
+    immediateContext_->SetExceptionCallback(asMETHOD(Script, ExceptionCallback), this, asCALL_THISCALL);
+#endif
 
     // Register Script library object factories
     RegisterScriptLibrary(context_);
@@ -303,7 +313,13 @@ asIScriptContext* Script::GetScriptFileContext()
     while (scriptNestingLevel_ >= scriptFileContexts_.Size())
     {
         asIScriptContext* newContext = scriptEngine_->CreateContext();
+//use the copy of the original asMETHOD macro in a web build (for some reason it still works, presumably because the signature of the function is known)
+#if defined(EMSCRIPTEN) || defined(FORCE_AS_PORTABLE)
         newContext->SetExceptionCallback(_asMETHOD(Script, ExceptionCallback), this, asCALL_THISCALL);
+#else
+        newContext->SetExceptionCallback(asMETHOD(Script, ExceptionCallback), this, asCALL_THISCALL);
+#endif
+
         scriptFileContexts_.Push(newContext);
     }