[gnash] 01/03: Imported Upstream version 0.8.11~git20160608

Tim Retout diocles at moszumanska.debian.org
Thu Jun 9 00:37:59 UTC 2016


This is an automated email from the git hooks/post-receive script.

diocles pushed a commit to branch master
in repository gnash.

commit f332cf27379a4a809b77be96ba5ddd7581fbb38f
Author: Tim Retout <diocles at debian.org>
Date:   Thu Jun 9 00:10:42 2016 +0100

    Imported Upstream version 0.8.11~git20160608
---
 gui/fb/fb.cpp                                      | 19 +++----
 gui/fb/fbsup.h                                     |  4 +-
 gui/gtk/gtk.cpp                                    | 15 ++++--
 gui/gtk/gtksup.h                                   |  3 ++
 gui/qt/Qt4Glue.cpp                                 |  5 +-
 gui/qt/kde.cpp                                     |  5 +-
 libbase/log.cpp                                    |  2 +-
 libcore/ExternalInterface.cpp                      |  6 +--
 libcore/asobj/Function_as.cpp                      |  6 +--
 libcore/asobj/MovieClip_as.cpp                     | 13 +++--
 libcore/asobj/NetStream_as.cpp                     | 15 ++++--
 libcore/asobj/Sound_as.cpp                         | 17 +++++--
 .../asobj/flash/external/ExternalInterface_as.cpp  | 14 ++---
 libcore/movie_root.cpp                             | 32 ++++++------
 libmedia/MediaParser.cpp                           | 38 +-------------
 libmedia/MediaParser.h                             | 40 +++++++++++++--
 libmedia/ffmpeg/VideoConverterFfmpeg.cpp           | 54 ++++++++++----------
 libmedia/ffmpeg/VideoDecoderFfmpeg.cpp             | 24 ++++-----
 libmedia/ffmpeg/ffmpegHeaders.h                    | 23 +++++++++
 libsound/Makefile.am                               | 11 ++--
 libsound/sound_handler.cpp                         | 12 ++++-
 plugin/npapi/callbacks.cpp                         | 24 +++------
 plugin/npapi/external.cpp                          | 57 +++++++++++++--------
 plugin/npapi/external.h                            | 12 ++---
 plugin/npapi/plugin.cpp                            | 17 +++----
 plugin/npapi/pluginScriptObject.cpp                | 12 ++---
 plugin/npapi/pluginScriptObject.h                  | 11 ++--
 plugin/npapi/test.cpp                              | 45 +++++++++++------
 revno.h                                            |  2 +-
 testsuite/actionscript.all/Function.as             | 56 ++++++++++++++++++--
 testsuite/actionscript.all/Makefile.am             |  3 +-
 testsuite/misc-ming.all/Makefile.am                |  6 +--
 .../misc-ming.all/extgetvariable_testrunner.sh     |  8 +--
 testsuite/misc-mtasc.all/extcomm.as                | 46 ++++++++++++++---
 testsuite/misc-mtasc.all/extcommtests-runner.sh    | 59 ++++++++++++++++++++--
 35 files changed, 465 insertions(+), 251 deletions(-)

diff --git a/gui/fb/fb.cpp b/gui/fb/fb.cpp
index 5e9a155..37948c7 100644
--- a/gui/fb/fb.cpp
+++ b/gui/fb/fb.cpp
@@ -153,7 +153,6 @@ terminate_signal(int /*signo*/) {
 
 FBGui::FBGui(unsigned long xid, float scale, bool loop, RunResources& r)
     : Gui(xid, scale, loop, r),
-      _fd(-1),
       _original_vt(-1),
       _original_kd(-1),
       _own_vt(-1),
@@ -174,11 +173,7 @@ FBGui::~FBGui()
 {  
     // GNASH_REPORT_FUNCTION;
     
-    if (_fd > 0) {
-        disable_terminal();
-        // log_debug("Closing framebuffer device");
-        close(_fd);
-    }
+    enable_terminal();
 }
 
 bool
@@ -517,6 +512,12 @@ FBGui::setInvalidatedRegions(const InvalidatedRanges& ranges)
      _glue->setInvalidatedRegions(ranges);
 }
 
+void
+FBGui::quitUI()
+{
+    terminate_request = true;
+}
+
 char *
 FBGui::find_accessible_tty(int no)
 {
@@ -582,8 +583,6 @@ FBGui::disable_terminal()
     struct vt_stat vts;
     if (ioctl(fd, VT_GETSTATE, &vts) == -1) {
         log_error(_("Could not get current VT state"));
-        close(_fd);
-        _fd = -1;
         close(fd);
         return false;
     }
@@ -612,7 +611,7 @@ FBGui::disable_terminal()
         return false;
     }
   
-    _fd = open(tty, O_RDWR);
+    fd = open(tty, O_RDWR);
     if (fd < 0) {
         log_error(_("Could not open %s"), tty);
         return false;
@@ -708,8 +707,6 @@ FBGui::enable_terminal()
 
     if (ioctl(fd, VT_ACTIVATE, _original_vt)) {
         log_error(_("Could not activate VT number %d"), _original_vt);
-        close(_fd);
-        _fd = -1;
         close(fd);
         return false;
     }
diff --git a/gui/fb/fbsup.h b/gui/fb/fbsup.h
index 23f409b..063b0b5 100644
--- a/gui/fb/fbsup.h
+++ b/gui/fb/fbsup.h
@@ -119,6 +119,9 @@ public:
     /// Start main rendering loop.
     bool run();
 
+    /// Stop main rendering loop.
+    void quitUI();
+
     // Resize the viewing area within the total framebuffer display
     bool resize_view(int width, int height);
     
@@ -184,7 +187,6 @@ private:
     /// reverts disable_terminal() changes
     bool enable_terminal();
     
-    int         _fd;
     int         _original_vt;   // virtual terminal that was active at startup
     int         _original_kd;   // keyboard mode at startup
     int         _own_vt;        // virtual terminal we are running in   
diff --git a/gui/gtk/gtk.cpp b/gui/gtk/gtk.cpp
index 6f6d828..7fc22c8 100644
--- a/gui/gtk/gtk.cpp
+++ b/gui/gtk/gtk.cpp
@@ -144,6 +144,7 @@ GtkGui::GtkGui(unsigned long xid, float scale, bool loop, RunResources& r)
     ,_popup_menu_alt(0)
     ,_menubar(0)
     ,_vbox(0)
+    ,_exiting(false)
     ,_advanceSourceTimer(0)
 {
 }
@@ -255,7 +256,11 @@ GtkGui::run()
     // Kick-start before setting the interval timeout
     advance_movie(this);
 
-    gtk_main();
+    if (!_exiting)
+    {
+        gtk_main();
+    }
+    gtk_widget_destroy(_window);
     return true;
 }
 
@@ -589,8 +594,12 @@ GtkGui::quitUI()
     // Unregister the callback registered by setTimeout, if any. This also
     // removes other callbacks, but we're about to go away anyway.
     while (g_source_remove_by_user_data(this)) {}
-    gtk_widget_destroy(_window);
-    gtk_main_quit();
+
+    _exiting = true;
+    if (gtk_main_level() > 0)
+    {
+        gtk_main_quit();
+    }
 }
 
 /*private*/
diff --git a/gui/gtk/gtksup.h b/gui/gtk/gtksup.h
index 1cefe35..7250a00 100644
--- a/gui/gtk/gtksup.h
+++ b/gui/gtk/gtksup.h
@@ -144,6 +144,9 @@ private:
     GtkWidget* _menubar;
     GtkWidget* _vbox;
 
+    /// Exit flag, set by quitUI() to prevent entering gtk_main() if Gnash
+    /// terminated in first frame.
+    bool _exiting;
 
     /// Add key press events to the toplevel window.
     //
diff --git a/gui/qt/Qt4Glue.cpp b/gui/qt/Qt4Glue.cpp
index 83f05eb..c3245d6 100644
--- a/gui/qt/Qt4Glue.cpp
+++ b/gui/qt/Qt4Glue.cpp
@@ -75,9 +75,10 @@ DrawingWidget::contextMenuEvent(QContextMenuEvent* event)
 }
 
 void
-DrawingWidget::mousePressEvent(QMouseEvent* /* event */)
+DrawingWidget::mousePressEvent(QMouseEvent* event)
 {
-    _gui.notifyMouseClick(true);
+    if(Qt::LeftButton & event->button())
+	_gui.notifyMouseClick(true);
 }
 
 void
diff --git a/gui/qt/kde.cpp b/gui/qt/kde.cpp
index 1a3f544..0a31f7c 100644
--- a/gui/qt/kde.cpp
+++ b/gui/qt/kde.cpp
@@ -451,9 +451,10 @@ qwidget::contextMenuEvent(QContextMenuEvent*)
 #endif
 
 void
-qwidget::mousePressEvent(QMouseEvent* /* event */)
+qwidget::mousePressEvent(QMouseEvent* event)
 {
-    _godfather->notifyMouseClick(true);
+    if(Qt::LeftButton & event->button())
+	_godfather->notifyMouseClick(true);
 }
 
 void
