1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript;
16
17 import static org.htmlunit.BrowserVersionFeatures.JS_NATIVE_FUNCTION_TOSTRING_COMPACT;
18 import static org.htmlunit.BrowserVersionFeatures.JS_NATIVE_FUNCTION_TOSTRING_NL;
19
20 import org.htmlunit.BrowserVersion;
21 import org.htmlunit.corejs.javascript.BaseFunction;
22 import org.htmlunit.corejs.javascript.Context;
23 import org.htmlunit.corejs.javascript.Function;
24 import org.htmlunit.corejs.javascript.Scriptable;
25 import org.htmlunit.corejs.javascript.ScriptableObject;
26
27
28
29
30
31
32
33
34
35 public final class NativeFunctionToStringFunction {
36
37
38
39
40
41
42 public static void installFix(final Scriptable window, final BrowserVersion browserVersion) {
43 if (browserVersion.hasFeature(JS_NATIVE_FUNCTION_TOSTRING_COMPACT)) {
44 final ScriptableObject fnPrototype =
45 (ScriptableObject) ScriptableObject.getClassPrototype(window, "Function");
46 final Function originalToString = (Function) ScriptableObject.getProperty(fnPrototype, "toString");
47 final Function newToString = new NativeFunctionToStringFunctionChrome(originalToString);
48 ScriptableObject.putProperty(fnPrototype, "toString", newToString);
49 }
50 else if (browserVersion.hasFeature(JS_NATIVE_FUNCTION_TOSTRING_NL)) {
51 final ScriptableObject fnPrototype =
52 (ScriptableObject) ScriptableObject.getClassPrototype(window, "Function");
53 final Function originalToString = (Function) ScriptableObject.getProperty(fnPrototype, "toString");
54 final Function newToString = new NativeFunctionToStringFunctionFF(originalToString);
55 ScriptableObject.putProperty(fnPrototype, "toString", newToString);
56 }
57 }
58
59 private NativeFunctionToStringFunction() {
60 super();
61 }
62
63 static class NativeFunctionToStringFunctionChrome extends FunctionWrapper {
64
65 NativeFunctionToStringFunctionChrome(final Function wrapped) {
66 super(wrapped);
67 }
68
69
70
71
72 @Override
73 public Object call(final Context cx, final Scriptable scope, final Scriptable thisObj, final Object[] args) {
74 final String s = (String) super.call(cx, scope, thisObj, args);
75
76 if (thisObj instanceof BaseFunction && s.contains("[native code")) {
77 final String functionName = ((BaseFunction) thisObj).getFunctionName();
78 return "function " + functionName + "() { [native code] }";
79 }
80 return s.replace("function anonymous() {", "function anonymous(\n) {\n");
81 }
82 }
83
84 static class NativeFunctionToStringFunctionFF extends FunctionWrapper {
85
86 NativeFunctionToStringFunctionFF(final Function wrapped) {
87 super(wrapped);
88 }
89
90
91
92
93 @Override
94 public Object call(final Context cx, final Scriptable scope, final Scriptable thisObj, final Object[] args) {
95 final String s = (String) super.call(cx, scope, thisObj, args);
96
97 if (thisObj instanceof BaseFunction && s.contains("[native code")) {
98 final String functionName = ((BaseFunction) thisObj).getFunctionName();
99 return "function " + functionName + "() {\n [native code]\n}";
100 }
101 return s.replace("function anonymous() {", "function anonymous(\n) {\n");
102 }
103 }
104 }