mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Add basic binding for HTMLCollection.
This commit is contained in:
parent
5f672775b2
commit
6660ea0278
14 changed files with 282 additions and 95 deletions
|
@ -212,9 +212,9 @@ DOMInterfaces = {
|
||||||
|
|
||||||
'HTMLCollection': [
|
'HTMLCollection': [
|
||||||
{
|
{
|
||||||
'nativeType': 'nsIHTMLCollection',
|
'nativeType': 'HTMLCollection',
|
||||||
'prefable': True,
|
#'prefable': True,
|
||||||
'resultNotAddRefed': [ 'item' ]
|
#'resultNotAddRefed': [ 'item' ]
|
||||||
}],
|
}],
|
||||||
|
|
||||||
'HTMLOptionsCollection': [
|
'HTMLOptionsCollection': [
|
||||||
|
@ -490,7 +490,7 @@ DOMInterfaces = {
|
||||||
}
|
}
|
||||||
|
|
||||||
# These are temporary, until they've been converted to use new DOM bindings
|
# These are temporary, until they've been converted to use new DOM bindings
|
||||||
def addExternalIface(iface, nativeType=None, headerFile=None):
|
def addExternalIface(iface, nativeType=None, headerFile=None, pointerType=None):
|
||||||
domInterface = {
|
domInterface = {
|
||||||
'concrete': False
|
'concrete': False
|
||||||
}
|
}
|
||||||
|
@ -498,6 +498,8 @@ def addExternalIface(iface, nativeType=None, headerFile=None):
|
||||||
domInterface['nativeType'] = nativeType
|
domInterface['nativeType'] = nativeType
|
||||||
if not headerFile is None:
|
if not headerFile is None:
|
||||||
domInterface['headerFile'] = headerFile
|
domInterface['headerFile'] = headerFile
|
||||||
|
if not pointerType is None:
|
||||||
|
domInterface['pointerType'] = pointerType
|
||||||
DOMInterfaces[iface] = domInterface
|
DOMInterfaces[iface] = domInterface
|
||||||
|
|
||||||
# If you add one of these, you need to make sure nsDOMQS.h has the relevant
|
# If you add one of these, you need to make sure nsDOMQS.h has the relevant
|
||||||
|
@ -519,7 +521,7 @@ addExternalIface('CSSRule')
|
||||||
addExternalIface('CSSValue')
|
addExternalIface('CSSValue')
|
||||||
addExternalIface('DOMStringList', nativeType='nsDOMStringList',
|
addExternalIface('DOMStringList', nativeType='nsDOMStringList',
|
||||||
headerFile='nsDOMLists.h')
|
headerFile='nsDOMLists.h')
|
||||||
addExternalIface('Element', nativeType='nsGenericElement')
|
addExternalIface('Element', nativeType='AbstractNode', pointerType='')
|
||||||
addExternalIface('File')
|
addExternalIface('File')
|
||||||
addExternalIface('HitRegionOptions', nativeType='nsISupports')
|
addExternalIface('HitRegionOptions', nativeType='nsISupports')
|
||||||
addExternalIface('HTMLElement')
|
addExternalIface('HTMLElement')
|
||||||
|
|
|
@ -1041,10 +1041,16 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
undefinedBehavior = treatAs[treatUndefinedAs]
|
undefinedBehavior = treatAs[treatUndefinedAs]
|
||||||
|
|
||||||
def getConversionCode(varName):
|
def getConversionCode(varName):
|
||||||
|
#conversionCode = (
|
||||||
|
# "if (!ConvertJSValueToString(cx, ${val}, ${valPtr}, %s, %s, %s)) {\n"
|
||||||
|
# " return false;\n"
|
||||||
|
# "}" % (nullBehavior, undefinedBehavior, varName))
|
||||||
conversionCode = (
|
conversionCode = (
|
||||||
"if (!ConvertJSValueToString(cx, ${val}, ${valPtr}, %s, %s, %s)) {\n"
|
"let strval = jsval_to_str(cx, ${val});\n"
|
||||||
" return false;\n"
|
"if strval.is_err() {\n"
|
||||||
"}" % (nullBehavior, undefinedBehavior, varName))
|
" return 0;\n"
|
||||||
|
"}\n"
|
||||||
|
"%s = str(strval.get());" % varName)
|
||||||
if defaultValue is None:
|
if defaultValue is None:
|
||||||
return conversionCode
|
return conversionCode
|
||||||
|
|
||||||
|
@ -1072,15 +1078,15 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
declType, None, isOptional)
|
declType, None, isOptional)
|
||||||
|
|
||||||
if isOptional:
|
if isOptional:
|
||||||
declType = "Optional<nsAString>"
|
declType = "Option<DOMString>"
|
||||||
else:
|
else:
|
||||||
declType = "NonNull<nsAString>"
|
declType = "DOMString"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
"%s\n"
|
"%s\n" %
|
||||||
"const_cast<%s&>(${declName}) = &${holderName};" %
|
#"const_cast<%s&>(${declName}) = &${holderName};" %
|
||||||
(getConversionCode("${holderName}"), declType),
|
(getConversionCode("${declName}")),
|
||||||
CGGeneric("const " + declType), CGGeneric("FakeDependentString"),
|
CGGeneric(declType), None, #CGGeneric("FakeDependentString"),
|
||||||
# No need to deal with Optional here; we have handled it already
|
# No need to deal with Optional here; we have handled it already
|
||||||
False)
|
False)
|
||||||
|
|
||||||
|
@ -1441,7 +1447,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
||||||
"}\n" +
|
"}\n" +
|
||||||
successCode)
|
successCode)
|
||||||
else:
|
else:
|
||||||
tail = "return JS_WrapValue(cx, ${jsvalPtr});"
|
tail = "return JS_WrapValue(cx, cast::transmute(${jsvalPtr}));"
|
||||||
return ("${jsvalRef} = %s;\n" +
|
return ("${jsvalRef} = %s;\n" +
|
||||||
tail) % (value)
|
tail) % (value)
|
||||||
|
|
||||||
|
@ -1511,7 +1517,8 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
if type.nullable():
|
if type.nullable():
|
||||||
wrappingCode = ("if %s.is_none() {\n" % (result) +
|
wrappingCode = ("if %s.is_none() {\n" % (result) +
|
||||||
CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
|
CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
|
||||||
"}\n")
|
"}\n" +
|
||||||
|
"let mut %s = %s.get();\n" % (result, result))
|
||||||
else:
|
else:
|
||||||
wrappingCode = ""
|
wrappingCode = ""
|
||||||
if (not descriptor.interface.isExternal() and
|
if (not descriptor.interface.isExternal() and
|
||||||
|
@ -1522,7 +1529,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
if not isCreator:
|
if not isCreator:
|
||||||
raise MethodNotCreatorError(descriptor.interface.identifier.name)
|
raise MethodNotCreatorError(descriptor.interface.identifier.name)
|
||||||
wrapMethod = "WrapNewBindingNonWrapperCachedObject"
|
wrapMethod = "WrapNewBindingNonWrapperCachedObject"
|
||||||
wrap = "%s(cx, ${obj}, %s.get(), ${jsvalPtr})" % (wrapMethod, result)
|
wrap = "%s(cx, ${obj}, %s, ${jsvalPtr})" % (wrapMethod, result)
|
||||||
# We don't support prefable stuff in workers.
|
# We don't support prefable stuff in workers.
|
||||||
assert(not descriptor.prefable or not descriptor.workers)
|
assert(not descriptor.prefable or not descriptor.workers)
|
||||||
if not descriptor.prefable:
|
if not descriptor.prefable:
|
||||||
|
@ -1544,7 +1551,8 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
getIID = "&NS_GET_IID(%s), " % descriptor.nativeType
|
getIID = "&NS_GET_IID(%s), " % descriptor.nativeType
|
||||||
else:
|
else:
|
||||||
getIID = ""
|
getIID = ""
|
||||||
wrap = "WrapObject(cx, ${obj}, %s, %s${jsvalPtr})" % (result, getIID)
|
#wrap = "WrapObject(cx, ${obj}, %s, %s${jsvalPtr})" % (result, getIID)
|
||||||
|
wrap = "%s.wrap(cx, ${obj}, %s${jsvalPtr})" % (result, getIID)
|
||||||
wrappingCode += wrapAndSetPtr(wrap)
|
wrappingCode += wrapAndSetPtr(wrap)
|
||||||
return (wrappingCode, False)
|
return (wrappingCode, False)
|
||||||
|
|
||||||
|
@ -1587,7 +1595,7 @@ if (!%(resultStr)s) {
|
||||||
# See comments in WrapNewBindingObject explaining why we need
|
# See comments in WrapNewBindingObject explaining why we need
|
||||||
# to wrap here.
|
# to wrap here.
|
||||||
if type.nullable():
|
if type.nullable():
|
||||||
toValue = "JS::ObjectOrNullValue(%s)"
|
toValue = "RUST_OBJECT_TO_JSVAL(%s)"
|
||||||
else:
|
else:
|
||||||
toValue = "JS::ObjectValue(*%s)"
|
toValue = "JS::ObjectValue(*%s)"
|
||||||
# NB: setValue(..., True) calls JS_WrapValue(), so is fallible
|
# NB: setValue(..., True) calls JS_WrapValue(), so is fallible
|
||||||
|
@ -1690,10 +1698,11 @@ def getRetvalDeclarationForType(returnType, descriptorProvider,
|
||||||
raise TypeError("We don't support nullable enum return values")
|
raise TypeError("We don't support nullable enum return values")
|
||||||
return CGGeneric(returnType.inner.identifier.name), False
|
return CGGeneric(returnType.inner.identifier.name), False
|
||||||
if returnType.isGeckoInterface():
|
if returnType.isGeckoInterface():
|
||||||
result = CGGeneric(descriptorProvider.getDescriptor(
|
descriptor = descriptorProvider.getDescriptor(
|
||||||
returnType.unroll().inner.identifier.name).nativeType)
|
returnType.unroll().inner.identifier.name)
|
||||||
|
result = CGGeneric(descriptor.nativeType)
|
||||||
if resultAlreadyAddRefed:
|
if resultAlreadyAddRefed:
|
||||||
result = CGWrapper(result, pre="Option<~", post=">")
|
result = CGWrapper(result, pre=("Option<" + descriptor.pointerType), post=">")
|
||||||
else:
|
else:
|
||||||
result = CGWrapper(result, post="*")
|
result = CGWrapper(result, post="*")
|
||||||
return result, False
|
return result, False
|
||||||
|
@ -2901,7 +2910,7 @@ class CGCallGenerator(CGThing):
|
||||||
if resultOutParam:
|
if resultOutParam:
|
||||||
args.append(CGGeneric("result"))
|
args.append(CGGeneric("result"))
|
||||||
if isFallible:
|
if isFallible:
|
||||||
args.append(CGGeneric("rv"))
|
args.append(CGGeneric("&mut rv"))
|
||||||
|
|
||||||
needsCx = (typeNeedsCx(returnType, True) or
|
needsCx = (typeNeedsCx(returnType, True) or
|
||||||
any(typeNeedsCx(a.type) for (a, _) in arguments) or
|
any(typeNeedsCx(a.type) for (a, _) in arguments) or
|
||||||
|
@ -2930,8 +2939,8 @@ class CGCallGenerator(CGThing):
|
||||||
self.cgRoot.append(call)
|
self.cgRoot.append(call)
|
||||||
|
|
||||||
if isFallible:
|
if isFallible:
|
||||||
self.cgRoot.prepend(CGGeneric("ErrorResult rv;"))
|
self.cgRoot.prepend(CGGeneric("let mut rv: ErrorResult = Ok(());"))
|
||||||
self.cgRoot.append(CGGeneric("if (rv.Failed()) {"))
|
self.cgRoot.append(CGGeneric("if (rv.is_err()) {"))
|
||||||
self.cgRoot.append(CGIndenter(errorReport))
|
self.cgRoot.append(CGIndenter(errorReport))
|
||||||
self.cgRoot.append(CGGeneric("}"))
|
self.cgRoot.append(CGGeneric("}"))
|
||||||
|
|
||||||
|
@ -3031,10 +3040,11 @@ class CGPerSignatureCall(CGThing):
|
||||||
self.idlNode.identifier.name))
|
self.idlNode.identifier.name))
|
||||||
|
|
||||||
def getErrorReport(self):
|
def getErrorReport(self):
|
||||||
return CGGeneric('return ThrowMethodFailedWithDetails<%s>(cx, rv, "%s", "%s");'
|
#return CGGeneric('return ThrowMethodFailedWithDetails<%s>(cx, rv, "%s", "%s");'
|
||||||
% (toStringBool(not self.descriptor.workers),
|
# % (toStringBool(not self.descriptor.workers),
|
||||||
self.descriptor.interface.identifier.name,
|
# self.descriptor.interface.identifier.name,
|
||||||
self.idlNode.identifier.name))
|
# self.idlNode.identifier.name))
|
||||||
|
return CGGeneric('return 0'); #XXXjdm
|
||||||
|
|
||||||
def define(self):
|
def define(self):
|
||||||
return (self.cgRoot.define() + "\n" + self.wrap_return_value())
|
return (self.cgRoot.define() + "\n" + self.wrap_return_value())
|
||||||
|
@ -3844,10 +3854,12 @@ class CGBindingRoot(CGThing):
|
||||||
'js::jsfriendapi::bindgen::*',
|
'js::jsfriendapi::bindgen::*',
|
||||||
'js::glue::bindgen::*',
|
'js::glue::bindgen::*',
|
||||||
'js::glue::*',
|
'js::glue::*',
|
||||||
|
'dom::node::AbstractNode',
|
||||||
'dom::bindings::utils::*',
|
'dom::bindings::utils::*',
|
||||||
'dom::bindings::conversions::*',
|
'dom::bindings::conversions::*',
|
||||||
'dom::bindings::clientrect::*', #XXXjdm
|
'dom::bindings::clientrect::*', #XXXjdm
|
||||||
'dom::bindings::clientrectlist::*', #XXXjdm
|
'dom::bindings::clientrectlist::*', #XXXjdm
|
||||||
|
'dom::bindings::htmlcollection::*', #XXXjdm
|
||||||
'dom::bindings::proxyhandler::*',
|
'dom::bindings::proxyhandler::*',
|
||||||
'content::content_task::task_from_context'
|
'content::content_task::task_from_context'
|
||||||
],
|
],
|
||||||
|
|
|
@ -139,7 +139,7 @@ class Descriptor(DescriptorProvider):
|
||||||
nativeTypeDefault = "mozilla::dom::" + ifaceName
|
nativeTypeDefault = "mozilla::dom::" + ifaceName
|
||||||
|
|
||||||
self.nativeType = desc.get('nativeType', nativeTypeDefault)
|
self.nativeType = desc.get('nativeType', nativeTypeDefault)
|
||||||
self.pointerType = desc.get('pointerType', '@')
|
self.pointerType = desc.get('pointerType', '~')
|
||||||
self.hasInstanceInterface = desc.get('hasInstanceInterface', None)
|
self.hasInstanceInterface = desc.get('hasInstanceInterface', None)
|
||||||
|
|
||||||
# Do something sane for JSObject
|
# Do something sane for JSObject
|
||||||
|
|
20
src/servo/dom/bindings/codegen/HTMLCollection.webidl
Normal file
20
src/servo/dom/bindings/codegen/HTMLCollection.webidl
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* The origin of this IDL file is
|
||||||
|
* http://www.w3.org/TR/2012/WD-dom-20120105/
|
||||||
|
*
|
||||||
|
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||||
|
* liability, trademark and document use rules apply.
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface Element;
|
||||||
|
|
||||||
|
interface HTMLCollection {
|
||||||
|
readonly attribute unsigned long length;
|
||||||
|
getter Element? item(unsigned long index);
|
||||||
|
[Throws]
|
||||||
|
getter object? namedItem(DOMString name); // only returns Element
|
||||||
|
};
|
|
@ -1,5 +1,6 @@
|
||||||
#include "ClientRectBinding.h"
|
#include "ClientRectBinding.h"
|
||||||
#include "ClientRectListBinding.h"
|
#include "ClientRectListBinding.h"
|
||||||
|
#include "HTMLCollectionBinding.h"
|
||||||
#include "nsScriptNameSpaceManager.h"
|
#include "nsScriptNameSpaceManager.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -13,6 +14,7 @@ Register(nsScriptNameSpaceManager* aNameSpaceManager)
|
||||||
|
|
||||||
REGISTER_PROTO(ClientRect, nullptr);
|
REGISTER_PROTO(ClientRect, nullptr);
|
||||||
REGISTER_PROTO(ClientRectList, nullptr);
|
REGISTER_PROTO(ClientRectList, nullptr);
|
||||||
|
REGISTER_PROTO(HTMLCollection, nullptr);
|
||||||
|
|
||||||
#undef REGISTER_PROTO
|
#undef REGISTER_PROTO
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@ use js::rust::{Compartment, jsobj};
|
||||||
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED,
|
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED,
|
||||||
JSVAL_NULL, JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS};
|
JSVAL_NULL, JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS};
|
||||||
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp,
|
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp,
|
||||||
JSPropertySpec, JSPropertyOpWrapper, JSStrictPropertyOpWrapper};
|
JSPropertySpec, JSPropertyOpWrapper, JSStrictPropertyOpWrapper,
|
||||||
|
JSNativeWrapper, JSFunctionSpec};
|
||||||
use js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError,
|
use js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError,
|
||||||
JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN,
|
JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN,
|
||||||
JS_DefineFunctions, JS_DefineProperty, JS_DefineProperties};
|
JS_DefineFunctions, JS_DefineProperty, JS_DefineProperties};
|
||||||
|
@ -12,58 +13,16 @@ use js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_Con
|
||||||
use core::ptr::null;
|
use core::ptr::null;
|
||||||
use core::libc::c_uint;
|
use core::libc::c_uint;
|
||||||
use dom::bindings::utils::{DOMString, domstring_to_jsval, rust_box, squirrel_away, str};
|
use dom::bindings::utils::{DOMString, domstring_to_jsval, rust_box, squirrel_away, str};
|
||||||
|
use dom::bindings::utils::{jsval_to_str, WrapNewBindingObject, CacheableWrapper};
|
||||||
|
use dom::bindings::utils::WrapperCache;
|
||||||
use dom::bindings::node::create;
|
use dom::bindings::node::create;
|
||||||
|
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
|
use dom::bindings::htmlcollection::HTMLCollection;
|
||||||
use dom::bindings::node;
|
use dom::bindings::node;
|
||||||
use dom::bindings::utils;
|
use dom::bindings::utils;
|
||||||
use dom::node::Node;
|
use dom::node::Node;
|
||||||
|
|
||||||
enum DOMException {
|
|
||||||
INVALID_CHARACTER_ERR
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Element(int);
|
|
||||||
|
|
||||||
/*extern fn getElementById(cx: *JSContext, argc: c_uint, vp: *jsval) -> JSBool {
|
|
||||||
//XXX check if actually document object
|
|
||||||
if argc != 1 {
|
|
||||||
//XXX throw proper DOM exception
|
|
||||||
str::as_c_str("Not enough arguments", |s| {
|
|
||||||
JS_ReportError(cx, s);
|
|
||||||
});
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
let id;
|
|
||||||
unsafe {
|
|
||||||
id = JS_ARGV(cx, vp)[0];
|
|
||||||
}
|
|
||||||
alt jsval_to_str(cx, id) {
|
|
||||||
ok(s) {
|
|
||||||
unsafe {
|
|
||||||
let doc: *Document = cast::reinterpret_cast(JS_GetContextPrivate(cx));
|
|
||||||
let elem = (*doc).getElementById(s);
|
|
||||||
}
|
|
||||||
//XXX wrap result
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
err(_) {
|
|
||||||
str::as_c_str("???", |s| {
|
|
||||||
JS_ReportError(cx, s);
|
|
||||||
});
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*extern fn getDocumentURI(cx: *JSContext, _argc: c_uint, vp: *jsval) -> JSBool {
|
|
||||||
unsafe {
|
|
||||||
let uri = (*unwrap(JS_THIS_OBJECT(cx, vp))).payload.getDocumentURI();
|
|
||||||
JS_SET_RVAL(cx, vp, domstring_to_jsval(cx, uri));
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
extern fn getDocumentElement(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
extern fn getDocumentElement(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let obj = JS_THIS_OBJECT(cx, cast::reinterpret_cast(&vp));
|
let obj = JS_THIS_OBJECT(cx, cast::reinterpret_cast(&vp));
|
||||||
|
@ -77,6 +36,34 @@ extern fn getDocumentElement(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> J
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern fn getElementsByTagName(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool {
|
||||||
|
unsafe {
|
||||||
|
let obj = JS_THIS_OBJECT(cx, vp);
|
||||||
|
|
||||||
|
let argv = JS_ARGV(cx, cast::transmute(vp));
|
||||||
|
|
||||||
|
let arg0: DOMString;
|
||||||
|
let strval = jsval_to_str(cx, (*argv.offset(0)));
|
||||||
|
if strval.is_err() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
arg0 = str(strval.get());
|
||||||
|
|
||||||
|
let doc = &mut (*unwrap(obj)).payload;
|
||||||
|
let rval: Option<~HTMLCollection>;
|
||||||
|
rval = doc.getElementsByTagName(arg0);
|
||||||
|
if rval.is_none() {
|
||||||
|
JS_SET_RVAL(cx, vp, JSVAL_NULL);
|
||||||
|
} else {
|
||||||
|
let cache = doc.get_wrappercache();
|
||||||
|
fail_unless!(WrapNewBindingObject(cx, cache.get_wrapper(),
|
||||||
|
rval.get(),
|
||||||
|
cast::transmute(vp)));
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn unwrap(obj: *JSObject) -> *mut rust_box<Document> {
|
unsafe fn unwrap(obj: *JSObject) -> *mut rust_box<Document> {
|
||||||
//TODO: some kind of check if this is a Document object
|
//TODO: some kind of check if this is a Document object
|
||||||
let val = JS_GetReservedSlot(obj, 0);
|
let val = JS_GetReservedSlot(obj, 0);
|
||||||
|
@ -112,11 +99,26 @@ pub fn init(compartment: @mut Compartment, doc: @mut Document) {
|
||||||
fail_unless!(JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs) == 1);
|
fail_unless!(JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs) == 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let methods = @~[JSFunctionSpec {name: compartment.add_name(~"getElementsByTagName"),
|
||||||
|
call: JSNativeWrapper {op: getElementsByTagName, info: null()},
|
||||||
|
nargs: 0,
|
||||||
|
flags: 0,
|
||||||
|
selfHostedName: null()},
|
||||||
|
JSFunctionSpec {name: null(),
|
||||||
|
call: JSNativeWrapper {op: null(), info: null()},
|
||||||
|
nargs: 0,
|
||||||
|
flags: 0,
|
||||||
|
selfHostedName: null()}];
|
||||||
|
vec::as_imm_buf(*methods, |fns, _len| {
|
||||||
|
JS_DefineFunctions(compartment.cx.ptr, obj.ptr, fns);
|
||||||
|
});
|
||||||
|
|
||||||
compartment.register_class(utils::instance_jsclass(~"DocumentInstance", finalize));
|
compartment.register_class(utils::instance_jsclass(~"DocumentInstance", finalize));
|
||||||
|
|
||||||
let instance : jsobj = result::unwrap(
|
let instance : jsobj = result::unwrap(
|
||||||
compartment.new_object_with_proto(~"DocumentInstance", ~"Document",
|
compartment.new_object_with_proto(~"DocumentInstance", ~"Document",
|
||||||
compartment.global_obj.ptr));
|
compartment.global_obj.ptr));
|
||||||
|
doc.wrapper.set_wrapper(instance.ptr);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let raw_ptr: *libc::c_void = cast::reinterpret_cast(&squirrel_away(doc));
|
let raw_ptr: *libc::c_void = cast::reinterpret_cast(&squirrel_away(doc));
|
||||||
|
@ -128,3 +130,17 @@ pub fn init(compartment: @mut Compartment, doc: @mut Document) {
|
||||||
GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
|
GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
|
||||||
JSPROP_ENUMERATE);
|
JSPROP_ENUMERATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CacheableWrapper for Document {
|
||||||
|
fn get_wrappercache(&mut self) -> &mut WrapperCache {
|
||||||
|
unsafe { cast::transmute(&self.wrapper) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wrap_object_unique(~self, cx: *JSContext, scope: *JSObject) -> *JSObject {
|
||||||
|
fail!(~"need to implement wrapping");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wrap_object_shared(@self, cx: *JSContext, scope: *JSObject) -> *JSObject {
|
||||||
|
fail!(~"need to implement wrapping");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ use content::content_task::{Content, task_from_context};
|
||||||
use dom::bindings::utils::{rust_box, squirrel_away_unique, get_compartment};
|
use dom::bindings::utils::{rust_box, squirrel_away_unique, get_compartment};
|
||||||
use dom::bindings::utils::{domstring_to_jsval, WrapNewBindingObject};
|
use dom::bindings::utils::{domstring_to_jsval, WrapNewBindingObject};
|
||||||
use dom::bindings::utils::{str, CacheableWrapper, DOM_OBJECT_SLOT};
|
use dom::bindings::utils::{str, CacheableWrapper, DOM_OBJECT_SLOT};
|
||||||
use dom::bindings::utils;
|
|
||||||
use dom::bindings::clientrectlist::ClientRectListImpl;
|
use dom::bindings::clientrectlist::ClientRectListImpl;
|
||||||
use dom::element::*;
|
use dom::element::*;
|
||||||
use dom::node::{AbstractNode, Node, Element, ElementNodeTypeId};
|
use dom::node::{AbstractNode, Node, Element, ElementNodeTypeId};
|
||||||
|
@ -22,7 +21,7 @@ use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, J
|
||||||
use js::{JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS};
|
use js::{JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS};
|
||||||
|
|
||||||
extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
|
extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
|
||||||
debug!("element finalize!");
|
debug!("element finalize: %?!", obj as uint);
|
||||||
unsafe {
|
unsafe {
|
||||||
let val = JS_GetReservedSlot(obj, DOM_OBJECT_SLOT as u32);
|
let val = JS_GetReservedSlot(obj, DOM_OBJECT_SLOT as u32);
|
||||||
let node: AbstractNode = cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(val));
|
let node: AbstractNode = cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(val));
|
||||||
|
@ -123,8 +122,7 @@ extern fn HTMLImageElement_getWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVa
|
||||||
let width = match node.type_id() {
|
let width = match node.type_id() {
|
||||||
ElementNodeTypeId(HTMLImageElementTypeId) => {
|
ElementNodeTypeId(HTMLImageElementTypeId) => {
|
||||||
let content = task_from_context(cx);
|
let content = task_from_context(cx);
|
||||||
let node = Node::as_abstract_node(~*node);
|
match (*content).query_layout(layout_task::ContentBox(*node)) {
|
||||||
match (*content).query_layout(layout_task::ContentBox(node)) {
|
|
||||||
Ok(rect) => rect.width,
|
Ok(rect) => rect.width,
|
||||||
Err(()) => 0
|
Err(()) => 0
|
||||||
}
|
}
|
||||||
|
|
65
src/servo/dom/bindings/htmlcollection.rs
Normal file
65
src/servo/dom/bindings/htmlcollection.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
use content::content_task::task_from_context;
|
||||||
|
use dom::element::Element;
|
||||||
|
use dom::node::AbstractNode;
|
||||||
|
use dom::bindings::codegen::HTMLCollectionBinding;
|
||||||
|
use dom::bindings::utils::{DOMString, ErrorResult, OpaqueBindingReference};
|
||||||
|
use dom::bindings::utils::{CacheableWrapper, BindingObject, WrapperCache};
|
||||||
|
use js::jsapi::{JSObject, JSContext};
|
||||||
|
|
||||||
|
pub struct HTMLCollection {
|
||||||
|
elements: ~[AbstractNode],
|
||||||
|
wrapper: WrapperCache
|
||||||
|
}
|
||||||
|
|
||||||
|
pub impl HTMLCollection {
|
||||||
|
static fn new(elements: ~[AbstractNode]) -> HTMLCollection {
|
||||||
|
HTMLCollection {
|
||||||
|
elements: elements,
|
||||||
|
wrapper: WrapperCache::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Length(&self) -> u32 {
|
||||||
|
self.elements.len() as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Item(&self, index: u32) -> Option<AbstractNode> {
|
||||||
|
if index < self.Length() {
|
||||||
|
Some(self.elements[index])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn NamedItem(&self, cx: *JSContext, name: DOMString, rv: &mut ErrorResult) -> *JSObject {
|
||||||
|
*rv = Ok(());
|
||||||
|
ptr::null()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<AbstractNode> {
|
||||||
|
*found = true;
|
||||||
|
self.Item(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BindingObject for HTMLCollection {
|
||||||
|
fn GetParentObject(&self, cx: *JSContext) -> OpaqueBindingReference {
|
||||||
|
let content = task_from_context(cx);
|
||||||
|
unsafe { OpaqueBindingReference(Right((*content).window.get() as @CacheableWrapper)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CacheableWrapper for HTMLCollection {
|
||||||
|
fn get_wrappercache(&mut self) -> &mut WrapperCache {
|
||||||
|
unsafe { cast::transmute(&self.wrapper) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wrap_object_unique(~self, cx: *JSContext, scope: *JSObject) -> *JSObject {
|
||||||
|
let mut unused = false;
|
||||||
|
HTMLCollectionBinding::Wrap(cx, scope, self, &mut unused)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wrap_object_shared(@self, cx: *JSContext, scope: *JSObject) -> *JSObject {
|
||||||
|
fail!(~"nyi")
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,9 +13,10 @@ use js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_Repor
|
||||||
JS_GetFunctionPrototype, JS_InternString, JS_GetFunctionObject,
|
JS_GetFunctionPrototype, JS_InternString, JS_GetFunctionObject,
|
||||||
JS_GetInternedStringCharsAndLength, JS_DefineProperties,
|
JS_GetInternedStringCharsAndLength, JS_DefineProperties,
|
||||||
JS_WrapValue, JS_GetObjectPrototype, JS_ForwardGetPropertyTo,
|
JS_WrapValue, JS_GetObjectPrototype, JS_ForwardGetPropertyTo,
|
||||||
JS_HasPropertyById, JS_GetPrototype, JS_GetGlobalForObject};
|
JS_HasPropertyById, JS_GetPrototype, JS_GetGlobalForObject,
|
||||||
|
JS_EncodeString, JS_free};
|
||||||
use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType;
|
use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType;
|
||||||
use js::glue::bindgen::{DefineFunctionWithReserved, GetObjectJSClass};
|
use js::glue::bindgen::{DefineFunctionWithReserved, GetObjectJSClass, RUST_OBJECT_TO_JSVAL};
|
||||||
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB,
|
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB,
|
||||||
RESOLVE_STUB};
|
RESOLVE_STUB};
|
||||||
use js::glue::bindgen::*;
|
use js::glue::bindgen::*;
|
||||||
|
@ -25,6 +26,9 @@ use content::content_task::{Content, task_from_context};
|
||||||
|
|
||||||
use core::hashmap::linear;
|
use core::hashmap::linear;
|
||||||
|
|
||||||
|
use dom::bindings::node;
|
||||||
|
use dom::node::AbstractNode;
|
||||||
|
|
||||||
const TOSTRING_CLASS_RESERVED_SLOT: u64 = 0;
|
const TOSTRING_CLASS_RESERVED_SLOT: u64 = 0;
|
||||||
const TOSTRING_NAME_RESERVED_SLOT: u64 = 1;
|
const TOSTRING_NAME_RESERVED_SLOT: u64 = 1;
|
||||||
|
|
||||||
|
@ -131,15 +135,11 @@ pub fn jsval_to_str(cx: *JSContext, v: JSVal) -> Result<~str, ()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let len = 0;
|
|
||||||
let chars = JS_GetStringCharsZAndLength(cx, jsstr, ptr::to_unsafe_ptr(&len));
|
|
||||||
return if chars.is_null() {
|
|
||||||
Err(())
|
|
||||||
} else {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let buf = vec::raw::from_buf_raw(chars as *u8, len as uint);
|
let strbuf = JS_EncodeString(cx, jsstr);
|
||||||
Ok(str::from_bytes(buf))
|
let buf = str::raw::from_buf(strbuf as *u8);
|
||||||
}
|
JS_free(cx, strbuf as *libc::c_void);
|
||||||
|
Ok(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +330,7 @@ pub struct ConstantSpec {
|
||||||
pub struct DOMClass {
|
pub struct DOMClass {
|
||||||
// A list of interfaces that this object implements, in order of decreasing
|
// A list of interfaces that this object implements, in order of decreasing
|
||||||
// derivedness.
|
// derivedness.
|
||||||
interface_chain: [prototypes::id::Prototype * 2 /*prototypes::id::_ID_Count*/],
|
interface_chain: [prototypes::id::Prototype * 2 /*max prototype chain length*/],
|
||||||
|
|
||||||
unused: bool, // DOMObjectIsISupports (always false)
|
unused: bool, // DOMObjectIsISupports (always false)
|
||||||
native_hooks: *NativePropertyHooks
|
native_hooks: *NativePropertyHooks
|
||||||
|
@ -353,6 +353,7 @@ pub mod prototypes {
|
||||||
pub enum Prototype {
|
pub enum Prototype {
|
||||||
ClientRect,
|
ClientRect,
|
||||||
ClientRectList,
|
ClientRectList,
|
||||||
|
HTMLCollection,
|
||||||
_ID_Count
|
_ID_Count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -540,7 +541,7 @@ pub extern fn ThrowingConstructor(cx: *JSContext, argc: uint, vp: *JSVal) -> JSB
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize_global(global: *JSObject) {
|
pub fn initialize_global(global: *JSObject) {
|
||||||
let protoArray = @mut [0 as *JSObject, ..2]; //XXXjdm number of constructors
|
let protoArray = @mut [0 as *JSObject, ..3]; //XXXjdm prototypes::_ID_COUNT
|
||||||
unsafe {
|
unsafe {
|
||||||
//XXXjdm we should be storing the box pointer instead of the inner
|
//XXXjdm we should be storing the box pointer instead of the inner
|
||||||
let box = squirrel_away(protoArray);
|
let box = squirrel_away(protoArray);
|
||||||
|
@ -778,3 +779,26 @@ pub fn InitIds(cx: *JSContext, specs: &[JSPropertySpec], ids: &mut [jsid]) -> bo
|
||||||
}
|
}
|
||||||
rval
|
rval
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait DerivedWrapper {
|
||||||
|
fn wrap(&mut self, cx: *JSContext, scope: *JSObject, vp: *mut JSVal) -> i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerivedWrapper for AbstractNode {
|
||||||
|
fn wrap(&mut self, cx: *JSContext, scope: *JSObject, vp: *mut JSVal) -> i32 {
|
||||||
|
let cache = self.get_wrappercache();
|
||||||
|
let wrapper = cache.get_wrapper();
|
||||||
|
if wrapper.is_not_null() {
|
||||||
|
unsafe { *vp = RUST_OBJECT_TO_JSVAL(wrapper) };
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
unsafe { *vp = RUST_OBJECT_TO_JSVAL(node::create(cx, self).ptr) };
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Error {
|
||||||
|
FailureUnknown
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type ErrorResult = Result<(), Error>;
|
|
@ -1,3 +1,5 @@
|
||||||
|
use dom::bindings::htmlcollection::HTMLCollection;
|
||||||
|
use dom::bindings::utils::{DOMString, WrapperCache, str};
|
||||||
use dom::node::AbstractNode;
|
use dom::node::AbstractNode;
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
|
|
||||||
|
@ -5,10 +7,32 @@ use std::arc::ARC;
|
||||||
|
|
||||||
pub struct Document {
|
pub struct Document {
|
||||||
root: AbstractNode,
|
root: AbstractNode,
|
||||||
|
wrapper: WrapperCache
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Document(root: AbstractNode) -> Document {
|
pub fn Document(root: AbstractNode) -> Document {
|
||||||
Document {
|
Document {
|
||||||
root: root,
|
root: root,
|
||||||
|
wrapper: WrapperCache::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub impl Document {
|
||||||
|
fn getElementsByTagName(&self, tag: DOMString) -> Option<~HTMLCollection> {
|
||||||
|
let mut elements = ~[];
|
||||||
|
let tag = match tag {
|
||||||
|
str(s) => s,
|
||||||
|
_ => ~""
|
||||||
|
};
|
||||||
|
let _ = for self.root.traverse_preorder |child| {
|
||||||
|
if child.is_element() {
|
||||||
|
do child.with_imm_element |elem| {
|
||||||
|
if elem.tag_name == tag {
|
||||||
|
elements.push(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(~HTMLCollection::new(elements))
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -390,4 +390,7 @@ pub fn define_bindings(compartment: @mut Compartment, doc: @mut Document, win: @
|
||||||
fail_unless!(codegen::ClientRectListBinding::DefineDOMInterface(compartment.cx.ptr,
|
fail_unless!(codegen::ClientRectListBinding::DefineDOMInterface(compartment.cx.ptr,
|
||||||
compartment.global_obj.ptr,
|
compartment.global_obj.ptr,
|
||||||
&mut unused));
|
&mut unused));
|
||||||
|
fail_unless!(codegen::HTMLCollectionBinding::DefineDOMInterface(compartment.cx.ptr,
|
||||||
|
compartment.global_obj.ptr,
|
||||||
|
&mut unused));
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,11 @@ pub mod dom {
|
||||||
pub mod proxyhandler;
|
pub mod proxyhandler;
|
||||||
pub mod clientrect;
|
pub mod clientrect;
|
||||||
pub mod clientrectlist;
|
pub mod clientrectlist;
|
||||||
|
pub mod htmlcollection;
|
||||||
pub mod codegen {
|
pub mod codegen {
|
||||||
pub mod ClientRectBinding;
|
pub mod ClientRectBinding;
|
||||||
pub mod ClientRectListBinding;
|
pub mod ClientRectListBinding;
|
||||||
|
pub mod HTMLCollectionBinding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub mod document;
|
pub mod document;
|
||||||
|
|
|
@ -1 +1,11 @@
|
||||||
<script src="test_bindings.js"></script>
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="test_bindings.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="first"></div>
|
||||||
|
<div id="second"></div>
|
||||||
|
<span id="third"></div>
|
||||||
|
<div id="fourth"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -23,3 +23,12 @@ window.alert(rect.right);
|
||||||
window.alert(rect.width);
|
window.alert(rect.width);
|
||||||
window.alert(rect.height);
|
window.alert(rect.height);
|
||||||
|
|
||||||
|
window.alert("HTMLCollection:");
|
||||||
|
let tags = document.getElementsByTagName("head");
|
||||||
|
//let tag = tags[0];
|
||||||
|
window.alert(tags);
|
||||||
|
window.alert(tags.length);
|
||||||
|
window.alert(tags[0]);
|
||||||
|
window.alert(tags[1]);
|
||||||
|
window.alert(tags[2]);
|
||||||
|
window.alert(tags[3]);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue