Java源码示例:net.sourceforge.htmlunit.corejs.javascript.Context

示例1
/**
 * Sets or updates the supplied attribute node on this element.
 * @param newAtt the attribute node to be associated with this element
 * @return the replaced attribute node, if any, {@code null} otherwise
 */
@JsxFunction
public XMLDOMAttribute setAttributeNode(final XMLDOMAttribute newAtt) {
    if (newAtt == null) {
        throw Context.reportRuntimeError("Type mismatch.");
    }

    final String name = newAtt.getBaseName();

    final XMLDOMNamedNodeMap nodes = (XMLDOMNamedNodeMap) getAttributes();
    final XMLDOMAttribute replacedAtt = (XMLDOMAttribute) nodes.getNamedItemWithoutSyntheticClassAttr(name);
    if (replacedAtt != null) {
        replacedAtt.detachFromParent();
    }

    final DomAttr newDomAttr = newAtt.getDomNodeOrDie();
    getDomNodeOrDie().setAttributeNode(newDomAttr);
    return replacedAtt;
}
 
示例2
/**
 * Sets the number of rows in this text area.
 * @param rows the number of rows in this text area
 */
@JsxSetter
public void setRows(final String rows) {
    try {
        final int i = new Float(rows).intValue();
        if (i < 0) {
            if (getBrowserVersion().hasFeature(JS_TEXT_AREA_SET_ROWS_NEGATIVE_THROWS_EXCEPTION)) {
                throw new NumberFormatException("New value for rows '" + rows + "' is smaller than zero.");
            }
            getDomNodeOrDie().setAttribute("rows", null);
            return;
        }
        getDomNodeOrDie().setAttribute("rows", Integer.toString(i));
    }
    catch (final NumberFormatException e) {
        if (getBrowserVersion().hasFeature(JS_TEXT_AREA_SET_ROWS_THROWS_EXCEPTION)) {
            throw Context.throwAsScriptRuntimeEx(e);
        }

        getDomNodeOrDie().setAttribute("rows", "2");
    }
}
 
示例3
/**
 * Deletes specified data.
 * @param offset the offset, in characters, at which to start deleting string data
 * @param count the number of characters to delete
 */
@JsxFunction
public void deleteData(final int offset, final int count) {
    if (offset < 0) {
        throw Context.reportRuntimeError("The offset must be 0 or a positive number that is not greater than the "
                + "number of characters in the data.");
    }
    if (count < 0) {
        throw Context.reportRuntimeError("The offset must be 0 or a positive number that is not greater than the "
                + "number of characters in the data.");
    }
    if (count == 0) {
        return;
    }

    final DomCharacterData domCharacterData = getDomNodeOrDie();
    if (offset > domCharacterData.getLength()) {
        throw Context.reportRuntimeError("The offset must be 0 or a positive number that is not greater than the "
                + "number of characters in the data.");
    }

    domCharacterData.deleteData(offset, count);
}
 
示例4
/**
 * Returns the value of the {@code forms} property.
 * @return the value of the {@code forms} property
 */
@JsxGetter({CHROME, IE})
public Object getForms() {
    return new HTMLCollection(getDomNodeOrDie(), false) {
        @Override
        protected boolean isMatching(final DomNode node) {
            return node instanceof HtmlForm && node.getPrefix() == null;
        }

        @Override
        public Object call(final Context cx, final Scriptable scope,
                final Scriptable thisObj, final Object[] args) {
            if (getBrowserVersion().hasFeature(JS_DOCUMENT_FORMS_FUNCTION_SUPPORTED)) {
                return super.call(cx, scope, thisObj, args);
            }
            throw Context.reportRuntimeError("TypeError: document.forms is not a function");
        }
    };
}
 
示例5
/**
 * Encapsulates the given {@link DOMException} into a Rhino-compatible exception.
 *
 * @param exception the exception to encapsulate
 * @return the created exception
 */
