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] <javascript:>> 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 [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] <javascript:>.
>> 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.

Reply via email to