From dd1839e1f660ffb36756e618b3555330069f5f42 Mon Sep 17 00:00:00 2001 From: Devika G N <41286723+Devika-Tantry@users.noreply.github.com> Date: Thu, 24 Jun 2021 19:15:15 +0530 Subject: [PATCH] Update to emscripten 2.0.23 (#681) --- .github/workflows/build.yml | 18 +++--- .gitignore | 1 + AUTHORS | 1 + docs/Build.md | 4 +- make-it/EmMakefile | 8 +-- make-it/EmMakefile-AAL | 4 +- source/core/TypeAndDataManager.cpp | 22 +++---- source/include/TypeAndDataManager.h | 3 +- source/io/module_eggShell.js | 13 ++++ test-it/karma/publicapi/Double.Test.js | 59 ++++++------------- .../ExecuteSlicesUntilClumpsFinshed.Test.js | 12 ++-- 11 files changed, 71 insertions(+), 74 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5aeb6f662..f6f1cf982 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: # Install lint dependencies - uses: actions/setup-python@v2 with: - python-version: '3.5' + python-version: '3.7' - uses: actions/setup-node@v1 with: node-version: '12' @@ -42,7 +42,7 @@ jobs: # Install web dependencies - uses: actions/setup-python@v2 with: - python-version: '3.5' + python-version: '3.7' - run: | python -m pip install --upgrade pip pip install -r requirements.txt @@ -55,10 +55,10 @@ jobs: - run: | git clone https://github.com/juj/emsdk.git cd emsdk - git checkout 369013943283939412fb2807bb0d2ded8ebd5a9e + git checkout tags/2.0.23 - run: | - emsdk/emsdk install 1.39.5-fastcomp - emsdk/emsdk activate 1.39.5-fastcomp + emsdk/emsdk install 2.0.23 + emsdk/emsdk activate 2.0.23 - run: . emsdk/emsdk_env.sh && emcc -v # Build web @@ -110,7 +110,7 @@ jobs: - run: chocolatey install gnuwin32-coreutils.portable -y - uses: actions/setup-python@v2 with: - python-version: '3.5' + python-version: '3.7' - run: | python -m pip install --upgrade pip pip install tox @@ -118,10 +118,10 @@ jobs: - run: | git clone https://github.com/juj/emsdk.git cd emsdk - git checkout 369013943283939412fb2807bb0d2ded8ebd5a9e + git checkout tags/2.0.23 - run: | - emsdk\emsdk install 1.39.5-fastcomp - emsdk\emsdk activate 1.39.5-fastcomp + emsdk\emsdk install 2.0.23 + emsdk\emsdk activate 2.0.23 - run: emsdk\emsdk_env.ps1 && emcc -v # Build web-windows diff --git a/.gitignore b/.gitignore index 7ba080f47..9458983de 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ Vireo_VS/VireoCommandLine.sln.DotSettings.user **.opendb **.suo .vscode/ +.vs/* # Other c_cpp_properties.json diff --git a/AUTHORS b/AUTHORS index edbce21a5..3289cb1f5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -18,3 +18,4 @@ Trevor Nelligan WebSocket Devin Carr Build/Test/Deploy, Strings Sankara Muthukrishnan Waveform Trevor Chipley ASan fixes +Devika G N Emscripten tool \ No newline at end of file diff --git a/docs/Build.md b/docs/Build.md index aa140ed07..68b3eaf4d 100644 --- a/docs/Build.md +++ b/docs/Build.md @@ -47,8 +47,8 @@ The emsdk toolchain is used to cross-compile Vireo to Vireo.js to run in Node.js 3. From the cloned emsdk repository run the following commands: ```console - emsdk install 1.39.5-fastcomp - emsdk activate 1.39.5-fastcomp + emsdk install 2.0.23 + emsdk activate 2.0.23 emcc -v # should match the sdk version ``` diff --git a/make-it/EmMakefile b/make-it/EmMakefile index 671d9f256..251772985 100644 --- a/make-it/EmMakefile +++ b/make-it/EmMakefile @@ -72,7 +72,7 @@ EMCC= emcc EM_OPTFLAG = -O3 ifeq ($(BUILD), debug) - EM_OPTFLAG = -g4 -s ASSERTIONS=2 -s SAFE_HEAP=1 + EM_OPTFLAG = -g -s ASSERTIONS=2 -s SAFE_HEAP=1 endif ifeq ($(BUILD), profile) @@ -92,11 +92,11 @@ ifeq ($(TARGET), asmjs-unknown-emscripten) endif ifeq ($(TARGET), wasm32-unknown-emscripten) - TARGET_FLAG = -s WASM=1 -s BINARYEN_TRAP_MODE=js -s ALLOW_MEMORY_GROWTH=1 + TARGET_FLAG = -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 endif # NO_DYNAMIC_EXECUTION=1 Allows Vireo to be used in CSP environments where eval() is forbidden: https://github.com/kripken/emscripten/blob/master/src/settings.js#L563 -EM_OPT = $(EM_OPTFLAGS) $(TARGET_FLAG) -s NO_EXIT_RUNTIME=1 -std=c++14 -fno-exceptions -Werror --memory-init-file 0 -s NO_DYNAMIC_EXECUTION=1 -s MODULARIZE=1 -s EXPORT_NAME=VireoCreateCoreModule -s EXPORT_ES6=1 -s USE_ES6_IMPORT_META=0 --minify 0 -s NO_FILESYSTEM=1 -s ABORTING_MALLOC=0 +EM_OPT = $(EM_OPTFLAGS) $(TARGET_FLAG) -std=c++14 -fno-exceptions -Werror --memory-init-file 0 -s NO_DYNAMIC_EXECUTION=1 -s MODULARIZE=1 -s EXPORT_NAME=VireoCreateCoreModule -s EXPORT_ES6=1 -s USE_ES6_IMPORT_META=0 --minify 0 -s NO_FILESYSTEM=1 -s ABORTING_MALLOC=0 EMFLAGS = -I$(INCDIR) -DkVireoOS_emscripten $(EM_OPT) EMLIBRARY = --js-library $(CORESOURCEDIR)/library_coreHelpers.js \ --js-library $(CORESOURCEDIR)/library_eventHelpers.js \ @@ -111,7 +111,7 @@ EM_EXPORTS = -s EXPORTED_FUNCTIONS="[\ '_free' \ ]" -EM_RUNTIME_EXPORTS = -s EXTRA_EXPORTED_RUNTIME_METHODS="[\ +EM_RUNTIME_EXPORTS = -s EXPORTED_RUNTIME_METHODS="[\ 'lengthBytesUTF8', \ 'stackAlloc', \ 'stackSave', \ diff --git a/make-it/EmMakefile-AAL b/make-it/EmMakefile-AAL index 548b6f65d..4604b672a 100644 --- a/make-it/EmMakefile-AAL +++ b/make-it/EmMakefile-AAL @@ -35,7 +35,7 @@ ifeq (,$(wildcard $(ANALYSIS_WRAPPERS_SOURCE_DIRECTORY)/AnalysisWrapper*.cpp)) ANALYSIS_LIBRARY = $(OBJS)/NoAnalysisLibrary.bc $(OBJS)/NoAnalysisLibrary.bc: | no-analysis touch $(OBJS)/NoAnalysis.cpp - $(EMCC) $(EM_ANALYSIS_FLAGS) -o $@ $(OBJS)/NoAnalysis.cpp + $(EMCC) $(EM_ANALYSIS_FLAGS) -o $@ $(OBJS)/NoAnalysis.cpp -c rm $(OBJS)/NoAnalysis.cpp no-analysis:: @@ -94,7 +94,7 @@ help: EMCC= emcc EM_OPTFLAG = -Os -EM_OPT= $(EM_OPT_FLAG) -s NO_EXIT_RUNTIME=1 -fno-exceptions --memory-init-file 0 +EM_OPT= $(EM_OPT_FLAG) -s -fno-exceptions --memory-init-file 0 EMFLAGS= -I$(INCDIR) -DkVireoOS_emscripten -DVIREO_LEAN $(EM_OPT) EMLIBRARY= --js-library $(IOSOURCEDIR)/library_canvas2d.js --js-library $(IOSOURCEDIR)/library_httpClient.js EM_WRAP= --pre-js $(CORESOURCEDIR)/vireo.preamble.js --post-js $(CORESOURCEDIR)/vireo.postamble.js diff --git a/source/core/TypeAndDataManager.cpp b/source/core/TypeAndDataManager.cpp index 2f7128a4b..0013a5308 100644 --- a/source/core/TypeAndDataManager.cpp +++ b/source/core/TypeAndDataManager.cpp @@ -2637,7 +2637,8 @@ IntMax ReadIntFromMemory(TypeRef type, void* pData) case 0: value = 0; break; case 4: { Single singleVal = RoundToEven(*(Single*)pData); - if (singleVal >= std::numeric_limits::max()) + const Single intMax = static_cast(std::numeric_limits::max()); + if (singleVal >= intMax) // >= is actually correct here because Int64 max isn't representable as a single and rounds up. value = std::numeric_limits::max(); else if (singleVal <= std::numeric_limits::min()) @@ -2648,7 +2649,8 @@ IntMax ReadIntFromMemory(TypeRef type, void* pData) } case 8: { Double doubleVal = RoundToEven(*(Double*)pData); - if (doubleVal >= std::numeric_limits::max()) + const Double intMax = static_cast(std::numeric_limits::max()); + if (doubleVal >= intMax) // >= is actually correct here because Int64 max isn't representable as a double and rounds up. value = std::numeric_limits::max(); else if (doubleVal <= std::numeric_limits::min()) @@ -2845,10 +2847,10 @@ NIError WriteDoubleToMemory(TypeRef type, void* pData, const Double value) case kEncoding_S2CInt: case kEncoding_DimInt: switch (aqSize) { - case 1: *(Int8*)pData = (Int8)value; break; - case 2: *(Int16*)pData = (Int16)value; break; - case 4: *(Int32*)pData = (Int32)value; break; - case 8: *(Int64*)pData = (Int64)value; break; + case 1: *(Int8*)pData = ConvertFloatToInt(value); break; + case 2: *(Int16*)pData = ConvertFloatToInt(value); break; + case 4: *(Int32*)pData = ConvertFloatToInt(value); break; + case 8: *(Int64*)pData = ConvertFloatToInt(value); break; default: err = kNIError_kCantEncode; break; } break; @@ -2861,10 +2863,10 @@ NIError WriteDoubleToMemory(TypeRef type, void* pData, const Double value) case kEncoding_UInt: case kEncoding_Enum: switch (aqSize) { - case 1: *(UInt8*)pData = (Int8)value; break; - case 2: *(UInt16*)pData = (UInt16)value; break; - case 4: *(UInt32*)pData = (UInt32)value; break; - case 8: *(UInt64*)pData = (UInt64)value; break; + case 1: *(UInt8*)pData = ConvertFloatToInt(value); break; + case 2: *(UInt16*)pData = ConvertFloatToInt(value); break; + case 4: *(UInt32*)pData = ConvertFloatToInt(value); break; + case 8: *(UInt64*)pData = ConvertFloatToInt(value); break; default: err = kNIError_kCantEncode; break; } break; diff --git a/source/include/TypeAndDataManager.h b/source/include/TypeAndDataManager.h index ad15bd7eb..eff89be12 100644 --- a/source/include/TypeAndDataManager.h +++ b/source/include/TypeAndDataManager.h @@ -366,13 +366,14 @@ template TDest ConvertFloatToInt(TSource src) { TDest dest; + const TSource maxDestValue = static_cast(std::numeric_limits::max()); if (std::isnan(src)) { dest = std::numeric_limits::max(); } else if (std::isinf(src)) { dest = src < 0 ? std::numeric_limits::min() : std::numeric_limits::max(); } else if (src < std::numeric_limits::min()) { dest = std::numeric_limits::min(); - } else if (src > std::numeric_limits::max()) { + } else if (src > maxDestValue) { dest = std::numeric_limits::max(); } else { dest = static_cast(RoundToEven(src)); diff --git a/source/io/module_eggShell.js b/source/io/module_eggShell.js index 6b4a72616..0ea6baa43 100644 --- a/source/io/module_eggShell.js +++ b/source/io/module_eggShell.js @@ -469,6 +469,13 @@ var assignEggShell; return dimensions; }; + // Note: If you are directly writing JavaScript numbers (floating point doubles) to + // integer TypedArray views then be aware that integer TypedArray views will truncate + // overflowing values as specified in TypedArray conversion operations: + // https://tc39.es/ecma262/#table-the-typedarray-constructors + // Vireo requires that overflowing JavaScript numbers written to Vireo integers + // are saturated instead of truncated. Make sure to perform Vireo's float-to-int + // conversion algorithm in JavaScript before directly writing to integer TypeArray views. Module.eggShell.readTypedArray = publicAPI.eggShell.readTypedArray = function (valueRef) { var TypedArrayConstructor = findCompatibleTypedArrayConstructor(valueRef.typeRef); if (TypedArrayConstructor === undefined) { @@ -488,6 +495,12 @@ var assignEggShell; return (TypedArrayConstructor !== undefined && typedArrayValue instanceof TypedArrayConstructor); }; + // Note: When creating integer TypedArrays views from JavaScript numbers to write to + // Vireo using writeTypedArray be aware that integer TypedArray views will truncate + // overflowing values as specified in TypedArray conversion operations: + // https://tc39.es/ecma262/#table-the-typedarray-constructors + // Make sure to perform Vireo's float-to-int conversion algorithm in JavaScript when creating + // integer TypedArray views from JavaScript numbers to write to Vireo memory. Module.eggShell.writeTypedArray = publicAPI.eggShell.writeTypedArray = function (valueRef, typedArrayValue) { var TypedArrayConstructor = findCompatibleTypedArrayConstructor(valueRef.typeRef); if (TypedArrayConstructor === undefined || !(typedArrayValue instanceof TypedArrayConstructor)) { diff --git a/test-it/karma/publicapi/Double.Test.js b/test-it/karma/publicapi/Double.Test.js index 27df897f5..af17c163c 100644 --- a/test-it/karma/publicapi/Double.Test.js +++ b/test-it/karma/publicapi/Double.Test.js @@ -56,12 +56,6 @@ describe('The Vireo EggShell Double api can', function () { expect(readDouble(path)).toMatchIEEE754Number(initialValue); }; - // Expected coerced values of Doubles in Vireo should have the same behavior as assignment to typed arrays - // This is so a user assigning a double to a typedarray using getTypedArray will see the same effect as writing to a double using writeDouble - var expectedCoercedValue = function (TypedArrayConstructor, value) { - return (new TypedArrayConstructor([value])[0]); - }; - beforeAll(function (done) { fixtures.preloadAbsoluteUrls([ publicApiMultipleTypesViaUrl @@ -138,45 +132,26 @@ describe('The Vireo EggShell Double api can', function () { }); it('to write integer values to memory', function () { - testWriteDoubleCoerced('int8MinValue', -128, 812, expectedCoercedValue(Int8Array, 812)); - testWriteDoubleCoerced('int8MinValue', -128, -812, expectedCoercedValue(Int8Array, -812)); - testWriteDoubleCoerced('int16MinValue', -32768, 81234, expectedCoercedValue(Int16Array, 81234)); - testWriteDoubleCoerced('int16MinValue', -32768, -81234, expectedCoercedValue(Int16Array, -81234)); - testWriteDoubleCoerced('int32MinValue', -2147483648, 8123456789, expectedCoercedValue(Int32Array, 8123456789)); - testWriteDoubleCoerced('int32MinValue', -2147483648, -8123456789, expectedCoercedValue(Int32Array, -8123456789)); - testWriteDoubleCoerced('uInt8MinValue', 0, 812, expectedCoercedValue(Uint8Array, 812)); - testWriteDoubleCoerced('uInt8MinValue', 0, -812, expectedCoercedValue(Uint8Array, -812)); - testWriteDoubleCoerced('uInt16MinValue', 0, 81234, expectedCoercedValue(Uint16Array, 81234)); - testWriteDoubleCoerced('uInt16MinValue', 0, -81234, expectedCoercedValue(Uint16Array, -81234)); - testWriteDoubleCoerced('uInt32MinValue', 0, 8123456789, expectedCoercedValue(Uint32Array, 8123456789)); - testWriteDoubleCoerced('uInt32MinValue', 0, -8123456789, expectedCoercedValue(Uint32Array, -8123456789)); - - expect(expectedCoercedValue(Int8Array, 812)).toBe(44); - expect(expectedCoercedValue(Int8Array, -812)).toBe(-44); - expect(expectedCoercedValue(Int16Array, 81234)).toBe(15698); - expect(expectedCoercedValue(Int16Array, -81234)).toBe(-15698); - expect(expectedCoercedValue(Int32Array, 8123456789)).toBe(-466477803); - expect(expectedCoercedValue(Int32Array, -8123456789)).toBe(466477803); - expect(expectedCoercedValue(Uint8Array, 812)).toBe(44); - expect(expectedCoercedValue(Uint8Array, -812)).toBe(212); - expect(expectedCoercedValue(Uint16Array, 81234)).toBe(15698); - expect(expectedCoercedValue(Uint16Array, -81234)).toBe(49838); - expect(expectedCoercedValue(Uint32Array, 8123456789)).toBe(3828489493); - expect(expectedCoercedValue(Uint32Array, -8123456789)).toBe(466477803); + testWriteDoubleCoerced('int8MinValue', -128, 812, 127); + testWriteDoubleCoerced('int8MinValue', -128, -812, -128); + testWriteDoubleCoerced('int16MinValue', -32768, 81234, 32767); + testWriteDoubleCoerced('int16MinValue', -32768, -81234, -32768); + testWriteDoubleCoerced('int32MinValue', -2147483648, 8123456789, 2147483647); + testWriteDoubleCoerced('int32MinValue', -2147483648, -8123456789, -2147483648); + testWriteDoubleCoerced('uInt8MinValue', 0, 812, 255); + testWriteDoubleCoerced('uInt8MinValue', 0, -812, 0); + testWriteDoubleCoerced('uInt16MinValue', 0, 81234, 65535); + testWriteDoubleCoerced('uInt16MinValue', 0, -81234, 0); + testWriteDoubleCoerced('uInt32MinValue', 0, 8123456789, 4294967295); + testWriteDoubleCoerced('uInt32MinValue', 0, -8123456789, 0); }); it('to coerce iee754 special values to memory', function () { - testWriteDoubleCoerced('int8MinValue', -128, NaN, expectedCoercedValue(Int8Array, NaN)); - testWriteDoubleCoerced('int8MinValue', -128, Infinity, expectedCoercedValue(Int8Array, Infinity)); - testWriteDoubleCoerced('int8MinValue', -128, -Infinity, expectedCoercedValue(Int8Array, -Infinity)); - testWriteDoubleCoerced('int8MinValue', -128, -0, expectedCoercedValue(Int8Array, -0)); - testWriteDoubleCoerced('int8MinValue', -128, 0, expectedCoercedValue(Int8Array, 0)); - - expect(expectedCoercedValue(Int8Array, NaN)).toBe(0); - expect(expectedCoercedValue(Int8Array, Infinity)).toBe(0); - expect(expectedCoercedValue(Int8Array, -Infinity)).toBe(0); - expect(expectedCoercedValue(Int8Array, -0)).toBe(0); - expect(expectedCoercedValue(Int8Array, 0)).toBe(0); + testWriteDoubleCoerced('int8MinValue', -128, NaN, 127); + testWriteDoubleCoerced('int8MinValue', -128, Infinity, 127); + testWriteDoubleCoerced('int8MinValue', -128, -Infinity, -128); + testWriteDoubleCoerced('int8MinValue', -128, -0, 0); + testWriteDoubleCoerced('int8MinValue', -128, 0, 0); }); it('to write different enum values to memory', function () { diff --git a/test-it/karma/publicapi/ExecuteSlicesUntilClumpsFinshed.Test.js b/test-it/karma/publicapi/ExecuteSlicesUntilClumpsFinshed.Test.js index 34a1fae54..d1ffcb0bb 100644 --- a/test-it/karma/publicapi/ExecuteSlicesUntilClumpsFinshed.Test.js +++ b/test-it/karma/publicapi/ExecuteSlicesUntilClumpsFinshed.Test.js @@ -117,9 +117,13 @@ describe('The Vireo EggShell executeSlicesUntilClumpsFinished api', function () it('reports error when the Vireo runtime stops execution', async function () { const runSlicesAsync = vireoRunner.rebootAndLoadVia(vireo, publicApiLargeAllocationUrl); - - const {rawPrint, rawPrintError} = await runSlicesAsync(); - expect(rawPrint).toMatch(/Failed to perform allocation/); - expect(rawPrintError).toBeEmptyString(); + var exception; + try { + await runSlicesAsync(); + } catch (ex) { + exception = ex; + } + expect(exception.rawPrint).toMatch(/Failed to perform allocation/); + expect(exception.rawPrintError).toBeEmptyString(); }); });