protected RhinoException asJavaScriptException(final DOMException exception) {
    final Window w = getWindow();
    exception.setPrototype(w.getPrototype(exception.getClass()));
    exception.setParentScope(w);

    // get current line and file name
    // this method can only be used in interpreted mode. If one day we choose to use compiled mode,
    // then we'll have to find an other way here.
    final String fileName;
    final int lineNumber;
    if (Context.getCurrentContext().getOptimizationLevel() == -1) {
        final int[] linep = new int[1];
        final String sourceName = new Interpreter().getSourcePositionFromStack(Context.getCurrentContext(), linep);
        fileName = sourceName.replaceFirst("script in (.*) from .*", "$1");
        lineNumber = linep[0];
    }
    else {
        throw new Error("HtmlUnit not ready to run in compiled mode");
    }

    exception.setLocation(fileName, lineNumber);

    return new JavaScriptException(exception, fileName, lineNumber);
}
 
示例6
/**
 * Checks whether the given element is contained within this object.
 * @param element element object that specifies the element to check
 * @return true if the element is contained within this object
 */
@JsxFunction({CHROME, FF})
public boolean contains(final Object element) {
    if (!(element instanceof Node)) {
        if (getBrowserVersion().hasFeature(JS_NODE_CONTAINS_RETURNS_FALSE_FOR_INVALID_ARG)) {
            return false;
        }
        throw Context.reportRuntimeError("Could not convert JavaScript argument arg 0");
    }

    if (getBrowserVersion().hasFeature(JS_NODE_CONTAINS_RETURNS_FALSE_FOR_INVALID_ARG)) {
        if (element instanceof CharacterData) {
            return false;
        }
        if (this instanceof CharacterData) {
            throw Context.reportRuntimeError("Function 'contains' not available for text nodes.");
        }
    }

    for (Node parent = (Node) element; parent != null; parent = parent.getParentElement()) {
        if (this == parent) {
            return true;
        }
    }
    return false;
}
 
示例7
/**
 * Sets the value of the {@code span} property.
 * @param span the value of the {@code span} property
 */
@JsxSetter
public void setSpan(final Object span) {
    final double d = Context.toNumber(span);
    int i = (int) d;
    if (i < 1) {
        if (getBrowserVersion().hasFeature(JS_TABLE_SPAN_THROWS_EXCEPTION_IF_INVALID)) {
            final Exception e = new Exception("Cannot set the span property to invalid value: " + span);
            Context.throwAsScriptRuntimeEx(e);
        }
        else {
            i = 1;
        }
    }
    getDomNodeOrDie().setAttribute("span", Integer.toString(i));
}
 
示例8
/**
 * Returns the value of the {@code embeds} property.
 * @return the value of the {@code embeds} property
 */
@JsxGetter({CHROME, IE})
public Object getImages() {
    return new HTMLCollection(getDomNodeOrDie(), false) {
        @Override
        protected boolean isMatching(final DomNode node) {
            return node instanceof HtmlImage;
        }

        @Override
        public Object call(final Context cx, final Scriptable scope,
                final Scriptable thisObj, final Object[] args) {
            if (getBrowserVersion().hasFeature(JS_DOCUMENT_FORMS_FUNCTION_SUPPORTED)) {
                return super.call(cx, scope, thisObj, args);
            }
            throw Context.reportRuntimeError("TypeError: document.images is not a function");
        }
    };
}
 
示例9
/**
 * Returns the value of the {@code src} attribute.
 * @return the value of the {@code src} attribute
 */
@JsxGetter
public String getSrc() {
    final HtmlImage img = (HtmlImage) getDomNodeOrDie();
    final String src = img.getSrcAttribute();
    if ("".equals(src)) {
        return src;
    }
    try {
        final HtmlPage page = (HtmlPage) img.getPage();
        return page.getFullyQualifiedUrl(src).toExternalForm();
    }
    catch (final MalformedURLException e) {
        final String msg = "Unable to create fully qualified URL for src attribute of image " + e.getMessage();
        throw Context.reportRuntimeError(msg);
    }
}
 
