Search in sources :

Example 1 with BaseFunction

use of net.sourceforge.htmlunit.corejs.javascript.BaseFunction in project htmlunit by HtmlUnit.

the class HTMLObjectElement method createAppletMethodAndProperties.

private void createAppletMethodAndProperties() throws Exception {
    final HtmlObject appletNode = (HtmlObject) getDomNodeOrDie();
    final Applet applet = appletNode.getApplet();
    if (applet == null) {
        return;
    }
    // Rhino should provide the possibility to declare delegate for Functions as it does for properties!!!
    for (final Method method : applet.getClass().getMethods()) {
        final Function f = new BaseFunction() {

            @Override
            public Object call(final Context cx, final Scriptable scope, final Scriptable thisObj, final Object[] args) {
                final Object[] realArgs = new Object[method.getParameterTypes().length];
                for (int i = 0; i < realArgs.length; i++) {
                    final Object arg;
                    if (i > args.length) {
                        arg = null;
                    } else {
                        arg = Context.jsToJava(args[i], method.getParameterTypes()[i]);
                    }
                    realArgs[i] = arg;
                }
                try {
                    return method.invoke(applet, realArgs);
                } catch (final Exception e) {
                    throw Context.throwAsScriptRuntimeEx(e);
                }
            }
        };
        ScriptableObject.defineProperty(this, method.getName(), f, ScriptableObject.READONLY);
    }
}
Also used : Context(net.sourceforge.htmlunit.corejs.javascript.Context) BaseFunction(net.sourceforge.htmlunit.corejs.javascript.BaseFunction) JsxFunction(com.gargoylesoftware.htmlunit.javascript.configuration.JsxFunction) Function(net.sourceforge.htmlunit.corejs.javascript.Function) BaseFunction(net.sourceforge.htmlunit.corejs.javascript.BaseFunction) Applet(java.applet.Applet) HtmlObject(com.gargoylesoftware.htmlunit.html.HtmlObject) ScriptableObject(net.sourceforge.htmlunit.corejs.javascript.ScriptableObject) HtmlObject(com.gargoylesoftware.htmlunit.html.HtmlObject) NativeJavaObject(net.sourceforge.htmlunit.corejs.javascript.NativeJavaObject) Method(java.lang.reflect.Method) Scriptable(net.sourceforge.htmlunit.corejs.javascript.Scriptable)

Example 2 with BaseFunction

use of net.sourceforge.htmlunit.corejs.javascript.BaseFunction in project htmlunit by HtmlUnit.

the class HTMLAppletElement method createAppletMethodAndProperties.

private void createAppletMethodAndProperties() throws Exception {
    final HtmlApplet appletNode = (HtmlApplet) getDomNodeOrDie();
    final Applet applet = appletNode.getApplet();
    if (applet == null) {
        return;
    }
    // Rhino should provide the possibility to declare delegate for Functions as it does for properties!!!
    for (final Method method : applet.getClass().getMethods()) {
        final Function f = new BaseFunction() {

            @Override
            public Object call(final Context cx, final Scriptable scope, final Scriptable thisObj, final Object[] args) {
                final Object[] realArgs = new Object[method.getParameterTypes().length];
                for (int i = 0; i < realArgs.length; i++) {
                    final Object arg;
                    if (i > args.length) {
                        arg = null;
                    } else {
                        arg = Context.jsToJava(args[i], method.getParameterTypes()[i]);
                    }
                    realArgs[i] = arg;
                }
                try {
                    return method.invoke(applet, realArgs);
                } catch (final Exception e) {
                    throw Context.throwAsScriptRuntimeEx(e);
                }
            }
        };
        ScriptableObject.defineProperty(this, method.getName(), f, ScriptableObject.READONLY);
    }
}
Also used : HtmlApplet(com.gargoylesoftware.htmlunit.html.HtmlApplet) Context(net.sourceforge.htmlunit.corejs.javascript.Context) Function(net.sourceforge.htmlunit.corejs.javascript.Function) BaseFunction(net.sourceforge.htmlunit.corejs.javascript.BaseFunction) BaseFunction(net.sourceforge.htmlunit.corejs.javascript.BaseFunction) Applet(java.applet.Applet) HtmlApplet(com.gargoylesoftware.htmlunit.html.HtmlApplet) ScriptableObject(net.sourceforge.htmlunit.corejs.javascript.ScriptableObject) Method(java.lang.reflect.Method) Scriptable(net.sourceforge.htmlunit.corejs.javascript.Scriptable)

