diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JConstructor.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JConstructor.java index b207a63f699..8ca2aa08e68 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/JConstructor.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JConstructor.java @@ -93,6 +93,11 @@ public boolean isConstructor() { return true; } + @Override + public boolean isJsNative() { + return getEnclosingType().isJsNative(); + } + /** * Returns true if this constructor does no real work. * diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java index e5b6bb313a0..276fdd9c216 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java @@ -160,6 +160,7 @@ public boolean isJsProperty() { return jsName != null; } + @Override public boolean isJsNative() { return enclosingType.isJsNative(); } 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 905904b98b2..f4efae47ea9 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 @@ -102,7 +102,7 @@ public void setJsMemberInfo(String namespace, String name, boolean exported) { } public boolean isJsInteropEntryPoint() { - return exported && !needsDynamicDispatch(); + return exported && !needsDynamicDispatch() && !isJsNative(); } public boolean canBeCalledExternally() { @@ -242,8 +242,9 @@ public boolean isOrOverridesJsFunctionMethod() { return false; } + @Override public boolean isJsNative() { - return enclosingType != null && enclosingType.isJsNative(); + return body == null && jsName != null; } public void setSyntheticAccidentalOverride() { 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 6b49d6a1853..f0cfdda3b05 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 @@ -2541,6 +2541,7 @@ private List getGlobalStatements() { */ private static boolean doesNotHaveConcreteImplementation(JMethod method) { return method.isAbstract() + || method.isJsNative() || JjsUtils.isUnnecessarySyntheticAccidentalOverride(method) || (JProgram.isClinit(method) && method.getEnclosingType().getClinitTarget() != method.getEnclosingType()); diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java index a45072dad56..1fa838de21e 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java @@ -3092,6 +3092,7 @@ private void processNativeMethod(MethodDeclaration x) { JMethod method = curMethod.method; JsniMethod jsniMethod = jsniMethods.get(x); if (jsniMethod == null) { + method.setBody(null); return; } SourceInfo info = method.getSourceInfo(); diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java index e332910356c..a2294575e7d 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java @@ -218,8 +218,8 @@ private boolean isDelegatingToConstructor(JConstructor ctor, JConstructor target } private void checkField(JField x) { - if (x.isJsNative()) { - checkNativeJsMember(x); + if (x.getEnclosingType().isJsNative()) { + checkMemberOfNativeJsType(x); } checkUnusableByJs(x); @@ -241,8 +241,8 @@ private void checkMethod(JMethod x) { } currentProcessedMethods.addAll(x.getOverriddenMethods()); - if (x.isJsNative()) { - checkNativeJsMember(x); + if (x.getEnclosingType().isJsNative()) { + checkMemberOfNativeJsType(x); } checkUnusableByJs(x); @@ -281,7 +281,7 @@ private void checkJsPropertyType(String propertyName, String enclosingTypeName, } } - private void checkNativeJsMember(JMember member) { + private void checkMemberOfNativeJsType(JMember member) { if (member.isSynthetic()) { return; } diff --git a/user/test/com/google/gwt/core/CoreJsInteropSuite.java b/user/test/com/google/gwt/core/CoreJsInteropSuite.java index 82ccbd82673..52f5787d893 100644 --- a/user/test/com/google/gwt/core/CoreJsInteropSuite.java +++ b/user/test/com/google/gwt/core/CoreJsInteropSuite.java @@ -17,6 +17,7 @@ import com.google.gwt.core.client.interop.JsExportTest; import com.google.gwt.core.client.interop.JsFunctionTest; +import com.google.gwt.core.client.interop.JsMethodTest; import com.google.gwt.core.client.interop.JsPropertyTest; import com.google.gwt.core.client.interop.JsTypeArrayTest; import com.google.gwt.core.client.interop.JsTypeTest; @@ -33,6 +34,7 @@ public static Test suite() { suite.addTestSuite(JsTypeTest.class); suite.addTestSuite(JsPropertyTest.class); + suite.addTestSuite(JsMethodTest.class); suite.addTestSuite(JsTypeArrayTest.class); suite.addTestSuite(JsExportTest.class); suite.addTestSuite(JsFunctionTest.class); diff --git a/user/test/com/google/gwt/core/client/interop/JsMethodTest.java b/user/test/com/google/gwt/core/client/interop/JsMethodTest.java new file mode 100644 index 00000000000..2eef1042f13 --- /dev/null +++ b/user/test/com/google/gwt/core/client/interop/JsMethodTest.java @@ -0,0 +1,60 @@ +/* + * Copyright 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.core.client.interop; + +import static jsinterop.annotations.JsPackage.GLOBAL; + +import com.google.gwt.junit.client.GWTTestCase; + +import jsinterop.annotations.JsMethod; +import jsinterop.annotations.JsProperty; + +/** + * Tests JsMethod functionality. + */ +public class JsMethodTest extends GWTTestCase { + + @Override + public String getModuleName() { + return "com.google.gwt.core.Core"; + } + + class MyObject { + @JsProperty + public int mine; + + @JsMethod + public native boolean hasOwnProperty(String name); + } + + public void testNativeJsMethod() { + MyObject obj = new MyObject(); + obj.mine = 0; + assertTrue(obj.hasOwnProperty("mine")); + assertFalse(obj.hasOwnProperty("toString")); + } + + @JsMethod(namespace = GLOBAL) + private static native boolean isFinite(double d); + + public void testStaticNativeJsMethod() { + assertFalse(isFinite(Double.POSITIVE_INFINITY)); + assertFalse(isFinite(Double.NEGATIVE_INFINITY)); + assertFalse(isFinite(Double.NaN)); + assertTrue(isFinite(0)); + assertTrue(isFinite(1)); + } +}