Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the entry global. #14840

Merged
merged 1 commit into from
Jan 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions components/script/dom/bindings/callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use dom::bindings::error::{Error, Fallible, report_pending_exception};
use dom::bindings::js::Root;
use dom::bindings::reflector::DomObject;
use dom::bindings::settings_stack::AutoEntryScript;
use dom::globalscope::GlobalScope;
use js::jsapi::{Heap, MutableHandleObject};
use js::jsapi::{IsCallable, JSContext, JSObject, JS_WrapObject};
Expand All @@ -16,6 +17,7 @@ use js::jsapi::JS_GetProperty;
use js::jsval::{JSVal, UndefinedValue};
use std::default::Default;
use std::ffi::CString;
use std::mem::drop;
use std::ptr;
use std::rc::Rc;

Expand Down Expand Up @@ -156,6 +158,9 @@ pub struct CallSetup {
old_compartment: *mut JSCompartment,
/// The exception handling used for the call.
handling: ExceptionHandling,
/// https://heycam.github.io/webidl/#es-invoking-callback-functions
/// steps 8 and 18.2.
entry_script: Option<AutoEntryScript>,
}

impl CallSetup {
Expand All @@ -167,11 +172,13 @@ impl CallSetup {
let global = unsafe { GlobalScope::from_object(callback.callback()) };
let cx = global.get_cx();

let aes = AutoEntryScript::new(&global);
CallSetup {
exception_global: global,
cx: cx,
old_compartment: unsafe { JS_EnterCompartment(cx, callback.callback()) },
handling: handling,
entry_script: Some(aes),
}
}

Expand All @@ -190,6 +197,7 @@ impl Drop for CallSetup {
self.exception_global.reflector().get_jsobject().get());
report_pending_exception(self.cx, true);
}
drop(self.entry_script.take().unwrap());
}
}
}
1 change: 1 addition & 0 deletions components/script/dom/bindings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ pub mod num;
pub mod proxyhandler;
pub mod refcounted;
pub mod reflector;
pub mod settings_stack;
pub mod str;
pub mod structuredclone;
pub mod trace;
Expand Down
70 changes: 70 additions & 0 deletions components/script/dom/bindings/settings_stack.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::js::{JS, Root};
use dom::bindings::trace::JSTraceable;
use dom::globalscope::GlobalScope;
use js::jsapi::JSTracer;
use std::cell::RefCell;

thread_local!(static STACK: RefCell<Vec<StackEntry>> = RefCell::new(Vec::new()));

#[allow(unrooted_must_root)]
#[derive(JSTraceable)]
struct StackEntry {
global: JS<GlobalScope>,
}

/// Traces the script settings stack.
pub unsafe fn trace(tracer: *mut JSTracer) {
STACK.with(|stack| {
stack.borrow().trace(tracer);
})
}

/// RAII struct that pushes and pops entries from the script settings stack.
pub struct AutoEntryScript {
global: *const GlobalScope,
}

impl AutoEntryScript {
/// https://html.spec.whatwg.org/multipage/#prepare-to-run-script
pub fn new(global: &GlobalScope) -> Self {
STACK.with(|stack| {
trace!("Prepare to run script with {:p}", global);
let mut stack = stack.borrow_mut();
stack.push(StackEntry {
global: JS::from_ref(global),
});
AutoEntryScript {
global: global as *const _,
}
})
}
}

impl Drop for AutoEntryScript {
/// https://html.spec.whatwg.org/multipage/#clean-up-after-running-script
fn drop(&mut self) {
STACK.with(|stack| {
let mut stack = stack.borrow_mut();
let entry = stack.pop().unwrap();
assert_eq!(&*entry.global as *const GlobalScope,
self.global,
"Dropped AutoEntryScript out of order.");
trace!("Clean up after running script with {:p}", self.global);
})
}
}

/// Returns the ["entry"] global object.
///
/// ["entry"]: https://html.spec.whatwg.org/multipage/#entry
pub fn entry_global() -> Root<GlobalScope> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: could you make that a static method on AutoEntryScript? Less things to import that way.

