Browse Source

Update AngelScript to 2.35.1. (#2831)

* Update AngelScript to 2.35.1. Now it support native calling convention for ARM64.

* Change comment.
orefkov 4 years ago
parent
commit
4a6e16344b

+ 5 - 1
Source/ThirdParty/AngelScript/CMakeLists.txt

@@ -43,7 +43,11 @@ if (ARM)
         # It is safe to add this assembler code in universal binary build because it has sufficient preprocessor define guards to exclude unsupported archs
         # It is safe to add this assembler code in universal binary build because it has sufficient preprocessor define guards to exclude unsupported archs
         set (ASM_FILES source/as_callfunc_arm_xcode.S)
         set (ASM_FILES source/as_callfunc_arm_xcode.S)
     else ()
     else ()
-        set (ASM_FILES source/as_callfunc_arm_gcc.S)
+		if (URHO3D_64BIT)
+			set (ASM_FILES source/as_callfunc_arm64_gcc.S)
+		else ()
+			set (ASM_FILES source/as_callfunc_arm_gcc.S)
+		endif ()
         set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${ARM_CFLAGS}")
         set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${ARM_CFLAGS}")
     endif ()
     endif ()
 elseif (MSVC AND URHO3D_64BIT)
 elseif (MSVC AND URHO3D_64BIT)

+ 2 - 2
Source/ThirdParty/AngelScript/Urho3DNotes.txt

@@ -1,3 +1,3 @@
 URL: https://github.com/codecat/angelscript-mirror
 URL: https://github.com/codecat/angelscript-mirror
-Date: 10.01.2021
-Latest commit: https://github.com/codecat/angelscript-mirror/commit/19b93c08ee75fbff808eba3349987277e5cbef1b
+Date: 03.10.2021
+Latest commit: https://github.com/codecat/angelscript-mirror/commit/5ac1ca8f6168bd18967c49e1036a76ecf200addc

+ 5 - 5
Source/ThirdParty/AngelScript/include/angelscript.h

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2020 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -40,8 +40,8 @@
 #ifndef ANGELSCRIPT_H
 #ifndef ANGELSCRIPT_H
 #define ANGELSCRIPT_H
 #define ANGELSCRIPT_H
 
 
-// Urho3D: Define AS_MAX_PORTABILITY for Web and 64-bit ARM / MCST Elbrus 2000 platforms
-#if defined(__EMSCRIPTEN__) || defined(__aarch64__) || defined(__e2k__)
+// Urho3D: Define AS_MAX_PORTABILITY for Web and MCST Elbrus 2000 platforms
+#if defined(__EMSCRIPTEN__) || defined(__e2k__)
 #define AS_MAX_PORTABILITY
 #define AS_MAX_PORTABILITY
 #endif
 #endif
 
 
@@ -64,8 +64,8 @@ BEGIN_AS_NAMESPACE
 
 
 // AngelScript version
 // AngelScript version
 
 
-#define ANGELSCRIPT_VERSION        23500
-#define ANGELSCRIPT_VERSION_STRING "2.35.0"
+#define ANGELSCRIPT_VERSION        23501
+#define ANGELSCRIPT_VERSION_STRING "2.35.1"
 
 
 // Data types
 // Data types
 
 

+ 47 - 8
Source/ThirdParty/AngelScript/source/as_builder.cpp

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2020 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -1603,8 +1603,29 @@ int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScri
 	}
 	}
 
 
 #ifndef AS_NO_COMPILER
 #ifndef AS_NO_COMPILER
-	// Check against class types
+	// Check against interface types
 	asUINT n;
 	asUINT n;