示例10
/**
 * Indicates support for the specified feature.
 * @param feature a string that specifies the feature to test
 * @param version a string that specifies the version number to test
 * @return true if the specified feature is implemented; otherwise false
 */
@JsxFunction
public boolean hasFeature(final String feature, final String version) {
    if (feature == null || "null".equals(feature) || version == null || "null".equals(version)) {
        throw Context.reportRuntimeError("Type mismatch.");
    }

    if ("XML".equals(feature) && "1.0".equals(version)) {
        return true;
    }
    else if ("DOM".equals(feature) && "1.0".equals(version)) {
        return true;
    }
    else if ("MS-DOM".equals(feature) && ("1.0".equals(version) || "2.0".equals(version))) {
        return true;
    }
    return false;
}
 
示例11
/**
 * Sets the number of columns in this text area.
 * @param cols the number of columns in this text area
 */
@JsxSetter
public void setCols(final String cols) {
    try {
        final int i = Float.valueOf(cols).intValue();
        if (i < 0) {
            if (getBrowserVersion().hasFeature(JS_TEXT_AREA_SET_COLS_NEGATIVE_THROWS_EXCEPTION)) {
                throw new NumberFormatException("New value for cols '" + cols + "' is smaller than zero.");
            }
            getDomNodeOrDie().setAttribute("cols", null);
            return;
        }
        getDomNodeOrDie().setAttribute("cols", Integer.toString(i));
    }
    catch (final NumberFormatException e) {
        if (getBrowserVersion().hasFeature(JS_TEXT_AREA_SET_COLS_THROWS_EXCEPTION)) {
            throw Context.throwAsScriptRuntimeEx(e);
        }
        getDomNodeOrDie().setAttribute("cols", "20");
    }
}
 
示例12
/**
 * Replaces this ChildNode in the children list of its parent with a set of Node or DOMString objects.
 * @param context the context
 * @param thisObj this object
 * @param args the arguments
 * @param function the function
 */
protected static void replaceWith(final Context context, final Scriptable thisObj, final Object[] args,
        final Function function) {
    final DomNode thisDomNode = ((Node) thisObj).getDomNodeOrDie();
    final DomNode parentNode = thisDomNode.getParentNode();
    final DomNode nextSibling = thisDomNode.getNextSibling();
    boolean isFirst = true;
    for (Object arg : args) {
        final DomNode newNode = toNodeOrTextNode((Node) thisObj, arg).getDomNodeOrDie();
        if (isFirst) {
            isFirst = false;
            thisDomNode.replace(newNode);
        }
        else {
            if (nextSibling != null) {
                nextSibling.insertBefore(newNode);
            }
            else {
                parentNode.appendChild(newNode);
            }
        }
    }
}
 
示例13
/**
 * Invokes the onerror handler if one has been set.
 * @param context the context within which the onerror handler is to be invoked;
 *                if {@code null}, the current thread's context is used.
 */
private void processError(Context context) {
    final Function onError = getOnerror();
    if (onError != null) {
        final Scriptable scope = onError.getParentScope();
        final JavaScriptEngine jsEngine = (JavaScriptEngine) containingPage_.getWebClient().getJavaScriptEngine();

        final Object[] params = {new ProgressEvent(this, Event.TYPE_ERROR)};

        if (LOG.isDebugEnabled()) {
            LOG.debug("Calling onerror handler");
        }
        jsEngine.callFunction(containingPage_, onError, this, scope, params);
        if (LOG.isDebugEnabled()) {
            if (context == null) {
                context = Context.getCurrentContext();
            }
            LOG.debug("onerror handler: " + context.decompileFunction(onError, 4));
            LOG.debug("Calling onerror handler done.");
        }
    }
}
 
示例14
/**
 * Returns the value of this number result.
 * @return the value of this number result
 */