Example 3 with BaseFunction

use of net.sourceforge.htmlunit.corejs.javascript.BaseFunction in project htmlunit by HtmlUnit.

the class WindowConcurrencyTest method doTestClearX_threadInterrupt.

private void doTestClearX_threadInterrupt(final String x) throws Exception {
    final String html = "<html><head><title>foo</title><script>\n" + "  function f() {\n" + "    alert('started');\n" + "    clear" + x + "(window.timeoutId);\n" + "    mySpecialFunction();\n" + "    alert('finished');\n" + "  }\n" + "  function test() {\n" + "    window.timeoutId = set" + x + "(f, 10);\n" + "  }\n" + "</script></head><body>\n" + "<span id='clickMe' onclick='test()'>click me</span>\n" + "</body></html>";
    final String[] expectedAlerts = { "started", "finished" };
    final List<String> collectedAlerts = new ArrayList<>();
    final HtmlPage page = loadPage(client_, html, collectedAlerts);
    final Function mySpecialFunction = new BaseFunction() {

        @Override
        public Object call(final Context cx, final Scriptable scope, final Scriptable thisObj, final Object[] args) {
            if (Thread.currentThread().isInterrupted()) {
                throw new RuntimeException("My thread is already interrupted");
            }
            return null;
        }
    };
    final ScriptableObject window = page.getEnclosingWindow().getScriptableObject();
    ScriptableObject.putProperty(window, "mySpecialFunction", mySpecialFunction);
    page.getHtmlElementById("clickMe").click();
    client_.waitForBackgroundJavaScript(5000);
    assertEquals(expectedAlerts, collectedAlerts);
}
Also used : Context(net.sourceforge.htmlunit.corejs.javascript.Context) Function(net.sourceforge.htmlunit.corejs.javascript.Function) BaseFunction(net.sourceforge.htmlunit.corejs.javascript.BaseFunction) BaseFunction(net.sourceforge.htmlunit.corejs.javascript.BaseFunction) ScriptableObject(net.sourceforge.htmlunit.corejs.javascript.ScriptableObject) HtmlPage(com.gargoylesoftware.htmlunit.html.HtmlPage) ArrayList(java.util.ArrayList) Scriptable(net.sourceforge.htmlunit.corejs.javascript.Scriptable)

Example 4 with BaseFunction

use of net.sourceforge.htmlunit.corejs.javascript.BaseFunction in project htmlunit by HtmlUnit.

the class JavaScriptEngine method init.

/**
 * Initializes all the JS stuff for the window.
 * @param webWindow the web window
 * @param context the current context
 * @throws Exception if something goes wrong
 */
