diff --git a/csrc/addon.cc b/csrc/addon.cc index 7712b72..5590fc4 100644 --- a/csrc/addon.cc +++ b/csrc/addon.cc @@ -31,7 +31,8 @@ NAN_METHOD(convert) { reinterpret_cast(input_data), input_length, reinterpret_cast(output_data), &actual_output_length )) { - Nan::ThrowError(Nan::Error("Could not convert the given font.")); + free(output_data); + Nan::ThrowError(Nan::Error("E_CONVERT_ERROR")); return; } diff --git a/csrc/fallback.cc b/csrc/fallback.cc index 0dfe3b0..e070220 100644 --- a/csrc/fallback.cc +++ b/csrc/fallback.cc @@ -22,16 +22,19 @@ int convert(int inputDataAddress, int inputLength, int outputSizePtrAddress) { uint8_t* outputData = reinterpret_cast(calloc(outputSize, sizeof(uint8_t))); - if(!woff2::ConvertTTFToWOFF2( reinterpret_cast(inputData), inputLength, outputData, &outputSize )) { - // throw an error + outputData = reinterpret_cast(realloc(outputData, 0)); + *outputSizePtr = 0; + return reinterpret_cast(outputData); } + outputData = reinterpret_cast(realloc(outputData, outputSize)); + *outputSizePtr = outputSize; return reinterpret_cast(outputData); diff --git a/jssrc/index.js b/jssrc/index.js index 2331edd..3adcd2f 100644 --- a/jssrc/index.js +++ b/jssrc/index.js @@ -1,31 +1,39 @@ +import { YError } from 'yerror'; import theTTFToWOFF2Module from './ttf2woff2.cjs'; export default function ttf2woff2(inputContent) { // Prepare input const inputBuffer = theTTFToWOFF2Module._malloc(inputContent.length + 1); - const outputSizePtr = theTTFToWOFF2Module._malloc(4); // eslint-disable-line + const outputSizePtr = theTTFToWOFF2Module._malloc(4); let outputBufferPtr; let outputSize; let outputContent; theTTFToWOFF2Module.writeArrayToMemory(inputContent, inputBuffer); - // Run - outputBufferPtr = theTTFToWOFF2Module.convert( - inputBuffer, - inputContent.length, - outputSizePtr, - ); + try { + // Run + outputBufferPtr = theTTFToWOFF2Module.convert( + inputBuffer, + inputContent.length, + outputSizePtr, + ); - // Retrieve output - outputSize = theTTFToWOFF2Module.getValue(outputSizePtr, 'i32'); - outputContent = Buffer.alloc(outputSize); + // Retrieve output + outputSize = theTTFToWOFF2Module.getValue(outputSizePtr, 'i32'); + outputContent = Buffer.alloc(outputSize); - for (let i = 0; i < outputSize; i++) { - outputContent[i] = theTTFToWOFF2Module.getValue(outputBufferPtr + i, 'i8'); - } + for (let i = 0; i < outputSize; i++) { + outputContent[i] = theTTFToWOFF2Module.getValue(outputBufferPtr + i, 'i8'); + } + + if (outputSize === 0) { + throw new YError('E_CONVERT_ERROR'); + } - theTTFToWOFF2Module.freePtrs(outputBufferPtr, outputSizePtr); + } finally { + theTTFToWOFF2Module.freePtrs(outputBufferPtr, outputSizePtr); + } return outputContent; }; diff --git a/jssrc/ttf2woff2.wasm b/jssrc/ttf2woff2.wasm index 696c70e..4fd9fa9 100755 Binary files a/jssrc/ttf2woff2.wasm and b/jssrc/ttf2woff2.wasm differ diff --git a/package.json b/package.json index d447b07..78271c2 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,8 @@ "configure": "node-gyp configure", "cover": "npm run jest -- --coverage", "cz": "env NODE_ENV=${NODE_ENV:-cli} git cz", - "emcc": "miniquery -p \"targets.#.sources.#\" ./binding.gyp | grep -v \"csrc/addon.cc\" | xargs emcc --bind -o jssrc/ttf2woff2.cjs -O2 -s \"TOTAL_MEMORY=536870912\" -s \"ALLOW_MEMORY_GROWTH=1\" -s BINARYEN_ASYNC_COMPILATION=0 -s EXPORTED_FUNCTIONS=[\"_malloc\"] -s 'EXPORTED_RUNTIME_METHODS=[\"getValue\", \"writeArrayToMemory\"]' -s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 --post-js jssrc/post.js csrc/fallback.cc", - "emcc-debug": "miniquery -p \"targets.#.sources.#\" ./binding.gyp | grep -v \"csrc/addon.cc\" | xargs emcc --bind -o jssrc/ttf2woff2.cjs -s \"ALLOW_MEMORY_GROWTH=1\" -s \"ASSERTIONS=1\" -s BINARYEN_ASYNC_COMPILATION=0 -s EXPORTED_FUNCTIONS=[\"_malloc\"] -s 'EXPORTED_RUNTIME_METHODS=[\"getValue\", \"writeArrayToMemory\"]' -s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 --post-js jssrc/post.js csrc/fallback.cc", + "emcc": "miniquery -p \"targets.#.sources.#\" ./binding.gyp | grep -v \"csrc/addon.cc\" | xargs docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk emcc --bind -o jssrc/ttf2woff2.cjs -O2 -s \"TOTAL_MEMORY=536870912\" -s \"ALLOW_MEMORY_GROWTH=1\" -s BINARYEN_ASYNC_COMPILATION=0 -s EXPORTED_FUNCTIONS=[\"_malloc\"] -s 'EXPORTED_RUNTIME_METHODS=[\"getValue\", \"writeArrayToMemory\"]' -s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 --post-js jssrc/post.js csrc/fallback.cc", + "emcc-debug": "miniquery -p \"targets.#.sources.#\" ./binding.gyp | grep -v \"csrc/addon.cc\" | xargs docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk emcc --bind -o jssrc/ttf2woff2.cjs -s \"ALLOW_MEMORY_GROWTH=1\" -s \"ASSERTIONS=1\" -s BINARYEN_ASYNC_COMPILATION=0 -s EXPORTED_FUNCTIONS=[\"_malloc\"] -s 'EXPORTED_RUNTIME_METHODS=[\"getValue\", \"writeArrayToMemory\"]' -s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 --post-js jssrc/post.js csrc/fallback.cc", "format": "npm run prettier", "install": "((node-gyp configure && node-gyp build) > builderror.log) || (exit 0)", "jest": "NODE_OPTIONS=--experimental-vm-modules NODE_ENV=test jest", diff --git a/src/tests.test.ts b/src/tests.test.ts index b9e6125..2529aa0 100755 --- a/src/tests.test.ts +++ b/src/tests.test.ts @@ -1,5 +1,6 @@ import { describe, test, expect, jest } from '@jest/globals'; import { readFile } from 'node:fs/promises'; +import { YError } from 'yerror'; describe('ttf2woff2', () => { test('should work from the main endpoint', async () => { @@ -24,7 +25,19 @@ describe('ttf2woff2', () => { expect(outputContent).toEqual(await readFile('fixtures/iconsfont.woff2')); }); - test('should work from the emscripten endpoint', async () => { + test('should well fail from the native build', async () => { + const ttf2woff2 = (await import('bindings')).default('addon.node').convert; + const inputContent = Buffer.alloc(2 ** 32, 0xff); + + try { + ttf2woff2(inputContent); + throw new YError('E_UNEXPECTED_SUCCESS'); + } catch (err) { + expect(err).toMatchInlineSnapshot(`[Error: E_CONVERT_ERROR]`); + } + }); + + test('should work from the Emscripten endpoint', async () => { jest.setTimeout(5000); const ttf2woff2 = (await import('../jssrc/index.js')).default; @@ -35,4 +48,18 @@ describe('ttf2woff2', () => { expect(outputContent[1071]).toEqual(0); expect(outputContent).toEqual(await readFile('fixtures/iconsfont.woff2')); }); + + test('should well fail from the Emscripten build', async () => { + jest.setTimeout(5000); + + const ttf2woff2 = (await import('../jssrc/index.js')).default; + const inputContent = Buffer.alloc(512, 0xff); + + try { + ttf2woff2(inputContent); + throw new YError('E_UNEXPECTED_SUCCESS'); + } catch (err) { + expect(err).toMatchInlineSnapshot(`[YError: E_CONVERT_ERROR (): E_CONVERT_ERROR]`); + } + }); });