diff --git a/.eslintignore b/.eslintignore index a0a1b71cd..c75e3c7cc 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,4 @@ -node_modules/* +node_modules dist/* make-it/objs/* env/* diff --git a/source/core/library_coreHelpers.js b/source/core/library_coreHelpers.js index 5c64e2ef1..ed9515796 100644 --- a/source/core/library_coreHelpers.js +++ b/source/core/library_coreHelpers.js @@ -3,6 +3,9 @@ var coreHelpersCAPI = { jsExecutionContextFPSync: function () { Module.coreHelpers.jsExecutionContextFPSync.apply(undefined, arguments); + }, + jsSystemLogging_WriteMessageUTF8: function () { + Module.coreHelpers.jsSystemLogging_WriteMessageUTF8.apply(undefined, arguments); } }; diff --git a/source/core/module_coreHelpers.js b/source/core/module_coreHelpers.js index e4265b556..365c12e3e 100644 --- a/source/core/module_coreHelpers.js +++ b/source/core/module_coreHelpers.js @@ -23,6 +23,29 @@ var assignCoreHelpers; fpSync(fpString); }; + Module.coreHelpers.jsSystemLogging_WriteMessageUTF8 = function ( + messageTypeRef, messageDataRef, + severityTypeRef, severityDataRef) { + var messageValueRef = Module.eggShell.createValueRef(messageTypeRef, messageDataRef); + var severityValueRef = Module.eggShell.createValueRef(severityTypeRef, severityDataRef); + var message = Module.eggShell.readString(messageValueRef); + var severity = Module.eggShell.readDouble(severityValueRef); + switch (severity) { + case 0: + console.error(message); + break; + case 1: + console.warn(message); + break; + case 2: + console.info(message); + break; + default: + console.log(message); + break; + } + }; + publicAPI.coreHelpers.setFPSyncFunction = function (fn) { if (typeof fn !== 'function') { throw new Error('FPSync must be a callable function'); diff --git a/source/io/FileIO.cpp b/source/io/FileIO.cpp index 26d14a9e5..3eab216ea 100644 --- a/source/io/FileIO.cpp +++ b/source/io/FileIO.cpp @@ -45,6 +45,14 @@ namespace Vireo { +#if kVireoOS_emscripten +extern "C" { + extern void jsSystemLogging_WriteMessageUTF8( + TypeRef messageType, StringRef * message, + TypeRef severityType, Int32 * severity); +} +#endif + typedef Int32 FileHandle; #ifdef VIREO_FILESYSTEM @@ -383,6 +391,31 @@ VIREO_FUNCTION_SIGNATURE2(Println, StaticType, void) } #endif //------------------------------------------------------------ +#if kVireoOS_emscripten +struct SystemLogging_WriteMessageUTF8ParamBlock : InstructionCore +{ + _ParamDef(StringRef, Ignored0In); + _ParamDef(StringRef, Ignored1In); + _ParamDef(StringRef, MessageIn); + _ParamDef(Int32, SeverityIn); + _ParamDef(ErrorCluster, ErrorInOut); + NEXT_INSTRUCTION_METHOD() +}; + +// An instruction to enable the Write to System Log VI which uses an SLI call to SystemLogging_WriteMessageUTF8 +VIREO_FUNCTION_SIGNATURET(SystemLogging_WriteMessageUTF8, SystemLogging_WriteMessageUTF8ParamBlock) +{ + TypeRef typeRefInt32 = TypeManagerScope::Current()->FindType("Int32"); + + if (!_Param(ErrorInOut).status) { + jsSystemLogging_WriteMessageUTF8( + _Param(MessageIn)->Type(), _ParamPointer(MessageIn), + typeRefInt32, _ParamPointer(SeverityIn)); + } + return _NextInstruction(); +} +#endif +//------------------------------------------------------------ DEFINE_VIREO_BEGIN(FileSystem) // Types DEFINE_VIREO_TYPE(FileHandle, "Int32") @@ -396,6 +429,10 @@ DEFINE_VIREO_BEGIN(FileSystem) DEFINE_VIREO_FUNCTION(Printf, "p(i(VarArgCount)i(String)i(StaticTypeAndData))") #endif //-------- +#if kVireoOS_emscripten + DEFINE_VIREO_FUNCTION(SystemLogging_WriteMessageUTF8, "p(i(.String) i(.String) i(.String) i(.Int32) io(ErrorCluster))") +#endif + //-------- #ifdef VIREO_FILESYSTEM DEFINE_VIREO_FUNCTION(FileOpen, "p(i(String)i(Int32)i(Int32)o(FileHandle))") DEFINE_VIREO_FUNCTION(FileSize, "p(i(FileHandle)o(Int32))") diff --git a/test-it/karma/fixtures/systemlogging/SystemLogging.via b/test-it/karma/fixtures/systemlogging/SystemLogging.via new file mode 100644 index 000000000..058bd05f7 --- /dev/null +++ b/test-it/karma/fixtures/systemlogging/SystemLogging.via @@ -0,0 +1,18 @@ +define(MyVI dv(VirtualInstrument ( + Locals: c( + e(c( + e(.Boolean status) + e(.Int32 code) + e(.String source) + ) error) + e(.String ignored1) + e(.String ignored2) + e(.String message) + e(.Int32 severity) + ) + clump ( + SystemLogging_WriteMessageUTF8(ignored1 ignored2 message severity error) + ) +) ) ) + +enqueue(MyVI) diff --git a/test-it/karma/systemlogging/SystemLogging.Test.js b/test-it/karma/systemlogging/SystemLogging.Test.js new file mode 100644 index 000000000..ce08d02c7 --- /dev/null +++ b/test-it/karma/systemlogging/SystemLogging.Test.js @@ -0,0 +1,109 @@ +describe('Performing a system log', function () { + 'use strict'; + // Reference aliases + const vireoHelpers = window.vireoHelpers; + const vireoRunner = window.testHelpers.vireoRunner; + const fixtures = window.testHelpers.fixtures; + let vireo; + + const systemLoggingViaUrl = fixtures.convertToAbsoluteFromFixturesDir('systemlogging/SystemLogging.via'); + + beforeAll(function (done) { + fixtures.preloadAbsoluteUrls([ + systemLoggingViaUrl + ], done); + }); + + beforeEach(async function () { + // TODO mraj create shared vireo instances to improve test perf https://github.com/ni/VireoSDK/issues/163 + vireo = await vireoHelpers.createInstance(); + spyOn(console, 'error'); + spyOn(console, 'warn'); + spyOn(console, 'info'); + spyOn(console, 'log'); + }); + + it('with error severity calls console error', async function () { + const runSlicesAsync = vireoRunner.rebootAndLoadVia(vireo, systemLoggingViaUrl); + const viPathParser = vireoRunner.createVIPathParser(vireo, 'MyVI'); + const viPathWriter = vireoRunner.createVIPathWriter(vireo, 'MyVI'); + + viPathWriter('message', 'this should be an error'); + viPathWriter('severity', 0); + const {rawPrint, rawPrintError} = await runSlicesAsync(); + + expect(console.error).toHaveBeenCalledTimes(1); + expect(console.error).toHaveBeenCalledWith('this should be an error'); + expect(console.warn).not.toHaveBeenCalled(); + expect(console.info).not.toHaveBeenCalled(); + expect(console.log).not.toHaveBeenCalled(); + expect(rawPrint).toBeEmptyString(); + expect(rawPrintError).toBeEmptyString(); + expect(viPathParser('error.status')).toBeFalse(); + expect(viPathParser('error.code')).toBe(0); + expect(viPathParser('error.source')).toBeEmptyString(); + }); + + it('with warn severity calls console warn', async function () { + const runSlicesAsync = vireoRunner.rebootAndLoadVia(vireo, systemLoggingViaUrl); + const viPathParser = vireoRunner.createVIPathParser(vireo, 'MyVI'); + const viPathWriter = vireoRunner.createVIPathWriter(vireo, 'MyVI'); + + viPathWriter('message', 'this should be a warning'); + viPathWriter('severity', 1); + const {rawPrint, rawPrintError} = await runSlicesAsync(); + + expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalledTimes(1); + expect(console.warn).toHaveBeenCalledWith('this should be a warning'); + expect(console.info).not.toHaveBeenCalled(); + expect(console.log).not.toHaveBeenCalled(); + expect(rawPrint).toBeEmptyString(); + expect(rawPrintError).toBeEmptyString(); + expect(viPathParser('error.status')).toBeFalse(); + expect(viPathParser('error.code')).toBe(0); + expect(viPathParser('error.source')).toBeEmptyString(); + }); + + it('with info severity calls console info', async function () { + const runSlicesAsync = vireoRunner.rebootAndLoadVia(vireo, systemLoggingViaUrl); + const viPathParser = vireoRunner.createVIPathParser(vireo, 'MyVI'); + const viPathWriter = vireoRunner.createVIPathWriter(vireo, 'MyVI'); + + viPathWriter('message', 'this should be an info'); + viPathWriter('severity', 2); + const {rawPrint, rawPrintError} = await runSlicesAsync(); + + expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + expect(console.info).toHaveBeenCalledTimes(1); + expect(console.info).toHaveBeenCalledWith('this should be an info'); + expect(console.log).not.toHaveBeenCalled(); + expect(rawPrint).toBeEmptyString(); + expect(rawPrintError).toBeEmptyString(); + expect(viPathParser('error.status')).toBeFalse(); + expect(viPathParser('error.code')).toBe(0); + expect(viPathParser('error.source')).toBeEmptyString(); + }); + + it('with invalid severity calls console log', async function () { + const runSlicesAsync = vireoRunner.rebootAndLoadVia(vireo, systemLoggingViaUrl); + const viPathParser = vireoRunner.createVIPathParser(vireo, 'MyVI'); + const viPathWriter = vireoRunner.createVIPathWriter(vireo, 'MyVI'); + + viPathWriter('message', 'this should be a log'); + viPathWriter('severity', 70); + const {rawPrint, rawPrintError} = await runSlicesAsync(); + + expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + expect(console.info).not.toHaveBeenCalled(); + expect(console.log).toHaveBeenCalledTimes(1); + expect(console.log).toHaveBeenCalledWith('this should be a log'); + expect(rawPrint).toBeEmptyString(); + expect(rawPrintError).toBeEmptyString(); + expect(viPathParser('error.status')).toBeFalse(); + expect(viPathParser('error.code')).toBe(0); + expect(viPathParser('error.source')).toBeEmptyString(); + }); +});