diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/script/dom/bindings/codegen/Bindings.conf | 1 | ||||
-rw-r--r-- | src/components/script/dom/bindings/codegen/CodegenRust.py | 32 | ||||
-rw-r--r-- | src/components/script/dom/bindings/codegen/Configuration.py | 1 | ||||
-rw-r--r-- | src/components/script/dom/bindings/codegen/Window.webidl | 2 | ||||
-rw-r--r-- | src/components/script/dom/bindings/utils.rs | 15 | ||||
-rw-r--r-- | src/components/script/dom/node.rs | 6 | ||||
-rw-r--r-- | src/components/script/dom/window.rs | 24 | ||||
-rw-r--r-- | src/components/script/script_task.rs | 60 | ||||
m--------- | src/support/spidermonkey/rust-mozjs | 0 | ||||
-rw-r--r-- | src/test/html/content/harness.js | 3 | ||||
-rw-r--r-- | src/test/html/content/test_global.html | 6 | ||||
-rw-r--r-- | src/test/html/content/test_global.js | 6 |
12 files changed, 91 insertions, 65 deletions
diff --git a/src/components/script/dom/bindings/codegen/Bindings.conf b/src/components/script/dom/bindings/codegen/Bindings.conf index f3f9ae8ab4c..5f6ed7de836 100644 --- a/src/components/script/dom/bindings/codegen/Bindings.conf +++ b/src/components/script/dom/bindings/codegen/Bindings.conf @@ -432,6 +432,7 @@ DOMInterfaces = { }], 'Window': { + 'createGlobal': True }, 'WindowProxy': { diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index 00e4736bca7..0e01fcef059 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -2210,11 +2210,17 @@ class CGDOMJSClass(CGThing): return "" def define(self): traceHook = "Some(%s)" % TRACE_HOOK_NAME if self.descriptor.customTrace else 'None' + if self.descriptor.createGlobal: + flags = "JSCLASS_IS_GLOBAL" + slots = "JSCLASS_GLOBAL_SLOT_COUNT + 1" + else: + flags = "0" + slots = "1" return """ static Class_name: [u8, ..%i] = %s; static Class: DOMJSClass = DOMJSClass { base: JSClass { name: &Class_name as *u8 as *libc::c_char, - flags: JSCLASS_IS_DOMJSCLASS | ((1 & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT), //JSCLASS_HAS_RESERVED_SLOTS(1), + flags: JSCLASS_IS_DOMJSCLASS | %s | (((%s) & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT), //JSCLASS_HAS_RESERVED_SLOTS(%s), addProperty: %s, /* addProperty */ delProperty: crust::JS_PropertyStub, /* delProperty */ getProperty: crust::JS_PropertyStub, /* getProperty */ @@ -2241,6 +2247,7 @@ static Class: DOMJSClass = DOMJSClass { }; """ % (len(self.descriptor.interface.identifier.name) + 1, str_to_const_array(self.descriptor.interface.identifier.name), + flags, slots, slots, #ADDPROPERTY_HOOK_NAME if self.descriptor.concrete and not self.descriptor.workers and self.descriptor.wrapperCache else 'crust::JS_PropertyStub', 'crust::JS_PropertyStub', FINALIZE_HOOK_NAME, traceHook, @@ -2455,7 +2462,7 @@ class CGAbstractMethod(CGThing): def definition_body(self): assert(False) # Override me! -def CreateBindingJSObject(descriptor, parent): +def CreateBindingJSObject(descriptor, parent=None): if descriptor.proxy: handler = """ //let cache = ptr::to_unsafe_ptr(aObject.get_wrappercache()); @@ -2470,17 +2477,20 @@ def CreateBindingJSObject(descriptor, parent): return ptr::null(); } -""" +""" % parent else: - create = """ let obj = JS_NewObject(aCx, &Class.base, proto, %s); - if obj.is_null() { + if descriptor.createGlobal: + create = " let obj = CreateDOMGlobal(aCx, &Class.base);\n" + else: + create = " let obj = JS_NewObject(aCx, &Class.base, proto, %s);\n" % parent + create += """ if obj.is_null() { return ptr::null(); } JS_SetReservedSlot(obj, DOM_OBJECT_SLOT as u32, RUST_PRIVATE_TO_JSVAL(squirrel_away(aObject) as *libc::c_void)); """ - return create % parent + return create class CGWrapWithCacheMethod(CGAbstractMethod): def __init__(self, descriptor): @@ -2495,7 +2505,8 @@ class CGWrapWithCacheMethod(CGAbstractMethod): return """ *aTriedToWrap = true; return aObject->GetJSObject();""" - return """ *aTriedToWrap = true; + if not self.descriptor.createGlobal: + return """ *aTriedToWrap = true; let mut parent = aObject.GetParentObject(aCx); let parent = WrapNativeParent(aCx, aScope, parent); if parent.is_null() { @@ -2517,6 +2528,13 @@ class CGWrapWithCacheMethod(CGAbstractMethod): (*cache).set_wrapper(obj); return obj;""" % (CreateBindingJSObject(self.descriptor, "parent")) + else: + return """ let cache = ptr::to_mut_unsafe_ptr(aObject.get_wrappercache()); +%s + let proto = GetProtoObject(aCx, obj, obj); + JS_SetPrototype(aCx, obj, proto); + (*cache).set_wrapper(obj); + return obj;""" % CreateBindingJSObject(self.descriptor) class CGWrapMethod(CGAbstractMethod): def __init__(self, descriptor): diff --git a/src/components/script/dom/bindings/codegen/Configuration.py b/src/components/script/dom/bindings/codegen/Configuration.py index d597da940e4..32918d272b3 100644 --- a/src/components/script/dom/bindings/codegen/Configuration.py +++ b/src/components/script/dom/bindings/codegen/Configuration.py @@ -143,6 +143,7 @@ class Descriptor(DescriptorProvider): self.concreteType = desc.get('concreteType', ifaceName) self.needsAbstract = desc.get('needsAbstract', []) self.hasInstanceInterface = desc.get('hasInstanceInterface', None) + self.createGlobal = desc.get('createGlobal', False) # Do something sane for JSObject if self.nativeType == "JSObject": diff --git a/src/components/script/dom/bindings/codegen/Window.webidl b/src/components/script/dom/bindings/codegen/Window.webidl index efa13f9c7b5..7b406f104c1 100644 --- a/src/components/script/dom/bindings/codegen/Window.webidl +++ b/src/components/script/dom/bindings/codegen/Window.webidl @@ -38,7 +38,7 @@ readonly attribute Element? frameElement; /*WindowProxy open(optional DOMString url = "about:blank", optional DOMString target = "_blank", optional DOMString features = "", optional boolean replace = false); getter WindowProxy (unsigned long index);*/ - getter object (DOMString name); + //getter object (DOMString name); // the user agent readonly attribute Navigator navigator; diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index 6adedbfad3d..3ea5eda38c7 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -29,7 +29,7 @@ use js::jsapi::{JS_NewStringCopyN, JS_DefineFunctions, JS_DefineProperty}; use js::jsapi::{JS_ValueToString, JS_GetReservedSlot, JS_SetReservedSlot}; use js::jsapi::{JSContext, JSObject, JSBool, jsid, JSClass, JSNative, JSTracer}; use js::jsapi::{JSFunctionSpec, JSPropertySpec, JSVal, JSPropertyDescriptor}; -use js::jsapi::{JSPropertyOp, JSStrictPropertyOp}; +use js::jsapi::{JSPropertyOp, JSStrictPropertyOp, JS_NewGlobalObject, JS_InitStandardClasses}; use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType; use js::rust::Compartment; use js::{JSPROP_ENUMERATE, JSVAL_NULL}; @@ -845,3 +845,16 @@ pub fn HasPropertyOnPrototype(cx: *JSContext, proxy: *JSObject, id: jsid) -> boo let mut found = false; return !GetPropertyOnPrototype(cx, proxy, id, &mut found, ptr::null()) || found; } + +#[fixed_stack_segment] +pub fn CreateDOMGlobal(cx: *JSContext, class: *JSClass) -> *JSObject { + unsafe { + let obj = JS_NewGlobalObject(cx, class, ptr::null()); + if obj.is_null() { + return ptr::null(); + } + JS_InitStandardClasses(cx, obj); + initialize_global(obj); + obj + } +} diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 0c564cd4223..a1ec371e905 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -21,7 +21,6 @@ use std::cast::transmute; use std::libc::c_void; use extra::arc::Arc; use js::jsapi::{JSObject, JSContext}; -use js::rust::Compartment; use netsurfcss::util::VoidPtrLike; use newcss::complete::CompleteSelectResults; use servo_util::tree::{TreeNode, TreeNodeRef}; @@ -628,11 +627,6 @@ impl VoidPtrLike for AbstractNode<LayoutView> { } } -pub fn define_bindings(compartment: @mut Compartment) { - bindings::utils::initialize_global(compartment.global_obj.ptr); - bindings::codegen::RegisterBindings::Register(compartment); -} - impl CacheableWrapper for Node<ScriptView> { fn get_wrappercache(&mut self) -> &mut WrapperCache { unsafe { cast::transmute(&mut self.wrapper) } diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs index bc3993d3f4e..00c4b63f539 100644 --- a/src/components/script/dom/window.rs +++ b/src/components/script/dom/window.rs @@ -14,7 +14,7 @@ use script_task::{ExitMsg, FireTimerMsg, Page, ScriptChan}; use servo_msg::compositor_msg::ScriptListener; use js::glue::*; -use js::jsapi::{JSObject, JSContext}; +use js::jsapi::{JSObject, JSContext, JS_DefineProperty}; use js::jsapi::{JSPropertyOp, JSStrictPropertyOp}; use js::{JSVAL_NULL, JSPROP_ENUMERATE}; @@ -128,10 +128,6 @@ impl Window { pub fn ShowModalDialog(&self, _cx: *JSContext, _url: &DOMString, _argument: JSVal) -> JSVal { JSVAL_NULL } - - pub fn NamedGetter(&self, _cx: *JSContext, _name: &DOMString, _found: &mut bool) -> *JSObject { - ptr::null() - } } impl CacheableWrapper for Window { @@ -177,7 +173,7 @@ impl Window { } #[fixed_stack_segment] - pub fn new(page: *mut Page, script_chan: ScriptChan, compositor: @ScriptListener) + pub fn new(cx: *JSContext, page: *mut Page, script_chan: ScriptChan, compositor: @ScriptListener) -> @mut Window { let script_chan_clone = script_chan.clone(); let win = @mut Window { @@ -203,14 +199,16 @@ impl Window { unsafe { // TODO(tkuehn): This just grabs the top-level page. Need to handle subframes. - let compartment = (*page).js_info.get_ref().js_compartment; let cache = ptr::to_unsafe_ptr(win.get_wrappercache()); - win.wrap_object_shared(compartment.cx.ptr, ptr::null()); //XXXjdm proper scope - compartment.define_property(~"window", - RUST_OBJECT_TO_JSVAL((*cache).wrapper), - GetJSClassHookStubPointer(PROPERTY_STUB) as JSPropertyOp, - GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as JSStrictPropertyOp, - JSPROP_ENUMERATE); + win.wrap_object_shared(cx, ptr::null()); //XXXjdm proper scope + let global = (*cache).wrapper; + do "window".to_c_str().with_ref |name| { + JS_DefineProperty(cx, global, name, + RUST_OBJECT_TO_JSVAL(global), + Some(GetJSClassHookStubPointer(PROPERTY_STUB) as JSPropertyOp), + Some(GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as JSStrictPropertyOp), + JSPROP_ENUMERATE); + } } win } diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 86524a3704d..759d37a6dc4 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -7,12 +7,12 @@ use servo_msg::compositor_msg::{ScriptListener, Loading, PerformingLayout}; use servo_msg::compositor_msg::FinishedLoading; -use dom::bindings::utils::GlobalStaticData; +use dom::bindings::codegen::RegisterBindings; +use dom::bindings::utils::{CacheableWrapper, GlobalStaticData}; use dom::document::AbstractDocument; use dom::element::Element; use dom::event::{Event_, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent, MouseUpEvent}; use dom::htmldocument::HTMLDocument; -use dom::node::{define_bindings}; use dom::window::Window; use layout_interface::{AddStylesheetMsg, DocumentDamage}; use layout_interface::{DocumentDamageLevel, HitTestQuery, HitTestResponse, LayoutQuery}; @@ -29,7 +29,7 @@ use std::cell::Cell; use std::comm; use std::comm::{Port, SharedChan}; use std::io::read_whole_file; -use std::ptr::null; +use std::ptr; use std::task::{SingleThreaded, task}; use std::util::replace; use dom::window::TimerData; @@ -38,9 +38,9 @@ use html::hubbub_html_parser::HtmlParserResult; use html::hubbub_html_parser::{HtmlDiscoveredStyle, HtmlDiscoveredIFrame, HtmlDiscoveredScript}; use html::hubbub_html_parser; use js::JSVAL_NULL; -use js::global::{global_class, debug_fns}; +use js::global::debug_fns; use js::glue::RUST_JSVAL_TO_OBJECT; -use js::jsapi::JSContext; +use js::jsapi::{JSContext, JSObject}; use js::jsapi::{JS_CallFunctionValue, JS_GetContextPrivate}; use js::rust::{Compartment, Cx}; use js; @@ -289,14 +289,14 @@ impl Page { self.reflow(goal, script_chan, compositor) } - pub fn initialize_js_info(&mut self, js_context: @Cx) { + pub fn initialize_js_info(&mut self, js_context: @Cx, global: *JSObject) { // Note that the order that these variables are initialized is _not_ arbitrary. Switching them around // can -- and likely will -- lead to things breaking. js_context.set_default_options_and_version(); js_context.set_logging_error_reporter(); - let compartment = match js_context.new_compartment(global_class) { + let compartment = match js_context.new_compartment_with_global(global) { Ok(c) => c, Err(()) => fail!("Failed to create a compartment"), }; @@ -313,7 +313,6 @@ impl Page { self.js_info = Some(JSPageInfo { dom_static: GlobalStaticData(), - bindings_initialized: false, js_compartment: compartment, js_context: js_context, }); @@ -332,8 +331,6 @@ pub struct Frame { pub struct JSPageInfo { /// Global static data related to the DOM. dom_static: GlobalStaticData, - /// Flag indicating if the JS bindings have been initialized. - bindings_initialized: bool, /// The JavaScript compartment for the origin associated with the script task. js_compartment: @mut Compartment, /// The JavaScript context. @@ -403,7 +400,6 @@ impl ScriptTask { js_runtime: js_runtime, }; - script_task.page_tree.page.initialize_js_info(script_task.js_runtime.cx()); script_task } @@ -477,8 +473,6 @@ impl ScriptTask { whose parent has a PipelineId which does not correspond to a pipeline in the script task's page tree. This is a bug."); let new_page_tree = PageTree::new(new_id, layout_chan, size_future); - new_page_tree.page.initialize_js_info(self.js_runtime.cx()); - parent_page_tree.inner.push(new_page_tree); } @@ -522,7 +516,7 @@ impl ScriptTask { this_value, timer_data.funval, 0, - null(), + ptr::null(), &rval); } @@ -588,23 +582,28 @@ impl ScriptTask { return; } } - - { - let js_info = page.js_info.get_mut_ref(); - // Define the script DOM bindings. + + let cx = self.js_runtime.cx(); + // Create the window and document objects. + let window = { + // Need an extra block here due to Rust #6248 // - // FIXME: Can this be done earlier, to save the flag? - if !js_info.bindings_initialized { - define_bindings(js_info.js_compartment); - js_info.bindings_initialized = true; - } - } + // FIXME(Servo #655): Unrelated to the Rust #6248 warning, this is fundamentally + // unsafe because the box could go away or get moved while we're holding this raw + // pointer. We think it's safe here because the main task will hold onto the box, + // and because the current refcounting implementation of @ doesn't move. + let page = &mut *page; + Window::new(cx.ptr, page, self.chan.clone(), self.compositor) + }; + page.initialize_js_info(cx, window.get_wrappercache().get_wrapper()); + + RegisterBindings::Register(page.js_info.get_ref().js_compartment); self.compositor.set_ready_state(Loading); // Parse HTML. // // Note: We can parse the next document in parallel with any previous documents. - let html_parsing_result = hubbub_html_parser::parse_html(page.js_info.get_ref().js_compartment.cx.ptr, + let html_parsing_result = hubbub_html_parser::parse_html(cx.ptr, url.clone(), self.resource_task.clone(), self.image_cache_task.clone(), @@ -613,17 +612,6 @@ impl ScriptTask { let HtmlParserResult {root, discovery_port} = html_parsing_result; - // Create the window and document objects. - let window = { - // Need an extra block here due to Rust #6248 - // - // FIXME(Servo #655): Unrelated to the Rust #6248 warning, this is fundamentally - // unsafe because the box could go away or get moved while we're holding this raw - // pointer. We think it's safe here because the main task will hold onto the box, - // and because the current refcounting implementation of @ doesn't move. - let page = &mut *page; - Window::new(page, self.chan.clone(), self.compositor) - }; let document = HTMLDocument::new(root, Some(window)); // Tie the root into the document. diff --git a/src/support/spidermonkey/rust-mozjs b/src/support/spidermonkey/rust-mozjs -Subproject b7121da7fcb5eba84b563118db49a43279c88ee +Subproject 353ef00db32e526f054f1f7899cd93425cfb1c5 diff --git a/src/test/html/content/harness.js b/src/test/html/content/harness.js index de2eec8bcf9..ab4bf17ce70 100644 --- a/src/test/html/content/harness.js +++ b/src/test/html/content/harness.js @@ -1,5 +1,6 @@ function _fail(s) { - window.alert("TEST-UNEXPECTED-FAIL | " + s); + // string split to avoid problems with tests that end up printing the value of window._fail. + window.alert("TEST-UNEXPECTED" + "-FAIL | " + s); } function _pass(s) { diff --git a/src/test/html/content/test_global.html b/src/test/html/content/test_global.html new file mode 100644 index 00000000000..c75ba555e66 --- /dev/null +++ b/src/test/html/content/test_global.html @@ -0,0 +1,6 @@ +<html> +<head> +<script src="harness.js"></script> +<script src="test_global.js"></script> +</head> +</html> diff --git a/src/test/html/content/test_global.js b/src/test/html/content/test_global.js new file mode 100644 index 00000000000..d6d84a8d474 --- /dev/null +++ b/src/test/html/content/test_global.js @@ -0,0 +1,6 @@ +is(window, window.window); +is(window, this); +for (var key in this) { + is(this[key], window[key]); +} +finish();
\ No newline at end of file |