aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/script/dom/bindings/codegen/Bindings.conf1
-rw-r--r--src/components/script/dom/bindings/codegen/CodegenRust.py32
-rw-r--r--src/components/script/dom/bindings/codegen/Configuration.py1
-rw-r--r--src/components/script/dom/bindings/codegen/Window.webidl2
-rw-r--r--src/components/script/dom/bindings/utils.rs15
-rw-r--r--src/components/script/dom/node.rs6
-rw-r--r--src/components/script/dom/window.rs24
-rw-r--r--src/components/script/script_task.rs60
m---------src/support/spidermonkey/rust-mozjs0
-rw-r--r--src/test/html/content/harness.js3
-rw-r--r--src/test/html/content/test_global.html6
-rw-r--r--src/test/html/content/test_global.js6
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