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);
}
}
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);
}
}
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);
}
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);
}
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);
}
Aggregations