aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library_fs.js16
-rw-r--r--system/include/emscripten/bind.h53
-rw-r--r--system/include/emscripten/val.h18
-rw-r--r--system/include/emscripten/wire.h127
-rwxr-xr-xtests/runner.py23
-rw-r--r--tests/test_core.py10
-rw-r--r--tests/test_other.py8
-rw-r--r--tools/jsrun.py2
8 files changed, 159 insertions, 98 deletions
diff --git a/src/library_fs.js b/src/library_fs.js
index a6bca77c..7932385e 100644
--- a/src/library_fs.js
+++ b/src/library_fs.js
@@ -1211,8 +1211,20 @@ mergeInto(LibraryManager.library, {
FS.mkdev('/dev/tty', FS.makedev(5, 0));
FS.mkdev('/dev/tty1', FS.makedev(6, 0));
// setup /dev/[u]random
- FS.createDevice('/dev', 'random', function() { return Math.floor(Math.random()*256); });
- FS.createDevice('/dev', 'urandom', function() { return Math.floor(Math.random()*256); });
+ var random_device;
+ if (typeof crypto !== 'undefined') {
+ // for modern web browsers
+ var randomBuffer = new Uint8Array(1);
+ random_device = function() { crypto.getRandomValues(randomBuffer); return randomBuffer[0]; };
+ } else if (ENVIRONMENT_IS_NODE) {
+ // for nodejs
+ random_device = function() { return require('crypto').randomBytes(1)[0]; };
+ } else {
+ // default for ES5 platforms
+ random_device = function() { return Math.floor(Math.random()*256); };
+ }
+ FS.createDevice('/dev', 'random', random_device);
+ FS.createDevice('/dev', 'urandom', random_device);
// we're not going to emulate the actual shm device,
// just create the tmp dirs that reside in it commonly
FS.mkdir('/dev/shm');
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
index 67e7c6a3..bd96f35f 100644
--- a/system/include/emscripten/bind.h
+++ b/system/include/emscripten/bind.h
@@ -71,7 +71,7 @@ namespace emscripten {
void _embind_register_function(
const char* name,
unsigned argCount,
- TYPEID argTypes[],
+ const TYPEID argTypes[],
const char* signature,
GenericFunction invoker,
GenericFunction function);
@@ -137,7 +137,7 @@ namespace emscripten {
void _embind_register_class_constructor(
TYPEID classType,
unsigned argCount,
- TYPEID argTypes[],
+ const TYPEID argTypes[],
const char* invokerSignature,
GenericFunction invoker,
GenericFunction constructor);
@@ -146,7 +146,7 @@ namespace emscripten {
TYPEID classType,
const char* methodName,
unsigned argCount,
- TYPEID argTypes[],
+ const TYPEID argTypes[],
const char* invokerSignature,
GenericFunction invoker,
void* context,
@@ -168,7 +168,7 @@ namespace emscripten {
TYPEID classType,
const char* methodName,
unsigned argCount,
- TYPEID argTypes[],
+ const TYPEID argTypes[],
const char* invokerSignature,
GenericFunction invoker,
GenericFunction method);
@@ -413,8 +413,8 @@ namespace emscripten {
auto invoker = &Invoker<ReturnType, Args...>::invoke;
_embind_register_function(
name,
- args.count,
- args.types,
+ args.getCount(),
+ args.getTypes(),
getSignature(invoker),
reinterpret_cast<GenericFunction>(invoker),
reinterpret_cast<GenericFunction>(fn));
@@ -760,6 +760,7 @@ namespace emscripten {
}
~value_object() {
+ using namespace internal;
_embind_finalize_value_object(internal::TypeID<ClassType>::get());
}
@@ -1084,7 +1085,7 @@ namespace emscripten {
class_() = delete;
- explicit class_(const char* name) {
+ EMSCRIPTEN_ALWAYS_INLINE explicit class_(const char* name) {
using namespace internal;
BaseSpecifier::template verify<ClassType>();
@@ -1111,7 +1112,7 @@ namespace emscripten {
}
template<typename PointerType>
- const class_& smart_ptr(const char* name) const {
+ EMSCRIPTEN_ALWAYS_INLINE const class_& smart_ptr(const char* name) const {
using namespace internal;
typedef smart_ptr_trait<PointerType> PointerTrait;
@@ -1141,14 +1142,14 @@ namespace emscripten {
};
template<typename... ConstructorArgs, typename... Policies>
- const class_& constructor(Policies... policies) const {
+ EMSCRIPTEN_ALWAYS_INLINE const class_& constructor(Policies... policies) const {
return constructor(
&internal::operator_new<ClassType, ConstructorArgs...>,
policies...);
}
template<typename... Args, typename ReturnType, typename... Policies>
- const class_& constructor(ReturnType (*factory)(Args...), Policies...) const {
+ EMSCRIPTEN_ALWAYS_INLINE const class_& constructor(ReturnType (*factory)(Args...), Policies...) const {
using namespace internal;
// TODO: allows all raw pointers... policies need a rethink
@@ -1156,8 +1157,8 @@ namespace emscripten {
auto invoke = &Invoker<ReturnType, Args...>::invoke;
_embind_register_class_constructor(
TypeID<ClassType>::get(),
- args.count,
- args.types,
+ args.getCount(),
+ args.getTypes(),
getSignature(invoke),
reinterpret_cast<GenericFunction>(invoke),
reinterpret_cast<GenericFunction>(factory));
@@ -1165,7 +1166,7 @@ namespace emscripten {
}
template<typename SmartPtr, typename... Args, typename... Policies>
- const class_& smart_ptr_constructor(const char* smartPtrName, SmartPtr (*factory)(Args...), Policies...) const {
+ EMSCRIPTEN_ALWAYS_INLINE const class_& smart_ptr_constructor(const char* smartPtrName, SmartPtr (*factory)(Args...), Policies...) const {
using namespace internal;
smart_ptr<SmartPtr>(smartPtrName);
@@ -1174,8 +1175,8 @@ namespace emscripten {
auto invoke = &Invoker<SmartPtr, Args...>::invoke;
_embind_register_class_constructor(
TypeID<ClassType>::get(),
- args.count,
- args.types,
+ args.getCount(),
+ args.getTypes(),
getSignature(invoke),
reinterpret_cast<GenericFunction>(invoke),
reinterpret_cast<GenericFunction>(factory));
@@ -1183,7 +1184,7 @@ namespace emscripten {
}
template<typename WrapperType, typename PointerType = WrapperType*, typename... ConstructorArgs>
- const class_& allow_subclass(
+ EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass(
const char* wrapperClassName,
const char* pointerName = "<UnknownPointerName>",
::emscripten::constructor<ConstructorArgs...> = ::emscripten::constructor<ConstructorArgs...>()
@@ -1209,7 +1210,7 @@ namespace emscripten {
}
template<typename WrapperType, typename... ConstructorArgs>
- const class_& allow_subclass(
+ EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass(
const char* wrapperClassName,
::emscripten::constructor<ConstructorArgs...> constructor
) const {
@@ -1226,8 +1227,8 @@ namespace emscripten {
_embind_register_class_function(
TypeID<ClassType>::get(),
methodName,
- args.count,
- args.types,
+ args.getCount(),
+ args.getTypes(),
getSignature(invoker),
reinterpret_cast<GenericFunction>(invoker),
getContext(memberFunction),
@@ -1245,8 +1246,8 @@ namespace emscripten {
_embind_register_class_function(
TypeID<ClassType>::get(),
methodName,
- args.count,
- args.types,
+ args.getCount(),
+ args.getTypes(),
getSignature(invoker),
reinterpret_cast<GenericFunction>(invoker),
getContext(memberFunction),
@@ -1263,8 +1264,8 @@ namespace emscripten {
_embind_register_class_function(
TypeID<ClassType>::get(),
methodName,
- args.count,
- args.types,
+ args.getCount(),
+ args.getTypes(),
getSignature(invoke),
reinterpret_cast<GenericFunction>(invoke),
getContext(function),
@@ -1362,8 +1363,8 @@ namespace emscripten {
_embind_register_class_class_function(
TypeID<ClassType>::get(),
methodName,
- args.count,
- args.types,
+ args.getCount(),
+ args.getTypes(),
getSignature(invoke),
reinterpret_cast<internal::GenericFunction>(invoke),
reinterpret_cast<GenericFunction>(classMethod));
@@ -1466,6 +1467,7 @@ namespace emscripten {
typedef EnumType enum_type;
enum_(const char* name) {
+ using namespace internal;
_embind_register_enum(
internal::TypeID<EnumType>::get(),
name,
@@ -1474,6 +1476,7 @@ namespace emscripten {
}
enum_& value(const char* name, EnumType value) {
+ using namespace internal;
// TODO: there's still an issue here.
// if EnumType is an unsigned long, then JS may receive it as a signed long
static_assert(sizeof(value) <= sizeof(internal::GenericEnumValue), "enum type must fit in a GenericEnumValue");
diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h
index 31f5923e..78c4b60c 100644
--- a/system/include/emscripten/val.h
+++ b/system/include/emscripten/val.h
@@ -33,7 +33,7 @@ namespace emscripten {
EM_VAL _emval_new(
EM_VAL value,
unsigned argCount,
- internal::TYPEID argTypes[],
+ const TYPEID argTypes[],
EM_VAR_ARGS argv);
EM_VAL _emval_get_global(const char* name);
@@ -45,14 +45,14 @@ namespace emscripten {
EM_VAL _emval_call(
EM_VAL value,
unsigned argCount,
- internal::TYPEID argTypes[],
+ const TYPEID argTypes[],
EM_VAR_ARGS argv);
// DO NOT call this more than once per signature. It will
// leak generated function objects!
EM_METHOD_CALLER _emval_get_method_caller(
unsigned argCount, // including return value
- internal::TYPEID argTypes[]);
+ const TYPEID argTypes[]);
EM_GENERIC_WIRE_TYPE _emval_call_method(
EM_METHOD_CALLER caller,
EM_VAL handle,
@@ -62,7 +62,7 @@ namespace emscripten {
bool _emval_has_function(
EM_VAL value,
const char* methodName,
- internal::TYPEID filter);
+ const TYPEID filter);
EM_VAL _emval_typeof(EM_VAL value);
}
@@ -91,7 +91,7 @@ namespace emscripten {
private:
static EM_METHOD_CALLER init_method_caller() {
WithPolicies<>::ArgTypeList<ReturnType, Args...> args;
- return _emval_get_method_caller(args.count, args.types);
+ return _emval_get_method_caller(args.getCount(), args.getTypes());
}
};
@@ -357,8 +357,8 @@ namespace emscripten {
return val(
_emval_new(
handle,
- argList.count,
- argList.types,
+ argList.getCount(),
+ argList.getTypes(),
argv));
}
@@ -381,8 +381,8 @@ namespace emscripten {
return val(
_emval_call(
handle,
- argList.count,
- argList.types,
+ argList.getCount(),
+ argList.getTypes(),
argv));
}
diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h
index 1a9432d6..d61b0bc7 100644
--- a/system/include/emscripten/wire.h
+++ b/system/include/emscripten/wire.h
@@ -27,10 +27,7 @@ namespace emscripten {
#endif
namespace internal {
- typedef void (*GenericFunction)();
-
- typedef const struct _TYPEID {}* TYPEID;
-
+ typedef const void* TYPEID;
// We don't need the full std::type_info implementation. We
// just need a unique identifier per type and polymorphic type
@@ -38,49 +35,48 @@ namespace emscripten {
template<typename T>
struct CanonicalizedID {
- static TYPEID get() {
- static _TYPEID c;
+ static char c;
+ static constexpr TYPEID get() {
return &c;
}
};
template<typename T>
+ char CanonicalizedID<T>::c;
+
+ template<typename T>
struct Canonicalized {
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
};
template<typename T>
struct LightTypeID {
- static TYPEID get() {
+ static constexpr TYPEID get() {
typedef typename Canonicalized<T>::type C;
- if (has_unbound_type_names || std::is_polymorphic<C>::value) {
- return reinterpret_cast<TYPEID>(&typeid(C));
- } else {
- return CanonicalizedID<C>::get();
- }
+ return (has_unbound_type_names || std::is_polymorphic<C>::value)
+ ? &typeid(C)
+ : CanonicalizedID<C>::get();
}
};
template<typename T>
- const TYPEID getLightTypeID(const T& value) {
+ constexpr TYPEID getLightTypeID(const T& value) {
typedef typename Canonicalized<T>::type C;
- if (has_unbound_type_names || std::is_polymorphic<C>::value) {
- return reinterpret_cast<TYPEID>(&typeid(value));
- } else {
- return LightTypeID<T>::get();
- }
+ return (has_unbound_type_names || std::is_polymorphic<C>::value)
+ ? &typeid(value)
+ : LightTypeID<T>::get();
}
template<typename T>
struct TypeID {
- static TYPEID get() {
+ static constexpr TYPEID get() {
return LightTypeID<T>::get();
}
};
template<typename T>
struct TypeID<std::unique_ptr<T>> {
- static TYPEID get() {
+ static constexpr TYPEID get() {
return TypeID<T>::get();
}
};
@@ -96,7 +92,7 @@ namespace emscripten {
template<typename T>
struct TypeID<AllowedRawPointer<T>> {
- static TYPEID get() {
+ static constexpr TYPEID get() {
return LightTypeID<T*>::get();
}
};
@@ -125,40 +121,89 @@ namespace emscripten {
};
};
- // ArgTypes<>
+ // TypeList<>
- template<int Index, typename... Args>
- struct ArgTypes;
+ template<typename...>
+ struct TypeList {};
- template<int Index>
- struct ArgTypes<Index> {
- template<typename... Policies>
- static void fill(TYPEID* argTypes) {
- }
+ // Cons :: T, TypeList<types...> -> Cons<T, types...>
+
+ template<typename First, typename TypeList>
+ struct Cons;
+
+ template<typename First, typename... Rest>
+ struct Cons<First, TypeList<Rest...>> {
+ typedef TypeList<First, Rest...> type;
};
- template<int Index, typename T, typename... Remaining>
- struct ArgTypes<Index, T, Remaining...> {
- template<typename... Policies>
- static void fill(TYPEID* argTypes) {
- typedef typename ExecutePolicies<Policies...>::template With<T, Index>::type TransformT;
- *argTypes = TypeID<TransformT>::get();
- return ArgTypes<Index + 1, Remaining...>::template fill<Policies...>(argTypes + 1);
+ // Apply :: T, TypeList<types...> -> T<types...>
+
+ template<template<typename...> class Output, typename TypeList>
+ struct Apply;
+
+ template<template<typename...> class Output, typename... Types>
+ struct Apply<Output, TypeList<Types...>> {
+ typedef Output<Types...> type;
+ };
+
+ // MapWithIndex_
+
+ template<template<size_t, typename> class Mapper, size_t CurrentIndex, typename... Args>
+ struct MapWithIndex_;
+
+ template<template<size_t, typename> class Mapper, size_t CurrentIndex, typename First, typename... Rest>
+ struct MapWithIndex_<Mapper, CurrentIndex, First, Rest...> {
+ typedef typename Cons<
+ typename Mapper<CurrentIndex, First>::type,
+ typename MapWithIndex_<Mapper, CurrentIndex + 1, Rest...>::type
+ >::type type;
+ };
+
+ template<template<size_t, typename> class Mapper, size_t CurrentIndex>
+ struct MapWithIndex_<Mapper, CurrentIndex> {
+ typedef TypeList<> type;
+ };
+
+ template<template<typename...> class Output, template<size_t, typename> class Mapper, typename... Args>
+ struct MapWithIndex {
+ typedef typename internal::Apply<
+ Output,
+ typename MapWithIndex_<Mapper, 0, Args...>::type
+ >::type type;
+ };
+
+
+ template<typename ArgList>
+ struct ArgArrayGetter;
+
+ template<typename... Args>
+ struct ArgArrayGetter<TypeList<Args...>> {
+ static const TYPEID* get() {
+ static constexpr TYPEID types[] = { TypeID<Args>::get()... };
+ return types;
}
};
// WithPolicies<...>::ArgTypeList<...>
+
template<typename... Policies>
struct WithPolicies {
+ template<size_t Index, typename T>
+ struct MapWithPolicies {
+ typedef typename ExecutePolicies<Policies...>::template With<T, Index>::type type;
+ };
+
template<typename... Args>
struct ArgTypeList {
- ArgTypeList() {
- count = sizeof...(Args);
- ArgTypes<0, Args...>::template fill<Policies...>(types);
+ unsigned getCount() const {
+ return sizeof...(Args);
}
- unsigned count;
- TYPEID types[sizeof...(Args)];
+ const TYPEID* getTypes() const {
+ return ArgArrayGetter<
+ typename MapWithIndex<TypeList, MapWithPolicies, Args...>::type
+ >::get();
+ }
};
};
diff --git a/tests/runner.py b/tests/runner.py
index 6d3f55f8..e9479313 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -258,7 +258,7 @@ process(sys.argv[1])
err = '\n'.join(filter(lambda line: 'uccessfully compiled asm.js code' not in line, err.split('\n')))
return err
- def run_generated_code(self, engine, filename, args=[], check_timeout=True, output_nicerizer=None):
+ def run_generated_code(self, engine, filename, args=[], check_timeout=True, output_nicerizer=None, assert_returncode=0):
stdout = os.path.join(self.get_dir(), 'stdout') # use files, as PIPE can get too full and hang us
stderr = os.path.join(self.get_dir(), 'stderr')
try:
@@ -266,7 +266,7 @@ process(sys.argv[1])
except:
cwd = None
os.chdir(self.get_dir())
- run_js(filename, engine, args, check_timeout, stdout=open(stdout, 'w'), stderr=open(stderr, 'w'))
+ run_js(filename, engine, args, check_timeout, stdout=open(stdout, 'w'), stderr=open(stderr, 'w'), assert_returncode=assert_returncode)
if cwd is not None:
os.chdir(cwd)
out = open(stdout, 'r').read()
@@ -445,7 +445,7 @@ process(sys.argv[1])
includes, force_c, build_ll_hook, extra_emscripten_args)
## Does a complete test - builds, runs, checks output, etc.
- def do_run(self, src, expected_output, args=[], output_nicerizer=None, output_processor=None, no_build=False, main_file=None, additional_files=[], js_engines=None, post_build=None, basename='src.cpp', libraries=[], includes=[], force_c=False, build_ll_hook=None, extra_emscripten_args=[]):
+ def do_run(self, src, expected_output, args=[], output_nicerizer=None, output_processor=None, no_build=False, main_file=None, additional_files=[], js_engines=None, post_build=None, basename='src.cpp', libraries=[], includes=[], force_c=False, build_ll_hook=None, extra_emscripten_args=[], assert_returncode=None):
if force_c or (main_file is not None and main_file[-2:]) == '.c':
basename = 'src.c'
Building.COMPILER = to_cc(Building.COMPILER)
@@ -464,7 +464,7 @@ process(sys.argv[1])
js_engines = filter(lambda engine: engine not in self.banned_js_engines, js_engines)
if len(js_engines) == 0: return self.skip('No JS engine present to run this test with. Check %s and the paths therein.' % EM_CONFIG)
for engine in js_engines:
- js_output = self.run_generated_code(engine, filename + '.o.js', args, output_nicerizer=output_nicerizer)
+ js_output = self.run_generated_code(engine, filename + '.o.js', args, output_nicerizer=output_nicerizer, assert_returncode=assert_returncode)
self.assertContained(expected_output, js_output.replace('\r\n', '\n'))
self.assertNotContained('ERROR', js_output)
@@ -477,7 +477,7 @@ process(sys.argv[1])
test_index += 1
# No building - just process an existing .ll file (or .bc, which we turn into .ll)
- def do_ll_run(self, ll_file, expected_output=None, args=[], js_engines=None, output_nicerizer=None, post_build=None, force_recompile=False, build_ll_hook=None, extra_emscripten_args=[]):
+ def do_ll_run(self, ll_file, expected_output=None, args=[], js_engines=None, output_nicerizer=None, post_build=None, force_recompile=False, build_ll_hook=None, extra_emscripten_args=[], assert_returncode=None):
filename = os.path.join(self.get_dir(), 'src.cpp')
self.prep_ll_run(filename, ll_file, force_recompile, build_ll_hook)
@@ -485,12 +485,13 @@ process(sys.argv[1])
self.ll_to_js(filename, extra_emscripten_args, post_build)
self.do_run(None,
- expected_output,
- args,
- no_build=True,
- js_engines=js_engines,
- output_nicerizer=output_nicerizer,
- post_build=None) # post_build was already done in ll_to_js, this do_run call is just to test the output
+ expected_output,
+ args,
+ no_build=True,
+ js_engines=js_engines,
+ output_nicerizer=output_nicerizer,
+ post_build=None,
+ assert_returncode=assert_returncode) # post_build was already done in ll_to_js, this do_run call is just to test the output
# Run a server and a web page. When a test runs, we tell the server about it,
diff --git a/tests/test_core.py b/tests/test_core.py
index a4579800..20278d37 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -6244,7 +6244,7 @@ def process(filename):
'''
try:
- self.do_run(src, '*nothingatall*')
+ self.do_run(src, '*nothingatall*', assert_returncode=None)
except Exception, e:
# This test *should* fail, by throwing this exception
assert 'Assertion failed: Load-store consistency assumption failure!' in str(e), str(e)
@@ -6261,7 +6261,7 @@ def process(filename):
Settings.SAFE_HEAP_LINES = ["src.cpp:99"]
try:
- self.do_run(src, '*nothingatall*')
+ self.do_run(src, '*nothingatall*', assert_returncode=None)
except Exception, e:
# This test *should* fail, by throwing this exception
assert 'Assertion failed: Load-store consistency assumption failure!' in str(e), str(e)
@@ -6311,7 +6311,7 @@ def process(filename):
Building.link([module_name + '.o', main_name + '.o'], all_name)
try:
- self.do_ll_run(all_name, '*nothingatall*')
+ self.do_ll_run(all_name, '*nothingatall*', assert_returncode=None)
except Exception, e:
# This test *should* fail, by throwing this exception
assert 'Assertion failed: Load-store consistency assumption failure!' in str(e), str(e)
@@ -6328,7 +6328,7 @@ def process(filename):
for lines in [["module.cpp:22", "main.cpp:9"], ["module.cpp:7", "main.cpp:29"], ["module.cpp:127", "main.cpp:449"], ["module.cpp:7"], ["main.cpp:9"]]:
Settings.SAFE_HEAP_LINES = lines
try:
- self.do_ll_run(all_name, '*nothingatall*')
+ self.do_ll_run(all_name, '*nothingatall*', assert_returncode=None)
except Exception, e:
# This test *should* fail, by throwing this exception
assert 'Assertion failed: Load-store consistency assumption failure!' in str(e), str(e)
@@ -6353,7 +6353,7 @@ def process(filename):
}
'''
try:
- self.do_run(src, '*nothingatall*')
+ self.do_run(src, '*nothingatall*', assert_returncode=None)
except Exception, e:
# This test *should* fail
assert 'Assertion failed: x < 15' in str(e), str(e)
diff --git a/tests/test_other.py b/tests/test_other.py
index 4fb90b1a..9e3c59e8 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -245,7 +245,7 @@ Options that are modified or new in %s include:
output = Popen([PYTHON, compiler, 'twopart_main.o', '-O1', '-g'] + args, stdout=PIPE, stderr=PIPE).communicate()
assert os.path.exists(target), '\n'.join(output)
#print '\n'.join(output)
- self.assertContained('missing function', run_js(target, stderr=STDOUT))
+ self.assertContained('missing function', run_js(target, stderr=STDOUT, assert_returncode=None))
try_delete(target)
# Combining those bc files into js should work
@@ -549,7 +549,7 @@ f.close()
print args, expected, err_expected
out, err = Popen([PYTHON, EMCC, 'src.c'] + args, stderr=PIPE).communicate()
if err_expected: self.assertContained(err_expected, err)
- self.assertContained(expected, run_js(self.in_dir('a.out.js'), stderr=PIPE, full_output=True))
+ self.assertContained(expected, run_js(self.in_dir('a.out.js'), stderr=PIPE, full_output=True, assert_returncode=None))
return open(self.in_dir('a.out.js')).read()
if os.environ.get('EMCC_FAST_COMPILER') == '0':
@@ -2406,7 +2406,7 @@ var Module = { print: function(x) { throw '<{(' + x + ')}>' } };
''')
Popen([PYTHON, EMCC, 'code.cpp', '--pre-js', 'pre.js']).communicate()
- output = run_js(os.path.join(self.get_dir(), 'a.out.js'), stderr=PIPE, full_output=True, engine=NODE_JS)
+ output = run_js(os.path.join(self.get_dir(), 'a.out.js'), stderr=PIPE, full_output=True, engine=NODE_JS, assert_returncode=None)
assert r'<{(123456789)}>' in output, output
def test_precompiled_headers(self):
@@ -2793,7 +2793,7 @@ int main() {
cmd = [PYTHON, EMCC, 'src.cpp', '-O' + str(opts), '-s', 'SAFE_HEAP=' + str(safe)]
print cmd
Popen(cmd).communicate()
- output = run_js('a.out.js', stderr=PIPE, full_output=True)
+ output = run_js('a.out.js', stderr=PIPE, full_output=True, assert_returncode=None)
if safe:
assert 'Function table mask error' in output, output
else:
diff --git a/tools/jsrun.py b/tools/jsrun.py
index d63451db..e2ec5439 100644
--- a/tools/jsrun.py
+++ b/tools/jsrun.py
@@ -17,7 +17,7 @@ def timeout_run(proc, timeout=None, note='unnamed process', full_output=False):
logging.info('Process ' + str(proc.pid) + ' finished after ' + str(time.time() - start) + ' seconds. Exit code: ' + str(proc.returncode))
return '\n'.join(out) if full_output else out[0]
-def run_js(filename, engine=None, args=[], check_timeout=False, stdin=None, stdout=PIPE, stderr=None, cwd=None, full_output=False, assert_returncode=None):
+def run_js(filename, engine=None, args=[], check_timeout=False, stdin=None, stdout=PIPE, stderr=None, cwd=None, full_output=False, assert_returncode=0):
if type(engine) is not list:
engine = [engine]
command = engine + [filename] + (['--'] if 'd8' in engine[0] or 'jsc' in engine[0] else []) + args