I suggest adding some debug printouts (using console.log for example). That can help you see in what order things are happening.
- Alon On Sat, Apr 11, 2015 at 5:12 AM, <[email protected]> wrote: > Basically what I am trying to do is to wait for everything to be > initialized, and then call the relevant functions and output into html. > > On Wednesday, April 8, 2015 at 9:29:04 PM UTC+1, Alon Zakai wrote: >> >> onRuntimeInitialized should call the test code. Instead of the test code >> running immediately. For example put the test code in a function called >> doTest(), and call that from onRuntimeInitialized. >> >> - Alon >> >> >> On Wed, Apr 8, 2015 at 12:47 PM, <[email protected]> wrote: >> >>> Hi, how should I correctly modify the html? I was just trying to use the >>> method you mentioned in https://groups.google.com/d/ >>> msg/emscripten-discuss/xDHk29DJ6zI/l5ishrLBu7UJ >>> >>> Thanks >>> >>> On Wednesday, April 8, 2015 at 8:17:34 PM UTC+1, Alon Zakai wrote: >>>> >>>> That html looks invalid. It will run the code in the last script tag >>>> immediately, without waiting for onRuntimeInitialized. >>>> >>>> - Alon >>>> >>>> >>>> On Tue, Apr 7, 2015 at 11:47 PM, <[email protected]> wrote: >>>> >>>>> Hi, it also works for me in the console (I hadn't tried that until you >>>>> mentioned). However it fails in the following html in both chrome and >>>>> firefox (but only with O2/O3 optimisations. With O0, O1 it works fine) : >>>>> >>>>> <!DOCTYPE html> >>>>> <html> >>>>> >>>>> <head> >>>>> <meta charset="UTF-8"> >>>>> <title>simple page</title> >>>>> </head> >>>>> >>>>> <body> >>>>> >>>>> <script type="text/javascript"> >>>>> var Module = { onRuntimeInitialized: function() { >>>>> Module._test(); >>>>> } }; >>>>> </script> >>>>> >>>>> <script type='text/javascript' src="a.out.js"></script> >>>>> >>>>> <script type='text/javascript'> >>>>> mytest = Module.cwrap('test', 'number', ['number']); >>>>> var result = mytest(0); >>>>> document.write(result); >>>>> document.write('<BR/>'); >>>>> document.write("\rFinished!"); >>>>> </script> >>>>> >>>>> </body> >>>>> >>>>> </html> >>>>> >>>>> On Wednesday, April 8, 2015 at 12:40:02 AM UTC+1, Alon Zakai wrote: >>>>>> >>>>>> I just put the js in an empty html file, and looked in the web >>>>>> console at the output. >>>>>> >>>>>> - Alon >>>>>> >>>>>> >>>>>> On Tue, Apr 7, 2015 at 1:32 PM, <[email protected]> wrote: >>>>>> >>>>>>> Hi, I am actually getting the same behaviour in chrome and firefox. >>>>>>> What does the html code that you are using to access the function look >>>>>>> like? Thanks >>>>>>> >>>>>>> On Monday, April 6, 2015 at 10:41:05 PM UTC+1, Alon Zakai wrote: >>>>>>>> >>>>>>>> I built with -O3 and ran it in html, and I can't see the problem. >>>>>>>> >>>>>>>> Perhaps try other browsers and versions, you may have found a >>>>>>>> browser bug. >>>>>>>> >>>>>>>> - Alon >>>>>>>> >>>>>>>> >>>>>>>> On Mon, Apr 6, 2015 at 1:09 PM, <[email protected]> wrote: >>>>>>>> >>>>>>>>> Just to clarify, building with em++ is fine. I only get a problem >>>>>>>>> when it try to use the resulting a.out.js in html. Thanks >>>>>>>>> >>>>>>>>> On Monday, April 6, 2015 at 7:53:28 PM UTC+1, Alon Zakai wrote: >>>>>>>>>> >>>>>>>>>> What are the steps to reproduce the problem? I build that source >>>>>>>>>> file with -O0, 1, 2 and 3, and in all of them I get "42" as the >>>>>>>>>> output. >>>>>>>>>> >>>>>>>>>> - Alon >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Sat, Apr 4, 2015 at 7:12 AM, <[email protected]> wrote: >>>>>>>>>> >>>>>>>>>>> OK the following self contained code (*not* calling any boost >>>>>>>>>>> headers) is fine with O0 or O1, but not with O2 or O3. The function >>>>>>>>>>> which I >>>>>>>>>>> am exporting is : >>>>>>>>>>> >>>>>>>>>>> extern "C" { >>>>>>>>>>> double test(void) { >>>>>>>>>>> boost::shared_ptr<int> y = boost::shared_ptr<int>(new >>>>>>>>>>> int(42)); >>>>>>>>>>> return *y; >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> The invocation of "dispose()" and "weak_release()" in >>>>>>>>>>> "sp_counted_base::release" is what is causing the problems : >>>>>>>>>>> >>>>>>>>>>> #include <atomic> >>>>>>>>>>> #include <iostream> >>>>>>>>>>> #include <vector> >>>>>>>>>>> using namespace std; >>>>>>>>>>> >>>>>>>>>>> namespace boost >>>>>>>>>>> { >>>>>>>>>>> >>>>>>>>>>> namespace core >>>>>>>>>>> { >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> class typeinfo >>>>>>>>>>> { >>>>>>>>>>> private: >>>>>>>>>>> >>>>>>>>>>> typeinfo( typeinfo const& ); >>>>>>>>>>> typeinfo& operator=( typeinfo const& ); >>>>>>>>>>> >>>>>>>>>>> char const * name_; >>>>>>>>>>> >>>>>>>>>>> public: >>>>>>>>>>> >>>>>>>>>>> explicit typeinfo( char const * name ): name_( name ) >>>>>>>>>>> { >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> bool operator==( typeinfo const& rhs ) const >>>>>>>>>>> { >>>>>>>>>>> return this == &rhs; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> bool operator!=( typeinfo const& rhs ) const >>>>>>>>>>> { >>>>>>>>>>> return this != &rhs; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> bool before( typeinfo const& rhs ) const >>>>>>>>>>> { >>>>>>>>>>> return std::less< typeinfo const* >()( this, &rhs ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> char const* name() const >>>>>>>>>>> { >>>>>>>>>>> return name_; >>>>>>>>>>> } >>>>>>>>>>> }; >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> }//namespace core >>>>>>>>>>> >>>>>>>>>>> template<class T> class shared_ptr; >>>>>>>>>>> template<class T> class enable_shared_from_this; >>>>>>>>>>> >>>>>>>>>>> template<class T> inline void checked_delete(T * x) >>>>>>>>>>> { >>>>>>>>>>> // intentionally complex - simplification causes regressions >>>>>>>>>>> typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; >>>>>>>>>>> (void) sizeof(type_must_be_complete); >>>>>>>>>>> delete x; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> namespace detail >>>>>>>>>>> { >>>>>>>>>>> >>>>>>>>>>> typedef boost::core::typeinfo sp_typeinfo; >>>>>>>>>>> >>>>>>>>>>> inline void atomic_increment( std::atomic_int_least32_t * pw ) >>>>>>>>>>> { >>>>>>>>>>> pw->fetch_add( 1, std::memory_order_relaxed ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> inline std::int_least32_t atomic_decrement( >>>>>>>>>>> std::atomic_int_least32_t * pw ) >>>>>>>>>>> { >>>>>>>>>>> return pw->fetch_sub( 1, std::memory_order_acq_rel ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> inline std::int_least32_t atomic_conditional_increment( >>>>>>>>>>> std::atomic_int_least32_t * pw ) >>>>>>>>>>> { >>>>>>>>>>> // long r = *pw; >>>>>>>>>>> // if( r != 0 ) ++*pw; >>>>>>>>>>> // return r; >>>>>>>>>>> >>>>>>>>>>> std::int_least32_t r = pw->load( std::memory_order_relaxed ); >>>>>>>>>>> >>>>>>>>>>> for( ;; ) >>>>>>>>>>> { >>>>>>>>>>> if( r == 0 ) >>>>>>>>>>> { >>>>>>>>>>> return r; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> if( pw->compare_exchange_weak( r, r + 1, >>>>>>>>>>> std::memory_order_relaxed, std::memory_order_relaxed ) ) >>>>>>>>>>> { >>>>>>>>>>> return r; >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> class sp_counted_base >>>>>>>>>>> { >>>>>>>>>>> private: >>>>>>>>>>> >>>>>>>>>>> sp_counted_base( sp_counted_base const & ); >>>>>>>>>>> sp_counted_base & operator= ( sp_counted_base const & ); >>>>>>>>>>> >>>>>>>>>>> std::atomic_int_least32_t use_count_; // #shared >>>>>>>>>>> std::atomic_int_least32_t weak_count_; // #weak + (#shared >>>>>>>>>>> != 0) >>>>>>>>>>> >>>>>>>>>>> public: >>>>>>>>>>> >>>>>>>>>>> sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) >>>>>>>>>>> { >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> virtual ~sp_counted_base() // nothrow >>>>>>>>>>> { >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> // dispose() is called when use_count_ drops to zero, to >>>>>>>>>>> release >>>>>>>>>>> // the resources managed by *this. >>>>>>>>>>> >>>>>>>>>>> virtual void dispose() = 0; // nothrow >>>>>>>>>>> >>>>>>>>>>> // destroy() is called when weak_count_ drops to zero. >>>>>>>>>>> >>>>>>>>>>> virtual void destroy() // nothrow >>>>>>>>>>> { >>>>>>>>>>> delete this; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> virtual void * get_deleter( sp_typeinfo const & ti ) = 0; >>>>>>>>>>> virtual void * get_untyped_deleter() = 0; >>>>>>>>>>> >>>>>>>>>>> void add_ref_copy() >>>>>>>>>>> { >>>>>>>>>>> atomic_increment( &use_count_ ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> bool add_ref_lock() // true on success >>>>>>>>>>> { >>>>>>>>>>> return atomic_conditional_increment( &use_count_ ) != 0; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> void release() // nothrow >>>>>>>>>>> { >>>>>>>>>>> if( atomic_decrement( &use_count_ ) == 1 ) >>>>>>>>>>> { >>>>>>>>>>> dispose(); >>>>>>>>>>> weak_release(); >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> void weak_add_ref() // nothrow >>>>>>>>>>> { >>>>>>>>>>> atomic_increment( &weak_count_ ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> void weak_release() // nothrow >>>>>>>>>>> { >>>>>>>>>>> if( atomic_decrement( &weak_count_ ) == 1 ) >>>>>>>>>>> { >>>>>>>>>>> destroy(); >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> long use_count() const // nothrow >>>>>>>>>>> { >>>>>>>>>>> return use_count_.load( std::memory_order_acquire ); >>>>>>>>>>> } >>>>>>>>>>> }; >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> template<class X> class sp_counted_impl_p: public sp_counted_base >>>>>>>>>>> { >>>>>>>>>>> private: >>>>>>>>>>> >>>>>>>>>>> X * px_; >>>>>>>>>>> >>>>>>>>>>> sp_counted_impl_p( sp_counted_impl_p const & ); >>>>>>>>>>> sp_counted_impl_p & operator= ( sp_counted_impl_p const & ); >>>>>>>>>>> >>>>>>>>>>> typedef sp_counted_impl_p<X> this_type; >>>>>>>>>>> >>>>>>>>>>> public: >>>>>>>>>>> >>>>>>>>>>> explicit sp_counted_impl_p( X * px ): px_( px ) >>>>>>>>>>> { >>>>>>>>>>> #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) >>>>>>>>>>> boost::sp_scalar_constructor_hook( px, sizeof(X), this >>>>>>>>>>> ); >>>>>>>>>>> #endif >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> virtual void dispose() // nothrow >>>>>>>>>>> { >>>>>>>>>>> #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) >>>>>>>>>>> boost::sp_scalar_destructor_hook( px_, sizeof(X), this >>>>>>>>>>> ); >>>>>>>>>>> #endif >>>>>>>>>>> boost::checked_delete( px_ ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> virtual void * get_deleter( detail::sp_typeinfo const & ) >>>>>>>>>>> { >>>>>>>>>>> return 0; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> virtual void * get_untyped_deleter() >>>>>>>>>>> { >>>>>>>>>>> return 0; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> #if defined(BOOST_SP_USE_STD_ALLOCATOR) >>>>>>>>>>> >>>>>>>>>>> void * operator new( std::size_t ) >>>>>>>>>>> { >>>>>>>>>>> return std::allocator<this_type>().allocate( 1, >>>>>>>>>>> static_cast<this_type *>(0) ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> void operator delete( void * p ) >>>>>>>>>>> { >>>>>>>>>>> std::allocator<this_type>().deallocate( >>>>>>>>>>> static_cast<this_type *>(p), 1 ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> #endif >>>>>>>>>>> >>>>>>>>>>> #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) >>>>>>>>>>> >>>>>>>>>>> void * operator new( std::size_t ) >>>>>>>>>>> { >>>>>>>>>>> return quick_allocator<this_type>::alloc(); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> void operator delete( void * p ) >>>>>>>>>>> { >>>>>>>>>>> quick_allocator<this_type>::dealloc( p ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> #endif >>>>>>>>>>> }; >>>>>>>>>>> >>>>>>>>>>> class shared_count >>>>>>>>>>> { >>>>>>>>>>> private: >>>>>>>>>>> >>>>>>>>>>> sp_counted_base * pi_; >>>>>>>>>>> >>>>>>>>>>> public: >>>>>>>>>>> >>>>>>>>>>> void swap(shared_count & r) // nothrow >>>>>>>>>>> { >>>>>>>>>>> sp_counted_base * tmp = r.pi_; >>>>>>>>>>> r.pi_ = pi_; >>>>>>>>>>> pi_ = tmp; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> shared_count(): pi_(0) // nothrow >>>>>>>>>>> #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) >>>>>>>>>>> , id_(shared_count_id) >>>>>>>>>>> #endif >>>>>>>>>>> { >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> template<class Y> explicit shared_count( Y * p ): pi_( 0 ) >>>>>>>>>>> #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) >>>>>>>>>>> , id_(shared_count_id) >>>>>>>>>>> #endif >>>>>>>>>>> { >>>>>>>>>>> #ifndef BOOST_NO_EXCEPTIONS >>>>>>>>>>> >>>>>>>>>>> try >>>>>>>>>>> { >>>>>>>>>>> pi_ = new sp_counted_impl_p<Y>( p ); >>>>>>>>>>> } >>>>>>>>>>> catch(...) >>>>>>>>>>> { >>>>>>>>>>> boost::checked_delete( p ); >>>>>>>>>>> throw; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> #else >>>>>>>>>>> >>>>>>>>>>> pi_ = new sp_counted_impl_p<Y>( p ); >>>>>>>>>>> >>>>>>>>>>> if( pi_ == 0 ) >>>>>>>>>>> { >>>>>>>>>>> boost::checked_delete( p ); >>>>>>>>>>> boost::throw_exception( std::bad_alloc() ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> #endif >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> shared_count(shared_count && r): pi_(r.pi_) // nothrow >>>>>>>>>>> #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) >>>>>>>>>>> , id_(shared_count_id) >>>>>>>>>>> #endif >>>>>>>>>>> { >>>>>>>>>>> r.pi_ = 0; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> ~shared_count() // nothrow >>>>>>>>>>> { >>>>>>>>>>> if( pi_ != 0 ) pi_->release(); >>>>>>>>>>> #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) >>>>>>>>>>> id_ = 0; >>>>>>>>>>> #endif >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> }; >>>>>>>>>>> >>>>>>>>>>> template< class T > struct sp_element >>>>>>>>>>> { >>>>>>>>>>> typedef T type; >>>>>>>>>>> }; >>>>>>>>>>> >>>>>>>>>>> template< class X, class Y, class T > inline void >>>>>>>>>>> sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y >>>>>>>>>>> const * py, >>>>>>>>>>> boost::enable_shared_from_this< T > const * pe ) >>>>>>>>>>> { >>>>>>>>>>> if( pe != 0 ) >>>>>>>>>>> { >>>>>>>>>>> pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) >>>>>>>>>>> ); >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> struct sp_any_pointer >>>>>>>>>>> { >>>>>>>>>>> template<class T> sp_any_pointer( T* ) {} >>>>>>>>>>> }; >>>>>>>>>>> >>>>>>>>>>> inline void sp_enable_shared_from_this( sp_any_pointer, >>>>>>>>>>> sp_any_pointer, sp_any_pointer ) >>>>>>>>>>> { >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> template< class T, class Y > inline void sp_pointer_construct( >>>>>>>>>>> boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & >>>>>>>>>>> pn ) >>>>>>>>>>> { >>>>>>>>>>> boost::detail::shared_count( p ).swap( pn ); >>>>>>>>>>> boost::detail::sp_enable_shared_from_this( ppx, p, p ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> template< class T > struct sp_dereference >>>>>>>>>>> { >>>>>>>>>>> typedef T & type; >>>>>>>>>>> }; >>>>>>>>>>> >>>>>>>>>>> }//namespace detail >>>>>>>>>>> >>>>>>>>>>> template<class T> class shared_ptr >>>>>>>>>>> { >>>>>>>>>>> private: >>>>>>>>>>> >>>>>>>>>>> // Borland 5.5.1 specific workaround >>>>>>>>>>> typedef shared_ptr<T> this_type; >>>>>>>>>>> >>>>>>>>>>> public: >>>>>>>>>>> >>>>>>>>>>> typedef typename boost::detail::sp_element< T >::type >>>>>>>>>>> element_type; >>>>>>>>>>> >>>>>>>>>>> template<class Y> >>>>>>>>>>> explicit shared_ptr( Y * p ): px( p ), pn() // Y must be >>>>>>>>>>> complete >>>>>>>>>>> { >>>>>>>>>>> boost::detail::sp_pointer_construct( this, p, pn ); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> element_type * px; // contained pointer >>>>>>>>>>> boost::detail::shared_count pn; // reference counter >>>>>>>>>>> >>>>>>>>>>> typename boost::detail::sp_dereference< T >::type operator* () >>>>>>>>>>> const >>>>>>>>>>> { >>>>>>>>>>> return *px; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> }; >>>>>>>>>>> >>>>>>>>>>> } // namespace boost >>>>>>>>>>> >>>>>>>>>>> extern "C" { >>>>>>>>>>> double test(void) { >>>>>>>>>>> boost::shared_ptr<int> y = boost::shared_ptr<int>(new >>>>>>>>>>> int(42)); >>>>>>>>>>> return *y; >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> int main(void){ >>>>>>>>>>> double result = test(); >>>>>>>>>>> cout<<result<<endl; >>>>>>>>>>> return 0; >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> You received this message because you are subscribed to the >>>>>>>>>>> Google Groups "emscripten-discuss" group. >>>>>>>>>>> To unsubscribe from this group and stop receiving emails from >>>>>>>>>>> it, send an email to emscripten-discuss+unsubscribe >>>>>>>>>>> @googlegroups.com. >>>>>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>> You received this message because you are subscribed to the Google >>>>>>>>> Groups "emscripten-discuss" group. >>>>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>>>> send an email to [email protected]. >>>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>> You received this message because you are subscribed to the Google >>>>>>> Groups "emscripten-discuss" group. >>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>> send an email to [email protected]. >>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>> >>>>>> >>>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "emscripten-discuss" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to [email protected]. >>>>> For more options, visit https://groups.google.com/d/optout. >>>>> >>>> >>>> -- >>> You received this message because you are subscribed to the Google >>> Groups "emscripten-discuss" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to [email protected]. >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> -- > You received this message because you are subscribed to the Google Groups > "emscripten-discuss" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "emscripten-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
