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() + ").");
}
}