├── .gitignore ├── CHANGELOG.md ├── Makefile ├── README.md ├── Script.2017.vcxproj ├── Script.2017.vcxproj.filters ├── Script.2022.vcxproj ├── Script.2022.vcxproj.filters ├── Script.cpp ├── TinyJS.cpp ├── TinyJS.h ├── TinyJS_DateFunctions.cpp ├── TinyJS_Functions.cpp ├── TinyJS_MathFunctions.cpp ├── TinyJS_PoolAllocator.cpp ├── TinyJS_PoolAllocator.h ├── TinyJS_StringFunctions.cpp ├── TinyJS_Threading.cpp ├── TinyJS_Threading.h ├── config.h ├── lib-tiny-js.2017.vcxproj ├── lib-tiny-js.2017.vcxproj.filters ├── lib-tiny-js.2022.vcxproj ├── lib-tiny-js.2022.vcxproj.filters ├── prebuild.tests.cpp ├── run_tests.2017.vcxproj ├── run_tests.2017.vcxproj.filters ├── run_tests.2022.vcxproj ├── run_tests.2022.vcxproj.filters ├── run_tests.cpp ├── tests ├── 42tests │ ├── test001.js │ ├── test002.js │ ├── test003.js │ ├── test004.js │ ├── test005.js │ ├── test006.js │ ├── test007.js │ └── test008.js ├── test001.js ├── test002.js ├── test003.js ├── test004.js ├── test005.js ├── test006.js ├── test007.js ├── test008.js ├── test009.js ├── test010.js ├── test011.js ├── test012.js ├── test013.js ├── test014.js ├── test015.js ├── test016.js ├── test017.js ├── test018.js ├── test019.42.js ├── test019.js ├── test020.js ├── test021.42.js ├── test021.js ├── test022.42.js ├── test022.js ├── test023.js ├── test024.js ├── test025.js ├── test026.js ├── test027.js ├── test028.42.js ├── test028.js ├── test029.js ├── test030.js ├── test031.js ├── test032.42.js ├── test032.js ├── test033.js ├── test034.js ├── test035.js └── test036.js ├── time_logger.h ├── tiny-js.2017.sln └── tiny-js.2022.sln /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio. 3 | ################################################################################ 4 | 5 | /Debug 6 | /Build 7 | /Release 8 | /tiny-js.2012.opensdf 9 | /tiny-js.2012.sdf 10 | /tiny-js.2012.v11.suo 11 | *.jsc 12 | /.vs 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Version 0.9.0 (2016-04-11 16:52:59) 2 | =================================== 3 | 4 | * added versioning (started at version 0.9.0) 5 | * added changelog.md 6 | * changed Makefile for stressless builds 7 | * Script.cpp remove generator test at startup 8 | * some speed-optimation 9 | * Array stuff changed (length is no more a getter) 10 | * many other changes 11 | 12 | ------------------------------------------------------------------------------- 13 | 14 | 15 | Version 0.9.1 (2016-04-11 18:00:23) 16 | =================================== 17 | 18 | * cleanup & fix pool_allocator 19 | 20 | ------------------------------------------------------------------------------- 21 | 22 | 23 | Version 0.9.2 (2016-04-13 18:51:24) 24 | =================================== 25 | 26 | * fix ScriptVar from int64_t 27 | * added: README.md 28 | 29 | ------------------------------------------------------------------------------- 30 | 31 | 32 | Version 0.9.3 (2016-04-14 20:10:22) 33 | =================================== 34 | 35 | * added MSVC 2013 project-files 36 | * added some virtual functions 37 | 38 | ------------------------------------------------------------------------------- 39 | 40 | 41 | Version 0.9.4 (2024-04-08 16:53:41) 42 | =================================== 43 | 44 | * little change on pool_allocator 45 | * wait on keypress on end of Script.exe 46 | * added MSVC 2017 project-files 47 | * added MSVC 2022 project-files 48 | * fix compiler error end warnings with MSVC 2017/2022 49 | * change some functions to const 50 | * change C++ Language with MSVC to ISO Standard C++20 51 | 52 | ------------------------------------------------------------------------------- 53 | 54 | 55 | Version 0.9.5 (2024-04-09 21:45:44) 56 | =================================== 57 | 58 | * fix typos in MSVC sln 59 | * fix for test029.js, test31.js and test032.42.js 60 | * remove c++ array.length 61 | 62 | ------------------------------------------------------------------------------- 63 | 64 | 65 | Version 0.9.6 (2024-04-13 01:30:28) 66 | =================================== 67 | 68 | * added few functions comments 69 | * added exponentiation operator (**) 70 | * added exponentiation assignment (**=) 71 | * added nullish coalescing operator (??) 72 | * added nullish coalescing assignment (??=) 73 | * added optional chaining (?.) e.g. obj.val?.prop or obj.val?.[expr] or obj.func?.(args) 74 | 75 | ------------------------------------------------------------------------------- 76 | 77 | 78 | Version 0.9.8 (2024-04-13 12:07:35) 79 | =================================== 80 | 81 | * fixed test024.js 82 | 83 | ------------------------------------------------------------------------------- 84 | 85 | 86 | Version 0.9.9 (2024-04-13 13:56:41) 87 | =================================== 88 | 89 | * removed cloning stuff 90 | * changed test019.42.js now uses JSON.parse(JSON.stringify(obj1)) instead of obj1.clone() 91 | * added generator function statements and expessions with asterisk 92 | - as statement: function* generator() { ... } 93 | - as expression let generator = function*() { ... } 94 | - or as object member: let obj = { *generator() { ... } } 95 | Previously, a generator was recognized by it if a yield expression was included. This behavior is no longer supported. 96 | * changed 42tests/test004.js now uses function* fibonacci() 97 | 98 | ------------------------------------------------------------------------------- 99 | 100 | 101 | Version 0.10.0 (2025-03-26 10:39) 102 | ================================= 103 | 104 | * modern times: from version 0.10.0 a compiler with C++17 support is required 105 | * changed: parseFloat, parseInt CNumber.operator=(string_view) 106 | * changed: Left2Right is now a sorted array at compile time (constexpr) 107 | * removed: serialize and unserialize binary (compiled js-code) 108 | * removed: dynamic_cast now std::variant is used no RTTI overhead 109 | * added: all CScriptTokenData... now hold in std::shared_ptr 110 | * removed global using namespace std; in all cpp-files 111 | * replaced dynamic_cast with CScriptVarDynamicCast (useing of custom RTTI) ca. 7x faster then dynamic_cast 112 | * removed unneeded deleted copy-constructors 113 | * changed CScriptVarPtr is replaced by std::shared_ptr 114 | * changed enum NType to enum class NType 115 | * changed reserved_words_begin is now a sorted array reserved_words at compile time (constexpr) 116 | * changed:str2reserved_begin is now a sorted array reserved_words_by_str at compile time (constexpr) 117 | * changed:tokens2str_begin is now a sorted array tokens2str at compile time (constexpr) 118 | * changed enum TOKENIZE_FLAGS to enum _class_ TOKENIZE_FLAGS 119 | * changed CScriptVarLink now allways hold in shared_ptr 120 | * removed some debuging stuff 121 | * added TinyJS now uses always the namespace TinyJS 122 | * added the lexer now uses a ring buffer system and can read directly from a stream 123 | * changed Now std::function is used instead of a simple function pointer for native functions 124 | * removed No longer required classes CScriptVarFunctionNativeCallback and CScriptVarFunctionNativeClass. All native functionality is now in class CScriptVarFunctionNative 125 | * added CScriptVarString(std::string &&) move constructor 126 | * added String.prototype.padStart(targetLength, padString) 127 | * added String.prototype.padEnd(targetLength, padString) 128 | * added String.prototype.repeat(count) 129 | * added String.prototype.includes(searchString, position) 130 | * added String.prototype.startsWith(searchString, position) 131 | * added String.prototype.endsWith(searchString, length) 132 | * removed octal escapes in string literals 133 | * added template literals 134 | * added ...Rest Parameter 135 | * changed let and const Statements rewriten 136 | * removed non Standard let expression 137 | * removed non Standard conditional catch 138 | * removed non Standard Array Comprehensions 139 | * changed destructuring rewritten 140 | * added Symbol() Symbol.for() and Symbol.keyFor() 141 | * changed rename Array.prototype.contains to Array.prototype.includes 142 | * added Array.prototype.map 143 | * added Array.prototype.shift 144 | * added Array.prototype.unshift 145 | * added Array.prototype.slice 146 | * added Array.prototype.splice 147 | * added Array.prototype.forEach 148 | * added Array.prototype.indexOf 149 | * added Array.prototype.reduce 150 | * added Array.prototype.reduceRight 151 | * removed unneeded files 152 | 153 | ------------------------------------------------------------------------------- 154 | 155 | 156 | Version 0.10.1 (2025-03-28 09:00) 157 | ================================= 158 | 159 | * updated README.md 160 | * changed MSVC 2017 c++ standard to c++17 161 | * changed MSVC 2020 c++ standard to c++20 162 | * fixed compilation issues with MSVC 2017 and 2022 163 | * removed debugging code from the pool allocato 164 | * updated improved readability of run_tests.cpp and Script.cpp 165 | * updated time_logger.h to use std::chrono::high_resolution_clock 166 | * added console.log, console.debug, console.info, console.warn and console.error 167 | * added CTinyJS::setConsole to set log level and output stream 168 | * added console.time, console.timeLog, console.timeEnd 169 | 170 | ------------------------------------------------------------------------------- 171 | 172 | 173 | Version 0.10.2 (2025-03-29 20:18) 174 | ================================= 175 | 176 | * added overlodaed versions of addNative to register standard functions like int(int,int) 177 | * renamed pool_allocator.h/.cpp to TinyJS_PoolAllocator.h/.cpp 178 | 179 | ------------------------------------------------------------------------------- 180 | 181 | 182 | Version 0.10.3 (2025-04-04 10:16) 183 | ================================= 184 | 185 | * updated Date() functions 186 | * removed extra constructor handling with setConstructor/getConstructor, as new.target has been supported since version 0.10.0 187 | 188 | ------------------------------------------------------------------------------- 189 | 190 | 191 | Version 0.10.4 (2025-04-07 21:30) 192 | ================================= 193 | 194 | * fixed compile with make on Linux or MingW or ... 195 | 196 | ------------------------------------------------------------------------------- 197 | 198 | 199 | Version 0.10.5 (2025-04-10 12:38) 200 | ================================= 201 | 202 | * changed The Date object has been refactored, with time handling now implemented using std::chrono::local_time from C++20 203 | 204 | ------------------------------------------------------------------------------- 205 | 206 | 207 | Version 0.10.6 (2025-04-18 10:14) 208 | ================================= 209 | 210 | * fixed compiling withs clang++ (moved some constructors fom .h to .cpp) 211 | 212 | ------------------------------------------------------------------------------- 213 | 214 | 215 | Version 0.10.7 (2025-05-01 11:04) 216 | ================================= 217 | 218 | * PoolAllocator optimized allocate_shared_protected allocates controlblock and object at once 219 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | CXXFLAGS += -g -Wall 4 | CXXFLAGS += $(CXXEXTRA) 5 | 6 | LDFLAGS += $(LDEXTRA) 7 | LIBS += $(LIBSEXTRA) 8 | 9 | ifneq ($(MAKECMDGOALS),clean) 10 | 11 | HAVE_INCLUDE = $(shell $(CXX) $(2) -include $(1) -xc++ -E - < /dev/null &> /dev/null && echo "yes" || echo "no") 12 | 13 | define PREBUILD_TEST 14 | $(shell 15 | [ -f ./prebuild.test.$(1)$(2).ok ] && echo -n "yes" 16 | || ( 17 | [ -f ./prebuild.test.$(1)$(2).failed ] && echo -n "no" 18 | || ( 19 | echo $(CXX) $(CXXFLAGS) -DTEST_$(1) prebuild.tests.cpp $(LIBS) $(2) -o prebuild.test.$(1)$(2) 1>&2 && 20 | $(CXX) $(CXXFLAGS) -DTEST_$(1) prebuild.tests.cpp $(LIBS) $(2) -o ./prebuild.test.$(1)$(2) 1>&2 && sleep 3.0 && [ -f ./prebuild.test.$(1)$(2) ] && ./prebuild.test.$(1)$(2) 21 | && 22 | (echo -n "yes" && touch ./prebuild.test.$(1)$(2).ok 1>&2 && rm -f ./prebuild.test.$(1)$(2) 1>&2) 23 | || 24 | (echo -n "no" && touch ./prebuild.test.$(1)$(2).failed 1>&2 && rm -f ./prebuild.test.$(1)$(2) 1>&2) 25 | ) 26 | ) 27 | ) 28 | endef 29 | 30 | ifeq ($(call PREBUILD_TEST,"CPP23","-std=c++23"),yes) 31 | CXX_STANDARD := c++23 32 | else ifeq ($(call PREBUILD_TEST,"CPP20","-std=c++20"),yes) 33 | CXX_STANDARD := c++20 34 | else ifeq ($(call PREBUILD_TEST,"CPP17","-std=c++17"),yes) 35 | CXX_STANDARD := c++17 36 | else 37 | $(error ❌ Dein Compiler unterstützt kein C++17! Bitte verwende GCC ≥ 7.1 oder Clang ≥ 5.0.) 38 | endif 39 | 40 | # Debug-Infos ausgeben 41 | $(info ✅ Höchster unterstützter C++-Standard: $(CXX_STANDARD)) 42 | 43 | CXXFLAGS += -std=$(CXX_STANDARD) 44 | 45 | ifeq ($(DEBUG),1) 46 | CXXFLAGS += -D_DEBUG 47 | endif 48 | 49 | 50 | ifeq ($(NO_POOL_ALLOCATOR),1) 51 | CXXFLAGS += -DNO_POOL_ALLOCATOR 52 | else 53 | ifeq ($(NO_SPINLOCK_IN_POOL_ALLOCATOR),1) 54 | CXXFLAGS += -DNO_SPINLOCK_IN_POOL_ALLOCATOR 55 | endif 56 | endif 57 | 58 | 59 | ifeq ($(NO_THREADING),1) 60 | CXXFLAGS += -DNO_THREADING 61 | else 62 | ifeq ($(shell $(CXX) $(CXXFLAGS) -xc++ -pthread -E - < /dev/null &> /dev/null && echo -n "yes"),yes) 63 | CXXFLAGS += -pthread 64 | endif 65 | 66 | ifeq ($(NO_CXX_THREADS),1) 67 | CXXFLAGS += -DNO_CXX_THREADS 68 | else ifneq ($(NO_CXX_THREADS),0) 69 | ifneq ($(call PREBUILD_TEST,"CXX11_THREAD"),yes) 70 | ifneq ($(call PREBUILD_TEST,"CXX11_THREAD","-lpthread"),yes) 71 | override NO_CXX_THREADS = 1 72 | CXXFLAGS += -DNO_CXX_THREADS 73 | else 74 | LIBS += -lpthread 75 | endif 76 | endif 77 | endif 78 | endif 79 | 80 | ifneq ($(call PREBUILD_TEST,"CXX11_FILESYSTEM"),yes) 81 | ifeq ($(call PREBUILD_TEST,"CXX11_FILESYSTEM","-lstdc++fs"),yes) 82 | LIBS += -lstdc++fs 83 | endif 84 | endif 85 | 86 | 87 | endif # ifneq ($(MAKECMDGOALS),clean) 88 | 89 | LIBS += -L '$(CURDIR)' -l42tiny-js 90 | 91 | SOURCES= \ 92 | TinyJS.cpp \ 93 | TinyJS_PoolAllocator.cpp \ 94 | TinyJS_Functions.cpp \ 95 | TinyJS_MathFunctions.cpp \ 96 | TinyJS_StringFunctions.cpp \ 97 | TinyJS_DateFunctions.cpp \ 98 | TinyJS_Threading.cpp 99 | 100 | OBJECTS=$(SOURCES:.cpp=.o) 101 | 102 | 103 | all: run_tests Script 104 | # @echo $(CXXFLAGS) 105 | 106 | run_tests: lib42tiny-js.a run_tests.o 107 | @echo link $@ 108 | $(CXX) $(LDFLAGS) run_tests.o $(LIBS) -o $@ 109 | 110 | Script: lib42tiny-js.a Script.o 111 | @echo link $@ 112 | $(CXX) $(LDFLAGS) Script.o $(LIBS) -o $@ 113 | 114 | lib42tiny-js.a: $(OBJECTS) 115 | 116 | help: 117 | @echo "using make [Options] [target]" 118 | @echo "Options:" 119 | @echo " DEBUG=1: activate debug-mode" 120 | @echo " NO_POOL_ALLOCATOR=1: deactivate the using of the pool-allocator" 121 | 122 | #-------------- rules -------------- 123 | 124 | .cpp.o: 125 | @echo compile $< 126 | $(CXX) -c -MMD -MP -MF $*.dep $(CXXFLAGS) $< -o $@ 127 | 128 | -include *.dep 129 | 130 | clean: 131 | @echo "clean" 132 | @rm -fv prebuild.test.* lib42tiny-js.a run_tests run_tests.exe run_tests.o run_tests.dep Script Script.exe Script.o Script.dep $(OBJECTS) $(OBJECTS:.o=.dep) 133 | 134 | %.a: 135 | @echo link $(notdir $@) 136 | @rm -f $@ 137 | $(AR) -rcs $@ $^ 138 | 139 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ardi69/42tiny-js/a31979449f329f0314f120ad6abb95b57c933ca4/README.md -------------------------------------------------------------------------------- /Script.2017.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8} 23 | Script 24 | Win32Proj 25 | Script 26 | 10.0.22621.0 27 | 28 | 29 | 30 | Application 31 | false 32 | false 33 | MultiByte 34 | true 35 | v141 36 | 37 | 38 | Application 39 | false 40 | false 41 | MultiByte 42 | true 43 | v141 44 | 45 | 46 | Application 47 | false 48 | false 49 | MultiByte 50 | v141 51 | 52 | 53 | Application 54 | false 55 | false 56 | MultiByte 57 | v141 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | <_ProjectFileVersion>10.0.30319.1 77 | $(SolutionDir)$(Configuration)\$(Platform)\ 78 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 79 | true 80 | true 81 | $(SolutionDir)$(Configuration)\$(Platform)\ 82 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 83 | false 84 | false 85 | 86 | 87 | $(SolutionDir)$(Configuration)\$(Platform)\ 88 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 89 | 90 | 91 | $(SolutionDir)$(Configuration)\$(Platform)\ 92 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 93 | 94 | 95 | 96 | Disabled 97 | %(AdditionalIncludeDirectories) 98 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 99 | true 100 | EnableFastChecks 101 | MultiThreadedDebugDLL 102 | 103 | 104 | Level4 105 | EditAndContinue 106 | stdcpp17 107 | 108 | 109 | true 110 | Console 111 | MachineX86 112 | false 113 | 114 | 115 | 116 | 117 | Disabled 118 | %(AdditionalIncludeDirectories) 119 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 120 | EnableFastChecks 121 | MultiThreadedDebugDLL 122 | 123 | 124 | Level4 125 | ProgramDatabase 126 | stdcpp17 127 | 128 | 129 | true 130 | Console 131 | false 132 | 133 | 134 | 135 | 136 | MaxSpeed 137 | true 138 | %(AdditionalIncludeDirectories) 139 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 140 | MultiThreadedDLL 141 | true 142 | 143 | 144 | Level3 145 | ProgramDatabase 146 | stdcpp17 147 | 148 | 149 | true 150 | Console 151 | true 152 | true 153 | MachineX86 154 | 155 | 156 | 157 | 158 | MaxSpeed 159 | true 160 | %(AdditionalIncludeDirectories) 161 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 162 | MultiThreadedDLL 163 | true 164 | 165 | 166 | Level3 167 | ProgramDatabase 168 | stdcpp17 169 | 170 | 171 | true 172 | Console 173 | true 174 | true 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | {9751c465-0294-43cd-a5d9-bd038aba3961} 183 | 184 | 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /Script.2017.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Quelldateien 20 | 21 | 22 | -------------------------------------------------------------------------------- /Script.2022.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8} 23 | Script 24 | Win32Proj 25 | Script 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | false 32 | false 33 | MultiByte 34 | true 35 | v143 36 | 37 | 38 | Application 39 | false 40 | false 41 | MultiByte 42 | true 43 | v143 44 | 45 | 46 | Application 47 | false 48 | false 49 | MultiByte 50 | v143 51 | 52 | 53 | Application 54 | false 55 | false 56 | MultiByte 57 | v143 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | <_ProjectFileVersion>10.0.30319.1 77 | $(SolutionDir)$(Configuration)\$(Platform)\ 78 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 79 | true 80 | true 81 | $(SolutionDir)$(Configuration)\$(Platform)\ 82 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 83 | false 84 | false 85 | 86 | 87 | $(SolutionDir)$(Configuration)\$(Platform)\ 88 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 89 | 90 | 91 | $(SolutionDir)$(Configuration)\$(Platform)\ 92 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 93 | 94 | 95 | 96 | Disabled 97 | %(AdditionalIncludeDirectories) 98 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 99 | EnableFastChecks 100 | MultiThreadedDebugDLL 101 | 102 | 103 | Level4 104 | EditAndContinue 105 | stdcpp17 106 | 107 | 108 | true 109 | Console 110 | MachineX86 111 | false 112 | 113 | 114 | 115 | 116 | Disabled 117 | %(AdditionalIncludeDirectories) 118 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | EnableFastChecks 120 | MultiThreadedDebugDLL 121 | 122 | 123 | Level4 124 | EditAndContinue 125 | stdcpp17 126 | 127 | 128 | true 129 | Console 130 | false 131 | 132 | 133 | 134 | 135 | MaxSpeed 136 | true 137 | %(AdditionalIncludeDirectories) 138 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 139 | MultiThreadedDLL 140 | true 141 | 142 | 143 | Level3 144 | ProgramDatabase 145 | stdcpp17 146 | 147 | 148 | true 149 | Console 150 | true 151 | true 152 | MachineX86 153 | 154 | 155 | 156 | 157 | MaxSpeed 158 | true 159 | %(AdditionalIncludeDirectories) 160 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 161 | MultiThreadedDLL 162 | true 163 | 164 | 165 | Level3 166 | ProgramDatabase 167 | stdcpp17 168 | 169 | 170 | true 171 | Console 172 | true 173 | true 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | {9751c465-0294-43cd-a5d9-bd038aba3961} 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /Script.2022.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Quelldateien 20 | 21 | 22 | -------------------------------------------------------------------------------- /Script.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TinyJS 3 | * 4 | * A single-file Javascript-alike engine 5 | * 6 | * Authored By Gordon Williams 7 | * 8 | * Copyright (C) 2009 Pur3 Ltd 9 | * 10 | 11 | * 42TinyJS 12 | * 13 | * A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine 14 | * 15 | * Authored / Changed By Armin Diedering 16 | * 17 | * Copyright (C) 2010-2025 ardisoft 18 | * 19 | * 20 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 21 | * this software and associated documentation files (the "Software"), to deal in 22 | * the Software without restriction, including without limitation the rights to 23 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 24 | * of the Software, and to permit persons to whom the Software is furnished to do 25 | * so, subject to the following conditions: 26 | 27 | * The above copyright notice and this permission notice shall be included in all 28 | * copies or substantial portions of the Software. 29 | 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36 | * SOFTWARE. 37 | */ 38 | 39 | 40 | /* 41 | * This is a simple program showing how to use TinyJS 42 | */ 43 | 44 | #include "TinyJS.h" 45 | #include 46 | using namespace TinyJS; 47 | 48 | void js_print(const CFunctionsScopePtr &v, void *) { 49 | std::cout << "> " << v->getArgument("text")->toString() << std::endl; 50 | } 51 | 52 | void js_dump(const CFunctionsScopePtr &v, void *) { 53 | v->getContext()->getRoot()->trace("> "); 54 | } 55 | 56 | 57 | char *topOfStack; 58 | #define sizeOfStack 1*1024*1024 /* for example 1 MB depend of Compiler-Options */ 59 | #define sizeOfSafeStack 50*1024 /* safety area */ 60 | 61 | 62 | void registerFnc(CTinyJS *js) { 63 | js->addNative("function print(...text)", &js_print, 0); 64 | // js->addNative("function console.log(text)", &js_print, 0); 65 | // js->addNative("function dump()", &js_dump, js); 66 | } 67 | 68 | 69 | int main(int , char **) { 70 | char dummy; 71 | topOfStack = &dummy; 72 | CTinyJS *js = new CTinyJS{ registerFnc }; 73 | /* Add a native function */ 74 | /* Execute out bit of code - we could call 'evaluate' here if 75 | we wanted something returned */ 76 | js->setStackBase(topOfStack-(sizeOfStack-sizeOfSafeStack)); 77 | try { 78 | js->execute(" lets_quit = 0; function quit() { lets_quit = 1; } dump = this.dump;"); 79 | js->execute("print(\"Interactive mode... Type quit(); to exit, or print(...); to print something, or dump() to dump the symbol table!\");"); 80 | } catch (CScriptException &e) { 81 | std::cout << e.toString() << std::endl; 82 | } 83 | int lineNumber = 0; 84 | while (js->evaluate("lets_quit") == "0") { 85 | std::string buffer; 86 | if(!std::getline(std::cin, buffer)) break; 87 | try { 88 | js->execute(buffer, "console.input", lineNumber++); 89 | } catch (CScriptException &e) { 90 | std::cout << e.toString() << std::endl; 91 | } 92 | } 93 | delete js; 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /TinyJS_Functions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TinyJS 3 | * 4 | * A single-file Javascript-alike engine 5 | * 6 | * Authored By Gordon Williams 7 | * 8 | * Copyright (C) 2009 Pur3 Ltd 9 | * 10 | 11 | * 42TinyJS 12 | * 13 | * A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine 14 | * 15 | * Authored / Changed By Armin Diedering 16 | * 17 | * Copyright (C) 2010-2025 ardisoft 18 | * 19 | * 20 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 21 | * this software and associated documentation files (the "Software"), to deal in 22 | * the Software without restriction, including without limitation the rights to 23 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 24 | * of the Software, and to permit persons to whom the Software is furnished to do 25 | * so, subject to the following conditions: 26 | 27 | * The above copyright notice and this permission notice shall be included in all 28 | * copies or substantial portions of the Software. 29 | 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36 | * SOFTWARE. 37 | */ 38 | 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include "TinyJS.h" 46 | 47 | namespace TinyJS { 48 | 49 | // ----------------------------------------------- Actual Functions 50 | 51 | static void scTrace(const CFunctionsScopePtr &c, void * userdata) { 52 | CTinyJS *js = (CTinyJS*)userdata; 53 | if(c->getArgumentsLength()) 54 | c->getArgument(0)->trace(); 55 | else 56 | js->getRoot()->trace("root"); 57 | } 58 | 59 | static void scObjectDump(const CFunctionsScopePtr &c, void *) { 60 | c->getArgument("this")->trace("> "); 61 | } 62 | 63 | /* 64 | static void scIntegerValueOf(const CFunctionsScopePtr &c, void *) { 65 | string str = c->getArgument("str")->toString(); 66 | 67 | int val = 0; 68 | if (str.length()==1) 69 | val = str.operator[](0); 70 | c->setReturnVar(c->newScriptVar(val)); 71 | } 72 | */ 73 | static void scJSONStringify(const CFunctionsScopePtr &c, void *) { 74 | uint32_t UniqueID = c->getContext()->allocUniqueID(); 75 | bool hasRecursion=false; 76 | c->setReturnVar(c->newScriptVar(c->getArgument("obj")->getParsableString("", " ", UniqueID, hasRecursion))); 77 | c->getContext()->freeUniqueID(); 78 | if(hasRecursion) c->throwError(TypeError, "cyclic object value"); 79 | } 80 | 81 | static void scArrayIncludes(const CFunctionsScopePtr &c, void *data) { 82 | CScriptVarPtr obj = c->getArgument("obj"); 83 | CScriptVarPtr arr = c->getArgument("this"); 84 | uint32_t len = arr->getLength(); 85 | uint32_t from = 0; 86 | if(c->getArgumentsLength() >1) from = c->getArgument(1)->toNumber().clampIndex(len).toUInt32(); 87 | auto begin = lower_bound(arr->Childs.begin(), arr->Childs.end(), from); 88 | auto end = lower_bound(begin, arr->Childs.end(), len); 89 | for (auto it = begin; it != end; ++it) { 90 | if (obj->mathsOp(it->getter(), LEX_EQUAL)->toBoolean()) { 91 | c->setReturnVar(c->constScriptVar(true)); 92 | return; 93 | } 94 | } 95 | c->setReturnVar(c->constScriptVar(false)); 96 | } 97 | 98 | static void scArrayRemove(const CFunctionsScopePtr &c, void *data) { 99 | CScriptVarPtr obj = c->getArgument("obj"); 100 | CScriptVarPtr arr = c->getArgument("this"); 101 | uint32_t len = arr->getLength(); 102 | uint32_t offset = 0; 103 | for(SCRIPTVAR_CHILDS_it it= lower_bound(arr->Childs.begin(), arr->Childs.end(), static_cast(0)); it != arr->Childs.end(); ++it) { 104 | while(it != arr->Childs.end() && obj->mathsOp(it->getter(), LEX_EQUAL)->toBoolean()) { 105 | it = arr->Childs.erase(it); 106 | offset++; 107 | } 108 | if(offset && it != arr->Childs.end()) 109 | (*it)->reName((*it)->getName().toArrayIndex() - offset); 110 | } 111 | if (offset) { 112 | c->setProperty(arr, "length", c->newScriptVar(len - offset)); 113 | 114 | } 115 | } 116 | 117 | static void scArrayJoin(const CFunctionsScopePtr &c, void *data) { 118 | auto sepVar = c->getArgument("separator"); 119 | std::string sep = sepVar->isUndefined() ? ", " : c->getArgument("separator")->toString(); 120 | CScriptVarPtr arr = c->getArgument("this"); 121 | 122 | std::ostringstream sstr; 123 | uint32_t l = arr->getLength(); 124 | for (uint32_t i=0;i0) sstr << sep; 126 | sstr << c->getPropertyValue(arr, i)->toString(); 127 | } 128 | 129 | c->setReturnVar(c->newScriptVar(sstr.str())); 130 | } 131 | 132 | static void scArrayFill(const CFunctionsScopePtr &c, void *data) { 133 | CScriptVarPtr arr = c->getArgument("this"); 134 | uint32_t len = c->getLength(arr); 135 | uint32_t args = c->getArgumentsLength(); 136 | CScriptVarPtr value = c->getArgument(0); 137 | uint32_t start=0, end=len; 138 | if (args > 1) start = c->getArgument(1)->toNumber().clampIndex(len).toUInt32(); 139 | if (args > 2) end = c->getArgument(2)->toNumber().clampIndex(len).toUInt32(); 140 | for(; start < end; ++start) c->setProperty(arr, start, value); 141 | c->setReturnVar(arr); 142 | } 143 | 144 | static void scArrayPop(const CFunctionsScopePtr &c, void *data) { 145 | CScriptVarPtr arr = c->getArgument("this"); 146 | uint32_t len = c->getLength(arr); 147 | if(len) { 148 | c->setReturnVar(c->getPropertyValue(arr, len-1)); 149 | c->removeOwnProperty(arr, len - 1); 150 | c->setProperty(arr, "length", c->newScriptVar(len - 1)); 151 | } else 152 | c->setReturnVar(c->constScriptVar(Undefined)); 153 | } 154 | 155 | static void scArrayPush(const CFunctionsScopePtr &c, void *data) { 156 | CScriptVarPtr arr = c->getArgument("this"); 157 | uint32_t len = c->getLength(arr); 158 | uint32_t args = c->getArgumentsLength(); 159 | bool rangeError = len > (std::numeric_limits::max() - args); 160 | if (rangeError) args = std::numeric_limits::max() - len; 161 | for (uint32_t src = 0, dst = len; src < args; ++src, ++dst) 162 | c->setProperty(arr, dst, c->getArgument(src)); 163 | c->setProperty(arr, "length", c->newScriptVar(len + args)); 164 | if (rangeError) c->throwError(RangeError, "Failed to set the 'length' property on 'Array': Invalid array length"); 165 | } 166 | 167 | namespace { 168 | class cmp_fnc { 169 | public: 170 | cmp_fnc(const CFunctionsScopePtr &Scope, CScriptVarFunctionPtr Fnc) : c(Scope), fnc(Fnc) {} 171 | bool operator()(CScriptVarLinkPtr a,CScriptVarLinkPtr b) { 172 | auto _a = a.getter(); 173 | auto _b = b.getter(); 174 | if(_a->getVarPtr()->isUndefined()) { 175 | return false; 176 | } else if(_b->getVarPtr()->isUndefined()) 177 | return true; 178 | else if(fnc) { 179 | std::vector arguments; 180 | arguments.push_back(_a); 181 | arguments.push_back(_b); 182 | return c->getContext()->callFunction(fnc, arguments)->toNumber().toInt32() < 0; 183 | } 184 | else { 185 | return _a->toString() < _b->toString(); 186 | } 187 | } 188 | const CFunctionsScopePtr &c; 189 | CScriptVarFunctionPtr fnc; 190 | }; 191 | // bool cmp_by_name(const CScriptVarLinkPtr &a, const CScriptVarLinkPtr &b) { 192 | // return a < b->getName(); 193 | // } 194 | } 195 | static void scArraySort(const CFunctionsScopePtr &c, void *data) { 196 | CScriptVarPtr arr = c->getArgument("this"); 197 | CScriptVarFunctionPtr cmp_fnc; 198 | uint32_t len = arr->getLength(); 199 | if(len > 1) { 200 | int args = c->getArgumentsLength(); 201 | if(args) { 202 | cmp_fnc = c->getArgument(0); 203 | if(!cmp_fnc) c->throwError(TypeError, "invalid Array.prototype.sort argument"); 204 | } 205 | SCRIPTVAR_CHILDS_it begin = lower_bound(arr->Childs.begin(), arr->Childs.end(), static_cast(0)); 206 | SCRIPTVAR_CHILDS_it end = lower_bound(begin, arr->Childs.end(), len); 207 | if(begin != end) { 208 | 209 | /* in ECMAScript the sort algorithm is not specified 210 | * in some cases sort throws a TypeError e.G. an array element is read-only, non-configurable, getter or setter 211 | * this will result in a partially sorted array 212 | * in worst case the sort algorithm results in an endless loop (more getters with constant return value) 213 | * 214 | * 42TinyJS checks before sort if an element read-only, setter or getter and throws immediately a TypeError 215 | */ 216 | uint32_t lastIndex = (*(end - 1))->getName().toIndex(); 217 | uint32_t countOfEntries = static_cast(std::distance(begin, end)); 218 | uint32_t countOfHoles = lastIndex + 1 - countOfEntries; 219 | uint32_t isExtensible = arr->isExtensible(); 220 | uint32_t idx = 0; 221 | for (SCRIPTVAR_CHILDS_it it = begin; it != end; ++it, ++idx) { 222 | if (countOfHoles && !isExtensible && (*it)->getName().toIndex() != idx) 223 | c->throwError(TypeError, "Cannot add property " + std::to_string(idx) + ", array is not extensible"); 224 | if (idx >= countOfEntries - countOfHoles && (*it)->getName().toIndex() > lastIndex - countOfHoles && !(*it)->isConfigurable()) 225 | c->throwError(TypeError, "Cannot delete property '" + (*it)->getName().toString() + "' array entry is not configurable"); 226 | if (!(*it)->isWritable()) c->throwError(TypeError, "Cannot assign to read-only property '" + (*it)->getName().toString() + "'"); 227 | if ((*it)->getVarPtr()->isAccessor()) c->throwError(TypeError, "Cannot sort an array containing accessors, e.g., '" + (*it)->getName().toString() + "'"); 228 | } 229 | // if (!(*it)->isConfigurable()) c->throwError(TypeError, "property " + (*it)->getName() + " is non-configurable"); 230 | 231 | sort(begin, end, TinyJS::cmp_fnc(c, cmp_fnc)); 232 | idx = 0; 233 | for (SCRIPTVAR_CHILDS_it it = begin; it != end; ++it, ++idx) 234 | (*it)->reName(idx); 235 | //sort(begin, arr->Childs.end(), cmp_by_name); 236 | } 237 | } 238 | c->setReturnVar(arr); 239 | } 240 | 241 | static void scArrayMap(const CFunctionsScopePtr &c, void *data) { 242 | CScriptVarPtr arr = c->getArgument("this"); 243 | uint32_t len = arr->getLength(); 244 | CScriptVarFunctionPtr fnc = c->getArgument("fnc"); 245 | CScriptVarPtr thisArg; if(c->getArgumentsLength() > 1) thisArg = c->getArgument("thisArg"); 246 | if (!fnc) c->throwError(TypeError, "invalid Array.prototype.map argument"); 247 | CScriptVarPtr newArr = c->newScriptVar(Array); 248 | if (len > 0) { 249 | SCRIPTVAR_CHILDS_it begin = lower_bound(arr->Childs.begin(), arr->Childs.end(), static_cast(0)); 250 | SCRIPTVAR_CHILDS_it end = lower_bound(begin, arr->Childs.end(), len); 251 | for (SCRIPTVAR_CHILDS_it it = begin; it != end; ++it) { 252 | std::vector arguments{ (*it).getter(), c->newScriptVar((*it)->getName().toIndex()), arr}; 253 | //c->setProperty(newArr, (*it)->getName(), c->getContext()->callFunction(fnc, arguments, thisArg)); 254 | newArr->addChild((*it)->getName(), c->getContext()->callFunction(fnc, arguments, thisArg)); // addChild is used because fastern than srtProperty 255 | } 256 | } 257 | c->setReturnVar(newArr); 258 | } 259 | 260 | static void scArrayShift(const CFunctionsScopePtr &c, void *data) { 261 | CScriptVarPtr arr = c->getArgument("this"); 262 | uint32_t len = arr->getLength(); 263 | if (len == 0) { 264 | c->setReturnVar(c->constScriptVar(Undefined)); 265 | return; 266 | } 267 | 268 | CScriptVarPtr first = c->getPropertyValue(arr, static_cast(0)); 269 | for (uint32_t i = 1; i < len; ++i) { 270 | auto v = arr->findChild(i); 271 | if (v) 272 | c->setProperty(arr, i - 1, c->getPropertyValue(arr, i)); 273 | else 274 | c->removeOwnProperty(arr, i - 1); 275 | } 276 | c->removeOwnProperty(arr, len - 1); // remove last element 277 | c->setProperty(arr, "length", c->newScriptVar(len - 1)); 278 | c->setReturnVar(first); 279 | } 280 | 281 | 282 | static void scArrayUnshift(const CFunctionsScopePtr &c, void *data) { 283 | CScriptVarPtr arr = c->getArgument("this"); 284 | uint32_t len = arr->getLength(); 285 | uint32_t args = c->getArgumentsLength(); 286 | if (args) { 287 | bool rangeError = len > (std::numeric_limits::max() - args); 288 | if (rangeError) args = std::numeric_limits::max() - len; 289 | 290 | if (len > 0) for (auto src = len - 1, dst = src + args; dst >= args; --src, --dst) 291 | c->setProperty(arr, dst, c->getPropertyValue(arr, src)); 292 | for (auto i = 0U; i < args; ++i) 293 | c->setProperty(arr, i, c->getArgument(i)); 294 | c->setProperty(arr, "length", c->newScriptVar(len + args)); 295 | if (rangeError) c->throwError(RangeError, "Failed to set the 'length' property on 'Array': Invalid array length"); 296 | } 297 | c->setReturnVar(c->newScriptVar(len + args)); 298 | } 299 | 300 | static void scArraySlice(const CFunctionsScopePtr &c, void *data) { 301 | CScriptVarPtr arr = c->getArgument("this"); 302 | auto argumentsLength = c->getArgumentsLength(); 303 | int32_t len = arr->getLength(); 304 | int32_t start = 0, end = (int32_t)len; 305 | if (argumentsLength > 0) start = c->getArgument(0)->toNumber().clampIndex(len).toUInt32(); 306 | if (argumentsLength > 1) end = c->getArgument(1)->toNumber().clampIndex(len).toUInt32(); 307 | CScriptVarPtr newArr = c->newScriptVar(Array); 308 | for (int32_t src = start, dst = 0; src < end; ++src, ++dst) { 309 | newArr->addChild(dst, c->getPropertyValue(arr, src)); // addChild is used because fastern than srtProperty 310 | //c->setProperty(newArr, i, c->getPropertyValue(arr, start + i)); 311 | } 312 | c->setReturnVar(newArr); 313 | } 314 | 315 | static void scArraySplice(const CFunctionsScopePtr &c, void *data) { 316 | CScriptVarPtr arr = c->getArgument("this"); 317 | uint32_t len = arr->getLength(); 318 | uint32_t args = c->getArgumentsLength(); 319 | uint32_t start = 0, delCount = 0; 320 | if (args > 0) start = c->getArgument(0)->toNumber().clampIndex(len).toUInt32(); 321 | if (args > 1) delCount = c->getArgument(1)->toNumber().clamp(0, len - start).toUInt32(); 322 | 323 | CScriptVarPtr removed = c->newScriptVar(Array); 324 | for (uint32_t i = 0; i < delCount; ++i) { 325 | auto v = arr->findChild(start + i); 326 | if (v) { 327 | // c->setProperty(removed, i, c->getPropertyValue(arr, start + i)); 328 | removed->addChild(i, v.getter()); // addChild is used because fastern than srtProperty 329 | } 330 | } 331 | args = args > 2 ? args - 2 : 0; 332 | if (len) { // Ensure the length is non-zero 333 | if (args < delCount) { // If the number of elements to add is less than the number to delete 334 | for (uint32_t dst = start + args, src = start + delCount; src < len; ++dst, ++src) { 335 | // Shift remaining elements downwards to fill in the deleted space 336 | c->setProperty(arr, dst, c->getPropertyValue(arr, src)); 337 | } 338 | for (uint32_t dst = len + args - delCount; dst < len; ++dst) { 339 | // Remove any remaining elements after the deletion 340 | c->removeOwnProperty(arr, dst); 341 | } 342 | } else if (args > delCount) { // If the number of elements to add is greater than the number to delete 343 | uint32_t shift = args - delCount; // Calculate how many extra elements are being added 344 | for (uint32_t src = len, dst = src + shift; src > start + delCount; --src, --dst) { 345 | // Move elements from the end to make space for the added elements 346 | c->setProperty(arr, dst - 1, c->getPropertyValue(arr, src - 1)); 347 | } 348 | } 349 | } 350 | 351 | // Insert the new elements at the specified starting position 352 | for (uint32_t src = 0, dst = start; src < args; ++src, ++dst) { 353 | c->setProperty(arr, dst, c->getArgument(src + 2)); // Set the new arguments starting from position 'start' 354 | } 355 | c->setProperty(arr, "length", c->newScriptVar(len + args - delCount)); 356 | c->setReturnVar(removed); 357 | } 358 | 359 | static void scArrayForEach(const CFunctionsScopePtr &c, void *data) { 360 | CScriptVarPtr arr = c->getArgument("this"); 361 | CScriptVarFunctionPtr callback = c->getArgument("callback"); 362 | if (!callback) c->throwError(TypeError, "forEach requires a callback function"); 363 | uint32_t len = arr->getLength(); 364 | 365 | SCRIPTVAR_CHILDS_it begin = lower_bound(arr->Childs.begin(), arr->Childs.end(), static_cast(0)); 366 | SCRIPTVAR_CHILDS_it end = lower_bound(begin, arr->Childs.end(), len); 367 | for (auto it = begin; it != end; ++it) { 368 | std::vector args = { it->getter(), c->newScriptVar((*it)->getName().toArrayIndex()), arr}; 369 | c->getContext()->callFunction(callback, args); 370 | } 371 | } 372 | 373 | static void scArrayIndexOf(const CFunctionsScopePtr &c, void *data) { 374 | CScriptVarPtr arr = c->getArgument("this"); 375 | CScriptVarPtr search = c->getArgument(0); 376 | uint32_t len = arr->getLength(); 377 | 378 | SCRIPTVAR_CHILDS_it begin = lower_bound(arr->Childs.begin(), arr->Childs.end(), static_cast(0)); 379 | SCRIPTVAR_CHILDS_it end = lower_bound(begin, arr->Childs.end(), len); 380 | for (auto it = begin; it != end; ++it) { 381 | if (search->mathsOp((*it).getter(), LEX_EQUAL)->toBoolean()) { 382 | c->setReturnVar(c->newScriptVar((*it)->getName().toArrayIndex())); 383 | return; 384 | } 385 | } 386 | c->setReturnVar(c->newScriptVar(-1)); 387 | } 388 | 389 | static void scArrayReduce(const CFunctionsScopePtr &c, void *data) { 390 | CScriptVarPtr arr = c->getArgument("this"); 391 | uint32_t len = arr->getLength(); 392 | CScriptVarFunctionPtr callback = c->getArgument("callback"); 393 | if (!callback) c->throwError(TypeError, "Reduce requires a callback function"); 394 | 395 | auto begin = lower_bound(arr->Childs.begin(), arr->Childs.end(), static_cast(0)); 396 | auto end = lower_bound(begin, arr->Childs.end(), len); 397 | if (begin != end) { 398 | CScriptVarPtr accumulator;// = c->getArgument(1); 399 | if (c->getArgumentsLength() > 1) 400 | accumulator = c->getArgument(1); 401 | else { 402 | accumulator = begin++->getter(); 403 | } 404 | for (auto it = begin; it != end; ++it) { 405 | std::vector args{ accumulator, it->getter(), c->newScriptVar((*it)->getName().toArrayIndex()), arr }; 406 | accumulator = c->getContext()->callFunction(callback, args); 407 | } 408 | c->setReturnVar(accumulator); 409 | } else if (c->getArgumentsLength() > 1) 410 | c->setReturnVar(c->getArgument(1)); 411 | else 412 | c->throwError(TypeError, "Reduce of empty array with no initiel value"); 413 | } 414 | 415 | static void scArrayReduceRight(const CFunctionsScopePtr &c, void *data) { 416 | CScriptVarPtr arr = c->getArgument("this"); 417 | uint32_t len = arr->getLength(); 418 | CScriptVarFunctionPtr callback = c->getArgument("callback"); 419 | if (!callback) c->throwError(TypeError, "Reduce requires a callback function"); 420 | 421 | auto end = std::make_reverse_iterator(lower_bound(arr->Childs.begin(), arr->Childs.end(), static_cast(0))); 422 | auto begin = std::make_reverse_iterator(lower_bound(end.base(), arr->Childs.end(), len)); 423 | if (begin != end) { 424 | CScriptVarPtr accumulator;// = c->getArgument(1); 425 | if (c->getArgumentsLength() > 1) 426 | accumulator = c->getArgument(1); 427 | else { 428 | accumulator = begin++->getter(); 429 | } 430 | for (auto it = begin; it != end; ++it) { 431 | std::vector args{ accumulator, it->getter(), c->newScriptVar((*it)->getName().toArrayIndex()), arr }; 432 | accumulator = c->getContext()->callFunction(callback, args); 433 | } 434 | c->setReturnVar(accumulator); 435 | } else if (c->getArgumentsLength() > 1) 436 | c->setReturnVar(c->getArgument(1)); 437 | else 438 | c->throwError(TypeError, "Reduce of empty array with no initiel value"); 439 | } 440 | 441 | 442 | // ----------------------------------------------- Register Functions 443 | extern "C" void _registerFunctions(CTinyJS *tinyJS) { 444 | tinyJS->addNative("function trace()", scTrace, tinyJS, SCRIPTVARLINK_BUILDINDEFAULT); 445 | tinyJS->addNative("function Object.prototype.dump()", scObjectDump, 0, SCRIPTVARLINK_BUILDINDEFAULT); 446 | 447 | // tinyJS->addNative("function Integer.valueOf(str)", scIntegerValueOf, 0, SCRIPTVARLINK_BUILDINDEFAULT); // value of a single character 448 | tinyJS->addNative("function JSON.stringify(obj, replacer)", scJSONStringify, 0, SCRIPTVARLINK_BUILDINDEFAULT); // convert to JSON. replacer is ignored at the moment 449 | 450 | // Array 451 | tinyJS->addNative("function Array.prototype.includes(obj)", scArrayIncludes, 0, SCRIPTVARLINK_BUILDINDEFAULT); 452 | tinyJS->addNative("function Array.prototype.remove(obj)", scArrayRemove, 0, SCRIPTVARLINK_BUILDINDEFAULT); 453 | tinyJS->addNative("function Array.prototype.join(separator)", scArrayJoin, 0, SCRIPTVARLINK_BUILDINDEFAULT); 454 | tinyJS->addNative("function Array.prototype.fill()", scArrayFill, 0, SCRIPTVARLINK_BUILDINDEFAULT); 455 | tinyJS->addNative("function Array.prototype.pop()", scArrayPop, 0, SCRIPTVARLINK_BUILDINDEFAULT); 456 | tinyJS->addNative("function Array.prototype.push()", scArrayPush, 0, SCRIPTVARLINK_BUILDINDEFAULT); 457 | tinyJS->addNative("function Array.prototype.sort()", scArraySort, 0, SCRIPTVARLINK_BUILDINDEFAULT); 458 | tinyJS->addNative("function Array.prototype.map(fnc, thisArg)", scArrayMap, 0, SCRIPTVARLINK_BUILDINDEFAULT); 459 | 460 | tinyJS->addNative("function Array.prototype.shift()", scArrayShift, 0, SCRIPTVARLINK_BUILDINDEFAULT); 461 | tinyJS->addNative("function Array.prototype.unshift()", scArrayUnshift, 0, SCRIPTVARLINK_BUILDINDEFAULT); 462 | tinyJS->addNative("function Array.prototype.slice()", scArraySlice, 0, SCRIPTVARLINK_BUILDINDEFAULT); 463 | tinyJS->addNative("function Array.prototype.splice()", scArraySplice, 0, SCRIPTVARLINK_BUILDINDEFAULT); 464 | tinyJS->addNative("function Array.prototype.forEach(callback)", scArrayForEach, 0, SCRIPTVARLINK_BUILDINDEFAULT); 465 | tinyJS->addNative("function Array.prototype.indexOf()", scArrayIndexOf, 0, SCRIPTVARLINK_BUILDINDEFAULT); 466 | tinyJS->addNative("function Array.prototype.reduce(callback, initialValue)", scArrayReduce, 0, SCRIPTVARLINK_BUILDINDEFAULT); 467 | tinyJS->addNative("function Array.prototype.reduceRight(callback, initialValue)", scArrayReduceRight, 0, SCRIPTVARLINK_BUILDINDEFAULT); 468 | 469 | } 470 | 471 | } /* namespace TinyJS */ -------------------------------------------------------------------------------- /TinyJS_MathFunctions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TinyJS 3 | * 4 | * A single-file Javascript-alike engine 5 | * 6 | * - Math and Trigonometry functions 7 | * 8 | * Authored By O.Z.L.B. 9 | * 10 | * Copyright (C) 2011 O.Z.L.B. 11 | * 12 | 13 | * 42TinyJS 14 | * 15 | * A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine 16 | * 17 | * Authored / Changed By Armin Diedering 18 | * 19 | * Copyright (C) 2010-2025 ardisoft 20 | * 21 | * 22 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 23 | * this software and associated documentation files (the "Software"), to deal in 24 | * the Software without restriction, including without limitation the rights to 25 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 26 | * of the Software, and to permit persons to whom the Software is furnished to do 27 | * so, subject to the following conditions: 28 | 29 | * The above copyright notice and this permission notice shall be included in all 30 | * copies or substantial portions of the Software. 31 | 32 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 33 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 34 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 35 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 36 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 37 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 38 | * SOFTWARE. 39 | */ 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include "TinyJS.h" 46 | 47 | namespace TinyJS { 48 | 49 | inline constexpr double k_PI = 3.1415926535897932384626433832795; // π 50 | inline constexpr double k_E = 2.7182818284590452353602874713527; // exp(1.0) 51 | inline constexpr double k_LN2 = 0.69314718055994530941723212145818; // log(2.0) 52 | inline constexpr double k_LN10 = 2.3025850929940456840179914546844; // log(10.0) 53 | inline constexpr double k_LOG2E = 1.4426950408889634073599246810019; // log(E) / log(2.0) 54 | inline constexpr double k_LOG10E = 0.43429448190325182765112891891661; // log10(E) 55 | inline constexpr double k_SQRT1_2 = 0.70710678118654752440084436210485; // sqrt(0.5) 56 | inline constexpr double k_SQRT2 = 1.4142135623730950488016887242097; // sqrt(2.0) 57 | /* 58 | #define F_ABS(a) ((a)>=0 ? (a) : (-(a))) 59 | #define F_MIN(a,b) ((a)>(b) ? (b) : (a)) 60 | #define F_MAX(a,b) ((a)>(b) ? (a) : (b)) 61 | #define F_SGN(a) ((a)>0 ? 1 : ((a)<0 ? -1 : 0 )) 62 | #define F_RNG(a,min,max) ((a)<(min) ? min : ((a)>(max) ? max : a )) 63 | */ 64 | #if defined(_MSC_VER) && _MSC_VER <= 1700 65 | namespace 66 | { 67 | 68 | double asinh( const double &value ) { 69 | double returned; 70 | 71 | if(value>0) 72 | returned = log(value + sqrt(value * value + 1)); 73 | else 74 | returned = -log(-value + sqrt(value * value + 1)); 75 | 76 | return(returned); 77 | } 78 | 79 | double acosh( const double &value ) { 80 | double returned; 81 | 82 | if(value>0) 83 | returned = log(value + sqrt(value * value - 1)); 84 | else 85 | returned = -log(-value + sqrt(value * value - 1)); 86 | 87 | return(returned); 88 | } 89 | 90 | double atanh( double value ) { 91 | bool neg = value<0; 92 | if(neg) value=-value; 93 | double value_x2 = 2.0*value; 94 | if(value>=0.5) 95 | value = log(1.0+value_x2/(1.0-value))/2.0; 96 | else 97 | value = log(1.0+value_x2+value_x2*value/(1.0-value))/2.0; 98 | return(neg ? -value : value); 99 | } 100 | } 101 | #endif 102 | 103 | #define PARAMETER_TO_NUMBER(v,n) CNumber v = c->getArgument(n)->toNumber() 104 | #define RETURN_NAN_IS_NAN(v) do{ if(v.isNaN()) { c->setReturnVar(c->constScriptVar(NaN)); return; } }while(0) 105 | #define RETURN_NAN_IS_NAN_OR_INFINITY(v) do{ if(v.isNaN() || v.isInfinity()) { c->setReturnVar(c->constScriptVar(NaN)); return; } }while(0) 106 | #define RETURN_INFINITY_IS_INFINITY(v) do{ if(v.isInfinity()) { c->setReturnVar(c->constScriptVar(v.isInfinity()<0 ? InfinityNegative : InfinityPositive)); return; } }while(0) 107 | #define RETURN_ZERO_IS_ZERO(v) do{ if(v.isZero()) { c->setReturnVar(c->newScriptVar(v)); return; } }while(0) 108 | #define RETURN(a) do{ c->setReturnVar(c->newScriptVar(a)); return; }while(0) 109 | #define RETURNconst(a) c->setReturnVar(c->constScriptVar(a)) 110 | 111 | //Math.abs(x) - returns absolute of given value 112 | static void scMathAbs(const CFunctionsScopePtr &c, void *userdata) { 113 | PARAMETER_TO_NUMBER(a,"a"); 114 | RETURN(a.sign()<0?-a:a); 115 | } 116 | 117 | //Math.round(a) - returns nearest round of given value 118 | static void scMathRound(const CFunctionsScopePtr &c, void *userdata) { 119 | PARAMETER_TO_NUMBER(a,"a"); 120 | RETURN(a.round()); 121 | } 122 | 123 | //Math.ceil(a) - returns nearest round of given value 124 | static void scMathCeil(const CFunctionsScopePtr &c, void *userdata) { 125 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_INFINITY_IS_INFINITY(a); 126 | RETURN(a.ceil()); 127 | } 128 | 129 | //Math.floor(a) - returns nearest round of given value 130 | static void scMathFloor(const CFunctionsScopePtr &c, void *userdata) { 131 | PARAMETER_TO_NUMBER(a,"a"); 132 | RETURN(a.floor()); 133 | } 134 | 135 | //Math.min(a,b) - returns minimum of two given values 136 | static void scMathMin(const CFunctionsScopePtr &c, void *userdata) { 137 | int length = c->getArgumentsLength(); 138 | CNumber ret(InfinityPositive); 139 | for(int i=0; ia) ret=a; 143 | } 144 | RETURN(ret); 145 | } 146 | 147 | //Math.max(a,b) - returns maximum of two given values 148 | static void scMathMax(const CFunctionsScopePtr &c, void *userdata) { 149 | int length = c->getArgumentsLength(); 150 | CNumber ret(InfinityNegative); 151 | for(int i=0; ib) RETURNconst(NaN); 166 | if(xb) RETURN(b); 168 | RETURN(x); 169 | } 170 | 171 | //Math.sign(a) - returns sign of given value (-1==negative,0=zero,1=positive) 172 | static void scMathSign(const CFunctionsScopePtr &c, void *userdata) { 173 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); 174 | RETURN(a.isZero() ? 0 : a.sign()); 175 | } 176 | static void scMathRandom(const CFunctionsScopePtr &c, void *) { 177 | static int inited=0; 178 | if(!inited) { 179 | inited = 1; 180 | srand((unsigned int)time(NULL)); 181 | } 182 | RETURN(double(rand())/RAND_MAX); 183 | } 184 | 185 | //Math.toDegrees(a) - returns degree value of a given angle in radians 186 | static void scMathToDegrees(const CFunctionsScopePtr &c, void *userdata) { 187 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_INFINITY_IS_INFINITY(a); 188 | RETURN( (180.0/k_PI)*a ); 189 | } 190 | 191 | //Math.toRadians(a) - returns radians value of a given angle in degrees 192 | static void scMathToRadians(const CFunctionsScopePtr &c, void *userdata) { 193 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_INFINITY_IS_INFINITY(a); 194 | RETURN( (k_PI/180.0)*a ); 195 | } 196 | 197 | //Math.sin(a) - returns trig. sine of given angle in radians 198 | static void scMathSin(const CFunctionsScopePtr &c, void *userdata) { 199 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN_OR_INFINITY(a); RETURN_ZERO_IS_ZERO(a); 200 | RETURN( sin(a.toDouble()) ); 201 | } 202 | 203 | //Math.asin(a) - returns trig. arcsine of given angle in radians 204 | static void scMathASin(const CFunctionsScopePtr &c, void *userdata) { 205 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_ZERO_IS_ZERO(a); 206 | if(abs(a)>1) RETURNconst(NaN); 207 | RETURN( asin(a.toDouble()) ); 208 | } 209 | 210 | //Math.cos(a) - returns trig. cosine of given angle in radians 211 | static void scMathCos(const CFunctionsScopePtr &c, void *userdata) { 212 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN_OR_INFINITY(a); 213 | if(a.isZero()) RETURN(1); 214 | RETURN( cos(a.toDouble()) ); 215 | } 216 | 217 | //Math.acos(a) - returns trig. arccosine of given angle in radians 218 | static void scMathACos(const CFunctionsScopePtr &c, void *userdata) { 219 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN_OR_INFINITY(a); 220 | if(abs(a)>1) RETURNconst(NaN); 221 | else if(a==1) RETURN(0); 222 | RETURN( acos(a.toDouble()) ); 223 | } 224 | 225 | //Math.tan(a) - returns trig. tangent of given angle in radians 226 | static void scMathTan(const CFunctionsScopePtr &c, void *userdata) { 227 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN_OR_INFINITY(a); RETURN_ZERO_IS_ZERO(a); 228 | RETURN( tan(a.toDouble()) ); 229 | } 230 | 231 | //Math.atan(a) - returns trig. arctangent of given angle in radians 232 | static void scMathATan(const CFunctionsScopePtr &c, void *userdata) { 233 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_ZERO_IS_ZERO(a); 234 | int infinity=a.isInfinity(); 235 | if(infinity) RETURN(k_PI/(infinity*2)); 236 | RETURN( atan(a.toDouble()) ); 237 | } 238 | 239 | //Math.atan2(a,b) - returns trig. arctangent of given angle in radians 240 | static void scMathATan2(const CFunctionsScopePtr &c, void *userdata) { 241 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); 242 | PARAMETER_TO_NUMBER(b,"b"); RETURN_NAN_IS_NAN(b); 243 | int sign_a = a.sign(); 244 | int sign_b = b.sign(); 245 | if(a.isZero()) 246 | RETURN(sign_a>0 ? (sign_b>0 ? 0.0 : k_PI) : (sign_b>0 ? -0.0 : -k_PI)); 247 | else if(b.isZero()) 248 | RETURN((sign_a>0 ? k_PI : -k_PI)/2.0); 249 | int infinity_a=a.isInfinity(); 250 | int infinity_b=b.isInfinity(); 251 | if(infinity_a) { 252 | if(infinity_b>0) RETURN(k_PI/(infinity_a*4)); 253 | else if(infinity_b<0) RETURN(3.0*k_PI/(infinity_a*4)); 254 | else RETURN(k_PI/(infinity_a*2)); 255 | } else if(infinity_b>0) 256 | RETURN(sign_a>0 ? 0.0 : -0.0); 257 | else if(infinity_b<0) 258 | RETURN(sign_a>0 ? k_PI : -k_PI); 259 | RETURN( atan2(a.toDouble(), b.toDouble()) ); 260 | } 261 | 262 | 263 | //Math.sinh(a) - returns trig. hyperbolic sine of given angle in radians 264 | static void scMathSinh(const CFunctionsScopePtr &c, void *userdata) { 265 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); 266 | RETURN_ZERO_IS_ZERO(a); 267 | if(abs(a)>1) RETURNconst(NaN); 268 | RETURN( sinh(a.toDouble()) ); 269 | } 270 | 271 | //Math.asinh(a) - returns trig. hyperbolic arcsine of given angle in radians 272 | static void scMathASinh(const CFunctionsScopePtr &c, void *userdata) { 273 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); 274 | RETURN_INFINITY_IS_INFINITY(a); 275 | RETURN_ZERO_IS_ZERO(a); 276 | RETURN( asinh(a.toDouble()) ); 277 | } 278 | 279 | //Math.cosh(a) - returns trig. hyperbolic cosine of given angle in radians 280 | static void scMathCosh(const CFunctionsScopePtr &c, void *userdata) { 281 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); 282 | if(a.isInfinity()) RETURNconst(InfinityPositive); 283 | RETURN( cosh(a.toDouble()) ); 284 | } 285 | 286 | //Math.acosh(a) - returns trig. hyperbolic arccosine of given angle in radians 287 | static void scMathACosh(const CFunctionsScopePtr &c, void *userdata) { 288 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); 289 | RETURN_INFINITY_IS_INFINITY(a); 290 | if(abs(a)<1) RETURNconst(NaN); 291 | RETURN( acosh(a.toDouble()) ); 292 | } 293 | 294 | //Math.tanh(a) - returns trig. hyperbolic tangent of given angle in radians 295 | static void scMathTanh(const CFunctionsScopePtr &c, void *userdata) { 296 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); 297 | RETURN_ZERO_IS_ZERO(a); 298 | if(a.isInfinity()) RETURN(a.sign()); 299 | RETURN( tanh(a.toDouble()) ); 300 | } 301 | 302 | //Math.atanh(a) - returns trig. hyperbolic arctangent of given angle in radians 303 | static void scMathATanh(const CFunctionsScopePtr &c, void *userdata) { 304 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); 305 | RETURN_ZERO_IS_ZERO(a); 306 | CNumber abs_a = abs(a); 307 | if(abs_a > 1) RETURNconst(NaN); 308 | if(abs_a == 1) RETURNconst(Infinity(a.sign())); 309 | RETURN( atanh(a.toDouble()) ); 310 | } 311 | 312 | //Math.log(a) - returns natural logaritm (base E) of given value 313 | static void scMathLog(const CFunctionsScopePtr &c, void *userdata) { 314 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); 315 | if(a.isZero()) RETURNconst(InfinityNegative); 316 | if(a.sign()<0) RETURNconst(NaN); 317 | if(a.isInfinity()) RETURNconst(InfinityPositive); 318 | RETURN( log( a.toDouble()) ); 319 | } 320 | 321 | //Math.log10(a) - returns logaritm(base 10) of given value 322 | static void scMathLog10(const CFunctionsScopePtr &c, void *userdata) { 323 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); 324 | if(a.isZero()) RETURNconst(InfinityNegative); 325 | if(a.sign()<0) RETURNconst(NaN); 326 | if(a.isInfinity()) RETURNconst(InfinityPositive); 327 | RETURN( log10( a.toDouble()) ); 328 | } 329 | 330 | //Math.exp(a) - returns e raised to the power of a given number 331 | static void scMathExp(const CFunctionsScopePtr &c, void *userdata) { 332 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); 333 | if(a.isZero()) RETURN(1); 334 | int a_i = a.isInfinity(); 335 | if(a_i>0) RETURNconst(InfinityPositive); 336 | else if(a_i<0) RETURN(0); 337 | RETURN( exp(a.toDouble()) ); 338 | } 339 | 340 | //Math.pow(a,b) - returns the result of a number raised to a power (a)^(b) 341 | static void scMathPow(const CFunctionsScopePtr &c, void *userdata) { 342 | PARAMETER_TO_NUMBER(a,"a"); 343 | PARAMETER_TO_NUMBER(b,"b"); 344 | CNumber ret = a.pow(b); 345 | RETURN_NAN_IS_NAN(ret); 346 | RETURN_INFINITY_IS_INFINITY(ret); 347 | RETURN(ret); 348 | /* 349 | RETURN_NAN_IS_NAN(b); 350 | if(b.isZero()) RETURN(1); 351 | RETURN_NAN_IS_NAN(a); 352 | if(b==1) RETURN(a); 353 | 354 | int sign; 355 | CNumber a_abs = abs(a); 356 | if((sign = b.isInfinity())) { 357 | if( a_abs==1 ) RETURNconst(NaN); 358 | else if( (a_abs>1) ^ (sign<0) ) RETURN(b); else RETURN(0); 359 | } else if((sign = a.isInfinity())) { 360 | if(sign>0) { 361 | if(b.sign()>0) RETURN(a); else RETURN(0); 362 | } else { 363 | bool b_is_odd_int = ((b+1)/2).isInteger(); 364 | if(b.sign()>0) RETURNconst(b_is_odd_int?InfinityNegative:InfinityPositive); 365 | else RETURN(b_is_odd_int?CNumber(NegativeZero):CNumber(0)); 366 | } 367 | } else if(a.isZero()) { 368 | if(a.isNegativeZero()) { 369 | bool b_is_odd_int = ((b+1)/2).isInteger(); 370 | if(b.sign()>0) RETURN(b_is_odd_int?CNumber(NegativeZero):CNumber(0)); 371 | else RETURNconst(b_is_odd_int?InfinityNegative:InfinityPositive); 372 | } else 373 | if(b.sign()>0) RETURN(a); else RETURNconst(InfinityPositive); 374 | } 375 | if(a.sign()<0 && !b.isInteger()) RETURNconst(NaN); 376 | 377 | RETURN( pow(a.toDouble(), b.toDouble()) ); 378 | */ 379 | } 380 | 381 | //Math.sqr(a) - returns square of given value 382 | static void scMathSqr(const CFunctionsScopePtr &c, void *userdata) { 383 | PARAMETER_TO_NUMBER(a,"a"); 384 | RETURN( a*a ); 385 | } 386 | 387 | //Math.sqrt(a) - returns square root of given value 388 | static void scMathSqrt(const CFunctionsScopePtr &c, void *userdata) { 389 | PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); 390 | RETURN_ZERO_IS_ZERO(a); 391 | if(a.sign()<0) RETURNconst(NaN); 392 | RETURN_INFINITY_IS_INFINITY(a); 393 | RETURN( sqrt(a.toDouble()) ); 394 | } 395 | 396 | // ----------------------------------------------- Register Functions 397 | extern "C" void _registerMathFunctions(CTinyJS *tinyJS) { 398 | 399 | CScriptVarPtr Math = tinyJS->getRoot()->addChild("Math", tinyJS->newScriptVar(Object), SCRIPTVARLINK_CONSTANT); 400 | 401 | // --- Math and Trigonometry functions --- 402 | tinyJS->addNative("function Math.abs(a)", scMathAbs, 0, SCRIPTVARLINK_BUILDINDEFAULT); 403 | tinyJS->addNative("function Math.round(a)", scMathRound, 0, SCRIPTVARLINK_BUILDINDEFAULT); 404 | tinyJS->addNative("function Math.ceil(a)", scMathCeil, 0, SCRIPTVARLINK_BUILDINDEFAULT); 405 | tinyJS->addNative("function Math.floor(a)", scMathFloor, 0, SCRIPTVARLINK_BUILDINDEFAULT); 406 | tinyJS->addNative("function Math.min()", scMathMin, 0, SCRIPTVARLINK_BUILDINDEFAULT); 407 | tinyJS->addNative("function Math.max()", scMathMax, 0, SCRIPTVARLINK_BUILDINDEFAULT); 408 | tinyJS->addNative("function Math.range(x,a,b)", scMathRange, 0, SCRIPTVARLINK_BUILDINDEFAULT); 409 | tinyJS->addNative("function Math.sign(a)", scMathSign, 0, SCRIPTVARLINK_BUILDINDEFAULT); 410 | tinyJS->addNative("function Math.random(a)", scMathRandom, 0, SCRIPTVARLINK_BUILDINDEFAULT); 411 | 412 | 413 | // atan2, ceil, floor, random, round, 414 | 415 | Math->addChild("LN2", tinyJS->newScriptVar(k_LN2), SCRIPTVARLINK_CONSTANT); 416 | Math->addChild("LN10", tinyJS->newScriptVar(k_LN10), SCRIPTVARLINK_CONSTANT); 417 | Math->addChild("LOG2E", tinyJS->newScriptVar(k_LOG2E), SCRIPTVARLINK_CONSTANT); 418 | Math->addChild("LOG10E", tinyJS->newScriptVar(k_LOG10E), SCRIPTVARLINK_CONSTANT); 419 | Math->addChild("SQRT1_2", tinyJS->newScriptVar(k_SQRT1_2), SCRIPTVARLINK_CONSTANT); 420 | Math->addChild("SQRT2", tinyJS->newScriptVar(k_SQRT2), SCRIPTVARLINK_CONSTANT); 421 | Math->addChild("PI", tinyJS->newScriptVar(k_PI), SCRIPTVARLINK_CONSTANT); 422 | tinyJS->addNative("function Math.toDegrees(a)", scMathToDegrees, 0, SCRIPTVARLINK_BUILDINDEFAULT); 423 | tinyJS->addNative("function Math.toRadians(a)", scMathToRadians, 0, SCRIPTVARLINK_BUILDINDEFAULT); 424 | tinyJS->addNative("function Math.sin(a)", scMathSin, 0, SCRIPTVARLINK_BUILDINDEFAULT); 425 | tinyJS->addNative("function Math.asin(a)", scMathASin, 0, SCRIPTVARLINK_BUILDINDEFAULT); 426 | tinyJS->addNative("function Math.cos(a)", scMathCos, 0, SCRIPTVARLINK_BUILDINDEFAULT); 427 | tinyJS->addNative("function Math.acos(a)", scMathACos, 0, SCRIPTVARLINK_BUILDINDEFAULT); 428 | tinyJS->addNative("function Math.tan(a)", scMathTan, 0, SCRIPTVARLINK_BUILDINDEFAULT); 429 | tinyJS->addNative("function Math.atan(a)", scMathATan, 0, SCRIPTVARLINK_BUILDINDEFAULT); 430 | tinyJS->addNative("function Math.atan2(a,b)", scMathATan2, 0, SCRIPTVARLINK_BUILDINDEFAULT); 431 | tinyJS->addNative("function Math.sinh(a)", scMathSinh, 0, SCRIPTVARLINK_BUILDINDEFAULT); 432 | tinyJS->addNative("function Math.asinh(a)", scMathASinh, 0, SCRIPTVARLINK_BUILDINDEFAULT); 433 | tinyJS->addNative("function Math.cosh(a)", scMathCosh, 0, SCRIPTVARLINK_BUILDINDEFAULT); 434 | tinyJS->addNative("function Math.acosh(a)", scMathACosh, 0, SCRIPTVARLINK_BUILDINDEFAULT); 435 | tinyJS->addNative("function Math.tanh(a)", scMathTanh, 0, SCRIPTVARLINK_BUILDINDEFAULT); 436 | tinyJS->addNative("function Math.atanh(a)", scMathATanh, 0, SCRIPTVARLINK_BUILDINDEFAULT); 437 | 438 | Math->addChild("E", tinyJS->newScriptVar(k_E), SCRIPTVARLINK_READONLY); 439 | tinyJS->addNative("function Math.log(a)", scMathLog, 0, SCRIPTVARLINK_BUILDINDEFAULT); 440 | tinyJS->addNative("function Math.log10(a)", scMathLog10, 0, SCRIPTVARLINK_BUILDINDEFAULT); 441 | tinyJS->addNative("function Math.exp(a)", scMathExp, 0, SCRIPTVARLINK_BUILDINDEFAULT); 442 | tinyJS->addNative("function Math.pow(a,b)", scMathPow, 0, SCRIPTVARLINK_BUILDINDEFAULT); 443 | 444 | tinyJS->addNative("function Math.sqr(a)", scMathSqr, 0, SCRIPTVARLINK_BUILDINDEFAULT); 445 | tinyJS->addNative("function Math.sqrt(a)", scMathSqrt, 0, SCRIPTVARLINK_BUILDINDEFAULT); 446 | 447 | } 448 | 449 | } /* namespace TinyJS */ -------------------------------------------------------------------------------- /TinyJS_PoolAllocator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 42TinyJS 3 | * 4 | * A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine 5 | * 6 | * Authored By Armin Diedering 7 | * 8 | * Copyright (C) 2010-2025 ardisoft 9 | * 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 12 | * this software and associated documentation files (the "Software"), to deal in 13 | * the Software without restriction, including without limitation the rights to 14 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 15 | * of the Software, and to permit persons to whom the Software is furnished to do 16 | * so, subject to the following conditions: 17 | 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #include "TinyJS_PoolAllocator.h" 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #ifndef ASSERT 39 | # define ASSERT(X) assert(X) 40 | #endif 41 | 42 | namespace TinyJS { 43 | 44 | namespace { 45 | 46 | struct block { 47 | block *next; 48 | }; 49 | struct block_head { 50 | block_head *next; 51 | }; 52 | 53 | 54 | class _fixed_size_allocator { 55 | public: 56 | _fixed_size_allocator(size_t numObjects, size_t objectSize) : 57 | num_objects(numObjects), object_size(objectSize >= sizeof(block) ? objectSize : sizeof(block)), block_size(sizeof(block_head) + object_size * num_objects), 58 | head(0), head_of_free_list(0), refs(0) {} 59 | 60 | ~_fixed_size_allocator() { 61 | while (head) { 62 | char *p = (char *)head; 63 | head = head->next; 64 | delete[] p; 65 | } 66 | } 67 | 68 | void *_alloc() { 69 | ++refs; 70 | block *p = head_of_free_list; 71 | if (p == 0) { 72 | char *new_block = new char[block_size]; 73 | ((block_head *)new_block)->next = head; 74 | head = (block_head *)new_block; 75 | 76 | p = (block *)(new_block + sizeof(block_head)); 77 | block *end = (block *)(new_block + block_size); 78 | block *last = p; 79 | for (block *it = (block *)(((char *)p) + object_size); it < end; last = it, it = (block *)(((char *)it) + object_size)) 80 | last->next = it; 81 | last->next = 0; 82 | } 83 | head_of_free_list = p->next; 84 | return p; 85 | } 86 | 87 | bool _free(void *p) { 88 | if (p == 0) return refs == 0; 89 | --refs; 90 | block *dead_object = (block *)p; 91 | dead_object->next = head_of_free_list; 92 | head_of_free_list = dead_object; 93 | return refs == 0; 94 | } 95 | 96 | size_t num_objects; 97 | size_t object_size; 98 | size_t block_size; 99 | block_head *head; 100 | block *head_of_free_list; 101 | int refs; 102 | }; 103 | 104 | 105 | #ifdef NO_THREADING 106 | # define LOCK do{}while(0) 107 | #elif SPINLOCK_IN_POOL_ALLOCATOR 108 | static CScriptSpinLock locker; 109 | # define LOCK CScriptUniqueLock lock(locker) 110 | #else 111 | static CScriptMutex locker; 112 | # define LOCK CScriptUniqueLock lock(locker) 113 | #endif 114 | 115 | static inline constexpr unsigned ilog2(unsigned v) noexcept { 116 | unsigned n = 0; 117 | while (v >>= 1) // shift until zero 118 | ++n; 119 | return n; 120 | } 121 | static inline constexpr std::size_t ROUND_SIZE(std::size_t size) noexcept { 122 | constexpr std::size_t A = __STDCPP_DEFAULT_NEW_ALIGNMENT__; 123 | static_assert((A & (A - 1)) == 0, "Alignment must be a power-of-two"); 124 | return (size + (A - 1)) & ~(A - 1); 125 | } 126 | 127 | static inline constexpr std::size_t SHIFT_SIZE(std::size_t size) noexcept { 128 | constexpr std::size_t shift = ilog2(__STDCPP_DEFAULT_NEW_ALIGNMENT__); 129 | return size >> shift; 130 | } 131 | static struct _fixed_size_allocator_init_control { 132 | _fixed_size_allocator_init_control() { 133 | pool.reserve(SHIFT_SIZE(256/*SmallObjectAllocator::MaxObjectSize*/) + 1); 134 | } 135 | ~_fixed_size_allocator_init_control() { 136 | for (auto it : pool) 137 | if (it) delete it; 138 | } 139 | _fixed_size_allocator *&getFromPool(size_t size) { 140 | size = SHIFT_SIZE(size); 141 | if (size >= pool.size()) 142 | pool.resize(size + 1, nullptr); 143 | return pool[size]; 144 | } 145 | std::vector<_fixed_size_allocator *> pool; 146 | 147 | } control; 148 | } /* namespace */ 149 | 150 | void *fixed_size_allocator::alloc(size_t size) { 151 | LOCK; 152 | size = ROUND_SIZE(size); 153 | _fixed_size_allocator *&allocator = control.getFromPool(size); 154 | if (!allocator) { 155 | allocator = new _fixed_size_allocator(64, size); 156 | } 157 | return allocator->_alloc(); 158 | } 159 | 160 | void fixed_size_allocator::free(void *p, size_t size) { 161 | LOCK; 162 | size = ROUND_SIZE(size); 163 | _fixed_size_allocator *&allocator = control.getFromPool(size); 164 | if (allocator) { 165 | if (allocator->_free(p)) { 166 | delete allocator; 167 | allocator = 0; 168 | } 169 | } else { 170 | ASSERT(0/* free called but not allocator defined*/); 171 | } 172 | } 173 | 174 | } -------------------------------------------------------------------------------- /TinyJS_PoolAllocator.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ardi69/42tiny-js/a31979449f329f0314f120ad6abb95b57c933ca4/TinyJS_PoolAllocator.h -------------------------------------------------------------------------------- /TinyJS_Threading.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 42TinyJS 3 | * 4 | * A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine 5 | * 6 | * Authored By Armin Diedering 7 | * 8 | * Copyright (C) 2010-2025 ardisoft 9 | * 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 12 | * this software and associated documentation files (the "Software"), to deal in 13 | * the Software without restriction, including without limitation the rights to 14 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 15 | * of the Software, and to permit persons to whom the Software is furnished to do 16 | * so, subject to the following conditions: 17 | 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | #include "TinyJS_Threading.h" 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #undef HAVE_THREADING 37 | #if !defined(NO_THREADING) && !defined(HAVE_CUSTOM_THREADING_IMPL) 38 | # define HAVE_THREADING 39 | # ifdef HAVE_CXX_THREADS 40 | # include 41 | # else 42 | # if defined(_WIN32) && !defined(HAVE_PTHREAD) 43 | # include 44 | # include 45 | # else 46 | # include 47 | # ifndef HAVE_PTHREAD 48 | # define HAVE_PTHREAD 49 | # endif 50 | # endif 51 | # endif 52 | #endif 53 | 54 | #ifdef HAVE_THREADING 55 | 56 | ////////////////////////////////////////////////////////////////////////// 57 | // Mutex 58 | ////////////////////////////////////////////////////////////////////////// 59 | #ifndef HAVE_CXX_THREADS 60 | 61 | #ifndef HAVE_PTHREAD 62 | // simple mutex 4 windows 63 | # define pthread_mutex_t CRITICAL_SECTION 64 | # define pthread_mutex_init(m, a) (InitializeCriticalSection(m), 0) 65 | # define pthread_mutex_destroy(m) do {} while(0) 66 | # define pthread_mutex_lock(m) EnterCriticalSection(m) 67 | # define pthread_mutex_unlock(m) LeaveCriticalSection(m) 68 | 69 | #endif 70 | CScriptMutex::CScriptMutex_t::~CScriptMutex_t() {} 71 | 72 | class CScriptMutex_impl : public CScriptMutex::CScriptMutex_t { 73 | public: 74 | CScriptMutex_impl() { 75 | pthread_mutex_init(&mutex, NULL); 76 | } 77 | virtual ~CScriptMutex_impl() { 78 | pthread_mutex_destroy(&mutex); 79 | } 80 | virtual void lock() { 81 | pthread_mutex_lock(&mutex); 82 | } 83 | virtual void unlock() { 84 | pthread_mutex_unlock(&mutex); 85 | } 86 | void *getRealMutex() { return &mutex; } 87 | pthread_mutex_t mutex; 88 | }; 89 | 90 | 91 | CScriptMutex::CScriptMutex() { 92 | mutex = new CScriptMutex_impl; 93 | } 94 | 95 | CScriptMutex::~CScriptMutex() { 96 | delete mutex; 97 | } 98 | 99 | #endif /* !HAVE_CXX_THREADS */ 100 | 101 | ////////////////////////////////////////////////////////////////////////// 102 | // CondVar 103 | ////////////////////////////////////////////////////////////////////////// 104 | 105 | #ifndef HAVE_CXX_THREADS 106 | 107 | #ifndef HAVE_PTHREAD 108 | // simple conditional Variable 4 windows 109 | 110 | class condition_variable_impl 111 | { 112 | public: 113 | condition_variable_impl() : mNumWaiters(0), mSemaphore(CreateEvent(NULL, FALSE, FALSE, NULL)), mWakeEvent(CreateEvent(NULL, FALSE, FALSE, NULL)) {} 114 | ~condition_variable_impl() { CloseHandle(mSemaphore); CloseHandle(mWakeEvent); } 115 | void wait(pthread_mutex_t *lock) { 116 | { 117 | CScriptUniqueLock quard(mMutex); 118 | mNumWaiters++; 119 | } 120 | pthread_mutex_unlock(lock); 121 | WaitForSingleObject(mSemaphore, INFINITE); 122 | mNumWaiters--; 123 | SetEvent(mWakeEvent); 124 | pthread_mutex_lock(lock); 125 | } 126 | int wait_until(pthread_mutex_t *lock, timespec *ts) { 127 | { 128 | CScriptUniqueLock quard(mMutex); 129 | mNumWaiters++; 130 | } 131 | auto rel_time = std::chrono::steady_clock::time_point(std::chrono::seconds(ts->tv_sec) + std::chrono::nanoseconds(ts->tv_nsec)) - std::chrono::steady_clock::now(); 132 | if (rel_time.count() <= 0) return ETIMEDOUT; 133 | pthread_mutex_unlock(lock); 134 | auto ret = WaitForSingleObject(mSemaphore, std::chrono::duration_cast>(rel_time).count()); 135 | mNumWaiters--; 136 | SetEvent(mWakeEvent); 137 | pthread_mutex_lock(lock); 138 | return ret == WAIT_TIMEOUT ? ETIMEDOUT : 0; 139 | } 140 | void notify_one() 141 | { 142 | CScriptUniqueLock quard(mMutex); 143 | if (!mNumWaiters) return; 144 | SetEvent(mSemaphore); 145 | WaitForSingleObject(mWakeEvent, INFINITE); 146 | } 147 | void notify_all() { 148 | while (mNumWaiters) notify_one(); 149 | } 150 | private: 151 | CScriptMutex mMutex; 152 | std::atomic mNumWaiters; 153 | HANDLE mSemaphore; 154 | HANDLE mWakeEvent; 155 | }; 156 | 157 | 158 | # define pthread_condattr_t struct {} 159 | # define pthread_condattr_init(a) do { (void*)(a); } while(0) 160 | # define pthread_condattr_destroy(a) do {} while(0) 161 | # define CLOCK_MONOTONIC 1 162 | # define pthread_condattr_setclock(a, c) do {} while(0) 163 | # define pthread_cond_t condition_variable_impl 164 | # define pthread_cond_init(c, a) do {} while(0) 165 | # define pthread_cond_destroy(c) do {} while(0) 166 | # define pthread_cond_wait(c, m) (c)->wait(m) 167 | # define pthread_cond_timedwait(c, m, t) (c)->wait_until(m, t) 168 | # define pthread_cond_signal(c) (c)->notify_one() 169 | # define pthread_cond_broadcast(c) (c)->notify_all() 170 | #endif 171 | 172 | class CScriptCondVar_impl : public CScriptCondVar::CScriptCondVar_t { 173 | public: 174 | CScriptCondVar_impl(CScriptCondVar *_this) : This(_this) { 175 | pthread_condattr_t attr; 176 | pthread_condattr_init(&attr); 177 | pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); 178 | pthread_cond_init(&cond, &attr); 179 | pthread_condattr_destroy(&attr); 180 | } 181 | virtual ~CScriptCondVar_impl() { 182 | pthread_cond_destroy(&cond); 183 | } 184 | CScriptCondVar *This; 185 | virtual void notify_one() override { 186 | pthread_cond_signal(&cond); 187 | } 188 | virtual void notify_all() override { 189 | pthread_cond_broadcast(&cond); 190 | } 191 | virtual void wait(CScriptUniqueLock &lock) override { 192 | pthread_cond_wait(&cond, (pthread_mutex_t *)lock.mutex.getRealMutex()); 193 | } 194 | virtual int wait_for(CScriptUniqueLock &lock, std::chrono::duration rel_time) override { 195 | return wait_until(lock, std::chrono::steady_clock::now() + rel_time); 196 | } 197 | virtual int wait_until(CScriptUniqueLock &lock, std::chrono::steady_clock::time_point abs_time) override { 198 | struct timespec ts; 199 | auto duration = abs_time.time_since_epoch(); 200 | ts.tv_sec = std::chrono::duration_cast(duration).count(); 201 | ts.tv_nsec = std::chrono::duration_cast>(duration % std::chrono::seconds(1)).count(); 202 | return pthread_cond_timedwait(&cond, (pthread_mutex_t *)lock.mutex.getRealMutex(), &ts) == ETIMEDOUT ? 1 : 0; 203 | } 204 | virtual int wait_until(CScriptUniqueLock &lock, std::chrono::system_clock::time_point abs_time) override { 205 | return wait_for(lock, std::chrono::duration_cast>(abs_time - std::chrono::system_clock::now())); 206 | } 207 | pthread_cond_t cond; 208 | }; 209 | 210 | CScriptCondVar::CScriptCondVar_t::~CScriptCondVar_t() {} 211 | CScriptCondVar::CScriptCondVar() { 212 | condVar = new CScriptCondVar_impl(this); 213 | } 214 | CScriptCondVar::~CScriptCondVar() { 215 | delete condVar; 216 | } 217 | 218 | #endif /*HAVE_CXX_THREADS*/ 219 | 220 | 221 | 222 | ////////////////////////////////////////////////////////////////////////// 223 | // Threading 224 | ////////////////////////////////////////////////////////////////////////// 225 | 226 | 227 | #ifdef HAVE_CXX_THREADS 228 | # define pthread_attr_t int 229 | # define pthread_attr_init(a) do {} while(0) 230 | # define pthread_attr_destroy(a) do {} while(0) 231 | # define pthread_t std::thread 232 | # define pthread_create(t, attr, fnc, a) *(t) = std::thread(fnc, a); 233 | # define pthread_join(t, v) t.join(); 234 | # define sched_yield std::this_thread::yield 235 | #elif !defined(HAVE_PTHREAD) 236 | // simple pthreads 4 windows 237 | # define pthread_attr_t SIZE_T 238 | # define pthread_attr_init(attr) (*attr=0) 239 | # define pthread_attr_destroy(a) do {} while(0) 240 | # define pthread_attr_setstacksize(attr, stack) *attr=stack; 241 | 242 | # define pthread_t HANDLE 243 | # define pthread_create(t, attr, fnc, a) *(t) = CreateThread(NULL, attr ? *((pthread_attr_t*)attr) : 0, (LPTHREAD_START_ROUTINE)fnc, a, 0, NULL) 244 | # define pthread_join(t, v) WaitForSingleObject(t, INFINITE), GetExitCodeThread(t,(LPDWORD)v), CloseHandle(t) 245 | # define sched_yield() Sleep(0) 246 | #endif 247 | 248 | class CScriptThread_impl : public CScriptThread::CScriptThread_t { 249 | public: 250 | CScriptThread_impl(CScriptThread *_this) : retvar((void*)-1), activ(false), running(false), started(false), This(_this) { 251 | 252 | } 253 | virtual ~CScriptThread_impl() { 254 | 255 | } 256 | virtual int Run(uint32_t timeout_ms) override { 257 | if(started) return 0; 258 | activ = true; 259 | // pthread_attr_t attribute; 260 | // pthread_attr_init(&attribute); 261 | // pthread_attr_setstacksize(&attribute,1024); 262 | pthread_create(&thread, NULL /*&attribute*/, (void*(*)(void*))ThreadFnc, this); 263 | // pthread_attr_destroy(&attribute); 264 | auto endtime = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeout_ms); 265 | while (!started) { 266 | sched_yield(); 267 | if (endtime < std::chrono::steady_clock::now()) return 1; 268 | } 269 | return 0; 270 | } 271 | virtual int Stop(bool Wait) override { 272 | activ = false; 273 | if (Wait && started) { 274 | if (!joined) { 275 | pthread_join(thread, &retvar); 276 | joined = true; 277 | } 278 | return retValue(); 279 | } 280 | return -1; 281 | } 282 | virtual int retValue() override { return (int)((ptrdiff_t)retvar); } 283 | virtual bool isActiv() override { return activ; } 284 | virtual bool isRunning() override { return running; } 285 | virtual bool isStarted() override { return started; } 286 | static void *ThreadFnc(CScriptThread_impl *This) { 287 | This->running = This->started = true; 288 | This->retvar = (void*)((ptrdiff_t)This->This->ThreadFnc()); 289 | This->running = false; 290 | This->This->ThreadFncFinished(); 291 | return This->retvar; 292 | } 293 | void *retvar; 294 | std::atomic activ; 295 | std::atomic running; 296 | std::atomic started; 297 | bool joined = false; 298 | CScriptThread *This; 299 | pthread_t thread; 300 | }; 301 | 302 | CScriptThread::CScriptThread() { 303 | thread = new CScriptThread_impl(this); 304 | } 305 | CScriptThread::~CScriptThread() { 306 | delete thread; 307 | } 308 | void CScriptThread::ThreadFncFinished() {} 309 | 310 | void CScriptThread::yield() { 311 | sched_yield(); 312 | } 313 | 314 | CScriptCoroutine::StopIteration_t CScriptCoroutine::StopIteration; 315 | 316 | bool CScriptCoroutine::next() 317 | { 318 | CScriptUniqueLock lock(mutex); 319 | if(!isStarted()) { 320 | Run(); 321 | if(mainNotifies-- == 0) mainCondVar.wait(lock); 322 | } else if(isRunning()) { 323 | ++coroutineNotifies; 324 | coroutineCondVar.notify_one(); 325 | if(mainNotifies-- == 0) mainCondVar.wait(lock); 326 | } else 327 | return false; 328 | if(!isRunning()) return false; 329 | return true; 330 | } 331 | bool CScriptCoroutine::yield_no_throw() { 332 | CScriptUniqueLock lock(mutex); 333 | ++mainNotifies; 334 | mainCondVar.notify_one(); 335 | if(coroutineNotifies-- == 0) coroutineCondVar.wait(lock); 336 | return isActiv(); 337 | } 338 | 339 | int CScriptCoroutine::ThreadFnc() { 340 | int ret=-1; 341 | try { 342 | ret = Coroutine(); 343 | } catch(StopIteration_t &) { 344 | return 0; 345 | } catch(std::exception & e) { 346 | printf("CScriptCoroutine has received an uncaught exception: %s\n", e.what()); 347 | return -1; 348 | } catch(...) { 349 | printf("CScriptCoroutine has received an uncaught and unknown exception\n"); 350 | return -1; 351 | } 352 | return ret; 353 | } 354 | void CScriptCoroutine::ThreadFncFinished() { 355 | ++mainNotifies; 356 | mainCondVar.notify_one(); 357 | } 358 | 359 | 360 | #endif // HAVE_THREADING 361 | 362 | -------------------------------------------------------------------------------- /TinyJS_Threading.h: -------------------------------------------------------------------------------- 1 | #ifndef TinyJS_Threading_h__ 2 | #define TinyJS_Threading_h__ 3 | #include "config.h" 4 | #ifndef NO_THREADING 5 | /* 6 | * 42TinyJS 7 | * 8 | * A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine 9 | * 10 | * Authored By Armin Diedering 11 | * 12 | * Copyright (C) 2010-2025 ardisoft 13 | * 14 | * 15 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 16 | * this software and associated documentation files (the "Software"), to deal in 17 | * the Software without restriction, including without limitation the rights to 18 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 19 | * of the Software, and to permit persons to whom the Software is furnished to do 20 | * so, subject to the following conditions: 21 | 22 | * The above copyright notice and this permission notice shall be included in all 23 | * copies or substantial portions of the Software. 24 | 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | * SOFTWARE. 32 | */ 33 | 34 | #ifdef HAVE_CXX_THREADS 35 | 36 | # include 37 | # include 38 | typedef std::mutex CScriptMutex; 39 | #define CScriptUniqueLock std::unique_lock 40 | typedef std::condition_variable CScriptCondVar; 41 | 42 | #else 43 | 44 | # include 45 | 46 | class CScriptMutex { 47 | public: 48 | CScriptMutex(); 49 | ~CScriptMutex(); 50 | void lock() { mutex->lock(); } 51 | void unlock() { mutex->unlock(); } 52 | void *getRealMutex() { return mutex->getRealMutex(); } 53 | class CScriptMutex_t{ 54 | public: 55 | virtual ~CScriptMutex_t(); 56 | virtual void lock()=0; 57 | virtual void unlock()=0; 58 | virtual void *getRealMutex()=0; 59 | }; 60 | private: 61 | CScriptMutex_t *mutex; 62 | 63 | }; 64 | 65 | template 66 | class CScriptUniqueLock { 67 | public: 68 | CScriptUniqueLock(LockClass &Mutex) : mutex(Mutex) { mutex.lock(); } 69 | ~CScriptUniqueLock() { mutex.unlock(); } 70 | LockClass &mutex; 71 | }; 72 | 73 | class CScriptCondVar { 74 | public: 75 | CScriptCondVar(); 76 | ~CScriptCondVar(); 77 | void notify_one() { condVar->notify_one(); } 78 | void notify_all() { condVar->notify_all(); } 79 | void wait(CScriptUniqueLock &Lock) { condVar->wait(Lock); } 80 | class CScriptCondVar_t { 81 | public: 82 | virtual ~CScriptCondVar_t(); 83 | virtual void notify_one() = 0; 84 | virtual void notify_all() = 0; 85 | virtual void wait(CScriptUniqueLock &lock) = 0; 86 | virtual int wait_for(CScriptUniqueLock &lock, std::chrono::duration rel_time) = 0; 87 | virtual int wait_until(CScriptUniqueLock &lock, std::chrono::system_clock::time_point abs_time) = 0; 88 | virtual int wait_until(CScriptUniqueLock &lock, std::chrono::steady_clock::time_point abs_time) = 0; 89 | }; 90 | private: 91 | CScriptCondVar_t *condVar; 92 | }; 93 | 94 | #endif /*HAVE_CXX_THREADS*/ 95 | 96 | class CScriptThread { 97 | public: 98 | CScriptThread(); 99 | virtual ~CScriptThread(); 100 | static void yield(); 101 | int Run(uint32_t timeout_ms = 800) { return thread->Run(timeout_ms); } 102 | int Stop(bool Wait=true) { return thread->Stop(Wait); } 103 | int retValue() { return thread->retValue(); } 104 | virtual int ThreadFnc()=0; 105 | virtual void ThreadFncFinished(); 106 | bool isActiv() { return thread->isActiv(); } 107 | bool isRunning() { return thread->isRunning(); } 108 | bool isStarted() { return thread->isStarted(); } 109 | class CScriptThread_t{ 110 | public: 111 | virtual ~CScriptThread_t(){} 112 | virtual int Run(uint32_t timeout_ms)=0; 113 | virtual int Stop(bool Wait)=0; 114 | virtual bool isActiv()=0; 115 | virtual bool isRunning()=0; 116 | virtual bool isStarted()=0; 117 | virtual int retValue()=0; 118 | }; 119 | private: 120 | CScriptThread_t *thread; 121 | }; 122 | 123 | #include 124 | class CScriptCoroutine : protected CScriptThread { 125 | public: 126 | CScriptCoroutine() : mainNotifies(0), coroutineNotifies(0) {} 127 | typedef struct{} StopIteration_t; 128 | static StopIteration_t StopIteration; 129 | bool next(); // returns true if coroutine is running 130 | protected: 131 | virtual int Coroutine()=0; 132 | void yield() { if(!yield_no_throw()) throw StopIteration; } 133 | bool yield_no_throw(); 134 | private: 135 | virtual int ThreadFnc(); 136 | virtual void ThreadFncFinished(); 137 | //void notify_and_wait(CScriptCondVar ¬ifyCondVar, CScriptCondVar &waitCondVar, bool &waitFlag); 138 | CScriptMutex mutex; 139 | CScriptCondVar mainCondVar, coroutineCondVar; 140 | std::atomic mainNotifies, coroutineNotifies; 141 | }; 142 | 143 | class CScriptSpinLock { 144 | public: 145 | CScriptSpinLock() { flag.clear(std::memory_order_release); } 146 | void lock() { while (flag.test_and_set(std::memory_order_acquire)) { CScriptThread::yield(); } } 147 | void unlock() { flag.clear(std::memory_order_release); } 148 | private: 149 | std::atomic_flag flag; 150 | }; 151 | 152 | #endif // NO_THREADING 153 | #endif // TinyJS_Threading_h__ 154 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | #ifndef _42TinyJS_config_h__ 2 | #define _42TinyJS_config_h__ 3 | 4 | /* 5 | * 42TinyJS 6 | * 7 | * A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine 8 | * 9 | * Authored By Armin Diedering 10 | * 11 | * Copyright (C) 2010-2025 ardisoft 12 | * 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 15 | * this software and associated documentation files (the "Software"), to deal in 16 | * the Software without restriction, including without limitation the rights to 17 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 18 | * of the Software, and to permit persons to whom the Software is furnished to do 19 | * so, subject to the following conditions: 20 | 21 | * The above copyright notice and this permission notice shall be included in all 22 | * copies or substantial portions of the Software. 23 | 24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | * SOFTWARE. 31 | */ 32 | 33 | ////////////////////////////////////////////////////////////////////////// 34 | 35 | /* POOL-ALLOCATOR 36 | * ============== 37 | * To speed-up new & delete 42TinyJS adds an object-pool 38 | * The pool is activated by default. 39 | * To deactivate this stuff define NO_POOL_ALLOCATOR 40 | */ 41 | //#define NO_POOL_ALLOCATOR 42 | 43 | /* 44 | * to increasing of speed a spin lock is used, if available 45 | * if c++11 not available or NO_SPINLOCK_IN_POOL_ALLOCATOR is defined 46 | * a normal mutex lock is used or noting if NO_THREADING defined 47 | */ 48 | //#define NO_SPINLOCK_IN_POOL_ALLOCATOR 49 | 50 | ////////////////////////////////////////////////////////////////////////// 51 | 52 | /* LET-STUFF 53 | * ========= 54 | * Redeclaration of LET-vars is not allowed in block-scopes. 55 | * But in the root- and functions-scopes it is currently allowed 56 | * In future ECMAScript versions this will be also in root-and functions-scopes forbidden 57 | * To enable the future behavior define PREVENT_REDECLARATION_IN_FUNCTION_SCOPES 58 | */ 59 | //#define PREVENT_REDECLARATION_IN_FUNCTION_SCOPES 60 | 61 | ////////////////////////////////////////////////////////////////////////// 62 | 63 | /* GENERATOR's 64 | * =========== 65 | * functions with "yield" in it is detected as Generator. 66 | * Generator-support needs threading-stuff 67 | * To disable Generators define NO_GENERATORS 68 | * NOTE NO_THREADING implies NO_GENERATORS 69 | */ 70 | //#define NO_GENERATORS 71 | 72 | 73 | ////////////////////////////////////////////////////////////////////////// 74 | 75 | /* MULTI-THREADING 76 | * =============== 77 | * 42TinyJS is basically thread-save. 78 | * You can run different or the same JS-code simultaneously in different instances of class TinyJS. 79 | * >>> NOTE: You can NOT run more threads on the SAME instance of class TinyJS <<< 80 | * The threading-stuff is needed by the pool-allocator (locking) and the generator-/yield-stuff 81 | * to deactivate threading define NO_THREADING 82 | * NOTE: if NO_THREADING defined and NO_POOL_ALLOCATOR is undefined you can not run JS-code simultaneously 83 | */ 84 | //#define NO_THREADING 85 | 86 | /* with C++2011 (or MS VisualC++ 2012 and above) the C++ 2011 STL-Threading-API is used. 87 | * You can define NO_CXX_THREADS to use alternate API's 88 | */ 89 | //#define NO_CXX_THREADS 90 | 91 | /* if C++ 2011 STL-Threading-API not available 92 | * - on Windows the windows-threading-API is used by default. 93 | * - on non-Windows (WIN32 is not defined) it is tried to use the POSIX pthread-API 94 | * to force the pthread-API define HAVE_PTHREAD (windows needs in this case 95 | * a pthread-lib e.g http://http://sourceware.org/pthreads-win32/) 96 | */ 97 | //#define HAVE_PTHREAD 98 | 99 | /* you can implement your own custom thread-implementation. 100 | * to prevent the using of the win- or pthread-API define HAVE_CUSTOM_THREADING_IMPL 101 | */ 102 | //#define HAVE_CUSTOM_THREADING_IMPL 103 | 104 | //////////////////////////////////////////////// 105 | // DO NOT MAKE CHANGES OF THE FOLLOWING STUFF // 106 | //////////////////////////////////////////////// 107 | 108 | #if defined(NO_THREADING) && !defined(NO_GENERATORS) 109 | # define NO_GENERATORS 110 | #pragma message("\n***********************************************************************\n\ 111 | * You have defined NO_THREADING and not defined NO_GENERATORS\n\ 112 | * NOTE: GENERATORS needs THREADING. Generators/Yield are deactivated\n\ 113 | ***********************************************************************\n") 114 | #endif 115 | 116 | #if defined(NO_POOL_ALLOCATOR) && defined(NO_GENERATORS) && !defined(NO_THREADING) 117 | # define NO_THREADING 118 | #endif 119 | 120 | #if !defined(NO_POOL_ALLOCATOR) && defined(NO_THREADING) 121 | #pragma message("\n***********************************************************************\n\ 122 | * You have defined NO_THREADING and not defined NO_POOL_ALLOCATOR\n\ 123 | * NOTE: you can not run JS-code simultaneously in different threads\n\ 124 | ***********************************************************************\n") 125 | #endif 126 | 127 | #define isCXX0x(version, minor) (defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ > version || __GNUC__ == version && __GNUC_MINOR__ >= minor)) 128 | 129 | #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || _MSC_VER >= 1700 // Visual Studio 2012 and above 130 | # if !defined(NO_CXX_THREADS) && !defined(NO_THREADING) 131 | # define HAVE_CXX_THREADS 1 132 | # endif 133 | #endif 134 | 135 | #if !defined(NO_SPINLOCK_IN_POOL_ALLOCATOR) && (__cplusplus >= 201103L || isCXX0x(4,5) || _MSC_VER >= 1700 /* Visual Studio 2012 */) 136 | # define SPINLOCK_IN_POOL_ALLOCATOR 1 137 | #endif 138 | 139 | //#undef HAVE_CXX_THREADS 140 | 141 | #endif // _42TinyJS_config_h__ 142 | -------------------------------------------------------------------------------- /lib-tiny-js.2017.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {9751C465-0294-43CD-A5D9-BD038ABA3961} 23 | lib-tiny-js 24 | lib-tiny-js 25 | 10.0.22621.0 26 | 27 | 28 | 29 | StaticLibrary 30 | false 31 | MultiByte 32 | true 33 | false 34 | v141 35 | 36 | 37 | StaticLibrary 38 | false 39 | MultiByte 40 | true 41 | false 42 | v141 43 | 44 | 45 | StaticLibrary 46 | false 47 | false 48 | MultiByte 49 | v141 50 | 51 | 52 | StaticLibrary 53 | false 54 | false 55 | MultiByte 56 | v141 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | <_ProjectFileVersion>10.0.30319.1 76 | $(SolutionDir)$(Configuration)\$(Platform)\ 77 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 78 | $(SolutionDir)$(Configuration)\$(Platform)\ 79 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 80 | 81 | 82 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 83 | $(SolutionDir)$(Configuration)\$(Platform)\ 84 | 85 | 86 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 87 | $(SolutionDir)$(Configuration)\$(Platform)\ 88 | 89 | 90 | false 91 | 92 | 93 | 94 | Disabled 95 | WIN32;_DEBUG;%(PreprocessorDefinitions) 96 | true 97 | EnableFastChecks 98 | MultiThreadedDebugDLL 99 | Level3 100 | EditAndContinue 101 | stdcpp17 102 | 103 | 104 | 105 | 106 | Disabled 107 | WIN32;_DEBUG;%(PreprocessorDefinitions) 108 | EnableFastChecks 109 | MultiThreadedDebugDLL 110 | Level3 111 | ProgramDatabase 112 | stdcpp17 113 | 114 | 115 | 116 | 117 | Full 118 | true 119 | WIN32;NDEBUG;%(PreprocessorDefinitions) 120 | MultiThreadedDLL 121 | true 122 | Level3 123 | ProgramDatabase 124 | false 125 | Speed 126 | stdcpp17 127 | 128 | 129 | 130 | 131 | Full 132 | true 133 | WIN32;NDEBUG;%(PreprocessorDefinitions) 134 | MultiThreadedDLL 135 | true 136 | Level3 137 | ProgramDatabase 138 | stdcpp17 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /lib-tiny-js.2017.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Quelldateien 20 | 21 | 22 | Quelldateien 23 | 24 | 25 | Quelldateien 26 | 27 | 28 | Quelldateien 29 | 30 | 31 | Quelldateien 32 | 33 | 34 | Quelldateien 35 | 36 | 37 | Quelldateien 38 | 39 | 40 | 41 | 42 | Headerdateien 43 | 44 | 45 | Headerdateien 46 | 47 | 48 | Headerdateien 49 | 50 | 51 | Headerdateien 52 | 53 | 54 | -------------------------------------------------------------------------------- /lib-tiny-js.2022.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {9751C465-0294-43CD-A5D9-BD038ABA3961} 23 | lib-tiny-js 24 | lib-tiny-js 25 | 10.0 26 | 27 | 28 | 29 | StaticLibrary 30 | false 31 | MultiByte 32 | true 33 | false 34 | v143 35 | 36 | 37 | StaticLibrary 38 | false 39 | MultiByte 40 | true 41 | false 42 | v143 43 | 44 | 45 | StaticLibrary 46 | false 47 | false 48 | MultiByte 49 | v143 50 | 51 | 52 | StaticLibrary 53 | false 54 | false 55 | MultiByte 56 | v143 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | <_ProjectFileVersion>10.0.30319.1 76 | $(SolutionDir)$(Configuration)\$(Platform)\ 77 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 78 | $(SolutionDir)$(Configuration)\$(Platform)\ 79 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 80 | 81 | 82 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 83 | $(SolutionDir)$(Configuration)\$(Platform)\ 84 | 85 | 86 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 87 | $(SolutionDir)$(Configuration)\$(Platform)\ 88 | 89 | 90 | false 91 | 92 | 93 | 94 | Disabled 95 | WIN32;_DEBUG;%(PreprocessorDefinitions) 96 | EnableFastChecks 97 | MultiThreadedDebugDLL 98 | Level3 99 | EditAndContinue 100 | stdcpp20 101 | 102 | 103 | 104 | 105 | Disabled 106 | WIN32;_DEBUG;%(PreprocessorDefinitions) 107 | EnableFastChecks 108 | MultiThreadedDebugDLL 109 | Level3 110 | EditAndContinue 111 | stdcpp20 112 | 113 | 114 | 115 | 116 | Full 117 | true 118 | WIN32;NDEBUG;%(PreprocessorDefinitions) 119 | MultiThreadedDLL 120 | true 121 | Level3 122 | ProgramDatabase 123 | false 124 | Speed 125 | stdcpp20 126 | 127 | 128 | 129 | 130 | Full 131 | true 132 | WIN32;NDEBUG;%(PreprocessorDefinitions) 133 | MultiThreadedDLL 134 | true 135 | Level3 136 | ProgramDatabase 137 | stdcpp20 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /lib-tiny-js.2022.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Quelldateien 20 | 21 | 22 | Quelldateien 23 | 24 | 25 | Quelldateien 26 | 27 | 28 | Quelldateien 29 | 30 | 31 | Quelldateien 32 | 33 | 34 | Quelldateien 35 | 36 | 37 | Quelldateien 38 | 39 | 40 | 41 | 42 | Headerdateien 43 | 44 | 45 | Headerdateien 46 | 47 | 48 | Headerdateien 49 | 50 | 51 | Headerdateien 52 | 53 | 54 | -------------------------------------------------------------------------------- /prebuild.tests.cpp: -------------------------------------------------------------------------------- 1 | 2 | #ifdef TEST_CXX11_THREAD 3 | #include 4 | void g(){} 5 | int main(){ 6 | { 7 | std::thread t(g); 8 | t.join(); 9 | } 10 | return 0; 11 | } 12 | #elif defined(TEST_PTHREAD) 13 | #include 14 | 15 | void *g(void *) { return 0; } 16 | int main() { 17 | pthread_t inc_x_thread; 18 | if (pthread_create(&inc_x_thread, 0, g, 0)) 19 | return 1; 20 | if (pthread_join(inc_x_thread, 0)) { 21 | return 1; 22 | } 23 | return 0; 24 | } 25 | #elif defined(TEST_CXX11_FILESYSTEM) 26 | #include 27 | 28 | int main() { 29 | if(std::filesystem::exists("test.txt")) 30 | do {} while(0); 31 | return 0; 32 | } 33 | #elif defined(TEST_CPP17) 34 | #if __cplusplus < 201703L 35 | #error C++17 not supported 36 | #endif 37 | int main() { 38 | return 0; 39 | } 40 | #elif defined(TEST_CPP20) 41 | #if __cplusplus < 202002L 42 | #error C++20 not supported 43 | #endif 44 | int main() { 45 | return 0; 46 | } 47 | #elif defined(TEST_CPP23) 48 | #if __cplusplus < 202302L 49 | #error C++23 not supported 50 | #endif 51 | int main() { 52 | return 0; 53 | } 54 | #else 55 | #error "no TEST specified" 56 | #endif 57 | 58 | -------------------------------------------------------------------------------- /run_tests.2017.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {C6C6CD82-1400-464C-9B80-E15450CFDD18} 23 | Win32Proj 24 | run_tests 25 | run_tests 26 | 10.0.22621.0 27 | 28 | 29 | 30 | Application 31 | true 32 | MultiByte 33 | false 34 | false 35 | v141 36 | 37 | 38 | Application 39 | true 40 | MultiByte 41 | false 42 | false 43 | v141 44 | 45 | 46 | Application 47 | false 48 | true 49 | MultiByte 50 | false 51 | false 52 | v141 53 | 54 | 55 | Application 56 | false 57 | true 58 | MultiByte 59 | false 60 | false 61 | v141 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | true 81 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 82 | $(SolutionDir)$(Configuration)\$(Platform)\ 83 | 84 | 85 | true 86 | $(SolutionDir)$(Configuration)\$(Platform)\ 87 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 88 | 89 | 90 | false 91 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 92 | $(SolutionDir)$(Configuration)\$(Platform)\ 93 | 94 | 95 | false 96 | $(SolutionDir)$(Configuration)\$(Platform)\ 97 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 98 | 99 | 100 | 101 | 102 | 103 | Level3 104 | Disabled 105 | WIN32;_DEBUG;_CONSOLE;WITH_TIME_LOGGER;%(PreprocessorDefinitions) 106 | stdcpp17 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | 116 | 117 | Level3 118 | Disabled 119 | WIN32;_DEBUG;_CONSOLE;WITH_TIME_LOGGER;%(PreprocessorDefinitions) 120 | stdcpp17 121 | 122 | 123 | Console 124 | true 125 | 126 | 127 | 128 | 129 | Level3 130 | 131 | 132 | MaxSpeed 133 | true 134 | true 135 | WIN32;NDEBUG;_CONSOLE;WITH_TIME_LOGGER;%(PreprocessorDefinitions) 136 | stdcpp17 137 | 138 | 139 | Console 140 | true 141 | true 142 | true 143 | 144 | 145 | 146 | 147 | Level3 148 | 149 | 150 | MaxSpeed 151 | true 152 | true 153 | WIN32;NDEBUG;_CONSOLE;WITH_TIME_LOGGER;%(PreprocessorDefinitions) 154 | stdcpp17 155 | 156 | 157 | Console 158 | true 159 | true 160 | true 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | {9751c465-0294-43cd-a5d9-bd038aba3961} 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /run_tests.2017.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Quelldateien 20 | 21 | 22 | 23 | 24 | Headerdateien 25 | 26 | 27 | -------------------------------------------------------------------------------- /run_tests.2022.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {C6C6CD82-1400-464C-9B80-E15450CFDD18} 23 | Win32Proj 24 | run_tests 25 | run_tests 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | MultiByte 33 | false 34 | false 35 | v143 36 | 37 | 38 | Application 39 | true 40 | MultiByte 41 | false 42 | false 43 | v143 44 | 45 | 46 | Application 47 | false 48 | true 49 | MultiByte 50 | false 51 | false 52 | v143 53 | 54 | 55 | Application 56 | false 57 | true 58 | MultiByte 59 | false 60 | false 61 | v143 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | true 81 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 82 | $(SolutionDir)$(Configuration)\$(Platform)\ 83 | 84 | 85 | true 86 | $(SolutionDir)$(Configuration)\$(Platform)\ 87 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 88 | 89 | 90 | false 91 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 92 | $(SolutionDir)$(Configuration)\$(Platform)\ 93 | 94 | 95 | false 96 | $(SolutionDir)$(Configuration)\$(Platform)\ 97 | $(SolutionDir)Build\$(ProjectName).$(Platform)\$(Configuration)\ 98 | 99 | 100 | 101 | 102 | 103 | Level3 104 | Disabled 105 | WIN32;_DEBUG;_CONSOLE;WITH_TIME_LOGGER;%(PreprocessorDefinitions) 106 | stdcpp17 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | 116 | 117 | Level3 118 | Disabled 119 | WIN32;_DEBUG;_CONSOLE;WITH_TIME_LOGGER;%(PreprocessorDefinitions) 120 | stdcpp17 121 | 122 | 123 | Console 124 | true 125 | 126 | 127 | 128 | 129 | Level3 130 | 131 | 132 | MaxSpeed 133 | true 134 | true 135 | WIN32;NDEBUG;_CONSOLE;WITH_TIME_LOGGER;%(PreprocessorDefinitions) 136 | stdcpp17 137 | 138 | 139 | Console 140 | true 141 | true 142 | true 143 | 144 | 145 | 146 | 147 | Level3 148 | 149 | 150 | MaxSpeed 151 | true 152 | true 153 | WIN32;NDEBUG;_CONSOLE;WITH_TIME_LOGGER;%(PreprocessorDefinitions) 154 | stdcpp17 155 | 156 | 157 | Console 158 | true 159 | true 160 | true 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | {9751c465-0294-43cd-a5d9-bd038aba3961} 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /run_tests.2022.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Quelldateien 20 | 21 | 22 | 23 | 24 | Headerdateien 25 | 26 | 27 | -------------------------------------------------------------------------------- /run_tests.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ardi69/42tiny-js/a31979449f329f0314f120ad6abb95b57c933ca4/run_tests.cpp -------------------------------------------------------------------------------- /tests/42tests/test001.js: -------------------------------------------------------------------------------- 1 | // switch-case-tests 2 | 3 | //////////////////////////////////////////////////// 4 | // switch-test 1: case with break; 5 | //////////////////////////////////////////////////// 6 | var a1=5; 7 | var b1=6; 8 | var r1=0; 9 | 10 | switch(a1+5){ 11 | case 6: 12 | r1 = 2; 13 | break; 14 | case b1+4: 15 | r1 = 42; 16 | break; 17 | case 7: 18 | r1 = 2; 19 | break; 20 | } 21 | 22 | //////////////////////////////////////////////////// 23 | // switch-test 2: case with out break; 24 | //////////////////////////////////////////////////// 25 | var a2=5; 26 | var b2=6; 27 | var r2=0; 28 | 29 | switch(a2+4){ 30 | case 6: 31 | r2 = 2; 32 | break; 33 | case b2+3: 34 | r2 = 40; 35 | //break; 36 | case 7: 37 | r2 += 2; 38 | break; 39 | } 40 | 41 | //////////////////////////////////////////////////// 42 | // switch-test 3: case with default; 43 | //////////////////////////////////////////////////// 44 | var a3=5; 45 | var b3=6; 46 | var r3=0; 47 | 48 | switch(a3+44){ 49 | case 6: 50 | r3 = 2; 51 | break; 52 | case b3+3: 53 | r3 = 1; 54 | break; 55 | default: 56 | r3 = 42; 57 | break; 58 | } 59 | 60 | //////////////////////////////////////////////////// 61 | // switch-test 4: case default before case; 62 | //////////////////////////////////////////////////// 63 | var a4=5; 64 | var b4=6; 65 | var r4=0; 66 | 67 | switch(a4+44){ 68 | default: 69 | r4 = 42; 70 | break; 71 | case 6: 72 | r4 = 2; 73 | break; 74 | case b4+3: 75 | r4 = 1; 76 | break; 77 | } 78 | 79 | 80 | result = r1 == 42 && r2 == 42 && r3 == 42 && r4 == 42; 81 | -------------------------------------------------------------------------------- /tests/42tests/test002.js: -------------------------------------------------------------------------------- 1 | // function-closure 2 | 3 | var a = 40; // a global var 4 | 5 | function closure() { 6 | var a = 39; // a local var; 7 | return function() { return a; }; 8 | } 9 | 10 | var b = closure(); // the local var a is now hidden 11 | 12 | result = b()+3 == 42 && a+2 == 42; 13 | -------------------------------------------------------------------------------- /tests/42tests/test003.js: -------------------------------------------------------------------------------- 1 | // with-test 2 | 3 | var a; 4 | 5 | with(Math) a=PI; 6 | 7 | var b = { get_member : function() { return this.member;}, member:41 }; 8 | 9 | with(b) { 10 | let a = get_member(); //<--- a is local for this block 11 | var c = a+1; 12 | } 13 | 14 | 15 | result = a == Math.PI && c == 42; 16 | -------------------------------------------------------------------------------- /tests/42tests/test004.js: -------------------------------------------------------------------------------- 1 | // generator-test 2 | 3 | function* fibonacci(){ 4 | var fn1 = 1; 5 | var fn2 = 1; 6 | while (1){ 7 | var current = fn2; 8 | fn2 = fn1; 9 | fn1 = fn1 + current; 10 | var reset = yield current; 11 | if (reset){ 12 | fn1 = 1; 13 | fn2 = 1; 14 | } 15 | } 16 | } 17 | 18 | var generator = fibonacci(); 19 | 20 | generator.next(); // 1 21 | generator.next(); // 1 22 | generator.next(); // 2 23 | generator.next(); // 3 24 | generator.next(); // 5 25 | 26 | 27 | result = generator.next() == 8 && generator.send(true) == 1; 28 | -------------------------------------------------------------------------------- /tests/42tests/test005.js: -------------------------------------------------------------------------------- 1 | // Allgemeiner Test für 42tinyjs (ohne Arrays) 2 | // Getestet werden: Arithmetik, Strings, Objekte, Funktionen, Closures, Rekursion, 3 | // Schleifen, Fehlerbehandlung, JSON-Serialisierung, Generatoren, "this"-Kontext, Logik. 4 | 5 | var failedTests = []; 6 | 7 | // Hilfsfunktion zum Speichern von Fehlschlägen 8 | function checkTest(testNumber, condition, errorMessage) { 9 | if (!condition) { 10 | failedTests.push("Test " + testNumber + (errorMessage ? " (" + errorMessage + ")" : "")); 11 | } 12 | } 13 | 14 | // ----------------------------------------------------------------- 15 | // Test 1: Basis-Arithmetik 16 | print("Test 1: Basis-Arithmetik"); 17 | try { 18 | var t1 = (1 + 2 === 3) && (5 - 2 === 3) && (2 * 3 === 6) && (8 / 2 === 4); 19 | print("Ergebnis Test 1: " + t1); 20 | checkTest(1, t1); 21 | } catch (e) { 22 | checkTest(1, false, e); 23 | } 24 | 25 | // ----------------------------------------------------------------- 26 | // Test 2: String-Operationen 27 | print("Test 2: String-Operationen"); 28 | try { 29 | var str = "Hello, " + "World!"; 30 | var t2 = (str == "Hello, World!" && str.charAt(0) === "H" && str.substring(7, 12) === "World"); 31 | print("Ergebnis Test 2: " + t2); 32 | checkTest(2, t2); 33 | } catch (e) { 34 | checkTest(2, false, e); 35 | } 36 | 37 | // ----------------------------------------------------------------- 38 | // Test 3: Objekt-Manipulation 39 | print("Test 3: Objekt-Manipulation"); 40 | try { 41 | var obj = { a: 10, b: 20 }; 42 | obj.c = obj.a + obj.b; 43 | var t3 = (obj.c === 30 && "c" in obj); 44 | print("Ergebnis Test 3: " + t3); 45 | checkTest(3, t3); 46 | } catch (e) { 47 | checkTest(3, false, e); 48 | } 49 | 50 | // ----------------------------------------------------------------- 51 | // Test 4: Funktionen und Closures 52 | print("Test 4: Funktionen und Closures"); 53 | try { 54 | function multiplier(factor) { 55 | return function(x) { 56 | return x * factor; 57 | }; 58 | } 59 | var double = multiplier(2); 60 | var t4 = (double(5) === 10); 61 | print("Ergebnis Test 4: " + t4); 62 | checkTest(4, t4); 63 | } catch (e) { 64 | checkTest(4, false, e); 65 | } 66 | 67 | // ----------------------------------------------------------------- 68 | // Test 5: Rekursion (Fakultät) 69 | print("Test 5: Rekursion (Fakultät)"); 70 | try { 71 | function factorial(n) { 72 | if (n <= 1) return 1; 73 | return n * factorial(n - 1); 74 | } 75 | var t5 = (factorial(5) === 120); 76 | print("Ergebnis Test 5: " + t5); 77 | checkTest(5, t5); 78 | } catch (e) { 79 | checkTest(5, false, e); 80 | } 81 | 82 | // ----------------------------------------------------------------- 83 | // Test 6: For-Schleife 84 | print("Test 6: For-Schleife"); 85 | try { 86 | var count = 0; 87 | for (var i = 0; i < 5; i++) { 88 | count++; 89 | } 90 | var t6 = (count === 5); 91 | print("Ergebnis Test 6: " + t6); 92 | checkTest(6, t6); 93 | } catch (e) { 94 | checkTest(6, false, e); 95 | } 96 | 97 | // ----------------------------------------------------------------- 98 | // Test 7: While-Schleife 99 | print("Test 7: While-Schleife"); 100 | try { 101 | var countWhile = 0; 102 | while (countWhile < 5) { 103 | countWhile++; 104 | } 105 | var t7 = (countWhile === 5); 106 | print("Ergebnis Test 7: " + t7); 107 | checkTest(7, t7); 108 | } catch (e) { 109 | checkTest(7, false, e); 110 | } 111 | 112 | // ----------------------------------------------------------------- 113 | // Test 8: Fehlerbehandlung (try-catch) 114 | print("Test 8: Fehlerbehandlung (try-catch)"); 115 | try { 116 | var errorCaught = false; 117 | try { 118 | throw "Test-Fehler"; 119 | } catch (e) { 120 | errorCaught = (e === "Test-Fehler"); 121 | } 122 | var t8 = errorCaught; 123 | print("Ergebnis Test 8: " + t8); 124 | checkTest(8, t8); 125 | } catch (e) { 126 | checkTest(8, false, e); 127 | } 128 | 129 | // ----------------------------------------------------------------- 130 | // Test 9: JSON-Serialisierung 131 | print("Test 9: JSON-Serialisierung"); 132 | try { 133 | var original = { name: "42tinyjs", version: "1.0" }; 134 | var clone = JSON.parse(JSON.stringify(original)); 135 | var t9 = (clone.name === "42tinyjs" && clone.version === "1.0"); 136 | print("Ergebnis Test 9: " + t9); 137 | checkTest(9, t9); 138 | } catch (e) { 139 | checkTest(9, false, e); 140 | } 141 | 142 | // ----------------------------------------------------------------- 143 | // Test 10: Generator-Funktion (Fibonacci) 144 | print("Test 10: Generator-Funktion (Fibonacci)"); 145 | try { 146 | function* fibGenerator() { 147 | var a = 1, b = 1; 148 | while (true) { 149 | yield a; 150 | var temp = a; 151 | a = b; 152 | b = temp + b; 153 | } 154 | } 155 | var gen = fibGenerator(); 156 | var t10 = (gen.next() === 1 && gen.next() === 1 && gen.next() === 2); 157 | print("Ergebnis Test 10: " + t10); 158 | checkTest(10, t10); 159 | } catch (e) { 160 | checkTest(10, false, e); 161 | } 162 | 163 | // ----------------------------------------------------------------- 164 | // Test 11: "this"-Kontext in Methoden 165 | print("Test 11: 'this'-Kontext"); 166 | try { 167 | var objTest = { 168 | value: 42, 169 | getValue: function() { 170 | return this.value; 171 | } 172 | }; 173 | var t11 = (objTest.getValue() === 42); 174 | print("Ergebnis Test 11: " + t11); 175 | checkTest(11, t11); 176 | } catch (e) { 177 | checkTest(11, false, e); 178 | } 179 | 180 | // ----------------------------------------------------------------- 181 | // Test 12: Logische Operatoren und ternärer Operator 182 | print("Test 12: Logische Operatoren und ternärer Operator"); 183 | try { 184 | var cond = (5 > 3) && (2 < 4); 185 | var ternary = cond ? "yes" : "no"; 186 | var t12 = (cond === true && ternary === "yes"); 187 | print("Ergebnis Test 12: " + t12); 188 | checkTest(12, t12); 189 | } catch (e) { 190 | checkTest(12, false, e); 191 | } 192 | 193 | // ----------------------------------------------------------------- 194 | // Abschluss der Tests 195 | if (failedTests.length === 0) { 196 | print("✅ Alle Tests bestanden!"); 197 | result = true; 198 | } else { 199 | print("❌ Fehler in folgenden Tests:\n" + failedTests.join("\n")); 200 | result = false; 201 | } 202 | -------------------------------------------------------------------------------- /tests/42tests/test006.js: -------------------------------------------------------------------------------- 1 | // Array-Test für 42tinyjs (isolierte Tests) 2 | // Jeder Test arbeitet mit einem eigenen Array, um Seiteneffekte zu vermeiden. 3 | 4 | var failedTests = []; 5 | 6 | // Hilfsfunktion zum Speichern von Fehlschlägen 7 | function checkTest(testNumber, condition, errorMessage) { 8 | if (!condition) { 9 | failedTests.push("Test " + testNumber + (errorMessage ? " (" + errorMessage + ")" : "")); 10 | } 11 | } 12 | 13 | // ----------------------------------------------------------------- 14 | // Test 1: Erstellung und Grundoperationen 15 | print("Test 1: Erstellung und Grundoperationen"); 16 | try { 17 | var arr1 = [10, 20, 30, 40, 50]; 18 | var t1 = (arr1.length === 5 && arr1[0] === 10 && arr1[4] === 50); 19 | print("Ergebnis Test 1: " + t1); 20 | checkTest(1, t1); 21 | } catch (e) { 22 | checkTest(1, false, e); 23 | } 24 | 25 | // ----------------------------------------------------------------- 26 | // Test 2: Zugriff und Manipulation 27 | print("Test 2: Zugriff und Manipulation"); 28 | try { 29 | var arr2 = [10, 20, 30, 40, 50]; 30 | arr2[2] = 99; 31 | var t2 = (arr2[2] === 99); 32 | print("Ergebnis Test 2: " + t2); 33 | checkTest(2, t2); 34 | } catch (e) { 35 | checkTest(2, false, e); 36 | } 37 | 38 | // ----------------------------------------------------------------- 39 | // Test 3: Push() und Pop() 40 | print("Test 3: Push() und Pop()"); 41 | try { 42 | var arr3 = [10, 20, 30, 40, 50]; 43 | arr3.push(60); 44 | var poppedValue = arr3.pop(); 45 | var t3 = (poppedValue === 60 && arr3.length === 5); 46 | print("Ergebnis Test 3: " + t3); 47 | checkTest(3, t3); 48 | } catch (e) { 49 | checkTest(3, false, e); 50 | } 51 | 52 | // ----------------------------------------------------------------- 53 | // Test 4: Unshift() und Shift() 54 | print("Test 4: Unshift() und Shift()"); 55 | try { 56 | var arr4 = [10, 20, 30, 40, 50]; 57 | arr4.unshift(5); 58 | var shiftedValue = arr4.shift(); 59 | var t4 = (shiftedValue === 5 && arr4.length === 5); 60 | print("Ergebnis Test 4: " + t4); 61 | checkTest(4, t4); 62 | } catch (e) { 63 | checkTest(4, false, e); 64 | } 65 | 66 | // ----------------------------------------------------------------- 67 | // Test 5: Slice() – Teilarray extrahieren 68 | print("Test 5: Slice()"); 69 | try { 70 | var arr5 = [10, 20, 30, 40, 50]; 71 | var sliced = arr5.slice(1, 3); 72 | // Erwartet: [20, 30] 73 | var t5 = (sliced.length === 2 && sliced[0] === 20 && sliced[1] === 30); 74 | print("Ergebnis Test 5: " + t5); 75 | checkTest(5, t5); 76 | } catch (e) { 77 | checkTest(5, false, e); 78 | } 79 | 80 | // ----------------------------------------------------------------- 81 | // Test 6: Splice() – Elemente entfernen 82 | print("Test 6: Splice()"); 83 | try { 84 | var arr6 = [10, 20, 30, 40, 50]; 85 | var spliced = arr6.splice(2, 2); // entfernt 30 und 40 86 | // arr6 sollte jetzt [10,20,50] sein 87 | var t6 = (spliced.length === 2 && arr6.length === 3 && arr6[2] === 50); 88 | print("Ergebnis Test 6: " + t6); 89 | checkTest(6, t6); 90 | } catch (e) { 91 | checkTest(6, false, e); 92 | } 93 | 94 | // ----------------------------------------------------------------- 95 | // Test 7: for-Schleife über ein Array 96 | print("Test 7: for-Schleife über ein Array"); 97 | try { 98 | var arr7 = [10, 20, 30, 40, 50]; 99 | var sum = 0; 100 | for (var i = 0; i < arr7.length; i++) { 101 | sum += arr7[i]; 102 | } 103 | var t7 = (sum === 150); 104 | print("Ergebnis Test 7: " + t7); 105 | checkTest(7, t7); 106 | } catch (e) { 107 | checkTest(7, false, e); 108 | } 109 | 110 | // ----------------------------------------------------------------- 111 | // Test 8: forEach() Methode 112 | print("Test 8: forEach()"); 113 | try { 114 | var arr8 = [10, 20, 30, 40, 50]; 115 | var sum2 = 0; 116 | arr8.forEach(function(num) { 117 | sum2 += num; 118 | }); 119 | var t8 = (sum2 === 150); 120 | print("Ergebnis Test 8: " + t8); 121 | checkTest(8, t8); 122 | } catch (e) { 123 | checkTest(8, false, e); 124 | } 125 | 126 | // ----------------------------------------------------------------- 127 | // Test 9: indexOf() und includes() 128 | print("Test 9: indexOf() und includes()"); 129 | try { 130 | var arr9 = [10, 20, 30, 40, 50]; 131 | var t9 = (arr9.indexOf(20) === 1 && arr9.includes(50) && !arr9.includes(99)); 132 | print("Ergebnis Test 9: " + t9); 133 | checkTest(9, t9); 134 | } catch (e) { 135 | checkTest(9, false, e); 136 | } 137 | 138 | // ----------------------------------------------------------------- 139 | // Test 10: Sort() 140 | print("Test 10: Sort()"); 141 | try { 142 | var arr10 = [5, 2, 9, 1, 10]; 143 | arr10.sort(function(a, b) { return a - b; }); 144 | var t10 = (arr10[0] === 1 && arr10[4] === 10); 145 | print("Ergebnis Test 10: " + t10); 146 | checkTest(10, t10); 147 | } catch (e) { 148 | checkTest(10, false, e); 149 | } 150 | 151 | // ----------------------------------------------------------------- 152 | // Test 11: map() – Transformation von Arrays 153 | print("Test 11: map()"); 154 | try { 155 | var arr11 = [10, 20, 30]; 156 | var squared = arr11.map(function(num) { return num * num; }); 157 | var t11 = (squared[0] === 100 && squared[1] === 400 && squared[2] === 900); 158 | print("Ergebnis Test 11: " + t11); 159 | checkTest(11, t11); 160 | } catch (e) { 161 | checkTest(11, false, e); 162 | } 163 | 164 | // ----------------------------------------------------------------- 165 | // Test 12: reduce() – Array zu einem Wert reduzieren 166 | print("Test 12: reduce()"); 167 | try { 168 | var arr12 = [10, 20, 30]; 169 | var reducedSum = arr12.reduce(function(acc, num) { return acc + num; }, 0); 170 | var t12 = (reducedSum === 60); 171 | print("Ergebnis Test 12: " + t12); 172 | checkTest(12, t12); 173 | } catch (e) { 174 | checkTest(12, false, e); 175 | } 176 | 177 | // ----------------------------------------------------------------- 178 | // Test 13: Mehrdimensionale Arrays 179 | print("Test 13: Mehrdimensionale Arrays"); 180 | try { 181 | var matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; 182 | var t13 = (matrix[1][1] === 5); 183 | print("Ergebnis Test 13: " + t13); 184 | checkTest(13, t13); 185 | } catch (e) { 186 | checkTest(13, false, e); 187 | } 188 | 189 | // ----------------------------------------------------------------- 190 | // Test 14: Leeres Array prüfen 191 | print("Test 14: Leeres Array"); 192 | try { 193 | var arr14 = []; 194 | var t14 = (arr14.length === 0); 195 | print("Ergebnis Test 14: " + t14); 196 | checkTest(14, t14); 197 | } catch (e) { 198 | checkTest(14, false, e); 199 | } 200 | 201 | // ----------------------------------------------------------------- 202 | // Abschluss des Array-Tests 203 | if (failedTests.length === 0) { 204 | print("✅ Alle Array-Tests bestanden!"); 205 | result = true; 206 | } else { 207 | print("❌ Fehler in folgenden Tests:\n" + failedTests.join("\n")); 208 | result = false; 209 | } 210 | -------------------------------------------------------------------------------- /tests/42tests/test007.js: -------------------------------------------------------------------------------- 1 | // String-Test für 42tinyjs 2 | // Überprüft verschiedene String-Operationen 3 | 4 | var failedTests = []; 5 | 6 | // Hilfsfunktion zum Speichern von Fehlschlägen 7 | function checkTest(testNumber, condition, errorMessage) { 8 | if (!condition) { 9 | failedTests.push("Test " + testNumber + (errorMessage ? " (" + errorMessage + ")" : "")); 10 | } 11 | } 12 | 13 | // ----------------------------------------------------------------- 14 | // Test 1: String-Konkatenation und Grundoperationen 15 | print("Test 1: String-Konkatenation und Grundoperationen"); 16 | try { 17 | var str1 = "Hello, " + "World!"; 18 | var t1 = (str1 === "Hello, World!" && str1.length === 13); 19 | print("Ergebnis Test 1: " + t1); 20 | checkTest(1, t1); 21 | } catch (e) { 22 | checkTest(1, false, e); 23 | } 24 | 25 | // ----------------------------------------------------------------- 26 | // Test 2: Zeichen-Zugriff mit charAt() 27 | print("Test 2: charAt()"); 28 | try { 29 | var str2 = "JavaScript"; 30 | var t2 = (str2.charAt(0) === "J" && str2.charAt(4) === "S"); 31 | print("Ergebnis Test 2: " + t2); 32 | checkTest(2, t2); 33 | } catch (e) { 34 | checkTest(2, false, e); 35 | } 36 | 37 | // ----------------------------------------------------------------- 38 | // Test 3: substring() und slice() 39 | print("Test 3: substring() und slice()"); 40 | try { 41 | var str3 = "42tinyjs"; 42 | var t3 = (str3.substring(2, 6) === "tiny" && str3.slice(2, 6) === "tiny"); 43 | print("Ergebnis Test 3: " + t3); 44 | checkTest(3, t3); 45 | } catch (e) { 46 | checkTest(3, false, e); 47 | } 48 | 49 | // ----------------------------------------------------------------- 50 | // Test 4: indexOf() und lastIndexOf() 51 | print("Test 4: indexOf() und lastIndexOf()"); 52 | try { 53 | var str4 = "banananana"; 54 | var t4 = (str4.indexOf("na") === 2 && str4.lastIndexOf("na") === 8); 55 | print("Ergebnis Test 4: " + t4); 56 | checkTest(4, t4); 57 | } catch (e) { 58 | checkTest(4, false, e); 59 | } 60 | 61 | // ----------------------------------------------------------------- 62 | // Test 5: includes(), startsWith(), endsWith() 63 | print("Test 5: includes(), startsWith(), endsWith()"); 64 | try { 65 | var str5 = "Hello, tinyJS!"; 66 | var t5 = (str5.includes("tiny") && str5.startsWith("Hello") && str5.endsWith("!")); 67 | print("Ergebnis Test 5: " + t5); 68 | checkTest(5, t5); 69 | } catch (e) { 70 | checkTest(5, false, e); 71 | } 72 | 73 | // ----------------------------------------------------------------- 74 | // Test 6: toUpperCase() und toLowerCase() 75 | print("Test 6: toUpperCase() und toLowerCase()"); 76 | try { 77 | var str6 = "MiXeD CaSe"; 78 | var t6 = (str6.toUpperCase() === "MIXED CASE" && str6.toLowerCase() === "mixed case"); 79 | print("Ergebnis Test 6: " + t6); 80 | checkTest(6, t6); 81 | } catch (e) { 82 | checkTest(6, false, e); 83 | } 84 | 85 | // ----------------------------------------------------------------- 86 | // Test 7: trim() 87 | print("Test 7: trim()"); 88 | try { 89 | var str7 = " whitespace "; 90 | var t7 = (str7.trim() === "whitespace"); 91 | print("Ergebnis Test 7: " + t7); 92 | checkTest(7, t7); 93 | } catch (e) { 94 | checkTest(7, false, e); 95 | } 96 | 97 | // ----------------------------------------------------------------- 98 | // Test 8: replace() 99 | print("Test 8: replace()"); 100 | try { 101 | var str8 = "Ich mag Kaffee!"; 102 | var newStr8 = str8.replace("Kaffee", "Tee"); 103 | var t8 = (newStr8 === "Ich mag Tee!"); 104 | print("Ergebnis Test 8: " + t8); 105 | checkTest(8, t8); 106 | } catch (e) { 107 | checkTest(8, false, e); 108 | } 109 | 110 | // ----------------------------------------------------------------- 111 | // Test 9: split() und join() 112 | print("Test 9: split() und join()"); 113 | try { 114 | var str9 = "eins,zwei,drei"; 115 | var parts = str9.split(","); 116 | var joined = parts.join("-"); 117 | var t9 = (parts.length === 3 && parts[1] === "zwei" && joined === "eins-zwei-drei"); 118 | print("Ergebnis Test 9: " + t9); 119 | checkTest(9, t9); 120 | } catch (e) { 121 | checkTest(9, false, e); 122 | } 123 | 124 | // ----------------------------------------------------------------- 125 | // Test 10: Mehrzeilige Strings mit \n 126 | print("Test 10: Mehrzeilige Strings mit \\n"); 127 | try { 128 | var str10 = "Zeile 1\nZeile 2\nZeile 3"; 129 | var t10 = (str10.split("\n").length === 3); 130 | print("Ergebnis Test 10: " + t10); 131 | checkTest(10, t10); 132 | } catch (e) { 133 | checkTest(10, false, e); 134 | } 135 | 136 | // ----------------------------------------------------------------- 137 | // Test 11: Escaping von Zeichen 138 | print("Test 11: Escaping von Zeichen"); 139 | try { 140 | var str11 = "Er sagte: \"Hallo!\""; 141 | var t11 = (str11 === "Er sagte: \"Hallo!\""); 142 | print("Ergebnis Test 11: " + t11); 143 | checkTest(11, t11); 144 | } catch (e) { 145 | checkTest(11, false, e); 146 | } 147 | 148 | // ----------------------------------------------------------------- 149 | // Abschluss des String-Tests 150 | if (failedTests.length === 0) { 151 | print("✅ Alle String-Tests bestanden!"); 152 | result = true; 153 | } else { 154 | print("❌ Fehler in folgenden Tests: " + failedTests.join(", ")); 155 | result = false; 156 | } 157 | -------------------------------------------------------------------------------- /tests/42tests/test008.js: -------------------------------------------------------------------------------- 1 | // Template Literal Test für 42tinyjs (inkl. Tagged Templates) 2 | 3 | var failedTests = []; 4 | 5 | // Hilfsfunktion zum Speichern von Fehlschlägen 6 | function checkTest(testNumber, condition, errorMessage) { 7 | if (!condition) { 8 | failedTests.push("Test " + testNumber + (errorMessage ? " (" + errorMessage + ")" : "")); 9 | } 10 | } 11 | 12 | // ----------------------------------------------------------------- 13 | // Test 1: Einfache Verwendung von Template Literals 14 | print("Test 1: Einfache Verwendung"); 15 | try { 16 | var str1 = `Hallo Welt`; 17 | var t1 = (str1 === "Hallo Welt"); 18 | print("Ergebnis Test 1: " + t1); 19 | checkTest(1, t1); 20 | } catch (e) { 21 | checkTest(1, false, e); 22 | } 23 | 24 | // ----------------------------------------------------------------- 25 | // Test 2: Variable Einbindung 26 | print("Test 2: Variable Einbindung"); 27 | try { 28 | var name = "42tinyjs"; 29 | var str2 = `Hallo, ${name}!`; 30 | var t2 = (str2 === "Hallo, 42tinyjs!"); 31 | print("Ergebnis Test 2: " + t2); 32 | checkTest(2, t2); 33 | } catch (e) { 34 | checkTest(2, false, e); 35 | } 36 | 37 | // ----------------------------------------------------------------- 38 | // Test 3: Tagged Template - Einfache Funktion 39 | print("Test 3: Tagged Template - Einfache Funktion"); 40 | try { 41 | function tag(strings, value) { 42 | return `Tagged: ${strings[0]}${value}`; 43 | } 44 | var str3 = tag`Hallo ${"42tinyjs"}`; 45 | var t3 = (str3 === "Tagged: Hallo 42tinyjs"); 46 | print("Ergebnis Test 3: " + t3); 47 | checkTest(3, t3); 48 | } catch (e) { 49 | checkTest(3, false, e); 50 | } 51 | 52 | // ----------------------------------------------------------------- 53 | // Test 4: Tagged Template mit mehreren Werten 54 | print("Test 4: Tagged Template mit mehreren Werten"); 55 | try { 56 | function format(strings, ...values) { 57 | return strings[0] + values.join(", ") + strings[2]; 58 | } 59 | var str4 = format`Werte: ${10} und ${20}.`; 60 | var t4 = (str4 === "Werte: 10, 20."); 61 | print("Ergebnis Test 4: " + t4); 62 | checkTest(4, t4); 63 | } catch (e) { 64 | checkTest(4, false, e); 65 | } 66 | 67 | // ----------------------------------------------------------------- 68 | // Test 5: Tagged Template mit Manipulation 69 | print("Test 5: Tagged Template mit Manipulation"); 70 | try { 71 | function upper(strings, ...values) { 72 | return strings[0] + values.map(v => v.toUpperCase()).join(" ") + strings[1]; 73 | } 74 | var str5 = upper`Hallo ${"welt"}!`; 75 | print(str5) 76 | var t5 = (str5 === "Hallo WELT!"); 77 | print("Ergebnis Test 5: " + t5); 78 | checkTest(5, t5); 79 | } catch (e) { 80 | checkTest(5, false, e); 81 | } 82 | 83 | // ----------------------------------------------------------------- 84 | // Test 6: Tagged Template mit Berechnung 85 | print("Test 6: Tagged Template mit Berechnung"); 86 | try { 87 | function sum(strings, a, b) { 88 | return `${strings[0]}${a + b}${strings[2]}`; 89 | } 90 | var str6 = sum`Summe: ${5} und ${10}.`; 91 | var t6 = (str6 === "Summe: 15."); 92 | print("Ergebnis Test 6: " + t6); 93 | checkTest(6, t6); 94 | } catch (e) { 95 | checkTest(6, false, e); 96 | } 97 | 98 | // ----------------------------------------------------------------- 99 | // Test 7: Mehrzeilige Tagged Templates 100 | print("Test 7: Mehrzeilige Tagged Templates"); 101 | try { 102 | function multiline(strings, ...values) { 103 | return strings.join("\n") + "\n" + values.join("\n"); 104 | } 105 | var str7 = multiline`Zeile 1 106 | Zeile 2 ${"Wert"} 107 | Zeile 3`; 108 | print(str7); 109 | var t7 = (str7.split("\n").length === 5); 110 | print("Ergebnis Test 7: " + t7); 111 | checkTest(7, t7); 112 | } catch (e) { 113 | checkTest(7, false, e); 114 | } 115 | 116 | // ----------------------------------------------------------------- 117 | // Abschluss des Template Literal Tests 118 | if (failedTests.length === 0) { 119 | print("✅ Alle Template Literal Tests bestanden!"); 120 | result = true; 121 | } else { 122 | print("❌ Fehler in folgenden Tests:\n" + failedTests.join("\n")); 123 | result = false; 124 | } 125 | -------------------------------------------------------------------------------- /tests/test001.js: -------------------------------------------------------------------------------- 1 | // simply testing we can return the correct value 2 | result = 1; 3 | -------------------------------------------------------------------------------- /tests/test002.js: -------------------------------------------------------------------------------- 1 | // comparison 2 | var a = 42; 3 | result = a==42; 4 | -------------------------------------------------------------------------------- /tests/test003.js: -------------------------------------------------------------------------------- 1 | // simple for loop 2 | var a = 0; 3 | var i; 4 | for (i=1;i<10;i++) a = a + i; 5 | result = a==45; 6 | -------------------------------------------------------------------------------- /tests/test004.js: -------------------------------------------------------------------------------- 1 | // simple if 2 | var a = 42; 3 | if (a < 43) 4 | result = 1; 5 | -------------------------------------------------------------------------------- /tests/test005.js: -------------------------------------------------------------------------------- 1 | // simple for loop containing initialisation, using += 2 | var a = 0; 3 | for (var i=1;i<10;i++) a += i; 4 | result = a==45; 5 | -------------------------------------------------------------------------------- /tests/test006.js: -------------------------------------------------------------------------------- 1 | // simple function 2 | function add(x,y) { return x+y; } 3 | result = add(3,6)==9; 4 | -------------------------------------------------------------------------------- /tests/test007.js: -------------------------------------------------------------------------------- 1 | // simple function scoping test 2 | var a = 7; 3 | function add(x,y) { var a=x+y; return a; } 4 | result = add(3,6)==9 && a==7; 5 | -------------------------------------------------------------------------------- /tests/test008.js: -------------------------------------------------------------------------------- 1 | // functions in variables 2 | var bob = {}; 3 | bob.add = function(x,y) { return x+y; }; 4 | 5 | result = bob.add(3,6)==9; 6 | -------------------------------------------------------------------------------- /tests/test009.js: -------------------------------------------------------------------------------- 1 | // functions in variables using JSON-style initialisation 2 | var bob = { add : function(x,y) { return x+y; } }; 3 | 4 | result = bob.add(3,6)==9; 5 | -------------------------------------------------------------------------------- /tests/test010.js: -------------------------------------------------------------------------------- 1 | // double function calls 2 | function a(x) { return x+2; } 3 | function b(x) { return a(x)+1; } 4 | result = a(3)==5 && b(3)==6; 5 | -------------------------------------------------------------------------------- /tests/test011.js: -------------------------------------------------------------------------------- 1 | // recursion 2 | function a(x) { 3 | if (x>1) 4 | return x*a(x-1); 5 | return 1; 6 | } 7 | result = a(5)==1*2*3*4*5; 8 | -------------------------------------------------------------------------------- /tests/test012.js: -------------------------------------------------------------------------------- 1 | // if .. else 2 | var a = 42; 3 | if (a != 42) 4 | result = 0; 5 | else 6 | result = 1; 7 | -------------------------------------------------------------------------------- /tests/test013.js: -------------------------------------------------------------------------------- 1 | // if .. else with blocks 2 | var a = 42; 3 | if (a != 42) { 4 | result = 0; 5 | } else { 6 | result = 1; 7 | } 8 | -------------------------------------------------------------------------------- /tests/test014.js: -------------------------------------------------------------------------------- 1 | // Variable creation and scope from http://en.wikipedia.org/wiki/JavaScript_syntax 2 | x = 0; // A global variable 3 | var y = 'Hello!'; // Another global variable 4 | z = 0; // yet another global variable 5 | 6 | function f(){ 7 | var z = 'foxes'; // A local variable 8 | twenty = 20; // Global because keyword var is not used 9 | return x; // We can use x here because it is global 10 | } 11 | // The value of z is no longer available 12 | 13 | 14 | // testing 15 | blah = f(); 16 | result = blah==0 && z!='foxes' && twenty==20; 17 | -------------------------------------------------------------------------------- /tests/test015.js: -------------------------------------------------------------------------------- 1 | // Number definition from http://en.wikipedia.org/wiki/JavaScript_syntax 2 | a = 345; // an "integer", although there is only one numeric type in JavaScript 3 | b = 34.5; // a floating-point number 4 | c = 3.45e2; // another floating-point, equivalent to 345 5 | d = 0o377; // an octal integer equal to 255 6 | e = 0xFF; // a hexadecimal integer equal to 255, digits represented by the letters A-F may be upper or lowercase 7 | 8 | result = a==345 && b*10==345 && c==345 && d==255 && e==255; 9 | -------------------------------------------------------------------------------- /tests/test016.js: -------------------------------------------------------------------------------- 1 | // Undefined/null from http://en.wikipedia.org/wiki/JavaScript_syntax 2 | var testUndefined; // variable declared but not defined, set to value of undefined 3 | var testObj = {}; 4 | 5 | result = 1; 6 | if ((""+testUndefined) != "undefined") result = 0; // test variable exists but value not defined, displays undefined 7 | if ((""+testObj.myProp) != "undefined") result = 0; // testObj exists, property does not, displays undefined 8 | if (!(undefined == null)) result = 0; // unenforced type during check, displays true 9 | if (undefined === null) result = 0;// enforce type during check, displays false 10 | 11 | 12 | if (null != undefined) result = 0; // unenforced type during check, displays true 13 | if (null === undefined) result = 0; // enforce type during check, displays false 14 | 15 | 16 | -------------------------------------------------------------------------------- /tests/test017.js: -------------------------------------------------------------------------------- 1 | // references for arrays 2 | 3 | var a = []; 4 | a[0] = 10; 5 | a[1] = 22; 6 | 7 | b = a; 8 | 9 | b[0] = 5; 10 | 11 | result = a[0]==5 && a[1]==22 && b[1]==22; 12 | -------------------------------------------------------------------------------- /tests/test018.js: -------------------------------------------------------------------------------- 1 | // references with functions 2 | 3 | var a = 42; 4 | var b = []; 5 | b[0] = 43; 6 | 7 | function foo(myarray) { 8 | myarray[0]++; 9 | } 10 | 11 | function bar(myvalue) { 12 | myvalue++; 13 | } 14 | 15 | foo(b); 16 | bar(a); 17 | 18 | result = a==42 && b[0]==44; 19 | -------------------------------------------------------------------------------- /tests/test019.42.js: -------------------------------------------------------------------------------- 1 | // built-in functions 2 | 3 | foo = "foo bar stuff"; 4 | // 42-tiny-js change begin ---> 5 | // in JavaScript this function is called Math.random() 6 | //r = Math.rand(); 7 | r = Math.random(); 8 | //<--- 42-tiny-js change end 9 | 10 | // 42-tiny-js change begin ---> 11 | // in JavaScript parseInt is a methode in the global scope (root-scope) 12 | //parsed = Integer.parseInt("42"); 13 | parsed = parseInt("42"); 14 | //<--- 42-tiny-js change end 15 | 16 | aStr = "ABCD"; 17 | aChar = aStr.charAt(0); 18 | 19 | obj1 = new Object(); 20 | obj1.food = "cake"; 21 | obj1.desert = "pie"; 22 | 23 | // 42-tiny-js change begin ---> 24 | // as of version 0.9.9 clone() has been removed 25 | //obj2 = obj1.clone(); 26 | // alternativly we can use: 27 | obj2 = JSON.parse(JSON.stringify(obj1)); 28 | //<--- 42-tiny-js change end 29 | obj2.food = "kittens"; 30 | 31 | result = foo.length==13 && foo.indexOf("bar")==4 && foo.substring(8,13)=="stuff" && parsed==42 && 32 | // 42-tiny-js change begin ---> 33 | // in 42tiny-js the Integer-Objecte will be removed 34 | // Integer.valueOf can be replaced by String.charCodeAt 35 | // Integer.valueOf(aChar)==65 && obj1.food=="cake" && obj2.desert=="pie"; 36 | aChar.charCodeAt()==65 && obj1.food=="cake" && obj2.desert=="pie"; 37 | //<--- 42-tiny-js change end 38 | -------------------------------------------------------------------------------- /tests/test019.js: -------------------------------------------------------------------------------- 1 | // built-in functions 2 | 3 | foo = "foo bar stuff"; 4 | r = Math.rand(); 5 | 6 | parsed = Integer.parseInt("42"); 7 | 8 | aStr = "ABCD"; 9 | aChar = aStr.charAt(0); 10 | 11 | obj1 = new Object(); 12 | obj1.food = "cake"; 13 | obj1.desert = "pie"; 14 | 15 | obj2 = obj1.clone(); 16 | obj2.food = "kittens"; 17 | 18 | result = foo.length==13 && foo.indexOf("bar")==4 && foo.substring(8,13)=="stuff" && parsed==42 && 19 | Integer.valueOf(aChar)==65 && obj1.food=="cake" && obj2.desert=="pie"; 20 | -------------------------------------------------------------------------------- /tests/test020.js: -------------------------------------------------------------------------------- 1 | // Test reported by sterowang, Variable attribute defines conflict with function. 2 | /* 3 | What steps will reproduce the problem? 4 | 1. function a (){}; 5 | 2. b = {}; 6 | 3. b.a = {}; 7 | 4. a(); 8 | 9 | What is the expected output? What do you see instead? 10 | Function "a" should be called. But the error message "Error Expecting 'a' 11 | to be a function at (line: 1, col: 1)" received. 12 | 13 | What version of the product are you using? On what operating system? 14 | Version 1.6 is used on Cent OS 5.4 15 | 16 | 17 | Please provide any additional information below. 18 | When using dump() to show symbols, found the function "a" is reassigned to 19 | "{}" by "b.a = {};" call. 20 | */ 21 | 22 | function a (){}; 23 | b = {}; 24 | b.a = {}; 25 | a(); 26 | 27 | result = 1; 28 | -------------------------------------------------------------------------------- /tests/test021.42.js: -------------------------------------------------------------------------------- 1 | /* Javascript eval */ 2 | 3 | // 42-tiny-js change begin ---> 4 | // in JavaScript eval is not JSON.parse 5 | // use parentheses or JSON.parse instead 6 | //myfoo = eval("{ foo: 42 }"); 7 | myfoo = eval("("+"{ foo: 42 }"+")"); 8 | //<--- 42-tiny-js change end 9 | 10 | result = eval("4*10+2")==42 && myfoo.foo==42; 11 | -------------------------------------------------------------------------------- /tests/test021.js: -------------------------------------------------------------------------------- 1 | /* Javascript eval */ 2 | 3 | myfoo = eval("{ foo: 42 }"); 4 | 5 | result = eval("4*10+2")==42 && myfoo.foo==42; 6 | -------------------------------------------------------------------------------- /tests/test022.42.js: -------------------------------------------------------------------------------- 1 | /* Javascript eval */ 2 | 3 | mystructure = { a:39, b:3, addStuff : function(c,d) { return c+d; } }; 4 | 5 | mystring = JSON.stringify(mystructure, undefined); 6 | 7 | // 42-tiny-js change begin ---> 8 | // in JavaScript eval is not JSON.parse 9 | // use parentheses or JSON.parse instead 10 | //mynewstructure = eval(mystring); 11 | mynewstructure = eval("("+mystring+")"); 12 | mynewstructure2 = JSON.parse(mystring); 13 | //<--- 42-tiny-js change end 14 | 15 | result = mynewstructure.addStuff(mynewstructure.a, mynewstructure.b) == 42 && mynewstructure2.addStuff(mynewstructure2.a, mynewstructure2.b) == 42; 16 | -------------------------------------------------------------------------------- /tests/test022.js: -------------------------------------------------------------------------------- 1 | /* Javascript eval */ 2 | 3 | mystructure = { a:39, b:3, addStuff : function(c,d) { return c+d; } }; 4 | 5 | mystring = JSON.stringify(mystructure, undefined); 6 | 7 | mynewstructure = eval(mystring); 8 | 9 | result = mynewstructure.addStuff(mynewstructure.a, mynewstructure.b); 10 | -------------------------------------------------------------------------------- /tests/test023.js: -------------------------------------------------------------------------------- 1 | // mikael.kindborg@mobilesorcery.com - Function symbol is evaluated in bracket-less body of false if-statement 2 | var foo; // a var is only created automated by assignment 3 | 4 | if (foo !== undefined) foo(); 5 | 6 | result = 1; 7 | -------------------------------------------------------------------------------- /tests/test024.js: -------------------------------------------------------------------------------- 1 | /* Mandelbrot! */ 2 | 3 | X1 = -2.0; 4 | Y1 = -2.0; 5 | X2 = 2.0; 6 | Y2 = 2.0; 7 | PX = 32; 8 | PY = 32; 9 | 10 | 11 | lines = []; 12 | for (y=0;y 6 | // in JavaScript Array.prototype.contains is not defined 7 | // use Array.prototype.includes instead 8 | //myfoo = eval("{ foo: 42 }"); 9 | myfoo = eval("(" + "{ foo: 42 }" + ")"); 10 | //<--- 42-tiny-js change end 11 | result = a.includes(1) && !a.includes(42) && b.includes("cheese") && !b.includes("eggs"); 12 | -------------------------------------------------------------------------------- /tests/test028.js: -------------------------------------------------------------------------------- 1 | // test for array contains 2 | var a = [1,2,4,5,7]; 3 | var b = ["bread","cheese","sandwich"]; 4 | 5 | result = a.contains(1) && !a.contains(42) && b.contains("cheese") && !b.contains("eggs"); 6 | -------------------------------------------------------------------------------- /tests/test029.js: -------------------------------------------------------------------------------- 1 | // test for array remove 2 | var a = [1,2,4,5,7]; 3 | 4 | a.remove(2); 5 | a.remove(5); 6 | 7 | result = a.length==3 && a[0]==1 && a[1]==4 && a[2]==7; 8 | -------------------------------------------------------------------------------- /tests/test030.js: -------------------------------------------------------------------------------- 1 | // test for array join 2 | var a = [1,2,4,5,7]; 3 | 4 | result = a.join(",")=="1,2,4,5,7"; 5 | -------------------------------------------------------------------------------- /tests/test031.js: -------------------------------------------------------------------------------- 1 | // test for string split 2 | var b = "1,4,7"; 3 | var a = b.split(","); 4 | 5 | result = a.length==3 && a[0]==1 && a[1]==4 && a[2]==7; 6 | -------------------------------------------------------------------------------- /tests/test032.42.js: -------------------------------------------------------------------------------- 1 | function Foo() { 2 | //this.__proto__ = Foo.prototype; 3 | } 4 | Foo.prototype = { value : function() { return this.x + this.y; } }; 5 | 6 | var a = { __proto__ : Foo.prototype, x: 1, y: 2 }; 7 | var b = new Foo(); 8 | b.x = 2; 9 | b.y = 3; 10 | 11 | var result1 = a.value(); 12 | var result2 = b.value(); 13 | result = result1==3 && result2==5; 14 | -------------------------------------------------------------------------------- /tests/test032.js: -------------------------------------------------------------------------------- 1 | var Foo = { 2 | value : function() { return this.x + this.y; } 3 | }; 4 | 5 | var a = { prototype: Foo, x: 1, y: 2 }; 6 | var b = new Foo(); 7 | b.x = 2; 8 | b.y = 3; 9 | 10 | var result1 = a.value(); 11 | var result2 = b.value(); 12 | result = result1==3 && result2==5; 13 | -------------------------------------------------------------------------------- /tests/test033.js: -------------------------------------------------------------------------------- 1 | // test for shift 2 | var a = (2<<2); 3 | var b = (16>>3); 4 | var c = (-1 >>> 16); 5 | result = a==8 && b==2 && c == 0xFFFF; 6 | -------------------------------------------------------------------------------- /tests/test034.js: -------------------------------------------------------------------------------- 1 | // test for ternary 2 | 3 | result = (true?3:4)==3 && (false?5:6)==6; 4 | -------------------------------------------------------------------------------- /tests/test035.js: -------------------------------------------------------------------------------- 1 | function Person(name) { 2 | this.name = name; 3 | this.kill = function() { this.name += " is dead"; }; 4 | } 5 | 6 | var a = new Person("Kenny"); 7 | a.kill(); 8 | result = a.name == "Kenny is dead"; 9 | 10 | -------------------------------------------------------------------------------- /tests/test036.js: -------------------------------------------------------------------------------- 1 | // the 'lf' in the printf caused issues writing doubles on some compilers 2 | var a=5.0/10.0*100.0; 3 | var b=5.0*110.0; 4 | var c=50.0/10.0; 5 | a.dump(); 6 | b.dump(); 7 | c.dump(); 8 | result = a==50 && b==550 && c==5; 9 | 10 | -------------------------------------------------------------------------------- /time_logger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 42TinyJS 3 | * 4 | * A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine 5 | * 6 | * Authored By Armin Diedering 7 | * 8 | * Copyright (C) 2010-2025 ardisoft 9 | * 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 12 | * this software and associated documentation files (the "Software"), to deal in 13 | * the Software without restriction, including without limitation the rights to 14 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 15 | * of the Software, and to permit persons to whom the Software is furnished to do 16 | * so, subject to the following conditions: 17 | 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | */ 29 | 30 | 31 | #ifndef time_logger_h__ 32 | #define time_logger_h__ 33 | #if WITH_TIME_LOGGER 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | class TimeLogger { 42 | public: 43 | TimeLogger(const char *Name, bool Start=false, const char *extName=0) 44 | : 45 | name(Name), start_time(std::chrono::high_resolution_clock::now()), sum_time(0), calls(0) { 46 | if (Start) start_time = std::chrono::high_resolution_clock::now(); 47 | if(extName) name = name + "[" + extName + "]"; 48 | } 49 | TimeLogger(const char *Name, const char *extName, bool Start=false) 50 | : 51 | name(Name), start_time(), sum_time(0), calls(0) { 52 | if (Start) start_time = std::chrono::high_resolution_clock::now(); 53 | if (extName) name = name + "[" + extName + "]"; 54 | } 55 | ~TimeLogger() { 56 | printLog(); 57 | } 58 | void startTimer() { 59 | start_time = std::chrono::high_resolution_clock::now(); 60 | } 61 | void stopTimer() { 62 | if(!start_time.time_since_epoch().count()) return; 63 | sum_time += std::chrono::high_resolution_clock::now() - start_time; 64 | calls++; 65 | start_time = std::chrono::high_resolution_clock::time_point(); 66 | } 67 | void printLog() { 68 | if(start_time.time_since_epoch().count()) stopTimer(); 69 | if (calls >= 1) { 70 | std::cout << "Timer(" << name << ") = " 71 | << std::chrono::duration_cast(sum_time).count() << "." 72 | << std::setfill('0') << std::setw(6) << std::chrono::duration_cast(sum_time % std::chrono::seconds(1)).count() << std::setw(1) 73 | << " sec"; 74 | if (calls > 1) 75 | std::cout << " (called " << calls << "times) -> " << std::chrono::duration_cast(sum_time % std::chrono::seconds(1)).count() << " microsec per call"; 76 | std::cout << std::endl; 77 | } 78 | calls = 0; sum_time = sum_time.zero(); 79 | } 80 | private: 81 | std::string name; 82 | std::chrono::high_resolution_clock::time_point start_time; 83 | std::chrono::high_resolution_clock::duration sum_time; 84 | uint32_t calls; 85 | }; 86 | 87 | class _TimeLoggerHelper { 88 | public: 89 | _TimeLoggerHelper(TimeLogger &Tl) : tl(Tl) { tl.startTimer(); } 90 | ~_TimeLoggerHelper() { tl.stopTimer(); } 91 | private: 92 | TimeLogger &tl; 93 | }; 94 | # define TimeLoggerCreate(a, ...) TimeLogger a##_TimeLogger(#a,##__VA_ARGS__) 95 | # define TimeLoggerStart(a) a##_TimeLogger.startTimer() 96 | # define TimeLoggerStop(a) a##_TimeLogger.stopTimer() 97 | # define TimeLoggerLogprint(a) a##_TimeLogger.printLog() 98 | # define TimeLoggerHelper(a) _TimeLoggerHelper a##_helper(a##_TimeLogger) 99 | #else /* _DEBUG */ 100 | # define TimeLoggerCreate(...) 101 | # define TimeLoggerStart(...) do{}while(0) 102 | # define TimeLoggerStop(...) do{}while(0) 103 | # define TimeLoggerLogprint(a) do{}while(0) 104 | # define TimeLoggerHelper(a) do{}while(0) 105 | #endif /* _DEBUG */ 106 | 107 | 108 | 109 | #endif // time_logger_h__ 110 | -------------------------------------------------------------------------------- /tiny-js.2017.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 15 3 | VisualStudioVersion = 15.0.28307.2092 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Script", "Script.2017.vcxproj", "{70D538BA-867B-4564-8DEE-F2C78C5AD4C8}" 6 | EndProject 7 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib-tiny-js", "lib-tiny-js.2017.vcxproj", "{9751C465-0294-43CD-A5D9-BD038ABA3961}" 8 | EndProject 9 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "run_tests", "run_tests.2017.vcxproj", "{C6C6CD82-1400-464C-9B80-E15450CFDD18}" 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Debug|x64 = Debug|x64 15 | Release|Win32 = Release|Win32 16 | Release|x64 = Release|x64 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Debug|Win32.ActiveCfg = Debug|Win32 20 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Debug|Win32.Build.0 = Debug|Win32 21 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Debug|x64.ActiveCfg = Debug|x64 22 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Debug|x64.Build.0 = Debug|x64 23 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Release|Win32.ActiveCfg = Release|Win32 24 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Release|Win32.Build.0 = Release|Win32 25 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Release|x64.ActiveCfg = Release|x64 26 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Release|x64.Build.0 = Release|x64 27 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Debug|Win32.ActiveCfg = Debug|Win32 28 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Debug|Win32.Build.0 = Debug|Win32 29 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Debug|x64.ActiveCfg = Debug|x64 30 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Debug|x64.Build.0 = Debug|x64 31 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Release|Win32.ActiveCfg = Release|Win32 32 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Release|Win32.Build.0 = Release|Win32 33 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Release|x64.ActiveCfg = Release|x64 34 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Release|x64.Build.0 = Release|x64 35 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Debug|Win32.ActiveCfg = Debug|Win32 36 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Debug|Win32.Build.0 = Debug|Win32 37 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Debug|x64.ActiveCfg = Debug|x64 38 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Debug|x64.Build.0 = Debug|x64 39 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Release|Win32.ActiveCfg = Release|Win32 40 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Release|Win32.Build.0 = Release|Win32 41 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Release|x64.ActiveCfg = Release|x64 42 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Release|x64.Build.0 = Release|x64 43 | EndGlobalSection 44 | GlobalSection(SolutionProperties) = preSolution 45 | HideSolutionNode = FALSE 46 | EndGlobalSection 47 | EndGlobal 48 | -------------------------------------------------------------------------------- /tiny-js.2022.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 17 3 | VisualStudioVersion = 17.9.34723.18 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Script", "Script.2022.vcxproj", "{70D538BA-867B-4564-8DEE-F2C78C5AD4C8}" 6 | EndProject 7 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib-tiny-js", "lib-tiny-js.2022.vcxproj", "{9751C465-0294-43CD-A5D9-BD038ABA3961}" 8 | EndProject 9 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "run_tests", "run_tests.2022.vcxproj", "{C6C6CD82-1400-464C-9B80-E15450CFDD18}" 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Debug|x64 = Debug|x64 15 | Release|Win32 = Release|Win32 16 | Release|x64 = Release|x64 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Debug|Win32.ActiveCfg = Debug|Win32 20 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Debug|Win32.Build.0 = Debug|Win32 21 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Debug|x64.ActiveCfg = Debug|x64 22 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Debug|x64.Build.0 = Debug|x64 23 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Release|Win32.ActiveCfg = Release|Win32 24 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Release|Win32.Build.0 = Release|Win32 25 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Release|x64.ActiveCfg = Release|x64 26 | {70D538BA-867B-4564-8DEE-F2C78C5AD4C8}.Release|x64.Build.0 = Release|x64 27 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Debug|Win32.ActiveCfg = Debug|Win32 28 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Debug|Win32.Build.0 = Debug|Win32 29 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Debug|x64.ActiveCfg = Debug|x64 30 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Debug|x64.Build.0 = Debug|x64 31 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Release|Win32.ActiveCfg = Release|Win32 32 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Release|Win32.Build.0 = Release|Win32 33 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Release|x64.ActiveCfg = Release|x64 34 | {9751C465-0294-43CD-A5D9-BD038ABA3961}.Release|x64.Build.0 = Release|x64 35 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Debug|Win32.ActiveCfg = Debug|Win32 36 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Debug|Win32.Build.0 = Debug|Win32 37 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Debug|x64.ActiveCfg = Debug|x64 38 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Debug|x64.Build.0 = Debug|x64 39 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Release|Win32.ActiveCfg = Release|Win32 40 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Release|Win32.Build.0 = Release|Win32 41 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Release|x64.ActiveCfg = Release|x64 42 | {C6C6CD82-1400-464C-9B80-E15450CFDD18}.Release|x64.Build.0 = Release|x64 43 | EndGlobalSection 44 | GlobalSection(SolutionProperties) = preSolution 45 | HideSolutionNode = FALSE 46 | EndGlobalSection 47 | EndGlobal 48 | --------------------------------------------------------------------------------