private void init(final WebWindow webWindow, final Page page, final Context context) throws Exception {
    final WebClient webClient = webWindow.getWebClient();
    final BrowserVersion browserVersion = webClient.getBrowserVersion();
    final Window window = new Window();
    window.setClassName("Window");
    context.initSafeStandardObjects(window);
    final ClassConfiguration windowConfig = jsConfig_.getClassConfiguration("Window");
    if (windowConfig.getJsConstructor() != null) {
        final FunctionObject functionObject = new RecursiveFunctionObject("Window", windowConfig.getJsConstructor(), window);
        ScriptableObject.defineProperty(window, "constructor", functionObject, ScriptableObject.DONTENUM | ScriptableObject.PERMANENT | ScriptableObject.READONLY);
    } else {
        defineConstructor(window, window, new Window());
    }
    // remove some objects, that Rhino defines in top scope but that we don't want
    deleteProperties(window, "Continuation", "Iterator", "StopIteration", "BigInt");
    if (!browserVersion.hasFeature(JS_PROMISE)) {
        deleteProperties(window, "Promise");
    }
    if (!browserVersion.hasFeature(JS_SYMBOL)) {
        deleteProperties(window, "Symbol");
    }
    final ScriptableObject errorObject = (ScriptableObject) ScriptableObject.getProperty(window, "Error");
    if (browserVersion.hasFeature(JS_ERROR_STACK_TRACE_LIMIT)) {
        errorObject.defineProperty("stackTraceLimit", 10, ScriptableObject.EMPTY);
    } else {
        ScriptableObject.deleteProperty(errorObject, "stackTraceLimit");
    }
    if (!browserVersion.hasFeature(JS_ERROR_CAPTURE_STACK_TRACE)) {
        ScriptableObject.deleteProperty(errorObject, "captureStackTrace");
    }
    if (browserVersion.hasFeature(JS_URL_SEARCH_PARMS_ITERATOR_SIMPLE_NAME)) {
        URLSearchParams.NativeParamsIterator.init(window, "Iterator");
    } else {
        URLSearchParams.NativeParamsIterator.init(window, "URLSearchParams Iterator");
    }
    if (browserVersion.hasFeature(JS_FORM_DATA_ITERATOR_SIMPLE_NAME)) {
        FormData.FormDataIterator.init(window, "Iterator");
    } else {
        FormData.FormDataIterator.init(window, "FormData Iterator");
    }
    final Intl intl = new Intl();
    intl.setParentScope(window);
    window.defineProperty(intl.getClassName(), intl, ScriptableObject.DONTENUM);
    if (browserVersion.hasFeature(JS_INTL_NAMED_OBJECT)) {
        intl.setClassName("Object");
    }
    intl.defineProperties(browserVersion);
    if (browserVersion.hasFeature(JS_REFLECT)) {
        final Reflect reflect = new Reflect();
        reflect.setParentScope(window);
        window.defineProperty(reflect.getClassName(), reflect, ScriptableObject.DONTENUM);
    }
    final Map<Class<? extends Scriptable>, Scriptable> prototypes = new HashMap<>();
    final Map<String, Scriptable> prototypesPerJSName = new HashMap<>();
    final String windowClassName = Window.class.getName();
    for (final ClassConfiguration config : jsConfig_.getAll()) {
        final boolean isWindow = windowClassName.equals(config.getHostClass().getName());
        if (isWindow) {
            configureConstantsPropertiesAndFunctions(config, window);
            final HtmlUnitScriptable prototype = configureClass(config, window, browserVersion);
            prototypesPerJSName.put(config.getClassName(), prototype);
        } else {
            final HtmlUnitScriptable prototype = configureClass(config, window, browserVersion);
            if (config.isJsObject()) {
                // Place object with prototype property in Window scope
                final HtmlUnitScriptable obj = config.getHostClass().newInstance();
                prototype.defineProperty("__proto__", prototype, ScriptableObject.DONTENUM);
                // but not setPrototype!
                obj.defineProperty("prototype", prototype, ScriptableObject.DONTENUM);
                obj.setParentScope(window);
                obj.setClassName(config.getClassName());
                ScriptableObject.defineProperty(window, obj.getClassName(), obj, ScriptableObject.DONTENUM);
                // this obj won't have prototype, constants need to be configured on it again
                configureConstants(config, obj);
            }
            prototypes.put(config.getHostClass(), prototype);
            prototypesPerJSName.put(config.getClassName(), prototype);
        }
    }
    for (final ClassConfiguration config : jsConfig_.getAll()) {
        final Executable jsConstructor = config.getJsConstructor();
        final String jsClassName = config.getClassName();
        Scriptable prototype = prototypesPerJSName.get(jsClassName);
        final String hostClassSimpleName = config.getHostClassSimpleName();
        if ("Image".equals(hostClassSimpleName)) {
            prototype = prototypesPerJSName.get("HTMLImageElement");
        }
        if ("Option".equals(hostClassSimpleName)) {
            prototype = prototypesPerJSName.get("HTMLOptionElement");
        }
        switch(hostClassSimpleName) {
            case "WebKitMutationObserver":
                prototype = prototypesPerJSName.get("MutationObserver");
                break;
            case "webkitURL":
                prototype = prototypesPerJSName.get("URL");
                break;
            default:
        }
        if (prototype != null && config.isJsObject()) {
            if (jsConstructor == null) {
                final ScriptableObject constructor;
                if ("Window".equals(jsClassName)) {
                    constructor = (ScriptableObject) ScriptableObject.getProperty(window, "constructor");
                } else {
                    constructor = config.getHostClass().newInstance();
                    ((HtmlUnitScriptable) constructor).setClassName(config.getClassName());
                }
                defineConstructor(window, prototype, constructor);
                configureConstantsStaticPropertiesAndStaticFunctions(config, constructor);
            } else {
                final BaseFunction function;
                if ("Window".equals(jsClassName)) {
                    function = (BaseFunction) ScriptableObject.getProperty(window, "constructor");
                } else {
                    function = new RecursiveFunctionObject(jsClassName, jsConstructor, window);
                }
                if ("WebKitMutationObserver".equals(hostClassSimpleName) || "webkitURL".equals(hostClassSimpleName) || "Image".equals(hostClassSimpleName) || "Option".equals(hostClassSimpleName)) {
                    final Object prototypeProperty = ScriptableObject.getProperty(window, prototype.getClassName());
                    if (function instanceof FunctionObject) {
                        try {
                            ((FunctionObject) function).addAsConstructor(window, prototype);
                        } catch (final Exception e) {
                            // TODO see issue #1897
                            if (LOG.isWarnEnabled()) {
                                final String newline = System.lineSeparator();
                                LOG.warn("Error during JavaScriptEngine.init(WebWindow, Context)" + newline + e.getMessage() + newline + "prototype: " + prototype.getClassName());
                            }
                        }
                    }
                    ScriptableObject.defineProperty(window, hostClassSimpleName, function, ScriptableObject.DONTENUM);
                    // so we restore its value
                    if (!hostClassSimpleName.equals(prototype.getClassName())) {
                        if (prototypeProperty == UniqueTag.NOT_FOUND) {
                            ScriptableObject.deleteProperty(window, prototype.getClassName());
                        } else {
                            ScriptableObject.defineProperty(window, prototype.getClassName(), prototypeProperty, ScriptableObject.DONTENUM);
                        }
                    }
                } else {
                    if (function instanceof FunctionObject) {
                        try {
                            ((FunctionObject) function).addAsConstructor(window, prototype);
                        } catch (final Exception e) {
                            // TODO see issue #1897
                            if (LOG.isWarnEnabled()) {
                                final String newline = System.lineSeparator();
                                LOG.warn("Error during JavaScriptEngine.init(WebWindow, Context)" + newline + e.getMessage() + newline + "prototype: " + prototype.getClassName());
                            }
                        }
                    }
                }
                configureConstantsStaticPropertiesAndStaticFunctions(config, function);
            }
        }
    }
    window.setPrototype(prototypesPerJSName.get(Window.class.getSimpleName()));
    // once all prototypes have been build, it's possible to configure the chains
    final Scriptable objectPrototype = ScriptableObject.getObjectPrototype(window);
    for (final Map.Entry<String, Scriptable> entry : prototypesPerJSName.entrySet()) {
        final String name = entry.getKey();
        final ClassConfiguration config = jsConfig_.getClassConfiguration(name);
        final Scriptable prototype = entry.getValue();
        if (!StringUtils.isEmpty(config.getExtendedClassName())) {
            final Scriptable parentPrototype = prototypesPerJSName.get(config.getExtendedClassName());
            prototype.setPrototype(parentPrototype);
        } else {
            prototype.setPrototype(objectPrototype);
        }
    }
    // if we need more in the future, we have to enhance our JSX annotations
    if (browserVersion.hasFeature(JS_WINDOW_ACTIVEXOBJECT_HIDDEN)) {
        final Scriptable prototype = prototypesPerJSName.get("ActiveXObject");
        if (null != prototype) {
            final Method jsConstructor = ActiveXObject.class.getDeclaredMethod("jsConstructor", Context.class, Object[].class, Function.class, boolean.class);
            final FunctionObject functionObject = new HiddenFunctionObject("ActiveXObject", jsConstructor, window);
            try {
                functionObject.addAsConstructor(window, prototype);
            } catch (final Exception e) {
                // TODO see issue #1897
                if (LOG.isWarnEnabled()) {
                    final String newline = System.lineSeparator();
                    LOG.warn("Error during JavaScriptEngine.init(WebWindow, Context)" + newline + e.getMessage() + newline + "prototype: " + prototype.getClassName());
                }
            }
        }
    }
    configureRhino(webClient, browserVersion, window);
    window.setPrototypes(prototypes, prototypesPerJSName);
    window.initialize(webWindow, page);
    applyPolyfills(webClient, browserVersion, context, window);
}
Also used : HashMap(java.util.HashMap) IdFunctionObject(net.sourceforge.htmlunit.corejs.javascript.IdFunctionObject) FunctionObject(net.sourceforge.htmlunit.corejs.javascript.FunctionObject) Executable(java.lang.reflect.Executable) ClassConfiguration(com.gargoylesoftware.htmlunit.javascript.configuration.ClassConfiguration) Intl(com.gargoylesoftware.htmlunit.javascript.host.intl.Intl) WebWindow(com.gargoylesoftware.htmlunit.WebWindow) Window(com.gargoylesoftware.htmlunit.javascript.host.Window) ScriptableObject(net.sourceforge.htmlunit.corejs.javascript.ScriptableObject) Method(java.lang.reflect.Method) Scriptable(net.sourceforge.htmlunit.corejs.javascript.Scriptable) WebClient(com.gargoylesoftware.htmlunit.WebClient) RhinoException(net.sourceforge.htmlunit.corejs.javascript.RhinoException) ScriptException(com.gargoylesoftware.htmlunit.ScriptException) IOException(java.io.IOException) BaseFunction(net.sourceforge.htmlunit.corejs.javascript.BaseFunction) Reflect(com.gargoylesoftware.htmlunit.javascript.host.Reflect) IdFunctionObject(net.sourceforge.htmlunit.corejs.javascript.IdFunctionObject) ScriptableObject(net.sourceforge.htmlunit.corejs.javascript.ScriptableObject) FunctionObject(net.sourceforge.htmlunit.corejs.javascript.FunctionObject) ActiveXObject(com.gargoylesoftware.htmlunit.javascript.host.ActiveXObject) BrowserVersion(com.gargoylesoftware.htmlunit.BrowserVersion) Map(java.util.Map) HashMap(java.util.HashMap)