+	for (n = 0; n < interfaceDeclarations.GetLength(); n++)
+	{
+		if (interfaceDeclarations[n]->name == name &&
+			interfaceDeclarations[n]->typeInfo->nameSpace == ns)
+		{
+			if (code)
+			{
+				asCString str;
+				if (ns->name != "")
+					str = ns->name + "::" + name;
+				else
+					str = name;
+				str.Format(TXT_NAME_CONFLICT_s_INTF, str.AddressOf());
+				WriteError(str, code, node);
+			}
+
+			return -1;
+		}
+	}
+
+	// Check against class types
 	for( n = 0; n < classDeclarations.GetLength(); n++ )
 	for( n = 0; n < classDeclarations.GetLength(); n++ )
 	{
 	{
 		if( classDeclarations[n]->name == name &&
 		if( classDeclarations[n]->name == name &&
@@ -2081,10 +2102,12 @@ int asCBuilder::RegisterMixinClass(asCScriptNode *node, asCScriptCode *file, asS
 
 
 	asCScriptNode *n = cl->firstChild;
 	asCScriptNode *n = cl->firstChild;
 
 
-	// Skip potential 'final' and 'shared' tokens
+	// Skip potential decorator tokens
 	while( n->tokenType == ttIdentifier &&
 	while( n->tokenType == ttIdentifier &&
 		   (file->TokenEquals(n->tokenPos, n->tokenLength, FINAL_TOKEN) ||
 		   (file->TokenEquals(n->tokenPos, n->tokenLength, FINAL_TOKEN) ||
-		    file->TokenEquals(n->tokenPos, n->tokenLength, SHARED_TOKEN)) )
+		    file->TokenEquals(n->tokenPos, n->tokenLength, SHARED_TOKEN) ||
+			file->TokenEquals(n->tokenPos, n->tokenLength, ABSTRACT_TOKEN) ||
+			file->TokenEquals(n->tokenPos, n->tokenLength, EXTERNAL_TOKEN)) )
 	{
 	{
 		// Report error, because mixin class cannot be final or shared
 		// Report error, because mixin class cannot be final or shared
 		asCString msg;
 		asCString msg;
@@ -2922,7 +2945,8 @@ void asCBuilder::CompileInterfaces()
 		// If any of the derived interfaces are found after this interface, then move this to the end of the list
 		// If any of the derived interfaces are found after this interface, then move this to the end of the list
 		for( asUINT m = n+1; m < interfaceDeclarations.GetLength(); m++ )
 		for( asUINT m = n+1; m < interfaceDeclarations.GetLength(); m++ )
 		{
 		{
-			if( intfType->Implements(interfaceDeclarations[m]->typeInfo) )
+			if( intfType != interfaceDeclarations[m]->typeInfo &&
+				intfType->Implements(interfaceDeclarations[m]->typeInfo) )
 			{
 			{
 				interfaceDeclarations.RemoveIndex(n);
 				interfaceDeclarations.RemoveIndex(n);
 				interfaceDeclarations.PushLast(intfDecl);
 				interfaceDeclarations.PushLast(intfDecl);
@@ -4769,7 +4793,7 @@ int asCBuilder::RegisterScriptFunctionFromNode(asCScriptNode *node, asCScriptCod
 	return RegisterScriptFunction(node, file, objType, isInterface, isGlobalFunction, ns, isExistingShared, isMixin, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, funcTraits);
 	return RegisterScriptFunction(node, file, objType, isInterface, isGlobalFunction, ns, isExistingShared, isMixin, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, funcTraits);
 }
 }
 
 
-asCScriptFunction *asCBuilder::RegisterLambda(asCScriptNode *node, asCScriptCode *file, asCScriptFunction *funcDef, const asCString &name, asSNameSpace *ns)
+asCScriptFunction *asCBuilder::RegisterLambda(asCScriptNode *node, asCScriptCode *file, asCScriptFunction *funcDef, const asCString &name, asSNameSpace *ns, bool isShared)
 {
 {
 	// Get the parameter names from the node
 	// Get the parameter names from the node
 	asCArray<asCString> parameterNames;
 	asCArray<asCString> parameterNames;
@@ -4792,7 +4816,9 @@ asCScriptFunction *asCBuilder::RegisterLambda(asCScriptNode *node, asCScriptCode
 
 
 	// Get the return and parameter types from the funcDef
 	// Get the return and parameter types from the funcDef
 	asCString funcName = name;
 	asCString funcName = name;
-	int r = RegisterScriptFunction(args, file, 0, 0, true, ns, false, false, funcName, funcDef->returnType, parameterNames, funcDef->parameterTypes, funcDef->inOutFlags, defaultArgs, asSFunctionTraits());
+	asSFunctionTraits traits;
+	traits.SetTrait(asTRAIT_SHARED, isShared);
+	int r = RegisterScriptFunction(args, file, 0, 0, true, ns, false, false, funcName, funcDef->returnType, parameterNames, funcDef->parameterTypes, funcDef->inOutFlags, defaultArgs, traits);
 	if( r < 0 )
 	if( r < 0 )
 		return 0;
 		return 0;
 
 
@@ -5477,7 +5503,7 @@ void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *ob
 		// TODO: child funcdef: A scope can include a template type, e.g. array<ns::type>
 		// TODO: child funcdef: A scope can include a template type, e.g. array<ns::type>
 		int n = scope.FindLast("::");
 		int n = scope.FindLast("::");
 		asCString className = n >= 0 ? scope.SubString(n+2) : scope;
 		asCString className = n >= 0 ? scope.SubString(n+2) : scope;
-		asCString nsName = n >= 0 ? scope.SubString(0, n) : "";
+		asCString nsName = n >= 0 ? scope.SubString(0, n) : asCString("");
 
 
 		// If a namespace was specifically defined, then this must be used
 		// If a namespace was specifically defined, then this must be used
 		asSNameSpace *ns = 0;
 		asSNameSpace *ns = 0;
@@ -5961,6 +5987,19 @@ asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCod
 	{
 	{
 		if( n->tokenType == ttOpenBracket )
 		if( n->tokenType == ttOpenBracket )
 		{
 		{
+			if (isImplicitHandle)
+			{
+				// Make the type a handle
+				if (dt.MakeHandle(true, acceptHandleForScope) < 0)
+				{
+					if (reportError)
+						WriteError(TXT_OBJECT_HANDLE_NOT_SUPPORTED, file, n);
+					if (isValid)
+						*isValid = false;
+				}
+				isImplicitHandle = false;
+			}
+
 			// Make sure the sub type can be instantiated
 			// Make sure the sub type can be instantiated
 			if( !dt.CanBeInstantiated() )
 			if( !dt.CanBeInstantiated() )
 			{
 			{

+ 2 - 2
Source/ThirdParty/AngelScript/source/as_builder.h

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2019 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -217,7 +217,7 @@ protected:
 	int                RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
 	int                RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
 	int                RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
 	int                RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
 	int                RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns, asCObjectType *parent);
 	int                RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns, asCObjectType *parent);
-	asCScriptFunction *RegisterLambda(asCScriptNode *node, asCScriptCode *file, asCScriptFunction *funcDef, const asCString &name, asSNameSpace *ns);
+	asCScriptFunction *RegisterLambda(asCScriptNode *node, asCScriptCode *file, asCScriptFunction *funcDef, const asCString &name, asSNameSpace *ns, bool isShared);
 	void               CompleteFuncDef(sFuncDef *funcDef);
 	void               CompleteFuncDef(sFuncDef *funcDef);
 	void               CompileInterfaces();
 	void               CompileInterfaces();
 	void               CompileClasses(asUINT originalNumTempl);
 	void               CompileClasses(asUINT originalNumTempl);

+ 2 - 3
Source/ThirdParty/AngelScript/source/as_callfunc.cpp

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2020 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -55,8 +55,7 @@ BEGIN_AS_NAMESPACE
 
 
 int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, void *auxiliary, asSSystemFunctionInterface *internal)
 int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, void *auxiliary, asSSystemFunctionInterface *internal)
 {
 {
-	memset(internal, 0, sizeof(asSSystemFunctionInterface));
-
+	internal->Clear();
 	internal->func      = ptr.ptr.f.func;
 	internal->func      = ptr.ptr.f.func;
 	internal->auxiliary = 0;
 	internal->auxiliary = 0;
 
 

+ 27 - 3
Source/ThirdParty/AngelScript/source/as_callfunc.h

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2020 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -119,13 +119,35 @@ struct asSSystemFunctionInterface
 	};
 	};
 	asCArray<SClean>     cleanArgs;
 	asCArray<SClean>     cleanArgs;
 
 
-	asSSystemFunctionInterface() : func(0), baseOffset(0), callConv(ICC_GENERIC_FUNC), hostReturnInMemory(false), hostReturnFloat(false), hostReturnSize(0), paramSize(0), takesObjByVal(false), returnAutoHandle(false), compositeOffset(0), isCompositeIndirect(false), auxiliary(0) {}
+	asSSystemFunctionInterface()
+	{ 
+		Clear(); 
+	}
 
 
 	asSSystemFunctionInterface(const asSSystemFunctionInterface &in)
 	asSSystemFunctionInterface(const asSSystemFunctionInterface &in)
 	{
 	{
 		*this = in;
 		*this = in;
 	}
 	}
 
 
+	void Clear()
+	{
+		func                = 0;
+		baseOffset          = 0;
+		callConv            = ICC_GENERIC_FUNC;
+		hostReturnInMemory  = false;
+		hostReturnFloat     = false;
+		hostReturnSize      = 0;
+		paramSize           = 0;
+		takesObjByVal       = false;
+		returnAutoHandle    = false;
+		compositeOffset     = 0;
+		isCompositeIndirect = false;
+		auxiliary           = 0;
+
+		paramAutoHandles.SetLength(0);
+		cleanArgs.SetLength(0);
+	}
+
 	asSSystemFunctionInterface &operator=(const asSSystemFunctionInterface &in)
 	asSSystemFunctionInterface &operator=(const asSSystemFunctionInterface &in)
 	{
 	{
 		func                = in.func;
 		func                = in.func;
@@ -136,12 +158,14 @@ struct asSSystemFunctionInterface
 		hostReturnSize      = in.hostReturnSize;
 		hostReturnSize      = in.hostReturnSize;
 		paramSize           = in.paramSize;
 		paramSize           = in.paramSize;
 		takesObjByVal       = in.takesObjByVal;
 		takesObjByVal       = in.takesObjByVal;
-		paramAutoHandles    = in.paramAutoHandles;
 		returnAutoHandle    = in.returnAutoHandle;
 		returnAutoHandle    = in.returnAutoHandle;
 		compositeOffset     = in.compositeOffset;
 		compositeOffset     = in.compositeOffset;
 		isCompositeIndirect = in.isCompositeIndirect;
 		isCompositeIndirect = in.isCompositeIndirect;
 		auxiliary           = in.auxiliary;
 		auxiliary           = in.auxiliary;
+
 		cleanArgs           = in.cleanArgs;
 		cleanArgs           = in.cleanArgs;
+		paramAutoHandles    = in.paramAutoHandles;
+
 		return *this;
 		return *this;
 	}
 	}
 };
 };

+ 2 - 2
Source/ThirdParty/AngelScript/source/as_callfunc_arm64.cpp

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2020-2020 Andreas Jonsson
+   Copyright (c) 2020-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -110,7 +110,7 @@ static inline bool IsRegisterHFA(const asCDataType &type)
 
 
 	if( typeInfo == nullptr ||
 	if( typeInfo == nullptr ||
 		(typeInfo->flags & asOBJ_APP_CLASS_ALLFLOATS) == 0 ||
 		(typeInfo->flags & asOBJ_APP_CLASS_ALLFLOATS) == 0 ||
-		type.IsObjectHandle() && type.IsReference() )
+		type.IsObjectHandle() || type.IsReference() )
 		return false;
 		return false;
 
 
 	const bool doubles = (typeInfo->flags & asOBJ_APP_CLASS_ALIGN8) != 0;
 	const bool doubles = (typeInfo->flags & asOBJ_APP_CLASS_ALIGN8) != 0;

+ 9 - 1
Source/ThirdParty/AngelScript/source/as_callfunc_arm64_gcc.S

@@ -1,6 +1,6 @@
 //
 //
 //  AngelCode Scripting Library
 //  AngelCode Scripting Library
-//  Copyright (c) 2020-2020 Andreas Jonsson
+//  Copyright (c) 2020-2021 Andreas Jonsson
 //
 //
 //  This software is provided 'as-is', without any express or implied
 //  This software is provided 'as-is', without any express or implied
 //  warranty. In no event will the authors be held liable for any
 //  warranty. In no event will the authors be held liable for any
@@ -35,6 +35,10 @@
 
 
 // Compile with GCC/GAS
 // Compile with GCC/GAS
 
 
+#if !defined(AS_MAX_PORTABILITY)
+
+#if defined(__aarch64__)
+
 .arch armv8-a
 .arch armv8-a
 .text
 .text
 
 
@@ -217,3 +221,7 @@ CallARM64RetInMemory:
 	.cfi_def_cfa_offset 0
 	.cfi_def_cfa_offset 0
     ret
     ret
     .cfi_endproc
     .cfi_endproc
+
+#endif /* __aarch64__ */
+
+#endif /* !AS_MAX_PORTABILITY */

+ 127 - 53
Source/ThirdParty/AngelScript/source/as_compiler.cpp

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2020 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -1514,7 +1514,8 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asCExprContext *ctx, as
 			else if( ctx->type.dataType.IsNullHandle() )
 			else if( ctx->type.dataType.IsNullHandle() )
 			{
 			{
 				// Make sure the argument type can support handles (or is itself a handle)
 				// Make sure the argument type can support handles (or is itself a handle)
-				if( !dt.SupportHandles() && !dt.IsObjectHandle() )
+				// Don't allow null handle to be converted to an object type of ASHANDLE here, that would require more logic to call the constructor (which should be handled in ImplicitConversion)
+				if( (!dt.SupportHandles() && !dt.IsObjectHandle()) || (dt.GetTypeInfo() && (dt.GetTypeInfo()->GetFlags() & asOBJ_ASHANDLE)) )
 				{
 				{
 					asCString str;
 					asCString str;
 					str.Format(TXT_CANT_IMPLICITLY_CONVERT_s_TO_s, ctx->type.dataType.Format(outFunc->nameSpace).AddressOf(), param.Format(outFunc->nameSpace).AddressOf());
 					str.Format(TXT_CANT_IMPLICITLY_CONVERT_s_TO_s, ctx->type.dataType.Format(outFunc->nameSpace).AddressOf(), param.Format(outFunc->nameSpace).AddressOf());
@@ -2697,7 +2698,6 @@ bool asCCompiler::CompileAutoType(asCDataType &type, asCExprContext &compiledCtx
 				
 				
 			// For types that support handles auto should prefer handle 
 			// For types that support handles auto should prefer handle 
 			// as it is more efficient than making a copy
 			// as it is more efficient than making a copy
-			// TODO: 'auto a = ...;' and 'auto @a = ...;' works the same in this case. Is this what we want?
 			if( newType.SupportHandles() )
 			if( newType.SupportHandles() )
 				newType.MakeHandle(true);
 				newType.MakeHandle(true);
 
 
@@ -3164,7 +3164,7 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, co
 		}
 		}
 		else
 		else
 		{
 		{
-			// Call the default constructur, then call the assignment operator
+			// Call the default constructor, then call the assignment operator
 			asCExprContext ctx(engine);
 			asCExprContext ctx(engine);
 
 
 			// Call the default constructor here
 			// Call the default constructor here
@@ -3813,7 +3813,7 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr
 				asCExprContext ctx(engine);
 				asCExprContext ctx(engine);
 				DoAssignment(&ctx, &lctx, &rctx, valueNode, valueNode, ttAssignment, valueNode);
 				DoAssignment(&ctx, &lctx, &rctx, valueNode, valueNode, ttAssignment, valueNode);
 
 
-				if( !lctx.type.dataType.IsPrimitive() )
+				if( !ctx.type.dataType.IsPrimitive() )
 					ctx.bc.Instr(asBC_PopPtr);
 					ctx.bc.Instr(asBC_PopPtr);
 
 
 				// Release temporary variables used by expression
 				// Release temporary variables used by expression
@@ -3905,7 +3905,7 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr
 						asCExprContext ctx(engine);
 						asCExprContext ctx(engine);
 						DoAssignment(&ctx, &lctx, &rctx, valueNode, valueNode, ttAssignment, valueNode);
 						DoAssignment(&ctx, &lctx, &rctx, valueNode, valueNode, ttAssignment, valueNode);
 
 
-						if( !lctx.type.dataType.IsPrimitive() )
+						if( !ctx.type.dataType.IsPrimitive() )
 							ctx.bc.Instr(asBC_PopPtr);
 							ctx.bc.Instr(asBC_PopPtr);
 
 
 						// Release temporary variables used by expression
 						// Release temporary variables used by expression
@@ -5274,7 +5274,7 @@ int asCCompiler::AllocateVariable(const asCDataType &type, bool isTemporary, boo
 
 
 	bool isOnHeap = true;
 	bool isOnHeap = true;
 	if( t.IsPrimitive() ||
 	if( t.IsPrimitive() ||
-		(t.GetTypeInfo() && (t.GetTypeInfo()->GetFlags() & asOBJ_VALUE) && !forceOnHeap) )
+		(t.GetTypeInfo() && (t.GetTypeInfo()->GetFlags() & asOBJ_VALUE) && !forceOnHeap && !asReference) )
 	{
 	{
 		// Primitives and value types (unless overridden) are allocated on the stack
 		// Primitives and value types (unless overridden) are allocated on the stack
 		isOnHeap = false;
 		isOnHeap = false;
@@ -6107,7 +6107,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asCExprContext *ctx, const
 	// Start by implicitly converting constant values
 	// Start by implicitly converting constant values
 	if( ctx->type.isConstant )
 	if( ctx->type.isConstant )
 	{
 	{
-		ImplicitConversionConstant(ctx, to, node, convType);
+		ImplicitConversionConstant(ctx, to, generateCode ? node : 0, convType);
 		ctx->type.dataType.MakeReadOnly(to.IsReadOnly());
 		ctx->type.dataType.MakeReadOnly(to.IsReadOnly());
 		return cost;
 		return cost;
 	}
 	}
@@ -6483,7 +6483,7 @@ asUINT asCCompiler::ImplicitConvLambdaToFunc(asCExprContext *ctx, const asCDataT
 			name.Format("$%s$%d", outFunc->GetDeclaration(), numLambdas++);
 			name.Format("$%s$%d", outFunc->GetDeclaration(), numLambdas++);
 
 
 		// Register the lambda with the builder for later compilation
 		// Register the lambda with the builder for later compilation
-		asCScriptFunction *func = builder->RegisterLambda(ctx->exprNode, script, funcDef, name, outFunc->nameSpace);
+		asCScriptFunction *func = builder->RegisterLambda(ctx->exprNode, script, funcDef, name, outFunc->nameSpace, outFunc->IsShared());
 		asASSERT( func == 0 || funcDef->IsSignatureExceptNameEqual(func) );
 		asASSERT( func == 0 || funcDef->IsSignatureExceptNameEqual(func) );
 		ctx->bc.InstrPTR(asBC_FuncPtr, func);
 		ctx->bc.InstrPTR(asBC_FuncPtr, func);
 
 
@@ -7175,12 +7175,23 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asCExprContext *ctx, const asCDat
 	asUINT cost = ImplicitConvObjectRef(ctx, to, node, convType, generateCode);
 	asUINT cost = ImplicitConvObjectRef(ctx, to, node, convType, generateCode);
 
 
 	// If the desired type is an asOBJ_ASHANDLE then we'll assume it is allowed to implicitly
 	// If the desired type is an asOBJ_ASHANDLE then we'll assume it is allowed to implicitly
-	// construct the object through any of the available constructors
+	// construct the object through any of the available constructors (except those marked as explicit)
 	if( to.GetTypeInfo() && (to.GetTypeInfo()->flags & asOBJ_ASHANDLE) && to.GetTypeInfo() != ctx->type.dataType.GetTypeInfo() && allowObjectConstruct )
 	if( to.GetTypeInfo() && (to.GetTypeInfo()->flags & asOBJ_ASHANDLE) && to.GetTypeInfo() != ctx->type.dataType.GetTypeInfo() && allowObjectConstruct )
 	{
 	{
 		asCArray<int> funcs;
 		asCArray<int> funcs;
 		funcs = CastToObjectType(to.GetTypeInfo())->beh.constructors;
 		funcs = CastToObjectType(to.GetTypeInfo())->beh.constructors;
 
 
+		// Don't allow use of explicit constructors/factories in implicit conversions
+		if (convType == asIC_IMPLICIT_CONV)
+		{
+			for (asUINT n = 0; n < funcs.GetLength(); n++)
+			{
+				asCScriptFunction* desc = builder->GetFunctionDescription(funcs[n]);
+				if (desc->IsExplicit())
+					funcs.RemoveIndex(n--);
+			}
+		}
+
 		asCArray<asCExprContext *> args;
 		asCArray<asCExprContext *> args;
 		args.PushLast(ctx);
 		args.PushLast(ctx);
 
 
@@ -8050,17 +8061,28 @@ void asCCompiler::ImplicitConversionConstant(asCExprContext *from, const asCData
 			// Verify if it is possible
 			// Verify if it is possible
 			if( to.GetSizeInMemoryBytes() == 1 )
 			if( to.GetSizeInMemoryBytes() == 1 )
 			{
 			{
-				if( asBYTE(from->type.GetConstantDW()) != from->type.GetConstantDW() )
+				if( (from->type.dataType.GetSizeInMemoryBytes() == 2 && asBYTE(from->type.GetConstantW()) != from->type.GetConstantW()) ||
+					(from->type.dataType.GetSizeInMemoryBytes() == 4 && asBYTE(from->type.GetConstantDW()) != from->type.GetConstantDW()) ||
+					(from->type.dataType.GetSizeInMemoryBytes() == 8 && asBYTE(from->type.GetConstantQW()) != from->type.GetConstantQW()) )
 					if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node);
 					if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node);
 
 
-				from->type.SetConstantB(asCDataType::CreatePrimitive(to.GetTokenType(), true), asBYTE(from->type.GetConstantDW()));
+				if( from->type.dataType.GetSizeInMemoryBytes() == 2 )
+					from->type.SetConstantB(asCDataType::CreatePrimitive(to.GetTokenType(), true), asBYTE(from->type.GetConstantW()));
+				else if (from->type.dataType.GetSizeInMemoryBytes() == 4)
+					from->type.SetConstantB(asCDataType::CreatePrimitive(to.GetTokenType(), true), asBYTE(from->type.GetConstantDW()));
+				else if (from->type.dataType.GetSizeInMemoryBytes() == 8)
+					from->type.SetConstantB(asCDataType::CreatePrimitive(to.GetTokenType(), true), asBYTE(from->type.GetConstantQW()));
 			}
 			}
 			else if( to.GetSizeInMemoryBytes() == 2 )
 			else if( to.GetSizeInMemoryBytes() == 2 )
 			{
 			{
-				if( asWORD(from->type.GetConstantDW()) != from->type.GetConstantDW())
+				if( (from->type.dataType.GetSizeInMemoryBytes() == 4 && asWORD(from->type.GetConstantDW()) != from->type.GetConstantDW()) ||
+					(from->type.dataType.GetSizeInMemoryBytes() == 8 && asWORD(from->type.GetConstantQW()) != from->type.GetConstantQW()) )
 					if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node);
 					if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node);
 
 
-				from->type.SetConstantW(asCDataType::CreatePrimitive(to.GetTokenType(), true), asWORD(from->type.GetConstantDW()));
+				if (from->type.dataType.GetSizeInMemoryBytes() == 4)
+					from->type.SetConstantW(asCDataType::CreatePrimitive(to.GetTokenType(), true), asWORD(from->type.GetConstantDW()));
+				else if (from->type.dataType.GetSizeInMemoryBytes() == 8)
+					from->type.SetConstantW(asCDataType::CreatePrimitive(to.GetTokenType(), true), asWORD(from->type.GetConstantQW()));
 			}
 			}
 			else if (to.GetSizeInMemoryBytes() == 4)
 			else if (to.GetSizeInMemoryBytes() == 4)
 			{
 			{
@@ -8657,7 +8679,7 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asCExprContext *ctx)
 		{
 		{
 			Error(TXT_EXPR_MUST_BE_BOOL, cexpr);
 			Error(TXT_EXPR_MUST_BE_BOOL, cexpr);
 			e.type.SetConstantB(asCDataType::CreatePrimitive(ttBool, true), true);
 			e.type.SetConstantB(asCDataType::CreatePrimitive(ttBool, true), true);
-		}
+		} 
 		ctype = e.type;
 		ctype = e.type;
 
 
 		if( ProcessPropertyGetAccessor(&e, cexpr) < 0)
 		if( ProcessPropertyGetAccessor(&e, cexpr) < 0)
@@ -8680,44 +8702,22 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asCExprContext *ctx)
 		int rr = CompileAssignment(cexpr->next->next, &re);
 		int rr = CompileAssignment(cexpr->next->next, &re);
 		DetermineSingleFunc(&re, cexpr->next->next);
 		DetermineSingleFunc(&re, cexpr->next->next);
 
 
-		if( lr >= 0 && rr >= 0 )
+		if (lr >= 0 && rr >= 0)
 		{
 		{
 			// Don't allow any operators on expressions that take address of class method
 			// Don't allow any operators on expressions that take address of class method
-			if( le.IsClassMethod() || re.IsClassMethod() )
+			if (le.IsClassMethod() || re.IsClassMethod())
 			{
 			{
 				Error(TXT_INVALID_OP_ON_METHOD, expr);
 				Error(TXT_INVALID_OP_ON_METHOD, expr);
 				return -1;
 				return -1;
 			}
 			}
 
 
-			if( ProcessPropertyGetAccessor(&le, cexpr->next) < 0 )
+			if (ProcessPropertyGetAccessor(&le, cexpr->next) < 0)
 				return -1;
 				return -1;
-			if( ProcessPropertyGetAccessor(&re, cexpr->next->next) < 0 )
+			if (ProcessPropertyGetAccessor(&re, cexpr->next->next) < 0)
 				return -1;
 				return -1;
 
 
 			bool isExplicitHandle = le.type.isExplicitHandle || re.type.isExplicitHandle;
 			bool isExplicitHandle = le.type.isExplicitHandle || re.type.isExplicitHandle;
 
 
-			// Allow a 0 or null in the first case to be implicitly converted to the second type
-			if( le.type.isConstant && le.type.GetConstantData() == 0 && le.type.dataType.IsIntegerType() )
-			{
-				asCDataType to = re.type.dataType;
-				to.MakeReference(false);
-				to.MakeReadOnly(true);
-				ImplicitConversionConstant(&le, to, cexpr->next, asIC_IMPLICIT_CONV);
-			}
-			else if( le.type.IsNullConstant() )
-			{
-				asCDataType to = re.type.dataType;
-				to.MakeHandle(true);
-				ImplicitConversion(&le, to, cexpr->next, asIC_IMPLICIT_CONV);
-			}
-
-			// Allow either case to be converted to const @ if the other is const @
-			if( (le.type.dataType.IsHandleToConst() && !le.type.IsNullConstant()) || (re.type.dataType.IsHandleToConst() && !re.type.dataType.IsNullHandle()) )
-			{
-				le.type.dataType.MakeHandleToConst(true);
-				re.type.dataType.MakeHandleToConst(true);
-			}
-
 			// Allow an anonymous initialization list to be converted to the type in the other condition
 			// Allow an anonymous initialization list to be converted to the type in the other condition
 			if (le.IsAnonymousInitList() && re.type.dataType.GetBehaviour() && re.type.dataType.GetBehaviour()->listFactory)
 			if (le.IsAnonymousInitList() && re.type.dataType.GetBehaviour() && re.type.dataType.GetBehaviour()->listFactory)
 			{
 			{
@@ -8734,7 +8734,7 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asCExprContext *ctx)
 				ImplicitConversion(&re, to, cexpr->next->next, asIC_IMPLICIT_CONV);
 				ImplicitConversion(&re, to, cexpr->next->next, asIC_IMPLICIT_CONV);
 			}
 			}
 
 
-			if (le.IsAnonymousInitList() )
+			if (le.IsAnonymousInitList())
 			{
 			{
 				Error(TXT_CANNOT_RESOLVE_AUTO, cexpr->next);
 				Error(TXT_CANNOT_RESOLVE_AUTO, cexpr->next);
 				return -1;
 				return -1;
@@ -8745,6 +8745,81 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asCExprContext *ctx)
 				return -1;
 				return -1;
 			}
 			}
 
 
+			// Try to perform an implicit cast to make the two operands of the same type
+			// Choose the conversion that is the least costly
+			if (le.type.dataType != re.type.dataType)
+			{
+				asCExprContext tmp(engine);
+				tmp.type = le.type;
+				tmp.type.dataType.MakeReference(false);
+				asUINT costAtoB = ImplicitConversion(&tmp, re.type.dataType, cexpr->next, asIC_IMPLICIT_CONV, false);
+				if (!tmp.type.dataType.IsEqualExceptRef(re.type.dataType))
+					costAtoB = 0xFFFFFFFF;
+				tmp.type = re.type;
+				tmp.type.dataType.MakeReference(false);
+				asUINT costBtoA = ImplicitConversion(&tmp, le.type.dataType, cexpr->next->next, asIC_IMPLICIT_CONV, false);
+				if (!tmp.type.dataType.IsEqualExceptRef(le.type.dataType))
+					costBtoA = 0xFFFFFFFF;
+
+				if (costAtoB < costBtoA && costAtoB != 0xFFFFFFFF)
+				{
+					Dereference(&le, true);
+					ImplicitConversion(&le, re.type.dataType, cexpr->next, asIC_IMPLICIT_CONV, true);
+				}
+				else if (costAtoB > costBtoA && costBtoA != 0xFFFFFFFF)
+				{
+					Dereference(&re, true);
+					ImplicitConversion(&re, le.type.dataType, cexpr->next->next, asIC_IMPLICIT_CONV, true);
+				}
+
+				// If the cost for conversion is the same in both directions we have an ambigious situation, 
+				// which we do not resolve. In that case the script need to perform an explicit conversion
+			}
+
+			// Allow a 0 to be implicitly converted to the other type
+			if (le.type.isConstant && le.type.GetConstantData() == 0 && le.type.dataType.IsIntegerType())
+			{
+				asCDataType to = re.type.dataType;
+				to.MakeReference(false);
+				to.MakeReadOnly(true);
+				ImplicitConversionConstant(&le, to, cexpr->next, asIC_IMPLICIT_CONV);
+			}
+			else if( re.type.isConstant && re.type.GetConstantData() == 0 && re.type.dataType.IsIntegerType())
+			{
+				asCDataType to = le.type.dataType;
+				to.MakeReference(false);
+				to.MakeReadOnly(true);
+				ImplicitConversionConstant(&re, to, cexpr->next->next, asIC_IMPLICIT_CONV);
+			}
+
+			// Allow expression to be converted to handle if the other is handle
+			if (!le.type.dataType.IsObjectHandle() && re.type.dataType.IsObjectHandle() && le.type.dataType.GetTypeInfo() == re.type.dataType.GetTypeInfo() )
+			{
+				asCDataType dt = le.type.dataType;
+				dt.MakeHandle(true);
+				ImplicitConversion(&le, dt, cexpr->next, asIC_IMPLICIT_CONV);
+			}
+			if (!re.type.dataType.IsObjectHandle() && le.type.dataType.IsObjectHandle() && le.type.dataType.GetTypeInfo() == re.type.dataType.GetTypeInfo())
+			{
+				asCDataType dt = re.type.dataType;
+				dt.MakeHandle(true);
+				ImplicitConversion(&re, dt, cexpr->next->next, asIC_IMPLICIT_CONV);
+			}
+
+			// Allow either case to be converted to const @ if the other is const @
+			if( (le.type.dataType.IsHandleToConst() && !le.type.IsNullConstant()) || (re.type.dataType.IsHandleToConst() && !re.type.dataType.IsNullHandle()) )
+			{
+				le.type.dataType.MakeHandleToConst(true);
+				re.type.dataType.MakeHandleToConst(true);
+			}
+
+			// Make sure both expressions have the same type
+			if (!le.type.dataType.IsEqualExceptRefAndConst(re.type.dataType))
+			{
+				Error(TXT_BOTH_MUST_BE_SAME, expr);
+				return -1;
+			}
+
 			//---------------------------------
 			//---------------------------------
 			// Output the byte code
 			// Output the byte code
 			int afterLabel = nextLabel++;
 			int afterLabel = nextLabel++;
@@ -8773,10 +8848,6 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asCExprContext *ctx)
 				MergeExprBytecode(ctx, &re);
 				MergeExprBytecode(ctx, &re);
 				ctx->bc.Label((short)afterLabel);
 				ctx->bc.Label((short)afterLabel);
 
 
-				// Make sure both expressions have the same type
-				if( le.type.dataType != re.type.dataType )
-					Error(TXT_BOTH_MUST_BE_SAME, expr);
-
 				// Set the type of the result
 				// Set the type of the result
 				ctx->type = le.type;
 				ctx->type = le.type;
 			}
 			}
@@ -8817,7 +8888,7 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asCExprContext *ctx)
 				// with a stack offset (i.e. it will not be allowed to use asBC_VAR)
 				// with a stack offset (i.e. it will not be allowed to use asBC_VAR)
 
 
 				if( le.type.isLValue && re.type.isLValue &&
 				if( le.type.isLValue && re.type.isLValue &&
-					le.deferredParams.GetLength() == 0 && re.deferredParams.GetLength() ==0 &&
+					le.deferredParams.GetLength() == 0 && re.deferredParams.GetLength() == 0 &&
 					!le.type.isTemporary && !re.type.isTemporary &&
 					!le.type.isTemporary && !re.type.isTemporary &&
 					le.type.dataType == re.type.dataType )
 					le.type.dataType == re.type.dataType )
 				{
 				{
@@ -8935,6 +9006,9 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asCExprContext *ctx)
 					// Release the old temporary variable
 					// Release the old temporary variable
 					ReleaseTemporaryVariable(le.type, &ctx->bc);
 					ReleaseTemporaryVariable(le.type, &ctx->bc);
 
 
+					// Process any deferred arguments in the expressions as these must not survive until after the condition returns
+					ProcessDeferredParams(ctx);
+
 					ctx->bc.InstrINT(asBC_JMP, afterLabel);
 					ctx->bc.InstrINT(asBC_JMP, afterLabel);
 
 
 					// Start of the right expression
 					// Start of the right expression
@@ -8957,11 +9031,10 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asCExprContext *ctx)
 					// Release the old temporary variable
 					// Release the old temporary variable
 					ReleaseTemporaryVariable(re.type, &ctx->bc);
 					ReleaseTemporaryVariable(re.type, &ctx->bc);
 
 
-					ctx->bc.Label((short)afterLabel);
+					// Process any deferred arguments in the expressions as these must not survive until after the condition returns
+					ProcessDeferredParams(ctx);
 
 
-					// Make sure both expressions have the same type
-					if( !le.type.dataType.IsEqualExceptConst(re.type.dataType) )
-						Error(TXT_BOTH_MUST_BE_SAME, expr);
+					ctx->bc.Label((short)afterLabel);
 
 
 					// Set the temporary variable as output
 					// Set the temporary variable as output
 					ctx->type = rtemp;
 					ctx->type = rtemp;
@@ -9373,7 +9446,7 @@ asCCompiler::SYMBOLTYPE asCCompiler::SymbolLookup(const asCString &name, const a
 		// TODO: child funcdef: A scope can include a template type, e.g. array<ns::type>
 		// TODO: child funcdef: A scope can include a template type, e.g. array<ns::type>
 		int n = currScope.FindLast("::");
 		int n = currScope.FindLast("::");
 		asCString typeName = n >= 0 ? currScope.SubString(n + 2) : currScope;
 		asCString typeName = n >= 0 ? currScope.SubString(n + 2) : currScope;
-		asCString nsName = n >= 0 ? currScope.SubString(0, n) : "";
+		asCString nsName = n >= 0 ? currScope.SubString(0, n) : asCString("");
 
 
 		// If the scope represents a type that the current class inherits
 		// If the scope represents a type that the current class inherits
 		// from then that should be used instead of going through the namespaces
 		// from then that should be used instead of going through the namespaces
@@ -10995,7 +11068,8 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asCExprContext *ctx)
 			if( conv.type.dataType.IsEqualExceptRef(dt) && cost > 0 )
 			if( conv.type.dataType.IsEqualExceptRef(dt) && cost > 0 )
 			{
 			{
 				// Make sure the result is a reference, just as if to a local variable
 				// Make sure the result is a reference, just as if to a local variable
-				dt.MakeReference(true);
+				if( !dt.IsFuncdef() )
+					dt.MakeReference(true);
 
 
 				// Make sure any property accessor is already evaluated
 				// Make sure any property accessor is already evaluated
 				if( ProcessPropertyGetAccessor(args[0], args[0]->exprNode) < 0 )
 				if( ProcessPropertyGetAccessor(args[0], args[0]->exprNode) < 0 )

+ 78 - 42
Source/ThirdParty/AngelScript/source/as_config.h

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2020 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -252,26 +252,27 @@
 // compiler is the same for both, when this is so these flags are used to produce the
 // compiler is the same for both, when this is so these flags are used to produce the
 // right code.
 // right code.
 
 
-// AS_WIN       - Microsoft Windows
-// AS_LINUX     - Linux
-// AS_MAC       - Apple Macintosh
-// AS_BSD       - BSD based OS (FreeBSD, DragonFly, OpenBSD, etc)
-// AS_XBOX      - Microsoft XBox
-// AS_XBOX360   - Microsoft XBox 360
-// AS_PSP       - Sony Playstation Portable
-// AS_PSVITA    - Sony Playstation Vita
-// AS_PS2       - Sony Playstation 2
-// AS_PS3       - Sony Playstation 3
-// AS_DC        - Sega Dreamcast
-// AS_GC        - Nintendo GameCube
-// AS_WII       - Nintendo Wii
-// AS_WIIU      - Nintendo Wii U
-// AS_IPHONE    - Apple IPhone
-// AS_ANDROID   - Android
-// AS_HAIKU     - Haiku
-// AS_ILLUMOS   - Illumos like (OpenSolaris, OpenIndiana, NCP, etc)
-// AS_MARMALADE - Marmalade cross platform SDK (a layer on top of the OS)
-// AS_SUN       - Sun UNIX
+// AS_WIN            - Microsoft Windows
+// AS_LINUX          - Linux
+// AS_MAC            - Apple Macintosh
+// AS_BSD            - BSD based OS (FreeBSD, DragonFly, OpenBSD, etc)
+// AS_XBOX           - Microsoft XBox
+// AS_XBOX360        - Microsoft XBox 360
+// AS_PSP            - Sony Playstation Portable
+// AS_PSVITA         - Sony Playstation Vita
+// AS_PS2            - Sony Playstation 2
+// AS_PS3            - Sony Playstation 3
+// AS_DC             - Sega Dreamcast
+// AS_GC             - Nintendo GameCube
+// AS_WII            - Nintendo Wii
+// AS_WIIU           - Nintendo Wii U
+// AS_NINTENDOSWITCH - Nintendo Switch
+// AS_IPHONE         - Apple IPhone
+// AS_ANDROID        - Android
+// AS_HAIKU          - Haiku
+// AS_ILLUMOS        - Illumos like (OpenSolaris, OpenIndiana, NCP, etc)
+// AS_MARMALADE      - Marmalade cross platform SDK (a layer on top of the OS)
+// AS_SUN            - Sun UNIX
 
 
 
 
 
 
@@ -656,6 +657,37 @@
 		// Native calling conventions are not yet supported
 		// Native calling conventions are not yet supported
 		#define AS_MAX_PORTABILITY
 		#define AS_MAX_PORTABILITY
 
 
+	// Nintendo Switch
+	// Note, __SWITCH__ is not an official define in the Nintendo dev kit. 
+	// You need to manually add this to the project when compiling for Switch.
+	#elif defined(__SWITCH__)
+		#define AS_NINTENDOSWITCH
+
+		#if (!defined(__LP64__))
+			#error write me
+		#else
+			#define AS_ARM64
+			#undef STDCALL
+			#define STDCALL
+
+			#undef GNU_STYLE_VIRTUAL_METHOD
+			#undef AS_NO_THISCALL_FUNCTOR_METHOD
+
+			#define HAS_128_BIT_PRIMITIVES
+
+			#define CDECL_RETURN_SIMPLE_IN_MEMORY
+			#define STDCALL_RETURN_SIMPLE_IN_MEMORY
+			#define THISCALL_RETURN_SIMPLE_IN_MEMORY
+
+			#undef THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
+			#undef CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
+			#undef STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
+
+			#define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 5
+			#define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE    5
+			#define STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE  5
+		#endif
+
 	// Marmalade is a cross platform SDK. It uses g++ to compile for iOS and Android
 	// Marmalade is a cross platform SDK. It uses g++ to compile for iOS and Android
 	#elif defined(__S3E__)
 	#elif defined(__S3E__)
 		#ifndef AS_MARMALADE
 		#ifndef AS_MARMALADE
@@ -757,7 +789,7 @@
 			#undef STDCALL
 			#undef STDCALL
 			#define STDCALL
 			#define STDCALL
 
 
-		#elif (defined(__arm64__))
+		#elif (defined(__aarch64__))
 			// The IPhone 5S+ uses an ARM64 processor
 			// The IPhone 5S+ uses an ARM64 processor
 
 
 			// AngelScript currently doesn't support native calling
 			// AngelScript currently doesn't support native calling
@@ -779,7 +811,7 @@
 			#undef COMPLEX_RETURN_MASK
 			#undef COMPLEX_RETURN_MASK
 			#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
 			#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
 
 
-		#elif defined(__LP64__) && !defined(__ppc__) && !defined(__PPC__) && !defined(__arm64__)
+		#elif defined(__LP64__) && !defined(__ppc__) && !defined(__PPC__) && !defined(__aarch64__)
 			// http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/LowLevelABI/140-x86-64_Function_Calling_Conventions/x86_64.html#//apple_ref/doc/uid/TP40005035-SW1
 			// http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/LowLevelABI/140-x86-64_Function_Calling_Conventions/x86_64.html#//apple_ref/doc/uid/TP40005035-SW1
 			#define AS_X64_GCC
 			#define AS_X64_GCC
 			#undef AS_NO_THISCALL_FUNCTOR_METHOD
 			#undef AS_NO_THISCALL_FUNCTOR_METHOD
@@ -1091,30 +1123,40 @@
 		#undef COMPLEX_RETURN_MASK
 		#undef COMPLEX_RETURN_MASK
 		#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
 		#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
 
 
-		#if (defined(_ARM_) || defined(__arm__))
+		#if (defined(_ARM_) || defined(__arm__) || defined(__aarch64__) || defined(__AARCH64EL__))
 			// Android ARM
 			// Android ARM
 
 
-			// TODO: The stack unwind on exceptions currently fails due to the assembler code in as_callfunc_arm_gcc.S
-			#define AS_NO_EXCEPTIONS
-
 			#undef THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
 			#undef THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
 			#undef CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
 			#undef CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
 			#undef STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
 			#undef STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
 
 
-			#define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
-			#define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
-			#define STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
-
 			// The stdcall calling convention is not used on the arm cpu
 			// The stdcall calling convention is not used on the arm cpu
 			#undef STDCALL
 			#undef STDCALL
 			#define STDCALL
 			#define STDCALL
 
 
 			#undef GNU_STYLE_VIRTUAL_METHOD
 			#undef GNU_STYLE_VIRTUAL_METHOD
-
-			#define AS_ARM
 			#undef AS_NO_THISCALL_FUNCTOR_METHOD
 			#undef AS_NO_THISCALL_FUNCTOR_METHOD
-			#define AS_SOFTFP
-			#define AS_CALLEE_DESTROY_OBJ_BY_VAL
+
+			#if (!defined(__LP64__))
+				// TODO: The stack unwind on exceptions currently fails due to the assembler code in as_callfunc_arm_gcc.S
+				#define AS_NO_EXCEPTIONS
+
+				#define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
+				#define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
+				#define STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
+
+				#define AS_ARM
+				#define AS_SOFTFP
+				#define AS_CALLEE_DESTROY_OBJ_BY_VAL
+			#elif (defined(__LP64__) || defined(__aarch64__))
+				#define AS_ARM64
+
+				#define HAS_128_BIT_PRIMITIVES
+
+				#define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 5
+				#define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE    5
+				#define STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE  5
+			#endif
 		#elif (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__)
 		#elif (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__)
 			// Android Intel x86 (same config as Linux x86). Tested with Intel x86 Atom System Image.
 			// Android Intel x86 (same config as Linux x86). Tested with Intel x86 Atom System Image.
 
 
@@ -1123,7 +1165,7 @@
 			#define AS_X86
 			#define AS_X86
 			#undef AS_NO_THISCALL_FUNCTOR_METHOD
 			#undef AS_NO_THISCALL_FUNCTOR_METHOD
 
 
-		// Urho3D: Add support for Android Intel x86_64 and Android ARM 64bit
+		// Urho3D: Add support for Android Intel x86_64
 		#elif defined(__LP64__) && !defined(__aarch64__)
 		#elif defined(__LP64__) && !defined(__aarch64__)
 			// Android Intel x86_64 (same config as Linux x86_64). Tested with Intel x86_64 Atom System Image.
 			// Android Intel x86_64 (same config as Linux x86_64). Tested with Intel x86_64 Atom System Image.
 			#define AS_X64_GCC
 			#define AS_X64_GCC
@@ -1135,12 +1177,6 @@
 			// STDCALL is not available on 64bit Linux
 			// STDCALL is not available on 64bit Linux
 			#undef STDCALL
 			#undef STDCALL
 			#define STDCALL
 			#define STDCALL
-		#elif defined(__aarch64__)
-			// Doesn't support native calling for Android ARM 64bit yet
-			#define AS_MAX_PORTABILITY
-			// STDCALL is not available on ARM
-			#undef STDCALL
-			#define STDCALL
 		// Urho3D: end
 		// Urho3D: end
 
 
 		#elif defined(__mips__)
 		#elif defined(__mips__)

+ 29 - 10
Source/ThirdParty/AngelScript/source/as_context.cpp

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2020 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -2882,7 +2882,8 @@ void asCContext::ExecuteNext()
 			m_regs.stackPointer      = l_sp;
 			m_regs.stackPointer      = l_sp;
 			m_regs.stackFramePointer = l_fp;
 			m_regs.stackFramePointer = l_fp;
 
 
-			if( !(objType->flags & asOBJ_NOCOUNT) )
+			// Update ref counter for object types that require it
+			if( !(objType->flags & (asOBJ_NOCOUNT | asOBJ_VALUE)) )
 			{
 			{
 				// Release previous object held by destination pointer
 				// Release previous object held by destination pointer
 				if( *d != 0 && beh->release )
 				if( *d != 0 && beh->release )
@@ -3912,21 +3913,21 @@ void asCContext::ExecuteNext()
 			}
 			}
 			else
 			else
 			{
 			{
-				if( func->funcType == asFUNC_SCRIPT )
+				if (func->funcType == asFUNC_SCRIPT)
 				{
 				{
 					m_regs.programPointer++;
 					m_regs.programPointer++;
 					CallScriptFunction(func);
 					CallScriptFunction(func);
 				}
 				}
-				else if( func->funcType == asFUNC_DELEGATE )
+				else if (func->funcType == asFUNC_DELEGATE)
 				{
 				{
 					// Push the object pointer on the stack. There is always a reserved space for this so
 					// Push the object pointer on the stack. There is always a reserved space for this so
 					// we don't don't need to worry about overflowing the allocated memory buffer
 					// we don't don't need to worry about overflowing the allocated memory buffer
-					asASSERT( m_regs.stackPointer - AS_PTR_SIZE >= m_stackBlocks[m_stackIndex] );
+					asASSERT(m_regs.stackPointer - AS_PTR_SIZE >= m_stackBlocks[m_stackIndex]);
 					m_regs.stackPointer -= AS_PTR_SIZE;
 					m_regs.stackPointer -= AS_PTR_SIZE;
 					*(asPWORD*)m_regs.stackPointer = asPWORD(func->objForDelegate);
 					*(asPWORD*)m_regs.stackPointer = asPWORD(func->objForDelegate);
 
 
 					// Call the delegated method
 					// Call the delegated method
-					if( func->funcForDelegate->funcType == asFUNC_SYSTEM )
+					if (func->funcForDelegate->funcType == asFUNC_SYSTEM)
 					{
 					{
 						m_regs.stackPointer += CallSystemFunction(func->funcForDelegate->id, this);
 						m_regs.stackPointer += CallSystemFunction(func->funcForDelegate->id, this);
 
 
@@ -3942,16 +3943,33 @@ void asCContext::ExecuteNext()
 						CallInterfaceMethod(func->funcForDelegate);
 						CallInterfaceMethod(func->funcForDelegate);
 					}
 					}
 				}
 				}
-				else
+				else if (func->funcType == asFUNC_SYSTEM)
 				{
 				{
-					asASSERT( func->funcType == asFUNC_SYSTEM );
-
 					m_regs.stackPointer += CallSystemFunction(func->id, this);
 					m_regs.stackPointer += CallSystemFunction(func->id, this);
 
 
 					// Update program position after the call so the line number
 					// Update program position after the call so the line number
 					// is correct in case the system function queries it
 					// is correct in case the system function queries it
 					m_regs.programPointer++;
 					m_regs.programPointer++;
 				}
 				}
+				else if (func->funcType == asFUNC_IMPORTED)
+				{
+					m_regs.programPointer++;
+					int funcId = m_engine->importedFunctions[func->id & ~FUNC_IMPORTED]->boundFunctionId;
+					if (funcId > 0)
+						CallScriptFunction(m_engine->scriptFunctions[funcId]);
+					else
+					{
+						// Tell the exception handler to clean up the arguments to this method
+						m_needToCleanupArgs = true;
+
+						SetInternalException(TXT_UNBOUND_FUNCTION);
+					}
+				}
+				else
+				{
+					// Should not get here
+					asASSERT(false);
+				}
 			}
 			}
 
 
 			// Extract the values from the context again
 			// Extract the values from the context again
@@ -4141,7 +4159,8 @@ void asCContext::ExecuteNext()
 			m_regs.stackPointer      = l_sp;
 			m_regs.stackPointer      = l_sp;
 			m_regs.stackFramePointer = l_fp;
 			m_regs.stackFramePointer = l_fp;
 
 
-			if( !(objType->flags & asOBJ_NOCOUNT) )
+			// Update ref counter for object types that require it
+			if( !(objType->flags & (asOBJ_NOCOUNT | asOBJ_VALUE)) )
 			{
 			{
 				// Release previous object held by destination pointer
 				// Release previous object held by destination pointer
 				if( *d != 0 && beh->release )
 				if( *d != 0 && beh->release )

+ 20 - 9
Source/ThirdParty/AngelScript/source/as_module.cpp

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2020 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -1470,7 +1470,8 @@ const char *asCModule::GetImportedFunctionDeclaration(asUINT index) const
 	if( func == 0 ) return 0;
 	if( func == 0 ) return 0;
 
 
 	asCString *tempString = &asCThreadManager::GetLocalData()->string;
 	asCString *tempString = &asCThreadManager::GetLocalData()->string;
-	*tempString = func->GetDeclarationStr();
+	// TODO: Allow the application to decide if the parameter name should be included or not (requires change in the interface)
+	*tempString = func->GetDeclarationStr(true, true, false);
 
 
 	return tempString->AddressOf();
 	return tempString->AddressOf();
 }
 }
@@ -1759,11 +1760,11 @@ int asCModule::CompileGlobalVar(const char *sectionName, const char *code, int l
 }
 }
 
 
 // interface
 // interface
-int asCModule::CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asIScriptFunction **outFunc)
+int asCModule::CompileFunction(const char* sectionName, const char* code, int lineOffset, asDWORD compileFlags, asIScriptFunction** outFunc)
 {
 {
 	// Make sure the outFunc is null if the function fails, so the
 	// Make sure the outFunc is null if the function fails, so the
 	// application doesn't attempt to release a non-existent function
 	// application doesn't attempt to release a non-existent function
-	if( outFunc )
+	if (outFunc)
 		*outFunc = 0;
 		*outFunc = 0;
 
 
 #ifdef AS_NO_COMPILER
 #ifdef AS_NO_COMPILER
@@ -1774,19 +1775,19 @@ int asCModule::CompileFunction(const char *sectionName, const char *code, int li
 	return asNOT_SUPPORTED;
 	return asNOT_SUPPORTED;
 #else
 #else
 	// Validate arguments
 	// Validate arguments
-	if( code == 0 ||
-		(compileFlags != 0 && compileFlags != asCOMP_ADD_TO_MODULE) )
+	if (code == 0 ||
+		(compileFlags != 0 && compileFlags != asCOMP_ADD_TO_MODULE))
 		return asINVALID_ARG;
 		return asINVALID_ARG;
 
 
 	// Only one thread may build at one time
 	// Only one thread may build at one time
 	// TODO: It should be possible to have multiple threads perform compilations
 	// TODO: It should be possible to have multiple threads perform compilations
 	int r = m_engine->RequestBuild();
 	int r = m_engine->RequestBuild();
-	if( r < 0 )
+	if (r < 0)
 		return r;
 		return r;
 
 
 	// Prepare the engine
 	// Prepare the engine
 	m_engine->PrepareEngine();
 	m_engine->PrepareEngine();
-	if( m_engine->configFailed )
+	if (m_engine->configFailed)
 	{
 	{
 		m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
 		m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
 		m_engine->BuildCompleted();
 		m_engine->BuildCompleted();
@@ -1796,9 +1797,19 @@ int asCModule::CompileFunction(const char *sectionName, const char *code, int li
 	// Compile the single function
 	// Compile the single function
 	asCBuilder funcBuilder(m_engine, this);
 	asCBuilder funcBuilder(m_engine, this);
 	asCString str = code;
 	asCString str = code;
-	asCScriptFunction *func = 0;
+	asCScriptFunction* func = 0;
 	r = funcBuilder.CompileFunction(sectionName, str.AddressOf(), lineOffset, compileFlags, &func);
 	r = funcBuilder.CompileFunction(sectionName, str.AddressOf(), lineOffset, compileFlags, &func);
 
 
+	if (r >= 0)
+	{
+		// Invoke the JIT compiler if it has been set
+		asIJITCompiler* jit = m_engine->GetJITCompiler();
+		if (jit)
+		{
+			func->JITCompile();
+		}
+	}
+
 	m_engine->BuildCompleted();
 	m_engine->BuildCompleted();
 
 
 	if( r >= 0 && outFunc && func )
 	if( r >= 0 && outFunc && func )

+ 25 - 4
Source/ThirdParty/AngelScript/source/as_parser.cpp

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2019 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -2488,7 +2488,7 @@ asCScriptNode *asCParser::ParseScript(bool inBlock)
 	UNREACHABLE_RETURN;
 	UNREACHABLE_RETURN;
 }
 }
 
 
-// BNF:1: NAMESPACE     ::= 'namespace' IDENTIFIER '{' SCRIPT '}'
+// BNF:1: NAMESPACE     ::= 'namespace' IDENTIFIER {'::' IDENTIFIER} '{' SCRIPT '}'
 asCScriptNode *asCParser::ParseNamespace()
 asCScriptNode *asCParser::ParseNamespace()
 {
 {
 	asCScriptNode *node = CreateNode(snNamespace);
 	asCScriptNode *node = CreateNode(snNamespace);
@@ -2505,11 +2505,32 @@ asCScriptNode *asCParser::ParseNamespace()
 		Error(InsteadFound(t1), &t1);
 		Error(InsteadFound(t1), &t1);
 	}
 	}
 
 
-	// TODO: namespace: Allow declaration of multiple nested namespace with namespace A::B::C { }
 	node->AddChildLast(ParseIdentifier());
 	node->AddChildLast(ParseIdentifier());
 	if( isSyntaxError ) return node;
 	if( isSyntaxError ) return node;
 
 
+	asCScriptNode *lowestNode = node;
 	GetToken(&t1);
 	GetToken(&t1);
+	while (t1.type == ttScope)
+	{
+		lowestNode->UpdateSourcePos(t1.pos, t1.length);
+
+		asCScriptNode *scopeNode = CreateNode(snScript);
+		if (scopeNode == 0) 
+			return 0;
+		lowestNode->AddChildLast(scopeNode);
+
+		lowestNode = CreateNode(snNamespace);
+		if (lowestNode == 0) 
+			return 0;
+
+		scopeNode->AddChildLast(lowestNode);
+		lowestNode->AddChildLast(ParseIdentifier());
+		if (isSyntaxError)
+			return node;
+
+		GetToken(&t1);
+	}
+	
 	if( t1.type == ttStartStatementBlock )
 	if( t1.type == ttStartStatementBlock )
 		node->UpdateSourcePos(t1.pos, t1.length);
 		node->UpdateSourcePos(t1.pos, t1.length);
 	else
 	else
@@ -2521,7 +2542,7 @@ asCScriptNode *asCParser::ParseNamespace()
 
 
 	sToken start = t1;
 	sToken start = t1;
 
 
-	node->AddChildLast(ParseScript(true));
+	lowestNode->AddChildLast(ParseScript(true));
 
 
 	if( !isSyntaxError )
 	if( !isSyntaxError )
 	{
 	{

+ 72 - 47
Source/ThirdParty/AngelScript/source/as_restore.cpp

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2020 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -155,7 +155,7 @@ int asCReader::ReadInner()
 	noDebugInfo = ReadEncodedUInt() ? VALUE_OF_BOOLEAN_TRUE : 0;
 	noDebugInfo = ReadEncodedUInt() ? VALUE_OF_BOOLEAN_TRUE : 0;
 
 
 	// Read enums
 	// Read enums
-	count = ReadEncodedUInt();
+	count = SanityCheck(ReadEncodedUInt(), 1000000);
 	module->m_enumTypes.Allocate(count, false);
 	module->m_enumTypes.Allocate(count, false);
 	for( i = 0; i < count && !error; i++ )
 	for( i = 0; i < count && !error; i++ )
 	{
 	{
@@ -228,7 +228,7 @@ int asCReader::ReadInner()
 
 
 	// classTypes[]
 	// classTypes[]
 	// First restore the structure names, then the properties
 	// First restore the structure names, then the properties
-	count = ReadEncodedUInt();
+	count = SanityCheck(ReadEncodedUInt(), 1000000);
 	module->m_classTypes.Allocate(count, false);
 	module->m_classTypes.Allocate(count, false);
 	for( i = 0; i < count && !error; ++i )
 	for( i = 0; i < count && !error; ++i )
 	{
 	{
@@ -299,7 +299,7 @@ int asCReader::ReadInner()
 	if( error ) return asERROR;
 	if( error ) return asERROR;
 
 
 	// Read func defs
 	// Read func defs
-	count = ReadEncodedUInt();
+	count = SanityCheck(ReadEncodedUInt(), 1000000);
 	module->m_funcDefs.Allocate(count, false);
 	module->m_funcDefs.Allocate(count, false);
 	for( i = 0; i < count && !error; i++ )
 	for( i = 0; i < count && !error; i++ )
 	{
 	{
@@ -401,7 +401,7 @@ int asCReader::ReadInner()
 	if( error ) return asERROR;
 	if( error ) return asERROR;
 
 
 	// Read typedefs
 	// Read typedefs
-	count = ReadEncodedUInt();
+	count = SanityCheck(ReadEncodedUInt(), 1000000);
 	module->m_typeDefs.Allocate(count, false);
 	module->m_typeDefs.Allocate(count, false);
 	for( i = 0; i < count && !error; i++ )
 	for( i = 0; i < count && !error; i++ )
 	{
 	{
@@ -422,7 +422,7 @@ int asCReader::ReadInner()
 	if( error ) return asERROR;
 	if( error ) return asERROR;
 
 
 	// scriptGlobals[]
 	// scriptGlobals[]
-	count = ReadEncodedUInt();
+	count = SanityCheck(ReadEncodedUInt(), 1000000);
 	if( count && engine->ep.disallowGlobalVars )
 	if( count && engine->ep.disallowGlobalVars )
 	{
 	{
 		engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_GLOBAL_VARS_NOT_ALLOWED);
 		engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_GLOBAL_VARS_NOT_ALLOWED);
@@ -435,7 +435,7 @@ int asCReader::ReadInner()
 	}
 	}
 
 
 	// scriptFunctions[]
 	// scriptFunctions[]
-	count = ReadEncodedUInt();
+	count = SanityCheck(ReadEncodedUInt(), 1000000);
 	for( i = 0; i < count && !error; ++i )
 	for( i = 0; i < count && !error; ++i )
 	{
 	{
 		size_t len = module->m_scriptFunctions.GetLength();
 		size_t len = module->m_scriptFunctions.GetLength();
@@ -496,7 +496,7 @@ int asCReader::ReadInner()
 	}
 	}
 
 
 	// globalFunctions[]
 	// globalFunctions[]
-	count = ReadEncodedUInt();
+	count = SanityCheck(ReadEncodedUInt(), 1000000);
 	for( i = 0; i < count && !error; ++i )
 	for( i = 0; i < count && !error; ++i )
 	{
 	{
 		bool isNew;
 		bool isNew;
@@ -516,7 +516,7 @@ int asCReader::ReadInner()
 	if( error ) return asERROR;
 	if( error ) return asERROR;
 
 
 	// bindInformations[]
 	// bindInformations[]
-	count = ReadEncodedUInt();
+	count = SanityCheck(ReadEncodedUInt(), 1000000);
 	module->m_bindInformations.Allocate(count, false);
 	module->m_bindInformations.Allocate(count, false);
 	for( i = 0; i < count && !error; ++i )
 	for( i = 0; i < count && !error; ++i )
 	{
 	{
@@ -554,7 +554,7 @@ int asCReader::ReadInner()
 	if( error ) return asERROR;
 	if( error ) return asERROR;
 
 
 	// usedTypes[]
 	// usedTypes[]
-	count = ReadEncodedUInt();
+	count = SanityCheck(ReadEncodedUInt(), 1000000);
 	usedTypes.Allocate(count, false);
 	usedTypes.Allocate(count, false);
 	for( i = 0; i < count && !error; ++i )
 	for( i = 0; i < count && !error; ++i )
 	{
 	{
@@ -660,7 +660,7 @@ void asCReader::ReadUsedStringConstants()
 	asCString str;
 	asCString str;
 
 
 	asUINT count;
 	asUINT count;
-	count = ReadEncodedUInt();
+	count = SanityCheck(ReadEncodedUInt(), 1000000);
 
 
 	if (count > 0 && engine->stringFactory == 0)
 	if (count > 0 && engine->stringFactory == 0)
 	{
 	{
@@ -681,7 +681,7 @@ void asCReader::ReadUsedFunctions()
 	TimeIt("asCReader::ReadUsedFunctions");
 	TimeIt("asCReader::ReadUsedFunctions");
 
 
 	asUINT count;
 	asUINT count;
-	count = ReadEncodedUInt();
+	count = SanityCheck(ReadEncodedUInt(), 1000000);
 	usedFunctions.SetLength(count);
 	usedFunctions.SetLength(count);
 	if( usedFunctions.GetLength() != count )
 	if( usedFunctions.GetLength() != count )
 	{
 	{
@@ -1026,13 +1026,7 @@ void asCReader::ReadFunctionSignature(asCScriptFunction *func, asCObjectType **p
 
 
 	ReadDataType(&func->returnType);
 	ReadDataType(&func->returnType);
 
 
-	count = ReadEncodedUInt();
-	if( count > 256 )
-	{
-		// Too many arguments, must be something wrong in the file
-		Error(TXT_INVALID_BYTECODE_d);
-		return;
-	}
+	count = SanityCheck(ReadEncodedUInt(), 256);
 	func->parameterTypes.Allocate(count, false);
 	func->parameterTypes.Allocate(count, false);
 	for( i = 0; i < count; ++i )
 	for( i = 0; i < count; ++i )
 	{
 	{
@@ -1253,12 +1247,12 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
 
 
 				ReadByteCode(func);
 				ReadByteCode(func);
 
 
-				func->scriptData->variableSpace = ReadEncodedUInt();
+				func->scriptData->variableSpace = SanityCheck(ReadEncodedUInt(), 1000000);
 
 
 				func->scriptData->objVariablesOnHeap = 0;
 				func->scriptData->objVariablesOnHeap = 0;
 				if (bits & 8)
 				if (bits & 8)
 				{
 				{
-					count = ReadEncodedUInt();
+					count = SanityCheck(ReadEncodedUInt(), 1000000);
 					func->scriptData->objVariablePos.Allocate(count, false);
 					func->scriptData->objVariablePos.Allocate(count, false);
 					func->scriptData->objVariableTypes.Allocate(count, false);
 					func->scriptData->objVariableTypes.Allocate(count, false);
 					for (i = 0; i < count; ++i)
 					for (i = 0; i < count; ++i)
@@ -1275,14 +1269,14 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
 						}
 						}
 					}
 					}
 					if (count > 0)
 					if (count > 0)
-						func->scriptData->objVariablesOnHeap = ReadEncodedUInt();
+						func->scriptData->objVariablesOnHeap = SanityCheck(ReadEncodedUInt(), 10000);
 
 
-					int length = ReadEncodedUInt();
+					int length = SanityCheck(ReadEncodedUInt(), 1000000);
 					func->scriptData->objVariableInfo.SetLength(length);
 					func->scriptData->objVariableInfo.SetLength(length);
 					for (i = 0; i < length; ++i)
 					for (i = 0; i < length; ++i)
 					{
 					{
-						func->scriptData->objVariableInfo[i].programPos = ReadEncodedUInt();
-						func->scriptData->objVariableInfo[i].variableOffset = ReadEncodedUInt();
+						func->scriptData->objVariableInfo[i].programPos = SanityCheck(ReadEncodedUInt(), 1000000);
+						func->scriptData->objVariableInfo[i].variableOffset = SanityCheck(ReadEncodedInt(), 10000);
 						asEObjVarInfoOption option = (asEObjVarInfoOption)ReadEncodedUInt();
 						asEObjVarInfoOption option = (asEObjVarInfoOption)ReadEncodedUInt();
 						func->scriptData->objVariableInfo[i].option = option;
 						func->scriptData->objVariableInfo[i].option = option;
 						if (option != asOBJ_INIT && 
 						if (option != asOBJ_INIT && 
@@ -1301,19 +1295,19 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
 				if (bits & 16)
 				if (bits & 16)
 				{
 				{
 					// Read info on try/catch blocks
 					// Read info on try/catch blocks
-					int length = ReadEncodedUInt();
+					int length = SanityCheck(ReadEncodedUInt(), 1000000);
 					func->scriptData->tryCatchInfo.SetLength(length);
 					func->scriptData->tryCatchInfo.SetLength(length);
 					for (i = 0; i < length; ++i)
 					for (i = 0; i < length; ++i)
 					{
 					{
 						// The program position must be adjusted to be in number of instructions
 						// The program position must be adjusted to be in number of instructions
-						func->scriptData->tryCatchInfo[i].tryPos = ReadEncodedUInt();
-						func->scriptData->tryCatchInfo[i].catchPos = ReadEncodedUInt();
+						func->scriptData->tryCatchInfo[i].tryPos = SanityCheck(ReadEncodedUInt(), 1000000);
+						func->scriptData->tryCatchInfo[i].catchPos = SanityCheck(ReadEncodedUInt(), 1000000);
 					}
 					}
 				}
 				}
 
 
 				if (!noDebugInfo)
 				if (!noDebugInfo)
 				{
 				{
-					int length = ReadEncodedUInt();
+					int length = SanityCheck(ReadEncodedUInt(), 1000000);
 					func->scriptData->lineNumbers.SetLength(length);
 					func->scriptData->lineNumbers.SetLength(length);
 					if (int(func->scriptData->lineNumbers.GetLength()) != length)
 					if (int(func->scriptData->lineNumbers.GetLength()) != length)
 					{
 					{
@@ -1326,7 +1320,7 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
 						func->scriptData->lineNumbers[i] = ReadEncodedUInt();
 						func->scriptData->lineNumbers[i] = ReadEncodedUInt();
 
 
 					// Read the array of script sections
 					// Read the array of script sections
-					length = ReadEncodedUInt();
+					length = SanityCheck(ReadEncodedUInt(), 1000000);
 					func->scriptData->sectionIdxs.SetLength(length);
 					func->scriptData->sectionIdxs.SetLength(length);
 					if (int(func->scriptData->sectionIdxs.GetLength()) != length)
 					if (int(func->scriptData->sectionIdxs.GetLength()) != length)
 					{
 					{
@@ -1351,7 +1345,7 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
 				// Read the variable information
 				// Read the variable information
 				if (!noDebugInfo)
 				if (!noDebugInfo)
 				{
 				{
-					int length = ReadEncodedUInt();
+					int length = SanityCheck(ReadEncodedUInt(), 1000000);
 					func->scriptData->variables.Allocate(length, false);
 					func->scriptData->variables.Allocate(length, false);
 					for (i = 0; i < length; i++)
 					for (i = 0; i < length; i++)
 					{
 					{
@@ -1366,7 +1360,7 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
 						func->scriptData->variables.PushLast(var);
 						func->scriptData->variables.PushLast(var);
 
 
 						var->declaredAtProgramPos = ReadEncodedUInt();
 						var->declaredAtProgramPos = ReadEncodedUInt();
-						var->stackOffset = ReadEncodedUInt();
+						var->stackOffset = SanityCheck(ReadEncodedInt(),10000);
 						ReadString(&var->name);
 						ReadString(&var->name);
 						ReadDataType(&var->type);
 						ReadDataType(&var->type);
 
 
@@ -1551,7 +1545,7 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
 		// Read the initial attributes
 		// Read the initial attributes
 		ReadString(&type->name);
 		ReadString(&type->name);
 		ReadData(&type->flags, 4);
 		ReadData(&type->flags, 4);
-		type->size = ReadEncodedUInt();
+		type->size = SanityCheck(ReadEncodedUInt(), 1000000);
 		asCString ns;
 		asCString ns;
 		ReadString(&ns);
 		ReadString(&ns);
 		type->nameSpace = engine->AddNameSpace(ns.AddressOf());
 		type->nameSpace = engine->AddNameSpace(ns.AddressOf());
@@ -1613,7 +1607,7 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
 		if( type->flags & asOBJ_ENUM )
 		if( type->flags & asOBJ_ENUM )
 		{
 		{
 			asCEnumType *t = CastToEnumType(type);
 			asCEnumType *t = CastToEnumType(type);
-			int count = ReadEncodedUInt();
+			int count = SanityCheck(ReadEncodedUInt(), 1000000);
 			bool sharedExists = existingShared.MoveTo(0, type);
 			bool sharedExists = existingShared.MoveTo(0, type);
 			if( !sharedExists )
 			if( !sharedExists )
 			{
 			{
@@ -1695,7 +1689,7 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
 			}
 			}
 
 
 			// interfaces[] / interfaceVFTOffsets[]
 			// interfaces[] / interfaceVFTOffsets[]
-			int size = ReadEncodedUInt();
+			int size = SanityCheck(ReadEncodedUInt(), 1000000);
 			if( sharedExists )
 			if( sharedExists )
 			{
 			{
 				for( int n = 0; n < size; n++ )
 				for( int n = 0; n < size; n++ )
@@ -1725,7 +1719,7 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
 
 
 					if (!ot->IsInterface())
 					if (!ot->IsInterface())
 					{
 					{
-						asUINT offset = ReadEncodedUInt();
+						asUINT offset = SanityCheck(ReadEncodedUInt(), 1000000);
 						ot->interfaceVFTOffsets.PushLast(offset);
 						ot->interfaceVFTOffsets.PushLast(offset);
 					}
 					}
 				}
 				}
@@ -1776,7 +1770,7 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
 						ot->beh.destruct = 0;
 						ot->beh.destruct = 0;
 				}
 				}
 
 
-				size = ReadEncodedUInt();
+				size = SanityCheck(ReadEncodedUInt(), 1000000);
 				for( int n = 0; n < size; n++ )
 				for( int n = 0; n < size; n++ )
 				{
 				{
 					func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists);
 					func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists);
@@ -1880,7 +1874,7 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
 			}
 			}
 
 
 			// methods[]
 			// methods[]
-			size = ReadEncodedUInt();
+			size = SanityCheck(ReadEncodedUInt(), 1000000);
 			int n;
 			int n;
 			for( n = 0; n < size; n++ )
 			for( n = 0; n < size; n++ )
 			{
 			{
@@ -1946,7 +1940,7 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
 			}
 			}
 
 
 			// virtualFunctionTable[]
 			// virtualFunctionTable[]
-			size = ReadEncodedUInt();
+			size = SanityCheck(ReadEncodedUInt(), 1000000);
 			for( n = 0; n < size; n++ )
 			for( n = 0; n < size; n++ )
 			{
 			{
 				bool isNew;
 				bool isNew;
@@ -2011,7 +2005,7 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
 		asASSERT(ot);
 		asASSERT(ot);
 
 
 		// properties[]
 		// properties[]
-		asUINT size = ReadEncodedUInt();
+		asUINT size = SanityCheck(ReadEncodedUInt(), 1000000);
 		for( asUINT n = 0; n < size; n++ )
 		for( asUINT n = 0; n < size; n++ )
 			ReadObjectProperty(ot);
 			ReadObjectProperty(ot);
 	}
 	}
@@ -2039,10 +2033,15 @@ asUINT asCReader::ReadEncodedUInt()
 	return asUINT(qw & 0xFFFFFFFFu);
 	return asUINT(qw & 0xFFFFFFFFu);
 }
 }
 
 
+int asCReader::ReadEncodedInt()
+{
+	return int(ReadEncodedUInt());
+}
+
 asQWORD asCReader::ReadEncodedUInt64()
 asQWORD asCReader::ReadEncodedUInt64()
 {
 {
 	asQWORD i = 0;
 	asQWORD i = 0;
-	asBYTE b;
+	asBYTE b = 0xFF; // set to 0xFF to better catch if the stream doesn't update the value
 	ReadData(&b, 1);
 	ReadData(&b, 1);
 	bool isNegative = ( b & 0x80 ) ? true : false;
 	bool isNegative = ( b & 0x80 ) ? true : false;
 	b &= 0x7F;
 	b &= 0x7F;
@@ -2113,9 +2112,35 @@ asQWORD asCReader::ReadEncodedUInt64()
 	return i;
 	return i;
 }
 }
 
 
+asUINT asCReader::SanityCheck(asUINT val, asUINT max)
+{
+	if (val > max)
+	{
+		Error(TXT_INVALID_BYTECODE_d);
+
+		// Return 0 as default value
+		return 0;
+	}
+
+	return val;
+}
+
+int asCReader::SanityCheck(int val, asUINT max)
+{
+	if (val > int(max) || val < -int(max))
+	{
+		Error(TXT_INVALID_BYTECODE_d);
+
+		// Return 0 as default value
+		return 0;
+	}
+
+	return val;
+}
+
 void asCReader::ReadString(asCString* str)
 void asCReader::ReadString(asCString* str)
 {
 {
-	asUINT len = ReadEncodedUInt();
+	asUINT len = SanityCheck(ReadEncodedUInt(), 1000000);
 	if( len & 1 )
 	if( len & 1 )
 	{
 	{
 		asUINT idx = len/2;
 		asUINT idx = len/2;
@@ -2261,7 +2286,7 @@ asCTypeInfo* asCReader::ReadTypeInfo()
 			return 0;
 			return 0;
 		}
 		}
 
 
-		asUINT numSubTypes = ReadEncodedUInt();
+		asUINT numSubTypes = SanityCheck(ReadEncodedUInt(), 100);
 		asCArray<asCDataType> subTypes;
 		asCArray<asCDataType> subTypes;
 		for( asUINT n = 0; n < numSubTypes; n++ )
 		for( asUINT n = 0; n < numSubTypes; n++ )
 		{
 		{
@@ -2422,7 +2447,7 @@ void asCReader::ReadByteCode(asCScriptFunction *func)
 
 
 	// Read number of instructions
 	// Read number of instructions
 	asUINT total, numInstructions;
 	asUINT total, numInstructions;
-	total = numInstructions = ReadEncodedUInt();
+	total = numInstructions = SanityCheck(ReadEncodedUInt(), 1000000);
 
 
 	// Reserve some space for the instructions
 	// Reserve some space for the instructions
 	func->scriptData->byteCode.AllocateNoConstruct(numInstructions, false);
 	func->scriptData->byteCode.AllocateNoConstruct(numInstructions, false);
@@ -2664,7 +2689,7 @@ void asCReader::ReadUsedTypeIds()
 {
 {
 	TimeIt("asCReader::ReadUsedTypeIds");
 	TimeIt("asCReader::ReadUsedTypeIds");
 
 
-	asUINT count = ReadEncodedUInt();
+	asUINT count = SanityCheck(ReadEncodedUInt(), 1000000);
 	usedTypeIds.Allocate(count, false);
 	usedTypeIds.Allocate(count, false);
 	for( asUINT n = 0; n < count; n++ )
 	for( asUINT n = 0; n < count; n++ )
 	{
 	{
@@ -2678,7 +2703,7 @@ void asCReader::ReadUsedGlobalProps()
 {
 {
 	TimeIt("asCReader::ReadUsedGlobalProps");
 	TimeIt("asCReader::ReadUsedGlobalProps");
 
 
-	int c = ReadEncodedUInt();
+	int c = SanityCheck(ReadEncodedUInt(), 1000000);
 
 
 	usedGlobalProperties.Allocate(c, false);
 	usedGlobalProperties.Allocate(c, false);
 
 
@@ -2719,7 +2744,7 @@ void asCReader::ReadUsedObjectProps()
 {
 {
 	TimeIt("asCReader::ReadUsedObjectProps");
 	TimeIt("asCReader::ReadUsedObjectProps");
 
 
-	asUINT c = ReadEncodedUInt();
+	asUINT c = SanityCheck(ReadEncodedUInt(), 1000000);
 
 
 	usedObjectProperties.SetLength(c);
 	usedObjectProperties.SetLength(c);
 	for( asUINT n = 0; n < c; n++ )
 	for( asUINT n = 0; n < c; n++ )

+ 4 - 1
Source/ThirdParty/AngelScript/source/as_restore.h

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2017 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
    warranty. In no event will the authors be held liable for any 
@@ -76,7 +76,10 @@ protected:
 	void               ReadByteCode(asCScriptFunction *func);
 	void               ReadByteCode(asCScriptFunction *func);
 	asWORD             ReadEncodedUInt16();
 	asWORD             ReadEncodedUInt16();
 	asUINT             ReadEncodedUInt();
 	asUINT             ReadEncodedUInt();
+	int                ReadEncodedInt();
 	asQWORD            ReadEncodedUInt64();
 	asQWORD            ReadEncodedUInt64();
+	asUINT             SanityCheck(asUINT val, asUINT max);
+	int                SanityCheck(int val, asUINT max);
 
 
 	void ReadUsedTypeIds();
 	void ReadUsedTypeIds();
 	void ReadUsedFunctions();
 	void ReadUsedFunctions();

+ 29 - 14
Source/ThirdParty/AngelScript/source/as_scriptengine.cpp

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2020 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -951,12 +951,16 @@ asCModule *asCScriptEngine::FindNewOwnerForSharedFunc(asCScriptFunction *in_func
 	if( in_func->module != in_mod)
 	if( in_func->module != in_mod)
 		return in_func->module;
 		return in_func->module;
 
 
-	if (in_func->objectType && in_func->objectType->module && 
-		in_func->objectType->module != in_func->module)
+	// Check if this is a class method or class factory for a type that has already been moved to a different module
+	if ((in_func->objectType && in_func->objectType->module && in_func->objectType->module != in_func->module) ||
+		(in_func->IsFactory() && in_func->returnType.GetTypeInfo()->module && in_func->returnType.GetTypeInfo()->module != in_func->module))
 	{
 	{
 		// The object type for the method has already been transferred to 
 		// The object type for the method has already been transferred to 
 		// another module, so transfer the method to the same module
 		// another module, so transfer the method to the same module
-		in_func->module = in_func->objectType->module;
+		if (in_func->objectType)
+			in_func->module = in_func->objectType->module;
+		else
+			in_func->module = in_func->returnType.GetTypeInfo()->module;
 
 
 		// Make sure the function is listed in the module
 		// Make sure the function is listed in the module
 		// The compiler may not have done this earlier, since the object
 		// The compiler may not have done this earlier, since the object
@@ -1370,7 +1374,9 @@ int asCScriptEngine::GetFactoryIdByDecl(const asCObjectType *ot, const char *dec
 	for( asUINT n = 0; n < ot->beh.factories.GetLength(); n++ )
 	for( asUINT n = 0; n < ot->beh.factories.GetLength(); n++ )
 	{
 	{
 		asCScriptFunction *f = scriptFunctions[ot->beh.factories[n]];
 		asCScriptFunction *f = scriptFunctions[ot->beh.factories[n]];
-		if( f->IsSignatureEqual(&func) )
+
+		// We don't really care if the name of the function is correct
+		if( f->IsSignatureExceptNameEqual(&func) )
 		{
 		{
 			id = ot->beh.factories[n];
 			id = ot->beh.factories[n];
 			break;
 			break;
@@ -2156,7 +2162,9 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as
 		}
 		}
 
 
 		// Verify the parameters
 		// Verify the parameters
-		if( func.parameterTypes.GetLength() != 1 || !func.parameterTypes[0].IsReference() )
+		// The templates take a hidden parameter with the object type
+		if( (!(objectType->flags & asOBJ_TEMPLATE) && (func.parameterTypes.GetLength() != 1 || !func.parameterTypes[0].IsReference())) || 
+			((objectType->flags & asOBJ_TEMPLATE) && (func.parameterTypes.GetLength() != 2 || !func.parameterTypes[0].IsReference() || !func.parameterTypes[1].IsReference())) )
 		{
 		{
 			if( listPattern )
 			if( listPattern )
 				listPattern->Destroy(this);
 				listPattern->Destroy(this);
@@ -4960,7 +4968,8 @@ int asCScriptEngine::RefCastObject(void *obj, asITypeInfo *fromType, asITypeInfo
 
 
 	// Look for ref cast behaviours
 	// Look for ref cast behaviours
 	asCScriptFunction *universalCastFunc = 0;
 	asCScriptFunction *universalCastFunc = 0;
-	asCObjectType *from = reinterpret_cast<asCObjectType*>(fromType);
+	asCObjectType *from = CastToObjectType(reinterpret_cast< asCTypeInfo*>(fromType));
+	if( from == 0 ) return asINVALID_ARG;
 	for( asUINT n = 0; n < from->methods.GetLength(); n++ )
 	for( asUINT n = 0; n < from->methods.GetLength(); n++ )
 	{
 	{
 		asCScriptFunction *func = scriptFunctions[from->methods[n]];
 		asCScriptFunction *func = scriptFunctions[from->methods[n]];
@@ -5044,7 +5053,8 @@ void *asCScriptEngine::CreateScriptObject(const asITypeInfo *type)
 {
 {
 	if( type == 0 ) return 0;
 	if( type == 0 ) return 0;
 
 
-	asCObjectType *objType = const_cast<asCObjectType*>(reinterpret_cast<const asCObjectType *>(type));
+	asCObjectType *objType = CastToObjectType(const_cast<asCTypeInfo*>(reinterpret_cast<const asCTypeInfo*>(type)));
+	if (objType == 0) return 0;
 	void *ptr = 0;
 	void *ptr = 0;
 
 
 	// Check that there is a default factory for ref types
 	// Check that there is a default factory for ref types
@@ -5243,7 +5253,9 @@ void *asCScriptEngine::CreateUninitializedScriptObject(const asITypeInfo *type)
 	if( type == 0 || !(type->GetFlags() & asOBJ_SCRIPT_OBJECT) )
 	if( type == 0 || !(type->GetFlags() & asOBJ_SCRIPT_OBJECT) )
 		return 0;
 		return 0;
 
 
-	asCObjectType *objType = const_cast<asCObjectType*>(reinterpret_cast<const asCObjectType*>(type));
+	asCObjectType *objType = CastToObjectType(const_cast<asCTypeInfo*>(reinterpret_cast<const asCTypeInfo*>(type)));
+	if (objType == 0)
+		return 0;
 
 
 	// Construct the object, but do not call the actual constructor that initializes the members
 	// Construct the object, but do not call the actual constructor that initializes the members
 	// The initialization will be done by the application afterwards, e.g. through serialization.
 	// The initialization will be done by the application afterwards, e.g. through serialization.
@@ -5260,9 +5272,11 @@ void *asCScriptEngine::CreateScriptObjectCopy(void *origObj, const asITypeInfo *
 {
 {
 	if( origObj == 0 || type == 0 ) return 0;
 	if( origObj == 0 || type == 0 ) return 0;
 
 
+	const asCObjectType* ot = CastToObjectType(const_cast<asCTypeInfo*>(reinterpret_cast<const asCTypeInfo*>(type)));
+	if (ot == 0) return 0;
+
 	void *newObj = 0;
 	void *newObj = 0;
 
 
-	const asCObjectType *ot = reinterpret_cast<const asCObjectType*>(type);
 	if ((ot->flags & asOBJ_SCRIPT_OBJECT) && ot->beh.copyfactory)
 	if ((ot->flags & asOBJ_SCRIPT_OBJECT) && ot->beh.copyfactory)
 	{
 	{
 		// Call the script class' default factory with a context
 		// Call the script class' default factory with a context
@@ -5286,7 +5300,7 @@ void *asCScriptEngine::CreateScriptObjectCopy(void *origObj, const asITypeInfo *
 		}
 		}
 #endif
 #endif
 	}
 	}
-	else if( ot->beh.copyconstruct )
+	else if(ot->beh.copyconstruct )
 	{
 	{
 		// Manually allocate the memory, then call the copy constructor
 		// Manually allocate the memory, then call the copy constructor
 		newObj = CallAlloc(ot);
 		newObj = CallAlloc(ot);
@@ -5351,7 +5365,8 @@ int asCScriptEngine::AssignScriptObject(void *dstObj, void *srcObj, const asITyp
 	// TODO: Warn about invalid call in message stream (make it optional)
 	// TODO: Warn about invalid call in message stream (make it optional)
 	if( type == 0 || dstObj == 0 || srcObj == 0 ) return asINVALID_ARG;
 	if( type == 0 || dstObj == 0 || srcObj == 0 ) return asINVALID_ARG;
 
 
-	const asCObjectType *objType = reinterpret_cast<const asCObjectType*>(type);
+	const asCObjectType *objType = CastToObjectType(const_cast<asCTypeInfo*>(reinterpret_cast<const asCTypeInfo*>(type)));
+	if (objType == 0) return asINVALID_ARG;
 
 
 	// If value assign for ref types has been disabled, then don't do anything if the type is a ref type
 	// If value assign for ref types has been disabled, then don't do anything if the type is a ref type
 	if (ep.disallowValueAssignForRefType && (objType->flags & asOBJ_REF) && !(objType->flags & asOBJ_SCOPED))
 	if (ep.disallowValueAssignForRefType && (objType->flags & asOBJ_REF) && !(objType->flags & asOBJ_SCOPED))
@@ -5389,7 +5404,7 @@ void asCScriptEngine::AddRefScriptObject(void *obj, const asITypeInfo *type)
 	// Make sure it is not a null pointer
 	// Make sure it is not a null pointer
 	if( obj == 0 || type == 0 ) return;
 	if( obj == 0 || type == 0 ) return;
 
 
-	const asCTypeInfo *ti = static_cast<const asCTypeInfo*>(type);
+	const asCTypeInfo *ti = reinterpret_cast<const asCTypeInfo*>(type);
 	if (ti->flags & asOBJ_FUNCDEF)
 	if (ti->flags & asOBJ_FUNCDEF)
 	{
 	{
 		CallObjectMethod(obj, functionBehaviours.beh.addref);
 		CallObjectMethod(obj, functionBehaviours.beh.addref);
@@ -5411,7 +5426,7 @@ void asCScriptEngine::ReleaseScriptObject(void *obj, const asITypeInfo *type)
 	// Make sure it is not a null pointer
 	// Make sure it is not a null pointer
 	if( obj == 0 || type == 0 ) return;
 	if( obj == 0 || type == 0 ) return;
 
 
-	const asCTypeInfo *ti = static_cast<const asCTypeInfo*>(type);
+	const asCTypeInfo *ti = reinterpret_cast<const asCTypeInfo*>(type);
 	if (ti->flags & asOBJ_FUNCDEF)
 	if (ti->flags & asOBJ_FUNCDEF)
 	{
 	{
 		CallObjectMethod(obj, functionBehaviours.beh.release);
 		CallObjectMethod(obj, functionBehaviours.beh.release);

+ 19 - 2
Source/ThirdParty/AngelScript/source/as_scriptfunction.cpp

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2020 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -306,7 +306,9 @@ int asCScriptFunction::ParseListPattern(asSListPatternNode *&target, const char
 			asCBuilder builder(engine, 0);
 			asCBuilder builder(engine, 0);
 			asCScriptCode code;
 			asCScriptCode code;
 			code.SetCode("", decl, 0, false);
 			code.SetCode("", decl, 0, false);
-			dt = builder.CreateDataTypeFromNode(listNodes, &code, engine->defaultNamespace, false, CastToObjectType(returnType.GetTypeInfo()));
+
+			// For list factory we get the object type from the return type, for list constructor we get it from the object type directly
+			dt = builder.CreateDataTypeFromNode(listNodes, &code, engine->defaultNamespace, false, objectType ? objectType : CastToObjectType(returnType.GetTypeInfo()));
 
 
 			node->next = asNEW(asSListPatternDataTypeNode)(dt);
 			node->next = asNEW(asSListPatternDataTypeNode)(dt);
 			node = node->next;
 			node = node->next;
@@ -1722,5 +1724,20 @@ bool asCScriptFunction::IsProperty() const
 	return traits.GetTrait(asTRAIT_PROPERTY);
 	return traits.GetTrait(asTRAIT_PROPERTY);
 }
 }
 
 
+// internal
+bool asCScriptFunction::IsFactory() const
+{
+	if (objectType) return false;
+	
+	asCObjectType* type = CastToObjectType(returnType.GetTypeInfo());
+	if (type == 0) return false;
+
+	if (type->name != name) return false;
+
+	if (type->nameSpace != nameSpace) return false;
+	
+	return true;
+}
+
 END_AS_NAMESPACE
 END_AS_NAMESPACE
 
 

+ 2 - 1
Source/ThirdParty/AngelScript/source/as_scriptfunction.h

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2019 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -215,6 +215,7 @@ public:
 	void SetProtected(bool set) { traits.SetTrait(asTRAIT_PROTECTED, set); }
 	void SetProtected(bool set) { traits.SetTrait(asTRAIT_PROTECTED, set); }
 	void SetPrivate(bool set) { traits.SetTrait(asTRAIT_PRIVATE, set); }
 	void SetPrivate(bool set) { traits.SetTrait(asTRAIT_PRIVATE, set); }
 	void SetProperty(bool set) { traits.SetTrait(asTRAIT_PROPERTY, set); }
 	void SetProperty(bool set) { traits.SetTrait(asTRAIT_PROPERTY, set); }
+	bool IsFactory() const;
 
 
 	asCScriptFunction(asCScriptEngine *engine, asCModule *mod, asEFuncType funcType);
 	asCScriptFunction(asCScriptEngine *engine, asCModule *mod, asEFuncType funcType);
 	~asCScriptFunction();
 	~asCScriptFunction();

+ 2 - 2
Source/ThirdParty/AngelScript/source/as_symboltable.h

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2012-2015 Andreas Jonsson
+   Copyright (c) 2012-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
    warranty. In no event will the authors be held liable for any
@@ -86,7 +86,7 @@ public:
 
 
 private:
 private:
 	friend class asCSymbolTable<T>;
 	friend class asCSymbolTable<T>;
-	asCSymbolTableIterator<T, T2>(asCSymbolTable<T> *table);
+	asCSymbolTableIterator(asCSymbolTable<T> *table);
 
 
 	void Next();
 	void Next();
 	void Previous();
 	void Previous();

+ 3 - 2
Source/ThirdParty/AngelScript/source/as_texts.h

@@ -1,6 +1,6 @@
 /*
 /*
    AngelCode Scripting Library
    AngelCode Scripting Library
-   Copyright (c) 2003-2019 Andreas Jonsson
+   Copyright (c) 2003-2021 Andreas Jonsson
 
 
    This software is provided 'as-is', without any express or implied 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
    warranty. In no event will the authors be held liable for any 
@@ -48,7 +48,7 @@
 #define TXT_ATTR_s_INFORMED_MULTIPLE_TIMES          "Attribute '%s' informed multiple times"
 #define TXT_ATTR_s_INFORMED_MULTIPLE_TIMES          "Attribute '%s' informed multiple times"
 #define TXT_AUTO_NOT_ALLOWED                        "Auto is not allowed here"
 #define TXT_AUTO_NOT_ALLOWED                        "Auto is not allowed here"
 
 
-#define TXT_BOTH_MUST_BE_SAME                     "Both expressions must have the same type"
+#define TXT_BOTH_MUST_BE_SAME                     "Can't find unambiguous implicit conversion to make both expressions have the same type"
 #define TXT_BOTH_CONDITIONS_MUST_CALL_CONSTRUCTOR "Both conditions must call constructor"
 #define TXT_BOTH_CONDITIONS_MUST_CALL_CONSTRUCTOR "Both conditions must call constructor"
 #define TEXT_BASE_DOESNT_HAVE_DEF_CONSTR          "Base class doesn't have default constructor. Make explicit call to base constructor"
 #define TEXT_BASE_DOESNT_HAVE_DEF_CONSTR          "Base class doesn't have default constructor. Make explicit call to base constructor"
 
 
@@ -189,6 +189,7 @@
 #define TXT_NAME_CONFLICT_s_IS_MIXIN               "Name conflict. '%s' is a mixin class."
 #define TXT_NAME_CONFLICT_s_IS_MIXIN               "Name conflict. '%s' is a mixin class."
 #define TXT_NAME_CONFLICT_s_IS_VIRTPROP            "Name conflict. '%s' is a virtual property."
 #define TXT_NAME_CONFLICT_s_IS_VIRTPROP            "Name conflict. '%s' is a virtual property."
 #define TXT_NAME_CONFLICT_s_STRUCT                 "Name conflict. '%s' is a class."
 #define TXT_NAME_CONFLICT_s_STRUCT                 "Name conflict. '%s' is a class."
+#define TXT_NAME_CONFLICT_s_INTF                   "Name conflict. '%s' is an interface."
 #define TXT_NAME_CONFLICT_s_OBJ_PROPERTY           "Name conflict. '%s' is an object property."
 #define TXT_NAME_CONFLICT_s_OBJ_PROPERTY           "Name conflict. '%s' is an object property."
 #define TXT_NAME_CONFLICT_s_METHOD                 "Name conflict. '%s' is a class method."
 #define TXT_NAME_CONFLICT_s_METHOD                 "Name conflict. '%s' is a class method."
 #define TXT_NAME_CONFLICT_s_ALREADY_USED           "Name conflict. '%s' is already used."
 #define TXT_NAME_CONFLICT_s_ALREADY_USED           "Name conflict. '%s' is already used."

+ 1 - 1
bin/Data/Scripts/Editor/AttributeEditor.as

@@ -68,7 +68,7 @@ UIElement@ SetValue(CheckBox@ element, bool value, bool sameValue)
 
 
 UIElement@ SetValue(DropDownList@ element, int value, bool sameValue)
 UIElement@ SetValue(DropDownList@ element, int value, bool sameValue)
 {
 {
-    element.selection = sameValue ? value : M_MAX_UNSIGNED;
+    element.selection = sameValue ? uint(value) : M_MAX_UNSIGNED;
     return element;
     return element;
 }
 }