diff options
Diffstat (limited to 'src/components/script')
40 files changed, 677 insertions, 377 deletions
diff --git a/src/components/script/dom/attrlist.rs b/src/components/script/dom/attrlist.rs index b172e976705..839043becf1 100644 --- a/src/components/script/dom/attrlist.rs +++ b/src/components/script/dom/attrlist.rs @@ -35,7 +35,7 @@ impl AttrList { } pub fn Item(&self, index: u32) -> Option<JS<Attr>> { - self.owner.get().attrs.get_opt(index as uint).map(|x| x.clone()) + self.owner.get().attrs.get(index as uint).map(|x| x.clone()) } pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<JS<Attr>> { diff --git a/src/components/script/dom/bindings/callback.rs b/src/components/script/dom/bindings/callback.rs index b965fcbfb72..dff5aeb6a2b 100644 --- a/src/components/script/dom/bindings/callback.rs +++ b/src/components/script/dom/bindings/callback.rs @@ -12,17 +12,17 @@ use std::cast; use std::libc; use std::ptr; -use extra::serialize::{Encodable, Encoder}; +use serialize::{Encodable, Encoder}; pub enum ExceptionHandling { // Report any exception and don't throw it to the caller code. - eReportExceptions, + ReportExceptions, // Throw an exception to the caller code if the thrown exception is a // binding object for a DOMError from the caller's scope, otherwise report // it. - eRethrowContentExceptions, + RethrowContentExceptions, // Throw any exception to the caller code. - eRethrowExceptions + RethrowExceptions } #[deriving(Clone,Eq)] diff --git a/src/components/script/dom/bindings/codegen/Bindings.conf b/src/components/script/dom/bindings/codegen/Bindings.conf index 6718071ac7d..eac06e8454d 100644 --- a/src/components/script/dom/bindings/codegen/Bindings.conf +++ b/src/components/script/dom/bindings/codegen/Bindings.conf @@ -52,6 +52,7 @@ DOMInterfaces = { 'Element': { 'needsAbstract': [ 'attributes', + 'className', 'getBoundingClientRect', 'getClientRects', 'getElementsByClassName', @@ -82,11 +83,14 @@ DOMInterfaces = { 'needsAbstract': [ 'appendChild', 'childNodes', + 'cloneNode', + 'compareDocumentPosition', 'contains', 'insertBefore', 'isEqualNode', 'nodeName', 'nodeValue', + 'normalize', 'removeChild', 'replaceChild', 'textContent', @@ -143,7 +147,7 @@ addHTMLElement('HTMLDirectoryElement') addHTMLElement('HTMLDListElement') addHTMLElement('HTMLElement') addHTMLElement('HTMLEmbedElement') -addHTMLElement('HTMLFieldSetElement') +addHTMLElement('HTMLFieldSetElement', needsAbstract=['elements']) addHTMLElement('HTMLFontElement') addHTMLElement('HTMLFormElement') addHTMLElement('HTMLFrameElement') diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index 2162d445c24..d06bfb0bc31 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -184,7 +184,7 @@ class CGMethodCall(CGThing): if requiredArgs > 0: code = ( - "if (argc < %d) {\n" + "if argc < %d {\n" " return 0; //XXXjdm throw exception\n" " //return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, %s);\n" "}" % (requiredArgs, methodName)) @@ -370,7 +370,7 @@ class CGMethodCall(CGThing): overloadCGThings = [] overloadCGThings.append( - CGGeneric("let argcount = argc.min(&%d);" % + CGGeneric("let argcount = cmp::min(argc, %d);" % maxArgCount)) overloadCGThings.append( CGSwitch("argcount", @@ -389,7 +389,7 @@ class CGMethodCall(CGThing): class FakeCastableDescriptor(): def __init__(self, descriptor): self.castable = True - self.nativeType = "*Box<%s>" % descriptor.concreteType + self.nativeType = "*%s" % descriptor.concreteType self.name = descriptor.name class FakeInterface: def inheritanceDepth(self): @@ -720,7 +720,7 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None, return handleDefault(conversionCode, "${declName}.SetNull()") - value = "str::from_utf8(data).to_owned()" + value = "str::from_utf8(data).unwrap().to_owned()" if type.nullable(): value = "Some(%s)" % value @@ -993,7 +993,7 @@ def instantiateJSToNativeConversionTemplate(templateTuple, replacements, conversion = CGList( [CGGeneric( - string.Template("if (${index} < ${argc}) {").substitute( + string.Template("if ${index} < ${argc} {").substitute( argcAndIndex )), declConstruct, @@ -1132,7 +1132,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode, raise TypeError("We don't support nullable enumerated return types " "yet") return ("""assert!((%(result)s as uint) < %(strings)s.len()); -let %(resultStr)s: *JSString = JS_NewStringCopyN(cx, ptr::to_unsafe_ptr(&%(strings)s[%(result)s as u32].value[0]) as *i8, %(strings)s[%(result)s as u32].length as libc::size_t); +let %(resultStr)s: *JSString = JS_NewStringCopyN(cx, &%(strings)s[%(result)s as u32].value[0] as *i8, %(strings)s[%(result)s as u32].length as libc::size_t); if %(resultStr)s.is_null() { return 0; } @@ -1225,36 +1225,36 @@ def memberIsCreator(member): def getRetvalDeclarationForType(returnType, descriptorProvider): if returnType is None or returnType.isVoid(): # Nothing to declare - return None, False + return None if returnType.isPrimitive() and returnType.tag() in builtinNames: result = CGGeneric(builtinNames[returnType.tag()]) if returnType.nullable(): result = CGWrapper(result, pre="Option<", post=">") - return result, False + return result if returnType.isString(): result = CGGeneric("DOMString") if returnType.nullable(): result = CGWrapper(result, pre="Option<", post=">") - return result, False + return result if returnType.isEnum(): if returnType.nullable(): raise TypeError("We don't support nullable enum return values") - return CGGeneric(returnType.inner.identifier.name), False + return CGGeneric(returnType.inner.identifier.name) if returnType.isGeckoInterface(): descriptor = descriptorProvider.getDescriptor( returnType.unroll().inner.identifier.name) result = CGGeneric(descriptor.nativeType) if returnType.nullable(): result = CGWrapper(result, pre="Option<", post=">") - return result, False + return result if returnType.isCallback(): # XXXbz we're going to assume that callback types are always # nullable for now. - return CGGeneric("*JSObject"), False + return CGGeneric("*JSObject") if returnType.isAny(): - return CGGeneric("JSVal"), False + return CGGeneric("JSVal") if returnType.isObject() or returnType.isSpiderMonkeyInterface(): - return CGGeneric("*JSObject"), False + return CGGeneric("*JSObject") if returnType.isSequence(): raise TypeError("We don't support sequence return values") @@ -1641,7 +1641,9 @@ class CGImports(CGWrapper): # sometimes produces two 'break's in a row. See for example # CallbackMember.getArgConversions. 'unreachable_code', + 'non_camel_case_types', 'non_uppercase_statics', + 'unnecessary_parens', 'unused_imports', 'unused_variable', 'unused_unsafe', @@ -1688,11 +1690,11 @@ class CGNamespace(CGWrapper): def DOMClass(descriptor): protoList = ['PrototypeList::id::' + proto for proto in descriptor.prototypeChain] - # Pad out the list to the right length with _ID_Count so we - # guarantee that all the lists are the same length. _ID_Count + # Pad out the list to the right length with IDCount so we + # guarantee that all the lists are the same length. IDCount # is never the ID of any prototype, so it's safe to use as # padding. - protoList.extend(['PrototypeList::id::_ID_Count'] * (descriptor.config.maxProtoChainLength - len(protoList))) + protoList.extend(['PrototypeList::id::IDCount'] * (descriptor.config.maxProtoChainLength - len(protoList))) prototypeChainString = ', '.join(protoList) return """DOMClass { interface_chain: [ %s ], @@ -2066,7 +2068,7 @@ def CreateBindingJSObject(descriptor, parent=None): let handler = js_info.get().get_ref().dom_static.proxy_handlers.get(&(PrototypeList::id::%s as uint)); """ % descriptor.name create += handler + """ let obj = NewProxyObject(aCx, *handler, - ptr::to_unsafe_ptr(&PrivateValue(squirrel_away_unique(aObject) as *libc::c_void)), + &PrivateValue(squirrel_away_unboxed(aObject) as *libc::c_void), proto, %s, ptr::null(), ptr::null()); if obj.is_null() { @@ -2084,7 +2086,7 @@ def CreateBindingJSObject(descriptor, parent=None): } JS_SetReservedSlot(obj, DOM_OBJECT_SLOT as u32, - PrivateValue(squirrel_away_unique(aObject) as *libc::c_void)); + PrivateValue(squirrel_away_unboxed(aObject) as *libc::c_void)); """ return create @@ -2230,7 +2232,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod): val = ('%(' + name + ')s') % self.properties.variableNames(False) if val == "ptr::null()": return val - return "ptr::to_unsafe_ptr(&%s[0])" % val + return "&%s[0]" % val call = """return CreateInterfaceObjects2(aCx, aGlobal, aReceiver, parentProto, %s, %s, %d, @@ -2376,7 +2378,7 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod): trace: %s }; js_info.dom_static.proxy_handlers.insert(PrototypeList::id::%s as uint, - CreateProxyHandler(ptr::to_unsafe_ptr(&traps), ptr::to_unsafe_ptr(&Class) as *libc::c_void)); + CreateProxyHandler(&traps, cast::transmute(&Class))); """ % (FINALIZE_HOOK_NAME, ('Some(%s)' % TRACE_HOOK_NAME), @@ -2388,7 +2390,7 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod): body = "" #XXXjdm xray stuff isn't necessary yet return (body + """ let cx = js_info.js_context.borrow().ptr; - let receiver = js_info.js_compartment.borrow().global_obj.borrow().ptr; + let receiver = js_info.js_compartment.borrow().global_obj; let global: *JSObject = JS_GetGlobalForObject(cx, receiver); return %s(cx, global, receiver).is_not_null();""" % (getter)) @@ -2420,8 +2422,7 @@ class CGCallGenerator(CGThing): isFallible = errorReport is not None - (result, resultOutParam) = getRetvalDeclarationForType(returnType, - descriptorProvider) + result = getRetvalDeclarationForType(returnType, descriptorProvider) args = CGList([CGGeneric(arg) for arg in argsPre], ", ") for (a, name) in arguments: @@ -2437,10 +2438,6 @@ class CGCallGenerator(CGThing): name = "&" + name args.append(CGGeneric(name)) - # Return values that go in outparams go here - if resultOutParam: - args.append(CGGeneric("result")) - needsCx = (typeNeedsCx(returnType, True) or any(typeNeedsCx(a.type) for (a, _) in arguments)) @@ -2467,17 +2464,17 @@ class CGCallGenerator(CGThing): if isFallible: call = CGWrapper(call, pre="result_fallible = ") - elif result is not None and not resultOutParam: + elif result is not None: call = CGWrapper(call, pre="result = ") call = CGWrapper(call) self.cgRoot.append(call) if isFallible: - self.cgRoot.append(CGGeneric("if (result_fallible.is_err()) {")) + self.cgRoot.append(CGGeneric("if result_fallible.is_err() {")) self.cgRoot.append(CGIndenter(errorReport)) self.cgRoot.append(CGGeneric("}")) - if result is not None and not resultOutParam: + if result is not None: self.cgRoot.append(CGGeneric("result = result_fallible.unwrap();")) def define(self): @@ -2698,7 +2695,7 @@ class CGAbstractBindingMethod(CGAbstractExternMethod): " return false as JSBool;\n" "}\n" "\n" - "let this: *Box<%s>;" % self.descriptor.concreteType)) + "let this: *%s;" % self.descriptor.concreteType)) def generate_code(self): assert(False) # Override me @@ -2726,7 +2723,7 @@ class CGSpecializedMethod(CGAbstractExternMethod): self.method = method name = method.identifier.name args = [Argument('*JSContext', 'cx'), Argument('JSHandleObject', 'obj'), - Argument('*mut Box<%s>' % descriptor.concreteType, 'this'), + Argument('*mut %s' % descriptor.concreteType, 'this'), Argument('libc::c_uint', 'argc'), Argument('*mut JSVal', 'vp')] CGAbstractExternMethod.__init__(self, descriptor, name, 'JSBool', args) @@ -2737,13 +2734,13 @@ class CGSpecializedMethod(CGAbstractExternMethod): argsPre = [] if name in self.descriptor.needsAbstract: abstractName = re.sub(r'<\w+>', '', self.descriptor.nativeType) - extraPre = ' let mut abstract_this = %s::from_box(this);\n' % abstractName + extraPre = ' let mut abstract_this = %s::from_raw(this);\n' % abstractName argsPre = ['&mut abstract_this'] return CGWrapper(CGMethodCall(argsPre, nativeName, self.method.isStatic(), self.descriptor, self.method), pre=extraPre + - " let obj = (*obj.unnamed);\n" + - " let this = &mut (*this).data;\n").define() + " let obj = *obj.unnamed;\n" + + " let this = &mut *this;\n").define() class CGGenericGetter(CGAbstractBindingMethod): """ @@ -2781,7 +2778,7 @@ class CGSpecializedGetter(CGAbstractExternMethod): name = 'get_' + attr.identifier.name args = [ Argument('*JSContext', 'cx'), Argument('JSHandleObject', 'obj'), - Argument('*mut Box<%s>' % descriptor.concreteType, 'this'), + Argument('*mut %s' % descriptor.concreteType, 'this'), Argument('*mut JSVal', 'vp') ] CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args) @@ -2790,22 +2787,20 @@ class CGSpecializedGetter(CGAbstractExternMethod): nativeName = MakeNativeName(name) extraPre = '' argsPre = [] - (_, resultOutParam) = getRetvalDeclarationForType(self.attr.type, - self.descriptor) infallible = ('infallible' in self.descriptor.getExtendedAttributes(self.attr, getter=True)) if name in self.descriptor.needsAbstract: abstractName = re.sub(r'<\w+>', '', self.descriptor.nativeType) - extraPre = ' let mut abstract_this = %s::from_box(this);\n' % abstractName + extraPre = ' let mut abstract_this = %s::from_raw(this);\n' % abstractName argsPre = ['&mut abstract_this'] - if resultOutParam or self.attr.type.nullable() or not infallible: + if self.attr.type.nullable() or not infallible: nativeName = "Get" + nativeName return CGWrapper(CGIndenter(CGGetterCall(argsPre, self.attr.type, nativeName, self.descriptor, self.attr)), pre=extraPre + - " let obj = (*obj.unnamed);\n" + - " let this = &mut (*this).data;\n").define() + " let obj = *obj.unnamed;\n" + + " let this = &mut *this;\n").define() class CGGenericSetter(CGAbstractBindingMethod): """ @@ -2849,7 +2844,7 @@ class CGSpecializedSetter(CGAbstractExternMethod): name = 'set_' + attr.identifier.name args = [ Argument('*JSContext', 'cx'), Argument('JSHandleObject', 'obj'), - Argument('*mut Box<%s>' % descriptor.concreteType, 'this'), + Argument('*mut %s' % descriptor.concreteType, 'this'), Argument('*mut JSVal', 'argv')] CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args) @@ -2860,13 +2855,13 @@ class CGSpecializedSetter(CGAbstractExternMethod): extraPre = '' if name in self.descriptor.needsAbstract: abstractName = re.sub(r'<\w+>', '', self.descriptor.nativeType) - extraPre = ' let mut abstract_this = %s::from_box(this);\n' % abstractName + extraPre = ' let mut abstract_this = %s::from_raw(this);\n' % abstractName argsPre = ['&mut abstract_this'] return CGWrapper(CGIndenter(CGSetterCall(argsPre, self.attr.type, nativeName, self.descriptor, self.attr)), pre=extraPre + - " let obj = (*obj.unnamed);\n" + - " let this = &mut (*this).data;\n").define() + " let obj = *obj.unnamed;\n" + + " let this = &mut *this;\n").define() def infallibleForMember(member, type, descriptorProvider): """ @@ -2977,6 +2972,34 @@ class CGEnum(CGThing): """ % (",\n ".join(map(getEnumValueName, self.enum.values())), ",\n ".join(['EnumEntry {value: &"' + val + '", length: ' + str(len(val)) + '}' for val in self.enum.values()])) + +def convertConstIDLValueToRust(value): + tag = value.type.tag() + if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, + IDLType.Tags.int16, IDLType.Tags.uint16, + IDLType.Tags.int32, IDLType.Tags.uint32, + IDLType.Tags.int64, IDLType.Tags.uint64, + IDLType.Tags.float, IDLType.Tags.double]: + return str(value.value) + + if tag == IDLType.Tags.bool: + return toStringBool(value.value) + + raise TypeError("Const value of unhandled type: " + value.type) + +class CGConstant(CGThing): + def __init__(self, constants): + CGThing.__init__(self) + self.constants = constants + + def define(self): + def stringDecl(const): + name = const.identifier.name + value = convertConstIDLValueToRust(const.value) + return CGGeneric("pub static %s: %s = %s;\n" % (name, builtinNames[const.value.type.tag()], value)) + + return CGIndenter(CGList(stringDecl(m) for m in self.constants)).define() + def getUnionAccessorSignatureType(type, descriptorProvider): """ Returns the types that are used in the getter and setter signatures for @@ -3870,8 +3893,8 @@ class CGProxyUnwrap(CGAbstractMethod): obj = js::UnwrapObject(obj); }*/ //MOZ_ASSERT(IsProxy(obj)); - let box_: *Box<%s> = cast::transmute(GetProxyPrivate(obj).to_private()); - return ptr::to_unsafe_ptr(&(*box_).data);""" % (self.descriptor.concreteType) + let box_: *%s = cast::transmute(GetProxyPrivate(obj).to_private()); + return box_;""" % (self.descriptor.concreteType) class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod): def __init__(self, descriptor): @@ -3892,7 +3915,7 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod): if indexedGetter: readonly = toStringBool(self.descriptor.operations['IndexedSetter'] is None) fillDescriptor = "FillPropertyDescriptor(&mut *desc, proxy, %s);\nreturn 1;" % readonly - templateValues = {'jsvalRef': '(*desc).value', 'jsvalPtr': 'ptr::to_mut_unsafe_ptr(&mut (*desc).value)', + templateValues = {'jsvalRef': '(*desc).value', 'jsvalPtr': '&mut (*desc).value', 'obj': 'proxy', 'successCode': fillDescriptor} get = ("if index.is_some() {\n" + " let index = index.unwrap();\n" + @@ -3934,7 +3957,7 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod): if namedGetter: readonly = toStringBool(self.descriptor.operations['NamedSetter'] is None) fillDescriptor = "FillPropertyDescriptor(&mut *desc, proxy, %s);\nreturn 1;" % readonly - templateValues = {'jsvalRef': '(*desc).value', 'jsvalPtr': 'ptr::to_unsafe_ptr(&(*desc).value)', + templateValues = {'jsvalRef': '(*desc).value', 'jsvalPtr': '&mut(*desc).value', 'obj': 'proxy', 'successCode': fillDescriptor} # Once we start supporting OverrideBuiltins we need to make # ResolveOwnProperty or EnumerateOwnProperties filter out named @@ -4080,7 +4103,7 @@ class CGDOMJSProxyHandler_get(CGAbstractExternMethod): getFromExpando = """let expando = GetExpandoObject(proxy); if expando.is_not_null() { let hasProp = 0; - if JS_HasPropertyById(cx, expando, id, ptr::to_unsafe_ptr(&hasProp)) == 0 { + if JS_HasPropertyById(cx, expando, id, &hasProp) == 0 { return 0; } @@ -4180,7 +4203,7 @@ class CGAbstractClassHook(CGAbstractExternMethod): def definition_body_prologue(self): return """ - let this: *%s = &(*unwrap::<*Box<%s>>(obj)).data; + let this: *%s = unwrap::<*%s>(obj); """ % (self.descriptor.concreteType, self.descriptor.concreteType) def definition_body(self): @@ -4316,6 +4339,10 @@ class CGDescriptor(CGThing): cgThings.append(CGGeneric(str(properties))) cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties)) + cgThings.append(CGNamespace.build([descriptor.name + "Constants"], + CGConstant(m for m in descriptor.interface.members if m.isConst()), + public=True)) + # Set up our Xray callbacks as needed. if descriptor.interface.hasInterfacePrototypeObject(): if descriptor.concrete and descriptor.proxy: @@ -4382,7 +4409,7 @@ class CGNamespacedEnum(CGThing): entries.append(entry) # Append a Count. - entries.append('_' + enumName + '_Count = ' + str(len(entries))) + entries.append(enumName + 'Count = ' + str(len(entries))) # Indent. entries = [' ' + e for e in entries] @@ -4512,7 +4539,7 @@ class CGDictionary(CGThing): "\n" " pub fn Init(&mut self, cx: *JSContext, val: JSVal) -> JSBool {\n" " unsafe {\n" - " if (!initedIds && !self.InitIds(cx)) {\n" + " if !initedIds && !self.InitIds(cx) {\n" " return 0;\n" " }\n" "${initParent}" @@ -4579,15 +4606,15 @@ class CGDictionary(CGThing): if True: #XXXjdm hack until 'static mut' exists for global jsids propName = member.identifier.name - propCheck = ('"%s".to_c_str().with_ref(|s| { JS_HasProperty(cx, val.to_object(), s, ptr::to_unsafe_ptr(&found)) })' % + propCheck = ('"%s".to_c_str().with_ref(|s| { JS_HasProperty(cx, val.to_object(), s, &found) })' % propName) - propGet = ('"%s".to_c_str().with_ref(|s| { JS_GetProperty(cx, val.to_object(), s, ptr::to_unsafe_ptr(&temp)) })' % + propGet = ('"%s".to_c_str().with_ref(|s| { JS_GetProperty(cx, val.to_object(), s, &temp) })' % propName) else: propId = self.makeIdName(member.identifier.name); - propCheck = ("JS_HasPropertyById(cx, val.to_object(), %s, ptr::to_unsafe_ptr(&found))" % + propCheck = ("JS_HasPropertyById(cx, val.to_object(), %s, &found)" % propId) - propGet = ("JS_GetPropertyById(cx, val.to_object(), %s, ptr::to_unsafe_ptr(&temp))" % + propGet = ("JS_GetPropertyById(cx, val.to_object(), %s, &temp)" % propId) conversionReplacements = { @@ -4771,7 +4798,7 @@ class CGBindingRoot(CGThing): 'dom::bindings::utils::{NativePropertyHooks}', 'dom::bindings::utils::global_object_for_js_object', 'dom::bindings::utils::{Reflectable}', - 'dom::bindings::utils::{squirrel_away_unique}', + 'dom::bindings::utils::{squirrel_away_unboxed}', 'dom::bindings::utils::{ThrowingConstructor, unwrap, unwrap_jsmanaged}', 'dom::bindings::utils::{unwrap_object, VoidVal, with_gc_disabled}', 'dom::bindings::utils::{with_gc_enabled, XrayResolveProperty}', @@ -4793,12 +4820,13 @@ class CGBindingRoot(CGThing): 'servo_util::str::DOMString', 'servo_util::vec::zip_copies', 'std::cast', + 'std::cmp', 'std::libc', 'std::ptr', 'std::vec', 'std::str', 'std::num', - 'std::unstable::raw::Box', + 'std::intrinsics::uninit', ]) # Add the auto-generated comment. @@ -5198,7 +5226,7 @@ class CGCallback(CGClass): # method, insert our optional argument for deciding whether the # CallSetup should re-throw exceptions on aRv. args.append(Argument("ExceptionHandling", "aExceptionHandling", - "eReportExceptions")) + "ReportExceptions")) args[0] = Argument('&' + args[0].argType, args[0].name, args[0].default) method.args[2] = args[0] @@ -5490,7 +5518,7 @@ class CallbackMember(CGNativeMember): args.append(Argument("JSCompartment*", "aCompartment", "nullptr")) else: args.append(Argument("ExceptionHandling", "aExceptionHandling", - "eReportExceptions")) + "ReportExceptions")) return args # We want to allow the caller to pass in a "this" object, as # well as a JSContext. @@ -5505,7 +5533,7 @@ class CallbackMember(CGNativeMember): if self.rethrowContentException: # getArgs doesn't add the aExceptionHandling argument but does add # aCompartment for us. - callSetup += ", eRethrowContentExceptions, aCompartment" + callSetup += ", RethrowContentExceptions, aCompartment" else: callSetup += ", aExceptionHandling" callSetup += ");" @@ -5742,7 +5770,7 @@ class GlobalGenRoots(): CGGeneric("use dom::types::*;\n"), CGGeneric("use dom::bindings::js::JS;\n"), CGGeneric("use dom::bindings::trace::Traceable;\n"), - CGGeneric("use extra::serialize::{Encodable, Encoder};\n"), + CGGeneric("use serialize::{Encodable, Encoder};\n"), CGGeneric("use js::jsapi::JSTracer;\n\n")] for descriptor in descriptors: name = descriptor.name diff --git a/src/components/script/dom/bindings/error.rs b/src/components/script/dom/bindings/error.rs index 8ea949b28f6..da30f40588b 100644 --- a/src/components/script/dom/bindings/error.rs +++ b/src/components/script/dom/bindings/error.rs @@ -7,7 +7,7 @@ use js::jsapi::{JS_IsExceptionPending}; use js::glue::{ReportError}; -#[deriving(ToStr)] +#[deriving(Show)] pub enum Error { FailureUnknown, NotFound, diff --git a/src/components/script/dom/bindings/js.rs b/src/components/script/dom/bindings/js.rs index 9f8e44ba06f..69758f2980a 100644 --- a/src/components/script/dom/bindings/js.rs +++ b/src/components/script/dom/bindings/js.rs @@ -9,7 +9,6 @@ use layout_interface::TrustedNodeAddress; use std::cast; use std::cell::RefCell; -use std::unstable::raw::Box; pub struct JS<T> { priv ptr: RefCell<*mut T> @@ -50,13 +49,6 @@ impl<T: Reflectable> JS<T> { } - pub unsafe fn from_box(box_: *mut Box<T>) -> JS<T> { - let raw: *mut T = &mut (*box_).data; - JS { - ptr: RefCell::new(raw) - } - } - pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> JS<T> { JS { ptr: RefCell::new(inner as *mut T) diff --git a/src/components/script/dom/bindings/proxyhandler.rs b/src/components/script/dom/bindings/proxyhandler.rs index aaf75a7bc7a..81c36d639ad 100644 --- a/src/components/script/dom/bindings/proxyhandler.rs +++ b/src/components/script/dom/bindings/proxyhandler.rs @@ -19,12 +19,10 @@ use std::ptr; use std::str; use std::mem::size_of; -type c_bool = libc::c_int; - static JSPROXYSLOT_EXPANDO: u32 = 0; pub extern fn getPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid, - set: c_bool, desc: *mut JSPropertyDescriptor) -> c_bool { + set: libc::c_int, desc: *mut JSPropertyDescriptor) -> libc::c_int { unsafe { let handler = GetProxyHandler(proxy); if InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, set, desc) == 0 { diff --git a/src/components/script/dom/bindings/trace.rs b/src/components/script/dom/bindings/trace.rs index 342c3110f5d..1cedf246728 100644 --- a/src/components/script/dom/bindings/trace.rs +++ b/src/components/script/dom/bindings/trace.rs @@ -11,7 +11,7 @@ use std::cast; use std::libc; use std::ptr; use std::ptr::null; -use extra::serialize::{Encodable, Encoder}; +use serialize::{Encodable, Encoder}; // IMPORTANT: We rely on the fact that we never attempt to encode DOM objects using // any encoder but JSTracer. Since we derive trace hooks automatically, diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index 54e518fcc97..e7385fc1ddd 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -8,16 +8,15 @@ use dom::bindings::js::JS; use dom::window; use servo_util::str::DOMString; +use collections::hashmap::HashMap; use std::libc::c_uint; use std::cast; use std::cmp::Eq; -use std::hashmap::HashMap; use std::libc; use std::ptr; use std::ptr::null; use std::str; use std::vec; -use std::unstable::raw::Box; use js::glue::*; use js::glue::{js_IsObjectProxyClass, js_IsFunctionProxyClass, IsProxyHandlerFamily}; use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewFunction}; @@ -121,10 +120,10 @@ pub fn unwrap_object<T>(obj: *JSObject, proto_id: PrototypeList::id::ID, proto_d pub fn unwrap_jsmanaged<T: Reflectable>(obj: *JSObject, proto_id: PrototypeList::id::ID, proto_depth: uint) -> Result<JS<T>, ()> { - let result: Result<*mut Box<T>, ()> = unwrap_object(obj, proto_id, proto_depth); + let result: Result<*mut T, ()> = unwrap_object(obj, proto_id, proto_depth); result.map(|unwrapped| { unsafe { - JS::from_box(unwrapped) + JS::from_raw(unwrapped) } }) } @@ -136,10 +135,6 @@ pub fn unwrap_value<T>(val: *JSVal, proto_id: PrototypeList::id::ID, proto_depth } } -pub unsafe fn squirrel_away_unique<T>(x: ~T) -> *Box<T> { - cast::transmute(x) -} - pub unsafe fn squirrel_away_unboxed<T>(x: ~T) -> *T { cast::transmute(x) } @@ -149,7 +144,7 @@ pub fn jsstring_to_str(cx: *JSContext, s: *JSString) -> DOMString { let length = 0; let chars = JS_GetStringCharsAndLength(cx, s, &length); vec::raw::buf_as_slice(chars, length as uint, |char_vec| { - str::from_utf16(char_vec) + str::from_utf16(char_vec).unwrap() }) } } @@ -412,7 +407,7 @@ pub extern fn ThrowingConstructor(_cx: *JSContext, _argc: c_uint, _vp: *mut JSVa } pub fn initialize_global(global: *JSObject) { - let protoArray = ~([0 as *JSObject, ..PrototypeList::id::_ID_Count as uint]); + let protoArray = ~([0 as *JSObject, ..PrototypeList::id::IDCount as uint]); unsafe { let box_ = squirrel_away_unboxed(protoArray); JS_SetReservedSlot(global, @@ -437,7 +432,6 @@ pub fn reflect_dom_object<T: Reflectable> #[deriving(Eq)] pub struct Reflector { object: *JSObject, - force_box_layout: @int, } impl Reflector { @@ -455,7 +449,6 @@ impl Reflector { pub fn new() -> Reflector { Reflector { object: ptr::null(), - force_box_layout: @1, } } } @@ -470,7 +463,7 @@ pub fn GetPropertyOnPrototype(cx: *JSContext, proxy: *JSObject, id: jsid, found: return true; } let hasProp = 0; - if JS_HasPropertyById(cx, proto, id, ptr::to_unsafe_ptr(&hasProp)) == 0 { + if JS_HasPropertyById(cx, proto, id, &hasProp) == 0 { return false; } *found = hasProp != 0; @@ -651,8 +644,8 @@ pub fn global_object_for_js_object(obj: *JSObject) -> JS<window::Window> { let clasp = JS_GetClass(global); assert!(((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)) != 0); // FIXME(jdm): Either don't hardcode or sanity assert prototype stuff. - match unwrap_object::<*mut Box<window::Window>>(global, PrototypeList::id::Window, 1) { - Ok(win) => JS::from_box(win), + match unwrap_object::<*mut window::Window>(global, PrototypeList::id::Window, 1) { + Ok(win) => JS::from_raw(win), Err(_) => fail!("found DOM global that doesn't unwrap to Window"), } } diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs index 07660e30e88..3cf1d35459a 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -38,12 +38,12 @@ use layout_interface::{DocumentDamageLevel, ContentChangedDocumentDamage}; use servo_util::namespace::{Namespace, Null}; use servo_util::str::DOMString; +use collections::hashmap::HashMap; use extra::url::{Url, from_str}; use js::jsapi::{JSObject, JSContext}; use std::ascii::StrAsciiExt; -use std::hashmap::HashMap; -use extra::serialize::{Encoder, Encodable}; +use serialize::{Encoder, Encodable}; #[deriving(Eq,Encodable)] pub enum IsHTMLDocument { @@ -61,7 +61,7 @@ pub struct Document { content_type: DOMString, encoding_name: DOMString, is_html_document: bool, - extra: Untraceable, + priv extra: Untraceable, } struct Untraceable { @@ -139,6 +139,12 @@ impl Document { } impl Document { + pub fn url<'a>(&'a self) -> &'a Url { + &self.extra.url + } +} + +impl Document { // http://dom.spec.whatwg.org/#dom-document pub fn Constructor(owner: &JS<Window>) -> Fallible<JS<Document>> { Ok(Document::new(owner, None, NonHTMLDocument, None)) @@ -166,7 +172,7 @@ impl Document { // http://dom.spec.whatwg.org/#dom-document-url pub fn URL(&self) -> DOMString { - self.extra.url.to_str() + self.url().to_str() } // http://dom.spec.whatwg.org/#dom-document-documenturi @@ -182,6 +188,10 @@ impl Document { } } + pub fn quirks_mode(&self) -> QuirksMode { + self.extra.quirks_mode + } + pub fn set_quirks_mode(&mut self, mode: QuirksMode) { self.extra.quirks_mode = mode; } @@ -331,17 +341,17 @@ impl Document { match title_node { Some(ref mut title_node) => { for mut title_child in title_node.children() { - title_node.RemoveChild(&mut title_child); + assert!(title_node.RemoveChild(&mut title_child).is_ok()); } let new_text = self.CreateTextNode(abstract_self, title.clone()); - title_node.AppendChild(&mut NodeCast::from(&new_text)); + assert!(title_node.AppendChild(&mut NodeCast::from(&new_text)).is_ok()); }, None => { let mut new_title: JS<Node> = NodeCast::from(&HTMLTitleElement::new(~"title", abstract_self)); let new_text = self.CreateTextNode(abstract_self, title.clone()); - new_title.AppendChild(&mut NodeCast::from(&new_text)); - head.AppendChild(&mut new_title); + assert!(new_title.AppendChild(&mut NodeCast::from(&new_text)).is_ok()); + assert!(head.AppendChild(&mut new_title).is_ok()); }, } }); @@ -408,9 +418,9 @@ impl Document { match old_body { Some(child) => { let mut child: JS<Node> = NodeCast::from(&child); - root.ReplaceChild(&mut new_body, &mut child) + assert!(root.ReplaceChild(&mut new_body, &mut child).is_ok()) } - None => root.AppendChild(&mut new_body) + None => assert!(root.AppendChild(&mut new_body).is_ok()) }; } } @@ -425,7 +435,7 @@ impl Document { } let element: JS<Element> = ElementCast::to(node); - element.get().get_attribute(Null, "name").map_default(false, |attr| { + element.get().get_attribute(Null, "name").map_or(false, |attr| { attr.get().value_ref() == name }) }) diff --git a/src/components/script/dom/domexception.rs b/src/components/script/dom/domexception.rs index 9d8142ac938..fe439a944e2 100644 --- a/src/components/script/dom/domexception.rs +++ b/src/components/script/dom/domexception.rs @@ -3,34 +3,35 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::DOMExceptionBinding; +use dom::bindings::codegen::DOMExceptionBinding::DOMExceptionConstants; use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; use servo_util::str::DOMString; #[repr(uint)] -#[deriving(ToStr, Encodable)] +#[deriving(Show, Encodable)] enum DOMErrorName { - IndexSizeError = 1, - HierarchyRequestError = 3, - WrongDocumentError = 4, - InvalidCharacterError = 5, - NoModificationAllowedError = 7, - NotFoundError = 8, - NotSupportedError = 9, - InvalidStateError = 11, - SyntaxError = 12, - InvalidModificationError = 13, - NamespaceError = 14, - InvalidAccessError = 15, - SecurityError = 18, - NetworkError = 19, - AbortError = 20, - URLMismatchError = 21, - QuotaExceededError = 22, - TimeoutError = 23, - InvalidNodeTypeError = 24, - DataCloneError = 25, + IndexSizeError = DOMExceptionConstants::INDEX_SIZE_ERR, + HierarchyRequestError = DOMExceptionConstants::HIERARCHY_REQUEST_ERR, + WrongDocumentError = DOMExceptionConstants::WRONG_DOCUMENT_ERR, + InvalidCharacterError = DOMExceptionConstants::INVALID_CHARACTER_ERR, + NoModificationAllowedError = DOMExceptionConstants::NO_MODIFICATION_ALLOWED_ERR, + NotFoundError = DOMExceptionConstants::NOT_FOUND_ERR, + NotSupportedError = DOMExceptionConstants::NOT_SUPPORTED_ERR, + InvalidStateError = DOMExceptionConstants::INVALID_STATE_ERR, + SyntaxError = DOMExceptionConstants::SYNTAX_ERR, + InvalidModificationError = DOMExceptionConstants::INVALID_MODIFICATION_ERR, + NamespaceError = DOMExceptionConstants::NAMESPACE_ERR, + InvalidAccessError = DOMExceptionConstants::INVALID_ACCESS_ERR, + SecurityError = DOMExceptionConstants::SECURITY_ERR, + NetworkError = DOMExceptionConstants::NETWORK_ERR, + AbortError = DOMExceptionConstants::ABORT_ERR, + URLMismatchError = DOMExceptionConstants::URL_MISMATCH_ERR, + QuotaExceededError = DOMExceptionConstants::QUOTA_EXCEEDED_ERR, + TimeoutError = DOMExceptionConstants::TIMEOUT_ERR, + InvalidNodeTypeError = DOMExceptionConstants::INVALID_NODE_TYPE_ERR, + DataCloneError = DOMExceptionConstants::DATA_CLONE_ERR, EncodingError } diff --git a/src/components/script/dom/domimplementation.rs b/src/components/script/dom/domimplementation.rs index 5a11d0119d4..71f63f52066 100644 --- a/src/components/script/dom/domimplementation.rs +++ b/src/components/script/dom/domimplementation.rs @@ -72,18 +72,18 @@ impl DOMImplementation { { // Step 3. let doc_type = DocumentType::new(~"html", None, None, &doc); - doc_node.AppendChild(&mut NodeCast::from(&doc_type)); + assert!(doc_node.AppendChild(&mut NodeCast::from(&doc_type)).is_ok()); } { // Step 4. let mut doc_html = NodeCast::from(&HTMLHtmlElement::new(~"html", &doc)); - doc_node.AppendChild(&mut doc_html); + assert!(doc_node.AppendChild(&mut doc_html).is_ok()); { // Step 5. let mut doc_head = NodeCast::from(&HTMLHeadElement::new(~"head", &doc)); - doc_html.AppendChild(&mut doc_head); + assert!(doc_html.AppendChild(&mut doc_head).is_ok()); // Step 6. match title { @@ -91,18 +91,18 @@ impl DOMImplementation { Some(title_str) => { // Step 6.1. let mut doc_title = NodeCast::from(&HTMLTitleElement::new(~"title", &doc)); - doc_head.AppendChild(&mut doc_title); + assert!(doc_head.AppendChild(&mut doc_title).is_ok()); // Step 6.2. let title_text = Text::new(title_str, &doc); - doc_title.AppendChild(&mut NodeCast::from(&title_text)); + assert!(doc_title.AppendChild(&mut NodeCast::from(&title_text)).is_ok()); } } } // Step 7. let doc_body = HTMLBodyElement::new(~"body", &doc); - doc_html.AppendChild(&mut NodeCast::from(&doc_body)); + assert!(doc_html.AppendChild(&mut NodeCast::from(&doc_body)).is_ok()); } // Step 8. diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 95e4e7f9af9..96f5bf8f7f4 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -156,6 +156,17 @@ impl Element { self.node.owner_doc().get().is_html_document } + pub unsafe fn html_element_in_html_document_for_layout(&self) -> bool { + if self.namespace != namespace::HTML { + return false + } + let owner_doc: *JS<Document> = self.node.owner_doc(); + let owner_doc: **Document = cast::transmute::<*JS<Document>, + **Document>( + owner_doc); + (**owner_doc).is_html_document + } + pub fn get_attribute(&self, namespace: Namespace, name: &str) -> Option<JS<Attr>> { @@ -192,9 +203,9 @@ impl Element { let (prefix, local_name) = get_attribute_parts(name.clone()); match prefix { Some(ref prefix_str) => { - if (namespace == namespace::Null || - ("xml" == prefix_str.as_slice() && namespace != namespace::XML) || - ("xmlns" == prefix_str.as_slice() && namespace != namespace::XMLNS)) { + if namespace == namespace::Null || + ("xml" == prefix_str.as_slice() && namespace != namespace::XML) || + ("xmlns" == prefix_str.as_slice() && namespace != namespace::XMLNS) { return Err(NamespaceError); } }, @@ -241,7 +252,7 @@ impl Element { match local_name.as_slice() { "style" => { let doc = self.node.owner_doc(); - let base_url = doc.get().extra.url.clone(); + let base_url = doc.get().url().clone(); self.style_attribute = Some(style::parse_style_attribute(value, &base_url)) } "id" => { @@ -249,7 +260,7 @@ impl Element { if self_node.is_in_doc() { // XXX: this dual declaration are workaround to avoid the compile error: // "borrowed value does not live long enough" - let mut doc = self.node.owner_doc(); + let mut doc = self.node.owner_doc().clone(); let doc = doc.get_mut(); doc.register_named_element(abstract_self, value.clone()); } @@ -318,7 +329,7 @@ impl Element { if self_node.is_in_doc() { // XXX: this dual declaration are workaround to avoid the compile error: // "borrowed value does not live long enough" - let mut doc = self.node.owner_doc(); + let mut doc = self.node.owner_doc().clone(); let doc = doc.get_mut(); doc.unregister_named_element(old_value); } @@ -399,7 +410,7 @@ impl Element { pub fn set_string_attribute(&mut self, abstract_self: &JS<Element>, name: &str, value: DOMString) { assert!(name == name.to_ascii_lower()); - self.set_attribute(abstract_self, Null, name.to_owned(), value); + assert!(self.set_attribute(abstract_self, Null, name.to_owned(), value).is_ok()); } } @@ -419,6 +430,16 @@ impl Element { self.set_string_attribute(abstract_self, "id", id); } + // http://dom.spec.whatwg.org/#dom-element-classname + pub fn ClassName(&self, _abstract_self: &JS<Element>) -> DOMString { + self.get_string_attribute("class") + } + + // http://dom.spec.whatwg.org/#dom-element-classname + pub fn SetClassName(&mut self, abstract_self: &JS<Element>, class: DOMString) { + self.set_string_attribute(abstract_self, "class", class); + } + // http://dom.spec.whatwg.org/#dom-element-attributes pub fn Attributes(&mut self, abstract_self: &JS<Element>) -> JS<AttrList> { match self.attr_list { diff --git a/src/components/script/dom/event.rs b/src/components/script/dom/event.rs index 6b612b4a220..c54688626d3 100644 --- a/src/components/script/dom/event.rs +++ b/src/components/script/dom/event.rs @@ -3,9 +3,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::EventBinding; +use dom::bindings::codegen::EventBinding::EventConstants; use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; -use dom::bindings::error::{Fallible, ErrorResult}; +use dom::bindings::error::Fallible; use dom::eventtarget::EventTarget; use dom::window::Window; use servo_util::str::DOMString; @@ -23,10 +24,10 @@ pub enum Event_ { #[deriving(Encodable)] pub enum EventPhase { - Phase_None = 0, - Phase_Capturing, - Phase_At_Target, - Phase_Bubbling + PhaseNone = EventConstants::NONE, + PhaseCapturing = EventConstants::CAPTURING_PHASE, + PhaseAtTarget = EventConstants::AT_TARGET, + PhaseBubbling = EventConstants::BUBBLING_PHASE, } #[deriving(Eq, Encodable)] @@ -62,7 +63,7 @@ impl Event { reflector_: Reflector::new(), current_target: None, target: None, - phase: Phase_None, + phase: PhaseNone, type_: ~"", default_prevented: false, cancelable: true, @@ -131,12 +132,11 @@ impl Event { pub fn InitEvent(&mut self, type_: DOMString, bubbles: bool, - cancelable: bool) -> ErrorResult { + cancelable: bool) { self.type_ = type_; self.cancelable = cancelable; self.bubbles = bubbles; self.initialized = true; - Ok(()) } pub fn IsTrusted(&self) -> bool { diff --git a/src/components/script/dom/eventdispatcher.rs b/src/components/script/dom/eventdispatcher.rs index 699dc1f68b5..bd55cb69909 100644 --- a/src/components/script/dom/eventdispatcher.rs +++ b/src/components/script/dom/eventdispatcher.rs @@ -2,11 +2,11 @@ * 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/. */ -use dom::bindings::callback::eReportExceptions; +use dom::bindings::callback::ReportExceptions; use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast, NodeDerived}; use dom::bindings::js::JS; use dom::eventtarget::{Capturing, Bubbling, EventTarget}; -use dom::event::{Event, Phase_At_Target, Phase_None, Phase_Bubbling, Phase_Capturing}; +use dom::event::{Event, PhaseAtTarget, PhaseNone, PhaseBubbling, PhaseCapturing}; use dom::node::{Node, NodeHelpers}; // See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm @@ -35,7 +35,7 @@ pub fn dispatch_event(target: &JS<EventTarget>, } } - event.get_mut().phase = Phase_Capturing; + event.get_mut().phase = PhaseCapturing; //FIXME: The "callback this value" should be currentTarget @@ -45,7 +45,9 @@ pub fn dispatch_event(target: &JS<EventTarget>, Some(listeners) => { event.get_mut().current_target = Some(cur_target.clone()); for listener in listeners.iter() { - listener.HandleEvent__(event, eReportExceptions); + //FIXME: this should have proper error handling, or explicitly + // drop the exception on the floor + assert!(listener.HandleEvent__(event, ReportExceptions).is_ok()); if event.get().stop_immediate { break; @@ -66,14 +68,16 @@ pub fn dispatch_event(target: &JS<EventTarget>, if !event.get().stop_propagation { { let event = event.get_mut(); - event.phase = Phase_At_Target; + event.phase = PhaseAtTarget; event.current_target = Some(target.clone()); } let opt_listeners = target.get().get_listeners(type_); for listeners in opt_listeners.iter() { for listener in listeners.iter() { - listener.HandleEvent__(event, eReportExceptions); + //FIXME: this should have proper error handling, or explicitly drop the + // exception on the floor. + assert!(listener.HandleEvent__(event, ReportExceptions).is_ok()); if event.get().stop_immediate { break; } @@ -83,14 +87,16 @@ pub fn dispatch_event(target: &JS<EventTarget>, /* bubbling */ if event.get().bubbles && !event.get().stop_propagation { - event.get_mut().phase = Phase_Bubbling; + event.get_mut().phase = PhaseBubbling; for cur_target in chain.iter() { let stopped = match cur_target.get().get_listeners_for(type_, Bubbling) { Some(listeners) => { event.get_mut().current_target = Some(cur_target.clone()); for listener in listeners.iter() { - listener.HandleEvent__(event, eReportExceptions); + //FIXME: this should have proper error handling or explicitly + // drop exceptions on the floor. + assert!(listener.HandleEvent__(event, ReportExceptions).is_ok()); if event.get().stop_immediate { break; @@ -109,7 +115,7 @@ pub fn dispatch_event(target: &JS<EventTarget>, let event = event.get_mut(); event.dispatching = false; - event.phase = Phase_None; + event.phase = PhaseNone; event.current_target = None; !event.DefaultPrevented() diff --git a/src/components/script/dom/eventtarget.rs b/src/components/script/dom/eventtarget.rs index 5b4d2d52412..a1a3a9d7514 100644 --- a/src/components/script/dom/eventtarget.rs +++ b/src/components/script/dom/eventtarget.rs @@ -11,7 +11,7 @@ use dom::eventdispatcher::dispatch_event; use dom::node::NodeTypeId; use servo_util::str::DOMString; -use std::hashmap::HashMap; +use collections::hashmap::HashMap; #[deriving(Eq,Encodable)] pub enum ListenerPhase { diff --git a/src/components/script/dom/formdata.rs b/src/components/script/dom/formdata.rs index bd4c7a03d6e..ac6cdac403e 100644 --- a/src/components/script/dom/formdata.rs +++ b/src/components/script/dom/formdata.rs @@ -11,7 +11,7 @@ use dom::htmlformelement::HTMLFormElement; use dom::window::Window; use servo_util::str::DOMString; -use std::hashmap::HashMap; +use collections::hashmap::HashMap; #[deriving(Encodable)] enum FormDatum { diff --git a/src/components/script/dom/htmlelement.rs b/src/components/script/dom/htmlelement.rs index 8464d23aec0..f8a1cd96a9b 100644 --- a/src/components/script/dom/htmlelement.rs +++ b/src/components/script/dom/htmlelement.rs @@ -140,13 +140,6 @@ impl HTMLElement { Ok(()) } - pub fn ClassName(&self) -> DOMString { - ~"" - } - - pub fn SetClassName(&self, _class: DOMString) { - } - pub fn GetOffsetParent(&self) -> Option<JS<Element>> { None } diff --git a/src/components/script/dom/htmlfieldsetelement.rs b/src/components/script/dom/htmlfieldsetelement.rs index 4dec639d041..5bbd13c2b79 100644 --- a/src/components/script/dom/htmlfieldsetelement.rs +++ b/src/components/script/dom/htmlfieldsetelement.rs @@ -3,16 +3,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLFieldSetElementBinding; -use dom::bindings::codegen::InheritTypes::HTMLFieldSetElementDerived; +use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLFieldSetElementDerived, NodeCast}; use dom::bindings::js::JS; use dom::bindings::error::ErrorResult; use dom::document::Document; -use dom::element::HTMLFieldSetElementTypeId; +use dom::element::{Element, HTMLFieldSetElementTypeId}; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlformelement::HTMLFormElement; use dom::htmlcollection::HTMLCollection; use dom::htmlelement::HTMLElement; -use dom::node::{Node, ElementNodeTypeId}; +use dom::node::{Node, ElementNodeTypeId, window_from_node}; use dom::validitystate::ValidityState; use servo_util::str::DOMString; @@ -68,11 +68,12 @@ impl HTMLFieldSetElement { ~"" } - pub fn Elements(&self) -> JS<HTMLCollection> { - // FIXME: https://github.com/mozilla/servo/issues/1843 - let doc = self.htmlelement.element.node.owner_doc(); - let doc = doc.get(); - HTMLCollection::new(&doc.window, ~[]) + pub fn Elements(&self, abstract_self: &JS<HTMLFieldSetElement>) -> JS<HTMLCollection> { + let node: JS<Node> = NodeCast::from(abstract_self); + let element: JS<Element> = ElementCast::from(abstract_self); + let window = &window_from_node(&node); + let listed_elements = ["button", "fieldset", "input", "keygen", "object", "output", "select", "textarea"]; + HTMLCollection::create(window, &node, |elem| *elem != element && listed_elements.iter().any(|&tag_name| tag_name == elem.get().tag_name)) } pub fn WillValidate(&self) -> bool { diff --git a/src/components/script/dom/htmliframeelement.rs b/src/components/script/dom/htmliframeelement.rs index 160ecc6c175..5098972ec15 100644 --- a/src/components/script/dom/htmliframeelement.rs +++ b/src/components/script/dom/htmliframeelement.rs @@ -15,9 +15,9 @@ use dom::windowproxy::WindowProxy; use servo_util::str::DOMString; use extra::url::Url; +use serialize::{Encoder, Encodable}; use servo_msg::constellation_msg::{PipelineId, SubpageId}; use std::ascii::StrAsciiExt; -use extra::serialize::{Encoder, Encodable}; enum SandboxAllowance { AllowNothing = 0x00, @@ -32,7 +32,7 @@ enum SandboxAllowance { #[deriving(Encodable)] pub struct HTMLIFrameElement { htmlelement: HTMLElement, - extra: Untraceable, + priv extra: Untraceable, size: Option<IFrameSize>, sandbox: Option<u8> } @@ -65,6 +65,10 @@ impl HTMLIFrameElement { pub fn is_sandboxed(&self) -> bool { self.sandbox.is_some() } + + pub fn set_frame(&mut self, frame: Url) { + self.extra.frame = Some(frame); + } } impl HTMLIFrameElement { diff --git a/src/components/script/dom/htmlimageelement.rs b/src/components/script/dom/htmlimageelement.rs index 5f2566ed089..861b8ca5633 100644 --- a/src/components/script/dom/htmlimageelement.rs +++ b/src/components/script/dom/htmlimageelement.rs @@ -19,12 +19,12 @@ use servo_net::image_cache_task; use servo_util::url::parse_url; use servo_util::str::DOMString; -use extra::serialize::{Encoder, Encodable}; +use serialize::{Encoder, Encodable}; #[deriving(Encodable)] pub struct HTMLImageElement { htmlelement: HTMLElement, - extra: Untraceable, + priv extra: Untraceable, } struct Untraceable { @@ -62,6 +62,10 @@ impl HTMLImageElement { } impl HTMLImageElement { + pub fn image<'a>(&'a self) -> &'a Option<Url> { + &self.extra.image + } + /// Makes the local `image` member match the status of the `src` attribute and starts /// prefetching the image. This method must be called after `src` is changed. fn update_image(&mut self, value: Option<DOMString>, url: Option<Url>) { @@ -89,7 +93,7 @@ impl HTMLImageElement { pub fn AfterSetAttr(&mut self, name: DOMString, value: DOMString) { if "src" == name { - let document = self.htmlelement.element.node.owner_doc(); + let document = self.htmlelement.element.node.owner_doc().clone(); let window = document.get().window.get(); let url = Some(window.get_url()); self.update_image(Some(value), url); @@ -116,8 +120,7 @@ impl HTMLImageElement { pub fn SetSrc(&mut self, abstract_self: &JS<HTMLImageElement>, src: DOMString) -> ErrorResult { let node = &mut self.htmlelement.element; - node.set_attr(&ElementCast::from(abstract_self), ~"src", src.clone()); - Ok(()) + node.set_attr(&ElementCast::from(abstract_self), ~"src", src.clone()) } pub fn CrossOrigin(&self) -> DOMString { @@ -160,8 +163,7 @@ impl HTMLImageElement { pub fn SetWidth(&mut self, abstract_self: &JS<HTMLImageElement>, width: u32) -> ErrorResult { let mut elem: JS<Element> = ElementCast::from(abstract_self); let mut elem_clone = elem.clone(); - elem.get_mut().set_attr(&mut elem_clone, ~"width", width.to_str()); - Ok(()) + elem.get_mut().set_attr(&mut elem_clone, ~"width", width.to_str()) } pub fn Height(&self, abstract_self: &JS<HTMLImageElement>) -> u32 { @@ -180,8 +182,7 @@ impl HTMLImageElement { pub fn SetHeight(&mut self, abstract_self: &JS<HTMLImageElement>, height: u32) -> ErrorResult { let node = &mut self.htmlelement.element; - node.set_attr(&ElementCast::from(abstract_self), ~"height", height.to_str()); - Ok(()) + node.set_attr(&ElementCast::from(abstract_self), ~"height", height.to_str()) } pub fn NaturalWidth(&self) -> u32 { diff --git a/src/components/script/dom/htmlobjectelement.rs b/src/components/script/dom/htmlobjectelement.rs index fba1a979e43..4c6e21012cf 100644 --- a/src/components/script/dom/htmlobjectelement.rs +++ b/src/components/script/dom/htmlobjectelement.rs @@ -73,7 +73,7 @@ impl HTMLObjectElement { pub fn AfterSetAttr(&mut self, name: DOMString, _value: DOMString) { if "data" == name { - let document = self.htmlelement.element.node.owner_doc(); + let document = self.htmlelement.element.node.owner_doc().clone(); let window = document.get().window.clone(); let url = Some(window.get().get_url()); self.process_data_url(window.get().image_cache_task.clone(), url); diff --git a/src/components/script/dom/htmlserializer.rs b/src/components/script/dom/htmlserializer.rs index e6822e79215..82c215c7d2f 100644 --- a/src/components/script/dom/htmlserializer.rs +++ b/src/components/script/dom/htmlserializer.rs @@ -25,7 +25,7 @@ pub fn serialize(iterator: &mut NodeIterator) -> ~str { for node in *iterator { while open_elements.len() > iterator.depth { - html.push_str(~"</" + open_elements.pop() + ">"); + html.push_str(~"</" + open_elements.pop().unwrap().as_slice() + ">"); } html.push_str( match node.type_id() { @@ -59,7 +59,7 @@ pub fn serialize(iterator: &mut NodeIterator) -> ~str { ); } while open_elements.len() > 0 { - html.push_str(~"</" + open_elements.pop() + ">"); + html.push_str(~"</" + open_elements.pop().unwrap().as_slice() + ">"); } html } diff --git a/src/components/script/dom/location.rs b/src/components/script/dom/location.rs index 2fc06fb353b..8e7e1ca5ced 100644 --- a/src/components/script/dom/location.rs +++ b/src/components/script/dom/location.rs @@ -12,13 +12,13 @@ use servo_util::str::DOMString; use script_task::{Page}; use std::rc::Rc; -use extra::serialize::{Encoder, Encodable}; +use serialize::{Encoder, Encodable}; #[deriving(Encodable)] pub struct Location { reflector_: Reflector, //XXXjdm cycle: window->Location->window - extra: Untraceable, + priv extra: Untraceable, } struct Untraceable { diff --git a/src/components/script/dom/mouseevent.rs b/src/components/script/dom/mouseevent.rs index 8741ea48a68..a261de252d7 100644 --- a/src/components/script/dom/mouseevent.rs +++ b/src/components/script/dom/mouseevent.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::MouseEventBinding; use dom::bindings::codegen::InheritTypes::MouseEventDerived; use dom::bindings::js::JS; -use dom::bindings::error::{ErrorResult, Fallible}; +use dom::bindings::error::Fallible; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::event::{Event, MouseEventTypeId}; use dom::eventtarget::EventTarget; @@ -135,7 +135,7 @@ impl MouseEvent { shiftKeyArg: bool, metaKeyArg: bool, buttonArg: u16, - relatedTargetArg: Option<JS<EventTarget>>) -> ErrorResult { + relatedTargetArg: Option<JS<EventTarget>>) { self.mouseevent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg); self.screen_x = screenXArg; self.screen_y = screenYArg; @@ -147,7 +147,6 @@ impl MouseEvent { self.meta_key = metaKeyArg; self.button = buttonArg; self.related_target = relatedTargetArg; - Ok(()) } } diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 9999503a758..71b2b121136 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -4,15 +4,20 @@ //! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements. -use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, ElementCast, TextCast, NodeCast}; +use dom::attr::Attr; +use dom::bindings::codegen::InheritTypes::{CommentCast, DocumentCast, DocumentTypeCast}; +use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDerived}; use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast; +use dom::bindings::codegen::NodeBinding::NodeConstants; use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::error::{ErrorResult, Fallible, NotFound, HierarchyRequest}; use dom::bindings::utils; use dom::characterdata::CharacterData; -use dom::document::Document; +use dom::comment::Comment; +use dom::document::{Document, HTMLDocument, NonHTMLDocument}; +use dom::documentfragment::DocumentFragment; use dom::documenttype::DocumentType; use dom::element::{Element, ElementTypeId, HTMLAnchorElementTypeId, IElement}; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -20,6 +25,7 @@ use dom::nodelist::{NodeList}; use dom::text::Text; use dom::processinginstruction::ProcessingInstruction; use dom::window::Window; +use html::hubbub_html_parser::build_element_from_tag; use layout_interface::{LayoutChan, ReapLayoutDataMsg, UntrustedNodeAddress}; use layout_interface::TrustedNodeAddress; use servo_util::str::{DOMString, null_str_as_empty}; @@ -31,10 +37,9 @@ use std::cast; use std::cell::{RefCell, Ref, RefMut}; use std::iter::{Map, Filter}; use std::libc::uintptr_t; -use std::unstable::raw::Box; -use std::util; +use std::mem; -use extra::serialize::{Encoder, Encodable}; +use serialize::{Encoder, Encodable}; // // The basic Node structure @@ -399,10 +404,12 @@ impl NodeHelpers for JS<Node> { assert!(self.parent_node().is_some()); let document = document_from_node(self); - for node in self.traverse_preorder() { - if node.is_element() { - let element: JS<Element> = ElementCast::to(&node); - element.bind_to_tree_impl(); + if self.is_in_doc() { + for node in self.traverse_preorder() { + if node.is_element() { + let element: JS<Element> = ElementCast::to(&node); + element.bind_to_tree_impl(); + } } } @@ -555,8 +562,8 @@ impl NodeHelpers for JS<Node> { if object.is_null() { fail!("Attempted to create a `JS<Node>` from an invalid pointer!") } - let boxed_node: *mut Box<Node> = utils::unwrap(object); - JS::from_box(boxed_node) + let boxed_node: *mut Node = utils::unwrap(object); + JS::from_raw(boxed_node) } } @@ -721,6 +728,14 @@ fn gather_abstract_nodes(cur: &JS<Node>, refs: &mut ~[JS<Node>], postorder: bool } } +/// Specifies whether children must be recursively cloned or not. +enum CloneChildrenFlag { + CloneChildren, + DoNotCloneChildren +} + +fn as_uintptr<T>(t: &T) -> uintptr_t { t as *T as uintptr_t } + impl Node { pub fn ancestors(&self) -> AncestorIterator { AncestorIterator { @@ -728,8 +743,8 @@ impl Node { } } - pub fn owner_doc(&self) -> JS<Document> { - self.owner_doc.clone().unwrap() + pub fn owner_doc<'a>(&'a self) -> &'a JS<Document> { + self.owner_doc.get_ref() } pub fn set_owner_doc(&mut self, document: &JS<Document>) { @@ -793,11 +808,14 @@ impl Node { /// Sends layout data, if any, back to the script task to be destroyed. pub unsafe fn reap_layout_data(&mut self) { if self.layout_data.is_present() { - let layout_data = util::replace(&mut self.layout_data, LayoutDataRef::new()); + let layout_data = mem::replace(&mut self.layout_data, LayoutDataRef::new()); let layout_chan = layout_data.take_chan(); match layout_chan { None => {} - Some(chan) => chan.send(ReapLayoutDataMsg(layout_data)), + Some(chan) => { + let LayoutChan(chan) = chan; + chan.send(ReapLayoutDataMsg(layout_data)) + }, } } } @@ -805,13 +823,13 @@ impl Node { // http://dom.spec.whatwg.org/#dom-node-nodetype pub fn NodeType(&self) -> u16 { match self.type_id { - ElementNodeTypeId(_) => 1, - TextNodeTypeId => 3, - ProcessingInstructionNodeTypeId => 7, - CommentNodeTypeId => 8, - DocumentNodeTypeId => 9, - DoctypeNodeTypeId => 10, - DocumentFragmentNodeTypeId => 11, + ElementNodeTypeId(_) => NodeConstants::ELEMENT_NODE, + TextNodeTypeId => NodeConstants::TEXT_NODE, + ProcessingInstructionNodeTypeId => NodeConstants::PROCESSING_INSTRUCTION_NODE, + CommentNodeTypeId => NodeConstants::COMMENT_NODE, + DocumentNodeTypeId => NodeConstants::DOCUMENT_NODE, + DoctypeNodeTypeId => NodeConstants::DOCUMENT_TYPE_NODE, + DocumentFragmentNodeTypeId => NodeConstants::DOCUMENT_FRAGMENT_NODE, } } @@ -852,7 +870,7 @@ impl Node { TextNodeTypeId | ProcessingInstructionNodeTypeId | DoctypeNodeTypeId | - DocumentFragmentNodeTypeId => Some(self.owner_doc()), + DocumentFragmentNodeTypeId => Some(self.owner_doc().clone()), DocumentNodeTypeId => None } } @@ -878,7 +896,7 @@ impl Node { pub fn ChildNodes(&mut self, abstract_self: &JS<Node>) -> JS<NodeList> { match self.child_list { None => { - let doc = self.owner_doc(); + let doc = self.owner_doc().clone(); let doc = doc.get(); let list = NodeList::new_child_list(&doc.window, abstract_self); self.child_list = Some(list.clone()); @@ -930,11 +948,10 @@ impl Node { CommentNodeTypeId | TextNodeTypeId | ProcessingInstructionNodeTypeId => { - self.SetTextContent(abstract_self, val); + self.SetTextContent(abstract_self, val) } - _ => {} + _ => Ok(()) } - Ok(()) } // http://dom.spec.whatwg.org/#dom-node-textcontent @@ -976,7 +993,7 @@ impl Node { None } else { let document = self.owner_doc(); - Some(NodeCast::from(&document.get().CreateTextNode(&document, value))) + Some(NodeCast::from(&document.get().CreateTextNode(document, value))) }; // Step 3. Node::replace_all(node, abstract_self); @@ -1255,7 +1272,7 @@ impl Node { // http://dom.spec.whatwg.org/#concept-node-remove fn remove(node: &mut JS<Node>, parent: &mut JS<Node>, suppress_observers: SuppressObserver) { - assert!(node.parent_node().map_default(false, |ref node_parent| node_parent == parent)); + assert!(node.parent_node().map_or(false, |ref node_parent| node_parent == parent)); // Step 1-5: ranges. // Step 6-7: mutation observers. @@ -1270,6 +1287,124 @@ impl Node { } } + // http://dom.spec.whatwg.org/#concept-node-clone + fn clone(node: &JS<Node>, maybe_doc: Option<&JS<Document>>, clone_children: CloneChildrenFlag) + -> JS<Node> { + fn clone_recursively(node: &JS<Node>, copy: &mut JS<Node>, doc: &JS<Document>) { + for ref child in node.get().children() { + let mut cloned = Node::clone(child, Some(doc), DoNotCloneChildren); + match Node::pre_insert(&mut cloned, copy, None) { + Ok(ref mut appended) => clone_recursively(child, appended, doc), + Err(..) => fail!("an error occurred while appending children") + } + } + } + + // Step 1. + let mut document = match maybe_doc { + Some(doc) => doc.clone(), + None => node.get().owner_doc().clone() + }; + + // Step 2. + // XXXabinader: clone() for each node as trait? + let mut copy: JS<Node> = match node.type_id() { + DoctypeNodeTypeId => { + let doctype: JS<DocumentType> = DocumentTypeCast::to(node); + let doctype = doctype.get(); + let doctype = DocumentType::new(doctype.name.clone(), + Some(doctype.public_id.clone()), + Some(doctype.system_id.clone()), &document); + NodeCast::from(&doctype) + }, + DocumentFragmentNodeTypeId => { + let doc_fragment = DocumentFragment::new(&document); + NodeCast::from(&doc_fragment) + }, + CommentNodeTypeId => { + let comment: JS<Comment> = CommentCast::to(node); + let comment = comment.get(); + let comment = Comment::new(comment.characterdata.data.clone(), &document); + NodeCast::from(&comment) + }, + DocumentNodeTypeId => { + let document: JS<Document> = DocumentCast::to(node); + let document = document.get(); + let is_html_doc = match document.is_html_document { + true => HTMLDocument, + false => NonHTMLDocument + }; + let document = Document::new(&document.window, Some(document.url().clone()), + is_html_doc, None); + NodeCast::from(&document) + }, + ElementNodeTypeId(..) => { + let element: JS<Element> = ElementCast::to(node); + let element = element.get(); + let element = build_element_from_tag(element.tag_name.clone(), &document); + NodeCast::from(&element) + }, + TextNodeTypeId => { + let text: JS<Text> = TextCast::to(node); + let text = text.get(); + let text = Text::new(text.characterdata.data.clone(), &document); + NodeCast::from(&text) + }, + ProcessingInstructionNodeTypeId => { + let pi: JS<ProcessingInstruction> = ProcessingInstructionCast::to(node); + let pi = pi.get(); + let pi = ProcessingInstruction::new(pi.target.clone(), + pi.characterdata.data.clone(), &document); + NodeCast::from(&pi) + }, + }; + + // Step 3. + if copy.is_document() { + document = DocumentCast::to(©); + } + assert_eq!(copy.get().owner_doc(), &document); + + // Step 4 (some data already copied in step 2). + match node.type_id() { + DocumentNodeTypeId => { + let node_doc: JS<Document> = DocumentCast::to(node); + let node_doc = node_doc.get(); + let mut copy_doc: JS<Document> = DocumentCast::to(©); + let copy_doc = copy_doc.get_mut(); + copy_doc.set_encoding_name(node_doc.encoding_name.clone()); + copy_doc.set_quirks_mode(node_doc.quirks_mode()); + }, + ElementNodeTypeId(..) => { + let node_elem: JS<Element> = ElementCast::to(node); + let node_elem = node_elem.get(); + let mut copy_elem: JS<Element> = ElementCast::to(©); + let copy_elem = copy_elem.get_mut(); + // FIXME: https://github.com/mozilla/servo/issues/1737 + copy_elem.namespace = node_elem.namespace.clone(); + for attr in node_elem.attrs.iter() { + let attr = attr.get(); + copy_elem.attrs.push(Attr::new_ns(&document.get().window, + attr.local_name.clone(), attr.value.clone(), + attr.name.clone(), attr.namespace.clone(), + attr.prefix.clone())); + } + }, + _ => () + } + + // Step 5: cloning steps. + + // Step 6. + match clone_children { + CloneChildren => clone_recursively(node, &mut copy, &document), + DoNotCloneChildren => () + } + + // Step 7. + copy + } + // http://dom.spec.whatwg.org/#dom-node-insertbefore pub fn InsertBefore(&self, abstract_self: &mut JS<Node>, node: &mut JS<Node>, child: Option<JS<Node>>) -> Fallible<JS<Node>> { @@ -1422,14 +1557,36 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-normalize - pub fn Normalize(&mut self) { - // FIXME (#1823) implement. + pub fn Normalize(&mut self, abstract_self: &mut JS<Node>) { + let mut prev_text = None; + for mut child in self.children() { + if child.is_text() { + let characterdata: JS<CharacterData> = CharacterDataCast::to(&child); + if characterdata.get().Length() == 0 { + abstract_self.remove_child(&mut child); + } else { + match prev_text { + Some(ref text_node) => { + let mut prev_characterdata: JS<CharacterData> = CharacterDataCast::to(text_node); + let _ = prev_characterdata.get_mut().AppendData(characterdata.get().Data()); + abstract_self.remove_child(&mut child); + }, + None => prev_text = Some(child) + } + } + } else { + prev_text = None; + } + + } } // http://dom.spec.whatwg.org/#dom-node-clonenode - pub fn CloneNode(&self, _deep: bool) -> Fallible<JS<Node>> { - // FIXME: stub - https://github.com/mozilla/servo/issues/1240 - fail!("stub") + pub fn CloneNode(&self, abstract_self: &mut JS<Node>, deep: bool) -> JS<Node> { + match deep { + true => Node::clone(abstract_self, None, CloneChildren), + false => Node::clone(abstract_self, None, DoNotCloneChildren) + } } // http://dom.spec.whatwg.org/#dom-node-isequalnode @@ -1507,9 +1664,57 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-comparedocumentposition - pub fn CompareDocumentPosition(&self, _other: &JS<Node>) -> u16 { - // FIXME (#1794) implement. - 0 + pub fn CompareDocumentPosition(&self, abstract_self: &JS<Node>, other: &JS<Node>) -> u16 { + if abstract_self == other { + // step 2. + 0 + } else { + let mut lastself = abstract_self.clone(); + let mut lastother = other.clone(); + for ancestor in abstract_self.ancestors() { + if &ancestor == other { + // step 4. + return NodeConstants::DOCUMENT_POSITION_CONTAINS + + NodeConstants::DOCUMENT_POSITION_PRECEDING; + } + lastself = ancestor; + } + for ancestor in other.ancestors() { + if &ancestor == abstract_self { + // step 5. + return NodeConstants::DOCUMENT_POSITION_CONTAINED_BY + + NodeConstants::DOCUMENT_POSITION_FOLLOWING; + } + lastother = ancestor; + } + + if lastself != lastother { + let abstract_uint: uintptr_t = as_uintptr(&abstract_self.get()); + let other_uint: uintptr_t = as_uintptr(&other.get()); + + let random = if abstract_uint < other_uint { + NodeConstants::DOCUMENT_POSITION_FOLLOWING + } else { + NodeConstants::DOCUMENT_POSITION_PRECEDING + }; + // step 3. + return random + + NodeConstants::DOCUMENT_POSITION_DISCONNECTED + + NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; + } + + for child in lastself.traverse_preorder() { + if &child == other { + // step 6. + return NodeConstants::DOCUMENT_POSITION_PRECEDING; + } + if &child == abstract_self { + // step 7. + return NodeConstants::DOCUMENT_POSITION_FOLLOWING; + } + } + unreachable!() + } } // http://dom.spec.whatwg.org/#dom-node-contains @@ -1558,31 +1763,31 @@ impl Node { // pub fn set_parent_node(&mut self, new_parent_node: Option<JS<Node>>) { - let doc = self.owner_doc(); + let doc = self.owner_doc().clone(); doc.get().wait_until_safe_to_modify_dom(); self.parent_node = new_parent_node } pub fn set_first_child(&mut self, new_first_child: Option<JS<Node>>) { - let doc = self.owner_doc(); + let doc = self.owner_doc().clone(); doc.get().wait_until_safe_to_modify_dom(); self.first_child = new_first_child } pub fn set_last_child(&mut self, new_last_child: Option<JS<Node>>) { - let doc = self.owner_doc(); + let doc = self.owner_doc().clone(); doc.get().wait_until_safe_to_modify_dom(); self.last_child = new_last_child } pub fn set_prev_sibling(&mut self, new_prev_sibling: Option<JS<Node>>) { - let doc = self.owner_doc(); + let doc = self.owner_doc().clone(); doc.get().wait_until_safe_to_modify_dom(); self.prev_sibling = new_prev_sibling } pub fn set_next_sibling(&mut self, new_next_sibling: Option<JS<Node>>) { - let doc = self.owner_doc(); + let doc = self.owner_doc().clone(); doc.get().wait_until_safe_to_modify_dom(); self.next_sibling = new_next_sibling } @@ -1619,6 +1824,11 @@ impl Node { pub fn next_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>> { self.next_sibling.as_ref() } + + pub unsafe fn get_hover_state_for_layout(&self) -> bool { + let unsafe_this: *Node = cast::transmute::<&Node,*Node>(self); + (*unsafe_this).flags.get_in_hover_state() + } } impl Reflectable for Node { diff --git a/src/components/script/dom/webidls/Document.webidl b/src/components/script/dom/webidls/Document.webidl index 98df0b2aef9..41d20631bde 100644 --- a/src/components/script/dom/webidls/Document.webidl +++ b/src/components/script/dom/webidls/Document.webidl @@ -44,6 +44,7 @@ interface Document : Node { partial interface Document { [SetterThrows] attribute DOMString title; + [SetterThrows] attribute HTMLElement? body; readonly attribute HTMLHeadElement? head; NodeList getElementsByName(DOMString elementName); diff --git a/src/components/script/dom/webidls/Element.webidl b/src/components/script/dom/webidls/Element.webidl index e26c9415d4a..2211fd5c887 100644 --- a/src/components/script/dom/webidls/Element.webidl +++ b/src/components/script/dom/webidls/Element.webidl @@ -28,10 +28,8 @@ interface Element : Node { [Pure] attribute DOMString id; -/* - FIXME Bug 810677 Move className from HTMLElement to Element + [Pure] attribute DOMString className; -*/ /*[Constant] readonly attribute DOMTokenList? classList;*/ diff --git a/src/components/script/dom/webidls/Event.webidl b/src/components/script/dom/webidls/Event.webidl index d33093d76e9..6e574427548 100644 --- a/src/components/script/dom/webidls/Event.webidl +++ b/src/components/script/dom/webidls/Event.webidl @@ -33,7 +33,6 @@ interface Event { readonly attribute boolean isTrusted; readonly attribute DOMTimeStamp timeStamp; - [Throws] void initEvent(DOMString type, boolean bubbles, boolean cancelable); }; diff --git a/src/components/script/dom/webidls/HTMLElement.webidl b/src/components/script/dom/webidls/HTMLElement.webidl index e0ce18aaff9..8f1315d011d 100644 --- a/src/components/script/dom/webidls/HTMLElement.webidl +++ b/src/components/script/dom/webidls/HTMLElement.webidl @@ -43,10 +43,6 @@ interface HTMLElement : Element { readonly attribute boolean isContentEditable; [SetterThrows, Pure] attribute boolean spellcheck; - - // Mozilla specific stuff - // FIXME Bug 810677 Move className from HTMLElement to Element - attribute DOMString className; }; // http://dev.w3.org/csswg/cssom-view/#extensions-to-the-htmlelement-interface diff --git a/src/components/script/dom/webidls/MouseEvent.webidl b/src/components/script/dom/webidls/MouseEvent.webidl index 68a273ebaaf..5bb4a84a90a 100644 --- a/src/components/script/dom/webidls/MouseEvent.webidl +++ b/src/components/script/dom/webidls/MouseEvent.webidl @@ -23,7 +23,6 @@ interface MouseEvent : UIEvent { readonly attribute unsigned short buttons; readonly attribute EventTarget? relatedTarget; // Deprecated in DOM Level 3: - [Throws] void initMouseEvent(DOMString typeArg, boolean canBubbleArg, boolean cancelableArg, diff --git a/src/components/script/dom/webidls/Node.webidl b/src/components/script/dom/webidls/Node.webidl index 0670e6eb3f6..2a13d6ab381 100644 --- a/src/components/script/dom/webidls/Node.webidl +++ b/src/components/script/dom/webidls/Node.webidl @@ -52,7 +52,6 @@ interface Node : EventTarget { attribute DOMString? textContent; void normalize(); - [Throws] Node cloneNode(optional boolean deep = true); boolean isEqualNode(Node? node); diff --git a/src/components/script/dom/webidls/Window.webidl b/src/components/script/dom/webidls/Window.webidl index de53cd2342c..0260324b91e 100644 --- a/src/components/script/dom/webidls/Window.webidl +++ b/src/components/script/dom/webidls/Window.webidl @@ -67,13 +67,13 @@ partial interface Window { [NoInterfaceObject] interface WindowTimers { - //long setTimeout(Function handler, optional long timeout, any... arguments); + //long setTimeout(Function handler, optional long timeout = 0, any... arguments); //XXXjdm No support for Function or variadic arguments yet - long setTimeout(any handler, optional long timeout/*, any... arguments*/); - void clearTimeout(long handle); - /*long setTimeout(DOMString handler, optional long timeout, any... arguments); - long setInterval(Function handler, optional long timeout, any... arguments); - long setInterval(DOMString handler, optional long timeout, any... arguments); - void clearInterval(long handle);*/ + long setTimeout(any handler, optional long timeout = 0/*, any... arguments*/); + void clearTimeout(optional long handle = 0); + /*long setTimeout(DOMString handler, optional long timeout = 0, any... arguments); + long setInterval(Function handler, optional long timeout = 0, any... arguments); + long setInterval(DOMString handler, optional long timeout = 0, any... arguments); + void clearInterval(optional long handle = 0);*/ }; Window implements WindowTimers; diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs index 7c3d2e90280..2ef70b0eac7 100644 --- a/src/components/script/dom/window.rs +++ b/src/components/script/dom/window.rs @@ -25,22 +25,22 @@ use js::jsval::JSVal; use js::jsval::{NullValue, ObjectValue}; use js::JSPROP_ENUMERATE; +use collections::hashmap::HashSet; use std::cast; -use std::comm::SharedChan; +use std::cmp; +use std::comm::Chan; use std::comm::Select; -use std::hashmap::HashSet; +use std::hash::{Hash, sip}; use std::io::timer::Timer; -use std::num; use std::rc::Rc; -use std::to_bytes::Cb; -use extra::serialize::{Encoder, Encodable}; +use serialize::{Encoder, Encodable}; use extra::url::{Url}; pub enum TimerControlMsg { - TimerMessage_Fire(~TimerData), - TimerMessage_Close, - TimerMessage_TriggerExit //XXXjdm this is just a quick hack to talk to the script task + TimerMessageFire(~TimerData), + TimerMessageClose, + TimerMessageTriggerExit //XXXjdm this is just a quick hack to talk to the script task } pub struct TimerHandle { @@ -53,9 +53,9 @@ impl<S: Encoder> Encodable<S> for TimerHandle { } } -impl IterBytes for TimerHandle { - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - self.handle.iter_bytes(lsb0, f) +impl Hash for TimerHandle { + fn hash(&self, state: &mut sip::SipState) { + self.handle.hash(state); } } @@ -81,13 +81,13 @@ pub struct Window { image_cache_task: ImageCacheTask, active_timers: ~HashSet<TimerHandle>, next_timer_handle: i32, - extra: Untraceable + priv extra: Untraceable } struct Untraceable { page: Rc<Page>, compositor: ~ScriptListener, - timer_chan: SharedChan<TimerControlMsg>, + timer_chan: Chan<TimerControlMsg>, } impl<S: Encoder> Encodable<S> for Untraceable { @@ -115,7 +115,7 @@ impl Window { #[unsafe_destructor] impl Drop for Window { fn drop(&mut self) { - self.extra.timer_chan.send(TimerMessage_Close); + self.extra.timer_chan.send(TimerMessageClose); for handle in self.active_timers.iter() { handle.cancel(); } @@ -134,11 +134,11 @@ pub struct TimerData { impl Window { pub fn Alert(&self, s: DOMString) { // Right now, just print to the console - println(format!("ALERT: {:s}", s)); + println!("ALERT: {:s}", s); } pub fn Close(&self) { - self.extra.timer_chan.send(TimerMessage_TriggerExit); + self.extra.timer_chan.send(TimerMessageTriggerExit); } pub fn Document(&self) -> JS<Document> { @@ -226,7 +226,7 @@ impl Reflectable for Window { impl Window { pub fn SetTimeout(&mut self, _cx: *JSContext, callback: JSVal, timeout: i32) -> i32 { - let timeout = num::max(0, timeout) as u64; + let timeout = cmp::max(0, timeout) as u64; let handle = self.next_timer_handle; self.next_timer_handle += 1; @@ -237,15 +237,17 @@ impl Window { let chan = self.extra.timer_chan.clone(); spawn_named("Window:SetTimeout", proc() { let mut tm = tm; - let mut timeout_port = tm.oneshot(timeout); - let mut cancel_port = cancel_port; + let timeout_port = tm.oneshot(timeout); + let cancel_port = cancel_port; let select = Select::new(); - let timeout_handle = select.add(&mut timeout_port); - let _cancel_handle = select.add(&mut cancel_port); + let mut timeout_handle = select.handle(&timeout_port); + unsafe { timeout_handle.add() }; + let mut cancel_handle = select.handle(&cancel_port); + unsafe { cancel_handle.add() }; let id = select.wait(); - if id == timeout_handle.id { - chan.send(TimerMessage_Fire(~TimerData { + if id == timeout_handle.id() { + chan.send(TimerMessageFire(~TimerData { handle: handle, funval: callback, args: ~[], @@ -290,14 +292,15 @@ impl Window { compositor: compositor, page: page.clone(), timer_chan: { - let (timer_port, timer_chan): (Port<TimerControlMsg>, SharedChan<TimerControlMsg>) = SharedChan::new(); + let (timer_port, timer_chan): (Port<TimerControlMsg>, Chan<TimerControlMsg>) = Chan::new(); let id = page.borrow().id.clone(); spawn_named("timer controller", proc() { + let ScriptChan(script_chan) = script_chan; loop { match timer_port.recv() { - TimerMessage_Close => break, - TimerMessage_Fire(td) => script_chan.send(FireTimerMsg(id, td)), - TimerMessage_TriggerExit => script_chan.send(ExitWindowMsg(id)), + TimerMessageClose => break, + TimerMessageFire(td) => script_chan.send(FireTimerMsg(id, td)), + TimerMessageTriggerExit => script_chan.send(ExitWindowMsg(id)), } } }); diff --git a/src/components/script/html/cssparse.rs b/src/components/script/html/cssparse.rs index 073b8562df4..846af813461 100644 --- a/src/components/script/html/cssparse.rs +++ b/src/components/script/html/cssparse.rs @@ -34,10 +34,11 @@ pub fn spawn_css_parser(provenance: StylesheetProvenance, resource_task.send(Load(url, input_chan)); let LoadResponse { metadata: metadata, progress_port: progress_port } = input_port.recv(); + let final_url = &metadata.final_url; let protocol_encoding_label = metadata.charset.as_ref().map(|s| s.as_slice()); let iter = ProgressMsgPortIterator { progress_port: progress_port }; Stylesheet::from_bytes_iter( - iter, metadata.final_url, + iter, final_url.clone(), protocol_encoding_label, Some(environment_encoding)) } InlineProvenance(base_url, data) => { diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs index 67a05c94386..34cbd08a59b 100644 --- a/src/components/script/html/hubbub_html_parser.rs +++ b/src/components/script/html/hubbub_html_parser.rs @@ -22,12 +22,13 @@ use hubbub::hubbub; use servo_msg::constellation_msg::SubpageId; use servo_net::resource_task::{Load, Payload, Done, ResourceTask, load_whole_resource}; use servo_util::namespace::Null; -use servo_util::str::DOMString; +use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS}; use servo_util::task::spawn_named; use servo_util::url::parse_url; +use std::ascii::StrAsciiExt; use std::cast; use std::cell::RefCell; -use std::comm::{Port, SharedChan}; +use std::comm::{Port, Chan}; use std::str; use style::Stylesheet; @@ -102,7 +103,7 @@ spawned, collates them, and sends them to the given result channel. * `from_parent` - A port on which to receive new links. */ -fn css_link_listener(to_parent: SharedChan<HtmlDiscoveryMessage>, +fn css_link_listener(to_parent: Chan<HtmlDiscoveryMessage>, from_parent: Port<CSSMessage>, resource_task: ResourceTask) { let mut result_vec = ~[]; @@ -125,7 +126,7 @@ fn css_link_listener(to_parent: SharedChan<HtmlDiscoveryMessage>, } } -fn js_script_listener(to_parent: SharedChan<HtmlDiscoveryMessage>, +fn js_script_listener(to_parent: Chan<HtmlDiscoveryMessage>, from_parent: Port<JSMessage>, resource_task: ResourceTask) { let mut result_vec = ~[]; @@ -139,7 +140,7 @@ fn js_script_listener(to_parent: SharedChan<HtmlDiscoveryMessage>, } Ok((metadata, bytes)) => { result_vec.push(JSFile { - data: str::from_utf8(bytes).to_owned(), + data: str::from_utf8(bytes).unwrap().to_owned(), url: metadata.final_url, }); } @@ -255,9 +256,9 @@ pub fn parse_html(page: &Page, // Spawn a CSS parser to receive links to CSS style sheets. let resource_task2 = resource_task.clone(); - let (discovery_port, discovery_chan) = SharedChan::new(); + let (discovery_port, discovery_chan) = Chan::new(); let stylesheet_chan = discovery_chan.clone(); - let (css_msg_port, css_chan) = SharedChan::new(); + let (css_msg_port, css_chan) = Chan::new(); spawn_named("parse_html:css", proc() { css_link_listener(stylesheet_chan, css_msg_port, resource_task2.clone()); }); @@ -265,7 +266,7 @@ pub fn parse_html(page: &Page, // Spawn a JS parser to receive JavaScript. let resource_task2 = resource_task.clone(); let js_result_chan = discovery_chan.clone(); - let (js_msg_port, js_chan) = SharedChan::new(); + let (js_msg_port, js_chan) = Chan::new(); spawn_named("parse_html:js", proc() { js_script_listener(js_result_chan, js_msg_port, resource_task2.clone()); }); @@ -302,11 +303,16 @@ pub fn parse_html(page: &Page, let next_subpage_id = RefCell::new(next_subpage_id); + let doc_cell = RefCell::new(document); + let tree_handler = hubbub::TreeHandler { create_comment: |data: ~str| { debug!("create comment"); - let comment: JS<Node> = NodeCast::from(&Comment::new(data, document)); - unsafe { comment.to_hubbub_node() } + // NOTE: tmp vars are workaround for lifetime issues. Both required. + let tmp_borrow = doc_cell.borrow(); + let tmp = tmp_borrow.get(); + let comment: JS<Node> = NodeCast::from(&Comment::new(data, *tmp)); + unsafe { comment.to_hubbub_node() } }, create_doctype: |doctype: ~hubbub::Doctype| { debug!("create doctype"); @@ -314,21 +320,29 @@ pub fn parse_html(page: &Page, public_id: public_id, system_id: system_id, force_quirks: _ } = doctype; - let doctype_node = DocumentType::new(name, public_id, system_id, document); + // NOTE: tmp vars are workaround for lifetime issues. Both required. + let tmp_borrow = doc_cell.borrow(); + let tmp = tmp_borrow.get(); + let doctype_node = DocumentType::new(name, public_id, system_id, *tmp); unsafe { doctype_node.to_hubbub_node() } }, create_element: |tag: ~hubbub::Tag| { debug!("create element"); - let mut element = build_element_from_tag(tag.name.clone(), document); + // NOTE: tmp vars are workaround for lifetime issues. Both required. + let tmp_borrow = doc_cell.borrow(); + let tmp = tmp_borrow.get(); + let mut element = build_element_from_tag(tag.name.clone(), *tmp); debug!("-- attach attrs"); for attr in tag.attributes.iter() { let elem = element.clone(); - element.get_mut().set_attr(&elem, - attr.name.clone(), - attr.value.clone()); + //FIXME: this should have proper error handling or explicitly drop + // exceptions on the ground + assert!(element.get_mut().set_attr(&elem, + attr.name.clone(), + attr.value.clone()).is_ok()); } // Spawn additional parsing, network loads, etc. from tag and attrs @@ -337,12 +351,16 @@ pub fn parse_html(page: &Page, ElementNodeTypeId(HTMLLinkElementTypeId) => { match (element.get().get_attribute(Null, "rel"), element.get().get_attribute(Null, "href")) { - (Some(rel), Some(href)) => { - if "stylesheet" == rel.get().value_ref() { - debug!("found CSS stylesheet: {:s}", href.get().value_ref()); - let url = parse_url(href.get().value_ref(), Some(url2.clone())); - css_chan2.send(CSSTaskNewFile(UrlProvenance(url))); - } + (Some(ref rel), Some(ref href)) if rel.get() + .value_ref() + .split(HTML_SPACE_CHARACTERS. + as_slice()) + .any(|s| { + s.eq_ignore_ascii_case("stylesheet") + }) => { + debug!("found CSS stylesheet: {:s}", href.get().value_ref()); + let url = parse_url(href.get().value_ref(), Some(url2.clone())); + css_chan2.send(CSSTaskNewFile(UrlProvenance(url))); } _ => {} } @@ -357,11 +375,12 @@ pub fn parse_html(page: &Page, let src_opt = elem.get().get_attribute(Null, "src").map(|x| x.get().Value()); for src in src_opt.iter() { let iframe_url = parse_url(*src, Some(url2.clone())); - iframe_element.get_mut().extra.frame = Some(iframe_url.clone()); + iframe_element.get_mut().set_frame(iframe_url.clone()); // Subpage Id let subpage_id = next_subpage_id.get(); - next_subpage_id.set(SubpageId(*subpage_id + 1)); + let SubpageId(id_num) = subpage_id; + next_subpage_id.set(SubpageId(id_num + 1)); iframe_element.get_mut().size = Some(IFrameSize { pipeline_id: pipeline_id, @@ -379,7 +398,10 @@ pub fn parse_html(page: &Page, }, create_text: |data: ~str| { debug!("create text"); - let text = Text::new(data, document); + // NOTE: tmp vars are workaround for lifetime issues. Both required. + let tmp_borrow = doc_cell.borrow(); + let tmp = tmp_borrow.get(); + let text = Text::new(data, *tmp); unsafe { text.to_hubbub_node() } }, ref_node: |_| {}, @@ -389,7 +411,7 @@ pub fn parse_html(page: &Page, debug!("append child {:x} {:x}", parent, child); let mut parent: JS<Node> = NodeWrapping::from_hubbub_node(parent); let mut child: JS<Node> = NodeWrapping::from_hubbub_node(child); - parent.AppendChild(&mut child); + assert!(parent.AppendChild(&mut child).is_ok()); } child }, @@ -426,11 +448,17 @@ pub fn parse_html(page: &Page, }, set_quirks_mode: |mode| { debug!("set quirks mode"); - document.get_mut().set_quirks_mode(mode); + // NOTE: tmp vars are workaround for lifetime issues. Both required. + let mut tmp_borrow = doc_cell.borrow_mut(); + let tmp = tmp_borrow.get(); + tmp.get_mut().set_quirks_mode(mode); }, encoding_change: |encname| { debug!("encoding change"); - document.get_mut().set_encoding_name(encname); + // NOTE: tmp vars are workaround for lifetime issues. Both required. + let mut tmp_borrow = doc_cell.borrow_mut(); + let tmp = tmp_borrow.get(); + tmp.get_mut().set_encoding_name(encname); }, complete_script: |script| { unsafe { @@ -495,6 +523,7 @@ pub fn parse_html(page: &Page, } } + debug!("finished parsing"); css_chan.send(CSSTaskExit); js_chan.send(JSTaskExit); diff --git a/src/components/script/layout_interface.rs b/src/components/script/layout_interface.rs index 6ebea1809af..4ccf959f8ab 100644 --- a/src/components/script/layout_interface.rs +++ b/src/components/script/layout_interface.rs @@ -15,7 +15,7 @@ use geom::size::Size2D; use script_task::{ScriptChan}; use servo_util::geometry::Au; use std::cmp; -use std::comm::{Chan, SharedChan}; +use std::comm::Chan; use std::libc::c_void; use style::Stylesheet; @@ -132,11 +132,11 @@ pub struct Reflow { /// Encapsulates a channel to the layout task. #[deriving(Clone)] -pub struct LayoutChan(SharedChan<Msg>); +pub struct LayoutChan(Chan<Msg>); impl LayoutChan { pub fn new() -> (Port<Msg>, LayoutChan) { - let (port, chan) = SharedChan::new(); + let (port, chan) = Chan::new(); (port, LayoutChan(chan)) } } diff --git a/src/components/script/macros.rs b/src/components/script/macros.rs index f8eaa07cc05..0ebdd7c6b7e 100644 --- a/src/components/script/macros.rs +++ b/src/components/script/macros.rs @@ -9,12 +9,14 @@ macro_rules! bitfield( impl $bitfieldname { #[inline] pub fn $getter(self) -> bool { - (*self & $value) != 0 + let $bitfieldname(s) = self; + (s & $value) != 0 } #[inline] pub fn $setter(&mut self, value: bool) { - *self = $bitfieldname((**self & !$value) | (if value { $value } else { 0 })) + let $bitfieldname(s) = *self; + *self = $bitfieldname((s & !$value) | (if value { $value } else { 0 })) } } ) diff --git a/src/components/script/script.rs b/src/components/script/script.rs index 3d57daa995f..4c5a53efbe6 100644 --- a/src/components/script/script.rs +++ b/src/components/script/script.rs @@ -10,16 +10,18 @@ #[feature(globs, macro_rules, struct_variant, managed_boxes)]; -extern mod geom; -extern mod hubbub; -extern mod encoding; -extern mod js; -extern mod servo_net = "net"; -extern mod servo_util = "util"; -extern mod style; -extern mod servo_msg = "msg"; -extern mod extra; -extern mod native; +extern crate collections; +extern crate geom; +extern crate hubbub; +extern crate encoding; +extern crate js; +extern crate serialize; +extern crate servo_net = "net"; +extern crate servo_util = "util"; +extern crate style; +extern crate servo_msg = "msg"; +extern crate extra; +extern crate native; // Macros mod macros; diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index d4561ebc21b..e82a0e87647 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -50,13 +50,13 @@ use servo_util::task::send_on_failure; use servo_util::namespace::Null; use std::cast; use std::cell::{RefCell, Ref, RefMut}; -use std::comm::{Port, SharedChan}; +use std::comm::{Port, Chan, Empty, Disconnected, Data}; +use std::mem::replace; use std::ptr; use std::rc::Rc; use std::task; -use std::util::replace; -use extra::serialize::{Encoder, Encodable}; +use serialize::{Encoder, Encodable}; /// Messages used to control the script task. pub enum ScriptMsg { @@ -90,7 +90,7 @@ pub struct NewLayoutInfo { /// Encapsulates external communication with the script task. #[deriving(Clone)] -pub struct ScriptChan(SharedChan<ScriptMsg>); +pub struct ScriptChan(Chan<ScriptMsg>); impl<S: Encoder> Encodable<S> for ScriptChan { fn encode(&self, _s: &mut S) { @@ -100,7 +100,7 @@ impl<S: Encoder> Encodable<S> for ScriptChan { impl ScriptChan { /// Creates a new script chan. pub fn new() -> (Port<ScriptMsg>, ScriptChan) { - let (port, chan) = SharedChan::new(); + let (port, chan) = Chan::new(); (port, ScriptChan(chan)) } } @@ -164,7 +164,7 @@ pub struct PageTreeIterator<'a> { impl PageTree { fn new(id: PipelineId, layout_chan: LayoutChan, window_size: Size2D<uint>) -> PageTree { PageTree { - page: unsafe { Rc::new_unchecked(Page { + page: Rc::new(Page { id: id, frame: RefCell::new(None), layout_chan: layout_chan, @@ -177,7 +177,7 @@ impl PageTree { resize_event: RefCell::new(None), fragment_node: RefCell::new(None), last_reflow_id: RefCell::new(0) - }) }, + }), inner: ~[], } } @@ -220,7 +220,7 @@ impl PageTree { .map(|(idx, _)| idx) }; match remove_idx { - Some(idx) => return Some(self.inner.remove(idx)), + Some(idx) => return Some(self.inner.remove(idx).unwrap()), None => { for page_tree in self.inner.mut_iter() { match page_tree.remove(id) { @@ -237,11 +237,9 @@ impl PageTree { impl<'a> Iterator<Rc<Page>> for PageTreeIterator<'a> { fn next(&mut self) -> Option<Rc<Page>> { if !self.stack.is_empty() { - let next = self.stack.pop(); - { - for child in next.inner.mut_iter() { - self.stack.push(child); - } + let next = self.stack.pop().unwrap(); + for child in next.inner.mut_iter() { + self.stack.push(child); } Some(next.page.clone()) } else { @@ -307,7 +305,7 @@ impl Page { pub fn get_url(&self) -> Url { let url = self.url(); - url.get().get_ref().first().clone() + url.get().get_ref().ref0().clone() } /// Sends a ping to layout and waits for the response. The response will arrive when the @@ -319,11 +317,14 @@ impl Page { match join_port { Some(ref join_port) => { match join_port.try_recv() { - None => { + Empty => { info!("script: waiting on layout"); join_port.recv(); } - Some(_) => {} + Data(_) => {} + Disconnected => { + fail!("Layout task failed while script was waiting for a result."); + } } debug!("script: layout joined") @@ -339,7 +340,8 @@ impl Page { response_port: Port<T>) -> T { self.join_layout(); - self.layout_chan.send(QueryMsg(query)); + let LayoutChan(ref chan) = self.layout_chan; + chan.send(QueryMsg(query)); response_port.recv() } @@ -397,7 +399,8 @@ impl Page { id: *last_reflow_id.get(), }; - self.layout_chan.send(ReflowMsg(reflow)); + let LayoutChan(ref chan) = self.layout_chan; + chan.send(ReflowMsg(reflow)); debug!("script: layout forked") } @@ -493,8 +496,7 @@ impl ScriptTask { -> Rc<ScriptTask> { let js_runtime = js::rust::rt(); - unsafe { - Rc::new_unchecked(ScriptTask { + Rc::new(ScriptTask { page_tree: RefCell::new(PageTree::new(id, layout_chan, window_size)), image_cache_task: img_cache_task, @@ -507,8 +509,7 @@ impl ScriptTask { js_runtime: js_runtime, mouse_over_targets: RefCell::new(None) - }) - } + }) } /// Starts the script task. After calling this method, the script task will loop receiving @@ -530,9 +531,9 @@ impl ScriptTask { resource_task: ResourceTask, image_cache_task: ImageCacheTask, window_size: Size2D<uint>) { - let mut builder = task::task(); - send_on_failure(&mut builder, FailureMsg(failure_msg), (*constellation_chan).clone()); - builder.name("ScriptTask"); + let mut builder = task::task().named("ScriptTask"); + let ConstellationChan(const_chan) = constellation_chan.clone(); + send_on_failure(&mut builder, FailureMsg(failure_msg), const_chan); builder.spawn(proc() { let script_task = ScriptTask::new(id, compositor as ~ScriptListener, @@ -593,8 +594,8 @@ impl ScriptTask { } match self.port.try_recv() { - None => break, - Some(ev) => event = ev, + Empty | Disconnected => break, + Data(ev) => event = ev, } } @@ -652,7 +653,7 @@ impl ScriptTask { let this_value = if timer_data.args.len() > 0 { fail!("NYI") } else { - js_info.get().get_ref().js_compartment.borrow().global_obj.borrow().ptr + js_info.get().get_ref().js_compartment.borrow().global_obj }; // TODO: Support extra arguments. This requires passing a `*JSVal` array as `argv`. @@ -683,7 +684,8 @@ impl ScriptTask { /// Handles a navigate forward or backward message. /// TODO(tkuehn): is it ever possible to navigate only on a subframe? fn handle_navigate_msg(&self, direction: NavigationDirection) { - self.constellation_chan.send(constellation_msg::NavigateMsg(direction)); + let ConstellationChan(ref chan) = self.constellation_chan; + chan.send(constellation_msg::NavigateMsg(direction)); } /// Window was resized, but this script was not active, so don't reflow yet @@ -696,7 +698,7 @@ impl ScriptTask { let mut page_url = page.mut_url(); let last_loaded_url = replace(page_url.get(), None); for url in last_loaded_url.iter() { - *page_url.get() = Some((url.first(), true)); + *page_url.get() = Some((url.ref0().clone(), true)); } } @@ -823,19 +825,22 @@ impl ScriptTask { js_scripts = Some(scripts); } Some(HtmlDiscoveredStyle(sheet)) => { - page.layout_chan.send(AddStylesheetMsg(sheet)); + let LayoutChan(ref chan) = page.layout_chan; + chan.send(AddStylesheetMsg(sheet)); } Some(HtmlDiscoveredIFrame((iframe_url, subpage_id, sandboxed))) => { - page.next_subpage_id.set(SubpageId(*subpage_id + 1)); + let SubpageId(num) = subpage_id; + page.next_subpage_id.set(SubpageId(num + 1)); let sandboxed = if sandboxed { IFrameSandboxed } else { IFrameUnsandboxed }; - self.constellation_chan.send(LoadIframeUrlMsg(iframe_url, - pipeline_id, - subpage_id, - sandboxed)); + let ConstellationChan(ref chan) = self.constellation_chan; + chan.send(LoadIframeUrlMsg(iframe_url, + pipeline_id, + subpage_id, + sandboxed)); } None => break } @@ -862,7 +867,7 @@ impl ScriptTask { let js_info = page.js_info(); let js_info = js_info.get().get_ref(); let compartment = js_info.js_compartment.borrow(); - compartment.define_functions(DEBUG_FNS); + assert!(compartment.define_functions(DEBUG_FNS).is_ok()); js_info.js_context.borrow().ptr }; @@ -873,12 +878,14 @@ impl ScriptTask { let (cx, global_obj) = { let js_info = page.js_info(); (js_info.get().get_ref().js_context.clone(), - js_info.get().get_ref().js_compartment.borrow().global_obj.clone()) + js_info.get().get_ref().js_compartment.borrow().global_obj) }; - cx.borrow().evaluate_script(global_obj, - file.data.clone(), - file.url.to_str(), - 1); + //FIXME: this should have some kind of error handling, or explicitly + // drop an exception on the floor. + assert!(cx.borrow().evaluate_script(global_obj, + file.data.clone(), + file.url.to_str(), + 1).is_ok()); }); } @@ -890,12 +897,13 @@ impl ScriptTask { let doctarget = EventTargetCast::from(&document); let mut wintarget: JS<EventTarget> = EventTargetCast::from(&window); let winclone = wintarget.clone(); - wintarget.get_mut().dispatch_event_with_target(&winclone, Some(doctarget), &mut event); + let _ = wintarget.get_mut().dispatch_event_with_target(&winclone, Some(doctarget), &mut event); let mut fragment_node = page.fragment_node.borrow_mut(); - *fragment_node.get() = fragment.map_default(None, |fragid| self.find_fragment_node(page, fragid)); + *fragment_node.get() = fragment.map_or(None, |fragid| self.find_fragment_node(page, fragid)); - self.constellation_chan.send(LoadCompleteMsg(page.id, url)); + let ConstellationChan(ref chan) = self.constellation_chan; + chan.send(LoadCompleteMsg(page.id, url)); } fn find_fragment_node(&self, page: &Page, fragid: ~str) -> Option<JS<Element>> { @@ -908,7 +916,7 @@ impl ScriptTask { let mut anchors = doc_node.traverse_preorder().filter(|node| node.is_anchor_element()); anchors.find(|node| { let elem: JS<Element> = ElementCast::to(node); - elem.get().get_attribute(Null, "name").map_default(false, |attr| { + elem.get().get_attribute(Null, "name").map_or(false, |attr| { attr.get().value_ref() == fragid }) }).map(|node| ElementCast::to(&node)) @@ -973,7 +981,7 @@ impl ScriptTask { // FIXME: this event should be dispatch on WindowProxy. See #1715 let mut wintarget: JS<EventTarget> = EventTargetCast::from(&frame.window); let winclone = wintarget.clone(); - wintarget.get_mut().dispatch_event_with_target(&winclone, None, event); + let _ = wintarget.get_mut().dispatch_event_with_target(&winclone, None, event); } None =>() } @@ -1121,8 +1129,9 @@ impl ScriptTask { None => {} } } else { - self.constellation_chan.send(LoadUrlMsg(page.id, url)); - } + let ConstellationChan(ref chan) = self.constellation_chan; + chan.send(LoadUrlMsg(page.id, url)); + } } } } @@ -1133,7 +1142,8 @@ fn shut_down_layout(page: &Page) { // Tell the layout task to begin shutting down. let (response_port, response_chan) = Chan::new(); - page.layout_chan.send(layout_interface::PrepareToExitMsg(response_chan)); + let LayoutChan(ref chan) = page.layout_chan; + chan.send(layout_interface::PrepareToExitMsg(response_chan)); response_port.recv(); // Destroy all nodes. Setting frame and js_info to None will trigger our @@ -1149,5 +1159,5 @@ fn shut_down_layout(page: &Page) { *js_info.get() = None; // Destroy the layout task. If there were node leaks, layout will now crash safely. - page.layout_chan.send(layout_interface::ExitNowMsg); + chan.send(layout_interface::ExitNowMsg); } |