Example 5 with BaseFunction

use of net.sourceforge.htmlunit.corejs.javascript.BaseFunction in project htmlunit by HtmlUnit.

the class Element method createEventHandler.

/**
 * Create the event handler function from the attribute value.
 * @param eventName the event name (ex: "onclick")
 * @param attrValue the attribute value
 */
protected void createEventHandler(final String eventName, final String attrValue) {
    final DomElement htmlElt = getDomNodeOrDie();
    // TODO: check that it is an "allowed" event for the browser, and take care to the case
    final BaseFunction eventHandler = new EventHandler(htmlElt, eventName, attrValue);
    setEventHandler(eventName, eventHandler);
}
Also used : BaseFunction(net.sourceforge.htmlunit.corejs.javascript.BaseFunction) DomElement(com.gargoylesoftware.htmlunit.html.DomElement) EventHandler(com.gargoylesoftware.htmlunit.javascript.host.event.EventHandler)

Aggregations

BaseFunction (net.sourceforge.htmlunit.corejs.javascript.BaseFunction)7 ScriptableObject (net.sourceforge.htmlunit.corejs.javascript.ScriptableObject)5 Scriptable (net.sourceforge.htmlunit.corejs.javascript.Scriptable)4 Method (java.lang.reflect.Method)3 Context (net.sourceforge.htmlunit.corejs.javascript.Context)3 Function (net.sourceforge.htmlunit.corejs.javascript.Function)3 WebWindow (com.gargoylesoftware.htmlunit.WebWindow)2 JsxFunction (com.gargoylesoftware.htmlunit.javascript.configuration.JsxFunction)2 Window (com.gargoylesoftware.htmlunit.javascript.host.Window)2 EventHandler (com.gargoylesoftware.htmlunit.javascript.host.event.EventHandler)2 Applet (java.applet.Applet)2 BrowserVersion (com.gargoylesoftware.htmlunit.BrowserVersion)1 ScriptException (com.gargoylesoftware.htmlunit.ScriptException)1 WebClient (com.gargoylesoftware.htmlunit.WebClient)1 DomElement (com.gargoylesoftware.htmlunit.html.DomElement)1 HtmlApplet (com.gargoylesoftware.htmlunit.html.HtmlApplet)1 HtmlObject (com.gargoylesoftware.htmlunit.html.HtmlObject)1 HtmlPage (com.gargoylesoftware.htmlunit.html.HtmlPage)1 HtmlUnitScriptable (com.gargoylesoftware.htmlunit.javascript.HtmlUnitScriptable)1 ClassConfiguration (com.gargoylesoftware.htmlunit.javascript.configuration.ClassConfiguration)1