@JsxGetter
public double getNumberValue() {
    if (resultType_ != NUMBER_TYPE) {
        throw Context.reportRuntimeError("Cannot get numberValue for type: " + resultType_);
    }
    final String asString = asString();
    Double answer;
    try {
        answer = Double.parseDouble(asString);
    }
    catch (final NumberFormatException e) {
        answer = Double.NaN;
    }
    return answer;
}
 
示例15
/**
 * Changes the start position of the range.
 * @param unit specifies the units to move
 * @param count the number of units to move
 * @return the number of units moved
 */
@JsxFunction
public int moveStart(final String unit, final Object count) {
    if (!"character".equals(unit)) {
        LOG.warn("moveStart('" + unit + "') is not yet supported");
        return 0;
    }
    int c = 1;
    if (count != Undefined.instance) {
        c = (int) Context.toNumber(count);
    }
    if (range_.getStartContainer() == range_.getEndContainer()
            && range_.getStartContainer() instanceof SelectableTextInput) {
        final SelectableTextInput input = (SelectableTextInput) range_.getStartContainer();
        c = constrainMoveBy(c, range_.getStartOffset(), input.getText().length());
        range_.setStart(input, range_.getStartOffset() + c);
    }
    return c;
}
 
示例16
/**
 * {@inheritDoc}
 */
@Override
@JsxFunction
public String toString() {
    String name;
    if (name_ == Undefined.instance) {
        name = "";
    }
    else {
        name = Context.toString(name_);
        final ClassConfiguration config = AbstractJavaScriptConfiguration
                .getClassConfiguration(getClass(), getBrowserVersion());

        for (final Entry<String, ClassConfiguration.PropertyInfo> propertyEntry
                : config.getStaticPropertyEntries()) {
            if (propertyEntry.getKey().equals(name)) {
                name = "Symbol." + name;
                break;
            }
        }
    }
    return "Symbol(" + name + ')';
}
 
示例17
/**
 * Sets the value of the {@code vAlign} property.
 * @param vAlign the value of the {@code vAlign} property
 * @param valid the valid values; if {@code null}, any value is valid
 */
protected void setVAlign(final Object vAlign, final String[] valid) {
    final String valign = Context.toString(vAlign);
    final String valignLC = valign.toLowerCase(Locale.ROOT);
    if (valid == null || ArrayUtils.contains(valid, valignLC)) {
        if (getBrowserVersion().hasFeature(JS_VALIGN_CONVERTS_TO_LOWERCASE)) {
            getDomNodeOrDie().setAttribute("valign", valignLC);
        }
        else {
            getDomNodeOrDie().setAttribute("valign", valign);
        }
    }
    else {
        throw Context.reportRuntimeError("Cannot set the vAlign property to invalid value: " + vAlign);
    }
}
 
示例18
/**
 * Returns the HTTP status code returned by a request.
 * @return the HTTP status code returned by a request
 */
@JsxGetter
public int getStatus() {
    if (state_ != STATE_DONE) {
        throw Context.reportRuntimeError("Unspecified error (request not sent).");
    }
    if (webResponse_ != null) {
        return webResponse_.getStatusCode();
    }

    if (LOG.isErrorEnabled()) {
        LOG.error("XMLHTTPRequest.status was retrieved without a response available (readyState: "
            + state_ + ").");
    }
    return 0;
}
 
示例19
/**
 * {@inheritDoc}
 */
@Override
public Object call(final Context cx, final Scriptable scope,
    final Scriptable thisObj, final Object[] args)
    throws JavaScriptException {

    // the js object to which this event is attached has to be the scope
    final SimpleScriptable jsObj = node_.getScriptableObject();
    // compile "just in time"
    if (realFunction_ == null) {
        realFunction_ = cx.compileFunction(jsObj, jsSnippet_, eventName_ + " event for " + node_
            + " in " + node_.getPage().getUrl(), 0, null);
        realFunction_.setParentScope(jsObj);
    }

    return realFunction_.call(cx, scope, thisObj, args);
}
 