diff --git a/libbase/log.cpp b/libbase/log.cpp
index c74cd5c..1037de2 100644
--- a/libbase/log.cpp
+++ b/libbase/log.cpp
@@ -102,7 +102,7 @@ namespace {
 
         std::uint64_t diff = clocktime::getTicks() - t.startTicks;
         // should we split in seconds/ms ?
-        o << getpid() << ":" << htid << "] " << diff;
+        o << "[" << getpid() << ":" << htid << "] " << diff;
 
         return o;
 
diff --git a/libcore/ExternalInterface.cpp b/libcore/ExternalInterface.cpp
index 3f24c95..8801696 100644
--- a/libcore/ExternalInterface.cpp
+++ b/libcore/ExternalInterface.cpp
@@ -1,7 +1,7 @@
 // ExternalInterface.cpp:  ActionScript "ExternalInterface" support
 //
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-//   Free Software Foundation, Inc
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014,
+//   2015, 2016 Free Software Foundation, Inc
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -115,7 +115,7 @@ ExternalInterface::_toXML(const as_value &val)
     } else if (val.is_number()) {
         ss << "<number>" << val.to_string() << "</number>";
     } else if (val.is_undefined()) {
-        ss << "<undefined/>";
+        ss << "<void/>";
     } else if (val.is_null()) {
         ss << "<null/>";
         // Exception isn't listed in any docs, but we'll use it for
diff --git a/libcore/asobj/Function_as.cpp b/libcore/asobj/Function_as.cpp
index f276109..879c927 100644
--- a/libcore/asobj/Function_as.cpp
+++ b/libcore/asobj/Function_as.cpp
@@ -104,13 +104,13 @@ function_apply(const fn_call& fn)
         IF_VERBOSE_ASCODING_ERRORS(
             log_aserror(_("Function.apply() called with no args"));
         );
-        new_fn_call.this_ptr = new as_object(getGlobal(fn));
+        new_fn_call.this_ptr = &getGlobal(fn);
 	}
 	else {
 		// Get the object to use as 'this' reference
 		as_object* obj = toObject(fn.arg(0), getVM(fn));
 
-        if (!obj) obj = new as_object(getGlobal(fn)); 
+        if (!obj) obj = &getGlobal(fn);
 
         new_fn_call.this_ptr = obj;
 
@@ -156,7 +156,7 @@ function_call(const fn_call& fn)
     as_object* tp;
 
     if (!fn.nargs || fn.arg(0).is_undefined() || fn.arg(0).is_null()) {
-        tp = new as_object(getGlobal(fn));
+        tp = &getGlobal(fn);
     }
     else tp = toObject(fn.arg(0), getVM(fn));
 
diff --git a/libcore/asobj/MovieClip_as.cpp b/libcore/asobj/MovieClip_as.cpp
index 391f037..02b8cce 100644
--- a/libcore/asobj/MovieClip_as.cpp
+++ b/libcore/asobj/MovieClip_as.cpp
@@ -1,6 +1,7 @@
 // MovieClip_as.cpp:  ActionScript "MovieClip" class, for Gnash.
 //
-//   Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+//   Copyright (C) 2009, 2010, 2011, 2012, 2014, 2016
+//   Free Software Foundation, Inc.
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -1494,7 +1495,7 @@ movieclip_lineStyle(const fn_call& fn)
 {
     MovieClip* movieclip = ensure<IsDisplayObject<MovieClip> >(fn);
 
-    if (!fn.nargs) {
+    if (!fn.nargs || fn.arg(0).is_undefined()) {
         movieclip->graphics().resetLineStyle();
         return as_value();
     }
@@ -1607,8 +1608,14 @@ movieclip_lineStyle(const fn_call& fn)
             b = std::uint8_t((rgbval & 0x0000FF) );
         }
         case 1:
+            double thicknessval = toNumber(fn.arg(0), getVM(fn));
+            if (!isFinite(thicknessval) || isNaN(thicknessval)) {
+                // Infinite (including positive infinite) and NaN are treated
+                // as hairline thickness.
+                thicknessval = 0;
+            }
             thickness = std::uint16_t(pixelsToTwips(clamp<float>(
-                            toNumber(fn.arg(0), getVM(fn)), 0, 255)));
+                            thicknessval, 0, 255)));
             break;
     }
 
diff --git a/libcore/asobj/NetStream_as.cpp b/libcore/asobj/NetStream_as.cpp
index 99d2a7a..bd2cd4b 100644
--- a/libcore/asobj/NetStream_as.cpp
+++ b/libcore/asobj/NetStream_as.cpp
@@ -1,7 +1,7 @@
 // NetStream.cpp:  ActionScript class for streaming audio/video, for Gnash.
 // 
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-//   Free Software Foundation, Inc
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014,
+//   2016 Free Software Foundation, Inc
 // 
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -194,6 +194,8 @@ NetStream_as::bufferLength()
 #ifdef USE_MEDIA
     if (_parser.get() == nullptr) return 0;
     return _parser->getBufferLength();
+#else
+    return 0;
 #endif  // USE_MEDIA
 }
 
@@ -622,6 +624,8 @@ NetStream_as::getDecodedVideoFrame(std::uint32_t ts)
             break; 
         }
     }
+#else // ndef USE_MEDIA
+    UNUSED(ts);
 #endif  // USE_MEDIA
     
     return video;
@@ -711,9 +715,10 @@ NetStream_as::decodeNextAudioFrame()
 #endif 
 
     raw->m_ptr = raw->m_data;
-#endif  // USE_MEDIA
-    
     return raw;
+#else   // USE_MEDIA
+    return nullptr;
+#endif
 }
 
 void
@@ -1051,6 +1056,8 @@ NetStream_as::pushDecodedAudioFrames(std::uint32_t ts)
 
         _playHead.setAudioConsumed();
     }
+#else // ndef USE_MEDIA
+    UNUSED(ts);
 #endif  // USE_MEDIA
 }
 
diff --git a/libcore/asobj/Sound_as.cpp b/libcore/asobj/Sound_as.cpp
index 4a6d11c..106cd79 100644
--- a/libcore/asobj/Sound_as.cpp
+++ b/libcore/asobj/Sound_as.cpp
@@ -1,6 +1,7 @@
 // Sound_as.cpp:  ActionScript "Sound" class, for Gnash.
 //
-//   Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+//   Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2016
+//   Free Software Foundation, Inc.
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -364,6 +365,7 @@ Sound_as::probeAudio()
 
     if (!_mediaParser) return; // nothing to do here w/out a media parser
 
+#ifdef USE_MEDIA
     if ( ! _soundLoaded ) {
 #ifdef GNASH_DEBUG_SOUND_AS
         log_debug("Probing audio for load");
@@ -441,6 +443,7 @@ Sound_as::probeAudio()
             assert(_audioDecoder.get());
         }
     }
+#endif  // USE_MEDIA
 #endif  // USE_SOUND
 }
 
@@ -810,12 +813,14 @@ Sound_as::getPosition() const
         return _soundHandler->tell(soundId);
     }
 
+#ifdef USE_MEDIA
     if (_mediaParser) {
         std::uint64_t ts;
         if ( _mediaParser->nextAudioFrameTimestamp(ts) ) {
             return ts;
         }
     }
+#endif  // USE_MEDIA
 #endif  // USE_SOUND
     
     return 0;
@@ -825,10 +830,9 @@ Sound_as::getPosition() const
 unsigned int
 Sound_as::getAudio(std::int16_t* samples, unsigned int nSamples, bool& atEOF)
 {
+#if defined USE_SOUND && defined USE_MEDIA
     std::uint8_t* stream = reinterpret_cast<std::uint8_t*>(samples);
     int len = nSamples*2;
-
-#ifdef USE_SOUND
     //GNASH_REPORT_FUNCTION;
 
     while (len) {
@@ -900,7 +904,12 @@ Sound_as::getAudio(std::int16_t* samples, unsigned int nSamples, bool& atEOF)
 
     atEOF=false;
     return nSamples-(len/2);
-#endif  // USE_SOUND
+#else   // USE_MEDIA && USE_SOUND
+    UNUSED(samples);
+    UNUSED(nSamples);
+    UNUSED(atEOF);
+    return 0;
+#endif
 }
 
 // audio callback is running in sound handler thread
diff --git a/libcore/asobj/flash/external/ExternalInterface_as.cpp b/libcore/asobj/flash/external/ExternalInterface_as.cpp
index 04c12bf..9bf2564 100644
--- a/libcore/asobj/flash/external/ExternalInterface_as.cpp
+++ b/libcore/asobj/flash/external/ExternalInterface_as.cpp
@@ -1,7 +1,7 @@
 // ExternalInterface_as.cpp:  ActionScript "ExternalInterface" class, for Gnash.
 //
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-//   Free Software Foundation, Inc
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014,
+//   2015, 2016 Free Software Foundation, Inc
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -286,7 +286,7 @@ externalinterface_call(const fn_call& fn)
         return val;
     }
 
-    if (fn.nargs > 1) {
+    if (fn.nargs >= 1) {
         const as_value& methodName_as = fn.arg(0);
         const std::string methodName = methodName_as.to_string();
         const std::vector<as_value>& args = fn.getArgs();
@@ -294,13 +294,7 @@ externalinterface_call(const fn_call& fn)
         std::string result = mr.callExternalJavascript(methodName, args);
         if (!result.empty()) {
             val = ExternalInterface::parseXML(result);
-            // There was an error trying to Invoke the callback
-            if (result == ExternalInterface::makeString("Error")
-                || (result == ExternalInterface::makeString("SecurityError"))) {
-                log_trace(_("VAL: %s"), val);
-                val.set_undefined();
-            }
-        } 
+        }
     }
     
     return val;
diff --git a/libcore/movie_root.cpp b/libcore/movie_root.cpp
index 3c643e9..cb63f7d 100644
--- a/libcore/movie_root.cpp
+++ b/libcore/movie_root.cpp
@@ -1596,13 +1596,17 @@ movie_root::processInvoke(ExternalInterface::invoke_t *invoke)
         MovieClip *mc = getLevel(0);
         as_object *obj = getObject(mc);
         VM &vm = getVM();
+        as_environment timeline = mc->get_environment();
+        as_environment::ScopeStack scope;
+        as_object *container = NULL;
         std::string var = invoke->args[0].to_string();
