Search in sources :

Example 1 with Intl

use of com.gargoylesoftware.htmlunit.javascript.host.intl.Intl 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)

Aggregations

BrowserVersion (com.gargoylesoftware.htmlunit.BrowserVersion)1 ScriptException (com.gargoylesoftware.htmlunit.ScriptException)1 WebClient (com.gargoylesoftware.htmlunit.WebClient)1 WebWindow (com.gargoylesoftware.htmlunit.WebWindow)1 ClassConfiguration (com.gargoylesoftware.htmlunit.javascript.configuration.ClassConfiguration)1 ActiveXObject (com.gargoylesoftware.htmlunit.javascript.host.ActiveXObject)1 Reflect (com.gargoylesoftware.htmlunit.javascript.host.Reflect)1 Window (com.gargoylesoftware.htmlunit.javascript.host.Window)1 Intl (com.gargoylesoftware.htmlunit.javascript.host.intl.Intl)1 IOException (java.io.IOException)1 Executable (java.lang.reflect.Executable)1 Method (java.lang.reflect.Method)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 BaseFunction (net.sourceforge.htmlunit.corejs.javascript.BaseFunction)1 FunctionObject (net.sourceforge.htmlunit.corejs.javascript.FunctionObject)1 IdFunctionObject (net.sourceforge.htmlunit.corejs.javascript.IdFunctionObject)1 RhinoException (net.sourceforge.htmlunit.corejs.javascript.RhinoException)1 Scriptable (net.sourceforge.htmlunit.corejs.javascript.Scriptable)1 ScriptableObject (net.sourceforge.htmlunit.corejs.javascript.ScriptableObject)1