示例20
/**
 * Replaces a state.
 * @param object the state object
 * @param title the title
 * @param url an optional URL
 */
@JsxFunction
public void replaceState(final Object object, final String title, final String url) {
    final WebWindow w = getWindow().getWebWindow();
    try {
        URL newStateUrl = null;
        final HtmlPage page = (HtmlPage) w.getEnclosedPage();
        if (StringUtils.isNotBlank(url)) {
            newStateUrl = page.getFullyQualifiedUrl(url);
        }
        w.getHistory().replaceState(object, newStateUrl);
    }
    catch (final MalformedURLException e) {
        Context.throwAsScriptRuntimeEx(e);
    }
}
 
示例21
/**
 * Converts a date to a string, returning the "time" portion using the current locale's conventions.
 * @param context the JavaScript context
 * @param thisObj the scriptable
 * @param args the arguments passed into the method
 * @param function the function
 * @return converted string
 */
public static String toLocaleTimeString(
        final Context context, final Scriptable thisObj, final Object[] args, final Function function) {
    final String formatString;
    final BrowserVersion browserVersion = ((Window) thisObj.getParentScope()).getBrowserVersion();

    if (browserVersion.hasFeature(JS_DATE_WITH_LEFT_TO_RIGHT_MARK)) {
        // [U+200E] -> Unicode Character 'LEFT-TO-RIGHT MARK'
        formatString = "\u200Eh\u200E:\u200Emm\u200E:\u200Ess\u200E \u200Ea";
    }
    else {
        formatString = "h:mm:ss a";
    }
    final FastDateFormat format =  FastDateFormat.getInstance(formatString, getLocale(browserVersion));
    return format.format(getDateValue(thisObj));
}
 
示例22
/**
 * Calculate TextMetrics for the given text.
 * @param text the text to measure
 * @return the text metrics
 */
@JsxFunction
public TextMetrics measureText(final Object text) {
    if (text == null || Undefined.instance == text) {
        throw Context.throwAsScriptRuntimeEx(
                new RuntimeException("Missing argument for CanvasRenderingContext2D.measureText()."));
    }

    final String textValue = Context.toString(text);

    // TODO take font into account
    final int width = textValue.length() * getBrowserVersion().getPixesPerChar();

    final TextMetrics metrics = new TextMetrics(width);
    metrics.setParentScope(getParentScope());
    metrics.setPrototype(getPrototype(metrics.getClass()));
    return metrics;
}
 
示例23
/**
 * {@inheritDoc}
 * @see ScriptableObject#get(java.lang.String,net.sourceforge.htmlunit.corejs.javascript.Scriptable)
 */
@Override
public Object get(final String name, final Scriptable start) {
    final Method propertyGetter = properties_.get(name);
    final Object response;
    if (propertyGetter != null) {
        response = invoke(propertyGetter);
    }
    else {
        final Object fromSuper = super.get(name, start);
        if (fromSuper != Scriptable.NOT_FOUND) {
            response = fromSuper;
        }
        else {
            final Object byName = invoke(getByNameFallback_, new Object[] {name});
            if (byName != null) {
                response = byName;
            }
            else {
                response = Scriptable.NOT_FOUND;
            }
        }
    }

    return Context.javaToJS(response, ScriptableObject
            .getTopLevelScope(start));
}
 
示例24
/**
 * {@inheritDoc}
 */
@Override
public Scriptable construct(final Context cx, final Scriptable scope, final Object[] args) {
    if (!getBrowserVersion().hasFeature(JS_FORM_USABLE_AS_FUNCTION)) {
        throw Context.reportRuntimeError("Not a function.");
    }
    return null;
}
 
示例25
private static int getSmallInt(final Object object) {
    final String s = Context.toString(object);
    if (Character.isDigit(s.charAt(0))) {
        final int i = Integer.parseInt(s);
        if (i < 70) {
            return i;
        }
    }
    return -1;
}
 
