diff --git a/.gitignore b/.gitignore
index 8d1ca1d523e79..c2bc162482f59 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,3 +50,6 @@ ipch/
*.*codeanalysis*
read.lock
fileList.bin
+
+*.js
+*.wasm
diff --git a/ACE/ACE-INSTALL.html b/ACE/ACE-INSTALL.html
index 185fe6d9d5235..e87072b692e23 100644
--- a/ACE/ACE-INSTALL.html
+++ b/ACE/ACE-INSTALL.html
@@ -284,6 +284,7 @@
Windows (including MinGW and Cygwin)
VxWorks
Android
+Emscripten WebAssembly
General Rules
@@ -1823,7 +1824,7 @@
OpenSSL. On Android, OpenSSL isn't part of the NDK Library and Android
preloads the system SSL library (either OpenSSL or BoringSSL) for the Java
Android API. This means OpenSSL MUST be statically linked to avoid
- conflicts with the almost certianly incompatible system SSL library.
+ conflicts with the almost certainly incompatible system SSL library.
To build OpenSSL for Android, please read NOTES.ANDROID
that comes
with OpenSSL's source code. The static libraries will used if the shared
@@ -1833,6 +1834,43 @@
building OpenSSL.
+
+
+
+
+NOTE: This has only been tested on Linux with NodeJS 16.18.
+
+Emscripten
+is a LLVM toolchain that allows compiling C++ to
+WebAssembly
+that can be ran on a web browser or NodeJS.
+
+Building
+
+
+ - Download and setup emscripten.
+ - Run
source emsdk_env.sh
in emsdk
.
+ - Make sure MPC is available and
MPC_ROOT
is set.
+ - Configure ACE:
+
+ $ACE_ROOT/bin/MakeProjectCreator/config/default.features
+ should contain no_cxx11=0
+ $ACE_ROOT/include/makeinclude/platform_macros.GNU
should contain
+ include $(ACE_ROOT)/include/makeinclude/platform_emscripten.GNU
+ $ACE_ROOT/ace/config.h
should contain
+ #include "config-emscripten.h"
+ cd $ACE_ROOT/ace && mwc.pl -type gnuace .
+
+
+ - Build ACE:
cd $ACE_ROOT/ace && make -j4
+
+
+Running Tests
+
+
+DOC_TEST_1=NODEJS NODEJS_OS=local ./run_test.pl -Config STATIC -Config NODEJS
+
+
diff --git a/ACE/ace/Notification_Queue.h b/ACE/ace/Notification_Queue.h
index 914904ac296fc..18749e4f2a221 100644
--- a/ACE/ace/Notification_Queue.h
+++ b/ACE/ace/Notification_Queue.h
@@ -13,6 +13,8 @@
#include "ace/Intrusive_List.h"
#include "ace/Intrusive_List_Node.h"
#include "ace/Unbounded_Queue.h"
+#include "ace/Synch_Traits.h"
+#include "ace/Thread_Mutex.h"
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
diff --git a/ACE/ace/Timer_Queue_T.inl b/ACE/ace/Timer_Queue_T.inl
index 15c0e8ef99d5f..72dc9e71e7067 100644
--- a/ACE/ace/Timer_Queue_T.inl
+++ b/ACE/ace/Timer_Queue_T.inl
@@ -1,4 +1,7 @@
// -*- C++ -*-
+
+#include "ace/Guard_T.h"
+
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
template ACE_INLINE FUNCTOR &
diff --git a/ACE/ace/config-emscripten.h b/ACE/ace/config-emscripten.h
new file mode 100644
index 0000000000000..7ec287328aaae
--- /dev/null
+++ b/ACE/ace/config-emscripten.h
@@ -0,0 +1,54 @@
+#ifndef ACE_CONFIG_EMSCRIPTEN_H
+#define ACE_CONFIG_EMSCRIPTEN_H
+
+#define ACE_EMSCRIPTEN
+
+#define ACE_HAS_CPP11
+
+// Threading
+#define ACE_MT_SAFE 1
+#define ACE_HAS_THREADS 1
+#define ACE_HAS_PTHREADS
+#define ACE_HAS_PTHREADS_UNIX98_EXT
+#define ACE_HAS_THREAD_SPECIFIC_STORAGE
+
+// Basic Types
+#define ACE_HAS_SSIZE_T
+#define ACE_HAS_WCHAR
+
+// Time
+#define ACE_HAS_POSIX_TIME
+#define ACE_LACKS_TIMESPEC_T
+#define ACE_HAS_NONCONST_SELECT_TIMEVAL
+#define ACE_HAS_VOIDPTR_GETTIMEOFDAY
+
+// Everything else
+#define ACE_HAS_UCONTEXT_T
+#define ACE_HAS_MSG
+#define ACE_HAS_CPU_SET_T
+#define ACE_LACKS_ISCTYPE
+#define ACE_HAS_STRBUF_T
+#define ACE_HAS_SOCKLEN_T
+#define ACE_LACKS_AUTO_PTR
+#define ACE_HAS_SIGINFO_T
+#define ACE_LACKS_SIGINFO_H
+#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES
+#define ACE_HAS_3_PARAM_WCSTOK
+#define ACE_LACKS_ITOW
+#define ACE_LACKS_WCSICMP
+#define ACE_LACKS_WCSNICMP
+#define ACE_HAS_DIRENT
+#define ACE_HAS_4_4BSD_SENDMSG_RECVMSG
+
+// These exist, but don't seem to work correctly
+#define ACE_LACKS_PWD_FUNCTIONS
+
+#include "config-posix.h"
+#include "config-g++-common.h"
+
+// Not supported: https://github.com/emscripten-core/emscripten/issues/18050
+#ifdef ACE_HAS_AIO_CALLS
+# undef ACE_HAS_AIO_CALLS
+#endif
+
+#endif
diff --git a/ACE/ace/os_include/sys/os_types.h b/ACE/ace/os_include/sys/os_types.h
index b179c7051ad73..9d5fe106549a2 100644
--- a/ACE/ace/os_include/sys/os_types.h
+++ b/ACE/ace/os_include/sys/os_types.h
@@ -53,7 +53,8 @@ typedef double ACE_timer_t;
#if defined (ACE_SIZEOF_LONG) && ACE_SIZEOF_LONG == 8
typedef off_t ACE_LOFF_T;
-#elif defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__APPLE__)
+#elif defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__APPLE__) || \
+ defined (ACE_EMSCRIPTEN)
typedef off_t ACE_LOFF_T;
#elif defined (__QNX__)
typedef off64_t ACE_LOFF_T;
diff --git a/ACE/bin/PerlACE/ProcessNodeJS.pm b/ACE/bin/PerlACE/ProcessNodeJS.pm
new file mode 100644
index 0000000000000..92be88dfe1188
--- /dev/null
+++ b/ACE/bin/PerlACE/ProcessNodeJS.pm
@@ -0,0 +1,21 @@
+package PerlACE::ProcessNodeJS;
+
+use strict;
+
+use PerlACE::Process;
+our @ISA = qw(PerlACE::Process);
+
+sub new {
+ my $class = shift();
+ my $name = shift();
+ my $args = shift();
+ my $node_args = shift() // '';
+
+ my $self = $class->SUPER::new("$name.js", $node_args);
+ bless($self, $class);
+ $self->IgnoreExeSubDir(1);
+ $self->{VALGRIND_CMD} = "node $node_args";
+ return $self;
+}
+
+1;
diff --git a/ACE/bin/PerlACE/Run_Test.pm b/ACE/bin/PerlACE/Run_Test.pm
index fe0bfb74aff49..ed9ddea0b2418 100644
--- a/ACE/bin/PerlACE/Run_Test.pm
+++ b/ACE/bin/PerlACE/Run_Test.pm
@@ -48,6 +48,11 @@ if ($PerlACE::Android_Test) {
require PerlACE::ProcessAndroid;
}
+$PerlACE::NodeJS_Test = $config->check_config("NODEJS");
+if ($PerlACE::NodeJS_Test) {
+ require PerlACE::ProcessNodeJS;
+}
+
# Figure out the svc.conf extension
$svcconf_ext = $ENV{'ACE_RUNTEST_SVCCONF_EXT'};
if (!defined $svcconf_ext) {
diff --git a/ACE/bin/PerlACE/TestTarget.pm b/ACE/bin/PerlACE/TestTarget.pm
index 83d1d8f91c470..7e2b2b5be4226 100644
--- a/ACE/bin/PerlACE/TestTarget.pm
+++ b/ACE/bin/PerlACE/TestTarget.pm
@@ -82,9 +82,10 @@ sub new
{
my $proto = shift;
my $class = ref ($proto) || $proto;
- my $self = {};
-
my $config_name = shift;
+
+ my $self = {config_name => $config_name};
+
bless ($self, $class);
$self->GetConfigSettings($config_name);
@@ -505,7 +506,7 @@ sub DeleteFile ($)
print STDERR "Deleting remote $file from path $newfile using $cmd\n";
}
if (system ($cmd) != 0) {
- print STDERR "ERROR executing [".$cmd."]\n";
+ print STDERR "ERROR executing [".$cmd."]\n";
}
} else {
unlink ($newfile);
@@ -523,9 +524,9 @@ sub GetFile ($)
$remote_file = $self->LocalFile($local_file);
}
if (defined $self->{GET_CMD}) {
- if (system ($self->{GET_CMD}.' '.$remote_file.' '.$local_file) != 0) {
- print STDERR "ERROR executing [".$self->{GET_CMD}." $remote_file $local_file]\n";
- }
+ if (system ($self->{GET_CMD}.' '.$remote_file.' '.$local_file) != 0) {
+ print STDERR "ERROR executing [".$self->{GET_CMD}." $remote_file $local_file]\n";
+ }
}
elsif (($remote_file ne $local_file) &&
(File::Spec->rel2abs($remote_file) ne File::Spec->rel2abs($local_file))) {
@@ -541,9 +542,9 @@ sub PutFile ($)
my $src = shift;
my $dest = $self->LocalFile ($src);
if (defined $self->{PUT_CMD}) {
- if (system ($self->{PUT_CMD}.' '.$src.' '.$dest) != 0) {
- print STDERR "ERROR executing [".$self->{PUT_CMD}." $src $dest]\n";
- }
+ if (system ($self->{PUT_CMD}.' '.$src.' '.$dest) != 0) {
+ print STDERR "ERROR executing [".$self->{PUT_CMD}." $src $dest]\n";
+ }
}
elsif (($src ne $dest) &&
(File::Spec->rel2abs($src) ne File::Spec->rel2abs($dest))) {
@@ -594,7 +595,14 @@ sub WaitForFileTimed ($)
sub CreateProcess ($)
{
my $self = shift;
- my $process = new PerlACE::Process (@_);
+
+ my $process;
+ if ($self->{config_name} eq 'NODEJS') {
+ $process = new PerlACE::ProcessNodeJS(@_);
+ } else {
+ $process = new PerlACE::Process (@_);
+ }
+
$process->Target($self);
return $process;
}
diff --git a/ACE/include/makeinclude/platform_clang_common.GNU b/ACE/include/makeinclude/platform_clang_common.GNU
index 667d394e1da0e..61992f911b3f5 100644
--- a/ACE/include/makeinclude/platform_clang_common.GNU
+++ b/ACE/include/makeinclude/platform_clang_common.GNU
@@ -9,9 +9,11 @@ ifneq ($(CROSS_COMPILE),)
CXX = ${CROSS_COMPILE}clang++${CROSS_COMPILE_SUFFIX}
AR = ${CROSS_COMPILE}ar${CROSS_COMPILE_SUFFIX}
endif
- # Cross-linker requires this for linked in shared libs that depend
- # themselves on other shared libs (not directly linked in)
- LDFLAGS += -Wl,-rpath-link,$(ACE_ROOT)/lib
+ ifneq ($(static_libs_only), 1)
+ # Cross-linker requires this for linked in shared libs that depend
+ # themselves on other shared libs (not directly linked in)
+ LDFLAGS += -Wl,-rpath-link,$(ACE_ROOT)/lib
+ endif
ifneq (,$(HOST_ROOT))
TAO_IDLFLAGS += -g $(HOST_ROOT)/bin/ace_gperf
TAO_IDL = $(HOST_ROOT)/bin/tao_idl
diff --git a/ACE/include/makeinclude/platform_emscripten.GNU b/ACE/include/makeinclude/platform_emscripten.GNU
new file mode 100644
index 0000000000000..d00b9c4ce5595
--- /dev/null
+++ b/ACE/include/makeinclude/platform_emscripten.GNU
@@ -0,0 +1,31 @@
+ACE_PLATFORM_CONFIG ?= config-emscripten.h
+EXEEXT = .js
+
+debug ?= 1
+optimize ?= 0
+threads ?= 1
+inline ?= 1
+static_libs_only = 1
+
+CROSS_COMPILE := THIS_VALUE_SHOULD_NOT_BE_USED
+override_cross_compile = 1
+CC = emcc
+CXX = em++
+AR = emar
+LD = emcc
+
+ifeq ($(threads),1)
+ FLAGS_C_CC += -pthread
+ LDFLAGS += -pthread
+ LIBS += -lrt
+endif
+
+ifeq ($(debug),1)
+ LDFLAGS += -sASSERTIONS=2
+endif
+
+# TODO: Require choosing Filesystem model:
+# https://emscripten.org/docs/api_reference/Filesystem-API.html
+LDFLAGS += -sNODERAWFS=1
+
+include $(ACE_ROOT)/include/makeinclude/platform_clang_common.GNU
diff --git a/ACE/tests/OS_Test.cpp b/ACE/tests/OS_Test.cpp
index b9fad77374903..b40832466fc93 100644
--- a/ACE/tests/OS_Test.cpp
+++ b/ACE/tests/OS_Test.cpp
@@ -1208,7 +1208,7 @@ ace_ctype_test ()
++retval;
}
- return 0;
+ return retval;
}
int