diff -r c7079a11fde0 build.gradle
--- a/build.gradle	Wed Dec 07 13:58:52 2016 -0800
+++ b/build.gradle	Fri Dec 09 16:51:34 2016 +0100
@@ -444,7 +444,7 @@
 ext.IS_WORKER_DEBUG = Boolean.parseBoolean(WORKER_DEBUG);
 
 // Specify the build configuration (Release, Debug, or DebugNative)
-defineProperty("CONF", "Debug")
+defineProperty("CONF", "DebugNative")
 ext.IS_DEBUG_JAVA = CONF == "Debug" || CONF == "DebugNative"
 ext.IS_DEBUG_NATIVE = CONF == "DebugNative"
 
diff -r c7079a11fde0 modules/javafx.web/src/main/java/com/sun/webkit/Disposer.java
--- a/modules/javafx.web/src/main/java/com/sun/webkit/Disposer.java	Wed Dec 07 13:58:52 2016 -0800
+++ b/modules/javafx.web/src/main/java/com/sun/webkit/Disposer.java	Fri Dec 09 16:51:34 2016 +0100
@@ -88,6 +88,11 @@
         disposerInstance.add(target, rec);
     }
 
+    public static void flush() {
+        disposerInstance.cleanUp(true);
+        DisposerRunnable.getInstance().waitFinished();
+    }
+
     /**
      * Performs the actual registration of the target object to be disposed.
      * @param target Object to be registered
@@ -98,10 +103,23 @@
         records.add(new WeakDisposerRecord(target, rec));
     }
 
+    @Override
     public void run() {
+        cleanUp(false);
+    }
+
+    private void cleanUp(boolean poll) {
         while (true) {
             try {
-                WeakDisposerRecord obj = (WeakDisposerRecord) queue.remove();
+                WeakDisposerRecord obj;
+                if (poll) {
+                    obj = (WeakDisposerRecord) queue.poll();
+                    if (obj == null) {
+                        return;
+                    }
+                } else {
+                    obj = (WeakDisposerRecord) queue.remove();
+                }
                 obj.clear();
                 DisposerRunnable.getInstance().enqueue(obj);
             } catch (Exception e) {
@@ -144,6 +162,7 @@
                     obj = disposerQueue.poll();
                     if (obj == null) {
                         isRunning = false;
+                        disposerLock.notifyAll();
                         break;
                     }
                 }
@@ -154,6 +173,18 @@
                 }
             }
         }
+
+        private void waitFinished() {
+            synchronized (disposerLock) {
+                while (isRunning) {
+                    try {
+                        disposerLock.wait();
+                    } catch (InterruptedException ex) {
+                        ex.printStackTrace();
+                    }
+                }
+            }
+        }
     }
 
     public static class WeakDisposerRecord
diff -r c7079a11fde0 modules/javafx.web/src/main/java/com/sun/webkit/dom/JSObject.java
--- a/modules/javafx.web/src/main/java/com/sun/webkit/dom/JSObject.java	Wed Dec 07 13:58:52 2016 -0800
+++ b/modules/javafx.web/src/main/java/com/sun/webkit/dom/JSObject.java	Fri Dec 09 16:51:34 2016 +0100
@@ -32,7 +32,7 @@
 import java.security.AccessController;
 import netscape.javascript.JSException;
 
-class JSObject extends netscape.javascript.JSObject {
+public class JSObject extends netscape.javascript.JSObject {
     private static final String UNDEFINED = new String("undefined");
     static final int JS_CONTEXT_OBJECT  = 0;
     static final int JS_DOM_NODE_OBJECT  = 1;
@@ -47,10 +47,15 @@
         Disposer.addRecord(this, new SelfDisposer(peer, peer_type));
     }
 
-    long getPeer() {
+    public long getPeer() {
         return peer;
     }
 
+    public int getPeerType() {
+        return peer_type;
+    }
+
+    public static native boolean isProtectedImpl(long peer, int peer_type);
     private static native void unprotectImpl(long peer, int peer_type);
 
     @Override
diff -r c7079a11fde0 modules/javafx.web/src/main/native/Source/JavaScriptCore/runtime/Options.cpp
--- a/modules/javafx.web/src/main/native/Source/JavaScriptCore/runtime/Options.cpp	Wed Dec 07 13:58:52 2016 -0800
+++ b/modules/javafx.web/src/main/native/Source/JavaScriptCore/runtime/Options.cpp	Fri Dec 09 16:51:34 2016 +0100
@@ -506,7 +506,7 @@
     case Options::Type::unsignedType:
         return m_entry.unsignedVal == other.m_entry.unsignedVal;
     case Options::Type::doubleType:
-        return (m_entry.doubleVal == other.m_entry.doubleVal) || (isnan(m_entry.doubleVal) && isnan(other.m_entry.doubleVal));
+        return (m_entry.doubleVal == other.m_entry.doubleVal) || (std::isnan(m_entry.doubleVal) && std::isnan(other.m_entry.doubleVal));
     case Options::Type::int32Type:
         return m_entry.int32Val == other.m_entry.int32Val;
     case Options::Type::optionRangeType:
diff -r c7079a11fde0 modules/javafx.web/src/main/native/Source/WebCore/mapfile-macosx
--- a/modules/javafx.web/src/main/native/Source/WebCore/mapfile-macosx	Wed Dec 07 13:58:52 2016 -0800
+++ b/modules/javafx.web/src/main/native/Source/WebCore/mapfile-macosx	Fri Dec 09 16:51:34 2016 +0100
@@ -1914,6 +1914,7 @@
                _Java_com_sun_webkit_dom_JSObject_setSlotImpl
                _Java_com_sun_webkit_dom_JSObject_toStringImpl
                _Java_com_sun_webkit_dom_JSObject_unprotectImpl
+               _Java_com_sun_webkit_dom_JSObject_isProtectedImpl
                _Java_com_sun_webkit_graphics_WCGraphicsManager_append
                _Java_com_sun_webkit_graphics_WCMediaPlayer_notifyBufferChanged
                _Java_com_sun_webkit_graphics_WCMediaPlayer_notifyDurationChanged
diff -r c7079a11fde0 modules/javafx.web/src/main/native/Source/WebCore/mapfile-vers
--- a/modules/javafx.web/src/main/native/Source/WebCore/mapfile-vers	Wed Dec 07 13:58:52 2016 -0800
+++ b/modules/javafx.web/src/main/native/Source/WebCore/mapfile-vers	Fri Dec 09 16:51:34 2016 +0100
@@ -1937,6 +1937,7 @@
                Java_com_sun_webkit_dom_JSObject_setSlotImpl;
                Java_com_sun_webkit_dom_JSObject_toStringImpl;
                Java_com_sun_webkit_dom_JSObject_unprotectImpl;
+               Java_com_sun_webkit_dom_JSObject_isProtectedImpl;
                Java_com_sun_webkit_graphics_WCGraphicsManager_append;
                Java_com_sun_webkit_graphics_WCMediaPlayer_notifyBufferChanged;
                Java_com_sun_webkit_graphics_WCMediaPlayer_notifyDurationChanged;
diff -r c7079a11fde0 modules/javafx.web/src/main/native/Source/WebCore/platform/java/BridgeUtils.cpp
--- a/modules/javafx.web/src/main/native/Source/WebCore/platform/java/BridgeUtils.cpp	Wed Dec 07 13:58:52 2016 -0800
+++ b/modules/javafx.web/src/main/native/Source/WebCore/platform/java/BridgeUtils.cpp	Fri Dec 09 16:51:34 2016 +0100
@@ -447,4 +447,14 @@
     rootObject->gcUnprotect(toJS(object));
 }
 
+JNIEXPORT jboolean JNICALL Java_com_sun_webkit_dom_JSObject_isProtectedImpl
+(JNIEnv *env, jclass clas, jlong peer, jint peer_type)
+{
+    JSObjectRef object;
+    JSContextRef ctx;
+    RefPtr<JSC::Bindings::RootObject> rootObject(checkJSPeer(peer, peer_type, object, ctx));
+
+    return rootObject->gcIsProtected(toJS(object));
 }
+
+}
diff -r c7079a11fde0 modules/javafx.web/src/test/java/test/javafx/scene/web/Leak8164792Test.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/javafx.web/src/test/java/test/javafx/scene/web/Leak8164792Test.java	Fri Dec 09 16:51:34 2016 +0100
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.javafx.scene.web;
+
+import com.sun.webkit.Disposer;
+import netscape.javascript.JSObject;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+public class Leak8164792Test extends TestBase {
+    @Test
+    public void multipleJSObjectsForASinglePeer() throws Exception {
+        testMultipleJSObjects(true);
+    }
+
+    @Test
+    public void multipleJSObjectsForMultiplePeers() throws Exception {
+        testMultipleJSObjects(false);
+    }
+
+    private void testMultipleJSObjects(boolean singlePeer) throws Exception {
+        Reference<?>[] willGC = new Reference[3];
+        JSObject[] toCheck = new JSObject[1];
+        long[] peerAndType = { 0, 0 };
+        int expectedValue = submit(() -> {
+            Object rawFn = getEngine().executeScript(""
+                    + "(function(add) {\n"
+                    + "  if (" + singlePeer + " && window.obj) {\n"
+                    + "     window.obj.count += add;\n"
+                    + "  } else {\n"
+                    + "     window.obj = {};\n"
+                    + "     window.obj.count = add;\n"
+                    + "  }\n"
+                    + "  return window.obj;\n"
+                    + "})"
+            );
+            assertTrue(rawFn instanceof JSObject);
+            JSObject fn = (JSObject)rawFn;
+
+            JSObject first = (JSObject) fn.call("call", null, 1);
+            JSObject second = (JSObject) fn.call("call", null, 1);
+            JSObject third = (JSObject) fn.call("call", null, 1);
+
+            getEngine().executeScript("window.obj = null");
+
+            if (singlePeer) {
+                assertEquals("Values of the same JS obj incremented", first.getMember("count"), 3);
+                assertEquals("Values of the same JS obj incremented", second.getMember("count"), 3);
+                assertEquals("Values of the same JS obj incremented", third.getMember("count"), 3);
+            } else {
+                assertEquals("Values of the different JS obj used", first.getMember("count"), 1);
+                assertEquals("Values of the different JS obj used", second.getMember("count"), 1);
+                assertEquals("Values of the different JS obj used", third.getMember("count"), 1);
+            }
+
+            assertNotSame(first, second);
+            assertNotSame(third, second);
+
+            willGC[0] = new WeakReference<>(first);
+            willGC[1] = new WeakReference<>(second);
+            toCheck[0] = third;
+
+             findPeerAndType(first, peerAndType);
+
+            return (int)third.getMember("count");
+        });
+
+        assertGC("First JSObject can disappear", willGC[0]);
+        assertGC("Second JSObject can disappear", willGC[1]);
+
+
+        disposerFlush();
+
+        submit(() -> {
+            JSObject third = toCheck[0];
+            assertEquals("Value of third JS object is still same", third.getMember("count"), expectedValue);
+            willGC[2] = new WeakReference<>(third);
+        });
+
+        disposerFlush();
+
+        if (singlePeer) {
+            assertFalse("Still one reference", isUnprotected(peerAndType));
+        } else {
+            assertTrue("No reference to 1st instance", isUnprotected(peerAndType));
+        }
+
+        toCheck[0] = null;
+        assertGC("Third JSObject can disappear", willGC[2]);
+
+        disposerFlush();
+
+        assertTrue("All reference to the peer are gone", isUnprotected(peerAndType));
+    }
+
+    private static void disposerFlush() {
+        Disposer.flush();
+    }
+
+    private static void assertGC(String msg, Reference<?> ref) throws InterruptedException {
+        for (int i = 0; i < 100; i++) {
+            if (isGone(ref)) {
+                return;
+            }
+
+            try {
+                System.gc();
+                System.runFinalization();
+            } catch (Error err) {
+                err.printStackTrace();
+            }
+        }
+        throw new InterruptedException(msg);
+    }
+
+    private static boolean isGone(Reference<?> ref) {
+        return ref.get() == null;
+    }
+
+    private static Method getPeer;
+    private static Method getPeerType;
+    private static Method isProtectedImpl;
+    private static void findPeerAndType(JSObject obj, long[] peerAndType) {
+        try {
+            if (getPeer == null) {
+                getPeer = obj.getClass().getDeclaredMethod("getPeer");
+                getPeerType = obj.getClass().getDeclaredMethod("getPeerType");
+                isProtectedImpl = obj.getClass().getDeclaredMethod("isProtectedImpl", long.class, int.class);
+                getPeer.setAccessible(true);
+                getPeerType.setAccessible(true);
+                isProtectedImpl.setAccessible(true);
+            }
+
+            peerAndType[0] = (long) getPeer.invoke(obj);
+            peerAndType[1] = (int) getPeerType.invoke(obj);
+        } catch (Exception ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    private static boolean isUnprotected(long[] peerAndType) {
+        try {
+            return (boolean) isProtectedImpl.invoke(null, peerAndType[0], (int) peerAndType[1]);
+        } catch (Exception ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+}