示例26
/**
 * {@inheritDoc}
 */
@Override
public void onEnter(final Context cx, final Scriptable activation, final Scriptable thisObj, final Object[] args) {
    if (LOG.isTraceEnabled()) {
        final StringBuilder sb = new StringBuilder();

        final String line = getFirstLine(cx);
        final String source = getSourceName(cx);
        sb.append(source).append(":").append(line).append(" ");

        Scriptable parent = activation.getParentScope();
        while (parent != null) {
            sb.append("   ");
            parent = parent.getParentScope();
        }
        final String functionName = getFunctionName(thisObj);
        sb.append(functionName).append("(");
        final int nbParams = functionOrScript_.getParamCount();
        for (int i = 0; i < nbParams; i++) {
            final String argAsString;
            if (i < args.length) {
                argAsString = stringValue(args[i]);
            }
            else {
                argAsString = "undefined";
            }
            sb.append(getParamName(i)).append(": ").append(argAsString);
            if (i < nbParams - 1) {
                sb.append(", ");
            }
        }
        sb.append(")");

        LOG.trace(sb);
    }
}
 
示例27
/**
 * Sets the root element of the document.
 * @param element the root element of the document
 */
@JsxSetter
public void setDocumentElement(final XMLDOMElement element) {
    if (element == null) {
        throw Context.reportRuntimeError("Type mismatch.");
    }

    final XMLDOMElement documentElement = getDocumentElement();
    if (documentElement != null) {
        documentElement.getDomNodeOrDie().remove();
    }

    appendChild(element);
}
 
示例28
/**
 * Returns the value of this string result.
 * @return the value of this string result
 */
@JsxGetter
public String getStringValue() {
    if (resultType_ != STRING_TYPE) {
        throw Context.reportRuntimeError("Cannot get stringValue for type: " + resultType_);
    }
    return asString();
}
 
示例29
/**
 * Changes the number of options: removes options if the new length
 * is less than the current one else add new empty options to reach the
 * new length.
 * @param newLength the new length property value
 */
@JsxSetter
public void setLength(final int newLength) {
    if (newLength < 0) {
        if (getBrowserVersion().hasFeature(JS_SELECT_OPTIONS_IGNORE_NEGATIVE_LENGTH)) {
            return;
        }
        throw Context.reportRuntimeError("Length is negative");
    }

    final int currentLength = htmlSelect_.getOptionSize();
    if (currentLength > newLength) {
        htmlSelect_.setOptionSize(newLength);
    }
    else {
        final SgmlPage page = htmlSelect_.getPage();
        final ElementFactory factory = page.getWebClient().getPageCreator()
                                        .getHtmlParser().getFactory(HtmlOption.TAG_NAME);
        for (int i = currentLength; i < newLength; i++) {
            final HtmlOption option = (HtmlOption) factory.createElement(page, HtmlOption.TAG_NAME, null);
            htmlSelect_.appendOption(option);
            if (getBrowserVersion().hasFeature(JS_SELECT_OPTIONS_ADD_EMPTY_TEXT_CHILD_WHEN_EXPANDING)) {
                option.appendChild(new DomText(option.getPage(), ""));
            }
        }
    }
}
 
示例30
/**
 * Returns the first element within the document that matches the specified group of selectors.
 * @param selectors the selectors
 * @return null if no matches are found; otherwise, it returns the first matching element
 */
@JsxFunction
public Node querySelector(final String selectors) {
    try {
        final DomNode node = getDomNodeOrDie().querySelector(selectors);
        if (node != null) {
            return (Node) node.getScriptableObject();
        }
        return null;
    }
    catch (final CSSException e) {
        throw Context.reportRuntimeError("An invalid or illegal selector was specified (selector: '"
                + selectors + "' error: " + e.getMessage() + ").");
    }
}