-        as_value val;
-        if (obj->get_member(getURI(vm, var), &val)) {
+        scope.push_back(obj);
+        as_value val = getVariable(timeline, var, scope, &container);
+        if (container != NULL) {
             // If the variable exists, GetVariable returns a string
             // representation of its value. Variable with undefined
             // or null value counts as exist too.
-            ss << ExternalInterface::toXML(val.to_string());
+            ss << ExternalInterface::toXML(val.to_string(vm.getSWFVersion()));
             ss << std::endl;
         } else {
             // If the variable does not exist, GetVariable sends null value
@@ -1675,12 +1679,7 @@ movie_root::processInvoke(ExternalInterface::invoke_t *invoke)
         ss << ExternalInterface::toXML(val);
         ss << std::endl;
     } else {
-        std::string result = callExternalCallback(invoke->name, invoke->args);
-        if (result == ExternalInterface::makeString("Error")) {
-            return false;
-        } else if (result == ExternalInterface::makeString("SecurityError")) {
-            return false;
-        }
+        callExternalCallback(invoke->name, invoke->args);
         return true;
     }
 
@@ -1943,6 +1942,12 @@ movie_root::callExternalCallback(const std::string &name,
         }
         else instance = instance_iterator->second;
 
+        // Use _global object as "this" instance if the callback is originally
+        // registered with null or undefined one.
+        if (instance == NULL) {
+            instance = &getGlobal(*method);
+        }
+
         // Populate function call arguments
         for (std::vector<as_value>::const_iterator args_iterator
                  = fnargs.begin();
@@ -1957,13 +1962,8 @@ movie_root::callExternalCallback(const std::string &name,
     }
 
     std::string result;
-    if (val.is_null()) {
-        // Return an error
-        result = ExternalInterface::makeString("Error");
-    } else {
-        result = ExternalInterface::toXML(val);
-    }
-        
+    result = ExternalInterface::toXML(val);
+
     // If the browser is connected, we send an Invoke message to the
     // browser.
     if (_hostfd >= 0) {
diff --git a/libmedia/MediaParser.cpp b/libmedia/MediaParser.cpp
index 7a7642d..8f40fb9 100644
--- a/libmedia/MediaParser.cpp
+++ b/libmedia/MediaParser.cpp
@@ -1,6 +1,6 @@
 // MediaParser.cpp:  Media file parser, for Gnash.
 //
-//   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
+//   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016
 //   Free Software Foundation, Inc.
 //
 // This program is free software; you can redistribute it and/or modify
@@ -468,42 +468,6 @@ operator<< (std::ostream& os, const videoCodecType& t)
     return os;
 }
 
-std::ostream&
-operator<< (std::ostream& os, const audioCodecType& t)
-{
-    switch (t)
-    {
-        case AUDIO_CODEC_RAW:
-            os << "Raw";
-            break;
-        case AUDIO_CODEC_ADPCM:
-            os << "ADPCM";
-            break;
-        case AUDIO_CODEC_MP3:
-            os << "MP3";
-            break;
-        case AUDIO_CODEC_UNCOMPRESSED:
-            os << "Uncompressed";
-            break;
-        case AUDIO_CODEC_NELLYMOSER_8HZ_MONO:
-            os << "Nellymoser 8Hz mono";
-            break;
-        case AUDIO_CODEC_NELLYMOSER:
-            os << "Nellymoser";
-            break;
-        case AUDIO_CODEC_AAC:
-            os << "Advanced Audio Coding";
-            break;
-        case AUDIO_CODEC_SPEEX:
-            os << "Speex";
-            break;
-        default:
-            os << "unknown/invalid codec " << static_cast<int>(t);
-            break;
-    }
-    return os;
-}
-
 } // end of gnash::media namespace
 } // end of gnash namespace
 
diff --git a/libmedia/MediaParser.h b/libmedia/MediaParser.h
index e9f28c1..0efe8f2 100644
--- a/libmedia/MediaParser.h
+++ b/libmedia/MediaParser.h
@@ -1,6 +1,6 @@
 // MediaParser.h: Base class for media parsers
 // 
-//   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
+//   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016
 //   Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
@@ -28,7 +28,7 @@
 #include <deque>
 #include <map>
 #include <vector>
-#include <iosfwd> // for output operator forward declarations
+#include <iostream> // for output operator
 #include <boost/optional.hpp>
 
 #include "IOChannel.h" // for inlines
@@ -190,7 +190,41 @@ enum audioCodecType
 	//       also add them to the output operator!
 };
 
-DSOEXPORT std::ostream& operator<< (std::ostream& os, const audioCodecType& t);
+inline std::ostream&
+operator<< (std::ostream& os, const audioCodecType& t)
+{
+    switch (t)
+    {
+        case AUDIO_CODEC_RAW:
+            os << "Raw";
+            break;
+        case AUDIO_CODEC_ADPCM:
+            os << "ADPCM";
+            break;
+        case AUDIO_CODEC_MP3:
+            os << "MP3";
+            break;
+        case AUDIO_CODEC_UNCOMPRESSED:
+            os << "Uncompressed";
+            break;
+        case AUDIO_CODEC_NELLYMOSER_8HZ_MONO:
+            os << "Nellymoser 8Hz mono";
+            break;
+        case AUDIO_CODEC_NELLYMOSER:
+            os << "Nellymoser";
+            break;
+        case AUDIO_CODEC_AAC:
+            os << "Advanced Audio Coding";
+            break;
+        case AUDIO_CODEC_SPEEX:
+            os << "Speex";
+            break;
+        default:
+            os << "unknown/invalid codec " << static_cast<int>(t);
+            break;
+    }
+    return os;
+}
 
 /// Information about an audio stream 
 //
diff --git a/libmedia/ffmpeg/VideoConverterFfmpeg.cpp b/libmedia/ffmpeg/VideoConverterFfmpeg.cpp
index 74aa55f..da11e5d 100644
--- a/libmedia/ffmpeg/VideoConverterFfmpeg.cpp
+++ b/libmedia/ffmpeg/VideoConverterFfmpeg.cpp
@@ -57,7 +57,7 @@ private:
 
 // The lookup table in this function is adapted from chroma.c from the VLC
 // codebase; its license permits distribution under GPLv3 and later.
-PixelFormat
+AVPixelFormat
 fourcc_to_ffmpeg(ImgBuf::Type4CC code)
 {
 
@@ -68,40 +68,40 @@ fourcc_to_ffmpeg(ImgBuf::Type4CC code)
     static const struct
     {
         ImgBuf::Type4CC  fourcc;
-        PixelFormat ffmpegcode;
+        AVPixelFormat ffmpegcode;
     } pixfmt_table[] =
     {
         // Planar YUV formats
-        {GNASH_FOURCC('I','4','4','4'), PIX_FMT_YUV444P},
-        {GNASH_FOURCC('J','4','4','4'), PIX_FMT_YUVJ444P},
+        {GNASH_FOURCC('I','4','4','4'), AV_PIX_FMT_YUV444P},
+        {GNASH_FOURCC('J','4','4','4'), AV_PIX_FMT_YUVJ444P},
 
 #if LIBAVUTIL_VERSION_INT >= ((49<<16)+(5<<8)+0)
-        {GNASH_FOURCC('I','4','4','0'), PIX_FMT_YUV440P},
-        {GNASH_FOURCC('J','4','4','0'), PIX_FMT_YUVJ440P},
+        {GNASH_FOURCC('I','4','4','0'), AV_PIX_FMT_YUV440P},
+        {GNASH_FOURCC('J','4','4','0'), AV_PIX_FMT_YUVJ440P},
 #endif
 
-        {GNASH_FOURCC('I','4','2','2'), PIX_FMT_YUV422P},
-        {GNASH_FOURCC('J','4','2','2'), PIX_FMT_YUVJ422P},
+        {GNASH_FOURCC('I','4','2','2'), AV_PIX_FMT_YUV422P},
+        {GNASH_FOURCC('J','4','2','2'), AV_PIX_FMT_YUVJ422P},
 
-        {GNASH_FOURCC('I','4','2','0'), PIX_FMT_YUV420P},
-        {GNASH_FOURCC('Y','V','1','2'), PIX_FMT_YUV420P},
-        {GNASH_FOURCC('I','Y','U','V'), PIX_FMT_YUV420P},
-        {GNASH_FOURCC('J','4','2','0'), PIX_FMT_YUVJ420P},
-        {GNASH_FOURCC('I','4','1','1'), PIX_FMT_YUV411P},
-        {GNASH_FOURCC('I','4','1','0'), PIX_FMT_YUV410P},
-        {GNASH_FOURCC('Y','V','U','9'), PIX_FMT_YUV410P},
+        {GNASH_FOURCC('I','4','2','0'), AV_PIX_FMT_YUV420P},
+        {GNASH_FOURCC('Y','V','1','2'), AV_PIX_FMT_YUV420P},
+        {GNASH_FOURCC('I','Y','U','V'), AV_PIX_FMT_YUV420P},
+        {GNASH_FOURCC('J','4','2','0'), AV_PIX_FMT_YUVJ420P},
+        {GNASH_FOURCC('I','4','1','1'), AV_PIX_FMT_YUV411P},
+        {GNASH_FOURCC('I','4','1','0'), AV_PIX_FMT_YUV410P},
+        {GNASH_FOURCC('Y','V','U','9'), AV_PIX_FMT_YUV410P},
 
 #if LIBAVUTIL_VERSION_INT >= ((49<<16)+(0<<8)+1)
-        {GNASH_FOURCC('N','V','1','2'), PIX_FMT_NV12},
-        {GNASH_FOURCC('N','V','2','1'), PIX_FMT_NV21},
+        {GNASH_FOURCC('N','V','1','2'), AV_PIX_FMT_NV12},
+        {GNASH_FOURCC('N','V','2','1'), AV_PIX_FMT_NV21},
 #endif
 
-        {GNASH_FOURCC('Y','U','Y','2'), PIX_FMT_YUYV422},
-        {GNASH_FOURCC('Y','U','Y','V'), PIX_FMT_YUYV422},
-        {GNASH_FOURCC('U','Y','V','Y'), PIX_FMT_UYVY422},
-        {GNASH_FOURCC('Y','4','1','1'), PIX_FMT_UYYVYY411},
+        {GNASH_FOURCC('Y','U','Y','2'), AV_PIX_FMT_YUYV422},
+        {GNASH_FOURCC('Y','U','Y','V'), AV_PIX_FMT_YUYV422},
+        {GNASH_FOURCC('U','Y','V','Y'), AV_PIX_FMT_UYVY422},
+        {GNASH_FOURCC('Y','4','1','1'), AV_PIX_FMT_UYYVYY411},
 
-        { 0, PIX_FMT_NONE}
+        { 0, AV_PIX_FMT_NONE}
     };
 #undef GNASH_FOURCC
 
@@ -112,13 +112,13 @@ fourcc_to_ffmpeg(ImgBuf::Type4CC code)
         }
     }
    