STACK.with(|stack| {
stack.borrow()
.last()
.map(|entry| Root::from_ref(&*entry.global))
}).unwrap()
}
9 changes: 9 additions & 0 deletions components/script/dom/globalscope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use dom::bindings::error::{ErrorInfo, report_pending_exception};
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::reflector::DomObject;
use dom::bindings::settings_stack::{AutoEntryScript, entry_global};
use dom::bindings::str::DOMString;
use dom::crypto::Crypto;
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
Expand Down Expand Up @@ -365,6 +366,7 @@ impl GlobalScope {
let filename = CString::new(filename).unwrap();

let _ac = JSAutoCompartment::new(cx, globalhandle.get());
let _aes = AutoEntryScript::new(self);
let options = CompileOptionsWrapper::new(cx, filename.as_ptr(), 1);
unsafe {
if !Evaluate2(cx, options.ptr, code.as_ptr(),
Expand Down Expand Up @@ -519,6 +521,13 @@ impl GlobalScope {
global_scope_from_global(global)
}
}

/// Returns the ["entry"] global object.
///
/// ["entry"]: https://html.spec.whatwg.org/multipage/#entry
pub fn entry() -> Root<Self> {
entry_global()
}
}

fn timestamp_in_ms(time: Timespec) -> u64 {
Expand Down
4 changes: 4 additions & 0 deletions components/script/dom/testbinding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,10 @@ impl TestBindingMethods for TestBinding {
}

fn Panic(&self) { panic!("explicit panic from script") }

fn EntryGlobal(&self) -> Root<GlobalScope> {
GlobalScope::entry()
}
}

impl TestBinding {
Expand Down
2 changes: 2 additions & 0 deletions components/script/dom/webidls/TestBinding.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,8 @@ interface TestBinding {
void resolvePromiseDelayed(Promise<any> p, DOMString value, unsigned long long ms);

void panic();

GlobalScope entryGlobal();
};

callback SimpleCallback = void(any value);
Expand Down
2 changes: 2 additions & 0 deletions components/script/dom/workerglobalscope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::DomObject;
use dom::bindings::settings_stack::AutoEntryScript;
use dom::bindings::str::DOMString;
use dom::crypto::Crypto;
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
Expand Down Expand Up @@ -331,6 +332,7 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
impl WorkerGlobalScope {
#[allow(unsafe_code)]
pub fn execute_script(&self, source: DOMString) {
let _aes = AutoEntryScript::new(self.upcast());
rooted!(in(self.runtime.cx()) let mut rval = UndefinedValue());
match self.runtime.evaluate_script(
self.reflector().get_jsobject(), &source, self.worker_url.as_str(), 1, rval.handle_mut()) {
Expand Down
2 changes: 2 additions & 0 deletions components/script/script_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::PromiseBinding::PromiseJobCallback;
use dom::bindings::js::{Root, RootCollection, RootCollectionPtr, trace_roots};
use dom::bindings::refcounted::{LiveDOMReferences, trace_refcounted_objects};
use dom::bindings::settings_stack;
use dom::bindings::trace::{JSTraceable, trace_traceables};
use dom::bindings::utils::DOM_CALLBACKS;
use dom::globalscope::GlobalScope;
Expand Down Expand Up @@ -474,6 +475,7 @@ unsafe extern fn trace_rust_roots(tr: *mut JSTracer, _data: *mut os::raw::c_void
trace_thread(tr);
trace_traceables(tr);
trace_roots(tr);
settings_stack::trace(tr);
debug!("done custom root handler");
}

Expand Down
12 changes: 12 additions & 0 deletions tests/wpt/mozilla/meta/MANIFEST.json
Original file line number Diff line number Diff line change
Expand Up @@ -8408,6 +8408,18 @@
"url": "/_mozilla/mozilla/global.html"
}
],
"mozilla/globals/entry.html": [
{
"path": "mozilla/globals/entry.html",
"url": "/_mozilla/mozilla/globals/entry.html"
}
],
"mozilla/globals/entry.worker.js": [
{
"path": "mozilla/globals/entry.worker.js",
"url": "/_mozilla/mozilla/globals/entry.worker.html"
}
],
"mozilla/hit_test_nested_sc.html": [
{
"path": "mozilla/hit_test_nested_sc.html",
Expand Down
3 changes: 3 additions & 0 deletions tests/wpt/mozilla/meta/mozilla/globals/entry.html.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[entry.html]
type: testharness
prefs: [dom.testbinding.enabled:true]
3 changes: 3 additions & 0 deletions tests/wpt/mozilla/meta/mozilla/globals/entry.worker.js.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[entry.worker.html]
type: testharness
prefs: [dom.testbinding.enabled:true]
2 changes: 2 additions & 0 deletions tests/wpt/mozilla/tests/mozilla/globals/empty.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<!DOCTYPE html>
<title>Empty page</title>
16 changes: 16 additions & 0 deletions tests/wpt/mozilla/tests/mozilla/globals/entry.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Entry page</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
var entry_test = async_test("Entry global");
var loaded = function() {
entry_test.step(function() {
var entry = document.querySelector("#incumbent").contentWindow.get_entry();
assert_equals(entry, window);
});
entry_test.done();
}
</script>
<iframe id="incumbent" src="incumbent.html" onload="loaded()"></iframe>
9 changes: 9 additions & 0 deletions tests/wpt/mozilla/tests/mozilla/globals/entry.worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
importScripts("/resources/testharness.js");

test(function() {
var entry = (new TestBinding()).entryGlobal();
assert_equals(entry, self);
});


done();
13 changes: 13 additions & 0 deletions tests/wpt/mozilla/tests/mozilla/globals/incumbent.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<title>Incumbent page</title>

<iframe src="empty.html" id="current"></iframe>
<iframe src="empty.html" id="relevant"></iframe>
<script>
function get_entry() {
var current = document.querySelector("#current").contentWindow;
var relevant = document.querySelector("#relevant").contentWindow;

return current.TestBinding.prototype.entryGlobal.call(new relevant.TestBinding());
}
</script>