Fix incorrect property copying for native JsType subclasses.

Bug: #9430
Bug-Link: https://github.com/gwtproject/gwt/issues/9430
Change-Id: Idb9c47cb5d7d9969dc379b23f6ab4d1ea4c589dd
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
index 4071518..f70a96b 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
@@ -199,7 +199,7 @@
    * an existing non-JsMember inside a class.
    */
   public boolean exposesNonJsMember() {
-    if (isInterfaceMethod() || !JjsUtils.exposesJsName(this)) {
+    if (isInterfaceMethod() || enclosingType.isJsNative() || !JjsUtils.exposesJsName(this)) {
       return false;
     }
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index 6a47400..f78edbb 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -2012,20 +2012,22 @@
           RuntimeConstants.RUNTIME_DEFINE_CLASS, defineClassArguments).makeStmt();
       addTypeDefinitionStatement(type, defineClassStatement);
 
-      maybeCopyObjProperties(
+      maybeCopyJavaLangObjectProperties(
           type,
           getPrototypeQualifierViaLookup(program.getTypeJavaLangObject(), type.getSourceInfo()),
           globalTemp.makeRef(type.getSourceInfo()));
     }
 
-    private void maybeCopyObjProperties(
-        JDeclaredType type, JsExpression toPrototype, JsExpression fromPrototype) {
+    private void maybeCopyJavaLangObjectProperties(
+        JDeclaredType type, JsExpression javaLangObjectPrototype, JsExpression toPrototype) {
       if (getSuperPrototype(type) != null && !type.isJsFunctionImplementation()) {
-        JsStatement statement = constructInvocation(type.getSourceInfo(),
-            RuntimeConstants.RUNTIME_COPY_OBJECT_PROPERTIES,
-            fromPrototype,
-            toPrototype)
-            .makeStmt();
+        JsStatement statement =
+            constructInvocation(
+                type.getSourceInfo(),
+                RuntimeConstants.RUNTIME_COPY_OBJECT_PROPERTIES,
+                javaLangObjectPrototype,
+                toPrototype
+            ).makeStmt();
         addTypeDefinitionStatement(type, statement);
       }
     }
@@ -2152,7 +2154,7 @@
 
       // inline assignment of castableTypeMap field instead of using defineClass()
       setupCastMapOnPrototype(type);
-      maybeCopyObjProperties(
+      maybeCopyJavaLangObjectProperties(
           type,
           getPrototypeQualifierOf(program.getTypeJavaLangObject(), info),
           getPrototypeQualifierOf(type, info));
diff --git a/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Runtime.java b/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Runtime.java
index 45bd626..e48652b 100644
--- a/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Runtime.java
+++ b/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Runtime.java
@@ -97,8 +97,7 @@
     return @Runtime::portableObjCreate(*)(superPrototype);
   }-*/;
 
-  public static native void copyObjectProperties(JavaScriptObject from,
-      JavaScriptObject to) /*-{
+  public static native void copyObjectProperties(JavaScriptObject from, JavaScriptObject to) /*-{
     for (var property in from) {
       if (to[property] === undefined) {
         to[property] = from[property];
diff --git a/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java b/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java
index 8dc10c7..b222732 100644
--- a/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java
+++ b/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java
@@ -468,4 +468,22 @@
     assertNotSame(IFrameWindow.window, MainWindow.window);
     assertSame(MainWindow.window, AlsoMainWindow.window);
   }
+
+  @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Error")
+  private static class NativeError {
+  }
+
+  private static class NativeErrorSubclass extends NativeError {
+  }
+
+  public void testObjectPropertiesAreCopied() {
+    Object error = new NativeErrorSubclass();
+    assertTrue(error instanceof NativeError);
+    // Make sure the subclass is a proper Java object (the typeMarker should be one of the
+    // properties copied from java.lang.Object).
+    assertFalse(error instanceof JavaScriptObject);
+    // TODO(rluble): NativeErrorSubclass should have inherited Error toString behavior not
+    // j.l.Object.toString behavior.
+    // assertTrue(error.toString().matches("[0-9a-zA-Z$_.]+@[0-9a-fA-F]+"));
+  }
 }