-    return PIX_FMT_NONE;
+    return AV_PIX_FMT_NONE;
 }
 
 VideoConverterFfmpeg::VideoConverterFfmpeg(ImgBuf::Type4CC srcFormat, ImgBuf::Type4CC dstFormat)
     : VideoConverter(srcFormat, dstFormat)
 {
-     if(fourcc_to_ffmpeg(_dst_fmt) == PIX_FMT_NONE) {
+     if(fourcc_to_ffmpeg(_dst_fmt) == AV_PIX_FMT_NONE) {
          throw MediaException(_("VideoConverterFfmpeg cannot convert to the "
                               "requested format"));
      }
@@ -138,9 +138,9 @@ VideoConverterFfmpeg::convert(const ImgBuf& src)
     const int width = src.width;
     const int height = src.height;
 
-    PixelFormat dst_pixFmt = fourcc_to_ffmpeg(_dst_fmt);
-    assert(dst_pixFmt != PIX_FMT_NONE);
-    PixelFormat src_pixFmt = PIX_FMT_RGB24;
+    AVPixelFormat dst_pixFmt = fourcc_to_ffmpeg(_dst_fmt);
+    assert(dst_pixFmt != AV_PIX_FMT_NONE);
+    AVPixelFormat src_pixFmt = AV_PIX_FMT_RGB24;
     
 #ifdef HAVE_SWSCALE_H
 
diff --git a/libmedia/ffmpeg/VideoDecoderFfmpeg.cpp b/libmedia/ffmpeg/VideoDecoderFfmpeg.cpp
index 20d49b9..caa0377 100644
--- a/libmedia/ffmpeg/VideoDecoderFfmpeg.cpp
+++ b/libmedia/ffmpeg/VideoDecoderFfmpeg.cpp
@@ -51,7 +51,7 @@ namespace {
     void set_vaapi_context(AVCodecContext* avctx, VaapiContextFfmpeg* vactx);
     void clear_vaapi_context(AVCodecContext* avctx);
     void reset_context(AVCodecContext* avctx, VaapiContextFfmpeg* vactx = nullptr);
-    PixelFormat get_format(AVCodecContext* avctx, const PixelFormat* fmt);
+    AVPixelFormat get_format(AVCodecContext* avctx, const AVPixelFormat* fmt);
 #if LIBAVCODEC_VERSION_MAJOR >= 55
     int get_buffer(AVCodecContext* avctx, AVFrame* pic, int flags);
 #else
@@ -251,16 +251,16 @@ VideoDecoderFfmpeg::frameToImage(AVCodecContext* srcCtx,
                                  const AVFrame& srcFrameRef)
 {
     const AVFrame *srcFrame = &srcFrameRef;
-    PixelFormat srcPixFmt = srcCtx->pix_fmt;
+    AVPixelFormat srcPixFmt = srcCtx->pix_fmt;
 
     const int width = srcCtx->width;
     const int height = srcCtx->height;
 
 #ifdef FFMPEG_VP6A
-    PixelFormat pixFmt = (srcCtx->codec->id == AV_CODEC_ID_VP6A) ?
-        PIX_FMT_RGBA : PIX_FMT_RGB24;
+    AVPixelFormat pixFmt = (srcCtx->codec->id == AV_CODEC_ID_VP6A) ?
+        AV_PIX_FMT_RGBA : AV_PIX_FMT_RGB24;
 #else 
-    PixelFormat pixFmt = PIX_FMT_RGB24;
+    AVPixelFormat pixFmt = AV_PIX_FMT_RGB24;
 #endif 
 
     std::unique_ptr<image::GnashImage> im;
@@ -306,10 +306,10 @@ VideoDecoderFfmpeg::frameToImage(AVCodecContext* srcCtx,
 
     switch (pixFmt)
     {
-        case PIX_FMT_RGBA:
+        case AV_PIX_FMT_RGBA:
             im.reset(new image::ImageRGBA(width, height));
             break;
-        case PIX_FMT_RGB24:
+        case AV_PIX_FMT_RGB24:
             im.reset(new image::ImageRGB(width, height));
             break;
         default:
@@ -325,7 +325,7 @@ VideoDecoderFfmpeg::frameToImage(AVCodecContext* srcCtx,
     avpicture_fill(&picture, im->begin(), pixFmt, width, height);
 
 #ifndef HAVE_SWSCALE_H
-    img_convert(&picture, PIX_FMT_RGB24, (AVPicture*)srcFrame,
+    img_convert(&picture, AV_PIX_FMT_RGB24, (AVPicture*)srcFrame,
             srcPixFmt, width, height);
 #else
 
@@ -499,15 +499,15 @@ reset_context(AVCodecContext* avctx, VaapiContextFfmpeg* vactx)
 }
 
 /// AVCodecContext.get_format() implementation
-PixelFormat
-get_format(AVCodecContext* avctx, const PixelFormat* fmt)
+AVPixelFormat
+get_format(AVCodecContext* avctx, const AVPixelFormat* fmt)
 {
 #ifdef HAVE_VA_VA_H
     VaapiContextFfmpeg* const vactx = get_vaapi_context(avctx);
 
     if (vactx) {
-        for (int i = 0; fmt[i] != PIX_FMT_NONE; i++) {
-            if (fmt[i] != PIX_FMT_VAAPI_VLD) continue;
+        for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++) {
+            if (fmt[i] != AV_PIX_FMT_VAAPI_VLD) continue;
 
             if (vactx->initDecoder(avctx->width, avctx->height)) {
                 return fmt[i];
diff --git a/libmedia/ffmpeg/ffmpegHeaders.h b/libmedia/ffmpeg/ffmpegHeaders.h
index 2e4944e..d8f9b26 100644
--- a/libmedia/ffmpeg/ffmpegHeaders.h
+++ b/libmedia/ffmpeg/ffmpegHeaders.h
@@ -185,4 +185,27 @@ extern "C" {
 }
 #endif
 
+#if LIBAVUTIL_VERSION_MAJOR < 55
+#define AVPixelFormat        PixelFormat
+#define AV_PIX_FMT_YUV444P   PIX_FMT_YUV444P
+#define AV_PIX_FMT_YUVJ444P  PIX_FMT_YUVJ444P
+#define AV_PIX_FMT_YUV440P   PIX_FMT_YUV440P
+#define AV_PIX_FMT_YUVJ440P  PIX_FMT_YUVJ440P
+#define AV_PIX_FMT_YUV422P   PIX_FMT_YUV422P
+#define AV_PIX_FMT_YUVJ422P  PIX_FMT_YUVJ422P
+#define AV_PIX_FMT_YUV420P   PIX_FMT_YUV420P
+#define AV_PIX_FMT_YUVJ420P  PIX_FMT_YUVJ420P
+#define AV_PIX_FMT_YUV411P   PIX_FMT_YUV411P
+#define AV_PIX_FMT_YUV410P   PIX_FMT_YUV410P
+#define AV_PIX_FMT_NV12      PIX_FMT_NV12
+#define AV_PIX_FMT_NV21      PIX_FMT_NV21
+#define AV_PIX_FMT_YUYV422   PIX_FMT_YUYV422
+#define AV_PIX_FMT_UYVY422   PIX_FMT_UYVY422
+#define AV_PIX_FMT_UYYVYY411 PIX_FMT_UYYVYY411
+#define AV_PIX_FMT_NONE      PIX_FMT_NONE
+#define AV_PIX_FMT_RGB24     PIX_FMT_RGB24
+#define AV_PIX_FMT_RGBA      PIX_FMT_RGBA
+#define AV_PIX_FMT_VAAPI_VLD PIX_FMT_VAAPI_VLD
+#endif
+
 #endif // GNASH_MEDIA_FFMPEG_HEADERS_H
diff --git a/libsound/Makefile.am b/libsound/Makefile.am
index a771188..1d0e092 100644
--- a/libsound/Makefile.am
+++ b/libsound/Makefile.am
@@ -1,5 +1,5 @@
 # 
-#   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
+#   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2016
 #    Free Software Foundation, Inc.
 # 
 # This program is free software; you can redistribute it and/or modify
@@ -73,8 +73,13 @@ libgnashsound_la_CPPFLAGS = \
 	$(SDL_CFLAGS) \
 	$(NULL)
 
-libgnashsound_la_LIBADD = \
-	$(top_builddir)/libmedia/libgnashmedia.la \
+if BUILD_LIBMEDIA
+libgnashsound_la_LIBADD = $(top_builddir)/libmedia/libgnashmedia.la
+else
+libgnashsound_la_LIBADD =
+endif
+
+libgnashsound_la_LIBADD += \
 	$(top_builddir)/libbase/libgnashbase.la \
 	$(BOOST_LIBS) \
 	$(SDL_LIBS) \
diff --git a/libsound/sound_handler.cpp b/libsound/sound_handler.cpp
index 454a03e..744bccc 100644
--- a/libsound/sound_handler.cpp
+++ b/libsound/sound_handler.cpp
@@ -1,6 +1,6 @@
 //
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-//   Free Software Foundation, Inc
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014,
+//   2015, 2016 Free Software Foundation, Inc
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -500,6 +500,10 @@ sound_handler::playStream(int soundId, StreamBlockId blockId)
     if (s.isPlaying() || s.empty()) return;
 
     try {
+        if (!_mediaHandler) {
+            throw MediaException("No media handler available");
+        }
+
         std::unique_ptr<InputStream> is(
                 s.createInstance(*_mediaHandler, blockId));
         plugInputStream(std::move(is));
@@ -588,6 +592,10 @@ sound_handler::startSound(int handle, int loops, const SoundEnvelopes* env,
     }
 
     try {
+        if (!_mediaHandler) {
+            throw MediaException("No media handler available");
+        }
+
         // Make an InputStream for this sound and plug it into  
         // the set of InputStream channels
         std::unique_ptr<InputStream> sound(
diff --git a/plugin/npapi/callbacks.cpp b/plugin/npapi/callbacks.cpp
index 081c72d..b2c61af 100644
--- a/plugin/npapi/callbacks.cpp
+++ b/plugin/npapi/callbacks.cpp
@@ -1,5 +1,5 @@
 // 
-//   Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc
+//   Copyright (C) 2010, 2011, 2012, 2016 Free Software Foundation, Inc
 // 
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -230,7 +230,7 @@ IsPlaying (NPObject *npobj, NPIdentifier /* name */, const NPVariant */*args */,
             return false;
         }
 
-        GnashNPVariant value = plugin::ExternalInterface::parseXML(data);
+        GnashNPVariant value = plugin::ExternalInterface::parseXML((GnashPluginScriptObject*)npobj, data);
         if (NPVARIANT_TO_BOOLEAN(value.get()) == true) {
             BOOLEAN_TO_NPVARIANT(true, *result);
         } else {
@@ -374,7 +374,7 @@ PercentLoaded (NPObject *npobj, NPIdentifier /* name */, const NPVariant */*args
             return false;
         }
         
-        GnashNPVariant value = plugin::ExternalInterface::parseXML(data);
+        GnashNPVariant value = plugin::ExternalInterface::parseXML((GnashPluginScriptObject*)npobj, data);
         if (NPVARIANT_IS_INT32(value.get())) {
             INT32_TO_NPVARIANT(NPVARIANT_TO_INT32(value.get()), *result);
         } else {
@@ -628,7 +628,7 @@ TotalFrames (NPObject *npobj, NPIdentifier /* name */, const NPVariant */*args *
             return false;
         }
 
-        GnashNPVariant value = plugin::ExternalInterface::parseXML(data);
+        GnashNPVariant value = plugin::ExternalInterface::parseXML((GnashPluginScriptObject*)npobj, data);
         if (NPVARIANT_IS_INT32(value.get())) {
             value.copy(*result);
         } else {
@@ -699,19 +699,9 @@ remoteCallback (NPObject *npobj, NPIdentifier name, const NPVariant *args,
         return false;
     }
 
-    std::string answer;
-    GnashNPVariant parsed = plugin::ExternalInterface::parseXML(data);
-    if (!NPVARIANT_IS_NULL(parsed.get())) {
-        answer = NPStringToString(NPVARIANT_TO_STRING(parsed.get()));
-    }
-    if (answer == "Error") {
-        NULL_TO_NPVARIANT(*result);
-    } else if (answer == "SecurityError") {
-        NULL_TO_NPVARIANT(*result);
-    } else {
-        parsed.copy(*result);
-    }
-    
+    GnashNPVariant parsed = plugin::ExternalInterface::parseXML((GnashPluginScriptObject*)npobj, data);
+    parsed.copy(*result);
+
     // printNPVariant(&parsed.get());
 
     // Returning false makes Javascript stop executing the script.
diff --git a/plugin/npapi/external.cpp b/plugin/npapi/external.cpp
index a1c199e..4ebce1d 100644
--- a/plugin/npapi/external.cpp
+++ b/plugin/npapi/external.cpp
@@ -1,5 +1,5 @@
 // 
-//   Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc
+//   Copyright (C) 2010, 2011, 2012, 2014, 2016 Free Software Foundation, Inc
 // 
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -200,7 +200,7 @@ ExternalInterface::makeObject (std::map<std::string, std::string> &args)
 //      </arguments>
 // </invoke>
 std::shared_ptr<ExternalInterface::invoke_t>
-ExternalInterface::parseInvoke(const std::string &xml)
+ExternalInterface::parseInvoke(GnashPluginScriptObject *scriptobj, const std::string &xml)
 {
     std::shared_ptr<ExternalInterface::invoke_t> invoke;
     if (xml.empty()) {
@@ -254,7 +254,7 @@ ExternalInterface::parseInvoke(const std::string &xml)
             end   = xml.find("</invoke");
             if (start != std::string::npos && end != std::string::npos) {
                     tag   = xml.substr(start, end-start);
-                    invoke->args = parseArguments(tag);
+                    invoke->args = parseArguments(scriptobj, tag);
                 }
         }
     }
@@ -263,7 +263,7 @@ ExternalInterface::parseInvoke(const std::string &xml)
 }
 
 GnashNPVariant 
-ExternalInterface::parseXML(const std::string &xml)
+ExternalInterface::parseXML(GnashPluginScriptObject *scriptobj, const std::string &xml)
 {
     NPVariant value;
     NULL_TO_NPVARIANT(value);
@@ -293,13 +293,8 @@ ExternalInterface::parseXML(const std::string &xml)
             start = end;
             end = xml.find("</number>");
             std::string str = xml.substr(start, end-start);
-            if (str.find(".") != std::string::npos) {
-                double num = strtod(str.c_str(), nullptr);
-                DOUBLE_TO_NPVARIANT(num, value);
-            } else {
-                int num = strtol(str.c_str(), nullptr, 0);
-                INT32_TO_NPVARIANT(num, value);
-            }
+            double num = strtod(str.c_str(), nullptr);
+            DOUBLE_TO_NPVARIANT(num, value);
         } else if (tag == "<string>") {
             start = end;
             end = xml.find("</string>");
@@ -318,7 +313,7 @@ ExternalInterface::parseXML(const std::string &xml)
             end = xml.find("</array");
             if ( end != std::string::npos )  {
               std::string str = xml.substr(start, end-start);
-              std::map<std::string, GnashNPVariant> props = parseProperties(str);
+              std::map<std::string, GnashNPVariant> props = parseProperties(scriptobj, str);
               std::map<std::string, GnashNPVariant>::iterator it;
               for (it=props.begin(); it != props.end(); ++it) {
                   NPIdentifier id = NPN_GetStringIdentifier(it->first.c_str());
@@ -328,20 +323,39 @@ ExternalInterface::parseXML(const std::string &xml)
               OBJECT_TO_NPVARIANT(obj, value);
             }
         } else if (tag == "<object>") {
+            NPObject *jswindow;
+            NPObject *obj;
+            NPVariant objvar;
+
             start = end;
             end = xml.find("</object");
-            if ( end != std::string::npos )  {
-              NPObject *obj =  (NPObject *)NPN_MemAlloc(sizeof(NPObject));
-              obj->referenceCount = 1;
+            while ( end != std::string::npos )  {
+              // To create a new JavaScript Object, we call JavaScript's
+              // window.Object() method and use the returned NPObject.
+              // Then we assign members according to the received XML data.
+              if (NPN_GetValue(scriptobj->nppinstance, NPNVWindowNPObject,
+                               &jswindow) != NPERR_NO_ERROR) {
+                  break;
+              }
+              if (!NPN_Invoke(scriptobj->nppinstance, jswindow,
+                              NPN_GetStringIdentifier("Object"),
+                              NULL, 0, &objvar)) {
+                  NPN_ReleaseObject(jswindow);
+                  break;
+              }
+              obj = NPVARIANT_TO_OBJECT(objvar);
+
               std::string str = xml.substr(start, end-start);
-              std::map<std::string, GnashNPVariant> props = parseProperties(str);
+              std::map<std::string, GnashNPVariant> props = parseProperties(scriptobj, str);
               std::map<std::string, GnashNPVariant>::iterator it;
               for (it=props.begin(); it != props.end(); ++it) {
                   NPIdentifier id = NPN_GetStringIdentifier(it->first.c_str());
                   GnashNPVariant& value = it->second;
-                  NPN_SetProperty(nullptr, obj, id, &value.get());
+                  NPN_SetProperty(scriptobj->nppinstance, obj, id, &value.get());
               }
+              NPN_ReleaseObject(jswindow);
               OBJECT_TO_NPVARIANT(obj, value);
+              break;
             }
         }
     }
@@ -358,6 +372,7 @@ ExternalInterface::convertNPVariant (const NPVariant *value)
     
     if (NPVARIANT_IS_DOUBLE(*value)) {
         double num = NPVARIANT_TO_DOUBLE(*value);
+        ss.precision(std::numeric_limits<double>::max_digits10);
         ss << "<number>" << num << "</number>";
     } else if (NPVARIANT_IS_STRING(*value)) {
         std::string str = NPStringToString(NPVARIANT_TO_STRING(*value));
@@ -384,7 +399,7 @@ ExternalInterface::convertNPVariant (const NPVariant *value)
 }
 
 std::map<std::string, GnashNPVariant>
-ExternalInterface::parseProperties(const std::string &xml)
+ExternalInterface::parseProperties(GnashPluginScriptObject *scriptobj, const std::string &xml)
 {
     std::map<std::string, GnashNPVariant> props;
 
@@ -404,7 +419,7 @@ ExternalInterface::parseProperties(const std::string &xml)
         start = end + 2;
         end = xml.find("</property>", start) ;
         std::string data = xml.substr(start, end-start);
-        props[id] = parseXML(data);
+        props[id] = parseXML(scriptobj, data);
         start = xml.find(" id=", end);
     }
 
@@ -412,7 +427,7 @@ ExternalInterface::parseProperties(const std::string &xml)
 }
 
 std::vector<GnashNPVariant>
-ExternalInterface::parseArguments(const std::string &xml)
+ExternalInterface::parseArguments(GnashPluginScriptObject *scriptobj, const std::string &xml)
 {
     std::vector<GnashNPVariant> args;
 
@@ -437,7 +452,7 @@ ExternalInterface::parseArguments(const std::string &xml)
         if (data == "</arguments>") {
             break;
         }
-        args.push_back(parseXML(sub));
+        args.push_back(parseXML(scriptobj, sub));
         data.erase(0, end);
     }
 
diff --git a/plugin/npapi/external.h b/plugin/npapi/external.h
index 7a0aa67..6031bda 100644
--- a/plugin/npapi/external.h
+++ b/plugin/npapi/external.h
@@ -1,5 +1,5 @@
 // 
-//   Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc
+//   Copyright (C) 2010, 2011, 2012, 2014, 2016 Free Software Foundation, Inc
 // 
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -31,7 +31,7 @@
 #include "npapi.h"
 #include "npruntime.h"
 
-#include "GnashNPVariant.h"
+#include "pluginScriptObject.h"
 
 namespace gnash {
 
@@ -61,11 +61,11 @@ struct ExternalInterface
     static std::string makeArray (std::vector<std::string> &args);
     static std::string makeObject (std::map<std::string, std::string> &args);
     
-    static GnashNPVariant parseXML(const std::string &xml);
-    static std::shared_ptr<invoke_t> parseInvoke(const std::string &xml);
+    static GnashNPVariant parseXML(GnashPluginScriptObject *scriptobj, const std::string &xml);
+    static std::shared_ptr<invoke_t> parseInvoke(GnashPluginScriptObject *scriptobj, const std::string &xml);
     
-    static std::map<std::string, GnashNPVariant> parseProperties(const std::string &xml);
-    static std::vector<GnashNPVariant> parseArguments(const std::string &xml);
+    static std::map<std::string, GnashNPVariant> parseProperties(GnashPluginScriptObject *scriptobj, const std::string &xml);
+    static std::vector<GnashNPVariant> parseArguments(GnashPluginScriptObject *scriptobj, const std::string &xml);
     static std::string convertNPVariant (const NPVariant *npv);
 };
 
diff --git a/plugin/npapi/plugin.cpp b/plugin/npapi/plugin.cpp
index 3c6f423..96585e6 100644
--- a/plugin/npapi/plugin.cpp
+++ b/plugin/npapi/plugin.cpp
@@ -1,6 +1,6 @@
 // 
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-//   Free Software Foundation, Inc
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014,
+//   2016 Free Software Foundation, Inc
 // 
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -821,7 +821,7 @@ nsPluginInstance::processPlayerRequest()
         // Extract a message from the packet
         std::string msg = packet.substr(0, pos + term.size());
         std::shared_ptr<plugin::ExternalInterface::invoke_t> invoke =
-            plugin::ExternalInterface::parseInvoke(msg);
+            plugin::ExternalInterface::parseInvoke(_scriptObject, msg);
 
         // drop the parsed message from the packet
         packet.erase(0, msg.size());
@@ -949,14 +949,9 @@ nsPluginInstance::processPlayerRequest()
         }
         // We got a result from invoking the Javascript method
         std::stringstream ss;
-        if (invokeResult) {
-            ss << plugin::ExternalInterface::convertNPVariant(&result);
-            NPN_ReleaseVariantValue(&result);
-        } else {
-            // Send response
-            // FIXME: "securityError" also possible, check domain
-            ss << plugin::ExternalInterface::makeString("Error");
-        }
+
+        ss << plugin::ExternalInterface::convertNPVariant(&result);
+        NPN_ReleaseVariantValue(&result);
         size_t ret = _scriptObject->writePlayer(ss.str());
         if (ret != ss.str().size()) {
             log_error("Couldn't write the response to Gnash, network problems.");
diff --git a/plugin/npapi/pluginScriptObject.cpp b/plugin/npapi/pluginScriptObject.cpp
index 3b599c8..59e8a06 100644
--- a/plugin/npapi/pluginScriptObject.cpp
+++ b/plugin/npapi/pluginScriptObject.cpp
@@ -1,5 +1,5 @@
 // 
-//   Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc
+//   Copyright (C) 2010, 2011, 2012, 2014, 2016 Free Software Foundation, Inc
 // 
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -125,7 +125,7 @@ GnashPluginScriptObject::initializeIdentifiers()
 {
     // log_debug("initializeIdentifiers");
 
-//    NPN_Status(_nppinstance, __FUNCTION__);
+//    NPN_Status(nppinstance, __FUNCTION__);
     
 //    http://www.adobe.com/support/flash/publishexport/scriptingwithflash/scriptingwithflash_04.html
     
@@ -247,7 +247,7 @@ GnashPluginScriptObject::initializeIdentifiers()
 
 // Constructor
 GnashPluginScriptObject::GnashPluginScriptObject()
-    : _nppinstance (nullptr),
+    : nppinstance (nullptr),
       _controlfd(-1),
       _hostfd(-1)
 {
@@ -259,7 +259,7 @@ GnashPluginScriptObject::GnashPluginScriptObject()
 
 // Constructor
 GnashPluginScriptObject::GnashPluginScriptObject(NPP npp)
-    : _nppinstance (npp),
+    : nppinstance (npp),
       _controlfd(-1),
       _hostfd(-1)
 {
@@ -519,7 +519,7 @@ GnashPluginScriptObject::Invoke(NPObject */* npobj */, NPIdentifier name,
 
     return false;
     
-//    return NPN_Invoke(_nppinstance, this, name, args, argCount, result);
+//    return NPN_Invoke(nppinstance, this, name, args, argCount, result);
 }
 
 bool
@@ -621,7 +621,7 @@ GnashPluginScriptObject::GetVariable(const std::string &name)
         return GnashNPVariant();
     }
 
-    GnashNPVariant parsed = plugin::ExternalInterface::parseXML(data);
+    GnashNPVariant parsed = plugin::ExternalInterface::parseXML(this, data);
 
     printNPVariant(&parsed.get());
     
diff --git a/plugin/npapi/pluginScriptObject.h b/plugin/npapi/pluginScriptObject.h
index 2a8b7aa..7c45091 100644
--- a/plugin/npapi/pluginScriptObject.h
+++ b/plugin/npapi/pluginScriptObject.h
@@ -1,5 +1,5 @@
 // 
-//   Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc
+//   Copyright (C) 2010, 2011, 2012, 2016 Free Software Foundation, Inc
 // 
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -138,6 +138,10 @@ public:
     void AddProperty(const std::string &name, double num);
     void AddProperty(const std::string &name, int num);
 
+    /// Plugin instance object
+    // nppinstance->pdata should be the nsPluginInstance once NPP_New() is finished.
+    NPP nppinstance;
+
 protected:
     // Internal functions for the API
     void Deallocate();
@@ -155,10 +159,7 @@ protected:
 
 private:
     void initializeIdentifiers();
-    void setInstance(NPP inst) { _nppinstance = inst; };
-    
-    // _nppinstance->pdata should be the nsPluginInstance once NPP_New() is finished.
-    NPP _nppinstance;
+    void setInstance(NPP inst) { nppinstance = inst; };
     
     std::map<NPIdentifier, GnashNPVariant> _properties;
     std::map<NPIdentifier, NPInvokeFunctionPtr> _methods;
diff --git a/plugin/npapi/test.cpp b/plugin/npapi/test.cpp
index 1eb2367..21d4ce5 100644
--- a/plugin/npapi/test.cpp
+++ b/plugin/npapi/test.cpp
@@ -1,5 +1,5 @@
 // 
-//   Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc
+//   Copyright (C) 2010, 2011, 2012, 2014, 2016 Free Software Foundation, Inc
 // 
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -166,7 +166,7 @@ main(int , char **)
     // Parsing tests
     //
     xml = "<string>Hello World!</string>";
-    GnashNPVariant np = plugin::ExternalInterface::parseXML(xml);
+    GnashNPVariant np = plugin::ExternalInterface::parseXML(nullptr, xml);
     std::string data = NPStringToString(NPVARIANT_TO_STRING(np.get()));
     if (NPVARIANT_IS_STRING(np.get()) &&
         (data == "Hello World!")) {
@@ -176,7 +176,7 @@ main(int , char **)
     }
 
     xml = "<number>123.456</number>";
-    np = plugin::ExternalInterface::parseXML(xml);
+    np = plugin::ExternalInterface::parseXML(nullptr, xml);
     double num = NPVARIANT_TO_DOUBLE(np.get());
     if (NPVARIANT_IS_DOUBLE(np.get()) &&
         (num == 123.456)) {
@@ -186,7 +186,7 @@ main(int , char **)
     }
 
     xml = "<number>78</number>";
-    np = plugin::ExternalInterface::parseXML(xml);
+    np = plugin::ExternalInterface::parseXML(nullptr, xml);
     int inum = NPVARIANT_TO_INT32(np.get());
     if (NPVARIANT_IS_INT32(np.get()) &&
         (inum == 78)) {
@@ -196,7 +196,7 @@ main(int , char **)
     }
 
     xml = "<true/>";
-    np = plugin::ExternalInterface::parseXML(xml);
+    np = plugin::ExternalInterface::parseXML(nullptr, xml);
     bool flag = NPVARIANT_TO_BOOLEAN(np.get());
     if (NPVARIANT_IS_BOOLEAN(np.get()) &&
         (flag == true)) {
@@ -206,7 +206,7 @@ main(int , char **)
     }
 
     xml = "<false/>";
-    np = plugin::ExternalInterface::parseXML(xml);
+    np = plugin::ExternalInterface::parseXML(nullptr, xml);
     flag = NPVARIANT_TO_BOOLEAN(np.get());
     if (NPVARIANT_IS_BOOLEAN(np.get()) &&
         (flag == false)) {
@@ -216,7 +216,7 @@ main(int , char **)
     }
 
     xml = "<null/>";
-    np = plugin::ExternalInterface::parseXML(xml);
+    np = plugin::ExternalInterface::parseXML(nullptr, xml);
     if (NPVARIANT_IS_NULL(np.get())) {
         runtest.pass("plugin::ExternalInterface::parseXML(null)");
     } else {
@@ -224,7 +224,7 @@ main(int , char **)
     }
 
     xml = "<void/>";
-    np = plugin::ExternalInterface::parseXML(xml);
+    np = plugin::ExternalInterface::parseXML(nullptr, xml);
     if (NPVARIANT_IS_VOID(np.get())) {
         runtest.pass("plugin::ExternalInterface::parseXML(void)");
     } else {
@@ -232,7 +232,7 @@ main(int , char **)
     }
 
     xml = "<property id=\"0\"><string>foobar</string></property><property id=\"1\"><number>12.34</number></property><property id=\"2\"><number>56</number></property>";
-    std::map<std::string, GnashNPVariant> props = plugin::ExternalInterface::parseProperties(xml);
+    std::map<std::string, GnashNPVariant> props = plugin::ExternalInterface::parseProperties(nullptr, xml);
     np = props["0"];
     data = NPStringToString(NPVARIANT_TO_STRING(np.get()));
     if ((props.size() == 3) && (data == "foobar")) {
@@ -241,13 +241,15 @@ main(int , char **)
         runtest.fail("plugin::ExternalInterface::parseProperties()");
     }
     
+#if 0
     xml = "<object><property id=\"test1\"><string>foobar</string></property><property id=\"test2\"><number>12.34</number></property><property id=\"test3\"><number>56</number></property></object>";
-    np = plugin::ExternalInterface::parseXML(xml);
+    np = plugin::ExternalInterface::parseXML(nullptr, xml);
     if (NPVARIANT_IS_OBJECT(np.get())) {
         runtest.pass("plugin::ExternalInterface::parseXML(object)");
     } else {
         runtest.fail("plugin::ExternalInterface::parseXML(object)");
     }
+#endif
     
     std::vector<std::string> iargs;
     str = plugin::ExternalInterface::makeString("barfoo");
@@ -267,7 +269,7 @@ main(int , char **)
     }
     
     xml = "<arguments><string>barfoo</string><number>135.78</number><number>89</number></arguments>";
-    std::vector<GnashNPVariant> arguments = plugin::ExternalInterface::parseArguments(xml);
+    std::vector<GnashNPVariant> arguments = plugin::ExternalInterface::parseArguments(nullptr, xml);
     np = arguments[0];
     str = NPStringToString(NPVARIANT_TO_STRING(np.get()));
     double dub = NPVARIANT_TO_DOUBLE(arguments[1].get());
@@ -281,7 +283,7 @@ main(int , char **)
 
     // Parse an invoke message
     xml = "<invoke name=\"barbyfoo\" returntype=\"xml\"><arguments><string>barfoo</string><number>135.78</number></arguments></invoke>";
-    std::shared_ptr<plugin::ExternalInterface::invoke_t> invoke ( plugin::ExternalInterface::parseInvoke(xml) );
+    std::shared_ptr<plugin::ExternalInterface::invoke_t> invoke ( plugin::ExternalInterface::parseInvoke(nullptr, xml) );
     str = NPStringToString(NPVARIANT_TO_STRING(invoke->args[0].get()));
     if ((invoke->name == "barbyfoo") && (invoke->type == "xml")
         && (NPVARIANT_IS_STRING(invoke->args[0].get()))
@@ -296,7 +298,7 @@ main(int , char **)
 
     // Test for bug #31766
     xml = "<invoke name=\"reportFlashTiming\" returntype=\"xml\"><arguments><string>reportFlashTiming</string><object><property id=\"5\"><number>1297286708921</number></property><property id=\"4\"><string>vr</string></p";
-    invoke = plugin::ExternalInterface::parseInvoke(xml);
+    invoke = plugin::ExternalInterface::parseInvoke(nullptr, xml);
     if ((invoke->name == "reportFlashTiming") && (invoke->type == "xml")
         && invoke->args.empty())
     {
@@ -307,7 +309,7 @@ main(int , char **)
 
 
     xml = "<invoke name=\"reportFlashTiming\" returntype=\"xml\"><arguments><string>reportFlashTiming</string><object><property id=\"5\"><number>1297326407594</number></property><property id=\"4\"><string>vr</string></property><property id=\"3\"><number>1297326407147</number></property><property id=\"2\"><string>gv</string></property><property id=\"1\"><number>1297326406281</number></property><property id=\"0\"><string>fs</string></property></object><string>34</string><number>2</number>< [...]
-    invoke = plugin::ExternalInterface::parseInvoke(xml);
+    invoke = plugin::ExternalInterface::parseInvoke(nullptr, xml);
     check_equals (invoke->name, "reportFlashTiming");
     check_equals (invoke->type, "xml");
     xcheck_equals (invoke->args.size(), 8);
@@ -345,7 +347,7 @@ main(int , char **)
 
     {
       xml = "<object><property id=\"5\">";
-      GnashNPVariant v = plugin::ExternalInterface::parseXML(xml);
+      GnashNPVariant v = plugin::ExternalInterface::parseXML(nullptr, xml);
       check(NPVARIANT_IS_NULL(v.get()));
     }
 
@@ -454,6 +456,19 @@ NPN_HasProperty(NPP , NPObject* , NPIdentifier name)
     return false;
 }
 
+NPError
+NPN_GetValue(NPP, NPNVariable, void*)
+{
+    return NPERR_GENERIC_ERROR;
+}
+
+bool
+NPN_Invoke(NPP, NPObject*, NPIdentifier, const NPVariant*, uint32_t,
+           NPVariant*)
+{
+    return false;
+}
+
 void
 NPN_ReleaseVariantValue(NPVariant *variant)
 {
diff --git a/revno.h b/revno.h
index 75d1a5a..13cba7d 100644
--- a/revno.h
+++ b/revno.h
@@ -1,3 +1,3 @@
 #define BRANCH_REVNO "2"
 #define BRANCH_NICK "master"
-#define COMMIT_ID "15d61a8"
+#define COMMIT_ID "f6a0b38"
diff --git a/testsuite/actionscript.all/Function.as b/testsuite/actionscript.all/Function.as
index b8b693f..e844403 100644
--- a/testsuite/actionscript.all/Function.as
+++ b/testsuite/actionscript.all/Function.as
@@ -1,5 +1,5 @@
 // 
-//   Copyright (C) 2005, 2006, 2007, 2009, 2010 Free Software
+//   Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011, 2016 Free Software
 //   Foundation, Inc
 //
 // This program is free software; you can redistribute it and/or modify
@@ -35,6 +35,14 @@ check( ! Function.hasOwnProperty('__constructor__') );
 // Define a function returning 'this'.name and the given args
 function getThisName(a,b,c) { return this.name+a+b+c; }
 
+#if OUTPUT_VERSION >= 6
+// Define a function for checking 'this' against '_global' object
+function isThisGlobal() { return this===_global; }
+#endif
+
+// Define a function which set a property named 'instanceCheck' to 'this'
+function setThisMember(value) { this.instanceCheck=value; }
+
 // Every newly created function's super class is Object
 check_equals(getThisName.prototype.__proto__, Object.prototype);
 
@@ -121,6 +129,21 @@ var ret=getThisName.apply(undefined, "7");
   check_equals ( ret , 0 );
 #endif
 
+// Test Function.apply() with 'thisObject' being unspecified, 'undefined',
+// or 'null'
+
+function setThisMember_apply_noarg() { this.instanceCheck = "apply_no_this"; }
+check ( isThisGlobal.apply() );
+check ( isThisGlobal.apply(undefined) );
+check ( isThisGlobal.apply(null) );
+setThisMember_apply_noarg.apply();
+check_equals ( _global.instanceCheck, "apply_no_this" );
+setThisMember.apply(undefined, ["apply_undefined_this"]);
+check_equals ( _global.instanceCheck, "apply_undefined_this" );
+setThisMember.apply(null, ["apply_null_this"]);
+check_equals ( _global.instanceCheck, "apply_null_this" );
+check ( delete _global.instanceCheck );
+
 #else // OUTPUT_VERSION < 6
 
 // No Function.apply... for SWF up to 5
@@ -162,6 +185,33 @@ check_equals(typeof(ret), 'object');
 check_equals(ret, undefined); // an object type which returns 'undefined' as primitive value ?
 check( ! (ret === undefined) ); // an object type which returns 'undefined' as primitive value ?
 check( ! (ret === null) ); // an object type which returns 'undefined' as primitive value ?
+check( ret === _global ); // an object is actually the '_global' ?
+ret = getThis.call(undefined);
+check_equals(c, 3);
+check_equals(typeof(ret), 'object');
+check_equals(ret, undefined); // an object type which returns 'undefined' as primitive value ?
+check( ! (ret === undefined) ); // an object type which returns 'undefined' as primitive value ?
+check( ! (ret === null) ); // an object type which returns 'undefined' as primitive value ?
+check( ret === _global ); // an object is actually the '_global' ?
+ret = getThis.call();
+check_equals(c, 4);
+check_equals(typeof(ret), 'object');
+check_equals(ret, undefined); // an object type which returns 'undefined' as primitive value ?
+check( ! (ret === undefined) ); // an object type which returns 'undefined' as primitive value ?
+check( ! (ret === null) ); // an object type which returns 'undefined' as primitive value ?
+check( ret === _global ); // an object is actually the '_global' ?
+
+// Test Function.call() with 'thisObject' being unspecified, 'undefined',
+// or 'null'
+
+function setThisMember_call_noarg() { this.instanceCheck = "call_no_this"; }
+setThisMember_call_noarg.call();
+check_equals(_global.instanceCheck, "call_no_this");
+setThisMember.call(undefined, "call_undefined_this");
+check_equals(_global.instanceCheck, "call_undefined_this");
+setThisMember.call(null, "call_null_this");
+check_equals(_global.instanceCheck, "call_null_this");
+check(delete _global.instanceCheck);
 
 retCaller = 'custom'; 
 myCaller = function()
@@ -1077,8 +1127,8 @@ check_equals(called, 0);
  check_totals(150); // SWF5
 #endif
 #if OUTPUT_VERSION == 6
- check_totals(239); // SWF6
+ check_totals(263); // SWF6
 #endif
 #if OUTPUT_VERSION >= 7
- check_totals(240); // SWF7,SWF8
+ check_totals(264); // SWF7,SWF8
 #endif
diff --git a/testsuite/actionscript.all/Makefile.am b/testsuite/actionscript.all/Makefile.am
index 5bc4e46..8efaa84 100644
--- a/testsuite/actionscript.all/Makefile.am
+++ b/testsuite/actionscript.all/Makefile.am
@@ -28,7 +28,8 @@ AUTOMAKE_OPTIONS = dejagnu -Wno-portability
 abs_mediadir = $(shell cd $(srcdir)/../media; pwd)
 swfdir = $(shell cd $(top_builddir)/testsuite/actionscript.all; pwd)
 
-COM_MAKESWF_FLAGS=-DMING_VERSION_CODE=$(MING_VERSION_CODE) -I"$(top_builddir)"
+COM_MAKESWF_FLAGS=-DMING_VERSION_CODE=$(MING_VERSION_CODE) \
+  -I"$(top_builddir)" -c -1
 DEF_MAKESWF_FLAGS=$(COM_MAKESWF_FLAGS) \
 	-DMEDIADIR='\"$(abs_mediadir)\"' \
 	-DSWFDIR='\"$(swfdir)\"' 
diff --git a/testsuite/misc-ming.all/Makefile.am b/testsuite/misc-ming.all/Makefile.am
index 946bcca..d3e2467 100644
--- a/testsuite/misc-ming.all/Makefile.am
+++ b/testsuite/misc-ming.all/Makefile.am
@@ -349,9 +349,9 @@ DefineTextTest_Runner_DEPENDENCIES = \
 	$(NULL)
 
 Version4Loader.swf: $(srcdir)/Version4Loader.as 
-	$(MAKESWF) $(MAKESWF_FLAGS) -o $@ -v4 $(srcdir)/Version4Loader.as
+	$(MAKESWF) $(MAKESWF_FLAGS) -c -1 -o $@ -v4 $(srcdir)/Version4Loader.as
 Version5Loaded.swf: $(srcdir)/Version5Loaded.as Dejagnu.swf
-	$(MAKESWF) $(MAKESWF_FLAGS) -o $@ Dejagnu.swf -v5 $(srcdir)/Version5Loaded.as
+	$(MAKESWF) $(MAKESWF_FLAGS) -c -1 -o $@ Dejagnu.swf -v5 $(srcdir)/Version5Loaded.as
 MixedVersion4And5Runner: Version4Loader.swf Version5Loaded.swf
 	sh $(srcdir)/../generic-testrunner.sh $(top_builddir) Version5Loaded.swf > $@
 	chmod 755 $@
@@ -1302,7 +1302,7 @@ XMLSocketTester: XMLSocketTester.sh XMLSocketTest.swf
 	chmod 755 $@
 
 extgetvariable_v5.swf: extgetvariable.as
-	$(MAKESWF) $(MAKESWF_FLAGS) -r 1 -v 5 -o $@  $(srcdir)/extgetvariable.as
+	$(MAKESWF) $(MAKESWF_FLAGS) -c -1 -r 1 -v 5 -o $@  $(srcdir)/extgetvariable.as
 
 extgetvariable_v6.swf: extgetvariable.as
 	$(MAKESWF) $(MAKESWF_FLAGS) -r 1 -v 6 -o $@  $(srcdir)/extgetvariable.as
diff --git a/testsuite/misc-ming.all/extgetvariable_testrunner.sh b/testsuite/misc-ming.all/extgetvariable_testrunner.sh
index 956d274..2380f2b 100644
--- a/testsuite/misc-ming.all/extgetvariable_testrunner.sh
+++ b/testsuite/misc-ming.all/extgetvariable_testrunner.sh
@@ -247,11 +247,11 @@ echo '<invoke name="GetVariable" returntype="xml"><arguments><string>unassigned_
 
 # Read for return value statement
 read_timeout LINE \$READTIMEOUT <&3
-if [ "${swfversion}" -gt 5 ]
+if [ "${swfversion}" -gt 6 ]
 then
 	check_equals "\$LINE" '<string>undefined</string>' "Gnash should return a correct value from GetVariable call on unassigned variable"
 else
-	xcheck_equals "\$LINE" '<string></string>' "Gnash should return a correct value from GetVariable call on unassigned variable"
+	check_equals "\$LINE" '<string></string>' "Gnash should return a correct value from GetVariable call on unassigned variable"
 fi
 
 # Call string-returning GetVariable() on variable with undefined value
@@ -259,11 +259,11 @@ echo '<invoke name="GetVariable" returntype="xml"><arguments><string>undefined_v
 
 # Read for return value statement
 read_timeout LINE \$READTIMEOUT <&3
-if [ "${swfversion}" -gt 5 ]
+if [ "${swfversion}" -gt 6 ]
 then
 	check_equals "\$LINE" '<string>undefined</string>' "Gnash should return a correct value from GetVariable call on variable with undefined value"
 else
-	xcheck_equals "\$LINE" '<string></string>' "Gnash should return a correct value from GetVariable call on variable with undefined value"
+	check_equals "\$LINE" '<string></string>' "Gnash should return a correct value from GetVariable call on variable with undefined value"
 fi
 
 # Call string-returning GetVariable() on non-existent variable
diff --git a/testsuite/misc-mtasc.all/extcomm.as b/testsuite/misc-mtasc.all/extcomm.as
index 4f455cd..0f76c15 100644
--- a/testsuite/misc-mtasc.all/extcomm.as
+++ b/testsuite/misc-mtasc.all/extcomm.as
@@ -1,6 +1,6 @@
 // extcomm.as - Host container communication (ExternalInterface) tests
 //
-//   Copyright (C) 2015 Free Software Foundation, Inc.
+//   Copyright (C) 2015, 2016 Free Software Foundation, Inc.
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -89,12 +89,14 @@ class ExternalCommTest
 				{
 					// `this` should be an "undefined" object like one in
 					// a function called via `function.call(null)`
-					xcheck_equals(typeof(this), "object");
+					check_equals(typeof(this), "object");
 					check(this == undefined);
 					check(this == null);
 					check(this !== undefined);
-					xcheck(this !== null);
-					xcheck_equals("" + this, "undefined");
+					check(this !== null);
+					check_equals("" + this, "undefined");
+					check(this === _global);
+					this.nothis1_value = "script_nothis1";
 				}
 			)
 		);
@@ -104,12 +106,25 @@ class ExternalCommTest
 				{
 					// `this` should be an "undefined" object like one in
 					// a function called via `function.call(undefined)`
-					xcheck_equals(typeof(this), "object");
+					check_equals(typeof(this), "object");
 					check(this == undefined);
 					check(this == null);
 					check(this !== undefined);
-					xcheck(this !== null);
-					xcheck_equals("" + this, "undefined");
+					check(this !== null);
+					check_equals("" + this, "undefined");
+					check(this === _global);
+					this.nothis2_value = "script_nothis2";
+				}
+			)
+		);
+
+		// Registering callback for checking _global properties shouldn't fail
+		check(
+			ExternalInterface.addCallback("script_globalcheck", mc,
+				function():Void
+				{
+					check_equals(_global.nothis1_value, "script_nothis1");
+					check_equals(_global.nothis2_value, "script_nothis2");
 				}
 			)
 		);
@@ -136,5 +151,22 @@ class ExternalCommTest
 				}
 			)
 		);
+
+		// Calling JavaScript function without any argument should give
+		// a correct return value
+		check_equals(ExternalInterface.call("js_simple"), "Correct");
+
+		// Calling JavaScript function 20 times in row should give all
+		// correct return value
+		var numreadings:Array = new Array(
+			"one", "two", "three", "four", "five", "six", "seven", "eight",
+			"nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
+			"fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty"
+		);
+		var i:Number;
+		for(i = 0; i < numreadings.length; i++) {
+			check_equals(ExternalInterface.call("js_readnumber", i + 1),
+			             numreadings[i]);
+		}
 	}
 }
diff --git a/testsuite/misc-mtasc.all/extcommtests-runner.sh b/testsuite/misc-mtasc.all/extcommtests-runner.sh
index c71cd6d..b165630 100644
--- a/testsuite/misc-mtasc.all/extcommtests-runner.sh
+++ b/testsuite/misc-mtasc.all/extcommtests-runner.sh
@@ -4,7 +4,7 @@
 # extcommtests-runner.sh: container-emulated, automated
 #     ExternalInterface test generator
 # 
-# Copyright (C) 2015 Free Software Foundation, Inc.
+# Copyright (C) 2015, 2016 Free Software Foundation, Inc.
 # 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -26,6 +26,10 @@
 # The generated test runner checks Gnash for:
 #  * ExternalInterface.addCallback() issues (bug #37223)
 #        <https://savannah.gnu.org/bugs/?37223>
+#  * ExternalInterface.call()'s delayed return value issue (bug #46131)
+#        <https://savannah.gnu.org/bugs/?46131>
+#  * Single-argument ExternalInterface.call() issue (bug #46878)
+#        <https://savannah.gnu.org/bugs/?46878>
 # 
 # Usage:
 #     ./extcommtests-runner.sh <builddir> <srcdir> <swf>
@@ -176,6 +180,13 @@ check_equals \
 	'<invoke name="addMethod" returntype="xml"><arguments><string>script_nothis2</string></arguments></invoke>' \
 	"Gnash should properly register script_nothis2 ExternalInterface callback"
 
+# Read for script_globalcheck callback registration statement
+read_timeout LINE \$READTIMEOUT <&3
+check_equals \
+	"\$LINE" \
+	'<invoke name="addMethod" returntype="xml"><arguments><string>script_globalcheck</string></arguments></invoke>' \
+	"Gnash should properly register script_globalcheck ExternalInterface callback"
+
 # Read for script_longarglist callback registration statement
 read_timeout LINE \$READTIMEOUT <&3
 check_equals \
@@ -183,6 +194,39 @@ check_equals \
 	'<invoke name="addMethod" returntype="xml"><arguments><string>script_longarglist</string></arguments></invoke>' \
 	"Gnash should properly register script_longarglist ExternalInterface callback"
 
+# Read for js_simple JavaScript function invocation statement
+read_timeout LINE \$READTIMEOUT <&3
+check_equals \
+	"\$LINE" \
+	'<invoke name="js_simple" returntype="xml"><arguments><string>js_simple</string></arguments></invoke>' \
+	"Gnash should call JavaScript's js_simple function correctly"
+
+# Return string value from js_simple function
+echo '<string>Correct</string>' >&4
+
+# Test using multiple ExternalInterface.call() in row
+NUMBER=1
+for READING in "one" "two" "three" "four" "five" "six" "seven" "eight" "nine" \
+	"ten" "eleven" "twelve" "thirteen" "fourteen" "fifteen"  "sixteen" \
+	"seventeen" "eighteen" "nineteen" "twenty"
+do
+	# Read for js_readnumber JavaScript function invocation statement
+	read_timeout LINE \$READTIMEOUT <&3
+	check_equals \
+		"\$LINE" \
+		"<invoke name=\"js_readnumber\" returntype=\"xml\"><arguments><string>js_readnumber</string><number>\$NUMBER</number></arguments></invoke>" \
+		"Gnash should call JavaScript's js_readnumber function with parameter \$NUMBER correctly"
+
+	# Return string value from js_readnumber function
+	echo "<string>\$READING</string>" >&4
+
+	NUMBER=\`expr \$NUMBER + 1\`
+done
+
+# Pause a bit, so the next script_call invoke doesn't get mixed up with
+# the previous return value data
+sleep 1
+
 # Call the script_call callback
 echo '<invoke name="script_call" returntype="xml"><arguments><string>Hello</string><string>World</string></arguments></invoke>' >&4
 
@@ -195,14 +239,21 @@ echo '<invoke name="script_nothis1" returntype="xml"><arguments></arguments></in
 
 # Read for callback return value statement
 read_timeout LINE \$READTIMEOUT <&3
-check_equals "\$LINE" '<undefined/>' "Gnash should return a correct value from script_nothis1 ExternalInterface callback"
+check_equals "\$LINE" '<void/>' "Gnash should return a correct value from script_nothis1 ExternalInterface callback"
 
 # Call the script_nothis2 callback
 echo '<invoke name="script_nothis2" returntype="xml"><arguments></arguments></invoke>' >&4
 
 # Read for callback return value statement
 read_timeout LINE \$READTIMEOUT <&3
-check_equals "\$LINE" '<undefined/>' "Gnash should return a correct value from script_nothis2 ExternalInterface callback"
+check_equals "\$LINE" '<void/>' "Gnash should return a correct value from script_nothis2 ExternalInterface callback"
+
+# Call the script_globalcheck callback
+echo '<invoke name="script_globalcheck" returntype="xml"><arguments></arguments></invoke>' >&4
+
+# Read for callback return value statement
+read_timeout LINE \$READTIMEOUT <&3
+check_equals "\$LINE" '<void/>' "Gnash should return a correct value from script_globalcheck ExternalInterface callback"
 
 # Call the script_longarglist callback
 echo '<invoke name="script_longarglist" returntype="xml"><arguments><string>The</string><string>quick</string><string>brown</string><string>fox</string><string>jumps</string><string>over</string><string>the</string><string>lazy</string><string>dog</string></arguments></invoke>' >&4
@@ -244,7 +295,7 @@ XFAILED=\`expr "\$XFAILED" + "\$PLAYERXFAILED"\`
 TESTED=\`expr "\$TESTED" + "\$PLAYERPASSED" + "\$PLAYERXPASSED" + "\$PLAYERFAILED" + "\$PLAYERXFAILED"\`
 
 # Check for total number of test run
-check_totals "45" "There should be 45 tests run"
+check_totals "94" "There should be 94 tests run"
 
 # Remove temporary files
 rm "\$LOGFILE"

-- 
Alioth's hooks/post-receive on /srv/git.debian.org/git/pkg-flash/gnash.git



More information about the pkg-flash-devel mailing list