aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/abstractworker.rs28
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py51
-rw-r--r--components/script/dom/bindings/codegen/Configuration.py2
-rw-r--r--components/script/dom/bindings/codegen/GlobalGen.py30
-rw-r--r--components/script/dom/bindings/codegen/api.html.template6
-rw-r--r--components/script/dom/bindings/codegen/apis.html.template35
-rw-r--r--components/script/dom/bindings/codegen/interface.html.template1
-rw-r--r--components/script/dom/bindings/codegen/parser/WebIDL.py797
-rw-r--r--components/script/dom/bindings/codegen/parser/abstract.patch12
-rw-r--r--components/script/dom/bindings/codegen/parser/debug.patch20
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_conditional_dictionary_member.py110
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_namespace.py223
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_securecontext_extended_attribute.py318
-rwxr-xr-xcomponents/script/dom/bindings/codegen/parser/update.sh2
-rw-r--r--components/script/dom/bindings/codegen/property.html.template3
-rw-r--r--components/script/dom/bindings/global.rs28
-rw-r--r--components/script/dom/bindings/str.rs37
-rw-r--r--components/script/dom/bindings/trace.rs5
-rw-r--r--components/script/dom/blob.rs173
-rw-r--r--components/script/dom/bluetoothremotegattcharacteristic.rs2
-rw-r--r--components/script/dom/bluetoothremotegattdescriptor.rs2
-rw-r--r--components/script/dom/bluetoothremotegattservice.rs2
-rw-r--r--components/script/dom/dedicatedworkerglobalscope.rs57
-rw-r--r--components/script/dom/document.rs93
-rw-r--r--components/script/dom/documenttype.rs5
-rw-r--r--components/script/dom/domimplementation.rs4
-rw-r--r--components/script/dom/domparser.rs8
-rw-r--r--components/script/dom/element.rs13
-rw-r--r--components/script/dom/event.rs38
-rw-r--r--components/script/dom/file.rs10
-rw-r--r--components/script/dom/filereader.rs62
-rw-r--r--components/script/dom/headers.rs251
-rw-r--r--components/script/dom/history.rs70
-rw-r--r--components/script/dom/htmlanchorelement.rs5
-rw-r--r--components/script/dom/htmlappletelement.rs5
-rw-r--r--components/script/dom/htmlareaelement.rs5
-rw-r--r--components/script/dom/htmlaudioelement.rs5
-rw-r--r--components/script/dom/htmlbaseelement.rs5
-rw-r--r--components/script/dom/htmlbodyelement.rs5
-rw-r--r--components/script/dom/htmlbrelement.rs5
-rw-r--r--components/script/dom/htmlbuttonelement.rs5
-rw-r--r--components/script/dom/htmlcanvaselement.rs5
-rw-r--r--components/script/dom/htmlcollection.rs2
-rw-r--r--components/script/dom/htmldataelement.rs5
-rw-r--r--components/script/dom/htmldatalistelement.rs5
-rw-r--r--components/script/dom/htmldetailselement.rs10
-rw-r--r--components/script/dom/htmldialogelement.rs5
-rw-r--r--components/script/dom/htmldirectoryelement.rs5
-rw-r--r--components/script/dom/htmldlistelement.rs5
-rw-r--r--components/script/dom/htmlelement.rs5
-rw-r--r--components/script/dom/htmlembedelement.rs5
-rw-r--r--components/script/dom/htmlfieldsetelement.rs5
-rw-r--r--components/script/dom/htmlfontelement.rs5
-rw-r--r--components/script/dom/htmlformelement.rs9
-rw-r--r--components/script/dom/htmlframeelement.rs5
-rw-r--r--components/script/dom/htmlframesetelement.rs5
-rw-r--r--components/script/dom/htmlheadelement.rs5
-rw-r--r--components/script/dom/htmlheadingelement.rs5
-rw-r--r--components/script/dom/htmlhrelement.rs5
-rw-r--r--components/script/dom/htmlhtmlelement.rs5
-rw-r--r--components/script/dom/htmliframeelement.rs210
-rw-r--r--components/script/dom/htmlimageelement.rs14
-rw-r--r--components/script/dom/htmlinputelement.rs35
-rw-r--r--components/script/dom/htmllabelelement.rs5
-rw-r--r--components/script/dom/htmllegendelement.rs5
-rw-r--r--components/script/dom/htmllielement.rs5
-rw-r--r--components/script/dom/htmllinkelement.rs8
-rw-r--r--components/script/dom/htmlmapelement.rs5
-rw-r--r--components/script/dom/htmlmediaelement.rs20
-rw-r--r--components/script/dom/htmlmetaelement.rs8
-rw-r--r--components/script/dom/htmlmeterelement.rs5
-rw-r--r--components/script/dom/htmlmodelement.rs5
-rw-r--r--components/script/dom/htmlobjectelement.rs5
-rw-r--r--components/script/dom/htmlolistelement.rs5
-rw-r--r--components/script/dom/htmloptgroupelement.rs5
-rw-r--r--components/script/dom/htmloptionelement.rs5
-rw-r--r--components/script/dom/htmloutputelement.rs5
-rw-r--r--components/script/dom/htmlparagraphelement.rs5
-rw-r--r--components/script/dom/htmlparamelement.rs5
-rw-r--r--components/script/dom/htmlpreelement.rs5
-rw-r--r--components/script/dom/htmlprogresselement.rs5
-rw-r--r--components/script/dom/htmlquoteelement.rs5
-rw-r--r--components/script/dom/htmlscriptelement.rs235
-rw-r--r--components/script/dom/htmlselectelement.rs5
-rw-r--r--components/script/dom/htmlsourceelement.rs5
-rw-r--r--components/script/dom/htmlspanelement.rs5
-rw-r--r--components/script/dom/htmlstyleelement.rs8
-rw-r--r--components/script/dom/htmltablecaptionelement.rs5
-rw-r--r--components/script/dom/htmltablecolelement.rs5
-rw-r--r--components/script/dom/htmltableelement.rs65
-rw-r--r--components/script/dom/htmltableheadercellelement.rs5
-rw-r--r--components/script/dom/htmltablesectionelement.rs5
-rw-r--r--components/script/dom/htmltemplateelement.rs5
-rw-r--r--components/script/dom/htmltextareaelement.rs11
-rw-r--r--components/script/dom/htmltimeelement.rs5
-rw-r--r--components/script/dom/htmltitleelement.rs5
-rw-r--r--components/script/dom/htmltrackelement.rs5
-rw-r--r--components/script/dom/htmlulistelement.rs5
-rw-r--r--components/script/dom/htmlunknownelement.rs5
-rw-r--r--components/script/dom/htmlvideoelement.rs5
-rw-r--r--components/script/dom/mod.rs2
-rw-r--r--components/script/dom/node.rs57
-rw-r--r--components/script/dom/serviceworker.rs81
-rw-r--r--components/script/dom/serviceworkercontainer.rs2
-rw-r--r--components/script/dom/serviceworkerglobalscope.rs269
-rw-r--r--components/script/dom/serviceworkerregistration.rs44
-rw-r--r--components/script/dom/servohtmlparser.rs17
-rw-r--r--components/script/dom/storage.rs8
-rw-r--r--components/script/dom/testbinding.rs38
-rw-r--r--components/script/dom/url.rs22
-rw-r--r--components/script/dom/userscripts.rs9
-rw-r--r--components/script/dom/webidls/DedicatedWorkerGlobalScope.webidl2
-rw-r--r--components/script/dom/webidls/Document.webidl2
-rw-r--r--components/script/dom/webidls/HTMLAnchorElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLAppletElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLAreaElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLAudioElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLBRElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLBaseElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLBodyElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLButtonElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLDListElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLDataElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLDataListElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLDetailsElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLDialogElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLDirectoryElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLDivElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLEmbedElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLFieldSetElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLFontElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLFrameElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLFrameSetElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLParagraphElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLParamElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLPreElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLProgressElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLQuoteElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLSelectElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLSourceElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLSpanElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLStyleElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLTableCaptionElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLTableCellElement.webidl2
-rw-r--r--components/script/dom/webidls/HTMLTableColElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLTableDataCellElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLTableElement.webidl3
-rw-r--r--components/script/dom/webidls/HTMLTableHeaderCellElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLTableRowElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLTableSectionElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLTemplateElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLTextAreaElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLTimeElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLTitleElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLTrackElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLUListElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLUnknownElement.webidl1
-rw-r--r--components/script/dom/webidls/HTMLVideoElement.webidl1
-rw-r--r--components/script/dom/webidls/Headers.webidl22
-rw-r--r--components/script/dom/webidls/History.webidl18
-rw-r--r--components/script/dom/webidls/ServiceWorkerGlobalScope.webidl3
-rw-r--r--components/script/dom/webidls/TestBinding.webidl16
-rw-r--r--components/script/dom/webidls/Window.webidl2
-rw-r--r--components/script/dom/webidls/WorkerGlobalScope.webidl6
-rw-r--r--components/script/dom/webidls/WorkerLocation.webidl2
-rw-r--r--components/script/dom/webidls/WorkerNavigator.webidl2
-rw-r--r--components/script/dom/websocket.rs8
-rw-r--r--components/script/dom/window.rs72
-rw-r--r--components/script/dom/worker.rs46
-rw-r--r--components/script/dom/workerglobalscope.rs116
-rw-r--r--components/script/dom/xmldocument.rs4
-rw-r--r--components/script/dom/xmlhttprequest.rs38
172 files changed, 2899 insertions, 1460 deletions
diff --git a/components/script/dom/abstractworker.rs b/components/script/dom/abstractworker.rs
index f9ff583a0dd..28c755d4f03 100644
--- a/components/script/dom/abstractworker.rs
+++ b/components/script/dom/abstractworker.rs
@@ -8,40 +8,14 @@ use dom::bindings::str::DOMString;
use dom::bindings::structuredclone::StructuredCloneData;
use js::jsapi::{JSRuntime, JS_RequestInterruptCallback};
use js::rust::Runtime;
-use msg::constellation_msg::{PipelineId, ReferrerPolicy};
-use net_traits::{LoadOrigin, RequestSource};
use script_runtime::CommonScriptMsg;
-use url::Url;
/// Messages used to control the worker event loops
pub enum WorkerScriptMsg {
/// Common variants associated with the script messages
Common(CommonScriptMsg),
/// Message sent through Worker.postMessage
- DOMMessage(StructuredCloneData),
-}
-
-#[derive(Clone)]
-pub struct WorkerScriptLoadOrigin {
- pub referrer_url: Option<Url>,
- pub referrer_policy: Option<ReferrerPolicy>,
- pub request_source: RequestSource,
- pub pipeline_id: Option<PipelineId>
-}
-
-impl LoadOrigin for WorkerScriptLoadOrigin {
- fn referrer_url(&self) -> Option<Url> {
- self.referrer_url.clone()
- }
- fn referrer_policy(&self) -> Option<ReferrerPolicy> {
- self.referrer_policy.clone()
- }
- fn request_source(&self) -> RequestSource {
- self.request_source.clone()
- }
- fn pipeline_id(&self) -> Option<PipelineId> {
- self.pipeline_id.clone()
- }
+ DOMMessage(StructuredCloneData)
}
pub struct SimpleWorkerErrorHandler<T: Reflectable> {
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index 2513b5b92eb..8360dfc322a 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -8,6 +8,7 @@ from collections import defaultdict
from itertools import groupby
import operator
+import os
import re
import string
import textwrap
@@ -87,6 +88,11 @@ def stripTrailingWhitespace(text):
return '\n'.join(lines) + tail
+def innerSequenceType(type):
+ assert type.isSequence()
+ return type.inner.inner if type.nullable() else type.inner
+
+
def MakeNativeName(name):
return name[0].upper() + name[1:]
@@ -713,7 +719,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
raise TypeError("Can't handle array arguments yet")
if type.isSequence():
- innerInfo = getJSToNativeConversionInfo(type.unroll(), descriptorProvider)
+ innerInfo = getJSToNativeConversionInfo(innerSequenceType(type), descriptorProvider)
declType = CGWrapper(innerInfo.declType, pre="Vec<", post=">")
config = getConversionConfigForType(type, isEnforceRange, isClamp, treatNullAs)
@@ -1302,8 +1308,7 @@ def getRetvalDeclarationForType(returnType, descriptorProvider):
if returnType.isObject() or returnType.isSpiderMonkeyInterface():
return CGGeneric("*mut JSObject")
if returnType.isSequence():
- inner = returnType.unroll()
- result = getRetvalDeclarationForType(inner, descriptorProvider)
+ result = getRetvalDeclarationForType(innerSequenceType(returnType), descriptorProvider)
result = CGWrapper(result, pre="Vec<", post=">")
if returnType.nullable():
result = CGWrapper(result, pre="Option<", post=">")
@@ -2072,7 +2077,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, config):
'dom::bindings::conversions::root_from_handlevalue',
'dom::bindings::error::throw_not_in_union',
'dom::bindings::js::Root',
- 'dom::bindings::str::{DOMString, USVString}',
+ 'dom::bindings::str::{ByteString, DOMString, USVString}',
'dom::types::*',
'js::jsapi::JSContext',
'js::jsapi::{HandleValue, MutableHandleValue}',
@@ -3743,12 +3748,15 @@ def getUnionTypeTemplateVars(type, descriptorProvider):
typeName = name
elif type.isSequence():
name = type.name
- inner = getUnionTypeTemplateVars(type.unroll(), descriptorProvider)
+ inner = getUnionTypeTemplateVars(innerSequenceType(type), descriptorProvider)
typeName = "Vec<" + inner["typeName"] + ">"
elif type.isArray():
name = str(type)
# XXXjdm dunno about typeName here
typeName = "/*" + type.name + "*/"
+ elif type.isByteString():
+ name = type.name
+ typeName = "ByteString"
elif type.isDOMString():
name = type.name
typeName = "DOMString"
@@ -6437,3 +6445,36 @@ impl %(base)s {
# Done.
return curr
+
+ @staticmethod
+ def SupportedDomApis(config):
+ descriptors = config.getDescriptors(isExposedConditionally=False)
+
+ base_path = os.path.join('dom', 'bindings', 'codegen')
+ with open(os.path.join(base_path, 'apis.html.template')) as f:
+ base_template = f.read()
+ with open(os.path.join(base_path, 'api.html.template')) as f:
+ api_template = f.read()
+ with open(os.path.join(base_path, 'property.html.template')) as f:
+ property_template = f.read()
+ with open(os.path.join(base_path, 'interface.html.template')) as f:
+ interface_template = f.read()
+
+ apis = []
+ interfaces = []
+ for descriptor in descriptors:
+ props = []
+ for m in descriptor.interface.members:
+ if PropertyDefiner.getStringAttr(m, 'Pref') or \
+ PropertyDefiner.getStringAttr(m, 'Func') or \
+ (m.isMethod() and m.isIdentifierLess()):
+ continue
+ display = m.identifier.name + ('()' if m.isMethod() else '')
+ props += [property_template.replace('${name}', display)]
+ name = descriptor.interface.identifier.name
+ apis += [(api_template.replace('${interface}', name)
+ .replace('${properties}', '\n'.join(props)))]
+ interfaces += [interface_template.replace('${interface}', name)]
+
+ return CGGeneric((base_template.replace('${apis}', '\n'.join(apis))
+ .replace('${interfaces}', '\n'.join(interfaces))))
diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py
index 9a39b1bc623..4074736a462 100644
--- a/components/script/dom/bindings/codegen/Configuration.py
+++ b/components/script/dom/bindings/codegen/Configuration.py
@@ -87,6 +87,8 @@ class Configuration:
getter = lambda x: x.interface.isJSImplemented()
elif key == 'isGlobal':
getter = lambda x: x.isGlobal()
+ elif key == 'isExposedConditionally':
+ getter = lambda x: x.interface.isExposedConditionally()
else:
getter = lambda x: getattr(x, key)
curr = filter(lambda x: getter(x) == val, curr)
diff --git a/components/script/dom/bindings/codegen/GlobalGen.py b/components/script/dom/bindings/codegen/GlobalGen.py
index 72a2faa71e4..23779d9e6d5 100644
--- a/components/script/dom/bindings/codegen/GlobalGen.py
+++ b/components/script/dom/bindings/codegen/GlobalGen.py
@@ -32,6 +32,8 @@ def main():
o = OptionParser(usage=usageString)
o.add_option("--cachedir", dest='cachedir', default=None,
help="Directory in which to cache lex/parse tables.")
+ o.add_option("--only-html", dest='only_html', action="store_true",
+ help="Only generate HTML from WebIDL inputs")
(options, args) = o.parse_args()
if len(args) < 2:
@@ -51,24 +53,30 @@ def main():
parser.parse(''.join(lines), fullPath)
parserResults = parser.finish()
- # Write the parser results out to a pickle.
- resultsPath = os.path.join(outputdir, 'ParserResults.pkl')
- with open(resultsPath, 'wb') as resultsFile:
- cPickle.dump(parserResults, resultsFile, -1)
+ if not options.only_html:
+ # Write the parser results out to a pickle.
+ resultsPath = os.path.join(outputdir, 'ParserResults.pkl')
+ with open(resultsPath, 'wb') as resultsFile:
+ cPickle.dump(parserResults, resultsFile, -1)
# Load the configuration.
config = Configuration(configFile, parserResults)
to_generate = [
- ('PrototypeList', 'PrototypeList.rs'),
- ('RegisterBindings', 'RegisterBindings.rs'),
- ('InterfaceObjectMap', 'InterfaceObjectMap.rs'),
- ('InterfaceTypes', 'InterfaceTypes.rs'),
- ('InheritTypes', 'InheritTypes.rs'),
- ('Bindings', os.path.join('Bindings', 'mod.rs')),
- ('UnionTypes', 'UnionTypes.rs'),
+ ('SupportedDomApis', 'apis.html'),
]
+ if not options.only_html:
+ to_generate = [
+ ('PrototypeList', 'PrototypeList.rs'),
+ ('RegisterBindings', 'RegisterBindings.rs'),
+ ('InterfaceObjectMap', 'InterfaceObjectMap.rs'),
+ ('InterfaceTypes', 'InterfaceTypes.rs'),
+ ('InheritTypes', 'InheritTypes.rs'),
+ ('Bindings', os.path.join('Bindings', 'mod.rs')),
+ ('UnionTypes', 'UnionTypes.rs'),
+ ]
+
for name, filename in to_generate:
generate_file(config, name, os.path.join(outputdir, filename))
diff --git a/components/script/dom/bindings/codegen/api.html.template b/components/script/dom/bindings/codegen/api.html.template
new file mode 100644
index 00000000000..807392693a4
--- /dev/null
+++ b/components/script/dom/bindings/codegen/api.html.template
@@ -0,0 +1,6 @@
+<table id="${interface}">
+<tr>
+<th>${interface}</th>
+</tr>
+${properties}
+</table>
diff --git a/components/script/dom/bindings/codegen/apis.html.template b/components/script/dom/bindings/codegen/apis.html.template
new file mode 100644
index 00000000000..a6f1e59d4ab
--- /dev/null
+++ b/components/script/dom/bindings/codegen/apis.html.template
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="generator" content="rustdoc">
+ <meta name="description" content="API documentation for the Rust `servo` crate.">
+ <meta name="keywords" content="rust, rustlang, rust-lang, servo">
+ <title>Supported DOM APIs - servo - Rust</title>
+ <link rel="stylesheet" type="text/css" href="../rustdoc.css">
+ <link rel="stylesheet" type="text/css" href="../main.css">
+</head>
+<body class="rustdoc">
+ <!--[if lte IE 8]>
+ <div class="warning">
+ This old browser is unsupported and will most likely display funky
+ things.
+ </div>
+ <![endif]-->
+ <nav class='sidebar'>
+ <div class='block crate'>
+ <h3>Interfaces</h3>
+ <ul>
+ ${interfaces}
+ </ul>
+ </div>
+ </nav>
+ <section id='main' class="content mod">
+ <h1 class='fqn'><span class='in-band'>DOM APIs currently supported in <a class='mod' href=''>Servo</a></span></h1>
+ <div id='properties' class='docblock'>
+ ${apis}
+ </div>
+ </section>
+</body>
+</html>
diff --git a/components/script/dom/bindings/codegen/interface.html.template b/components/script/dom/bindings/codegen/interface.html.template
new file mode 100644
index 00000000000..92b023165e2
--- /dev/null
+++ b/components/script/dom/bindings/codegen/interface.html.template
@@ -0,0 +1 @@
+<li><a href="#${interface}">${interface}</a></li>
diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
index acedc38ae5d..da32340dda6 100644
--- a/components/script/dom/bindings/codegen/parser/WebIDL.py
+++ b/components/script/dom/bindings/codegen/parser/WebIDL.py
@@ -158,6 +158,9 @@ class IDLObject(object):
def isInterface(self):
return False
+ def isNamespace(self):
+ return False
+
def isEnum(self):
return False
@@ -585,8 +588,8 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
return set()
-class IDLPartialInterface(IDLObject):
- def __init__(self, location, name, members, nonPartialInterface):
+class IDLPartialInterfaceOrNamespace(IDLObject):
+ def __init__(self, location, name, members, nonPartialInterfaceOrNamespace):
assert isinstance(name, IDLUnresolvedIdentifier)
IDLObject.__init__(self, location)
@@ -595,9 +598,10 @@ class IDLPartialInterface(IDLObject):
# propagatedExtendedAttrs are the ones that should get
# propagated to our non-partial interface.
self.propagatedExtendedAttrs = []
- self._nonPartialInterface = nonPartialInterface
+ self._haveSecureContextExtendedAttribute = False
+ self._nonPartialInterfaceOrNamespace = nonPartialInterfaceOrNamespace
self._finished = False
- nonPartialInterface.addPartialInterface(self)
+ nonPartialInterfaceOrNamespace.addPartialInterface(self)
def addExtendedAttributes(self, attrs):
for attr in attrs:
@@ -605,6 +609,16 @@ class IDLPartialInterface(IDLObject):
if identifier in ["Constructor", "NamedConstructor"]:
self.propagatedExtendedAttrs.append(attr)
+ elif identifier == "SecureContext":
+ self._haveSecureContextExtendedAttribute = True
+ # This gets propagated to all our members.
+ for member in self.members:
+ if member.getExtendedAttribute("SecureContext"):
+ raise WebIDLError("[SecureContext] specified on both a "
+ "partial interface member and on the "
+ "partial interface itself",
+ [member.location, attr.location])
+ member.addExtendedAttributes([attr])
elif identifier == "Exposed":
# This just gets propagated to all our members.
for member in self.members:
@@ -623,9 +637,23 @@ class IDLPartialInterface(IDLObject):
if self._finished:
return
self._finished = True
- # Need to make sure our non-partial interface gets finished so it can
- # report cases when we only have partial interfaces.
- self._nonPartialInterface.finish(scope)
+ if (not self._haveSecureContextExtendedAttribute and
+ self._nonPartialInterfaceOrNamespace.getExtendedAttribute("SecureContext")):
+ # This gets propagated to all our members.
+ for member in self.members:
+ if member.getExtendedAttribute("SecureContext"):
+ raise WebIDLError("[SecureContext] specified on both a "
+ "partial interface member and on the "
+ "non-partial interface",
+ [member.location,
+ self._nonPartialInterfaceOrNamespace.location])
+ member.addExtendedAttributes(
+ [IDLExtendedAttribute(self._nonPartialInterfaceOrNamespace.location,
+ ("SecureContext",))])
+ # Need to make sure our non-partial interface or namespace gets
+ # finished so it can report cases when we only have partial
+ # interfaces/namespaces.
+ self._nonPartialInterfaceOrNamespace.finish(scope)
def validate(self):
pass
@@ -645,7 +673,7 @@ def globalNameSetToExposureSet(globalScope, nameSet, exposureSet):
exposureSet.update(globalScope.globalNameMapping[name])
-class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
+class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
def __init__(self, location, parentScope, name, parent, members,
isKnownNonPartial):
assert isinstance(parentScope, IDLScope)
@@ -691,9 +719,6 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
if isKnownNonPartial:
self.setNonPartial(location, parent, members)
- def __str__(self):
- return "Interface '%s'" % self.identifier.name
-
def ctor(self):
identifier = IDLUnresolvedIdentifier(self.location, "constructor",
allowForbidden=True)
@@ -789,6 +814,20 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
assert iter(self.members)
+ if self.isNamespace():
+ assert not self.parent
+ for m in self.members:
+ if m.isAttr() or m.isMethod():
+ if m.isStatic():
+ raise WebIDLError("Don't mark things explicitly static "
+ "in namespaces",
+ [self.location, m.location])
+ # Just mark all our methods/attributes as static. The other
+ # option is to duplicate the relevant InterfaceMembers
+ # production bits but modified to produce static stuff to
+ # start with, but that sounds annoying.
+ m.forceStatic()
+
if self.parent:
self.parent.finish(scope)
self.parent._hasChildInterfaces = True
@@ -843,6 +882,17 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
self.parent.identifier.name),
[self.location, self.parent.location])
+ # Interfaces that are not [SecureContext] can't inherit
+ # from [SecureContext] interfaces.
+ if (self.parent.getExtendedAttribute("SecureContext") and
+ not self.getExtendedAttribute("SecureContext")):
+ raise WebIDLError("Interface %s does not have "
+ "[SecureContext] but inherits from "
+ "interface %s which does" %
+ (self.identifier.name,
+ self.parent.identifier.name),
+ [self.location, self.parent.location])
+
for iface in self.implementedInterfaces:
iface.finish(scope)
@@ -1211,6 +1261,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
member.getExtendedAttribute("ChromeOnly") or
member.getExtendedAttribute("Pref") or
member.getExtendedAttribute("Func") or
+ member.getExtendedAttribute("SecureContext") or
member.getExtendedAttribute("AvailableIn") or
member.getExtendedAttribute("CheckAnyPermissions") or
member.getExtendedAttribute("CheckAllPermissions")):
@@ -1285,9 +1336,6 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
[self.location, iterableDecl.location,
indexedGetter.location])
- def isInterface(self):
- return True
-
def isExternal(self):
return False
@@ -1338,7 +1386,172 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
return not hasattr(self, "_noInterfaceObject")
def hasInterfacePrototypeObject(self):
- return not self.isCallback() and self.getUserData('hasConcreteDescendant', False)
+ return (not self.isCallback() and not self.isNamespace()
+ and self.getUserData('hasConcreteDescendant', False))
+
+ def addImplementedInterface(self, implementedInterface):
+ assert(isinstance(implementedInterface, IDLInterface))
+ self.implementedInterfaces.add(implementedInterface)
+
+ def getInheritedInterfaces(self):
+ """
+ Returns a list of the interfaces this interface inherits from
+ (not including this interface itself). The list is in order
+ from most derived to least derived.
+ """
+ assert(self._finished)
+ if not self.parent:
+ return []
+ parentInterfaces = self.parent.getInheritedInterfaces()
+ parentInterfaces.insert(0, self.parent)
+ return parentInterfaces
+
+ def getConsequentialInterfaces(self):
+ assert(self._finished)
+ # The interfaces we implement directly
+ consequentialInterfaces = set(self.implementedInterfaces)
+
+ # And their inherited interfaces
+ for iface in self.implementedInterfaces:
+ consequentialInterfaces |= set(iface.getInheritedInterfaces())
+
+ # And now collect up the consequential interfaces of all of those
+ temp = set()
+ for iface in consequentialInterfaces:
+ temp |= iface.getConsequentialInterfaces()
+
+ return consequentialInterfaces | temp
+
+ def findInterfaceLoopPoint(self, otherInterface):
+ """
+ Finds an interface, amongst our ancestors and consequential interfaces,
+ that inherits from otherInterface or implements otherInterface
+ directly. If there is no such interface, returns None.
+ """
+ if self.parent:
+ if self.parent == otherInterface:
+ return self
+ loopPoint = self.parent.findInterfaceLoopPoint(otherInterface)
+ if loopPoint:
+ return loopPoint
+ if otherInterface in self.implementedInterfaces:
+ return self
+ for iface in self.implementedInterfaces:
+ loopPoint = iface.findInterfaceLoopPoint(otherInterface)
+ if loopPoint:
+ return loopPoint
+ return None
+
+ def getExtendedAttribute(self, name):
+ return self._extendedAttrDict.get(name, None)
+
+ def setNonPartial(self, location, parent, members):
+ assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
+ if self._isKnownNonPartial:
+ raise WebIDLError("Two non-partial definitions for the "
+ "same %s" %
+ ("interface" if self.isInterface()
+ else "namespace"),
+ [location, self.location])
+ self._isKnownNonPartial = True
+ # Now make it look like we were parsed at this new location, since
+ # that's the place where the interface is "really" defined
+ self.location = location
+ assert not self.parent
+ self.parent = parent
+ # Put the new members at the beginning
+ self.members = members + self.members
+
+ def addPartialInterface(self, partial):
+ assert self.identifier.name == partial.identifier.name
+ self._partialInterfaces.append(partial)
+
+ def getJSImplementation(self):
+ classId = self.getExtendedAttribute("JSImplementation")
+ if not classId:
+ return classId
+ assert isinstance(classId, list)
+ assert len(classId) == 1
+ return classId[0]
+
+ def isJSImplemented(self):
+ return bool(self.getJSImplementation())
+
+ def isProbablyShortLivingObject(self):
+ current = self
+ while current:
+ if current.getExtendedAttribute("ProbablyShortLivingObject"):
+ return True
+ current = current.parent
+ return False
+
+ def isNavigatorProperty(self):
+ naviProp = self.getExtendedAttribute("NavigatorProperty")
+ if not naviProp:
+ return False
+ assert len(naviProp) == 1
+ assert isinstance(naviProp, list)
+ assert len(naviProp[0]) != 0
+ return True
+
+ def getNavigatorProperty(self):
+ naviProp = self.getExtendedAttribute("NavigatorProperty")
+ if not naviProp:
+ return None
+ assert len(naviProp) == 1
+ assert isinstance(naviProp, list)
+ assert len(naviProp[0]) != 0
+ conditionExtendedAttributes = self._extendedAttrDict.viewkeys() & IDLInterfaceOrNamespace.conditionExtendedAttributes
+ attr = IDLAttribute(self.location,
+ IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), naviProp[0]),
+ IDLUnresolvedType(self.location, IDLUnresolvedIdentifier(self.location, self.identifier.name)),
+ True,
+ extendedAttrDict={ a: self._extendedAttrDict[a] for a in conditionExtendedAttributes },
+ navigatorObjectGetter=True)
+ attr._exposureGlobalNames = self._exposureGlobalNames
+ # We're abusing Constant a little bit here, because we need Cached. The
+ # getter will create a new object every time, but we're never going to
+ # clear the cached value.
+ extendedAttrs = [ IDLExtendedAttribute(self.location, ("Throws", )),
+ IDLExtendedAttribute(self.location, ("Cached", )),
+ IDLExtendedAttribute(self.location, ("Constant", )) ]
+ attr.addExtendedAttributes(extendedAttrs)
+ return attr
+
+ def hasChildInterfaces(self):
+ return self._hasChildInterfaces
+
+ def isOnGlobalProtoChain(self):
+ return self._isOnGlobalProtoChain
+
+ def _getDependentObjects(self):
+ deps = set(self.members)
+ deps.update(self.implementedInterfaces)
+ if self.parent:
+ deps.add(self.parent)
+ return deps
+
+ def hasMembersInSlots(self):
+ return self._ownMembersInSlots != 0
+
+ conditionExtendedAttributes = [ "Pref", "ChromeOnly", "Func", "AvailableIn",
+ "SecureContext",
+ "CheckAnyPermissions",
+ "CheckAllPermissions" ]
+ def isExposedConditionally(self):
+ return any(self.getExtendedAttribute(a) for a in self.conditionExtendedAttributes)
+
+class IDLInterface(IDLInterfaceOrNamespace):
+ def __init__(self, location, parentScope, name, parent, members,
+ isKnownNonPartial):
+ IDLInterfaceOrNamespace.__init__(self, location, parentScope, name,
+ parent, members, isKnownNonPartial)
+
+ def __str__(self):
+ return "Interface '%s'" % self.identifier.name
+
+ def isInterface(self):
+ return True
def addExtendedAttributes(self, attrs):
for attr in attrs:
@@ -1469,6 +1682,18 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
self.parentScope.globalNames.add(self.identifier.name)
self.parentScope.globalNameMapping[self.identifier.name].add(self.identifier.name)
self._isOnGlobalProtoChain = True
+ elif identifier == "SecureContext":
+ if not attr.noArguments():
+ raise WebIDLError("[%s] must take no arguments" % identifier,
+ [attr.location])
+ # This gets propagated to all our members.
+ for member in self.members:
+ if member.getExtendedAttribute("SecureContext"):
+ raise WebIDLError("[SecureContext] specified on both "
+ "an interface member and on the "
+ "interface itself",
+ [member.location, attr.location])
+ member.addExtendedAttributes([attr])
elif (identifier == "NeedResolve" or
identifier == "OverrideBuiltins" or
identifier == "ChromeOnly" or
@@ -1506,154 +1731,46 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
attrlist = attr.listValue()
self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
- def addImplementedInterface(self, implementedInterface):
- assert(isinstance(implementedInterface, IDLInterface))
- self.implementedInterfaces.add(implementedInterface)
-
- def getInheritedInterfaces(self):
- """
- Returns a list of the interfaces this interface inherits from
- (not including this interface itself). The list is in order
- from most derived to least derived.
- """
- assert(self._finished)
- if not self.parent:
- return []
- parentInterfaces = self.parent.getInheritedInterfaces()
- parentInterfaces.insert(0, self.parent)
- return parentInterfaces
-
- def getConsequentialInterfaces(self):
- assert(self._finished)
- # The interfaces we implement directly
- consequentialInterfaces = set(self.implementedInterfaces)
-
- # And their inherited interfaces
- for iface in self.implementedInterfaces:
- consequentialInterfaces |= set(iface.getInheritedInterfaces())
-
- # And now collect up the consequential interfaces of all of those
- temp = set()
- for iface in consequentialInterfaces:
- temp |= iface.getConsequentialInterfaces()
-
- return consequentialInterfaces | temp
-
- def findInterfaceLoopPoint(self, otherInterface):
- """
- Finds an interface, amongst our ancestors and consequential interfaces,
- that inherits from otherInterface or implements otherInterface
- directly. If there is no such interface, returns None.
- """
- if self.parent:
- if self.parent == otherInterface:
- return self
- loopPoint = self.parent.findInterfaceLoopPoint(otherInterface)
- if loopPoint:
- return loopPoint
- if otherInterface in self.implementedInterfaces:
- return self
- for iface in self.implementedInterfaces:
- loopPoint = iface.findInterfaceLoopPoint(otherInterface)
- if loopPoint:
- return loopPoint
- return None
-
- def getExtendedAttribute(self, name):
- return self._extendedAttrDict.get(name, None)
-
- def setNonPartial(self, location, parent, members):
- assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
- if self._isKnownNonPartial:
- raise WebIDLError("Two non-partial definitions for the "
- "same interface",
- [location, self.location])
- self._isKnownNonPartial = True
- # Now make it look like we were parsed at this new location, since
- # that's the place where the interface is "really" defined
- self.location = location
- assert not self.parent
- self.parent = parent
- # Put the new members at the beginning
- self.members = members + self.members
-
- def addPartialInterface(self, partial):
- assert self.identifier.name == partial.identifier.name
- self._partialInterfaces.append(partial)
- def getJSImplementation(self):
- classId = self.getExtendedAttribute("JSImplementation")
- if not classId:
- return classId
- assert isinstance(classId, list)
- assert len(classId) == 1
- return classId[0]
-
- def isJSImplemented(self):
- return bool(self.getJSImplementation())
+class IDLNamespace(IDLInterfaceOrNamespace):
+ def __init__(self, location, parentScope, name, members, isKnownNonPartial):
+ IDLInterfaceOrNamespace.__init__(self, location, parentScope, name,
+ None, members, isKnownNonPartial)
- def isProbablyShortLivingObject(self):
- current = self
- while current:
- if current.getExtendedAttribute("ProbablyShortLivingObject"):
- return True
- current = current.parent
- return False
+ def __str__(self):
+ return "Namespace '%s'" % self.identifier.name
- def isNavigatorProperty(self):
- naviProp = self.getExtendedAttribute("NavigatorProperty")
- if not naviProp:
- return False
- assert len(naviProp) == 1
- assert isinstance(naviProp, list)
- assert len(naviProp[0]) != 0
+ def isNamespace(self):
return True
- def getNavigatorProperty(self):
- naviProp = self.getExtendedAttribute("NavigatorProperty")
- if not naviProp:
- return None
- assert len(naviProp) == 1
- assert isinstance(naviProp, list)
- assert len(naviProp[0]) != 0
- conditionExtendedAttributes = self._extendedAttrDict.viewkeys() & IDLInterface.conditionExtendedAttributes
- attr = IDLAttribute(self.location,
- IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), naviProp[0]),
- IDLUnresolvedType(self.location, IDLUnresolvedIdentifier(self.location, self.identifier.name)),
- True,
- extendedAttrDict={ a: self._extendedAttrDict[a] for a in conditionExtendedAttributes },
- navigatorObjectGetter=True)
- attr._exposureGlobalNames = self._exposureGlobalNames
- # We're abusing Constant a little bit here, because we need Cached. The
- # getter will create a new object every time, but we're never going to
- # clear the cached value.
- extendedAttrs = [ IDLExtendedAttribute(self.location, ("Throws", )),
- IDLExtendedAttribute(self.location, ("Cached", )),
- IDLExtendedAttribute(self.location, ("Constant", )) ]
- attr.addExtendedAttributes(extendedAttrs)
- return attr
-
- def hasChildInterfaces(self):
- return self._hasChildInterfaces
-
- def isOnGlobalProtoChain(self):
- return self._isOnGlobalProtoChain
-
- def _getDependentObjects(self):
- deps = set(self.members)
- deps.update(self.implementedInterfaces)
- if self.parent:
- deps.add(self.parent)
- return deps
+ def addExtendedAttributes(self, attrs):
+ # The set of things namespaces support is small enough it's simpler
+ # to factor out into a separate method than it is to sprinkle
+ # isNamespace() checks all through
+ # IDLInterfaceOrNamespace.addExtendedAttributes.
+ for attr in attrs:
+ identifier = attr.identifier()
- def hasMembersInSlots(self):
- return self._ownMembersInSlots != 0
+ if identifier == "Exposed":
+ convertExposedAttrToGlobalNameSet(attr,
+ self._exposureGlobalNames)
+ elif identifier == "ClassString":
+ # Takes a string value to override the default "Object" if
+ # desired.
+ if not attr.hasValue():
+ raise WebIDLError("[%s] must have a value" % identifier,
+ [attr.location])
+ elif identifier == "ProtoObjectHack":
+ if not attr.noArguments():
+ raise WebIDLError("[%s] must not have arguments" % identifier,
+ [attr.location])
+ else:
+ raise WebIDLError("Unknown extended attribute %s on namespace" %
+ identifier,
+ [attr.location])
- conditionExtendedAttributes = [ "Pref", "ChromeOnly", "Func", "AvailableIn",
- "CheckAnyPermissions",
- "CheckAllPermissions" ]
- def isExposedConditionally(self):
- return any(self.getExtendedAttribute(a) for a in self.conditionExtendedAttributes)
+ attrlist = attr.listValue()
+ self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
class IDLDictionary(IDLObjectWithScope):
@@ -2066,7 +2183,30 @@ class IDLUnresolvedType(IDLType):
"distinguishable from other things")
-class IDLNullableType(IDLType):
+class IDLParameterizedType(IDLType):
+ def __init__(self, location, name, innerType):
+ IDLType.__init__(self, location, name)
+ self.builtin = False
+ self.inner = innerType
+
+ def includesRestrictedFloat(self):
+ return self.inner.includesRestrictedFloat()
+
+ def resolveType(self, parentScope):
+ assert isinstance(parentScope, IDLScope)
+ self.inner.resolveType(parentScope)
+
+ def isComplete(self):
+ return self.inner.isComplete()
+
+ def unroll(self):
+ return self.inner.unroll()
+
+ def _getDependentObjects(self):
+ return self.inner._getDependentObjects()
+
+
+class IDLNullableType(IDLParameterizedType):
def __init__(self, location, innerType):
assert not innerType.isVoid()
assert not innerType == BuiltinTypes[IDLBuiltinType.Types.any]
@@ -2074,9 +2214,7 @@ class IDLNullableType(IDLType):
name = innerType.name
if innerType.isComplete():
name += "OrNull"
- IDLType.__init__(self, location, name)
- self.inner = innerType
- self.builtin = False
+ IDLParameterizedType.__init__(self, location, name, innerType)
def __eq__(self, other):
return isinstance(other, IDLNullableType) and self.inner == other.inner
@@ -2117,9 +2255,6 @@ class IDLNullableType(IDLType):
def isUnrestricted(self):
return self.inner.isUnrestricted()
- def includesRestrictedFloat(self):
- return self.inner.includesRestrictedFloat()
-
def isInteger(self):
return self.inner.isInteger()
@@ -2174,13 +2309,6 @@ class IDLNullableType(IDLType):
def tag(self):
return self.inner.tag()
- def resolveType(self, parentScope):
- assert isinstance(parentScope, IDLScope)
- self.inner.resolveType(parentScope)
-
- def isComplete(self):
- return self.inner.isComplete()
-
def complete(self, scope):
self.inner = self.inner.complete(scope)
if self.inner.nullable():
@@ -2196,9 +2324,6 @@ class IDLNullableType(IDLType):
self.name = self.inner.name + "OrNull"
return self
- def unroll(self):
- return self.inner.unroll()
-
def isDistinguishableFrom(self, other):
if (other.nullable() or (other.isUnion() and other.hasNullableType) or
other.isDictionary()):
@@ -2206,17 +2331,12 @@ class IDLNullableType(IDLType):
return False
return self.inner.isDistinguishableFrom(other)
- def _getDependentObjects(self):
- return self.inner._getDependentObjects()
-
-class IDLSequenceType(IDLType):
+class IDLSequenceType(IDLParameterizedType):
def __init__(self, location, parameterType):
assert not parameterType.isVoid()
- IDLType.__init__(self, location, parameterType.name)
- self.inner = parameterType
- self.builtin = False
+ IDLParameterizedType.__init__(self, location, parameterType.name, parameterType)
# Need to set self.name up front if our inner type is already complete,
# since in that case our .complete() won't be called.
if self.inner.isComplete():
@@ -2267,27 +2387,14 @@ class IDLSequenceType(IDLType):
def isSerializable(self):
return self.inner.isSerializable()
- def includesRestrictedFloat(self):
- return self.inner.includesRestrictedFloat()
-
def tag(self):
return IDLType.Tags.sequence
- def resolveType(self, parentScope):
- assert isinstance(parentScope, IDLScope)
- self.inner.resolveType(parentScope)
-
- def isComplete(self):
- return self.inner.isComplete()
-
def complete(self, scope):
self.inner = self.inner.complete(scope)
self.name = self.inner.name + "Sequence"
return self
- def unroll(self):
- return self.inner.unroll()
-
def isDistinguishableFrom(self, other):
if other.isPromise():
return False
@@ -2299,20 +2406,12 @@ class IDLSequenceType(IDLType):
other.isDictionary() or
other.isCallback() or other.isMozMap())
- def _getDependentObjects(self):
- return self.inner._getDependentObjects()
-
-class IDLMozMapType(IDLType):
- # XXXbz This is pretty similar to IDLSequenceType in various ways.
- # And maybe to IDLNullableType. Should we have a superclass for
- # "type containing this other type"? Bug 1015318.
+class IDLMozMapType(IDLParameterizedType):
def __init__(self, location, parameterType):
assert not parameterType.isVoid()
- IDLType.__init__(self, location, parameterType.name)
- self.inner = parameterType
- self.builtin = False
+ IDLParameterizedType.__init__(self, location, parameterType.name, parameterType)
# Need to set self.name up front if our inner type is already complete,
# since in that case our .complete() won't be called.
if self.inner.isComplete():
@@ -2327,19 +2426,9 @@ class IDLMozMapType(IDLType):
def isMozMap(self):
return True
- def includesRestrictedFloat(self):
- return self.inner.includesRestrictedFloat()
-
def tag(self):
return IDLType.Tags.mozmap
- def resolveType(self, parentScope):
- assert isinstance(parentScope, IDLScope)
- self.inner.resolveType(parentScope)
-
- def isComplete(self):
- return self.inner.isComplete()
-
def complete(self, scope):
self.inner = self.inner.complete(scope)
self.name = self.inner.name + "MozMap"
@@ -2363,9 +2452,6 @@ class IDLMozMapType(IDLType):
def isExposedInAllOf(self, exposureSet):
return self.inner.unroll().isExposedInAllOf(exposureSet)
- def _getDependentObjects(self):
- return self.inner._getDependentObjects()
-
class IDLUnionType(IDLType):
def __init__(self, location, memberTypes):
@@ -3877,6 +3963,7 @@ class IDLConst(IDLInterfaceMember):
elif (identifier == "Pref" or
identifier == "ChromeOnly" or
identifier == "Func" or
+ identifier == "SecureContext" or
identifier == "AvailableIn" or
identifier == "CheckAnyPermissions" or
identifier == "CheckAllPermissions"):
@@ -3903,7 +3990,7 @@ class IDLAttribute(IDLInterfaceMember):
self.type = type
self.readonly = readonly
self.inherit = inherit
- self.static = static
+ self._static = static
self.lenientThis = False
self._unforgeable = False
self.stringifier = stringifier
@@ -3925,7 +4012,10 @@ class IDLAttribute(IDLInterfaceMember):
[self.location])
def isStatic(self):
- return self.static
+ return self._static
+
+ def forceStatic(self):
+ self._static = True
def __str__(self):
return "'%s' attribute '%s'" % (self.type, self.identifier)
@@ -3979,16 +4069,53 @@ class IDLAttribute(IDLInterfaceMember):
"interface type as its type", [self.location])
def validate(self):
+ def typeContainsChromeOnlyDictionaryMember(type):
+ if (type.nullable() or
+ type.isSequence() or
+ type.isMozMap()):
+ return typeContainsChromeOnlyDictionaryMember(type.inner)
+
+ if type.isUnion():
+ for memberType in type.flatMemberTypes:
+ (contains, location) = typeContainsChromeOnlyDictionaryMember(memberType)
+ if contains:
+ return (True, location)
+
+ if type.isDictionary():
+ dictionary = type.inner
+ while dictionary:
+ (contains, location) = dictionaryContainsChromeOnlyMember(dictionary)
+ if contains:
+ return (True, location)
+ dictionary = dictionary.parent
+
+ return (False, None)
+
+ def dictionaryContainsChromeOnlyMember(dictionary):
+ for member in dictionary.members:
+ if member.getExtendedAttribute("ChromeOnly"):
+ return (True, member.location)
+ (contains, location) = typeContainsChromeOnlyDictionaryMember(member.type)
+ if contains:
+ return (True, location)
+ return (False, None)
+
IDLInterfaceMember.validate(self)
- if ((self.getExtendedAttribute("Cached") or
- self.getExtendedAttribute("StoreInSlot")) and
- not self.affects == "Nothing"):
- raise WebIDLError("Cached attributes and attributes stored in "
- "slots must be Constant or Pure or "
- "Affects=Nothing, since the getter won't always "
- "be called.",
- [self.location])
+ if (self.getExtendedAttribute("Cached") or
+ self.getExtendedAttribute("StoreInSlot")):
+ if not self.affects == "Nothing":
+ raise WebIDLError("Cached attributes and attributes stored in "
+ "slots must be Constant or Pure or "
+ "Affects=Nothing, since the getter won't always "
+ "be called.",
+ [self.location])
+ (contains, location) = typeContainsChromeOnlyDictionaryMember(self.type)
+ if contains:
+ raise WebIDLError("[Cached] and [StoreInSlot] must not be used "
+ "on an attribute whose type contains a "
+ "[ChromeOnly] dictionary member",
+ [self.location, location])
if self.getExtendedAttribute("Frozen"):
if (not self.type.isSequence() and not self.type.isDictionary() and
not self.type.isMozMap()):
@@ -4177,6 +4304,7 @@ class IDLAttribute(IDLInterfaceMember):
identifier == "GetterThrows" or
identifier == "ChromeOnly" or
identifier == "Func" or
+ identifier == "SecureContext" or
identifier == "Frozen" or
identifier == "AvailableIn" or
identifier == "NewObject" or
@@ -4233,6 +4361,7 @@ class IDLArgument(IDLObjectWithIdentifier):
self.enforceRange = False
self.clamp = False
self._allowTreatNonCallableAsNull = False
+ self._extendedAttrDict = {}
assert not variadic or optional
assert not variadic or not defaultValue
@@ -4262,11 +4391,22 @@ class IDLArgument(IDLObjectWithIdentifier):
self.enforceRange = True
elif identifier == "TreatNonCallableAsNull":
self._allowTreatNonCallableAsNull = True
+ elif (self.dictionaryMember and
+ (identifier == "ChromeOnly" or identifier == "Func")):
+ if not self.optional:
+ raise WebIDLError("[%s] must not be used on a required "
+ "dictionary member" % identifier,
+ [attribute.location])
else:
raise WebIDLError("Unhandled extended attribute on %s" %
("a dictionary member" if self.dictionaryMember else
"an argument"),
[attribute.location])
+ attrlist = attribute.listValue()
+ self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
+
+ def getExtendedAttribute(self, name):
+ return self._extendedAttrDict.get(name, None)
def isComplete(self):
return self._isComplete
@@ -4537,6 +4677,9 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
def isStatic(self):
return self._static
+ def forceStatic(self):
+ self._static = True
+
def isGetter(self):
return self._getter
@@ -4888,6 +5031,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
identifier == "Pref" or
identifier == "Deprecated" or
identifier == "Func" or
+ identifier == "SecureContext" or
identifier == "AvailableIn" or
identifier == "CheckAnyPermissions" or
identifier == "CheckAllPermissions" or
@@ -5115,7 +5259,8 @@ class Tokenizer(object):
"or": "OR",
"maplike": "MAPLIKE",
"setlike": "SETLIKE",
- "iterable": "ITERABLE"
+ "iterable": "ITERABLE",
+ "namespace": "NAMESPACE"
}
tokens.extend(keywords.values())
@@ -5212,7 +5357,8 @@ class Parser(Tokenizer):
def p_Definition(self, p):
"""
Definition : CallbackOrInterface
- | PartialInterface
+ | Namespace
+ | Partial
| Dictionary
| Exception
| Enum
@@ -5246,33 +5392,54 @@ class Parser(Tokenizer):
assert p[1]
p[0] = p[1]
- def p_Interface(self, p):
+ def handleNonPartialObject(self, location, identifier, constructor,
+ constructorArgs, nonPartialArgs):
"""
- Interface : INTERFACE IDENTIFIER Inheritance LBRACE InterfaceMembers RBRACE SEMICOLON
+ This handles non-partial objects (interfaces and namespaces) by
+ checking for an existing partial object, and promoting it to
+ non-partial as needed. The return value is the non-partial object.
+
+ constructorArgs are all the args for the constructor except the last
+ one: isKnownNonPartial.
+
+ nonPartialArgs are the args for the setNonPartial call.
"""
- location = self.getLocation(p, 1)
- identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
- members = p[5]
- parent = p[3]
+ # The name of the class starts with "IDL", so strip that off.
+ # Also, starts with a capital letter after that, so nix that
+ # as well.
+ prettyname = constructor.__name__[3:].lower()
try:
existingObj = self.globalScope()._lookupIdentifier(identifier)
if existingObj:
- p[0] = existingObj
- if not isinstance(p[0], IDLInterface):
- raise WebIDLError("Interface has the same name as "
- "non-interface object",
- [location, p[0].location])
- p[0].setNonPartial(location, parent, members)
- return
+ if not isinstance(existingObj, constructor):
+ raise WebIDLError("%s has the same name as "
+ "non-%s object" %
+ (prettyname.capitalize(), prettyname),
+ [location, existingObj.location])
+ existingObj.setNonPartial(*nonPartialArgs)
+ return existingObj
except Exception, ex:
if isinstance(ex, WebIDLError):
raise ex
pass
- iface = IDLInterface(location, self.globalScope(), identifier, parent,
- members, isKnownNonPartial=True)
- p[0] = iface
+ # True for isKnownNonPartial
+ return constructor(*(constructorArgs + [True]))
+
+ def p_Interface(self, p):
+ """
+ Interface : INTERFACE IDENTIFIER Inheritance LBRACE InterfaceMembers RBRACE SEMICOLON
+ """
+ location = self.getLocation(p, 1)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+ members = p[5]
+ parent = p[3]
+
+ p[0] = self.handleNonPartialObject(
+ location, identifier, IDLInterface,
+ [location, self.globalScope(), identifier, parent, members],
+ [location, parent, members])
def p_InterfaceForwardDecl(self, p):
"""
@@ -5297,34 +5464,100 @@ class Parser(Tokenizer):
p[0] = IDLExternalInterface(location, self.globalScope(), identifier)
- def p_PartialInterface(self, p):
+ def p_Namespace(self, p):
"""
- PartialInterface : PARTIAL INTERFACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
+ Namespace : NAMESPACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
"""
- location = self.getLocation(p, 2)
- identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
- members = p[5]
+ location = self.getLocation(p, 1)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+ members = p[4]
+
+ p[0] = self.handleNonPartialObject(
+ location, identifier, IDLNamespace,
+ [location, self.globalScope(), identifier, members],
+ [location, None, members])
+
+ def p_Partial(self, p):
+ """
+ Partial : PARTIAL PartialDefinition
+ """
+ p[0] = p[2]
+
+ def p_PartialDefinition(self, p):
+ """
+ PartialDefinition : PartialInterface
+ | PartialNamespace
+ """
+ p[0] = p[1]
+
+ def handlePartialObject(self, location, identifier, nonPartialConstructor,
+ nonPartialConstructorArgs,
+ partialConstructorArgs):
+ """
+ This handles partial objects (interfaces and namespaces) by checking for
+ an existing non-partial object, and adding ourselves to it as needed.
+ The return value is our partial object. For now we just use
+ IDLPartialInterfaceOrNamespace for partial objects.
+
+ nonPartialConstructorArgs are all the args for the non-partial
+ constructor except the last two: members and isKnownNonPartial.
+
+ partialConstructorArgs are the arguments for the
+ IDLPartialInterfaceOrNamespace constructor, except the last one (the
+ non-partial object).
+ """
+ # The name of the class starts with "IDL", so strip that off.
+ # Also, starts with a capital letter after that, so nix that
+ # as well.
+ prettyname = nonPartialConstructor.__name__[3:].lower()
- nonPartialInterface = None
+ nonPartialObject = None
try:
- nonPartialInterface = self.globalScope()._lookupIdentifier(identifier)
- if nonPartialInterface:
- if not isinstance(nonPartialInterface, IDLInterface):
- raise WebIDLError("Partial interface has the same name as "
- "non-interface object",
- [location, nonPartialInterface.location])
+ nonPartialObject = self.globalScope()._lookupIdentifier(identifier)
+ if nonPartialObject:
+ if not isinstance(nonPartialObject, nonPartialConstructor):
+ raise WebIDLError("Partial %s has the same name as "
+ "non-%s object" %
+ (prettyname, prettyname),
+ [location, nonPartialObject.location])
except Exception, ex:
if isinstance(ex, WebIDLError):
raise ex
pass
- if not nonPartialInterface:
- nonPartialInterface = IDLInterface(location, self.globalScope(),
- identifier, None,
- [], isKnownNonPartial=False)
- partialInterface = IDLPartialInterface(location, identifier, members,
- nonPartialInterface)
- p[0] = partialInterface
+ if not nonPartialObject:
+ nonPartialObject = nonPartialConstructor(
+ # No members, False for isKnownNonPartial
+ *(nonPartialConstructorArgs + [[], False]))
+ partialInterface = IDLPartialInterfaceOrNamespace(
+ *(partialConstructorArgs + [nonPartialObject]))
+ return partialInterface
+
+ def p_PartialInterface(self, p):
+ """
+ PartialInterface : INTERFACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
+ """
+ location = self.getLocation(p, 1)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+ members = p[4]
+
+ p[0] = self.handlePartialObject(
+ location, identifier, IDLInterface,
+ [location, self.globalScope(), identifier, None],
+ [location, identifier, members])
+
+ def p_PartialNamespace(self, p):
+ """
+ PartialNamespace : NAMESPACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
+ """
+ location = self.getLocation(p, 1)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+ members = p[4]
+
+ p[0] = self.handlePartialObject(
+ location, identifier, IDLNamespace,
+ [location, self.globalScope(), identifier],
+ [location, identifier, members])
def p_Inheritance(self, p):
"""
@@ -5985,6 +6218,7 @@ class Parser(Tokenizer):
| JSONIFIER
| TYPEDEF
| UNRESTRICTED
+ | NAMESPACE
"""
p[0] = p[1]
@@ -6585,19 +6819,21 @@ class Parser(Tokenizer):
Tokenizer.__init__(self, outputdir, lexer)
logger = SqueakyCleanLogger()
- self.parser = yacc.yacc(module=self,
- outputdir=outputdir,
- tabmodule='webidlyacc',
- errorlog=logger,
- debug=False
- # Pickling the grammar is a speedup in
- # some cases (older Python?) but a
- # significant slowdown in others.
- # We're not pickling for now, until it
- # becomes a speedup again.
- # , picklefile='WebIDLGrammar.pkl'
- )
- logger.reportGrammarErrors()
+ try:
+ self.parser = yacc.yacc(module=self,
+ outputdir=outputdir,
+ tabmodule='webidlyacc',
+ errorlog=logger,
+ debug=False
+ # Pickling the grammar is a speedup in
+ # some cases (older Python?) but a
+ # significant slowdown in others.
+ # We're not pickling for now, until it
+ # becomes a speedup again.
+ # , picklefile='WebIDLGrammar.pkl'
+ )
+ finally:
+ logger.reportGrammarErrors()
self._globalScope = IDLScope(BuiltinLocation("<Global Scope>"), None, None)
# To make our test harness work, pretend like we have a primary global already.
@@ -6668,10 +6904,11 @@ class Parser(Tokenizer):
# We're generating a partial interface to add a readonly
# property to the Navigator interface for every interface
# annotated with NavigatorProperty.
- partialInterface = IDLPartialInterface(iface.location,
- IDLUnresolvedIdentifier(iface.location, "Navigator"),
- [ navigatorProperty ],
- navigatorInterface)
+ partialInterface = IDLPartialInterfaceOrNamespace(
+ iface.location,
+ IDLUnresolvedIdentifier(iface.location, "Navigator"),
+ [ navigatorProperty ],
+ navigatorInterface)
self._productions.append(partialInterface)
iterable = None
diff --git a/components/script/dom/bindings/codegen/parser/abstract.patch b/components/script/dom/bindings/codegen/parser/abstract.patch
deleted file mode 100644
index a8e2ddcf759..00000000000
--- a/components/script/dom/bindings/codegen/parser/abstract.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- WebIDL.py
-+++ WebIDL.py
-@@ -1416,7 +1416,8 @@
- identifier == "LegacyEventInit" or
- identifier == "ProbablyShortLivingObject" or
- identifier == "LegacyUnenumerableNamedProperties" or
-- identifier == "NonOrdinaryGetPrototypeOf"):
-+ identifier == "NonOrdinaryGetPrototypeOf" or
-+ identifier == "Abstract"):
- # Known extended attributes that do not take values
- if not attr.noArguments():
- raise WebIDLError("[%s] must take no arguments" % identifier,
diff --git a/components/script/dom/bindings/codegen/parser/debug.patch b/components/script/dom/bindings/codegen/parser/debug.patch
index 85075dea490..ca391c38273 100644
--- a/components/script/dom/bindings/codegen/parser/debug.patch
+++ b/components/script/dom/bindings/codegen/parser/debug.patch
@@ -1,12 +1,12 @@
--- WebIDL.py
+++ WebIDL.py
-@@ -6438,7 +6438,8 @@ class Parser(Tokenizer):
- self.parser = yacc.yacc(module=self,
- outputdir=outputdir,
- tabmodule='webidlyacc',
-- errorlog=logger
-+ errorlog=logger,
-+ debug=False
- # Pickling the grammar is a speedup in
- # some cases (older Python?) but a
- # significant slowdown in others.
+@@ -6823,7 +6823,8 @@ class Parser(Tokenizer):
+ self.parser = yacc.yacc(module=self,
+ outputdir=outputdir,
+ tabmodule='webidlyacc',
+- errorlog=logger
++ errorlog=logger,
++ debug=False
+ # Pickling the grammar is a speedup in
+ # some cases (older Python?) but a
+ # significant slowdown in others.
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_conditional_dictionary_member.py b/components/script/dom/bindings/codegen/parser/tests/test_conditional_dictionary_member.py
new file mode 100644
index 00000000000..433b7e501a4
--- /dev/null
+++ b/components/script/dom/bindings/codegen/parser/tests/test_conditional_dictionary_member.py
@@ -0,0 +1,110 @@
+def WebIDLTest(parser, harness):
+ parser.parse("""
+ dictionary Dict {
+ any foo;
+ [ChromeOnly] any bar;
+ };
+ """)
+ results = parser.finish()
+ harness.check(len(results), 1, "Should have a dictionary")
+ members = results[0].members;
+ harness.check(len(members), 2, "Should have two members")
+ # Note that members are ordered lexicographically, so "bar" comes
+ # before "foo".
+ harness.ok(members[0].getExtendedAttribute("ChromeOnly"),
+ "First member is not ChromeOnly")
+ harness.ok(not members[1].getExtendedAttribute("ChromeOnly"),
+ "Second member is ChromeOnly")
+
+ parser = parser.reset()
+ parser.parse("""
+ dictionary Dict {
+ any foo;
+ any bar;
+ };
+
+ interface Iface {
+ [Constant, Cached] readonly attribute Dict dict;
+ };
+ """)
+ results = parser.finish()
+ harness.check(len(results), 2, "Should have a dictionary and an interface")
+
+ parser = parser.reset()
+ exception = None
+ try:
+ parser.parse("""
+ dictionary Dict {
+ any foo;
+ [ChromeOnly] any bar;
+ };
+
+ interface Iface {
+ [Constant, Cached] readonly attribute Dict dict;
+ };
+ """)
+ results = parser.finish()
+ except Exception, exception:
+ pass
+
+ harness.ok(exception, "Should have thrown.")
+ harness.check(exception.message,
+ "[Cached] and [StoreInSlot] must not be used on an attribute "
+ "whose type contains a [ChromeOnly] dictionary member",
+ "Should have thrown the right exception")
+
+ parser = parser.reset()
+ exception = None
+ try:
+ parser.parse("""
+ dictionary ParentDict {
+ [ChromeOnly] any bar;
+ };
+
+ dictionary Dict : ParentDict {
+ any foo;
+ };
+
+ interface Iface {
+ [Constant, Cached] readonly attribute Dict dict;
+ };
+ """)
+ results = parser.finish()
+ except Exception, exception:
+ pass
+
+ harness.ok(exception, "Should have thrown (2).")
+ harness.check(exception.message,
+ "[Cached] and [StoreInSlot] must not be used on an attribute "
+ "whose type contains a [ChromeOnly] dictionary member",
+ "Should have thrown the right exception (2)")
+
+ parser = parser.reset()
+ exception = None
+ try:
+ parser.parse("""
+ dictionary GrandParentDict {
+ [ChromeOnly] any baz;
+ };
+
+ dictionary ParentDict : GrandParentDict {
+ any bar;
+ };
+
+ dictionary Dict : ParentDict {
+ any foo;
+ };
+
+ interface Iface {
+ [Constant, Cached] readonly attribute Dict dict;
+ };
+ """)
+ results = parser.finish()
+ except Exception, exception:
+ pass
+
+ harness.ok(exception, "Should have thrown (3).")
+ harness.check(exception.message,
+ "[Cached] and [StoreInSlot] must not be used on an attribute "
+ "whose type contains a [ChromeOnly] dictionary member",
+ "Should have thrown the right exception (3)")
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_namespace.py b/components/script/dom/bindings/codegen/parser/tests/test_namespace.py
new file mode 100644
index 00000000000..74533a1770e
--- /dev/null
+++ b/components/script/dom/bindings/codegen/parser/tests/test_namespace.py
@@ -0,0 +1,223 @@
+def WebIDLTest(parser, harness):
+ parser.parse(
+ """
+ namespace MyNamespace {
+ attribute any foo;
+ any bar();
+ };
+ """)
+
+ results = parser.finish()
+ harness.check(len(results), 1, "Should have a thing.")
+ harness.ok(results[0].isNamespace(), "Our thing should be a namespace");
+ harness.check(len(results[0].members), 2,
+ "Should have two things in our namespace")
+ harness.ok(results[0].members[0].isAttr(), "First member is attribute")
+ harness.ok(results[0].members[0].isStatic(), "Attribute should be static")
+ harness.ok(results[0].members[1].isMethod(), "Second member is method")
+ harness.ok(results[0].members[1].isStatic(), "Operation should be static")
+
+ parser = parser.reset()
+ parser.parse(
+ """
+ namespace MyNamespace {
+ attribute any foo;
+ };
+ partial namespace MyNamespace {
+ any bar();
+ };
+ """)
+
+ results = parser.finish()
+ harness.check(len(results), 2, "Should have things.")
+ harness.ok(results[0].isNamespace(), "Our thing should be a namespace");
+ harness.check(len(results[0].members), 2,
+ "Should have two things in our namespace")
+ harness.ok(results[0].members[0].isAttr(), "First member is attribute")
+ harness.ok(results[0].members[0].isStatic(), "Attribute should be static");
+ harness.ok(results[0].members[1].isMethod(), "Second member is method")
+ harness.ok(results[0].members[1].isStatic(), "Operation should be static");
+
+ parser = parser.reset()
+ parser.parse(
+ """
+ partial namespace MyNamespace {
+ any bar();
+ };
+ namespace MyNamespace {
+ attribute any foo;
+ };
+ """)
+
+ results = parser.finish()
+ harness.check(len(results), 2, "Should have things.")
+ harness.ok(results[1].isNamespace(), "Our thing should be a namespace");
+ harness.check(len(results[1].members), 2,
+ "Should have two things in our namespace")
+ harness.ok(results[1].members[0].isAttr(), "First member is attribute")
+ harness.ok(results[1].members[0].isStatic(), "Attribute should be static");
+ harness.ok(results[1].members[1].isMethod(), "Second member is method")
+ harness.ok(results[1].members[1].isStatic(), "Operation should be static");
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ namespace MyNamespace {
+ static attribute any foo;
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, x:
+ threw = True
+ harness.ok(threw, "Should have thrown.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ namespace MyNamespace {
+ static any bar();
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, x:
+ threw = True
+ harness.ok(threw, "Should have thrown.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ namespace MyNamespace {
+ any bar();
+ };
+
+ interface MyNamespace {
+ any baz();
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, x:
+ threw = True
+ harness.ok(threw, "Should have thrown.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ interface MyNamespace {
+ any baz();
+ };
+
+ namespace MyNamespace {
+ any bar();
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, x:
+ threw = True
+ harness.ok(threw, "Should have thrown.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ namespace MyNamespace {
+ any baz();
+ };
+
+ namespace MyNamespace {
+ any bar();
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, x:
+ threw = True
+ harness.ok(threw, "Should have thrown.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ partial namespace MyNamespace {
+ any baz();
+ };
+
+ interface MyNamespace {
+ any bar();
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, x:
+ threw = True
+ harness.ok(threw, "Should have thrown.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ namespace MyNamespace {
+ any bar();
+ };
+
+ partial interface MyNamespace {
+ any baz();
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, x:
+ threw = True
+ harness.ok(threw, "Should have thrown.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ partial interface MyNamespace {
+ any baz();
+ };
+
+ namespace MyNamespace {
+ any bar();
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, x:
+ threw = True
+ harness.ok(threw, "Should have thrown.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ interface MyNamespace {
+ any bar();
+ };
+
+ partial namespace MyNamespace {
+ any baz();
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, x:
+ threw = True
+ harness.ok(threw, "Should have thrown.")
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_securecontext_extended_attribute.py b/components/script/dom/bindings/codegen/parser/tests/test_securecontext_extended_attribute.py
new file mode 100644
index 00000000000..d907d08449f
--- /dev/null
+++ b/components/script/dom/bindings/codegen/parser/tests/test_securecontext_extended_attribute.py
@@ -0,0 +1,318 @@
+import WebIDL
+
+def WebIDLTest(parser, harness):
+ parser.parse("""
+ [SecureContext]
+ interface TestSecureContextOnInterface {
+ const octet TEST_CONSTANT = 0;
+ readonly attribute byte testAttribute;
+ void testMethod(byte foo);
+ };
+ partial interface TestSecureContextOnInterface {
+ const octet TEST_CONSTANT_2 = 0;
+ readonly attribute byte testAttribute2;
+ void testMethod2(byte foo);
+ };
+ """)
+ results = parser.finish()
+ harness.check(len(results[0].members), 6, "TestSecureContextOnInterface should have six members")
+ harness.ok(results[0].getExtendedAttribute("SecureContext"),
+ "Interface should have [SecureContext] extended attribute")
+ harness.ok(results[0].members[0].getExtendedAttribute("SecureContext"),
+ "[SecureContext] should propagate from interface to constant members")
+ harness.ok(results[0].members[1].getExtendedAttribute("SecureContext"),
+ "[SecureContext] should propagate from interface to attribute members")
+ harness.ok(results[0].members[2].getExtendedAttribute("SecureContext"),
+ "[SecureContext] should propagate from interface to method members")
+ harness.ok(results[0].members[3].getExtendedAttribute("SecureContext"),
+ "[SecureContext] should propagate from interface to constant members from partial interface")
+ harness.ok(results[0].members[4].getExtendedAttribute("SecureContext"),
+ "[SecureContext] should propagate from interface to attribute members from partial interface")
+ harness.ok(results[0].members[5].getExtendedAttribute("SecureContext"),
+ "[SecureContext] should propagate from interface to method members from partial interface")
+
+ # Same thing, but with the partial interface specified first:
+ parser = parser.reset()
+ parser.parse("""
+ partial interface TestSecureContextOnInterfaceAfterPartialInterface {
+ const octet TEST_CONSTANT_2 = 0;
+ readonly attribute byte testAttribute2;
+ void testMethod2(byte foo);
+ };
+ [SecureContext]
+ interface TestSecureContextOnInterfaceAfterPartialInterface {
+ const octet TEST_CONSTANT = 0;
+ readonly attribute byte testAttribute;
+ void testMethod(byte foo);
+ };
+ """)
+ results = parser.finish()
+ harness.check(len(results[1].members), 6, "TestSecureContextOnInterfaceAfterPartialInterface should have six members")
+ harness.ok(results[1].getExtendedAttribute("SecureContext"),
+ "Interface should have [SecureContext] extended attribute")
+ harness.ok(results[1].members[0].getExtendedAttribute("SecureContext"),
+ "[SecureContext] should propagate from interface to constant members")
+ harness.ok(results[1].members[1].getExtendedAttribute("SecureContext"),
+ "[SecureContext] should propagate from interface to attribute members")
+ harness.ok(results[1].members[2].getExtendedAttribute("SecureContext"),
+ "[SecureContext] should propagate from interface to method members")
+ harness.ok(results[1].members[3].getExtendedAttribute("SecureContext"),
+ "[SecureContext] should propagate from interface to constant members from partial interface")
+ harness.ok(results[1].members[4].getExtendedAttribute("SecureContext"),
+ "[SecureContext] should propagate from interface to attribute members from partial interface")
+ harness.ok(results[1].members[5].getExtendedAttribute("SecureContext"),
+ "[SecureContext] should propagate from interface to method members from partial interface")
+
+ parser = parser.reset()
+ parser.parse("""
+ interface TestSecureContextOnPartialInterface {
+ const octet TEST_CONSTANT = 0;
+ readonly attribute byte testAttribute;
+ void testMethod(byte foo);
+ };
+ [SecureContext]
+ partial interface TestSecureContextOnPartialInterface {
+ const octet TEST_CONSTANT_2 = 0;
+ readonly attribute byte testAttribute2;
+ void testMethod2(byte foo);
+ };
+ """)
+ results = parser.finish()
+ harness.check(len(results[0].members), 6, "TestSecureContextOnPartialInterface should have six members")
+ harness.ok(results[0].getExtendedAttribute("SecureContext") is None,
+ "[SecureContext] should not propagate from a partial interface to the interface")
+ harness.ok(results[0].members[0].getExtendedAttribute("SecureContext") is None,
+ "[SecureContext] should not propagate from a partial interface to the interface's constant members")
+ harness.ok(results[0].members[1].getExtendedAttribute("SecureContext") is None,
+ "[SecureContext] should not propagate from a partial interface to the interface's attribute members")
+ harness.ok(results[0].members[2].getExtendedAttribute("SecureContext") is None,
+ "[SecureContext] should not propagate from a partial interface to the interface's method members")
+ harness.ok(results[0].members[3].getExtendedAttribute("SecureContext"),
+ "Constant members from [SecureContext] partial interface should be [SecureContext]")
+ harness.ok(results[0].members[4].getExtendedAttribute("SecureContext"),
+ "Attribute members from [SecureContext] partial interface should be [SecureContext]")
+ harness.ok(results[0].members[5].getExtendedAttribute("SecureContext"),
+ "Method members from [SecureContext] partial interface should be [SecureContext]")
+
+ parser = parser.reset()
+ parser.parse("""
+ interface TestSecureContextOnInterfaceMembers {
+ const octet TEST_NON_SECURE_CONSTANT_1 = 0;
+ [SecureContext]
+ const octet TEST_SECURE_CONSTANT = 1;
+ const octet TEST_NON_SECURE_CONSTANT_2 = 2;
+ readonly attribute byte testNonSecureAttribute1;
+ [SecureContext]
+ readonly attribute byte testSecureAttribute;
+ readonly attribute byte testNonSecureAttribute2;
+ void testNonSecureMethod1(byte foo);
+ [SecureContext]
+ void testSecureMethod(byte foo);
+ void testNonSecureMethod2(byte foo);
+ };
+ """)
+ results = parser.finish()
+ harness.check(len(results[0].members), 9, "TestSecureContextOnInterfaceMembers should have nine members")
+ harness.ok(results[0].getExtendedAttribute("SecureContext") is None,
+ "[SecureContext] on members should not propagate up to the interface")
+ harness.ok(results[0].members[0].getExtendedAttribute("SecureContext") is None,
+ "Constant should not have [SecureContext] extended attribute")
+ harness.ok(results[0].members[1].getExtendedAttribute("SecureContext"),
+ "Constant should have [SecureContext] extended attribute")
+ harness.ok(results[0].members[2].getExtendedAttribute("SecureContext") is None,
+ "Constant should not have [SecureContext] extended attribute")
+ harness.ok(results[0].members[3].getExtendedAttribute("SecureContext") is None,
+ "Attribute should not have [SecureContext] extended attribute")
+ harness.ok(results[0].members[4].getExtendedAttribute("SecureContext"),
+ "Attribute should have [SecureContext] extended attribute")
+ harness.ok(results[0].members[5].getExtendedAttribute("SecureContext") is None,
+ "Attribute should not have [SecureContext] extended attribute")
+ harness.ok(results[0].members[6].getExtendedAttribute("SecureContext") is None,
+ "Method should not have [SecureContext] extended attribute")
+ harness.ok(results[0].members[7].getExtendedAttribute("SecureContext"),
+ "Method should have [SecureContext] extended attribute")
+ harness.ok(results[0].members[8].getExtendedAttribute("SecureContext") is None,
+ "Method should not have [SecureContext] extended attribute")
+
+ parser = parser.reset()
+ parser.parse("""
+ interface TestSecureContextOnPartialInterfaceMembers {
+ };
+ partial interface TestSecureContextOnPartialInterfaceMembers {
+ const octet TEST_NON_SECURE_CONSTANT_1 = 0;
+ [SecureContext]
+ const octet TEST_SECURE_CONSTANT = 1;
+ const octet TEST_NON_SECURE_CONSTANT_2 = 2;
+ readonly attribute byte testNonSecureAttribute1;
+ [SecureContext]
+ readonly attribute byte testSecureAttribute;
+ readonly attribute byte testNonSecureAttribute2;
+ void testNonSecureMethod1(byte foo);
+ [SecureContext]
+ void testSecureMethod(byte foo);
+ void testNonSecureMethod2(byte foo);
+ };
+ """)
+ results = parser.finish()
+ harness.check(len(results[0].members), 9, "TestSecureContextOnPartialInterfaceMembers should have nine members")
+ harness.ok(results[0].members[0].getExtendedAttribute("SecureContext") is None,
+ "Constant from partial interface should not have [SecureContext] extended attribute")
+ harness.ok(results[0].members[1].getExtendedAttribute("SecureContext"),
+ "Constant from partial interface should have [SecureContext] extended attribute")
+ harness.ok(results[0].members[2].getExtendedAttribute("SecureContext") is None,
+ "Constant from partial interface should not have [SecureContext] extended attribute")
+ harness.ok(results[0].members[3].getExtendedAttribute("SecureContext") is None,
+ "Attribute from partial interface should not have [SecureContext] extended attribute")
+ harness.ok(results[0].members[4].getExtendedAttribute("SecureContext"),
+ "Attribute from partial interface should have [SecureContext] extended attribute")
+ harness.ok(results[0].members[5].getExtendedAttribute("SecureContext") is None,
+ "Attribute from partial interface should not have [SecureContext] extended attribute")
+ harness.ok(results[0].members[6].getExtendedAttribute("SecureContext") is None,
+ "Method from partial interface should not have [SecureContext] extended attribute")
+ harness.ok(results[0].members[7].getExtendedAttribute("SecureContext"),
+ "Method from partial interface should have [SecureContext] extended attribute")
+ harness.ok(results[0].members[8].getExtendedAttribute("SecureContext") is None,
+ "Method from partial interface should not have [SecureContext] extended attribute")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [SecureContext=something]
+ interface TestSecureContextTakesNoValue1 {
+ const octet TEST_SECURE_CONSTANT = 0;
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+ harness.ok(threw, "[SecureContext] must take no arguments (testing on interface)")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface TestSecureContextForOverloads1 {
+ [SecureContext]
+ void testSecureMethod(byte foo);
+ };
+ partial interface TestSecureContextForOverloads1 {
+ void testSecureMethod(byte foo, byte bar);
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+ harness.ok(threw, "If [SecureContext] appears on an overloaded operation, then it MUST appear on all overloads")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface TestSecureContextForOverloads2 {
+ [SecureContext]
+ void testSecureMethod(byte foo);
+ };
+ partial interface TestSecureContextForOverloads2 {
+ [SecureContext]
+ void testSecureMethod(byte foo, byte bar);
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+ harness.ok(not threw, "[SecureContext] can appear on an overloaded operation if it appears on all overloads")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [SecureContext]
+ interface TestSecureContextOnInterfaceAndMember {
+ [SecureContext]
+ void testSecureMethod(byte foo);
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+ harness.ok(threw, "[SecureContext] must not appear on an interface and interface member")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface TestSecureContextOnPartialInterfaceAndMember {
+ };
+ [SecureContext]
+ partial interface TestSecureContextOnPartialInterfaceAndMember {
+ [SecureContext]
+ void testSecureMethod(byte foo);
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+ harness.ok(threw, "[SecureContext] must not appear on a partial interface and one of the partial interface's member's")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [SecureContext]
+ interface TestSecureContextOnInterfaceAndPartialInterfaceMember {
+ };
+ partial interface TestSecureContextOnInterfaceAndPartialInterfaceMember {
+ [SecureContext]
+ void testSecureMethod(byte foo);
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+ harness.ok(threw, "[SecureContext] must not appear on an interface and one of its partial interface's member's")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [SecureContext]
+ interface TestSecureContextOnInheritedInterface {
+ };
+ interface TestSecureContextNotOnInheritingInterface : TestSecureContextOnInheritedInterface {
+ void testSecureMethod(byte foo);
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+ harness.ok(threw, "[SecureContext] must appear on interfaces that inherit from another [SecureContext] interface")
+
+ # Test 'implements'. The behavior tested here may have to change depending
+ # on the resolution of https://github.com/heycam/webidl/issues/118
+ parser = parser.reset()
+ parser.parse("""
+ [SecureContext]
+ interface TestSecureContextInterfaceThatImplementsNonSecureContextInterface {
+ const octet TEST_CONSTANT = 0;
+ };
+ interface TestNonSecureContextInterface {
+ const octet TEST_CONSTANT_2 = 0;
+ readonly attribute byte testAttribute2;
+ void testMethod2(byte foo);
+ };
+ TestSecureContextInterfaceThatImplementsNonSecureContextInterface implements TestNonSecureContextInterface;
+ """)
+ results = parser.finish()
+ harness.check(len(results[0].members), 4, "TestSecureContextInterfaceThatImplementsNonSecureContextInterface should have two members")
+ harness.ok(results[0].getExtendedAttribute("SecureContext"),
+ "Interface should have [SecureContext] extended attribute")
+ harness.ok(results[0].members[0].getExtendedAttribute("SecureContext"),
+ "[SecureContext] should propagate from interface to constant members even when other members are copied from a non-[SecureContext] interface")
+ harness.ok(results[0].members[1].getExtendedAttribute("SecureContext") is None,
+ "Constants copied from non-[SecureContext] interface should not be [SecureContext]")
+ harness.ok(results[0].members[2].getExtendedAttribute("SecureContext") is None,
+ "Attributes copied from non-[SecureContext] interface should not be [SecureContext]")
+ harness.ok(results[0].members[3].getExtendedAttribute("SecureContext") is None,
+ "Methods copied from non-[SecureContext] interface should not be [SecureContext]")
+
diff --git a/components/script/dom/bindings/codegen/parser/update.sh b/components/script/dom/bindings/codegen/parser/update.sh
index ac4be6c73fd..76a99d9cecb 100755
--- a/components/script/dom/bindings/codegen/parser/update.sh
+++ b/components/script/dom/bindings/codegen/parser/update.sh
@@ -1,4 +1,4 @@
-wget https://mxr.mozilla.org/mozilla-central/source/dom/bindings/parser/WebIDL.py?raw=1 -O WebIDL.py
+wget https://hg.mozilla.org/mozilla-central/raw-file/tip/dom/bindings/parser/WebIDL.py -O WebIDL.py
patch < abstract.patch
patch < debug.patch
patch < pref-main-thread.patch
diff --git a/components/script/dom/bindings/codegen/property.html.template b/components/script/dom/bindings/codegen/property.html.template
new file mode 100644
index 00000000000..7b16aa78d0f
--- /dev/null
+++ b/components/script/dom/bindings/codegen/property.html.template
@@ -0,0 +1,3 @@
+<tr>
+ <td>${name}</td>
+</tr>
diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs
index 1040e7b5965..fe81b8a14de 100644
--- a/components/script/dom/bindings/global.rs
+++ b/components/script/dom/bindings/global.rs
@@ -18,14 +18,15 @@ use ipc_channel::ipc::IpcSender;
use js::jsapi::{CurrentGlobalOrNull, GetGlobalForObjectCrossCompartment};
use js::jsapi::{JSContext, JSObject, JS_GetClass, MutableHandleValue};
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
-use msg::constellation_msg::{PipelineId, PanicMsg};
+use msg::constellation_msg::PipelineId;
use net_traits::filemanager_thread::FileManagerThreadMsg;
-use net_traits::{ResourceThreads, CoreResourceThread, RequestSource, IpcSend};
+use net_traits::{ResourceThreads, CoreResourceThread, IpcSend};
use profile_traits::{mem, time};
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
-use script_thread::{MainThreadScriptChan, ScriptThread};
+use script_thread::{MainThreadScriptChan, ScriptThread, RunnableWrapper};
use script_traits::{MsDuration, ScriptMsg as ConstellationMsg, TimerEventRequest};
use task_source::dom_manipulation::DOMManipulationTaskSource;
+use task_source::file_reading::FileReadingTaskSource;
use timers::{OneshotTimerCallback, OneshotTimerHandle};
use url::Url;
@@ -65,14 +66,6 @@ impl<'a> GlobalRef<'a> {
}
}
- /// gets the custom message channel associated with global object
- pub fn request_source(&self) -> RequestSource {
- match *self {
- GlobalRef::Window(ref window) => RequestSource::Window(window.custom_message_chan()),
- GlobalRef::Worker(ref worker) => RequestSource::Worker(worker.custom_message_chan()),
- }
- }
-
/// Get the `PipelineId` for this global scope.
pub fn pipeline(&self) -> PipelineId {
match *self {
@@ -219,10 +212,10 @@ impl<'a> GlobalRef<'a> {
/// `ScriptChan` used to send messages to the event loop of this global's
/// thread.
- pub fn file_reading_task_source(&self) -> Box<ScriptChan + Send> {
+ pub fn file_reading_task_source(&self) -> FileReadingTaskSource {
match *self {
GlobalRef::Window(ref window) => window.file_reading_task_source(),
- GlobalRef::Worker(ref worker) => worker.script_chan(),
+ GlobalRef::Worker(ref worker) => worker.file_reading_task_source(),
}
}
@@ -290,11 +283,12 @@ impl<'a> GlobalRef<'a> {
}
}
- /// Returns an `IpcSender` to report panics on.
- pub fn panic_chan(&self) -> &IpcSender<PanicMsg> {
+ /// Returns a wrapper for runnables to ensure they are cancelled if the global
+ /// is being destroyed.
+ pub fn get_runnable_wrapper(&self) -> RunnableWrapper {
match *self {
- GlobalRef::Window(ref window) => window.panic_chan(),
- GlobalRef::Worker(ref worker) => worker.panic_chan(),
+ GlobalRef::Window(ref window) => window.get_runnable_wrapper(),
+ GlobalRef::Worker(ref worker) => worker.get_runnable_wrapper(),
}
}
}
diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs
index 310285a8bcd..c73a08d182b 100644
--- a/components/script/dom/bindings/str.rs
+++ b/components/script/dom/bindings/str.rs
@@ -15,7 +15,7 @@ use std::str::{Bytes, FromStr};
use string_cache::Atom;
/// Encapsulates the IDL `ByteString` type.
-#[derive(JSTraceable, Clone, Eq, PartialEq, HeapSizeOf)]
+#[derive(JSTraceable, Clone, Eq, PartialEq, HeapSizeOf, Debug)]
pub struct ByteString(Vec<u8>);
impl ByteString {
@@ -113,6 +113,41 @@ pub fn is_token(s: &[u8]) -> bool {
}
/// A DOMString.
+///
+/// This type corresponds to the [`DOMString`](idl) type in WebIDL.
+///
+/// [idl]: https://heycam.github.io/webidl/#idl-DOMString
+///
+/// Cenceptually, a DOMString has the same value space as a JavaScript String,
+/// i.e., an array of 16-bit *code units* representing UTF-16, potentially with
+/// unpaired surrogates present (also sometimes called WTF-16).
+///
+/// Currently, this type stores a Rust `String`, in order to avoid issues when
+/// integrating with the rest of the Rust ecosystem and even the rest of the
+/// browser itself.
+///
+/// However, Rust `String`s are guaranteed to be valid UTF-8, and as such have
+/// a *smaller value space* than WTF-16 (i.e., some JavaScript String values
+/// can not be represented as a Rust `String`). This introduces the question of
+/// what to do with values being passed from JavaScript to Rust that contain
+/// unpaired surrogates.
+///
+/// The hypothesis is that it does not matter much how exactly those values are
+/// transformed, because passing unpaired surrogates into the DOM is very rare.
+/// In order to test this hypothesis, Servo will panic when encountering any
+/// unpaired surrogates on conversion to `DOMString` by default. (The command
+/// line option `-Z replace-surrogates` instead causes Servo to replace the
+/// unpaired surrogate by a U+FFFD replacement character.)
+///
+/// Currently, the lack of crash reports about this issue provides some
+/// evidence to support the hypothesis. This evidence will hopefully be used to
+/// convince other browser vendors that it would be safe to replace unpaired
+/// surrogates at the boundary between JavaScript and native code. (This would
+/// unify the `DOMString` and `USVString` types, both in the WebIDL standard
+/// and in Servo.)
+///
+/// This type is currently `!Send`, in order to help with an independent
+/// experiment to store `JSString`s rather than Rust `String`s.
#[derive(Clone, Debug, Eq, Hash, HeapSizeOf, Ord, PartialEq, PartialOrd)]
pub struct DOMString(String);
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index e2c6e540a3d..3c13572bf37 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -79,6 +79,7 @@ use std::collections::{BTreeMap, HashMap, HashSet};
use std::hash::{BuildHasher, Hash};
use std::mem;
use std::ops::{Deref, DerefMut};
+use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize};
@@ -88,8 +89,7 @@ use string_cache::{Atom, Namespace, QualName};
use style::attr::{AttrIdentifier, AttrValue, LengthOrPercentageOrAuto};
use style::element_state::*;
use style::properties::PropertyDeclarationBlock;
-use style::restyle_hints::ElementSnapshot;
-use style::selector_impl::PseudoElement;
+use style::selector_impl::{PseudoElement, ElementSnapshot};
use style::values::specified::Length;
use url::Origin as UrlOrigin;
use url::Url;
@@ -331,6 +331,7 @@ no_jsmanaged_fields!(SystemTime);
no_jsmanaged_fields!(SelectedFileId);
no_jsmanaged_fields!(RelativePos);
no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
+no_jsmanaged_fields!(PathBuf);
no_jsmanaged_fields!(CSSErrorReporter);
no_jsmanaged_fields!(WebGLBufferId);
no_jsmanaged_fields!(WebGLFramebufferId);
diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs
index 1b114e90652..ae2b1725319 100644
--- a/components/script/dom/blob.rs
+++ b/components/script/dom/blob.rs
@@ -15,17 +15,29 @@ use encoding::all::UTF_8;
use encoding::types::{EncoderTrap, Encoding};
use ipc_channel::ipc;
use net_traits::IpcSend;
-use net_traits::blob_url_store::BlobURLStoreEntry;
-use net_traits::filemanager_thread::{FileManagerThreadMsg, SelectedFileId, RelativePos};
-use std::ascii::AsciiExt;
+use net_traits::blob_url_store::{BlobBuf, get_blob_origin};
+use net_traits::filemanager_thread::{FileManagerThreadMsg, SelectedFileId, RelativePos, ReadFileProgress};
use std::cell::Cell;
use std::ops::Index;
+use std::path::PathBuf;
+use uuid::Uuid;
+/// File-based blob
+#[derive(JSTraceable)]
+pub struct FileBlob {
+ id: SelectedFileId,
+ name: PathBuf,
+ cache: DOMRefCell<Option<Vec<u8>>>,
+ size: u64,
+}
+
+
+/// Blob backend implementation
#[must_root]
#[derive(JSTraceable)]
pub enum BlobImpl {
- /// File-based blob, including id and possibly cached content
- File(SelectedFileId, DOMRefCell<Option<Vec<u8>>>),
+ /// File-based blob
+ File(FileBlob),
/// Memory-based blob
Memory(Vec<u8>),
/// Sliced blob, including parent blob and
@@ -42,8 +54,13 @@ impl BlobImpl {
}
/// Construct file-backed BlobImpl from File ID
- pub fn new_from_file(file_id: SelectedFileId) -> BlobImpl {
- BlobImpl::File(file_id, DOMRefCell::new(None))
+ pub fn new_from_file(file_id: SelectedFileId, name: PathBuf, size: u64) -> BlobImpl {
+ BlobImpl::File(FileBlob {
+ id: file_id,
+ name: name,
+ cache: DOMRefCell::new(None),
+ size: size,
+ })
}
}
@@ -69,7 +86,9 @@ impl Blob {
Blob {
reflector_: Reflector::new(),
blob_impl: DOMRefCell::new(blob_impl),
- typeString: typeString,
+ // NOTE: Guarding the format correctness here,
+ // https://w3c.github.io/FileAPI/#dfn-type
+ typeString: normalize_type_string(&typeString),
isClosed_: Cell::new(false),
}
}
@@ -79,8 +98,8 @@ impl Blob {
relativeContentType: DOMString) -> Root<Blob> {
let global = parent.global();
let blob_impl = match *parent.blob_impl.borrow() {
- BlobImpl::File(ref id, _) => {
- inc_ref_id(global.r(), id.clone());
+ BlobImpl::File(ref f) => {
+ inc_ref_id(global.r(), f.id.clone());
// Create new parent node
BlobImpl::Sliced(JS::from_ref(parent), rel_pos)
@@ -93,8 +112,8 @@ impl Blob {
// Adjust the slicing position, using same parent
let new_rel_pos = old_rel_pos.slice_inner(&rel_pos);
- if let BlobImpl::File(ref id, _) = *grandparent.blob_impl.borrow() {
- inc_ref_id(global.r(), id.clone());
+ if let BlobImpl::File(ref f) = *grandparent.blob_impl.borrow() {
+ inc_ref_id(global.r(), f.id.clone());
}
BlobImpl::Sliced(grandparent.clone(), new_rel_pos)
@@ -118,28 +137,28 @@ impl Blob {
}
};
- Ok(Blob::new(global, BlobImpl::new_from_bytes(bytes), blobPropertyBag.get_typestring()))
+ Ok(Blob::new(global, BlobImpl::new_from_bytes(bytes), blobPropertyBag.type_.to_string()))
}
/// Get a slice to inner data, this might incur synchronous read and caching
pub fn get_bytes(&self) -> Result<Vec<u8>, ()> {
match *self.blob_impl.borrow() {
- BlobImpl::File(ref id, ref cached) => {
- let buffer = match *cached.borrow() {
- Some(ref s) => Ok(s.clone()),
+ BlobImpl::File(ref f) => {
+ let (buffer, is_new_buffer) = match *f.cache.borrow() {
+ Some(ref bytes) => (bytes.clone(), false),
None => {
let global = self.global();
- let s = read_file(global.r(), id.clone())?;
- Ok(s)
+ let bytes = read_file(global.r(), f.id.clone())?;
+ (bytes, true)
}
};
// Cache
- if let Ok(buf) = buffer.clone() {
- *cached.borrow_mut() = Some(buf);
+ if is_new_buffer {
+ *f.cache.borrow_mut() = Some(buffer.clone());
}
- buffer
+ Ok(buffer)
}
BlobImpl::Memory(ref s) => Ok(s.clone()),
BlobImpl::Sliced(ref parent, ref rel_pos) => {
@@ -155,31 +174,33 @@ impl Blob {
/// used by URL.createObjectURL
pub fn get_blob_url_id(&self) -> SelectedFileId {
match *self.blob_impl.borrow() {
- BlobImpl::File(ref id, _) => {
+ BlobImpl::File(ref f) => {
let global = self.global();
- let origin = global.r().get_url().origin().unicode_serialization();
+ let origin = get_blob_origin(&global.r().get_url());
let filemanager = global.r().resource_threads().sender();
let (tx, rx) = ipc::channel().unwrap();
- let _ = filemanager.send(FileManagerThreadMsg::ActivateBlobURL(id.clone(), tx, origin.clone()));
+ let _ = filemanager.send(FileManagerThreadMsg::ActivateBlobURL(f.id.clone(), tx, origin.clone()));
match rx.recv().unwrap() {
- Ok(_) => id.clone(),
- Err(_) => SelectedFileId("".to_string()) // Return a dummy id on error
+ Ok(_) => f.id.clone(),
+ Err(_) => SelectedFileId(Uuid::new_v4().simple().to_string()) // Return a dummy id on error
}
}
- BlobImpl::Memory(ref slice) => self.promote_to_file(slice),
+ BlobImpl::Memory(ref slice) => {
+ self.promote(slice, true)
+ }
BlobImpl::Sliced(ref parent, ref rel_pos) => {
match *parent.blob_impl.borrow() {
BlobImpl::Sliced(_, _) => {
debug!("Sliced can't have a sliced parent");
// Return dummy id
- SelectedFileId("".to_string())
+ SelectedFileId(Uuid::new_v4().simple().to_string())
}
- BlobImpl::File(ref parent_id, _) =>
- self.create_sliced_url_id(parent_id, rel_pos),
+ BlobImpl::File(ref f) =>
+ self.create_sliced_url_id(&f.id, rel_pos),
BlobImpl::Memory(ref bytes) => {
- let parent_id = parent.promote_to_file(bytes);
+ let parent_id = parent.promote(bytes, false);
*self.blob_impl.borrow_mut() = BlobImpl::Sliced(parent.clone(), rel_pos.clone());
self.create_sliced_url_id(&parent_id, rel_pos)
}
@@ -189,25 +210,28 @@ impl Blob {
}
/// Promite memory-based Blob to file-based,
- /// The bytes in data slice will be transferred to file manager thread
- fn promote_to_file(&self, bytes: &[u8]) -> SelectedFileId {
+ /// The bytes in data slice will be transferred to file manager thread.
+ /// Depending on set_valid, the returned FileID can be part of
+ /// valid or invalid Blob URL.
+ fn promote(&self, bytes: &[u8], set_valid: bool) -> SelectedFileId {
let global = self.global();
- let origin = global.r().get_url().origin().unicode_serialization();
+ let origin = get_blob_origin(&global.r().get_url());
let filemanager = global.r().resource_threads().sender();
- let entry = BlobURLStoreEntry {
+ let blob_buf = BlobBuf {
+ filename: None,
type_string: self.typeString.clone(),
size: self.Size(),
bytes: bytes.to_vec(),
};
let (tx, rx) = ipc::channel().unwrap();
- let _ = filemanager.send(FileManagerThreadMsg::PromoteMemory(entry, tx, origin.clone()));
+ let _ = filemanager.send(FileManagerThreadMsg::PromoteMemory(blob_buf, set_valid, tx, origin.clone()));
match rx.recv().unwrap() {
Ok(new_id) => SelectedFileId(new_id.0),
// Dummy id
- Err(_) => SelectedFileId("".to_string()),
+ Err(_) => SelectedFileId(Uuid::new_v4().simple().to_string()),
}
}
@@ -216,7 +240,7 @@ impl Blob {
rel_pos: &RelativePos) -> SelectedFileId {
let global = self.global();
- let origin = global.r().get_url().origin().unicode_serialization();
+ let origin = get_blob_origin(&global.r().get_url());
let filemanager = global.r().resource_threads().sender();
let (tx, rx) = ipc::channel().unwrap();
@@ -232,14 +256,14 @@ impl Blob {
/// Cleanups at the time of destruction/closing
fn clean_up_file_resource(&self) {
- if let BlobImpl::File(ref id, _) = *self.blob_impl.borrow() {
+ if let BlobImpl::File(ref f) = *self.blob_impl.borrow() {
let global = self.global();
- let origin = global.r().get_url().origin().unicode_serialization();
+ let origin = get_blob_origin(&global.r().get_url());
let filemanager = global.r().resource_threads().sender();
let (tx, rx) = ipc::channel().unwrap();
- let msg = FileManagerThreadMsg::DecRef(id.clone(), origin, tx);
+ let msg = FileManagerThreadMsg::DecRef(f.id.clone(), origin, tx);
let _ = filemanager.send(msg);
let _ = rx.recv().unwrap();
}
@@ -257,19 +281,27 @@ impl Drop for Blob {
fn read_file(global: GlobalRef, id: SelectedFileId) -> Result<Vec<u8>, ()> {
let file_manager = global.filemanager_thread();
let (chan, recv) = ipc::channel().map_err(|_|())?;
- let origin = global.get_url().origin().unicode_serialization();
- let msg = FileManagerThreadMsg::ReadFile(chan, id, origin);
+ let origin = get_blob_origin(&global.get_url());
+ let check_url_validity = false;
+ let msg = FileManagerThreadMsg::ReadFile(chan, id, check_url_validity, origin);
let _ = file_manager.send(msg);
- let result = match recv.recv() {
- Ok(ret) => ret,
- Err(e) => {
- debug!("File manager thread has problem {:?}", e);
- return Err(())
- }
- };
+ let mut bytes = vec![];
- result.map_err(|_|())
+ loop {
+ match recv.recv().unwrap() {
+ Ok(ReadFileProgress::Meta(mut blob_buf)) => {
+ bytes.append(&mut blob_buf.bytes);
+ }
+ Ok(ReadFileProgress::Partial(mut bytes_in)) => {
+ bytes.append(&mut bytes_in);
+ }
+ Ok(ReadFileProgress::EOF) => {
+ return Ok(bytes);
+ }
+ Err(_) => return Err(()),
+ }
+ }
}
/// Extract bytes from BlobParts, used by Blob and File constructor
@@ -314,20 +346,8 @@ impl BlobMethods for Blob {
end: Option<i64>,
contentType: Option<DOMString>)
-> Root<Blob> {
- let relativeContentType = match contentType {
- None => DOMString::new(),
- Some(mut str) => {
- if is_ascii_printable(&str) {
- str.make_ascii_lowercase();
- str
- } else {
- DOMString::new()
- }
- }
- };
-
let rel_pos = RelativePos::from_opts(start, end);
- Blob::new_sliced(self, rel_pos, relativeContentType)
+ Blob::new_sliced(self, rel_pos, contentType.unwrap_or(DOMString::from("")))
}
// https://w3c.github.io/FileAPI/#dfn-isClosed
@@ -350,15 +370,20 @@ impl BlobMethods for Blob {
}
}
-impl BlobBinding::BlobPropertyBag {
- /// Get the normalized inner type string
- /// https://w3c.github.io/FileAPI/#dfn-type
- pub fn get_typestring(&self) -> String {
- if is_ascii_printable(&self.type_) {
- self.type_.to_lowercase()
- } else {
- "".to_string()
- }
+/// Get the normalized, MIME-parsable type string
+/// https://w3c.github.io/FileAPI/#dfn-type
+/// XXX: We will relax the restriction here,
+/// since the spec has some problem over this part.
+/// see https://github.com/w3c/FileAPI/issues/43
+fn normalize_type_string(s: &str) -> String {
+ if is_ascii_printable(s) {
+ let s_lower = s.to_lowercase();
+ // match s_lower.parse() as Result<Mime, ()> {
+ // Ok(_) => s_lower,
+ // Err(_) => "".to_string()
+ s_lower
+ } else {
+ "".to_string()
}
}
@@ -371,7 +396,7 @@ fn is_ascii_printable(string: &str) -> bool {
/// Bump the reference counter in file manager thread
fn inc_ref_id(global: GlobalRef, id: SelectedFileId) {
let file_manager = global.filemanager_thread();
- let origin = global.get_url().origin().unicode_serialization();
+ let origin = get_blob_origin(&global.get_url());
let msg = FileManagerThreadMsg::IncRef(id, origin);
let _ = file_manager.send(msg);
}
diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs
index 0fc9d7a41f2..e3e17b4a0f9 100644
--- a/components/script/dom/bluetoothremotegattcharacteristic.rs
+++ b/components/script/dom/bluetoothremotegattcharacteristic.rs
@@ -76,7 +76,7 @@ impl BluetoothRemoteGATTCharacteristic {
global_ref.as_window().bluetooth_thread()
}
- pub fn get_instance_id(&self) -> String {
+ fn get_instance_id(&self) -> String {
self.instanceID.clone()
}
}
diff --git a/components/script/dom/bluetoothremotegattdescriptor.rs b/components/script/dom/bluetoothremotegattdescriptor.rs
index 035233b01f7..f821d4aca2d 100644
--- a/components/script/dom/bluetoothremotegattdescriptor.rs
+++ b/components/script/dom/bluetoothremotegattdescriptor.rs
@@ -63,7 +63,7 @@ impl BluetoothRemoteGATTDescriptor {
global_ref.as_window().bluetooth_thread()
}
- pub fn get_instance_id(&self) -> String {
+ fn get_instance_id(&self) -> String {
self.instanceID.clone()
}
}
diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs
index cf0f896d3f6..f0954a1c76f 100644
--- a/components/script/dom/bluetoothremotegattservice.rs
+++ b/components/script/dom/bluetoothremotegattservice.rs
@@ -63,7 +63,7 @@ impl BluetoothRemoteGATTService {
global_ref.as_window().bluetooth_thread()
}
- pub fn get_instance_id(&self) -> String {
+ fn get_instance_id(&self) -> String {
self.instanceID.clone()
}
}
diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs
index 87ac897a4e4..d997a33ebd6 100644
--- a/components/script/dom/dedicatedworkerglobalscope.rs
+++ b/components/script/dom/dedicatedworkerglobalscope.rs
@@ -4,7 +4,7 @@
use devtools;
use devtools_traits::DevtoolScriptControlMsg;
-use dom::abstractworker::{WorkerScriptLoadOrigin, WorkerScriptMsg, SharedRt , SimpleWorkerErrorHandler};
+use dom::abstractworker::{WorkerScriptMsg, SharedRt , SimpleWorkerErrorHandler};
use dom::abstractworkerglobalscope::{SendableWorkerScriptChan, WorkerThreadWorkerChan};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding;
@@ -21,7 +21,6 @@ use dom::bindings::structuredclone::StructuredCloneData;
use dom::messageevent::MessageEvent;
use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler};
use dom::workerglobalscope::WorkerGlobalScope;
-use dom::workerglobalscope::WorkerGlobalScopeInit;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
use js::jsapi::{HandleValue, JS_SetInterruptCallback};
@@ -29,17 +28,18 @@ use js::jsapi::{JSAutoCompartment, JSContext};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use msg::constellation_msg::PipelineId;
-use net_traits::{LoadContext, load_whole_resource, CustomResponse, IpcSend};
+use net_traits::{LoadContext, load_whole_resource, IpcSend};
use rand::random;
use script_runtime::ScriptThreadEventCategory::WorkerEvent;
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
-use script_traits::{TimerEvent, TimerSource};
+use script_traits::{TimerEvent, TimerSource, WorkerScriptLoadOrigin, WorkerGlobalScopeInit};
use std::mem::replace;
+use std::sync::atomic::AtomicBool;
use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel};
use std::sync::{Arc, Mutex};
use url::Url;
-use util::thread::spawn_named_with_send_on_panic;
-use util::thread_state::{IN_WORKER, SCRIPT};
+use util::thread::spawn_named;
+use util::thread_state;
/// Set the `worker` field of a related DedicatedWorkerGlobalScope object to a particular
/// value for the duration of this object's lifetime. This ensures that the related Worker
@@ -70,8 +70,7 @@ impl<'a> Drop for AutoWorkerReset<'a> {
enum MixedMessage {
FromWorker((TrustedWorkerAddress, WorkerScriptMsg)),
FromScheduler((TrustedWorkerAddress, TimerEvent)),
- FromDevtools(DevtoolScriptControlMsg),
- FromNetwork(IpcSender<Option<CustomResponse>>),
+ FromDevtools(DevtoolScriptControlMsg)
}
// https://html.spec.whatwg.org/multipage/#dedicatedworkerglobalscope
@@ -102,14 +101,16 @@ impl DedicatedWorkerGlobalScope {
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
timer_event_chan: IpcSender<TimerEvent>,
- timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>)
+ timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>,
+ closing: Arc<AtomicBool>)
-> DedicatedWorkerGlobalScope {
DedicatedWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope::new_inherited(init,
worker_url,
runtime,
from_devtools_receiver,
- timer_event_chan),
+ timer_event_chan,
+ Some(closing)),
id: id,
receiver: receiver,
own_sender: own_sender,
@@ -128,7 +129,8 @@ impl DedicatedWorkerGlobalScope {
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
timer_event_chan: IpcSender<TimerEvent>,
- timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>)
+ timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>,
+ closing: Arc<AtomicBool>)
-> Root<DedicatedWorkerGlobalScope> {
let cx = runtime.cx();
let scope = box DedicatedWorkerGlobalScope::new_inherited(init,
@@ -140,7 +142,8 @@ impl DedicatedWorkerGlobalScope {
own_sender,
receiver,
timer_event_chan,
- timer_event_port);
+ timer_event_port,
+ closing);
DedicatedWorkerGlobalScopeBinding::Wrap(cx, scope)
}
@@ -154,11 +157,14 @@ impl DedicatedWorkerGlobalScope {
parent_sender: Box<ScriptChan + Send>,
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
- worker_load_origin: WorkerScriptLoadOrigin) {
+ worker_load_origin: WorkerScriptLoadOrigin,
+ closing: Arc<AtomicBool>) {
let serialized_worker_url = worker_url.to_string();
let name = format!("WebWorker for {}", serialized_worker_url);
- let panic_chan = init.panic_chan.clone();
- spawn_named_with_send_on_panic(name, SCRIPT | IN_WORKER, move || {
+ spawn_named(name, move || {
+ thread_state::initialize(thread_state::SCRIPT | thread_state::IN_WORKER);
+ PipelineId::install(id);
+
let roots = RootCollection::new();
let _stack_roots_tls = StackRootTLS::new(&roots);
let (url, source) = match load_whole_resource(LoadContext::Script,
@@ -193,7 +199,7 @@ impl DedicatedWorkerGlobalScope {
let global = DedicatedWorkerGlobalScope::new(
init, url, id, devtools_mpsc_port, runtime,
parent_sender.clone(), own_sender, receiver,
- timer_ipc_chan, timer_rx);
+ timer_ipc_chan, timer_rx, closing);
// FIXME(njn): workers currently don't have a unique ID suitable for using in reporter
// registration (#6631), so we instead use a random number and cross our fingers.
let scope = global.upcast::<WorkerGlobalScope>();
@@ -221,7 +227,7 @@ impl DedicatedWorkerGlobalScope {
global.handle_event(event);
}
}, reporter_name, parent_sender, CommonScriptMsg::CollectReports);
- }, Some(id.clone()), panic_chan);
+ });
}
pub fn script_chan(&self) -> Box<ScriptChan + Send> {
@@ -254,20 +260,17 @@ impl DedicatedWorkerGlobalScope {
let worker_port = &self.receiver;
let timer_event_port = &self.timer_event_port;
let devtools_port = scope.from_devtools_receiver();
- let msg_port = scope.custom_message_port();
let sel = Select::new();
let mut worker_handle = sel.handle(worker_port);
let mut timer_event_handle = sel.handle(timer_event_port);
let mut devtools_handle = sel.handle(devtools_port);
- let mut msg_port_handle = sel.handle(msg_port);
unsafe {
worker_handle.add();
timer_event_handle.add();
if scope.from_devtools_sender().is_some() {
devtools_handle.add();
}
- msg_port_handle.add();
}
let ret = sel.wait();
if ret == worker_handle.id() {
@@ -276,8 +279,6 @@ impl DedicatedWorkerGlobalScope {
Ok(MixedMessage::FromScheduler(try!(timer_event_port.recv())))
} else if ret == devtools_handle.id() {
Ok(MixedMessage::FromDevtools(try!(devtools_port.recv())))
- } else if ret == msg_port_handle.id() {
- Ok(MixedMessage::FromNetwork(try!(msg_port.recv())))
} else {
panic!("unexpected select result!")
}
@@ -306,7 +307,7 @@ impl DedicatedWorkerGlobalScope {
let path_seg = format!("url({})", scope.get_url());
let reports = get_reports(cx, path_seg);
reports_chan.send(reports);
- },
+ }
}
}
@@ -339,10 +340,6 @@ impl DedicatedWorkerGlobalScope {
MixedMessage::FromWorker((linked_worker, msg)) => {
let _ar = AutoWorkerReset::new(self, linked_worker);
self.handle_script_event(msg);
- },
- MixedMessage::FromNetwork(network_sender) => {
- // We send None as of now
- let _ = network_sender.send(None);
}
}
}
@@ -373,6 +370,12 @@ impl DedicatedWorkerGlobalScopeMethods for DedicatedWorkerGlobalScope {
Ok(())
}
+ // https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-close
+ fn Close(&self) {
+ // Step 2
+ self.upcast::<WorkerGlobalScope>().close();
+ }
+
// https://html.spec.whatwg.org/multipage/#handler-dedicatedworkerglobalscope-onmessage
event_handler!(message, GetOnmessage, SetOnmessage);
}
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 669c4d9a31a..78ccbbdf1f5 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -122,9 +122,9 @@ use std::sync::Arc;
use string_cache::{Atom, QualName};
use style::attr::AttrValue;
use style::context::ReflowGoal;
-use style::restyle_hints::ElementSnapshot;
-use style::servo::Stylesheet;
+use style::selector_impl::ElementSnapshot;
use style::str::{split_html_space_chars, str_join};
+use style::stylesheets::Stylesheet;
use time;
use url::Url;
use url::percent_encoding::percent_decode;
@@ -239,6 +239,8 @@ pub struct Document {
origin: Origin,
/// https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-states
referrer_policy: Cell<Option<ReferrerPolicy>>,
+ /// https://html.spec.whatwg.org/multipage/#dom-document-referrer
+ referrer: Option<String>,
}
#[derive(JSTraceable, HeapSizeOf)]
@@ -374,6 +376,7 @@ impl Document {
// that workable.
match self.GetDocumentElement() {
Some(root) => {
+ root.upcast::<Node>().is_dirty() ||
root.upcast::<Node>().has_dirty_descendants() ||
!self.modified_elements.borrow().is_empty()
}
@@ -1279,7 +1282,7 @@ impl Document {
if PREFS.is_mozbrowser_enabled() {
if let Some((containing_pipeline_id, subpage_id, _)) = self.window.parent_info() {
let event = ConstellationMsg::MozBrowserEvent(containing_pipeline_id,
- subpage_id,
+ Some(subpage_id),
event);
self.window.constellation_chan().send(event).unwrap();
}
@@ -1369,6 +1372,7 @@ impl Document {
}
pub fn finish_load(&self, load: LoadType) {
+ debug!("Document got finish_load: {:?}", load);
// The parser might need the loader, so restrict the lifetime of the borrow.
{
let mut loader = self.loader.borrow_mut();
@@ -1394,9 +1398,9 @@ impl Document {
// If we don't have a parser, and the reflow timer has been reset, explicitly
// trigger a reflow.
if let LoadType::Stylesheet(_) = load {
- self.window().reflow(ReflowGoal::ForDisplay,
- ReflowQueryType::NoQuery,
- ReflowReason::StylesheetLoaded);
+ self.window.reflow(ReflowGoal::ForDisplay,
+ ReflowQueryType::NoQuery,
+ ReflowReason::StylesheetLoaded);
}
}
@@ -1485,23 +1489,25 @@ impl Document {
return;
}
self.domcontentloaded_dispatched.set(true);
+ assert!(self.ReadyState() != DocumentReadyState::Complete,
+ "Complete before DOMContentLoaded?");
update_with_current_time_ms(&self.dom_content_loaded_event_start);
- self.window().dom_manipulation_task_source().queue_event(self.upcast(), atom!("DOMContentLoaded"),
- EventBubbles::Bubbles, EventCancelable::NotCancelable);
- self.window().reflow(ReflowGoal::ForDisplay,
- ReflowQueryType::NoQuery,
- ReflowReason::DOMContentLoaded);
+ let window = self.window();
+ window.dom_manipulation_task_source().queue_event(self.upcast(), atom!("DOMContentLoaded"),
+ EventBubbles::Bubbles, EventCancelable::NotCancelable, window);
+ window.reflow(ReflowGoal::ForDisplay,
+ ReflowQueryType::NoQuery,
+ ReflowReason::DOMContentLoaded);
update_with_current_time_ms(&self.dom_content_loaded_event_end);
}
pub fn notify_constellation_load(&self) {
let pipeline_id = self.window.pipeline();
- let event = ConstellationMsg::DOMLoad(pipeline_id);
- self.window.constellation_chan().send(event).unwrap();
-
+ let load_event = ConstellationMsg::LoadComplete(pipeline_id);
+ self.window.constellation_chan().send(load_event).unwrap();
}
pub fn set_current_parser(&self, script: Option<ParserRef>) {
@@ -1629,7 +1635,9 @@ impl Document {
content_type: Option<DOMString>,
last_modified: Option<String>,
source: DocumentSource,
- doc_loader: DocumentLoader)
+ doc_loader: DocumentLoader,
+ referrer: Option<String>,
+ referrer_policy: Option<ReferrerPolicy>)
-> Document {
let url = url.unwrap_or_else(|| Url::parse("about:blank").unwrap());
@@ -1648,6 +1656,17 @@ impl Document {
Origin::opaque_identifier()
};
+ // TODO: we currently default to Some(NoReferrer) instead of None (i.e. unset)
+ // for an important reason. Many of the methods by which a referrer policy is communicated
+ // are currently unimplemented, and so in such cases we may be ignoring the desired policy.
+ // If the default were left unset, then in Step 7 of the Fetch algorithm we adopt
+ // no-referrer-when-downgrade. However, since we are potentially ignoring a stricter
+ // referrer policy, this might be passing too much info. Hence, we default to the
+ // strictest policy, which is no-referrer.
+ // Once other delivery methods are implemented, make the unset case really
+ // unset (i.e. None).
+ let referrer_policy = referrer_policy.or(Some(ReferrerPolicy::NoReferrer));
+
Document {
node: Node::new_document_node(),
window: JS::from_ref(window),
@@ -1714,8 +1733,8 @@ impl Document {
https_state: Cell::new(HttpsState::None),
touchpad_pressure_phase: Cell::new(TouchpadPressurePhase::BeforeClick),
origin: origin,
- //TODO - setting this for now so no Referer header set
- referrer_policy: Cell::new(Some(ReferrerPolicy::NoReferrer)),
+ referrer: referrer,
+ referrer_policy: Cell::new(referrer_policy),
}
}
@@ -1732,7 +1751,9 @@ impl Document {
None,
None,
DocumentSource::NotFromParser,
- docloader))
+ docloader,
+ None,
+ None))
}
pub fn new(window: &Window,
@@ -1742,7 +1763,9 @@ impl Document {
content_type: Option<DOMString>,
last_modified: Option<String>,
source: DocumentSource,
- doc_loader: DocumentLoader)
+ doc_loader: DocumentLoader,
+ referrer: Option<String>,
+ referrer_policy: Option<ReferrerPolicy>)
-> Root<Document> {
let document = reflect_dom_object(box Document::new_inherited(window,
browsing_context,
@@ -1751,7 +1774,9 @@ impl Document {
content_type,
last_modified,
source,
- doc_loader),
+ doc_loader,
+ referrer,
+ referrer_policy),
GlobalRef::Window(window),
DocumentBinding::Wrap);
{
@@ -1815,7 +1840,9 @@ impl Document {
None,
None,
DocumentSource::NotFromParser,
- DocumentLoader::new(&self.loader()));
+ DocumentLoader::new(&self.loader()),
+ None,
+ None);
new_doc.appropriate_template_contents_owner_document.set(Some(&new_doc));
new_doc
})
@@ -1827,7 +1854,10 @@ impl Document {
pub fn element_state_will_change(&self, el: &Element) {
let mut map = self.modified_elements.borrow_mut();
- let snapshot = map.entry(JS::from_ref(el)).or_insert(ElementSnapshot::new());
+ let snapshot = map.entry(JS::from_ref(el))
+ .or_insert_with(|| {
+ ElementSnapshot::new(el.html_element_in_html_document())
+ });
if snapshot.state.is_none() {
snapshot.state = Some(el.state());
}
@@ -1835,7 +1865,10 @@ impl Document {
pub fn element_attr_will_change(&self, el: &Element) {
let mut map = self.modified_elements.borrow_mut();
- let mut snapshot = map.entry(JS::from_ref(el)).or_insert(ElementSnapshot::new());
+ let mut snapshot = map.entry(JS::from_ref(el))
+ .or_insert_with(|| {
+ ElementSnapshot::new(el.html_element_in_html_document())
+ });
if snapshot.attrs.is_none() {
let attrs = el.attrs()
.iter()
@@ -1934,6 +1967,14 @@ impl DocumentMethods for Document {
}
}
+ // https://html.spec.whatwg.org/multipage/#dom-document-referrer
+ fn Referrer(&self) -> DOMString {
+ match self.referrer {
+ Some(ref referrer) => DOMString::from(referrer.to_string()),
+ None => DOMString::new()
+ }
+ }
+
// https://dom.spec.whatwg.org/#dom-document-documenturi
fn DocumentURI(&self) -> USVString {
self.URL()
@@ -2831,7 +2872,7 @@ pub fn determine_policy_for_token(token: &str) -> Option<ReferrerPolicy> {
let lower = token.to_lowercase();
return match lower.as_ref() {
"never" | "no-referrer" => Some(ReferrerPolicy::NoReferrer),
- "default" | "no-referrer-when-downgrade" => Some(ReferrerPolicy::NoRefWhenDowngrade),
+ "default" | "no-referrer-when-downgrade" => Some(ReferrerPolicy::NoReferrerWhenDowngrade),
"origin" => Some(ReferrerPolicy::Origin),
"same-origin" => Some(ReferrerPolicy::SameOrigin),
"origin-when-cross-origin" => Some(ReferrerPolicy::OriginWhenCrossOrigin),
@@ -2870,16 +2911,18 @@ impl DocumentProgressHandler {
// http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventStart
update_with_current_time_ms(&document.load_event_start);
+ debug!("About to dispatch load for {:?}", document.url());
let _ = wintarget.dispatch_event_with_target(document.upcast(), &event);
// http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventEnd
update_with_current_time_ms(&document.load_event_end);
- document.notify_constellation_load();
window.reflow(ReflowGoal::ForDisplay,
ReflowQueryType::NoQuery,
ReflowReason::DocumentLoaded);
+
+ document.notify_constellation_load();
}
}
diff --git a/components/script/dom/documenttype.rs b/components/script/dom/documenttype.rs
index 0f8b688c93b..c48805eed79 100644
--- a/components/script/dom/documenttype.rs
+++ b/components/script/dom/documenttype.rs
@@ -41,8 +41,9 @@ impl DocumentType {
system_id: Option<DOMString>,
document: &Document)
-> Root<DocumentType> {
- let documenttype = DocumentType::new_inherited(name, public_id, system_id, document);
- Node::reflect_node(box documenttype, document, DocumentTypeBinding::Wrap)
+ Node::reflect_node(box DocumentType::new_inherited(name, public_id, system_id, document),
+ document,
+ DocumentTypeBinding::Wrap)
}
#[inline]
diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs
index 30974ea2f46..824cc0b88cf 100644
--- a/components/script/dom/domimplementation.rs
+++ b/components/script/dom/domimplementation.rs
@@ -129,7 +129,9 @@ impl DOMImplementationMethods for DOMImplementation {
None,
None,
DocumentSource::NotFromParser,
- loader);
+ loader,
+ None,
+ None);
{
// Step 3.
diff --git a/components/script/dom/domparser.rs b/components/script/dom/domparser.rs
index 346b8f80170..3964c84abcb 100644
--- a/components/script/dom/domparser.rs
+++ b/components/script/dom/domparser.rs
@@ -68,7 +68,9 @@ impl DOMParserMethods for DOMParser {
Some(content_type),
None,
DocumentSource::FromParser,
- loader);
+ loader,
+ None,
+ None);
parse_html(document.r(), s, url, ParseContext::Owner(None));
document.set_ready_state(DocumentReadyState::Complete);
Ok(document)
@@ -82,7 +84,9 @@ impl DOMParserMethods for DOMParser {
Some(content_type),
None,
DocumentSource::NotFromParser,
- loader);
+ loader,
+ None,
+ None);
parse_xml(document.r(), s, url, xml::ParseContext::Owner(None));
Ok(document)
}
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 6b671d6fe6b..a4c1ed28583 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -78,6 +78,7 @@ use selectors::parser::{AttrSelector, NamespaceConstraint, parse_author_origin_s
use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::cell::{Cell, Ref};
+use std::convert::TryFrom;
use std::default::Default;
use std::mem;
use std::sync::Arc;
@@ -126,8 +127,10 @@ pub enum AdjacentPosition {
BeforeEnd,
}
-impl AdjacentPosition {
- pub fn parse(position: &str) -> Fallible<AdjacentPosition> {
+impl<'a> TryFrom<&'a str> for AdjacentPosition {
+ type Err = Error;
+
+ fn try_from(position: &'a str) -> Result<AdjacentPosition, Self::Err> {
match_ignore_ascii_case! { &*position,
"beforebegin" => Ok(AdjacentPosition::BeforeBegin),
"afterbegin" => Ok(AdjacentPosition::AfterBegin),
@@ -2028,7 +2031,7 @@ impl ElementMethods for Element {
// https://dom.spec.whatwg.org/#dom-element-insertadjacentelement
fn InsertAdjacentElement(&self, where_: DOMString, element: &Element)
-> Fallible<Option<Root<Element>>> {
- let where_ = try!(AdjacentPosition::parse(&*where_));
+ let where_ = try!(AdjacentPosition::try_from(&*where_));
let inserted_node = try!(self.insert_adjacent(where_, element.upcast()));
Ok(inserted_node.map(|node| Root::downcast(node).unwrap()))
}
@@ -2040,7 +2043,7 @@ impl ElementMethods for Element {
let text = Text::new(data, &document_from_node(self));
// Step 2.
- let where_ = try!(AdjacentPosition::parse(&*where_));
+ let where_ = try!(AdjacentPosition::try_from(&*where_));
self.insert_adjacent(where_, text.upcast()).map(|_| ())
}
@@ -2048,7 +2051,7 @@ impl ElementMethods for Element {
fn InsertAdjacentHTML(&self, position: DOMString, text: DOMString)
-> ErrorResult {
// Step 1.
- let position = try!(AdjacentPosition::parse(&*position));
+ let position = try!(AdjacentPosition::try_from(&*position));
let context = match position {
AdjacentPosition::BeforeBegin | AdjacentPosition::AfterEnd => {
diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs
index 9174fa2cb3d..da7664e0e19 100644
--- a/components/script/dom/event.rs
+++ b/components/script/dom/event.rs
@@ -8,9 +8,11 @@ use dom::bindings::codegen::Bindings::EventBinding::{EventConstants, EventMethod
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutNullableHeap, Root};
+use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
use dom::eventtarget::EventTarget;
+use script_thread::Runnable;
use std::cell::Cell;
use std::default::Default;
use string_cache::Atom;
@@ -26,7 +28,7 @@ pub enum EventPhase {
Bubbling = EventConstants::BUBBLING_PHASE,
}
-#[derive(PartialEq, HeapSizeOf)]
+#[derive(PartialEq, HeapSizeOf, Copy, Clone)]
pub enum EventBubbles {
Bubbles,
DoesNotBubble
@@ -50,7 +52,7 @@ impl From<bool> for EventBubbles {
}
}
-#[derive(PartialEq, HeapSizeOf)]
+#[derive(PartialEq, HeapSizeOf, Copy, Clone)]
pub enum EventCancelable {
Cancelable,
NotCancelable
@@ -297,3 +299,35 @@ impl Event {
target.dispatch_event(self)
}
}
+
+// https://dom.spec.whatwg.org/#concept-event-fire
+pub struct EventRunnable {
+ pub target: Trusted<EventTarget>,
+ pub name: Atom,
+ pub bubbles: EventBubbles,
+ pub cancelable: EventCancelable,
+}
+
+impl Runnable for EventRunnable {
+ fn name(&self) -> &'static str { "EventRunnable" }
+
+ fn handler(self: Box<EventRunnable>) {
+ let target = self.target.root();
+ target.fire_event(&*self.name, self.bubbles, self.cancelable);
+ }
+}
+
+// https://html.spec.whatwg.org/multipage/#fire-a-simple-event
+pub struct SimpleEventRunnable {
+ pub target: Trusted<EventTarget>,
+ pub name: Atom,
+}
+
+impl Runnable for SimpleEventRunnable {
+ fn name(&self) -> &'static str { "SimpleEventRunnable" }
+
+ fn handler(self: Box<SimpleEventRunnable>) {
+ let target = self.target.root();
+ target.fire_simple_event(&*self.name);
+ }
+}
diff --git a/components/script/dom/file.rs b/components/script/dom/file.rs
index 75f73aeda59..f9b181dbf1a 100644
--- a/components/script/dom/file.rs
+++ b/components/script/dom/file.rs
@@ -54,7 +54,8 @@ impl File {
let global = GlobalRef::Window(window);
- File::new(global, BlobImpl::new_from_file(selected.id), name, Some(selected.modified as i64), "")
+ File::new(global, BlobImpl::new_from_file(selected.id, selected.filename, selected.size),
+ name, Some(selected.modified as i64), &selected.type_string)
}
// https://w3c.github.io/FileAPI/#file-constructor
@@ -69,10 +70,13 @@ impl File {
};
let ref blobPropertyBag = filePropertyBag.parent;
- let typeString = blobPropertyBag.get_typestring();
+ let ref typeString = blobPropertyBag.type_;
let modified = filePropertyBag.lastModified;
- Ok(File::new(global, BlobImpl::new_from_bytes(bytes), filename, modified, &typeString))
+ // NOTE: Following behaviour might be removed in future,
+ // see https://github.com/w3c/FileAPI/issues/41
+ let replaced_filename = DOMString::from_string(filename.replace("/", ":"));
+ Ok(File::new(global, BlobImpl::new_from_bytes(bytes), replaced_filename, modified, typeString))
}
pub fn name(&self) -> &DOMString {
diff --git a/components/script/dom/filereader.rs b/components/script/dom/filereader.rs
index be57d67f7c0..a82e4dc47bc 100644
--- a/components/script/dom/filereader.rs
+++ b/components/script/dom/filereader.rs
@@ -23,12 +23,12 @@ use encoding::label::encoding_from_whatwg_label;
use encoding::types::{DecoderTrap, EncodingRef};
use hyper::mime::{Attr, Mime};
use rustc_serialize::base64::{CharacterSet, Config, Newline, ToBase64};
-use script_runtime::ScriptThreadEventCategory::FileRead;
-use script_runtime::{ScriptChan, CommonScriptMsg};
-use script_thread::Runnable;
+use script_thread::RunnableWrapper;
use std::cell::Cell;
use std::sync::Arc;
use string_cache::Atom;
+use task_source::TaskSource;
+use task_source::file_reading::{FileReadingTaskSource, FileReadingRunnable, FileReadingTask};
use util::thread::spawn_named;
#[derive(PartialEq, Clone, Copy, JSTraceable, HeapSizeOf)]
@@ -358,10 +358,11 @@ impl FileReader {
let fr = Trusted::new(self);
let gen_id = self.generation_id.get();
- let script_chan = self.global().r().file_reading_task_source();
+ let wrapper = self.global().r().get_runnable_wrapper();
+ let task_source = self.global().r().file_reading_task_source();
spawn_named("file reader async operation".to_owned(), move || {
- perform_annotated_read_operation(gen_id, load_data, blob_contents, fr, script_chan)
+ perform_annotated_read_operation(gen_id, load_data, blob_contents, fr, task_source, wrapper)
});
Ok(())
}
@@ -371,47 +372,20 @@ impl FileReader {
}
}
-#[derive(Clone)]
-pub enum FileReaderEvent {
- ProcessRead(TrustedFileReader, GenerationId),
- ProcessReadData(TrustedFileReader, GenerationId),
- ProcessReadError(TrustedFileReader, GenerationId, DOMErrorName),
- ProcessReadEOF(TrustedFileReader, GenerationId, ReadMetaData, Arc<Vec<u8>>)
-}
-
-impl Runnable for FileReaderEvent {
- fn name(&self) -> &'static str { "FileReaderEvent" }
-
- fn handler(self: Box<FileReaderEvent>) {
- let file_reader_event = *self;
- match file_reader_event {
- FileReaderEvent::ProcessRead(filereader, gen_id) => {
- FileReader::process_read(filereader, gen_id);
- },
- FileReaderEvent::ProcessReadData(filereader, gen_id) => {
- FileReader::process_read_data(filereader, gen_id);
- },
- FileReaderEvent::ProcessReadError(filereader, gen_id, error) => {
- FileReader::process_read_error(filereader, gen_id, error);
- },
- FileReaderEvent::ProcessReadEOF(filereader, gen_id, data, blob_contents) => {
- FileReader::process_read_eof(filereader, gen_id, data, blob_contents);
- }
- }
- }
-}
-
// https://w3c.github.io/FileAPI/#thread-read-operation
-fn perform_annotated_read_operation(gen_id: GenerationId, data: ReadMetaData, blob_contents: Arc<Vec<u8>>,
- filereader: TrustedFileReader, script_chan: Box<ScriptChan + Send>) {
- let chan = &script_chan;
+fn perform_annotated_read_operation(gen_id: GenerationId,
+ data: ReadMetaData,
+ blob_contents: Arc<Vec<u8>>,
+ filereader: TrustedFileReader,
+ task_source: FileReadingTaskSource,
+ wrapper: RunnableWrapper) {
// Step 4
- let thread = box FileReaderEvent::ProcessRead(filereader.clone(), gen_id);
- chan.send(CommonScriptMsg::RunnableMsg(FileRead, thread)).unwrap();
+ let task = FileReadingRunnable::new(FileReadingTask::ProcessRead(filereader.clone(), gen_id));
+ task_source.queue_with_wrapper(task, &wrapper).unwrap();
- let thread = box FileReaderEvent::ProcessReadData(filereader.clone(), gen_id);
- chan.send(CommonScriptMsg::RunnableMsg(FileRead, thread)).unwrap();
+ let task = FileReadingRunnable::new(FileReadingTask::ProcessReadData(filereader.clone(), gen_id));
+ task_source.queue_with_wrapper(task, &wrapper).unwrap();
- let thread = box FileReaderEvent::ProcessReadEOF(filereader, gen_id, data, blob_contents);
- chan.send(CommonScriptMsg::RunnableMsg(FileRead, thread)).unwrap();
+ let task = FileReadingRunnable::new(FileReadingTask::ProcessReadEOF(filereader, gen_id, data, blob_contents));
+ task_source.queue_with_wrapper(task, &wrapper).unwrap();
}
diff --git a/components/script/dom/headers.rs b/components/script/dom/headers.rs
new file mode 100644
index 00000000000..e97edc00572
--- /dev/null
+++ b/components/script/dom/headers.rs
@@ -0,0 +1,251 @@
+/* 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::cell::DOMRefCell;
+use dom::bindings::codegen::Bindings::HeadersBinding;
+use dom::bindings::codegen::Bindings::HeadersBinding::HeadersMethods;
+use dom::bindings::error::Error;
+use dom::bindings::global::GlobalRef;
+use dom::bindings::js::Root;
+use dom::bindings::reflector::{Reflector, reflect_dom_object};
+use dom::bindings::str::{ByteString, is_token};
+use hyper;
+use std::result::Result;
+
+#[dom_struct]
+pub struct Headers {
+ reflector_: Reflector,
+ guard: Guard,
+ #[ignore_heap_size_of = "Defined in hyper"]
+ header_list: DOMRefCell<hyper::header::Headers>
+}
+
+// https://fetch.spec.whatwg.org/#concept-headers-guard
+#[derive(JSTraceable, HeapSizeOf, PartialEq)]
+pub enum Guard {
+ Immutable,
+ Request,
+ RequestNoCors,
+ Response,
+ None,
+}
+
+impl Headers {
+ pub fn new_inherited() -> Headers {
+ Headers {
+ reflector_: Reflector::new(),
+ guard: Guard::None,
+ header_list: DOMRefCell::new(hyper::header::Headers::new()),
+ }
+ }
+
+ pub fn new(global: GlobalRef) -> Root<Headers> {
+ reflect_dom_object(box Headers::new_inherited(), global, HeadersBinding::Wrap)
+ }
+}
+
+impl HeadersMethods for Headers {
+ // https://fetch.spec.whatwg.org/#concept-headers-append
+ fn Append(&self, name: ByteString, value: ByteString) -> Result<(), Error> {
+ // Step 1
+ let value = normalize_value(value);
+
+ // Step 2
+ let (valid_name, valid_value) = try!(validate_name_and_value(name, value));
+ // Step 3
+ if self.guard == Guard::Immutable {
+ return Err(Error::Type("Guard is immutable".to_string()));
+ }
+
+ // Step 4
+ if self.guard == Guard::Request && is_forbidden_header_name(&valid_name) {
+ return Ok(());
+ }
+
+ // Step 5
+ if self.guard == Guard::RequestNoCors && !is_cors_safelisted_request_header(&valid_name) {
+ return Ok(());
+ }
+
+ // Step 6
+ if self.guard == Guard::Response && is_forbidden_response_header(&valid_name) {
+ return Ok(());
+ }
+
+ // Step 7
+ self.header_list.borrow_mut().set_raw(valid_name, vec![valid_value]);
+ return Ok(());
+ }
+}
+
+// TODO
+// "Content-Type" once parsed, the value should be
+// `application/x-www-form-urlencoded`, `multipart/form-data`,
+// or `text/plain`.
+// "DPR", "Downlink", "Save-Data", "Viewport-Width", "Width":
+// once parsed, the value should not be failure.
+// https://fetch.spec.whatwg.org/#cors-safelisted-request-header
+fn is_cors_safelisted_request_header(name: &str) -> bool {
+ match name {
+ "accept" |
+ "accept-language" |
+ "content-language" => true,
+ _ => false,
+ }
+}
+
+// https://fetch.spec.whatwg.org/#forbidden-response-header-name
+fn is_forbidden_response_header(name: &str) -> bool {
+ match name {
+ "set-cookie" |
+ "set-cookie2" => true,
+ _ => false,
+ }
+}
+
+// https://fetch.spec.whatwg.org/#forbidden-header-name
+pub fn is_forbidden_header_name(name: &str) -> bool {
+ let disallowed_headers =
+ ["accept-charset", "accept-encoding",
+ "access-control-request-headers",
+ "access-control-request-method",
+ "connection", "content-length",
+ "cookie", "cookie2", "date", "dnt",
+ "expect", "host", "keep-alive", "origin",
+ "referer", "te", "trailer", "transfer-encoding",
+ "upgrade", "via"];
+
+ let disallowed_header_prefixes = ["sec-", "proxy-"];
+
+ disallowed_headers.iter().any(|header| *header == name) ||
+ disallowed_header_prefixes.iter().any(|prefix| name.starts_with(prefix))
+}
+
+// There is some unresolved confusion over the definition of a name and a value.
+// The fetch spec [1] defines a name as "a case-insensitive byte
+// sequence that matches the field-name token production. The token
+// productions are viewable in [2]." A field-name is defined as a
+// token, which is defined in [3].
+// ISSUE 1:
+// It defines a value as "a byte sequence that matches the field-content token production."
+// To note, there is a difference between field-content and
+// field-value (which is made up of fied-content and obs-fold). The
+// current definition does not allow for obs-fold (which are white
+// space and newlines) in values. So perhaps a value should be defined
+// as "a byte sequence that matches the field-value token production."
+// However, this would then allow values made up entirely of white space and newlines.
+// RELATED ISSUE 2:
+// According to a previously filed Errata ID: 4189 in [4], "the
+// specified field-value rule does not allow single field-vchar
+// surrounded by whitespace anywhere". They provided a fix for the
+// field-content production, but ISSUE 1 has still not been resolved.
+// The production definitions likely need to be re-written.
+// [1] https://fetch.spec.whatwg.org/#concept-header-value
+// [2] https://tools.ietf.org/html/rfc7230#section-3.2
+// [3] https://tools.ietf.org/html/rfc7230#section-3.2.6
+// [4] https://www.rfc-editor.org/errata_search.php?rfc=7230
+fn validate_name_and_value(name: ByteString, value: ByteString)
+ -> Result<(String, Vec<u8>), Error> {
+ if !is_field_name(&name) {
+ return Err(Error::Type("Name is not valid".to_string()));
+ }
+ if !is_field_content(&value) {
+ return Err(Error::Type("Value is not valid".to_string()));
+ }
+ match String::from_utf8(name.into()) {
+ Ok(ns) => Ok((ns, value.into())),
+ _ => Err(Error::Type("Non-UTF8 header name found".to_string())),
+ }
+}
+
+// Removes trailing and leading HTTP whitespace bytes.
+// https://fetch.spec.whatwg.org/#concept-header-value-normalize
+pub fn normalize_value(value: ByteString) -> ByteString {
+ match (index_of_first_non_whitespace(&value), index_of_last_non_whitespace(&value)) {
+ (Some(begin), Some(end)) => ByteString::new(value[begin..end + 1].to_owned()),
+ _ => ByteString::new(vec![]),
+ }
+}
+
+fn is_HTTP_whitespace(byte: u8) -> bool {
+ byte == b'\t' || byte == b'\n' || byte == b'\r' || byte == b' '
+}
+
+fn index_of_first_non_whitespace(value: &ByteString) -> Option<usize> {
+ for (index, &byte) in value.iter().enumerate() {
+ if !is_HTTP_whitespace(byte) {
+ return Some(index);
+ }
+ }
+ None
+}
+
+fn index_of_last_non_whitespace(value: &ByteString) -> Option<usize> {
+ for (index, &byte) in value.iter().enumerate().rev() {
+ if !is_HTTP_whitespace(byte) {
+ return Some(index);
+ }
+ }
+ None
+}
+
+// http://tools.ietf.org/html/rfc7230#section-3.2
+fn is_field_name(name: &ByteString) -> bool {
+ is_token(&*name)
+}
+
+// https://tools.ietf.org/html/rfc7230#section-3.2
+// http://www.rfc-editor.org/errata_search.php?rfc=7230
+// Errata ID: 4189
+// field-content = field-vchar [ 1*( SP / HTAB / field-vchar )
+// field-vchar ]
+fn is_field_content(value: &ByteString) -> bool {
+ if value.len() == 0 {
+ return false;
+ }
+ if !is_field_vchar(value[0]) {
+ return false;
+ }
+
+ for &ch in &value[1..value.len() - 1] {
+ if !is_field_vchar(ch) || !is_space(ch) || !is_htab(ch) {
+ return false;
+ }
+ }
+
+ if !is_field_vchar(value[value.len() - 1]) {
+ return false;
+ }
+
+ return true;
+}
+
+fn is_space(x: u8) -> bool {
+ x == b' '
+}
+
+fn is_htab(x: u8) -> bool {
+ x == b'\t'
+}
+
+// https://tools.ietf.org/html/rfc7230#section-3.2
+fn is_field_vchar(x: u8) -> bool {
+ is_vchar(x) || is_obs_text(x)
+}
+
+// https://tools.ietf.org/html/rfc5234#appendix-B.1
+fn is_vchar(x: u8) -> bool {
+ match x {
+ 0x21...0x7E => true,
+ _ => false,
+ }
+}
+
+// http://tools.ietf.org/html/rfc7230#section-3.2.6
+fn is_obs_text(x: u8) -> bool {
+ match x {
+ 0x80...0xFF => true,
+ _ => false,
+ }
+}
diff --git a/components/script/dom/history.rs b/components/script/dom/history.rs
new file mode 100644
index 00000000000..061d7616f4a
--- /dev/null
+++ b/components/script/dom/history.rs
@@ -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::codegen::Bindings::HistoryBinding;
+use dom::bindings::codegen::Bindings::HistoryBinding::HistoryMethods;
+use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods;
+use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
+use dom::bindings::global::GlobalRef;
+use dom::bindings::js::{JS, Root};
+use dom::bindings::reflector::{Reflector, reflect_dom_object};
+use dom::window::Window;
+use msg::constellation_msg::TraversalDirection;
+use script_traits::ScriptMsg as ConstellationMsg;
+
+// https://html.spec.whatwg.org/multipage/#the-history-interface
+#[dom_struct]
+pub struct History {
+ reflector_: Reflector,
+ window: JS<Window>,
+}
+
+impl History {
+ pub fn new_inherited(window: &Window) -> History {
+ History {
+ reflector_: Reflector::new(),
+ window: JS::from_ref(&window),
+ }
+ }
+
+ pub fn new(window: &Window) -> Root<History> {
+ reflect_dom_object(box History::new_inherited(window),
+ GlobalRef::Window(window),
+ HistoryBinding::Wrap)
+ }
+}
+
+impl History {
+ fn traverse_history(&self, direction: TraversalDirection) {
+ let pipeline = self.window.pipeline();
+ let msg = ConstellationMsg::TraverseHistory(Some(pipeline), direction);
+ let _ = self.window.constellation_chan().send(msg);
+ }
+}
+
+impl HistoryMethods for History {
+ // https://html.spec.whatwg.org/multipage/#dom-history-go
+ fn Go(&self, delta: i32) {
+ let direction = if delta > 0 {
+ TraversalDirection::Forward(delta as usize)
+ } else if delta < 0 {
+ TraversalDirection::Back(-delta as usize)
+ } else {
+ self.window.Location().Reload();
+ return;
+ };
+
+ self.traverse_history(direction);
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-history-back
+ fn Back(&self) {
+ self.traverse_history(TraversalDirection::Back(1));
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-history-forward
+ fn Forward(&self) {
+ self.traverse_history(TraversalDirection::Forward(1));
+ }
+}
diff --git a/components/script/dom/htmlanchorelement.rs b/components/script/dom/htmlanchorelement.rs
index 713aa0a92cb..e9df2b6c999 100644
--- a/components/script/dom/htmlanchorelement.rs
+++ b/components/script/dom/htmlanchorelement.rs
@@ -54,8 +54,9 @@ impl HTMLAnchorElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLAnchorElement> {
- let element = HTMLAnchorElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLAnchorElementBinding::Wrap)
+ Node::reflect_node(box HTMLAnchorElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLAnchorElementBinding::Wrap)
}
// https://html.spec.whatwg.org/multipage/#concept-hyperlink-url-set
diff --git a/components/script/dom/htmlappletelement.rs b/components/script/dom/htmlappletelement.rs
index 16d7e46b10e..f61a6499ea1 100644
--- a/components/script/dom/htmlappletelement.rs
+++ b/components/script/dom/htmlappletelement.rs
@@ -33,8 +33,9 @@ impl HTMLAppletElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLAppletElement> {
- let element = HTMLAppletElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLAppletElementBinding::Wrap)
+ Node::reflect_node(box HTMLAppletElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLAppletElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlareaelement.rs b/components/script/dom/htmlareaelement.rs
index 7998333810e..511308dd8fc 100644
--- a/components/script/dom/htmlareaelement.rs
+++ b/components/script/dom/htmlareaelement.rs
@@ -34,8 +34,9 @@ impl HTMLAreaElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLAreaElement> {
- let element = HTMLAreaElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLAreaElementBinding::Wrap)
+ Node::reflect_node(box HTMLAreaElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLAreaElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlaudioelement.rs b/components/script/dom/htmlaudioelement.rs
index 4db6b013116..ad3062a1077 100644
--- a/components/script/dom/htmlaudioelement.rs
+++ b/components/script/dom/htmlaudioelement.rs
@@ -29,7 +29,8 @@ impl HTMLAudioElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLAudioElement> {
- let element = HTMLAudioElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLAudioElementBinding::Wrap)
+ Node::reflect_node(box HTMLAudioElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLAudioElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlbaseelement.rs b/components/script/dom/htmlbaseelement.rs
index e0c38b1ab41..9175cc77872 100644
--- a/components/script/dom/htmlbaseelement.rs
+++ b/components/script/dom/htmlbaseelement.rs
@@ -33,8 +33,9 @@ impl HTMLBaseElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLBaseElement> {
- let element = HTMLBaseElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLBaseElementBinding::Wrap)
+ Node::reflect_node(box HTMLBaseElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLBaseElementBinding::Wrap)
}
/// https://html.spec.whatwg.org/multipage/#frozen-base-url
diff --git a/components/script/dom/htmlbodyelement.rs b/components/script/dom/htmlbodyelement.rs
index 79dbd1438e4..c8007c39ea8 100644
--- a/components/script/dom/htmlbodyelement.rs
+++ b/components/script/dom/htmlbodyelement.rs
@@ -42,8 +42,9 @@ impl HTMLBodyElement {
#[allow(unrooted_must_root)]
pub fn new(localName: Atom, prefix: Option<DOMString>, document: &Document)
-> Root<HTMLBodyElement> {
- let element = HTMLBodyElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLBodyElementBinding::Wrap)
+ Node::reflect_node(box HTMLBodyElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLBodyElementBinding::Wrap)
}
/// https://drafts.csswg.org/cssom-view/#the-html-body-element
diff --git a/components/script/dom/htmlbrelement.rs b/components/script/dom/htmlbrelement.rs
index e95a667c0c4..b2d0067c3f6 100644
--- a/components/script/dom/htmlbrelement.rs
+++ b/components/script/dom/htmlbrelement.rs
@@ -26,7 +26,8 @@ impl HTMLBRElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLBRElement> {
- let element = HTMLBRElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLBRElementBinding::Wrap)
+ Node::reflect_node(box HTMLBRElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLBRElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlbuttonelement.rs b/components/script/dom/htmlbuttonelement.rs
index 23b9b79cc5d..6c15cf92150 100644
--- a/components/script/dom/htmlbuttonelement.rs
+++ b/components/script/dom/htmlbuttonelement.rs
@@ -58,8 +58,9 @@ impl HTMLButtonElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLButtonElement> {
- let element = HTMLButtonElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLButtonElementBinding::Wrap)
+ Node::reflect_node(box HTMLButtonElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLButtonElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs
index add54917e6d..38969860722 100644
--- a/components/script/dom/htmlcanvaselement.rs
+++ b/components/script/dom/htmlcanvaselement.rs
@@ -67,8 +67,9 @@ impl HTMLCanvasElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLCanvasElement> {
- let element = HTMLCanvasElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap)
+ Node::reflect_node(box HTMLCanvasElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLCanvasElementBinding::Wrap)
}
fn recreate_contexts(&self) {
diff --git a/components/script/dom/htmlcollection.rs b/components/script/dom/htmlcollection.rs
index 798d0731b2c..95134556bc0 100644
--- a/components/script/dom/htmlcollection.rs
+++ b/components/script/dom/htmlcollection.rs
@@ -248,7 +248,7 @@ impl<'a> Iterator for HTMLCollectionElementsIter<'a> {
.filter_map(Root::downcast)
.filter(|element| filter.filter(&element, root))
.next()
- }
+ }
}
impl HTMLCollectionMethods for HTMLCollection {
diff --git a/components/script/dom/htmldataelement.rs b/components/script/dom/htmldataelement.rs
index c665fece132..f412fd57570 100644
--- a/components/script/dom/htmldataelement.rs
+++ b/components/script/dom/htmldataelement.rs
@@ -28,7 +28,8 @@ impl HTMLDataElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLDataElement> {
- let element = HTMLDataElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLDataElementBinding::Wrap)
+ Node::reflect_node(box HTMLDataElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLDataElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmldatalistelement.rs b/components/script/dom/htmldatalistelement.rs
index a44e3965d5c..b592457fea2 100644
--- a/components/script/dom/htmldatalistelement.rs
+++ b/components/script/dom/htmldatalistelement.rs
@@ -34,8 +34,9 @@ impl HTMLDataListElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLDataListElement> {
- let element = HTMLDataListElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLDataListElementBinding::Wrap)
+ Node::reflect_node(box HTMLDataListElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLDataListElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmldetailselement.rs b/components/script/dom/htmldetailselement.rs
index f8fc6545f8d..3c86a9fd0d9 100644
--- a/components/script/dom/htmldetailselement.rs
+++ b/components/script/dom/htmldetailselement.rs
@@ -5,6 +5,7 @@
use dom::attr::Attr;
use dom::bindings::codegen::Bindings::HTMLDetailsElementBinding;
use dom::bindings::codegen::Bindings::HTMLDetailsElementBinding::HTMLDetailsElementMethods;
+use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::refcounted::Trusted;
@@ -19,7 +20,6 @@ use script_thread::Runnable;
use std::cell::Cell;
use string_cache::Atom;
use task_source::TaskSource;
-use task_source::dom_manipulation::DOMManipulationTask;
#[dom_struct]
pub struct HTMLDetailsElement {
@@ -42,8 +42,9 @@ impl HTMLDetailsElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLDetailsElement> {
- let element = HTMLDetailsElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLDetailsElementBinding::Wrap)
+ Node::reflect_node(box HTMLDetailsElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLDetailsElementBinding::Wrap)
}
pub fn check_toggle_count(&self, number: u32) -> bool {
@@ -72,14 +73,13 @@ impl VirtualMethods for HTMLDetailsElement {
self.toggle_counter.set(counter);
let window = window_from_node(self);
- let window = window.r();
let task_source = window.dom_manipulation_task_source();
let details = Trusted::new(self);
let runnable = box DetailsNotificationRunnable {
element: details,
toggle_number: counter
};
- let _ = task_source.queue(DOMManipulationTask::Runnable(runnable));
+ let _ = task_source.queue(runnable, GlobalRef::Window(&window));
}
}
}
diff --git a/components/script/dom/htmldialogelement.rs b/components/script/dom/htmldialogelement.rs
index 70edd6ec7fb..621eefcd8a4 100644
--- a/components/script/dom/htmldialogelement.rs
+++ b/components/script/dom/htmldialogelement.rs
@@ -33,8 +33,9 @@ impl HTMLDialogElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLDialogElement> {
- let element = HTMLDialogElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLDialogElementBinding::Wrap)
+ Node::reflect_node(box HTMLDialogElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLDialogElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmldirectoryelement.rs b/components/script/dom/htmldirectoryelement.rs
index 7a2cbd19c67..82253004650 100644
--- a/components/script/dom/htmldirectoryelement.rs
+++ b/components/script/dom/htmldirectoryelement.rs
@@ -29,7 +29,8 @@ impl HTMLDirectoryElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLDirectoryElement> {
- let element = HTMLDirectoryElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLDirectoryElementBinding::Wrap)
+ Node::reflect_node(box HTMLDirectoryElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLDirectoryElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmldlistelement.rs b/components/script/dom/htmldlistelement.rs
index c29aea80325..dbd67a87398 100644
--- a/components/script/dom/htmldlistelement.rs
+++ b/components/script/dom/htmldlistelement.rs
@@ -27,7 +27,8 @@ impl HTMLDListElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLDListElement> {
- let element = HTMLDListElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLDListElementBinding::Wrap)
+ Node::reflect_node(box HTMLDListElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLDListElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs
index 87bf5d92ff4..e9d967514d7 100644
--- a/components/script/dom/htmlelement.rs
+++ b/components/script/dom/htmlelement.rs
@@ -63,8 +63,9 @@ impl HTMLElement {
#[allow(unrooted_must_root)]
pub fn new(localName: Atom, prefix: Option<DOMString>, document: &Document) -> Root<HTMLElement> {
- let element = HTMLElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLElementBinding::Wrap)
+ Node::reflect_node(box HTMLElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLElementBinding::Wrap)
}
fn is_body_or_frameset(&self) -> bool {
diff --git a/components/script/dom/htmlembedelement.rs b/components/script/dom/htmlembedelement.rs
index fe0ed5424ac..195a82958fb 100644
--- a/components/script/dom/htmlembedelement.rs
+++ b/components/script/dom/htmlembedelement.rs
@@ -26,7 +26,8 @@ impl HTMLEmbedElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLEmbedElement> {
- let element = HTMLEmbedElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLEmbedElementBinding::Wrap)
+ Node::reflect_node(box HTMLEmbedElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLEmbedElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlfieldsetelement.rs b/components/script/dom/htmlfieldsetelement.rs
index 085b8291ddf..86561581bd7 100644
--- a/components/script/dom/htmlfieldsetelement.rs
+++ b/components/script/dom/htmlfieldsetelement.rs
@@ -40,8 +40,9 @@ impl HTMLFieldSetElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLFieldSetElement> {
- let element = HTMLFieldSetElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLFieldSetElementBinding::Wrap)
+ Node::reflect_node(box HTMLFieldSetElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLFieldSetElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlfontelement.rs b/components/script/dom/htmlfontelement.rs
index 85dd000d183..7dacde26cf9 100644
--- a/components/script/dom/htmlfontelement.rs
+++ b/components/script/dom/htmlfontelement.rs
@@ -35,8 +35,9 @@ impl HTMLFontElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLFontElement> {
- let element = HTMLFontElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLFontElementBinding::Wrap)
+ Node::reflect_node(box HTMLFontElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLFontElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs
index 18c30a9d86c..9d7ce208ee2 100644
--- a/components/script/dom/htmlformelement.rs
+++ b/components/script/dom/htmlformelement.rs
@@ -12,6 +12,7 @@ use dom::bindings::codegen::Bindings::HTMLFormElementBinding::HTMLFormElementMet
use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods;
use dom::bindings::conversions::DerivedFrom;
+use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId};
use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::refcounted::Trusted;
@@ -53,7 +54,6 @@ use string_cache::Atom;
use style::attr::AttrValue;
use style::str::split_html_space_chars;
use task_source::TaskSource;
-use task_source::dom_manipulation::DOMManipulationTask;
use url::form_urlencoded;
#[derive(JSTraceable, PartialEq, Clone, Copy, HeapSizeOf)]
@@ -83,8 +83,9 @@ impl HTMLFormElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLFormElement> {
- let element = HTMLFormElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLFormElementBinding::Wrap)
+ Node::reflect_node(box HTMLFormElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLFormElementBinding::Wrap)
}
pub fn generation_id(&self) -> GenerationId {
@@ -484,7 +485,7 @@ impl HTMLFormElement {
};
// Step 3
- window.dom_manipulation_task_source().queue(DOMManipulationTask::Runnable(nav)).unwrap();
+ window.dom_manipulation_task_source().queue(nav, GlobalRef::Window(window)).unwrap();
}
/// Interactively validate the constraints of form elements
diff --git a/components/script/dom/htmlframeelement.rs b/components/script/dom/htmlframeelement.rs
index 04207c711af..b2b46777843 100644
--- a/components/script/dom/htmlframeelement.rs
+++ b/components/script/dom/htmlframeelement.rs
@@ -26,7 +26,8 @@ impl HTMLFrameElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLFrameElement> {
- let element = HTMLFrameElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLFrameElementBinding::Wrap)
+ Node::reflect_node(box HTMLFrameElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLFrameElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlframesetelement.rs b/components/script/dom/htmlframesetelement.rs
index 30cfc1fa677..08f23eb1b26 100644
--- a/components/script/dom/htmlframesetelement.rs
+++ b/components/script/dom/htmlframesetelement.rs
@@ -32,8 +32,9 @@ impl HTMLFrameSetElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLFrameSetElement> {
- let element = HTMLFrameSetElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLFrameSetElementBinding::Wrap)
+ Node::reflect_node(box HTMLFrameSetElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLFrameSetElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlheadelement.rs b/components/script/dom/htmlheadelement.rs
index 995f380f442..cc88a4e4c87 100644
--- a/components/script/dom/htmlheadelement.rs
+++ b/components/script/dom/htmlheadelement.rs
@@ -34,8 +34,9 @@ impl HTMLHeadElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLHeadElement> {
- let element = HTMLHeadElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLHeadElementBinding::Wrap)
+ Node::reflect_node(box HTMLHeadElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLHeadElementBinding::Wrap)
}
/// https://html.spec.whatwg.org/multipage/#meta-referrer
diff --git a/components/script/dom/htmlheadingelement.rs b/components/script/dom/htmlheadingelement.rs
index 9340cb09d3b..94710294570 100644
--- a/components/script/dom/htmlheadingelement.rs
+++ b/components/script/dom/htmlheadingelement.rs
@@ -43,7 +43,8 @@ impl HTMLHeadingElement {
prefix: Option<DOMString>,
document: &Document,
level: HeadingLevel) -> Root<HTMLHeadingElement> {
- let element = HTMLHeadingElement::new_inherited(localName, prefix, document, level);
- Node::reflect_node(box element, document, HTMLHeadingElementBinding::Wrap)
+ Node::reflect_node(box HTMLHeadingElement::new_inherited(localName, prefix, document, level),
+ document,
+ HTMLHeadingElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlhrelement.rs b/components/script/dom/htmlhrelement.rs
index a3127449fcc..432b56eb345 100644
--- a/components/script/dom/htmlhrelement.rs
+++ b/components/script/dom/htmlhrelement.rs
@@ -31,8 +31,9 @@ impl HTMLHRElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLHRElement> {
- let element = HTMLHRElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLHRElementBinding::Wrap)
+ Node::reflect_node(box HTMLHRElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLHRElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlhtmlelement.rs b/components/script/dom/htmlhtmlelement.rs
index e513eaa1bcc..3b397c7fd04 100644
--- a/components/script/dom/htmlhtmlelement.rs
+++ b/components/script/dom/htmlhtmlelement.rs
@@ -26,7 +26,8 @@ impl HTMLHtmlElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLHtmlElement> {
- let element = HTMLHtmlElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLHtmlElementBinding::Wrap)
+ Node::reflect_node(box HTMLHtmlElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLHtmlElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index dccba5846cc..73d750cc8dd 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -38,7 +38,7 @@ use dom::window::{ReflowReason, Window};
use ipc_channel::ipc;
use js::jsapi::{JSAutoCompartment, JSContext, MutableHandleValue};
use js::jsval::{UndefinedValue, NullValue};
-use msg::constellation_msg::{FrameType, LoadData, NavigationDirection, PipelineId, SubpageId};
+use msg::constellation_msg::{FrameType, LoadData, TraversalDirection, PipelineId, SubpageId};
use net_traits::response::HttpsState;
use script_layout_interface::message::ReflowQueryType;
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
@@ -161,25 +161,11 @@ impl HTMLIFrameElement {
#[allow(unsafe_code)]
pub fn dispatch_mozbrowser_event(&self, event: MozBrowserEvent) {
- // TODO(gw): Support mozbrowser event types that have detail which is not a string.
- // See https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API
- // for a list of mozbrowser events.
assert!(PREFS.is_mozbrowser_enabled());
if self.Mozbrowser() {
let window = window_from_node(self);
- let custom_event = unsafe {
- let cx = window.get_cx();
- let _ac = JSAutoCompartment::new(cx, window.reflector().get_jsobject().get());
- rooted!(in(cx) let mut detail = UndefinedValue());
- let event_name = Atom::from(event.name());
- self.build_mozbrowser_event_detail(event, cx, detail.handle_mut());
- CustomEvent::new(GlobalRef::Window(window.r()),
- event_name,
- true,
- true,
- detail.handle())
- };
+ let custom_event = build_mozbrowser_custom_event(&window, event);
custom_event.upcast::<Event>().fire(self.upcast());
}
}
@@ -212,8 +198,9 @@ impl HTMLIFrameElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLIFrameElement> {
- let element = HTMLIFrameElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLIFrameElementBinding::Wrap)
+ Node::reflect_node(box HTMLIFrameElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLIFrameElementBinding::Wrap)
}
#[inline]
@@ -335,105 +322,108 @@ impl HTMLIFrameElementLayoutMethods for LayoutJS<HTMLIFrameElement> {
}
}
-pub trait MozBrowserEventDetailBuilder {
- #[allow(unsafe_code)]
- unsafe fn build_mozbrowser_event_detail(&self,
- event: MozBrowserEvent,
- cx: *mut JSContext,
- rval: MutableHandleValue);
+#[allow(unsafe_code)]
+pub fn build_mozbrowser_custom_event(window: &Window, event: MozBrowserEvent) -> Root<CustomEvent> {
+ // TODO(gw): Support mozbrowser event types that have detail which is not a string.
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API
+ // for a list of mozbrowser events.
+ let cx = window.get_cx();
+ let _ac = JSAutoCompartment::new(cx, window.reflector().get_jsobject().get());
+ rooted!(in(cx) let mut detail = UndefinedValue());
+ let event_name = Atom::from(event.name());
+ unsafe { build_mozbrowser_event_detail(event, cx, detail.handle_mut()); }
+ CustomEvent::new(GlobalRef::Window(window),
+ event_name,
+ true,
+ true,
+ detail.handle())
}
-impl MozBrowserEventDetailBuilder for HTMLIFrameElement {
- #[allow(unsafe_code)]
- unsafe fn build_mozbrowser_event_detail(&self,
- event: MozBrowserEvent,
- cx: *mut JSContext,
- rval: MutableHandleValue) {
- match event {
- MozBrowserEvent::AsyncScroll | MozBrowserEvent::Close | MozBrowserEvent::ContextMenu |
- MozBrowserEvent::LoadEnd | MozBrowserEvent::LoadStart |
- MozBrowserEvent::Connected | MozBrowserEvent::OpenSearch |
- MozBrowserEvent::UsernameAndPasswordRequired => {
- rval.set(NullValue());
- }
- MozBrowserEvent::Error(error_type, description, report) => {
- BrowserElementErrorEventDetail {
- type_: Some(DOMString::from(error_type.name())),
- description: description.map(DOMString::from),
- report: report.map(DOMString::from),
- version: Some(DOMString::from_string(servo_version().into())),
- }.to_jsval(cx, rval);
- },
- MozBrowserEvent::SecurityChange(https_state) => {
- BrowserElementSecurityChangeDetail {
- // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsersecuritychange
- state: Some(DOMString::from(match https_state {
- HttpsState::Modern => "secure",
- HttpsState::Deprecated => "broken",
- HttpsState::None => "insecure",
- }.to_owned())),
- // FIXME - Not supported yet:
- trackingContent: None,
- mixedContent: None,
- trackingState: None,
- extendedValidation: None,
- mixedState: None,
- }.to_jsval(cx, rval);
- }
- MozBrowserEvent::TitleChange(ref string) => {
- string.to_jsval(cx, rval);
- }
- MozBrowserEvent::LocationChange(url, can_go_back, can_go_forward) => {
- BrowserElementLocationChangeEventDetail {
- url: Some(DOMString::from(url)),
- canGoBack: Some(can_go_back),
- canGoForward: Some(can_go_forward),
- }.to_jsval(cx, rval);
- }
- MozBrowserEvent::OpenTab(url) => {
- BrowserElementOpenTabEventDetail {
- url: Some(DOMString::from(url)),
- }.to_jsval(cx, rval);
- }
- MozBrowserEvent::OpenWindow(url, target, features) => {
- BrowserElementOpenWindowEventDetail {
- url: Some(DOMString::from(url)),
- target: target.map(DOMString::from),
- features: features.map(DOMString::from),
- }.to_jsval(cx, rval);
- }
- MozBrowserEvent::IconChange(rel, href, sizes) => {
- BrowserElementIconChangeEventDetail {
- rel: Some(DOMString::from(rel)),
- href: Some(DOMString::from(href)),
- sizes: Some(DOMString::from(sizes)),
- }.to_jsval(cx, rval);
- }
- MozBrowserEvent::ShowModalPrompt(prompt_type, title, message, return_value) => {
- BrowserShowModalPromptEventDetail {
- promptType: Some(DOMString::from(prompt_type)),
- title: Some(DOMString::from(title)),
- message: Some(DOMString::from(message)),
- returnValue: Some(DOMString::from(return_value)),
- }.to_jsval(cx, rval)
- }
- MozBrowserEvent::VisibilityChange(visibility) => {
- BrowserElementVisibilityChangeEventDetail {
- visible: Some(visibility),
- }.to_jsval(cx, rval);
- }
+#[allow(unsafe_code)]
+unsafe fn build_mozbrowser_event_detail(event: MozBrowserEvent,
+ cx: *mut JSContext,
+ rval: MutableHandleValue) {
+ match event {
+ MozBrowserEvent::AsyncScroll | MozBrowserEvent::Close | MozBrowserEvent::ContextMenu |
+ MozBrowserEvent::LoadEnd | MozBrowserEvent::LoadStart |
+ MozBrowserEvent::Connected | MozBrowserEvent::OpenSearch |
+ MozBrowserEvent::UsernameAndPasswordRequired => {
+ rval.set(NullValue());
+ }
+ MozBrowserEvent::Error(error_type, description, report) => {
+ BrowserElementErrorEventDetail {
+ type_: Some(DOMString::from(error_type.name())),
+ description: Some(DOMString::from(description)),
+ report: Some(DOMString::from(report)),
+ version: Some(DOMString::from_string(servo_version().into())),
+ }.to_jsval(cx, rval);
+ },
+ MozBrowserEvent::SecurityChange(https_state) => {
+ BrowserElementSecurityChangeDetail {
+ // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsersecuritychange
+ state: Some(DOMString::from(match https_state {
+ HttpsState::Modern => "secure",
+ HttpsState::Deprecated => "broken",
+ HttpsState::None => "insecure",
+ }.to_owned())),
+ // FIXME - Not supported yet:
+ trackingContent: None,
+ mixedContent: None,
+ trackingState: None,
+ extendedValidation: None,
+ mixedState: None,
+ }.to_jsval(cx, rval);
+ }
+ MozBrowserEvent::TitleChange(ref string) => {
+ string.to_jsval(cx, rval);
+ }
+ MozBrowserEvent::LocationChange(url, can_go_back, can_go_forward) => {
+ BrowserElementLocationChangeEventDetail {
+ url: Some(DOMString::from(url)),
+ canGoBack: Some(can_go_back),
+ canGoForward: Some(can_go_forward),
+ }.to_jsval(cx, rval);
+ }
+ MozBrowserEvent::OpenTab(url) => {
+ BrowserElementOpenTabEventDetail {
+ url: Some(DOMString::from(url)),
+ }.to_jsval(cx, rval);
+ }
+ MozBrowserEvent::OpenWindow(url, target, features) => {
+ BrowserElementOpenWindowEventDetail {
+ url: Some(DOMString::from(url)),
+ target: target.map(DOMString::from),
+ features: features.map(DOMString::from),
+ }.to_jsval(cx, rval);
+ }
+ MozBrowserEvent::IconChange(rel, href, sizes) => {
+ BrowserElementIconChangeEventDetail {
+ rel: Some(DOMString::from(rel)),
+ href: Some(DOMString::from(href)),
+ sizes: Some(DOMString::from(sizes)),
+ }.to_jsval(cx, rval);
+ }
+ MozBrowserEvent::ShowModalPrompt(prompt_type, title, message, return_value) => {
+ BrowserShowModalPromptEventDetail {
+ promptType: Some(DOMString::from(prompt_type)),
+ title: Some(DOMString::from(title)),
+ message: Some(DOMString::from(message)),
+ returnValue: Some(DOMString::from(return_value)),
+ }.to_jsval(cx, rval)
+ }
+ MozBrowserEvent::VisibilityChange(visibility) => {
+ BrowserElementVisibilityChangeEventDetail {
+ visible: Some(visibility),
+ }.to_jsval(cx, rval);
}
}
}
-pub fn Navigate(iframe: &HTMLIFrameElement, direction: NavigationDirection) -> ErrorResult {
+pub fn Navigate(iframe: &HTMLIFrameElement, direction: TraversalDirection) -> ErrorResult {
if iframe.Mozbrowser() {
if iframe.upcast::<Node>().is_in_doc() {
let window = window_from_node(iframe);
-
- let pipeline_info = Some((window.pipeline(),
- iframe.subpage_id().unwrap()));
- let msg = ConstellationMsg::Navigate(pipeline_info, direction);
+ let msg = ConstellationMsg::TraverseHistory(iframe.pipeline(), direction);
window.constellation_chan().send(msg).unwrap();
}
@@ -506,12 +496,12 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/goBack
fn GoBack(&self) -> ErrorResult {
- Navigate(self, NavigationDirection::Back(1))
+ Navigate(self, TraversalDirection::Back(1))
}
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/goForward
fn GoForward(&self) -> ErrorResult {
- Navigate(self, NavigationDirection::Forward(1))
+ Navigate(self, TraversalDirection::Forward(1))
}
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/reload
diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs
index 8c28b1e8c8d..cb0f65d0b2b 100644
--- a/components/script/dom/htmlimageelement.rs
+++ b/components/script/dom/htmlimageelement.rs
@@ -32,7 +32,6 @@ use std::sync::Arc;
use string_cache::Atom;
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
use task_source::TaskSource;
-use task_source::dom_manipulation::DOMManipulationTask;
use url::Url;
#[derive(JSTraceable, HeapSizeOf)]
@@ -141,7 +140,7 @@ impl HTMLImageElement {
// Return the image via a message to the script thread, which marks the element
// as dirty and triggers a reflow.
let image_response = message.to().unwrap();
- let runnable = ImageResponseHandlerRunnable::new(
+ let runnable = box ImageResponseHandlerRunnable::new(
trusted_node.clone(), image_response);
let runnable = wrapper.wrap_runnable(runnable);
let _ = script_chan.send(CommonScriptMsg::RunnableMsg(
@@ -180,12 +179,12 @@ impl HTMLImageElement {
}
}
- let runnable = Box::new(ImgParseErrorRunnable {
+ let runnable = box ImgParseErrorRunnable {
img: Trusted::new(self),
src: src.into(),
- });
+ };
let task = window.dom_manipulation_task_source();
- let _ = task.queue(DOMManipulationTask::Runnable(runnable));
+ let _ = task.queue(runnable, GlobalRef::Window(window));
}
}
}
@@ -214,8 +213,9 @@ impl HTMLImageElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLImageElement> {
- let element = HTMLImageElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLImageElementBinding::Wrap)
+ Node::reflect_node(box HTMLImageElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLImageElementBinding::Wrap)
}
pub fn Image(global: GlobalRef,
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index 35e2a6f5116..7f524cac29d 100644
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -35,6 +35,7 @@ use ipc_channel::ipc::{self, IpcSender};
use mime_guess;
use msg::constellation_msg::Key;
use net_traits::IpcSend;
+use net_traits::blob_url_store::get_blob_origin;
use net_traits::filemanager_thread::{FileManagerThreadMsg, FilterPattern};
use script_traits::ScriptMsg as ConstellationMsg;
use std::borrow::ToOwned;
@@ -147,8 +148,9 @@ impl HTMLInputElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLInputElement> {
- let element = HTMLInputElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLInputElementBinding::Wrap)
+ Node::reflect_node(box HTMLInputElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLInputElementBinding::Wrap)
}
pub fn type_(&self) -> Atom {
@@ -577,7 +579,8 @@ impl HTMLInputElementMethods for HTMLInputElement {
&self.upcast(),
atom!("select"),
EventBubbles::Bubbles,
- EventCancelable::NotCancelable);
+ EventCancelable::NotCancelable,
+ window.r());
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
}
@@ -747,7 +750,7 @@ impl HTMLInputElement {
// Select files by invoking UI or by passed in argument
fn select_files(&self, opt_test_paths: Option<Vec<DOMString>>) {
let window = window_from_node(self);
- let origin = window.get_url().origin().unicode_serialization();
+ let origin = get_blob_origin(&window.get_url());
let filemanager = window.resource_threads().sender();
let mut files: Vec<Root<File>> = vec![];
@@ -768,13 +771,6 @@ impl HTMLInputElement {
for selected in selected_files {
files.push(File::new_from_selected(window.r(), selected));
}
-
- target.fire_event("input",
- EventBubbles::Bubbles,
- EventCancelable::NotCancelable);
- target.fire_event("change",
- EventBubbles::Bubbles,
- EventCancelable::NotCancelable);
},
Err(err) => error = Some(err),
};
@@ -797,13 +793,6 @@ impl HTMLInputElement {
match recv.recv().expect("IpcSender side error") {
Ok(selected) => {
files.push(File::new_from_selected(window.r(), selected));
-
- target.fire_event("input",
- EventBubbles::Bubbles,
- EventCancelable::NotCancelable);
- target.fire_event("change",
- EventBubbles::Bubbles,
- EventCancelable::NotCancelable);
},
Err(err) => error = Some(err),
};
@@ -814,6 +803,13 @@ impl HTMLInputElement {
} else {
let filelist = FileList::new(window.r(), files);
self.filelist.set(Some(&filelist));
+
+ target.fire_event("input",
+ EventBubbles::Bubbles,
+ EventCancelable::NotCancelable);
+ target.fire_event("change",
+ EventBubbles::Bubbles,
+ EventCancelable::NotCancelable);
}
}
}
@@ -1070,7 +1066,8 @@ impl VirtualMethods for HTMLInputElement {
&self.upcast(),
atom!("input"),
EventBubbles::Bubbles,
- EventCancelable::NotCancelable);
+ EventCancelable::NotCancelable,
+ window.r());
}
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
diff --git a/components/script/dom/htmllabelelement.rs b/components/script/dom/htmllabelelement.rs
index 6e808a14fc3..af3b51609a3 100644
--- a/components/script/dom/htmllabelelement.rs
+++ b/components/script/dom/htmllabelelement.rs
@@ -38,8 +38,9 @@ impl HTMLLabelElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLLabelElement> {
- let element = HTMLLabelElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLLabelElementBinding::Wrap)
+ Node::reflect_node(box HTMLLabelElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLLabelElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmllegendelement.rs b/components/script/dom/htmllegendelement.rs
index 7a5a3632eeb..91bc29b4099 100644
--- a/components/script/dom/htmllegendelement.rs
+++ b/components/script/dom/htmllegendelement.rs
@@ -35,8 +35,9 @@ impl HTMLLegendElement {
prefix: Option<DOMString>,
document: &Document)
-> Root<HTMLLegendElement> {
- let element = HTMLLegendElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLLegendElementBinding::Wrap)
+ Node::reflect_node(box HTMLLegendElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLLegendElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmllielement.rs b/components/script/dom/htmllielement.rs
index 64bedf2d8ce..444fc37827c 100644
--- a/components/script/dom/htmllielement.rs
+++ b/components/script/dom/htmllielement.rs
@@ -26,7 +26,8 @@ impl HTMLLIElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLLIElement> {
- let element = HTMLLIElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLLIElementBinding::Wrap)
+ Node::reflect_node(box HTMLLIElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLLIElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs
index ea5c25d8d46..d089caed3f5 100644
--- a/components/script/dom/htmllinkelement.rs
+++ b/components/script/dom/htmllinkelement.rs
@@ -39,9 +39,8 @@ use string_cache::Atom;
use style::attr::AttrValue;
use style::media_queries::{MediaQueryList, parse_media_query_list};
use style::parser::ParserContextExtraData;
-use style::servo::Stylesheet;
use style::str::HTML_SPACE_CHARACTERS;
-use style::stylesheets::Origin;
+use style::stylesheets::{Stylesheet, Origin};
use url::Url;
no_jsmanaged_fields!(Stylesheet);
@@ -72,8 +71,9 @@ impl HTMLLinkElement {
prefix: Option<DOMString>,
document: &Document,
creator: ElementCreator) -> Root<HTMLLinkElement> {
- let element = HTMLLinkElement::new_inherited(localName, prefix, document, creator);
- Node::reflect_node(box element, document, HTMLLinkElementBinding::Wrap)
+ Node::reflect_node(box HTMLLinkElement::new_inherited(localName, prefix, document, creator),
+ document,
+ HTMLLinkElementBinding::Wrap)
}
pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
diff --git a/components/script/dom/htmlmapelement.rs b/components/script/dom/htmlmapelement.rs
index b1a4ff1af4a..ac4b4970bb3 100644
--- a/components/script/dom/htmlmapelement.rs
+++ b/components/script/dom/htmlmapelement.rs
@@ -28,7 +28,8 @@ impl HTMLMapElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLMapElement> {
- let element = HTMLMapElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLMapElementBinding::Wrap)
+ Node::reflect_node(box HTMLMapElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLMapElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs
index b38f796e57c..7a94768c13a 100644
--- a/components/script/dom/htmlmediaelement.rs
+++ b/components/script/dom/htmlmediaelement.rs
@@ -33,7 +33,6 @@ use std::cell::Cell;
use std::sync::{Arc, Mutex};
use string_cache::Atom;
use task_source::TaskSource;
-use task_source::dom_manipulation::DOMManipulationTask;
use time::{self, Timespec, Duration};
use url::Url;
@@ -238,11 +237,11 @@ impl HTMLMediaElement {
}
}
- let task = Task {
+ let task = box Task {
elem: Trusted::new(self),
};
let win = window_from_node(self);
- let _ = win.dom_manipulation_task_source().queue(DOMManipulationTask::Runnable(box task));
+ let _ = win.dom_manipulation_task_source().queue(task, GlobalRef::Window(&win));
}
// https://html.spec.whatwg.org/multipage/#internal-pause-steps step 2.2
@@ -262,17 +261,17 @@ impl HTMLMediaElement {
}
}
- let task = Task {
+ let task = box Task {
elem: Trusted::new(self),
};
let win = window_from_node(self);
- let _ = win.dom_manipulation_task_source().queue(DOMManipulationTask::Runnable(box task));
+ let _ = win.dom_manipulation_task_source().queue(task, GlobalRef::Window(&win));
}
fn queue_fire_simple_event(&self, type_: &'static str) {
let win = window_from_node(self);
- let task = FireSimpleEventTask::new(self, type_);
- let _ = win.dom_manipulation_task_source().queue(DOMManipulationTask::Runnable(box task));
+ let task = box FireSimpleEventTask::new(self, type_);
+ let _ = win.dom_manipulation_task_source().queue(task, GlobalRef::Window(&win));
}
fn fire_simple_event(&self, type_: &str) {
@@ -498,8 +497,9 @@ impl HTMLMediaElement {
}
fn queue_dedicated_media_source_failure_steps(&self) {
- let _ = window_from_node(self).dom_manipulation_task_source().queue(
- DOMManipulationTask::Runnable(box DedicatedMediaSourceFailureTask::new(self)));
+ let window = window_from_node(self);
+ let _ = window.dom_manipulation_task_source().queue(box DedicatedMediaSourceFailureTask::new(self),
+ GlobalRef::Window(&window));
}
// https://html.spec.whatwg.org/multipage/#dedicated-media-source-failure-steps
@@ -801,6 +801,8 @@ impl PauseIfNotInDocumentTask {
}
impl Runnable for PauseIfNotInDocumentTask {
+ fn name(&self) -> &'static str { "PauseIfNotInDocumentTask" }
+
fn handler(self: Box<PauseIfNotInDocumentTask>) {
let elem = self.elem.root();
if !elem.upcast::<Node>().is_in_doc() {
diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs
index 14d8d300bb6..b8c2cd423fa 100644
--- a/components/script/dom/htmlmetaelement.rs
+++ b/components/script/dom/htmlmetaelement.rs
@@ -20,9 +20,8 @@ use std::ascii::AsciiExt;
use std::sync::Arc;
use string_cache::Atom;
use style::attr::AttrValue;
-use style::servo::Stylesheet;
use style::str::HTML_SPACE_CHARACTERS;
-use style::stylesheets::{CSSRule, Origin};
+use style::stylesheets::{Stylesheet, CSSRule, Origin};
use style::viewport::ViewportRule;
#[dom_struct]
@@ -45,8 +44,9 @@ impl HTMLMetaElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLMetaElement> {
- let element = HTMLMetaElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLMetaElementBinding::Wrap)
+ Node::reflect_node(box HTMLMetaElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLMetaElementBinding::Wrap)
}
pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
diff --git a/components/script/dom/htmlmeterelement.rs b/components/script/dom/htmlmeterelement.rs
index 10af136ffa5..e0844d0dd55 100644
--- a/components/script/dom/htmlmeterelement.rs
+++ b/components/script/dom/htmlmeterelement.rs
@@ -30,8 +30,9 @@ impl HTMLMeterElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLMeterElement> {
- let element = HTMLMeterElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLMeterElementBinding::Wrap)
+ Node::reflect_node(box HTMLMeterElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLMeterElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlmodelement.rs b/components/script/dom/htmlmodelement.rs
index 07d974d46da..c34b27762ca 100644
--- a/components/script/dom/htmlmodelement.rs
+++ b/components/script/dom/htmlmodelement.rs
@@ -29,7 +29,8 @@ impl HTMLModElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLModElement> {
- let element = HTMLModElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLModElementBinding::Wrap)
+ Node::reflect_node(box HTMLModElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLModElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlobjectelement.rs b/components/script/dom/htmlobjectelement.rs
index 13798632e17..593895461b5 100644
--- a/components/script/dom/htmlobjectelement.rs
+++ b/components/script/dom/htmlobjectelement.rs
@@ -42,8 +42,9 @@ impl HTMLObjectElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLObjectElement> {
- let element = HTMLObjectElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLObjectElementBinding::Wrap)
+ Node::reflect_node(box HTMLObjectElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLObjectElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlolistelement.rs b/components/script/dom/htmlolistelement.rs
index 85cc77959ea..fe65339bc80 100644
--- a/components/script/dom/htmlolistelement.rs
+++ b/components/script/dom/htmlolistelement.rs
@@ -28,7 +28,8 @@ impl HTMLOListElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLOListElement> {
- let element = HTMLOListElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLOListElementBinding::Wrap)
+ Node::reflect_node(box HTMLOListElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLOListElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmloptgroupelement.rs b/components/script/dom/htmloptgroupelement.rs
index 9665a0cf22f..9a725975d0a 100644
--- a/components/script/dom/htmloptgroupelement.rs
+++ b/components/script/dom/htmloptgroupelement.rs
@@ -37,8 +37,9 @@ impl HTMLOptGroupElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLOptGroupElement> {
- let element = HTMLOptGroupElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLOptGroupElementBinding::Wrap)
+ Node::reflect_node(box HTMLOptGroupElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLOptGroupElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmloptionelement.rs b/components/script/dom/htmloptionelement.rs
index 7d0eeb45752..737bc67bd4c 100644
--- a/components/script/dom/htmloptionelement.rs
+++ b/components/script/dom/htmloptionelement.rs
@@ -52,8 +52,9 @@ impl HTMLOptionElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLOptionElement> {
- let element = HTMLOptionElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLOptionElementBinding::Wrap)
+ Node::reflect_node(box HTMLOptionElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLOptionElementBinding::Wrap)
}
pub fn set_selectedness(&self, selected: bool) {
diff --git a/components/script/dom/htmloutputelement.rs b/components/script/dom/htmloutputelement.rs
index b1b51c6d47e..32e123a4700 100644
--- a/components/script/dom/htmloutputelement.rs
+++ b/components/script/dom/htmloutputelement.rs
@@ -34,8 +34,9 @@ impl HTMLOutputElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLOutputElement> {
- let element = HTMLOutputElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLOutputElementBinding::Wrap)
+ Node::reflect_node(box HTMLOutputElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLOutputElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlparagraphelement.rs b/components/script/dom/htmlparagraphelement.rs
index fc4b342b633..5b913da8801 100644
--- a/components/script/dom/htmlparagraphelement.rs
+++ b/components/script/dom/htmlparagraphelement.rs
@@ -29,7 +29,8 @@ impl HTMLParagraphElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLParagraphElement> {
- let element = HTMLParagraphElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLParagraphElementBinding::Wrap)
+ Node::reflect_node(box HTMLParagraphElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLParagraphElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlparamelement.rs b/components/script/dom/htmlparamelement.rs
index 9c3d745f612..b2296f7750b 100644
--- a/components/script/dom/htmlparamelement.rs
+++ b/components/script/dom/htmlparamelement.rs
@@ -29,7 +29,8 @@ impl HTMLParamElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLParamElement> {
- let element = HTMLParamElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLParamElementBinding::Wrap)
+ Node::reflect_node(box HTMLParamElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLParamElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlpreelement.rs b/components/script/dom/htmlpreelement.rs
index f03af0f4c45..d39bb44f21f 100644
--- a/components/script/dom/htmlpreelement.rs
+++ b/components/script/dom/htmlpreelement.rs
@@ -29,7 +29,8 @@ impl HTMLPreElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLPreElement> {
- let element = HTMLPreElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLPreElementBinding::Wrap)
+ Node::reflect_node(box HTMLPreElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLPreElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlprogresselement.rs b/components/script/dom/htmlprogresselement.rs
index 9fb721b795b..b2f7d818210 100644
--- a/components/script/dom/htmlprogresselement.rs
+++ b/components/script/dom/htmlprogresselement.rs
@@ -31,8 +31,9 @@ impl HTMLProgressElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLProgressElement> {
- let element = HTMLProgressElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLProgressElementBinding::Wrap)
+ Node::reflect_node(box HTMLProgressElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLProgressElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlquoteelement.rs b/components/script/dom/htmlquoteelement.rs
index d4692f72b9e..81eb0d37864 100644
--- a/components/script/dom/htmlquoteelement.rs
+++ b/components/script/dom/htmlquoteelement.rs
@@ -29,7 +29,8 @@ impl HTMLQuoteElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLQuoteElement> {
- let element = HTMLQuoteElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLQuoteElementBinding::Wrap)
+ Node::reflect_node(box HTMLQuoteElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLQuoteElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index 2d10e5f43d8..442f3063524 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -5,7 +5,6 @@
use document_loader::LoadType;
use dom::attr::Attr;
use dom::bindings::cell::DOMRefCell;
-use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::HTMLScriptElementBinding;
use dom::bindings::codegen::Bindings::HTMLScriptElementBinding::HTMLScriptElementMethods;
@@ -35,7 +34,6 @@ use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, NetworkEr
use network_listener::{NetworkListener, PreInvoke};
use std::ascii::AsciiExt;
use std::cell::Cell;
-use std::mem;
use std::sync::{Arc, Mutex};
use string_cache::Atom;
use style::str::{HTML_SPACE_CHARACTERS, StaticStringVec};
@@ -63,11 +61,7 @@ pub struct HTMLScriptElement {
parser_document: JS<Document>,
/// The source this script was loaded from
- load: DOMRefCell<Option<ScriptOrigin>>,
-
- #[ignore_heap_size_of = "Defined in rust-encoding"]
- /// https://html.spec.whatwg.org/multipage/#concept-script-encoding
- block_character_encoding: Cell<Option<EncodingRef>>,
+ load: DOMRefCell<Option<Result<ScriptOrigin, NetworkError>>>,
}
impl HTMLScriptElement {
@@ -82,15 +76,15 @@ impl HTMLScriptElement {
ready_to_be_parser_executed: Cell::new(false),
parser_document: JS::from_ref(document),
load: DOMRefCell::new(None),
- block_character_encoding: Cell::new(None),
}
}
#[allow(unrooted_must_root)]
pub fn new(localName: Atom, prefix: Option<DOMString>, document: &Document,
creator: ElementCreator) -> Root<HTMLScriptElement> {
- let element = HTMLScriptElement::new_inherited(localName, prefix, document, creator);
- Node::reflect_node(box element, document, HTMLScriptElementBinding::Wrap)
+ Node::reflect_node(box HTMLScriptElement::new_inherited(localName, prefix, document, creator),
+ document,
+ HTMLScriptElementBinding::Wrap)
}
}
@@ -117,15 +111,37 @@ static SCRIPT_JS_MIMES: StaticStringVec = &[
];
#[derive(HeapSizeOf, JSTraceable)]
-pub enum ScriptOrigin {
- Internal(DOMString, Url),
- External(Result<(Metadata, Vec<u8>), NetworkError>),
+pub struct ScriptOrigin {
+ text: DOMString,
+ url: Url,
+ external: bool,
+}
+
+impl ScriptOrigin {
+ fn internal(text: DOMString, url: Url) -> ScriptOrigin {
+ ScriptOrigin {
+ text: text,
+ url: url,
+ external: false,
+ }
+ }
+
+ fn external(text: DOMString, url: Url) -> ScriptOrigin {
+ ScriptOrigin {
+ text: text,
+ url: url,
+ external: true,
+ }
+ }
}
/// The context required for asynchronously loading an external script source.
struct ScriptContext {
/// The element that initiated the request.
elem: Trusted<HTMLScriptElement>,
+ /// The (fallback) character encoding argument to the "fetch a classic
+ /// script" algorithm.
+ character_encoding: EncodingRef,
/// The response body received to date.
data: Vec<u8>,
/// The response metadata received to date.
@@ -161,15 +177,28 @@ impl AsyncResponseListener for ScriptContext {
}
}
+ /// https://html.spec.whatwg.org/multipage/#fetch-a-classic-script
+ /// step 4-9
fn response_complete(&mut self, status: Result<(), NetworkError>) {
+ // Step 5.
let load = status.and(self.status.clone()).map(|_| {
- let data = mem::replace(&mut self.data, vec!());
let metadata = self.metadata.take().unwrap();
- (metadata, data)
+
+ // Step 6.
+ let encoding = metadata.charset
+ .and_then(|encoding| encoding_from_whatwg_label(&encoding))
+ .unwrap_or(self.character_encoding);
+
+ // Step 7.
+ let source_text = encoding.decode(&self.data, DecoderTrap::Replace).unwrap();
+ ScriptOrigin::external(DOMString::from(source_text), metadata.final_url)
});
+
+ // Step 9.
+ // https://html.spec.whatwg.org/multipage/#prepare-a-script
+ // Step 18.6 (When the chosen algorithm asynchronously completes).
let elem = self.elem.root();
- // TODO: maybe set this to None again after script execution to save memory.
- *elem.load.borrow_mut() = Some(ScriptOrigin::External(load));
+ *elem.load.borrow_mut() = Some(load);
elem.ready_to_be_parser_executed.set(true);
let document = document_from_node(elem.r());
@@ -179,6 +208,38 @@ impl AsyncResponseListener for ScriptContext {
impl PreInvoke for ScriptContext {}
+/// https://html.spec.whatwg.org/multipage/#fetch-a-classic-script
+fn fetch_a_classic_script(script: &HTMLScriptElement,
+ url: Url,
+ character_encoding: EncodingRef) {
+ // TODO(#9186): use the fetch infrastructure.
+ let context = Arc::new(Mutex::new(ScriptContext {
+ elem: Trusted::new(script),
+ character_encoding: character_encoding,
+ data: vec!(),
+ metadata: None,
+ url: url.clone(),
+ status: Ok(())
+ }));
+
+ let doc = document_from_node(script);
+
+ let (action_sender, action_receiver) = ipc::channel().unwrap();
+ let listener = NetworkListener {
+ context: context,
+ script_chan: doc.window().networking_task_source(),
+ wrapper: Some(doc.window().get_runnable_wrapper()),
+ };
+ let response_target = AsyncResponseTarget {
+ sender: action_sender,
+ };
+ ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
+ listener.notify_action(message.to().unwrap());
+ });
+
+ doc.load_async(LoadType::Script(url), response_target);
+}
+
impl HTMLScriptElement {
/// https://html.spec.whatwg.org/multipage/#prepare-a-script
pub fn prepare(&self) -> NextParserState {
@@ -226,13 +287,12 @@ impl HTMLScriptElement {
// Step 9.
let doc = document_from_node(self);
- let document_from_node_ref = doc.r();
- if self.parser_inserted.get() && &*self.parser_document != document_from_node_ref {
+ if self.parser_inserted.get() && &*self.parser_document != &*doc {
return NextParserState::Continue;
}
// Step 10.
- if !document_from_node_ref.is_scripting_enabled() {
+ if !doc.is_scripting_enabled() {
return NextParserState::Continue;
}
@@ -259,73 +319,51 @@ impl HTMLScriptElement {
}
// Step 13.
- if let Some(ref charset) = element.get_attribute(&ns!(), &atom!("charset")) {
- if let Some(encodingRef) = encoding_from_whatwg_label(&charset.Value()) {
- self.block_character_encoding.set(Some(encodingRef));
- }
- }
+ let encoding = element.get_attribute(&ns!(), &atom!("charset"))
+ .and_then(|charset| encoding_from_whatwg_label(&charset.value()))
+ .unwrap_or_else(|| doc.encoding());
// TODO: Step 14: CORS.
- // TODO: Step 15: environment settings object.
+ // TODO: Step 15: Nonce.
+
+ // TODO: Step 16: Parser state.
+
+ // TODO: Step 17: environment settings object.
let base_url = doc.base_url();
let is_external = match element.get_attribute(&ns!(), &atom!("src")) {
- // Step 16.
+ // Step 18.
Some(ref src) => {
- // Step 16.1.
+ // Step 18.1.
let src = src.value();
- // Step 16.2.
+ // Step 18.2.
if src.is_empty() {
self.queue_error_event();
return NextParserState::Continue;
}
- // Step 16.4-16.5.
+ // Step 18.4-18.5.
let url = match base_url.join(&src) {
Err(_) => {
- error!("error parsing URL for script {}", &**src);
+ warn!("error parsing URL for script {}", &**src);
self.queue_error_event();
return NextParserState::Continue;
}
Ok(url) => url,
};
- // Step 16.6.
- // TODO(#9186): use the fetch infrastructure.
- let elem = Trusted::new(self);
-
- let context = Arc::new(Mutex::new(ScriptContext {
- elem: elem,
- data: vec!(),
- metadata: None,
- url: url.clone(),
- status: Ok(())
- }));
-
- let (action_sender, action_receiver) = ipc::channel().unwrap();
- let listener = NetworkListener {
- context: context,
- script_chan: doc.window().networking_task_source(),
- wrapper: Some(doc.window().get_runnable_wrapper()),
- };
- let response_target = AsyncResponseTarget {
- sender: action_sender,
- };
- ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
- listener.notify_action(message.to().unwrap());
- });
-
- doc.load_async(LoadType::Script(url), response_target);
+ // Step 18.6.
+ fetch_a_classic_script(self, url, encoding);
true
},
None => false,
};
- // Step 18.
+ // Step 20.
let deferred = element.has_attribute(&atom!("defer"));
- // Step 18.a: has src, has defer, was parser-inserted, is not async.
+ // Step 20.a: classic, has src, has defer, was parser-inserted, is not async.
if is_external &&
deferred &&
was_parser_inserted &&
@@ -333,35 +371,35 @@ impl HTMLScriptElement {
doc.add_deferred_script(self);
// Second part implemented in Document::process_deferred_scripts.
return NextParserState::Continue;
- // Step 18.b: has src, was parser-inserted, is not async.
+ // Step 20.b: classic, has src, was parser-inserted, is not async.
} else if is_external &&
was_parser_inserted &&
!async {
doc.set_pending_parsing_blocking_script(Some(self));
// Second part implemented in the load result handler.
- // Step 18.c: has src, isn't async, isn't non-blocking.
+ // Step 20.c: classic, has src, isn't async, isn't non-blocking.
} else if is_external &&
!async &&
!self.non_blocking.get() {
doc.push_asap_in_order_script(self);
// Second part implemented in Document::process_asap_scripts.
- // Step 18.d: has src.
+ // Step 20.d: classic, has src.
} else if is_external {
doc.add_asap_script(self);
// Second part implemented in Document::process_asap_scripts.
- // Step 18.e: doesn't have src, was parser-inserted, is blocked on stylesheet.
+ // Step 20.e: doesn't have src, was parser-inserted, is blocked on stylesheet.
} else if !is_external &&
was_parser_inserted &&
// TODO: check for script nesting levels.
doc.get_script_blocking_stylesheets_count() > 0 {
doc.set_pending_parsing_blocking_script(Some(self));
- *self.load.borrow_mut() = Some(ScriptOrigin::Internal(text, base_url));
+ *self.load.borrow_mut() = Some(Ok(ScriptOrigin::internal(text, base_url)));
self.ready_to_be_parser_executed.set(true);
- // Step 18.f: otherwise.
+ // Step 20.f: otherwise.
} else {
assert!(!text.is_empty());
self.ready_to_be_parser_executed.set(true);
- *self.load.borrow_mut() = Some(ScriptOrigin::Internal(text, base_url));
+ *self.load.borrow_mut() = Some(Ok(ScriptOrigin::internal(text, base_url)));
self.execute();
return NextParserState::Continue;
}
@@ -390,82 +428,67 @@ impl HTMLScriptElement {
}
let load = self.load.borrow_mut().take().unwrap();
-
- // Step 2.
- let (source, external, url) = match load {
- // Step 2.a.
- ScriptOrigin::External(Err(e)) => {
- error!("error loading script {:?}", e);
+ let script = match load {
+ // Step 2.
+ Err(e) => {
+ warn!("error loading script {:?}", e);
self.dispatch_error_event();
return;
}
- // Step 2.b.1.a.
- ScriptOrigin::External(Ok((metadata, bytes))) => {
- debug!("loading external script, url = {}", metadata.final_url);
-
- let encoding = metadata.charset
- .and_then(|encoding| encoding_from_whatwg_label(&encoding))
- .or_else(|| self.block_character_encoding.get())
- .unwrap_or_else(|| self.parser_document.encoding());
-
- (DOMString::from(encoding.decode(&*bytes, DecoderTrap::Replace).unwrap()),
- true,
- metadata.final_url)
- },
-
- // Step 2.b.1.c.
- ScriptOrigin::Internal(text, url) => {
- (text, false, url)
- }
+ Ok(script) => script,
};
- // Step 2.b.2.
+ if script.external {
+ debug!("loading external script, url = {}", script.url);
+ }
+
+ // TODO(#12446): beforescriptexecute.
if !self.dispatch_before_script_execute_event() {
return;
}
- // Step 2.b.3.
+ // Step 3.
// TODO: If the script is from an external file, then increment the
// ignore-destructive-writes counter of the script element's node
// document. Let neutralised doc be that Document.
- // Step 2.b.4.
+ // Step 4.
let document = document_from_node(self);
let document = document.r();
let old_script = document.GetCurrentScript();
- // Step 2.b.5.
+ // Step 5.a.1.
document.set_current_script(Some(self));
- // Step 2.b.6.
- // TODO: Create a script...
+ // Step 5.a.2.
let window = window_from_node(self);
rooted!(in(window.get_cx()) let mut rval = UndefinedValue());
- window.evaluate_script_on_global_with_result(&*source,
- url.as_str(),
- rval.handle_mut());
+ window.evaluate_script_on_global_with_result(&script.text,
+ script.url.as_str(),
+ rval.handle_mut());
- // Step 2.b.7.
+ // Step 6.
document.set_current_script(old_script.r());
- // Step 2.b.8.
+ // Step 7.
// TODO: Decrement the ignore-destructive-writes counter of neutralised
// doc, if it was incremented in the earlier step.
- // Step 2.b.9.
+ // TODO(#12446): afterscriptexecute.
self.dispatch_after_script_execute_event();
- // Step 2.b.10.
- if external {
+ // Step 8.
+ if script.external {
self.dispatch_load_event();
} else {
- window.dom_manipulation_task_source().queue_simple_event(self.upcast(), atom!("load"));
+ window.dom_manipulation_task_source().queue_simple_event(self.upcast(), atom!("load"), window.r());
}
}
pub fn queue_error_event(&self) {
- window_from_node(self).dom_manipulation_task_source().queue_simple_event(self.upcast(), atom!("error"));
+ let window = window_from_node(self);
+ window.dom_manipulation_task_source().queue_simple_event(self.upcast(), atom!("error"), window.r());
}
pub fn dispatch_before_script_execute_event(&self) -> bool {
diff --git a/components/script/dom/htmlselectelement.rs b/components/script/dom/htmlselectelement.rs
index 26e1ad9b0c4..cb42ca2521b 100644
--- a/components/script/dom/htmlselectelement.rs
+++ b/components/script/dom/htmlselectelement.rs
@@ -48,8 +48,9 @@ impl HTMLSelectElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLSelectElement> {
- let element = HTMLSelectElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLSelectElementBinding::Wrap)
+ Node::reflect_node(box HTMLSelectElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLSelectElementBinding::Wrap)
}
// https://html.spec.whatwg.org/multipage/#ask-for-a-reset
diff --git a/components/script/dom/htmlsourceelement.rs b/components/script/dom/htmlsourceelement.rs
index 585d7678281..c369ab86aaf 100644
--- a/components/script/dom/htmlsourceelement.rs
+++ b/components/script/dom/htmlsourceelement.rs
@@ -29,7 +29,8 @@ impl HTMLSourceElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLSourceElement> {
- let element = HTMLSourceElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLSourceElementBinding::Wrap)
+ Node::reflect_node(box HTMLSourceElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLSourceElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlspanelement.rs b/components/script/dom/htmlspanelement.rs
index b66b1602284..d95975c135c 100644
--- a/components/script/dom/htmlspanelement.rs
+++ b/components/script/dom/htmlspanelement.rs
@@ -26,7 +26,8 @@ impl HTMLSpanElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLSpanElement> {
- let element = HTMLSpanElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLSpanElementBinding::Wrap)
+ Node::reflect_node(box HTMLSpanElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLSpanElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs
index 47409402855..c7cc4cc44a3 100644
--- a/components/script/dom/htmlstyleelement.rs
+++ b/components/script/dom/htmlstyleelement.rs
@@ -19,8 +19,7 @@ use std::sync::Arc;
use string_cache::Atom;
use style::media_queries::parse_media_query_list;
use style::parser::ParserContextExtraData;
-use style::servo::Stylesheet;
-use style::stylesheets::Origin;
+use style::stylesheets::{Stylesheet, Origin};
#[dom_struct]
pub struct HTMLStyleElement {
@@ -42,8 +41,9 @@ impl HTMLStyleElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLStyleElement> {
- let element = HTMLStyleElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLStyleElementBinding::Wrap)
+ Node::reflect_node(box HTMLStyleElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLStyleElementBinding::Wrap)
}
pub fn parse_own_css(&self) {
diff --git a/components/script/dom/htmltablecaptionelement.rs b/components/script/dom/htmltablecaptionelement.rs
index 108e0b8ea7d..fd01e2ee3fa 100644
--- a/components/script/dom/htmltablecaptionelement.rs
+++ b/components/script/dom/htmltablecaptionelement.rs
@@ -29,7 +29,8 @@ impl HTMLTableCaptionElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLTableCaptionElement> {
- let element = HTMLTableCaptionElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLTableCaptionElementBinding::Wrap)
+ Node::reflect_node(box HTMLTableCaptionElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLTableCaptionElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmltablecolelement.rs b/components/script/dom/htmltablecolelement.rs
index c995a2f8048..b5e69aaadc1 100644
--- a/components/script/dom/htmltablecolelement.rs
+++ b/components/script/dom/htmltablecolelement.rs
@@ -29,7 +29,8 @@ impl HTMLTableColElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLTableColElement> {
- let element = HTMLTableColElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLTableColElementBinding::Wrap)
+ Node::reflect_node(box HTMLTableColElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLTableColElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmltableelement.rs b/components/script/dom/htmltableelement.rs
index ec6e4b59efe..1d189f4a21f 100644
--- a/components/script/dom/htmltableelement.rs
+++ b/components/script/dom/htmltableelement.rs
@@ -34,6 +34,20 @@ pub struct HTMLTableElement {
tbodies: MutNullableHeap<JS<HTMLCollection>>,
}
+#[allow(unrooted_must_root)]
+#[derive(JSTraceable, HeapSizeOf)]
+struct TableRowFilter {
+ sections: Vec<JS<Node>>,
+}
+
+impl CollectionFilter for TableRowFilter {
+ fn filter(&self, elem: &Element, root: &Node) -> bool {
+ elem.is::<HTMLTableRowElement>() &&
+ (root.is_parent_of(elem.upcast())
+ || self.sections.iter().any(|ref section| section.is_parent_of(elem.upcast())))
+ }
+}
+
impl HTMLTableElement {
fn new_inherited(localName: Atom, prefix: Option<DOMString>, document: &Document)
-> HTMLTableElement {
@@ -48,8 +62,9 @@ impl HTMLTableElement {
#[allow(unrooted_must_root)]
pub fn new(localName: Atom, prefix: Option<DOMString>, document: &Document)
-> Root<HTMLTableElement> {
- let element = HTMLTableElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLTableElementBinding::Wrap)
+ Node::reflect_node(box HTMLTableElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLTableElementBinding::Wrap)
}
pub fn get_border(&self) -> Option<u32> {
@@ -119,32 +134,22 @@ impl HTMLTableElement {
thead.upcast::<Node>().remove_self();
}
}
-}
-
-impl HTMLTableElementMethods for HTMLTableElement {
- // https://html.spec.whatwg.org/multipage/#dom-table-rows
- fn Rows(&self) -> Root<HTMLCollection> {
- #[allow(unrooted_must_root)]
- #[derive(JSTraceable, HeapSizeOf)]
- struct TableRowFilter {
- sections: Vec<JS<Node>>
- }
-
- impl CollectionFilter for TableRowFilter {
- fn filter(&self, elem: &Element, root: &Node) -> bool {
- elem.is::<HTMLTableRowElement>() &&
- (root.is_parent_of(elem.upcast())
- || self.sections.iter().any(|ref section| section.is_parent_of(elem.upcast())))
- }
- }
- let filter = TableRowFilter {
+ fn get_rows(&self) -> TableRowFilter {
+ TableRowFilter {
sections: self.upcast::<Node>()
.children()
.filter_map(|ref node|
node.downcast::<HTMLTableSectionElement>().map(|_| JS::from_ref(&**node)))
.collect()
- };
+ }
+ }
+}
+
+impl HTMLTableElementMethods for HTMLTableElement {
+ // https://html.spec.whatwg.org/multipage/#dom-table-rows
+ fn Rows(&self) -> Root<HTMLCollection> {
+ let filter = self.get_rows();
HTMLCollection::new(window_from_node(self).r(), self.upcast(), box filter)
}
@@ -337,6 +342,22 @@ impl HTMLTableElementMethods for HTMLTableElement {
Ok(new_row)
}
+ // https://html.spec.whatwg.org/multipage/#dom-table-deleterow
+ fn DeleteRow(&self, mut index: i32) -> Fallible<()> {
+ let rows = self.Rows();
+ // Step 1.
+ if index == -1 {
+ index = rows.Length() as i32 - 1;
+ }
+ // Step 2.
+ if index < 0 || index as u32 >= rows.Length() {
+ return Err(Error::IndexSize);
+ }
+ // Step 3.
+ Root::upcast::<Node>(rows.Item(index as u32).unwrap()).remove_self();
+ Ok(())
+ }
+
// https://html.spec.whatwg.org/multipage/#dom-table-bgcolor
make_getter!(BgColor, "bgcolor");
diff --git a/components/script/dom/htmltableheadercellelement.rs b/components/script/dom/htmltableheadercellelement.rs
index 17ecc472d25..da980e7d840 100644
--- a/components/script/dom/htmltableheadercellelement.rs
+++ b/components/script/dom/htmltableheadercellelement.rs
@@ -29,7 +29,8 @@ impl HTMLTableHeaderCellElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLTableHeaderCellElement> {
- let element = HTMLTableHeaderCellElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLTableHeaderCellElementBinding::Wrap)
+ Node::reflect_node(box HTMLTableHeaderCellElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLTableHeaderCellElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmltablesectionelement.rs b/components/script/dom/htmltablesectionelement.rs
index 7b047439743..3279e03ff0c 100644
--- a/components/script/dom/htmltablesectionelement.rs
+++ b/components/script/dom/htmltablesectionelement.rs
@@ -35,8 +35,9 @@ impl HTMLTableSectionElement {
#[allow(unrooted_must_root)]
pub fn new(localName: Atom, prefix: Option<DOMString>, document: &Document)
-> Root<HTMLTableSectionElement> {
- let element = HTMLTableSectionElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLTableSectionElementBinding::Wrap)
+ Node::reflect_node(box HTMLTableSectionElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLTableSectionElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmltemplateelement.rs b/components/script/dom/htmltemplateelement.rs
index 0459a772273..aa98d849c85 100644
--- a/components/script/dom/htmltemplateelement.rs
+++ b/components/script/dom/htmltemplateelement.rs
@@ -39,8 +39,9 @@ impl HTMLTemplateElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLTemplateElement> {
- let element = HTMLTemplateElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLTemplateElementBinding::Wrap)
+ Node::reflect_node(box HTMLTemplateElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLTemplateElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs
index 69fe9046dad..a89df91f99b 100644
--- a/components/script/dom/htmltextareaelement.rs
+++ b/components/script/dom/htmltextareaelement.rs
@@ -114,8 +114,9 @@ impl HTMLTextAreaElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLTextAreaElement> {
- let element = HTMLTextAreaElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLTextAreaElementBinding::Wrap)
+ Node::reflect_node(box HTMLTextAreaElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLTextAreaElementBinding::Wrap)
}
}
@@ -260,7 +261,8 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
&self.upcast(),
atom!("select"),
EventBubbles::Bubbles,
- EventCancelable::NotCancelable);
+ EventCancelable::NotCancelable,
+ window.r());
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
}
}
@@ -383,7 +385,8 @@ impl VirtualMethods for HTMLTextAreaElement {
&self.upcast(),
atom!("input"),
EventBubbles::Bubbles,
- EventCancelable::NotCancelable);
+ EventCancelable::NotCancelable,
+ window.r());
}
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
diff --git a/components/script/dom/htmltimeelement.rs b/components/script/dom/htmltimeelement.rs
index 7c55c2f7e61..bcf214cf5f6 100644
--- a/components/script/dom/htmltimeelement.rs
+++ b/components/script/dom/htmltimeelement.rs
@@ -26,7 +26,8 @@ impl HTMLTimeElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLTimeElement> {
- let element = HTMLTimeElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLTimeElementBinding::Wrap)
+ Node::reflect_node(box HTMLTimeElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLTimeElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmltitleelement.rs b/components/script/dom/htmltitleelement.rs
index d475f37bc73..077b6d6afdc 100644
--- a/components/script/dom/htmltitleelement.rs
+++ b/components/script/dom/htmltitleelement.rs
@@ -32,8 +32,9 @@ impl HTMLTitleElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLTitleElement> {
- let element = HTMLTitleElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLTitleElementBinding::Wrap)
+ Node::reflect_node(box HTMLTitleElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLTitleElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmltrackelement.rs b/components/script/dom/htmltrackelement.rs
index df071125b7b..979cbe17079 100644
--- a/components/script/dom/htmltrackelement.rs
+++ b/components/script/dom/htmltrackelement.rs
@@ -26,7 +26,8 @@ impl HTMLTrackElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLTrackElement> {
- let element = HTMLTrackElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLTrackElementBinding::Wrap)
+ Node::reflect_node(box HTMLTrackElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLTrackElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlulistelement.rs b/components/script/dom/htmlulistelement.rs
index 145d3e6770c..2b38b49f1db 100644
--- a/components/script/dom/htmlulistelement.rs
+++ b/components/script/dom/htmlulistelement.rs
@@ -26,7 +26,8 @@ impl HTMLUListElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLUListElement> {
- let element = HTMLUListElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLUListElementBinding::Wrap)
+ Node::reflect_node(box HTMLUListElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLUListElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlunknownelement.rs b/components/script/dom/htmlunknownelement.rs
index 5211b5c11e6..1bf321735fc 100644
--- a/components/script/dom/htmlunknownelement.rs
+++ b/components/script/dom/htmlunknownelement.rs
@@ -29,7 +29,8 @@ impl HTMLUnknownElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLUnknownElement> {
- let element = HTMLUnknownElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLUnknownElementBinding::Wrap)
+ Node::reflect_node(box HTMLUnknownElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLUnknownElementBinding::Wrap)
}
}
diff --git a/components/script/dom/htmlvideoelement.rs b/components/script/dom/htmlvideoelement.rs
index 6295227cf26..4c6f9663f97 100644
--- a/components/script/dom/htmlvideoelement.rs
+++ b/components/script/dom/htmlvideoelement.rs
@@ -27,7 +27,8 @@ impl HTMLVideoElement {
pub fn new(localName: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<HTMLVideoElement> {
- let element = HTMLVideoElement::new_inherited(localName, prefix, document);
- Node::reflect_node(box element, document, HTMLVideoElementBinding::Wrap)
+ Node::reflect_node(box HTMLVideoElement::new_inherited(localName, prefix, document),
+ document,
+ HTMLVideoElementBinding::Wrap)
}
}
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index d76721ed040..effc7f2c761 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -269,6 +269,8 @@ pub mod focusevent;
pub mod forcetouchevent;
pub mod formdata;
pub mod hashchangeevent;
+pub mod headers;
+pub mod history;
pub mod htmlanchorelement;
pub mod htmlappletelement;
pub mod htmlareaelement;
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 811716088b6..2769b7503bc 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -159,7 +159,9 @@ bitflags! {
const SEQUENTIALLY_FOCUSABLE = 0x20,
/// Whether any ancestor is a fragmentation container
- const CAN_BE_FRAGMENTED = 0x40
+ const CAN_BE_FRAGMENTED = 0x40,
+ #[doc = "Specifies whether this node needs to be dirted when viewport size changed."]
+ const DIRTY_ON_VIEWPORT_SIZE_CHANGE = 0x80
}
}
@@ -477,19 +479,7 @@ impl Node {
return
}
- // 2. Dirty descendants.
- fn dirty_subtree(node: &Node) {
- // Stop if this subtree is already dirty.
- if node.is_dirty() { return }
-
- node.set_flag(IS_DIRTY | HAS_DIRTY_DESCENDANTS, true);
-
- for kid in node.children() {
- dirty_subtree(kid.r());
- }
- }
-
- dirty_subtree(self);
+ self.set_flag(IS_DIRTY, true);
// 4. Dirty ancestors.
for ancestor in self.ancestors() {
@@ -1297,22 +1287,17 @@ impl TreeIterator {
depth: 0,
}
}
-}
-impl Iterator for TreeIterator {
- type Item = Root<Node>;
-
- // https://dom.spec.whatwg.org/#concept-tree-order
- fn next(&mut self) -> Option<Root<Node>> {
+ pub fn next_skipping_children(&mut self) -> Option<Root<Node>> {
let current = match self.current.take() {
None => return None,
Some(current) => current,
};
- if let Some(first_child) = current.GetFirstChild() {
- self.current = Some(first_child);
- self.depth += 1;
- return Some(current);
- };
+
+ self.next_skipping_children_impl(current)
+ }
+
+ fn next_skipping_children_impl(&mut self, current: Root<Node>) -> Option<Root<Node>> {
for ancestor in current.inclusive_ancestors() {
if self.depth == 0 {
break;
@@ -1329,6 +1314,25 @@ impl Iterator for TreeIterator {
}
}
+impl Iterator for TreeIterator {
+ type Item = Root<Node>;
+
+ // https://dom.spec.whatwg.org/#concept-tree-order
+ fn next(&mut self) -> Option<Root<Node>> {
+ let current = match self.current.take() {
+ None => return None,
+ Some(current) => current,
+ };
+ if let Some(first_child) = current.GetFirstChild() {
+ self.current = Some(first_child);
+ self.depth += 1;
+ return Some(current);
+ };
+
+ self.next_skipping_children_impl(current)
+ }
+}
+
/// Specifies whether children must be recursively cloned or not.
#[derive(Copy, Clone, PartialEq, HeapSizeOf)]
pub enum CloneChildrenFlag {
@@ -1721,7 +1725,8 @@ impl Node {
let document = Document::new(window, None,
Some((*document.url()).clone()),
is_html_doc, None,
- None, DocumentSource::NotFromParser, loader);
+ None, DocumentSource::NotFromParser, loader,
+ None, None);
Root::upcast::<Node>(document)
},
NodeTypeId::Element(..) => {
diff --git a/components/script/dom/serviceworker.rs b/components/script/dom/serviceworker.rs
index ad303d45915..19af9b09ba4 100644
--- a/components/script/dom/serviceworker.rs
+++ b/components/script/dom/serviceworker.rs
@@ -2,8 +2,8 @@
* 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::abstractworker::WorkerScriptMsg;
use dom::abstractworker::{SimpleWorkerErrorHandler, WorkerErrorHandler};
-use dom::abstractworker::{WorkerScriptMsg, WorkerScriptLoadOrigin, SharedRt};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::ServiceWorkerBinding::{ServiceWorkerMethods, ServiceWorkerState, Wrap};
@@ -13,19 +13,13 @@ use dom::bindings::js::Root;
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
use dom::bindings::str::{DOMString, USVString};
-use dom::client::Client;
use dom::errorevent::ErrorEvent;
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
-use dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
-use dom::workerglobalscope::prepare_workerscope_init;
-use ipc_channel::ipc;
use js::jsval::UndefinedValue;
use script_thread::Runnable;
use std::cell::Cell;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::mpsc::{Sender, channel};
-use std::sync::{Arc, Mutex};
+use std::sync::mpsc::Sender;
use url::Url;
pub type TrustedServiceWorkerAddress = Trusted<ServiceWorker>;
@@ -35,36 +29,27 @@ pub struct ServiceWorker {
eventtarget: EventTarget,
script_url: DOMRefCell<String>,
state: Cell<ServiceWorkerState>,
- closing: Arc<AtomicBool>,
#[ignore_heap_size_of = "Defined in std"]
- sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
- #[ignore_heap_size_of = "Defined in rust-mozjs"]
- runtime: Arc<Mutex<Option<SharedRt>>>,
+ sender: Option<Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>>,
skip_waiting: Cell<bool>
}
impl ServiceWorker {
- fn new_inherited(sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
- closing: Arc<AtomicBool>,
- script_url: &str,
+ fn new_inherited(script_url: &str,
skip_waiting: bool) -> ServiceWorker {
ServiceWorker {
eventtarget: EventTarget::new_inherited(),
- closing: closing,
- sender: sender,
+ sender: None,
script_url: DOMRefCell::new(String::from(script_url)),
state: Cell::new(ServiceWorkerState::Installing),
- runtime: Arc::new(Mutex::new(None)),
skip_waiting: Cell::new(skip_waiting)
}
}
pub fn new(global: GlobalRef,
- closing: Arc<AtomicBool>,
- sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
script_url: &str,
skip_waiting: bool) -> Root<ServiceWorker> {
- reflect_dom_object(box ServiceWorker::new_inherited(sender, closing, script_url, skip_waiting), global, Wrap)
+ reflect_dom_object(box ServiceWorker::new_inherited(script_url, skip_waiting), global, Wrap)
}
pub fn dispatch_simple_error(address: TrustedServiceWorkerAddress) {
@@ -72,23 +57,19 @@ impl ServiceWorker {
service_worker.upcast().fire_simple_event("error");
}
- pub fn is_closing(&self) -> bool {
- self.closing.load(Ordering::SeqCst)
- }
-
pub fn set_transition_state(&self, state: ServiceWorkerState) {
self.state.set(state);
self.upcast::<EventTarget>().fire_simple_event("statechange");
}
+ pub fn get_script_url(&self) -> Url {
+ Url::parse(&self.script_url.borrow().clone()).unwrap()
+ }
+
pub fn handle_error_message(address: TrustedServiceWorkerAddress, message: DOMString,
filename: DOMString, lineno: u32, colno: u32) {
let worker = address.root();
- if worker.is_closing() {
- return;
- }
-
let global = worker.r().global();
rooted!(in(global.r().get_cx()) let error = UndefinedValue());
let errorevent = ErrorEvent::new(global.r(), atom!("error"),
@@ -97,42 +78,12 @@ impl ServiceWorker {
errorevent.upcast::<Event>().fire(worker.upcast());
}
- #[allow(unsafe_code)]
- pub fn init_service_worker(global: GlobalRef,
- script_url: Url,
- skip_waiting: bool) -> Root<ServiceWorker> {
- let (sender, receiver) = channel();
- let closing = Arc::new(AtomicBool::new(false));
- let worker = ServiceWorker::new(global,
- closing.clone(),
- sender.clone(),
- script_url.as_str(),
- skip_waiting);
- let worker_ref = Trusted::new(worker.r());
-
- let worker_load_origin = WorkerScriptLoadOrigin {
- referrer_url: None,
- referrer_policy: None,
- request_source: global.request_source(),
- pipeline_id: Some(global.pipeline())
- };
-
- let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
- let init = prepare_workerscope_init(global,
- "Service Worker".to_owned(),
- script_url.clone(),
- devtools_sender.clone(),
- closing);
-
- // represents a service worker client
- let sw_client = Client::new(global.as_window());
- let trusted_client = Trusted::new(&*sw_client);
-
- ServiceWorkerGlobalScope::run_serviceworker_scope(
- init, script_url, global.pipeline(), devtools_receiver, worker.runtime.clone(), worker_ref,
- global.script_chan(), sender, receiver, trusted_client, worker_load_origin);
-
- worker
+ pub fn install_serviceworker(global: GlobalRef,
+ script_url: Url,
+ skip_waiting: bool) -> Root<ServiceWorker> {
+ ServiceWorker::new(global,
+ script_url.as_str(),
+ skip_waiting)
}
}
diff --git a/components/script/dom/serviceworkercontainer.rs b/components/script/dom/serviceworkercontainer.rs
index 744daba7b91..17fea7100be 100644
--- a/components/script/dom/serviceworkercontainer.rs
+++ b/components/script/dom/serviceworkercontainer.rs
@@ -98,7 +98,7 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer {
script_url,
scope_str.clone(),
self);
- ScriptThread::set_registration(scope, &*worker_registration);
+ ScriptThread::set_registration(scope, &*worker_registration, self.global().r().pipeline());
Ok(worker_registration)
}
}
diff --git a/components/script/dom/serviceworkerglobalscope.rs b/components/script/dom/serviceworkerglobalscope.rs
index cbe195d1b8e..4208754f91d 100644
--- a/components/script/dom/serviceworkerglobalscope.rs
+++ b/components/script/dom/serviceworkerglobalscope.rs
@@ -4,8 +4,7 @@
use devtools;
use devtools_traits::DevtoolScriptControlMsg;
-use dom::abstractworker::{WorkerScriptLoadOrigin, WorkerScriptMsg, SharedRt, SimpleWorkerErrorHandler};
-use dom::abstractworkerglobalscope::{SendableWorkerScriptChan, WorkerThreadWorkerChan};
+use dom::abstractworker::WorkerScriptMsg;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::ServiceWorkerGlobalScopeBinding;
@@ -13,66 +12,42 @@ use dom::bindings::codegen::Bindings::ServiceWorkerGlobalScopeBinding::ServiceWo
use dom::bindings::global::{GlobalRef, global_root_from_context};
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{Root, RootCollection};
-use dom::bindings::refcounted::{Trusted, LiveDOMReferences};
+use dom::bindings::refcounted::LiveDOMReferences;
use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
-use dom::client::Client;
use dom::messageevent::MessageEvent;
use dom::serviceworker::TrustedServiceWorkerAddress;
use dom::workerglobalscope::WorkerGlobalScope;
-use dom::workerglobalscope::WorkerGlobalScopeInit;
-use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
+use ipc_channel::ipc::{self, IpcSender, IpcReceiver};
use ipc_channel::router::ROUTER;
use js::jsapi::{JS_SetInterruptCallback, JSAutoCompartment, JSContext};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use msg::constellation_msg::PipelineId;
-use net_traits::{LoadContext, load_whole_resource, CustomResponse, IpcSend};
-use rand::random;
-use script_runtime::ScriptThreadEventCategory::ServiceWorkerEvent;
-use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
-use script_traits::{TimerEvent, TimerSource};
-use std::mem::replace;
+use net_traits::{LoadContext, load_whole_resource, IpcSend, CustomResponseMediator};
+use script_runtime::{CommonScriptMsg, StackRootTLS, get_reports, new_rt_and_cx};
+use script_traits::{TimerEvent, WorkerGlobalScopeInit, ScopeThings, ServiceWorkerMsg};
use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel};
-use std::sync::{Arc, Mutex};
-use std::time::Instant;
+use std::thread;
+use std::time::Duration;
use url::Url;
use util::prefs::PREFS;
use util::thread::spawn_named;
use util::thread_state;
use util::thread_state::{IN_WORKER, SCRIPT};
-/// Set the `worker` field of a related ServiceWorkerGlobalScope object to a particular
-/// value for the duration of this object's lifetime. This ensures that the related Worker
-/// object only lives as long as necessary (ie. while events are being executed), while
-/// providing a reference that can be cloned freely.
-struct AutoWorkerReset<'a> {
- workerscope: &'a ServiceWorkerGlobalScope,
- old_worker: Option<TrustedServiceWorkerAddress>,
+/// Messages used to control service worker event loop
+pub enum ServiceWorkerScriptMsg {
+ /// Message common to all workers
+ CommonWorker(WorkerScriptMsg),
+ // Message to request a custom response by the service worker
+ Response(CustomResponseMediator)
}
-impl<'a> AutoWorkerReset<'a> {
- fn new(workerscope: &'a ServiceWorkerGlobalScope,
- worker: TrustedServiceWorkerAddress)
- -> AutoWorkerReset<'a> {
- AutoWorkerReset {
- workerscope: workerscope,
- old_worker: replace(&mut *workerscope.worker.borrow_mut(), Some(worker)),
- }
- }
-}
-
-impl<'a> Drop for AutoWorkerReset<'a> {
- fn drop(&mut self) {
- *self.workerscope.worker.borrow_mut() = self.old_worker.clone();
- }
-}
-
-enum MixedMessage {
- FromServiceWorker((TrustedServiceWorkerAddress, WorkerScriptMsg)),
- FromScheduler((TrustedServiceWorkerAddress, TimerEvent)),
+pub enum MixedMessage {
+ FromServiceWorker(ServiceWorkerScriptMsg),
FromDevtools(DevtoolScriptControlMsg),
- FromNetwork(IpcSender<Option<CustomResponse>>),
+ FromTimeoutThread(()),
}
#[dom_struct]
@@ -80,18 +55,17 @@ pub struct ServiceWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope,
id: PipelineId,
#[ignore_heap_size_of = "Defined in std"]
- receiver: Receiver<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
+ receiver: Receiver<ServiceWorkerScriptMsg>,
#[ignore_heap_size_of = "Defined in std"]
- own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
+ own_sender: Sender<ServiceWorkerScriptMsg>,
#[ignore_heap_size_of = "Defined in std"]
- timer_event_port: Receiver<(TrustedServiceWorkerAddress, TimerEvent)>,
+ timer_event_port: Receiver<()>,
#[ignore_heap_size_of = "Trusted<T> has unclear ownership like JS<T>"]
worker: DOMRefCell<Option<TrustedServiceWorkerAddress>>,
- #[ignore_heap_size_of = "Can't measure trait objects"]
- /// Sender to the parent thread.
- parent_sender: Box<ScriptChan + Send>,
#[ignore_heap_size_of = "Defined in std"]
- service_worker_client: Trusted<Client>
+ swmanager_sender: IpcSender<ServiceWorkerMsg>,
+ #[ignore_heap_size_of = "Defined in std"]
+ scope_url: Url
}
impl ServiceWorkerGlobalScope {
@@ -100,26 +74,27 @@ impl ServiceWorkerGlobalScope {
id: PipelineId,
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
runtime: Runtime,
- parent_sender: Box<ScriptChan + Send>,
- own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
- receiver: Receiver<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
+ own_sender: Sender<ServiceWorkerScriptMsg>,
+ receiver: Receiver<ServiceWorkerScriptMsg>,
timer_event_chan: IpcSender<TimerEvent>,
- timer_event_port: Receiver<(TrustedServiceWorkerAddress, TimerEvent)>,
- client: Trusted<Client>)
+ timer_event_port: Receiver<()>,
+ swmanager_sender: IpcSender<ServiceWorkerMsg>,
+ scope_url: Url)
-> ServiceWorkerGlobalScope {
ServiceWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope::new_inherited(init,
worker_url,
runtime,
from_devtools_receiver,
- timer_event_chan),
+ timer_event_chan,
+ None),
id: id,
receiver: receiver,
- own_sender: own_sender,
timer_event_port: timer_event_port,
- parent_sender: parent_sender,
+ own_sender: own_sender,
worker: DOMRefCell::new(None),
- service_worker_client: client
+ swmanager_sender: swmanager_sender,
+ scope_url: scope_url
}
}
@@ -128,12 +103,12 @@ impl ServiceWorkerGlobalScope {
id: PipelineId,
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
runtime: Runtime,
- parent_sender: Box<ScriptChan + Send>,
- own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
- receiver: Receiver<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
+ own_sender: Sender<ServiceWorkerScriptMsg>,
+ receiver: Receiver<ServiceWorkerScriptMsg>,
timer_event_chan: IpcSender<TimerEvent>,
- timer_event_port: Receiver<(TrustedServiceWorkerAddress, TimerEvent)>,
- client: Trusted<Client>)
+ timer_event_port: Receiver<()>,
+ swmanager_sender: IpcSender<ServiceWorkerMsg>,
+ scope_url: Url)
-> Root<ServiceWorkerGlobalScope> {
let cx = runtime.cx();
let scope = box ServiceWorkerGlobalScope::new_inherited(init,
@@ -141,42 +116,39 @@ impl ServiceWorkerGlobalScope {
id,
from_devtools_receiver,
runtime,
- parent_sender,
own_sender,
receiver,
timer_event_chan,
timer_event_port,
- client);
+ swmanager_sender,
+ scope_url);
ServiceWorkerGlobalScopeBinding::Wrap(cx, scope)
}
#[allow(unsafe_code)]
- pub fn run_serviceworker_scope(init: WorkerGlobalScopeInit,
- worker_url: Url,
- id: PipelineId,
- from_devtools_receiver: IpcReceiver<DevtoolScriptControlMsg>,
- main_thread_rt: Arc<Mutex<Option<SharedRt>>>,
- worker: TrustedServiceWorkerAddress,
- parent_sender: Box<ScriptChan + Send>,
- own_sender: Sender<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
- receiver: Receiver<(TrustedServiceWorkerAddress, WorkerScriptMsg)>,
- client: Trusted<Client>,
- worker_load_origin: WorkerScriptLoadOrigin) {
- let serialized_worker_url = worker_url.to_string();
+ pub fn run_serviceworker_scope(scope_things: ScopeThings,
+ own_sender: Sender<ServiceWorkerScriptMsg>,
+ receiver: Receiver<ServiceWorkerScriptMsg>,
+ devtools_receiver: IpcReceiver<DevtoolScriptControlMsg>,
+ swmanager_sender: IpcSender<ServiceWorkerMsg>,
+ scope_url: Url) {
+ let ScopeThings { script_url,
+ pipeline_id,
+ init,
+ worker_load_origin,
+ .. } = scope_things;
+
+ let serialized_worker_url = script_url.to_string();
spawn_named(format!("ServiceWorker for {}", serialized_worker_url), move || {
thread_state::initialize(SCRIPT | IN_WORKER);
-
let roots = RootCollection::new();
let _stack_roots_tls = StackRootTLS::new(&roots);
-
let (url, source) = match load_whole_resource(LoadContext::Script,
&init.resource_threads.sender(),
- worker_url,
+ script_url,
&worker_load_origin) {
Err(_) => {
println!("error loading script {}", serialized_worker_url);
- parent_sender.send(CommonScriptMsg::RunnableMsg(ServiceWorkerEvent,
- box SimpleWorkerErrorHandler::new(worker))).unwrap();
return;
}
Ok((metadata, bytes)) => {
@@ -185,25 +157,18 @@ impl ServiceWorkerGlobalScope {
};
let runtime = unsafe { new_rt_and_cx() };
- *main_thread_rt.lock().unwrap() = Some(SharedRt::new(&runtime));
let (devtools_mpsc_chan, devtools_mpsc_port) = channel();
- ROUTER.route_ipc_receiver_to_mpsc_sender(from_devtools_receiver, devtools_mpsc_chan);
+ ROUTER.route_ipc_receiver_to_mpsc_sender(devtools_receiver, devtools_mpsc_chan);
- let (timer_tx, timer_rx) = channel();
- let (timer_ipc_chan, timer_ipc_port) = ipc::channel().unwrap();
- let worker_for_route = worker.clone();
- ROUTER.add_route(timer_ipc_port.to_opaque(), box move |message| {
- let event = message.to().unwrap();
- timer_tx.send((worker_for_route.clone(), event)).unwrap();
- });
+ // TODO XXXcreativcoder use this timer_ipc_port, when we have a service worker instance here
+ let (timer_ipc_chan, _timer_ipc_port) = ipc::channel().unwrap();
+ let (timer_chan, timer_port) = channel();
let global = ServiceWorkerGlobalScope::new(
- init, url, id, devtools_mpsc_port, runtime,
- parent_sender.clone(), own_sender, receiver,
- timer_ipc_chan, timer_rx, client);
- // FIXME(njn): workers currently don't have a unique ID suitable for using in reporter
- // registration (#6631), so we instead use a random number and cross our fingers.
+ init, url, pipeline_id, devtools_mpsc_port, runtime,
+ own_sender, receiver,
+ timer_ipc_chan, timer_port, swmanager_sender, scope_url);
let scope = global.upcast::<WorkerGlobalScope>();
unsafe {
@@ -211,35 +176,25 @@ impl ServiceWorkerGlobalScope {
JS_SetInterruptCallback(scope.runtime(), Some(interrupt_callback));
}
- if scope.is_closing() {
- return;
- }
-
- {
- let _ar = AutoWorkerReset::new(global.r(), worker);
- scope.execute_script(DOMString::from(source));
- }
-
+ scope.execute_script(DOMString::from(source));
- let reporter_name = format!("service-worker-reporter-{}", random::<u64>());
- scope.mem_profiler_chan().run_with_memory_reporting(|| {
- // Service workers are time limited
- let sw_lifetime = Instant::now();
+ // Service workers are time limited
+ spawn_named("SWTimeoutThread".to_owned(), move || {
let sw_lifetime_timeout = PREFS.get("dom.serviceworker.timeout_seconds").as_u64().unwrap();
- while let Ok(event) = global.receive_event() {
- if scope.is_closing() {
- break;
- }
- global.handle_event(event);
- if sw_lifetime.elapsed().as_secs() == sw_lifetime_timeout {
- break;
- }
+ thread::sleep(Duration::new(sw_lifetime_timeout, 0));
+ let _ = timer_chan.send(());
+ });
+
+ // TODO XXXcreativcoder bring back run_with_memory_reporting when things are more concrete here.
+ while let Ok(event) = global.receive_event() {
+ if !global.handle_event(event) {
+ break;
}
- }, reporter_name, parent_sender, CommonScriptMsg::CollectReports);
+ }
});
}
- fn handle_event(&self, event: MixedMessage) {
+ fn handle_event(&self, event: MixedMessage) -> bool {
match event {
MixedMessage::FromDevtools(msg) => {
let global_ref = GlobalRef::Worker(self.upcast());
@@ -252,33 +207,24 @@ impl ServiceWorkerGlobalScope {
devtools::handle_wants_live_notifications(&global_ref, bool_val),
_ => debug!("got an unusable devtools control message inside the worker!"),
}
- },
- MixedMessage::FromScheduler((linked_worker, timer_event)) => {
- match timer_event {
- TimerEvent(TimerSource::FromWorker, id) => {
- let _ar = AutoWorkerReset::new(self, linked_worker);
- let scope = self.upcast::<WorkerGlobalScope>();
- scope.handle_fire_timer(id);
- },
- TimerEvent(_, _) => {
- panic!("The service worker received a TimerEvent from a window.")
- }
- }
+ true
}
- MixedMessage::FromServiceWorker((linked_worker, msg)) => {
- let _ar = AutoWorkerReset::new(self, linked_worker);
+ MixedMessage::FromServiceWorker(msg) => {
self.handle_script_event(msg);
- },
- MixedMessage::FromNetwork(network_sender) => {
- // We send None as of now
- let _ = network_sender.send(None);
+ true
+ }
+ MixedMessage::FromTimeoutThread(_) => {
+ let _ = self.swmanager_sender.send(ServiceWorkerMsg::Timeout(self.scope_url.clone()));
+ false
}
}
}
- fn handle_script_event(&self, msg: WorkerScriptMsg) {
+ fn handle_script_event(&self, msg: ServiceWorkerScriptMsg) {
+ use self::ServiceWorkerScriptMsg::*;
+
match msg {
- WorkerScriptMsg::DOMMessage(data) => {
+ CommonWorker(WorkerScriptMsg::DOMMessage(data)) => {
let scope = self.upcast::<WorkerGlobalScope>();
let target = self.upcast();
let _ac = JSAutoCompartment::new(scope.get_cx(),
@@ -287,19 +233,22 @@ impl ServiceWorkerGlobalScope {
data.read(GlobalRef::Worker(scope), message.handle_mut());
MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message.handle());
},
- WorkerScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) => {
+ CommonWorker(WorkerScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable))) => {
runnable.handler()
},
- WorkerScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr)) => {
+ CommonWorker(WorkerScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr))) => {
LiveDOMReferences::cleanup(addr);
},
- WorkerScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan)) => {
+ CommonWorker(WorkerScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan))) => {
let scope = self.upcast::<WorkerGlobalScope>();
let cx = scope.get_cx();
let path_seg = format!("url({})", scope.get_url());
let reports = get_reports(cx, path_seg);
reports_chan.send(reports);
},
+ Response(mediator) => {
+ let _ = mediator.response_chan.send(None);
+ }
}
}
@@ -307,59 +256,39 @@ impl ServiceWorkerGlobalScope {
fn receive_event(&self) -> Result<MixedMessage, RecvError> {
let scope = self.upcast::<WorkerGlobalScope>();
let worker_port = &self.receiver;
- let timer_event_port = &self.timer_event_port;
let devtools_port = scope.from_devtools_receiver();
- let msg_port = scope.custom_message_port();
+ let timer_event_port = &self.timer_event_port;
let sel = Select::new();
let mut worker_handle = sel.handle(worker_port);
- let mut timer_event_handle = sel.handle(timer_event_port);
let mut devtools_handle = sel.handle(devtools_port);
- let mut msg_port_handle = sel.handle(msg_port);
+ let mut timer_port_handle = sel.handle(timer_event_port);
unsafe {
worker_handle.add();
- timer_event_handle.add();
if scope.from_devtools_sender().is_some() {
devtools_handle.add();
}
- msg_port_handle.add();
+ timer_port_handle.add();
}
+
let ret = sel.wait();
if ret == worker_handle.id() {
Ok(MixedMessage::FromServiceWorker(try!(worker_port.recv())))
- } else if ret == timer_event_handle.id() {
- Ok(MixedMessage::FromScheduler(try!(timer_event_port.recv())))
- } else if ret == devtools_handle.id() {
+ }else if ret == devtools_handle.id() {
Ok(MixedMessage::FromDevtools(try!(devtools_port.recv())))
- } else if ret == msg_port_handle.id() {
- Ok(MixedMessage::FromNetwork(try!(msg_port.recv())))
+ } else if ret == timer_port_handle.id() {
+ Ok(MixedMessage::FromTimeoutThread(try!(timer_event_port.recv())))
} else {
panic!("unexpected select result!")
}
}
- pub fn script_chan(&self) -> Box<ScriptChan + Send> {
- box WorkerThreadWorkerChan {
- sender: self.own_sender.clone(),
- worker: self.worker.borrow().as_ref().unwrap().clone(),
- }
- }
-
pub fn pipeline(&self) -> PipelineId {
self.id
}
pub fn process_event(&self, msg: CommonScriptMsg) {
- self.handle_script_event(WorkerScriptMsg::Common(msg));
- }
-
- pub fn new_script_pair(&self) -> (Box<ScriptChan + Send>, Box<ScriptPort + Send>) {
- let (tx, rx) = channel();
- let chan = box SendableWorkerScriptChan {
- sender: tx,
- worker: self.worker.borrow().as_ref().unwrap().clone(),
- };
- (chan, box rx)
+ self.handle_script_event(ServiceWorkerScriptMsg::CommonWorker(WorkerScriptMsg::Common(msg)));
}
}
diff --git a/components/script/dom/serviceworkerregistration.rs b/components/script/dom/serviceworkerregistration.rs
index 358331afffc..e20b7e06c47 100644
--- a/components/script/dom/serviceworkerregistration.rs
+++ b/components/script/dom/serviceworkerregistration.rs
@@ -11,6 +11,8 @@ use dom::bindings::str::USVString;
use dom::eventtarget::EventTarget;
use dom::serviceworker::ServiceWorker;
use dom::serviceworkercontainer::Controllable;
+use dom::workerglobalscope::prepare_workerscope_init;
+use script_traits::{WorkerScriptLoadOrigin, ScopeThings};
use url::Url;
#[dom_struct]
@@ -19,7 +21,7 @@ pub struct ServiceWorkerRegistration {
active: Option<JS<ServiceWorker>>,
installing: Option<JS<ServiceWorker>>,
waiting: Option<JS<ServiceWorker>>,
- scope: String,
+ scope: String
}
impl ServiceWorkerRegistration {
@@ -29,7 +31,7 @@ impl ServiceWorkerRegistration {
active: Some(JS::from_ref(active_sw)),
installing: None,
waiting: None,
- scope: scope
+ scope: scope,
}
}
#[allow(unrooted_must_root)]
@@ -37,11 +39,47 @@ impl ServiceWorkerRegistration {
script_url: Url,
scope: String,
container: &Controllable) -> Root<ServiceWorkerRegistration> {
- let active_worker = ServiceWorker::init_service_worker(global, script_url, true);
+ let active_worker = ServiceWorker::install_serviceworker(global, script_url.clone(), true);
active_worker.set_transition_state(ServiceWorkerState::Installed);
container.set_controller(&*active_worker.clone());
reflect_dom_object(box ServiceWorkerRegistration::new_inherited(&*active_worker, scope), global, Wrap)
}
+
+ pub fn get_installed(&self) -> &ServiceWorker {
+ self.active.as_ref().unwrap()
+ }
+
+ pub fn create_scope_things(global: GlobalRef, script_url: Url) -> ScopeThings {
+ let worker_load_origin = WorkerScriptLoadOrigin {
+ referrer_url: None,
+ referrer_policy: None,
+ pipeline_id: Some(global.pipeline())
+ };
+
+ let worker_id = global.get_next_worker_id();
+ let init = prepare_workerscope_init(global, None);
+ ScopeThings {
+ script_url: script_url,
+ pipeline_id: global.pipeline(),
+ init: init,
+ worker_load_origin: worker_load_origin,
+ devtools_chan: global.devtools_chan(),
+ worker_id: worker_id
+ }
+ }
+}
+
+pub fn longest_prefix_match(stored_scope: &Url, potential_match: &Url) -> bool {
+ if stored_scope.origin() != potential_match.origin() {
+ return false;
+ }
+ let scope_chars = stored_scope.path().chars();
+ let matching_chars = potential_match.path().chars();
+ if scope_chars.count() > matching_chars.count() {
+ return false;
+ }
+
+ stored_scope.path().chars().zip(potential_match.path().chars()).all(|(scope, matched)| scope == matched)
}
impl ServiceWorkerRegistrationMethods for ServiceWorkerRegistration {
diff --git a/components/script/dom/servohtmlparser.rs b/components/script/dom/servohtmlparser.rs
index 884ac6c8653..a28612416fc 100644
--- a/components/script/dom/servohtmlparser.rs
+++ b/components/script/dom/servohtmlparser.rs
@@ -171,13 +171,24 @@ impl AsyncResponseListener for ParserContext {
Some(parser) => parser.root(),
None => return,
};
- parser.r().document().finish_load(LoadType::PageSource(self.url.clone()));
- if let Err(err) = status {
- debug!("Failed to load page URL {}, error: {:?}", self.url, err);
+ if let Err(NetworkError::Internal(ref reason)) = status {
+ // Show an error page for network errors,
+ // certificate errors are handled earlier.
+ self.is_synthesized_document = true;
+ let parser = parser.r();
+ let page_bytes = read_resource_file("neterror.html").unwrap();
+ let page = String::from_utf8(page_bytes).unwrap();
+ let page = page.replace("${reason}", reason);
+ parser.pending_input().borrow_mut().push(page);
+ parser.parse_sync();
+ } else if let Err(err) = status {
// TODO(Savago): we should send a notification to callers #5463.
+ debug!("Failed to load page URL {}, error: {:?}", self.url, err);
}
+ parser.r().document().finish_load(LoadType::PageSource(self.url.clone()));
+
parser.r().last_chunk_received().set(true);
if !parser.r().is_suspended() {
parser.r().parse_sync();
diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs
index d927c5ba213..d6d1e1968f8 100644
--- a/components/script/dom/storage.rs
+++ b/components/script/dom/storage.rs
@@ -19,7 +19,6 @@ use net_traits::IpcSend;
use net_traits::storage_thread::{StorageThreadMsg, StorageType};
use script_thread::{Runnable, ScriptThread};
use task_source::TaskSource;
-use task_source::dom_manipulation::DOMManipulationTask;
use url::Url;
#[dom_struct]
@@ -159,10 +158,11 @@ impl Storage {
new_value: Option<String>) {
let global_root = self.global();
let global_ref = global_root.r();
- let task_source = global_ref.as_window().dom_manipulation_task_source();
+ let window = global_ref.as_window();
+ let task_source = window.dom_manipulation_task_source();
let trusted_storage = Trusted::new(self);
- task_source.queue(DOMManipulationTask::Runnable(
- box StorageEventRunnable::new(trusted_storage, key, old_value, new_value))).unwrap();
+ task_source.queue(box StorageEventRunnable::new(trusted_storage, key, old_value, new_value),
+ global_ref).unwrap();
}
}
diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs
index 64fb6fb7578..13579d71330 100644
--- a/components/script/dom/testbinding.rs
+++ b/components/script/dom/testbinding.rs
@@ -9,8 +9,9 @@ use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::codegen::Bindings::TestBindingBinding;
use dom::bindings::codegen::Bindings::TestBindingBinding::{TestBindingMethods, TestDictionary};
use dom::bindings::codegen::Bindings::TestBindingBinding::{TestDictionaryDefaults, TestEnum};
-use dom::bindings::codegen::UnionTypes::{BlobOrBoolean, BlobOrBlobSequence};
+use dom::bindings::codegen::UnionTypes::{BlobOrBoolean, BlobOrBlobSequence, LongOrLongSequenceSequence};
use dom::bindings::codegen::UnionTypes::{BlobOrString, BlobOrUnsignedLong, EventOrString};
+use dom::bindings::codegen::UnionTypes::{ByteStringOrLong, ByteStringSequenceOrLongOrString, ByteStringSequenceOrLong};
use dom::bindings::codegen::UnionTypes::{EventOrUSVString, HTMLElementOrLong};
use dom::bindings::codegen::UnionTypes::{HTMLElementOrUnsignedLongOrStringOrBoolean, LongSequenceOrBoolean};
use dom::bindings::codegen::UnionTypes::{StringOrLongSequence, StringOrStringSequence, StringSequenceOrUnsignedLong};
@@ -132,6 +133,10 @@ impl TestBindingMethods for TestBinding {
BlobOrUnsignedLong::UnsignedLong(0u32)
}
fn SetUnion8Attribute(&self, _: BlobOrUnsignedLong) {}
+ fn Union9Attribute(&self) -> ByteStringOrLong {
+ ByteStringOrLong::ByteString(ByteString::new(vec!()))
+ }
+ fn SetUnion9Attribute(&self, _: ByteStringOrLong) {}
fn ArrayAttribute(&self, _: *mut JSContext) -> *mut JSObject { NullValue().to_object_or_null() }
fn AnyAttribute(&self, _: *mut JSContext) -> JSVal { NullValue() }
fn SetAnyAttribute(&self, _: *mut JSContext, _: HandleValue) {}
@@ -210,6 +215,10 @@ impl TestBindingMethods for TestBinding {
Some(StringOrBoolean::Boolean(true))
}
fn SetUnion5AttributeNullable(&self, _: Option<StringOrBoolean>) {}
+ fn GetUnion6AttributeNullable(&self) -> Option<ByteStringOrLong> {
+ Some(ByteStringOrLong::ByteString(ByteString::new(vec!())))
+ }
+ fn SetUnion6AttributeNullable(&self, _: Option<ByteStringOrLong>) {}
fn BinaryRenamedMethod(&self) -> () {}
fn ReceiveVoid(&self) -> () {}
fn ReceiveBoolean(&self) -> bool { false }
@@ -245,6 +254,10 @@ impl TestBindingMethods for TestBinding {
fn ReceiveUnion9(&self) -> HTMLElementOrUnsignedLongOrStringOrBoolean {
HTMLElementOrUnsignedLongOrStringOrBoolean::Boolean(true)
}
+ fn ReceiveUnion10(&self) -> ByteStringOrLong { ByteStringOrLong::ByteString(ByteString::new(vec!())) }
+ fn ReceiveUnion11(&self) -> ByteStringSequenceOrLongOrString {
+ ByteStringSequenceOrLongOrString::ByteStringSequence(vec!(ByteString::new(vec!())))
+ }
fn ReceiveSequence(&self) -> Vec<i32> { vec![1] }
fn ReceiveInterfaceSequence(&self) -> Vec<Root<Blob>> {
vec![Blob::new(self.global().r(), BlobImpl::new_from_bytes(vec![]), "".to_owned())]
@@ -286,6 +299,9 @@ impl TestBindingMethods for TestBinding {
fn ReceiveNullableUnion5(&self) -> Option<UnsignedLongOrBoolean> {
Some(UnsignedLongOrBoolean::UnsignedLong(0u32))
}
+ fn ReceiveNullableUnion6(&self) -> Option<ByteStringOrLong> {
+ Some(ByteStringOrLong::ByteString(ByteString::new(vec!())))
+ }
fn ReceiveNullableSequence(&self) -> Option<Vec<i32>> { Some(vec![1]) }
fn ReceiveTestDictionaryWithSuccessOnKeyword(&self) -> TestDictionary {
TestDictionary {
@@ -382,6 +398,7 @@ impl TestBindingMethods for TestBinding {
fn PassUnion5(&self, _: StringOrBoolean) {}
fn PassUnion6(&self, _: UnsignedLongOrBoolean) {}
fn PassUnion7(&self, _: StringSequenceOrUnsignedLong) {}
+ fn PassUnion8(&self, _: ByteStringSequenceOrLong) {}
fn PassAny(&self, _: *mut JSContext, _: HandleValue) {}
fn PassObject(&self, _: *mut JSContext, _: *mut JSObject) {}
fn PassCallbackFunction(&self, _: Rc<Function>) {}
@@ -414,6 +431,7 @@ impl TestBindingMethods for TestBinding {
fn PassNullableUnion3(&self, _: Option<StringOrLongSequence>) {}
fn PassNullableUnion4(&self, _: Option<LongSequenceOrBoolean>) {}
fn PassNullableUnion5(&self, _: Option<UnsignedLongOrBoolean>) {}
+ fn PassNullableUnion6(&self, _: Option<ByteStringOrLong>) {}
fn PassNullableCallbackFunction(&self, _: Option<Rc<Function>>) {}
fn PassNullableCallbackInterface(&self, _: Option<Rc<EventListener>>) {}
fn PassNullableSequence(&self, _: Option<Vec<i32>>) {}
@@ -441,6 +459,7 @@ impl TestBindingMethods for TestBinding {
fn PassOptionalUnion3(&self, _: Option<StringOrLongSequence>) {}
fn PassOptionalUnion4(&self, _: Option<LongSequenceOrBoolean>) {}
fn PassOptionalUnion5(&self, _: Option<UnsignedLongOrBoolean>) {}
+ fn PassOptionalUnion6(&self, _: Option<ByteStringOrLong>) {}
fn PassOptionalAny(&self, _: *mut JSContext, _: HandleValue) {}
fn PassOptionalObject(&self, _: *mut JSContext, _: Option<*mut JSObject>) {}
fn PassOptionalCallbackFunction(&self, _: Option<Rc<Function>>) {}
@@ -471,6 +490,7 @@ impl TestBindingMethods for TestBinding {
fn PassOptionalNullableUnion3(&self, _: Option<Option<StringOrLongSequence>>) {}
fn PassOptionalNullableUnion4(&self, _: Option<Option<LongSequenceOrBoolean>>) {}
fn PassOptionalNullableUnion5(&self, _: Option<Option<UnsignedLongOrBoolean>>) {}
+ fn PassOptionalNullableUnion6(&self, _: Option<Option<ByteStringOrLong>>) {}
fn PassOptionalNullableCallbackFunction(&self, _: Option<Option<Rc<Function>>>) {}
fn PassOptionalNullableCallbackInterface(&self, _: Option<Option<Rc<EventListener>>>) {}
fn PassOptionalNullableSequence(&self, _: Option<Option<Vec<i32>>>) {}
@@ -555,6 +575,7 @@ impl TestBindingMethods for TestBinding {
fn PassVariadicUnion4(&self, _: Vec<BlobOrBoolean>) {}
fn PassVariadicUnion5(&self, _: Vec<StringOrUnsignedLong>) {}
fn PassVariadicUnion6(&self, _: Vec<UnsignedLongOrBoolean>) {}
+ fn PassVariadicUnion7(&self, _: Vec<ByteStringOrLong>) {}
fn PassVariadicAny(&self, _: *mut JSContext, _: Vec<HandleValue>) {}
fn PassVariadicObject(&self, _: *mut JSContext, _: Vec<*mut JSObject>) {}
fn BooleanMozPreference(&self, pref_name: DOMString) -> bool {
@@ -572,6 +593,17 @@ impl TestBindingMethods for TestBinding {
fn FuncControlledMethodDisabled(&self) {}
fn FuncControlledMethodEnabled(&self) {}
+ fn PassSequenceSequence(&self, _seq: Vec<Vec<i32>>) {}
+ fn ReturnSequenceSequence(&self) -> Vec<Vec<i32>> { vec![] }
+ fn PassUnionSequenceSequence(&self, seq: LongOrLongSequenceSequence) {
+ match seq {
+ LongOrLongSequenceSequence::Long(_) => (),
+ LongOrLongSequenceSequence::LongSequenceSequence(seq) => {
+ let _seq: Vec<Vec<i32>> = seq;
+ }
+ }
+ }
+
#[allow(unsafe_code)]
fn CrashHard(&self) {
static READ_ONLY_VALUE: i32 = 0;
@@ -581,6 +613,10 @@ impl TestBindingMethods for TestBinding {
}
}
+ fn AdvanceClock(&self, ms: i32) {
+ self.global().r().as_window().advance_animation_clock(ms);
+ }
+
fn Panic(&self) { panic!("explicit panic from script") }
}
diff --git a/components/script/dom/url.rs b/components/script/dom/url.rs
index 961d3c2fd29..81c806de806 100644
--- a/components/script/dom/url.rs
+++ b/components/script/dom/url.rs
@@ -15,8 +15,8 @@ use dom::urlhelper::UrlHelper;
use dom::urlsearchparams::URLSearchParams;
use ipc_channel::ipc;
use net_traits::IpcSend;
-use net_traits::blob_url_store::parse_blob_url;
-use net_traits::filemanager_thread::{FileOrigin, SelectedFileId, FileManagerThreadMsg};
+use net_traits::blob_url_store::{get_blob_origin, parse_blob_url};
+use net_traits::filemanager_thread::{SelectedFileId, FileManagerThreadMsg};
use std::borrow::ToOwned;
use std::default::Default;
use url::quirks::domain_to_unicode;
@@ -117,7 +117,7 @@ impl URL {
pub fn CreateObjectURL(global: GlobalRef, blob: &Blob) -> DOMString {
/// XXX: Second field is an unicode-serialized Origin, it is a temporary workaround
/// and should not be trusted. See issue https://github.com/servo/servo/issues/11722
- let origin = URL::get_blob_origin(&global.get_url());
+ let origin = get_blob_origin(&global.get_url());
if blob.IsClosed() {
// Generate a dummy id
@@ -141,10 +141,10 @@ impl URL {
NOTE: The first step is unnecessary, since closed blobs do not exist in the store
*/
- let origin = global.get_url().origin().unicode_serialization();
+ let origin = get_blob_origin(&global.get_url());
if let Ok(url) = Url::parse(&url) {
- if let Some((id, _)) = parse_blob_url(&url) {
+ if let Ok((id, _, _)) = parse_blob_url(&url) {
let filemanager = global.resource_threads().sender();
let id = SelectedFileId(id.simple().to_string());
let (tx, rx) = ipc::channel().unwrap();
@@ -172,18 +172,6 @@ impl URL {
result
}
-
- /* NOTE(izgzhen): WebKit will return things like blob:file:///XXX
- while Chrome will return blob:null/XXX
- This is not well-specified, and I prefer the WebKit way here
- */
- fn get_blob_origin(url: &Url) -> FileOrigin {
- if url.scheme() == "file" {
- "file://".to_string()
- } else {
- url.origin().unicode_serialization()
- }
- }
}
impl URLMethods for URL {
diff --git a/components/script/dom/userscripts.rs b/components/script/dom/userscripts.rs
index 25490fb7726..e1c071e83c7 100644
--- a/components/script/dom/userscripts.rs
+++ b/components/script/dom/userscripts.rs
@@ -24,9 +24,12 @@ pub fn load_script(head: &HTMLHeadElement) {
let doc = doc.r();
let path = if &**path_str == "" {
- let mut p = resources_dir_path();
- p.push("user-agent-js");
- p
+ if let Ok(mut p) = resources_dir_path() {
+ p.push("user-agent-js");
+ p
+ } else {
+ return
+ }
} else {
PathBuf::from(path_str)
};
diff --git a/components/script/dom/webidls/DedicatedWorkerGlobalScope.webidl b/components/script/dom/webidls/DedicatedWorkerGlobalScope.webidl
index cd0d393e22e..53996ee3965 100644
--- a/components/script/dom/webidls/DedicatedWorkerGlobalScope.webidl
+++ b/components/script/dom/webidls/DedicatedWorkerGlobalScope.webidl
@@ -8,4 +8,6 @@
[Throws]
void postMessage(any message/*, optional sequence<Transferable> transfer*/);
attribute EventHandler onmessage;
+
+ void close();
};
diff --git a/components/script/dom/webidls/Document.webidl b/components/script/dom/webidls/Document.webidl
index 09b82109ae8..6ea8d3e7e91 100644
--- a/components/script/dom/webidls/Document.webidl
+++ b/components/script/dom/webidls/Document.webidl
@@ -82,7 +82,7 @@ partial /*sealed*/ interface Document {
[/*PutForwards=href, */Unforgeable]
readonly attribute Location? location;
readonly attribute DOMString domain;
- // readonly attribute DOMString referrer;
+ readonly attribute DOMString referrer;
[Throws]
attribute DOMString cookie;
readonly attribute DOMString lastModified;
diff --git a/components/script/dom/webidls/HTMLAnchorElement.webidl b/components/script/dom/webidls/HTMLAnchorElement.webidl
index c728744e495..f78d1dae6dd 100644
--- a/components/script/dom/webidls/HTMLAnchorElement.webidl
+++ b/components/script/dom/webidls/HTMLAnchorElement.webidl
@@ -11,7 +11,6 @@
*/
// https://html.spec.whatwg.org/multipage/#htmlanchorelement
-[Exposed=(Window,Worker)]
interface HTMLAnchorElement : HTMLElement {
attribute DOMString target;
// attribute DOMString download;
diff --git a/components/script/dom/webidls/HTMLAppletElement.webidl b/components/script/dom/webidls/HTMLAppletElement.webidl
index efb3d24b2e7..9cfeb4183df 100644
--- a/components/script/dom/webidls/HTMLAppletElement.webidl
+++ b/components/script/dom/webidls/HTMLAppletElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlappletelement
-[Exposed=(Window,Worker)]
interface HTMLAppletElement : HTMLElement {
// attribute DOMString align;
// attribute DOMString alt;
diff --git a/components/script/dom/webidls/HTMLAreaElement.webidl b/components/script/dom/webidls/HTMLAreaElement.webidl
index f39db4fa4d2..14883df3613 100644
--- a/components/script/dom/webidls/HTMLAreaElement.webidl
+++ b/components/script/dom/webidls/HTMLAreaElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlareaelement
-[Exposed=(Window,Worker)]
interface HTMLAreaElement : HTMLElement {
// attribute DOMString alt;
// attribute DOMString coords;
diff --git a/components/script/dom/webidls/HTMLAudioElement.webidl b/components/script/dom/webidls/HTMLAudioElement.webidl
index df0710b1856..09ad8a7cdb3 100644
--- a/components/script/dom/webidls/HTMLAudioElement.webidl
+++ b/components/script/dom/webidls/HTMLAudioElement.webidl
@@ -4,5 +4,4 @@
// https://html.spec.whatwg.org/multipage/#htmlaudioelement
//[NamedConstructor=Audio(optional DOMString src)]
-[Exposed=(Window,Worker)]
interface HTMLAudioElement : HTMLMediaElement {};
diff --git a/components/script/dom/webidls/HTMLBRElement.webidl b/components/script/dom/webidls/HTMLBRElement.webidl
index 4d811f3e285..ab277396bdd 100644
--- a/components/script/dom/webidls/HTMLBRElement.webidl
+++ b/components/script/dom/webidls/HTMLBRElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlbrelement
-[Exposed=(Window,Worker)]
interface HTMLBRElement : HTMLElement {
// also has obsolete members
};
diff --git a/components/script/dom/webidls/HTMLBaseElement.webidl b/components/script/dom/webidls/HTMLBaseElement.webidl
index dee9895c8ef..a13be544cb9 100644
--- a/components/script/dom/webidls/HTMLBaseElement.webidl
+++ b/components/script/dom/webidls/HTMLBaseElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlbaseelement
-[Exposed=(Window,Worker)]
interface HTMLBaseElement : HTMLElement {
attribute DOMString href;
// attribute DOMString target;
diff --git a/components/script/dom/webidls/HTMLBodyElement.webidl b/components/script/dom/webidls/HTMLBodyElement.webidl
index 31097e75614..36c6f4d64e3 100644
--- a/components/script/dom/webidls/HTMLBodyElement.webidl
+++ b/components/script/dom/webidls/HTMLBodyElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#the-body-element
-[Exposed=(Window,Worker)]
interface HTMLBodyElement : HTMLElement {
// also has obsolete members
};
diff --git a/components/script/dom/webidls/HTMLButtonElement.webidl b/components/script/dom/webidls/HTMLButtonElement.webidl
index a5c689cbc46..7f663fd305f 100644
--- a/components/script/dom/webidls/HTMLButtonElement.webidl
+++ b/components/script/dom/webidls/HTMLButtonElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlbuttonelement
-[Exposed=(Window,Worker)]
interface HTMLButtonElement : HTMLElement {
// attribute boolean autofocus;
attribute boolean disabled;
diff --git a/components/script/dom/webidls/HTMLDListElement.webidl b/components/script/dom/webidls/HTMLDListElement.webidl
index e0420cf8418..b6275107db5 100644
--- a/components/script/dom/webidls/HTMLDListElement.webidl
+++ b/components/script/dom/webidls/HTMLDListElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmldlistelement
-[Exposed=(Window,Worker)]
interface HTMLDListElement : HTMLElement {
// also has obsolete members
};
diff --git a/components/script/dom/webidls/HTMLDataElement.webidl b/components/script/dom/webidls/HTMLDataElement.webidl
index e0b2aa2cafa..be932250678 100644
--- a/components/script/dom/webidls/HTMLDataElement.webidl
+++ b/components/script/dom/webidls/HTMLDataElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmldataelement
-[Exposed=(Window,Worker)]
interface HTMLDataElement : HTMLElement {
// attribute DOMString value;
};
diff --git a/components/script/dom/webidls/HTMLDataListElement.webidl b/components/script/dom/webidls/HTMLDataListElement.webidl
index c970ae495fb..b8673b21c77 100644
--- a/components/script/dom/webidls/HTMLDataListElement.webidl
+++ b/components/script/dom/webidls/HTMLDataListElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmldatalistelement
-[Exposed=(Window,Worker)]
interface HTMLDataListElement : HTMLElement {
readonly attribute HTMLCollection options;
};
diff --git a/components/script/dom/webidls/HTMLDetailsElement.webidl b/components/script/dom/webidls/HTMLDetailsElement.webidl
index 8dbffdea064..811465c1c02 100644
--- a/components/script/dom/webidls/HTMLDetailsElement.webidl
+++ b/components/script/dom/webidls/HTMLDetailsElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmldetailselement
-[Exposed=(Window,Worker)]
interface HTMLDetailsElement : HTMLElement {
attribute boolean open;
};
diff --git a/components/script/dom/webidls/HTMLDialogElement.webidl b/components/script/dom/webidls/HTMLDialogElement.webidl
index 82d11ea2cae..78a14e1e2a0 100644
--- a/components/script/dom/webidls/HTMLDialogElement.webidl
+++ b/components/script/dom/webidls/HTMLDialogElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmldialogelement
-[Exposed=(Window,Worker)]
interface HTMLDialogElement : HTMLElement {
attribute boolean open;
attribute DOMString returnValue;
diff --git a/components/script/dom/webidls/HTMLDirectoryElement.webidl b/components/script/dom/webidls/HTMLDirectoryElement.webidl
index 4a1d8af74ab..5df65cd90c2 100644
--- a/components/script/dom/webidls/HTMLDirectoryElement.webidl
+++ b/components/script/dom/webidls/HTMLDirectoryElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmldirectoryelement
-[Exposed=(Window,Worker)]
interface HTMLDirectoryElement : HTMLElement {
// attribute boolean compact;
};
diff --git a/components/script/dom/webidls/HTMLDivElement.webidl b/components/script/dom/webidls/HTMLDivElement.webidl
index 827dfe7ab49..46ee67ee0e5 100644
--- a/components/script/dom/webidls/HTMLDivElement.webidl
+++ b/components/script/dom/webidls/HTMLDivElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmldivelement
-[Exposed=(Window,Worker)]
interface HTMLDivElement : HTMLElement {
// also has obsolete members
};
diff --git a/components/script/dom/webidls/HTMLEmbedElement.webidl b/components/script/dom/webidls/HTMLEmbedElement.webidl
index 3e4063c9377..26fa4c3ea5a 100644
--- a/components/script/dom/webidls/HTMLEmbedElement.webidl
+++ b/components/script/dom/webidls/HTMLEmbedElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlembedelement
-[Exposed=(Window,Worker)]
interface HTMLEmbedElement : HTMLElement {
// attribute DOMString src;
// attribute DOMString type;
diff --git a/components/script/dom/webidls/HTMLFieldSetElement.webidl b/components/script/dom/webidls/HTMLFieldSetElement.webidl
index 6c05b23f9ae..d041cdd612f 100644
--- a/components/script/dom/webidls/HTMLFieldSetElement.webidl
+++ b/components/script/dom/webidls/HTMLFieldSetElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlfieldsetelement
-[Exposed=(Window,Worker)]
interface HTMLFieldSetElement : HTMLElement {
attribute boolean disabled;
readonly attribute HTMLFormElement? form;
diff --git a/components/script/dom/webidls/HTMLFontElement.webidl b/components/script/dom/webidls/HTMLFontElement.webidl
index 7c524eb0a4d..74db3f45057 100644
--- a/components/script/dom/webidls/HTMLFontElement.webidl
+++ b/components/script/dom/webidls/HTMLFontElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlfontelement
-[Exposed=(Window,Worker)]
interface HTMLFontElement : HTMLElement {
[TreatNullAs=EmptyString] attribute DOMString color;
attribute DOMString face;
diff --git a/components/script/dom/webidls/HTMLFrameElement.webidl b/components/script/dom/webidls/HTMLFrameElement.webidl
index 0de80f7df1e..ecac61f6860 100644
--- a/components/script/dom/webidls/HTMLFrameElement.webidl
+++ b/components/script/dom/webidls/HTMLFrameElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlframeelement
-[Exposed=(Window,Worker)]
interface HTMLFrameElement : HTMLElement {
// attribute DOMString name;
// attribute DOMString scrolling;
diff --git a/components/script/dom/webidls/HTMLFrameSetElement.webidl b/components/script/dom/webidls/HTMLFrameSetElement.webidl
index 34ab7a42289..5addd41d253 100644
--- a/components/script/dom/webidls/HTMLFrameSetElement.webidl
+++ b/components/script/dom/webidls/HTMLFrameSetElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlframesetelement
-[Exposed=(Window,Worker)]
interface HTMLFrameSetElement : HTMLElement {
// attribute DOMString cols;
// attribute DOMString rows;
diff --git a/components/script/dom/webidls/HTMLParagraphElement.webidl b/components/script/dom/webidls/HTMLParagraphElement.webidl
index ff2facc455d..a96c6dc6f81 100644
--- a/components/script/dom/webidls/HTMLParagraphElement.webidl
+++ b/components/script/dom/webidls/HTMLParagraphElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlparagraphelement
-[Exposed=(Window,Worker)]
interface HTMLParagraphElement : HTMLElement {
// also has obsolete members
};
diff --git a/components/script/dom/webidls/HTMLParamElement.webidl b/components/script/dom/webidls/HTMLParamElement.webidl
index 1b0805480a6..9648c9f87ce 100644
--- a/components/script/dom/webidls/HTMLParamElement.webidl
+++ b/components/script/dom/webidls/HTMLParamElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlparamelement
-[Exposed=(Window,Worker)]
interface HTMLParamElement : HTMLElement {
// attribute DOMString name;
// attribute DOMString value;
diff --git a/components/script/dom/webidls/HTMLPreElement.webidl b/components/script/dom/webidls/HTMLPreElement.webidl
index 7d65e225d4f..ea0df151020 100644
--- a/components/script/dom/webidls/HTMLPreElement.webidl
+++ b/components/script/dom/webidls/HTMLPreElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlpreelement
-[Exposed=(Window,Worker)]
interface HTMLPreElement : HTMLElement {
// also has obsolete members
};
diff --git a/components/script/dom/webidls/HTMLProgressElement.webidl b/components/script/dom/webidls/HTMLProgressElement.webidl
index 852e683b1f7..cf69566ecdd 100644
--- a/components/script/dom/webidls/HTMLProgressElement.webidl
+++ b/components/script/dom/webidls/HTMLProgressElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlprogresselement
-[Exposed=(Window,Worker)]
interface HTMLProgressElement : HTMLElement {
// attribute double value;
// attribute double max;
diff --git a/components/script/dom/webidls/HTMLQuoteElement.webidl b/components/script/dom/webidls/HTMLQuoteElement.webidl
index 6741d7b4041..e546f151d49 100644
--- a/components/script/dom/webidls/HTMLQuoteElement.webidl
+++ b/components/script/dom/webidls/HTMLQuoteElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlquoteelement
-[Exposed=(Window,Worker)]
interface HTMLQuoteElement : HTMLElement {
// attribute DOMString cite;
};
diff --git a/components/script/dom/webidls/HTMLSelectElement.webidl b/components/script/dom/webidls/HTMLSelectElement.webidl
index 2bcbbf098e4..ba84d183a72 100644
--- a/components/script/dom/webidls/HTMLSelectElement.webidl
+++ b/components/script/dom/webidls/HTMLSelectElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlselectelement
-[Exposed=(Window,Worker)]
interface HTMLSelectElement : HTMLElement {
// attribute boolean autofocus;
attribute boolean disabled;
diff --git a/components/script/dom/webidls/HTMLSourceElement.webidl b/components/script/dom/webidls/HTMLSourceElement.webidl
index a631876b42e..738a545713a 100644
--- a/components/script/dom/webidls/HTMLSourceElement.webidl
+++ b/components/script/dom/webidls/HTMLSourceElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlsourceelement
-[Exposed=(Window,Worker)]
interface HTMLSourceElement : HTMLElement {
// attribute DOMString src;
// attribute DOMString type;
diff --git a/components/script/dom/webidls/HTMLSpanElement.webidl b/components/script/dom/webidls/HTMLSpanElement.webidl
index 082ba45cf8b..a74967536a1 100644
--- a/components/script/dom/webidls/HTMLSpanElement.webidl
+++ b/components/script/dom/webidls/HTMLSpanElement.webidl
@@ -3,5 +3,4 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlspanelement
-[Exposed=(Window,Worker)]
interface HTMLSpanElement : HTMLElement {};
diff --git a/components/script/dom/webidls/HTMLStyleElement.webidl b/components/script/dom/webidls/HTMLStyleElement.webidl
index 4bc4430a38c..dd766f41d22 100644
--- a/components/script/dom/webidls/HTMLStyleElement.webidl
+++ b/components/script/dom/webidls/HTMLStyleElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlstyleelement
-[Exposed=(Window,Worker)]
interface HTMLStyleElement : HTMLElement {
// attribute DOMString media;
// attribute DOMString type;
diff --git a/components/script/dom/webidls/HTMLTableCaptionElement.webidl b/components/script/dom/webidls/HTMLTableCaptionElement.webidl
index 0860aa7e796..b405d23ed40 100644
--- a/components/script/dom/webidls/HTMLTableCaptionElement.webidl
+++ b/components/script/dom/webidls/HTMLTableCaptionElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmltablecaptionelement
-[Exposed=(Window,Worker)]
interface HTMLTableCaptionElement : HTMLElement {
// also has obsolete members
};
diff --git a/components/script/dom/webidls/HTMLTableCellElement.webidl b/components/script/dom/webidls/HTMLTableCellElement.webidl
index 2264d56b5e2..33863b3dc20 100644
--- a/components/script/dom/webidls/HTMLTableCellElement.webidl
+++ b/components/script/dom/webidls/HTMLTableCellElement.webidl
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmltablecellelement
-[Abstract, Exposed=(Window,Worker)]
+[Abstract]
interface HTMLTableCellElement : HTMLElement {
attribute unsigned long colSpan;
// attribute unsigned long rowSpan;
diff --git a/components/script/dom/webidls/HTMLTableColElement.webidl b/components/script/dom/webidls/HTMLTableColElement.webidl
index 3868de31272..69188251443 100644
--- a/components/script/dom/webidls/HTMLTableColElement.webidl
+++ b/components/script/dom/webidls/HTMLTableColElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmltablecolelement
-[Exposed=(Window,Worker)]
interface HTMLTableColElement : HTMLElement {
// attribute unsigned long span;
diff --git a/components/script/dom/webidls/HTMLTableDataCellElement.webidl b/components/script/dom/webidls/HTMLTableDataCellElement.webidl
index 7c286df77e4..208ed76d692 100644
--- a/components/script/dom/webidls/HTMLTableDataCellElement.webidl
+++ b/components/script/dom/webidls/HTMLTableDataCellElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmltabledatacellelement
-[Exposed=(Window,Worker)]
interface HTMLTableDataCellElement : HTMLTableCellElement {
// also has obsolete members
};
diff --git a/components/script/dom/webidls/HTMLTableElement.webidl b/components/script/dom/webidls/HTMLTableElement.webidl
index c97d24fd57b..f0d8e19d0eb 100644
--- a/components/script/dom/webidls/HTMLTableElement.webidl
+++ b/components/script/dom/webidls/HTMLTableElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmltableelement
-[Exposed=(Window,Worker)]
interface HTMLTableElement : HTMLElement {
attribute HTMLTableCaptionElement? caption;
HTMLTableCaptionElement createCaption();
@@ -20,7 +19,7 @@ interface HTMLTableElement : HTMLElement {
HTMLTableSectionElement createTBody();
readonly attribute HTMLCollection rows;
[Throws] HTMLTableRowElement insertRow(optional long index = -1);
- //void deleteRow(long index);
+ [Throws] void deleteRow(long index);
// also has obsolete members
};
diff --git a/components/script/dom/webidls/HTMLTableHeaderCellElement.webidl b/components/script/dom/webidls/HTMLTableHeaderCellElement.webidl
index fb3e7126672..9bf8f1fc950 100644
--- a/components/script/dom/webidls/HTMLTableHeaderCellElement.webidl
+++ b/components/script/dom/webidls/HTMLTableHeaderCellElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmltableheadercellelement
-[Exposed=(Window,Worker)]
interface HTMLTableHeaderCellElement : HTMLTableCellElement {
// attribute DOMString scope;
// attribute DOMString abbr;
diff --git a/components/script/dom/webidls/HTMLTableRowElement.webidl b/components/script/dom/webidls/HTMLTableRowElement.webidl
index 75898c577e1..9d4b0655cad 100644
--- a/components/script/dom/webidls/HTMLTableRowElement.webidl
+++ b/components/script/dom/webidls/HTMLTableRowElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmltablerowelement
-[Exposed=(Window,Worker)]
interface HTMLTableRowElement : HTMLElement {
readonly attribute long rowIndex;
readonly attribute long sectionRowIndex;
diff --git a/components/script/dom/webidls/HTMLTableSectionElement.webidl b/components/script/dom/webidls/HTMLTableSectionElement.webidl
index dd9d1c654f1..979d8030ffd 100644
--- a/components/script/dom/webidls/HTMLTableSectionElement.webidl
+++ b/components/script/dom/webidls/HTMLTableSectionElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmltablesectionelement
-[Exposed=(Window,Worker)]
interface HTMLTableSectionElement : HTMLElement {
readonly attribute HTMLCollection rows;
[Throws]
diff --git a/components/script/dom/webidls/HTMLTemplateElement.webidl b/components/script/dom/webidls/HTMLTemplateElement.webidl
index 7506f9a28e0..b3383de69d2 100644
--- a/components/script/dom/webidls/HTMLTemplateElement.webidl
+++ b/components/script/dom/webidls/HTMLTemplateElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmltemplateelement
-[Exposed=(Window,Worker)]
interface HTMLTemplateElement : HTMLElement {
readonly attribute DocumentFragment content;
};
diff --git a/components/script/dom/webidls/HTMLTextAreaElement.webidl b/components/script/dom/webidls/HTMLTextAreaElement.webidl
index 32a2ba43ccf..f92e662c354 100644
--- a/components/script/dom/webidls/HTMLTextAreaElement.webidl
+++ b/components/script/dom/webidls/HTMLTextAreaElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmltextareaelement
-[Exposed=(Window,Worker)]
interface HTMLTextAreaElement : HTMLElement {
// attribute DOMString autocomplete;
// attribute boolean autofocus;
diff --git a/components/script/dom/webidls/HTMLTimeElement.webidl b/components/script/dom/webidls/HTMLTimeElement.webidl
index dbd80686b0c..21f9dcf090e 100644
--- a/components/script/dom/webidls/HTMLTimeElement.webidl
+++ b/components/script/dom/webidls/HTMLTimeElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmltimeelement
-[Exposed=(Window,Worker)]
interface HTMLTimeElement : HTMLElement {
// attribute DOMString dateTime;
};
diff --git a/components/script/dom/webidls/HTMLTitleElement.webidl b/components/script/dom/webidls/HTMLTitleElement.webidl
index 9332cae40a7..10373be7e4b 100644
--- a/components/script/dom/webidls/HTMLTitleElement.webidl
+++ b/components/script/dom/webidls/HTMLTitleElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmltitleelement
-[Exposed=(Window,Worker)]
interface HTMLTitleElement : HTMLElement {
[Pure]
attribute DOMString text;
diff --git a/components/script/dom/webidls/HTMLTrackElement.webidl b/components/script/dom/webidls/HTMLTrackElement.webidl
index 9828139bee2..55733235321 100644
--- a/components/script/dom/webidls/HTMLTrackElement.webidl
+++ b/components/script/dom/webidls/HTMLTrackElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmltrackelement
-[Exposed=(Window,Worker)]
interface HTMLTrackElement : HTMLElement {
// attribute DOMString kind;
// attribute DOMString src;
diff --git a/components/script/dom/webidls/HTMLUListElement.webidl b/components/script/dom/webidls/HTMLUListElement.webidl
index 6abaf544b7f..91a79c7f925 100644
--- a/components/script/dom/webidls/HTMLUListElement.webidl
+++ b/components/script/dom/webidls/HTMLUListElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlulistelement
-[Exposed=(Window,Worker)]
interface HTMLUListElement : HTMLElement {
// also has obsolete members
};
diff --git a/components/script/dom/webidls/HTMLUnknownElement.webidl b/components/script/dom/webidls/HTMLUnknownElement.webidl
index 624d7d8541d..acf5a47a996 100644
--- a/components/script/dom/webidls/HTMLUnknownElement.webidl
+++ b/components/script/dom/webidls/HTMLUnknownElement.webidl
@@ -11,6 +11,5 @@
* and create derivative works of this document.
*/
-[Exposed=(Window,Worker)]
interface HTMLUnknownElement : HTMLElement {
};
diff --git a/components/script/dom/webidls/HTMLVideoElement.webidl b/components/script/dom/webidls/HTMLVideoElement.webidl
index 3af425cc06b..5e7c9cb9fce 100644
--- a/components/script/dom/webidls/HTMLVideoElement.webidl
+++ b/components/script/dom/webidls/HTMLVideoElement.webidl
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#htmlvideoelement
-[Exposed=(Window,Worker)]
interface HTMLVideoElement : HTMLMediaElement {
// attribute unsigned long width;
// attribute unsigned long height;
diff --git a/components/script/dom/webidls/Headers.webidl b/components/script/dom/webidls/Headers.webidl
new file mode 100644
index 00000000000..038dbe46f74
--- /dev/null
+++ b/components/script/dom/webidls/Headers.webidl
@@ -0,0 +1,22 @@
+/* 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/. */
+
+// https://fetch.spec.whatwg.org/#headers-class
+
+/* typedef (Headers or sequence<sequence<ByteString>>) HeadersInit; */
+
+/* [Constructor(optional HeadersInit init),*/
+ [Exposed=(Window,Worker)]
+
+interface Headers {
+ [Throws]
+ void append(ByteString name, ByteString value);
+};
+
+/* void delete(ByteString name);
+ * ByteString? get(ByteString name);
+ * boolean has(ByteString name);
+ * void set(ByteString name, ByteString value);
+ * iterable<ByteString, ByteString>;
+ * }; */
diff --git a/components/script/dom/webidls/History.webidl b/components/script/dom/webidls/History.webidl
new file mode 100644
index 00000000000..04742d52601
--- /dev/null
+++ b/components/script/dom/webidls/History.webidl
@@ -0,0 +1,18 @@
+/* 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/. */
+
+// enum ScrollRestoration { "auto", "manual" };
+
+// https://html.spec.whatwg.org/multipage/#the-history-interface
+[Exposed=(Window,Worker)]
+interface History {
+ // readonly attribute unsigned long length;
+ // attribute ScrollRestoration scrollRestoration;
+ // readonly attribute any state;
+ void go(optional long delta = 0);
+ void back();
+ void forward();
+ // void pushState(any data, DOMString title, optional USVString? url = null);
+ // void replaceState(any data, DOMString title, optional USVString? url = null);
+};
diff --git a/components/script/dom/webidls/ServiceWorkerGlobalScope.webidl b/components/script/dom/webidls/ServiceWorkerGlobalScope.webidl
index cbe028c129b..35e4b98f9d5 100644
--- a/components/script/dom/webidls/ServiceWorkerGlobalScope.webidl
+++ b/components/script/dom/webidls/ServiceWorkerGlobalScope.webidl
@@ -4,7 +4,8 @@
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope
-[Global=(Worker,ServiceWorker), Pref="dom.serviceworker.enabled"]
+[Global=(Worker,ServiceWorker), Exposed=ServiceWorker,
+ Pref="dom.serviceworker.enabled"]
interface ServiceWorkerGlobalScope : WorkerGlobalScope {
// A container for a list of Client objects that correspond to
// browsing contexts (or shared workers) that are on the origin of this SW
diff --git a/components/script/dom/webidls/TestBinding.webidl b/components/script/dom/webidls/TestBinding.webidl
index 355141a4d92..9fc8a9e3bb6 100644
--- a/components/script/dom/webidls/TestBinding.webidl
+++ b/components/script/dom/webidls/TestBinding.webidl
@@ -110,6 +110,7 @@ interface TestBinding {
attribute (unsigned long or boolean) union6Attribute;
attribute (Blob or boolean) union7Attribute;
attribute (Blob or unsigned long) union8Attribute;
+ attribute (ByteString or long) union9Attribute;
readonly attribute Uint8ClampedArray arrayAttribute;
attribute any anyAttribute;
attribute object objectAttribute;
@@ -139,6 +140,7 @@ interface TestBinding {
attribute (Blob or boolean)? union3AttributeNullable;
attribute (unsigned long or boolean)? union4AttributeNullable;
attribute (DOMString or boolean)? union5AttributeNullable;
+ attribute (ByteString or long)? union6AttributeNullable;
[BinaryName="BinaryRenamedAttribute"] attribute DOMString attrToBinaryRename;
[BinaryName="BinaryRenamedAttribute2"] attribute DOMString attr-to-binary-rename;
attribute DOMString attr-to-automatically-rename;
@@ -177,6 +179,8 @@ interface TestBinding {
(DOMString or boolean) receiveUnion7();
(unsigned long or boolean) receiveUnion8();
(HTMLElement or unsigned long or DOMString or boolean) receiveUnion9();
+ (ByteString or long) receiveUnion10();
+ (sequence<ByteString> or long or DOMString) receiveUnion11();
sequence<long> receiveSequence();
sequence<Blob> receiveInterfaceSequence();
@@ -204,6 +208,7 @@ interface TestBinding {
(DOMString or sequence<long>)? receiveNullableUnion3();
(sequence<long> or boolean)? receiveNullableUnion4();
(unsigned long or boolean)? receiveNullableUnion5();
+ (ByteString or long)? receiveNullableUnion6();
sequence<long>? receiveNullableSequence();
TestDictionary receiveTestDictionaryWithSuccessOnKeyword();
boolean dictMatchesPassedValues(TestDictionary arg);
@@ -233,6 +238,7 @@ interface TestBinding {
void passUnion5((DOMString or boolean) data);
void passUnion6((unsigned long or boolean) bool);
void passUnion7((sequence<DOMString> or unsigned long) arg);
+ void passUnion8((sequence<ByteString> or long) arg);
void passAny(any arg);
void passObject(object arg);
void passCallbackFunction(Function fun);
@@ -265,6 +271,7 @@ interface TestBinding {
void passNullableUnion3((DOMString or sequence<long>)? data);
void passNullableUnion4((sequence<long> or boolean)? bool);
void passNullableUnion5((unsigned long or boolean)? arg);
+ void passNullableUnion6((ByteString or long)? arg);
void passNullableCallbackFunction(Function? fun);
void passNullableCallbackInterface(EventListener? listener);
void passNullableSequence(sequence<long>? seq);
@@ -292,6 +299,7 @@ interface TestBinding {
void passOptionalUnion3(optional (DOMString or sequence<long>) arg);
void passOptionalUnion4(optional (sequence<long> or boolean) data);
void passOptionalUnion5(optional (unsigned long or boolean) bool);
+ void passOptionalUnion6(optional (ByteString or long) arg);
void passOptionalAny(optional any arg);
void passOptionalObject(optional object arg);
void passOptionalCallbackFunction(optional Function fun);
@@ -322,6 +330,7 @@ interface TestBinding {
void passOptionalNullableUnion3(optional (DOMString or sequence<long>)? arg);
void passOptionalNullableUnion4(optional (sequence<long> or boolean)? data);
void passOptionalNullableUnion5(optional (unsigned long or boolean)? bool);
+ void passOptionalNullableUnion6(optional (ByteString or long)? arg);
void passOptionalNullableCallbackFunction(optional Function? fun);
void passOptionalNullableCallbackInterface(optional EventListener? listener);
void passOptionalNullableSequence(optional sequence<long>? seq);
@@ -406,9 +415,14 @@ interface TestBinding {
void passVariadicUnion4((Blob or boolean)... args);
void passVariadicUnion5((DOMString or unsigned long)... args);
void passVariadicUnion6((unsigned long or boolean)... args);
+ void passVariadicUnion7((ByteString or long)... args);
void passVariadicAny(any... args);
void passVariadicObject(object... args);
+ void passSequenceSequence(sequence<sequence<long>> seq);
+ sequence<sequence<long>> returnSequenceSequence();
+ void passUnionSequenceSequence((long or sequence<sequence<long>>) seq);
+
static attribute boolean booleanAttributeStatic;
static void receiveVoidStatic();
boolean BooleanMozPreference(DOMString pref_name);
@@ -424,6 +438,8 @@ interface TestBinding {
static void prefControlledStaticMethodDisabled();
[Pref="dom.testbinding.prefcontrolled.enabled"]
const unsigned short prefControlledConstDisabled = 0;
+ [Pref="layout.animations.test.enabled"]
+ void advanceClock(long millis);
[Pref="dom.testbinding.prefcontrolled2.enabled"]
readonly attribute boolean prefControlledAttributeEnabled;
diff --git a/components/script/dom/webidls/Window.webidl b/components/script/dom/webidls/Window.webidl
index bda73c9479a..651c7081305 100644
--- a/components/script/dom/webidls/Window.webidl
+++ b/components/script/dom/webidls/Window.webidl
@@ -11,7 +11,7 @@
[Unforgeable] readonly attribute Document document;
// attribute DOMString name;
[/*PutForwards=href, */Unforgeable] readonly attribute Location location;
- //readonly attribute History history;
+ readonly attribute History history;
//[Replaceable] readonly attribute BarProp locationbar;
//[Replaceable] readonly attribute BarProp menubar;
//[Replaceable] readonly attribute BarProp personalbar;
diff --git a/components/script/dom/webidls/WorkerGlobalScope.webidl b/components/script/dom/webidls/WorkerGlobalScope.webidl
index 0a269068b57..ec65bcb09a6 100644
--- a/components/script/dom/webidls/WorkerGlobalScope.webidl
+++ b/components/script/dom/webidls/WorkerGlobalScope.webidl
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#workerglobalscope
-[Abstract, Exposed=(Window,Worker)]
+[Abstract, Exposed=Worker]
interface WorkerGlobalScope : EventTarget {
[BinaryName="Self_"] readonly attribute WorkerGlobalScope self;
readonly attribute WorkerLocation location;
@@ -16,7 +16,7 @@ interface WorkerGlobalScope : EventTarget {
};
// https://html.spec.whatwg.org/multipage/#WorkerGlobalScope-partial
-[Exposed=(Window,Worker)]
+[Exposed=Worker]
partial interface WorkerGlobalScope { // not obsolete
[Throws]
void importScripts(DOMString... urls);
@@ -26,7 +26,7 @@ WorkerGlobalScope implements WindowTimers;
WorkerGlobalScope implements WindowBase64;
// Proprietary
-[Exposed=(Window,Worker)]
+[Exposed=Worker]
partial interface WorkerGlobalScope {
[Replaceable]
readonly attribute Console console;
diff --git a/components/script/dom/webidls/WorkerLocation.webidl b/components/script/dom/webidls/WorkerLocation.webidl
index 797956aca26..e4c410f720a 100644
--- a/components/script/dom/webidls/WorkerLocation.webidl
+++ b/components/script/dom/webidls/WorkerLocation.webidl
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#worker-locations
-[Exposed=(Window,Worker)]
+[Exposed=Worker]
interface WorkerLocation {
/*stringifier*/ readonly attribute USVString href;
// readonly attribute USVString origin;
diff --git a/components/script/dom/webidls/WorkerNavigator.webidl b/components/script/dom/webidls/WorkerNavigator.webidl
index 04006714a0c..0661325b8be 100644
--- a/components/script/dom/webidls/WorkerNavigator.webidl
+++ b/components/script/dom/webidls/WorkerNavigator.webidl
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#workernavigator
-[Exposed=(Window,Worker)]
+[Exposed=Worker]
interface WorkerNavigator {};
WorkerNavigator implements NavigatorID;
WorkerNavigator implements NavigatorLanguage;
diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs
index 1a34096f26b..3b3652040e9 100644
--- a/components/script/dom/websocket.rs
+++ b/components/script/dom/websocket.rs
@@ -461,6 +461,8 @@ struct ConnectionEstablishedTask {
}
impl Runnable for ConnectionEstablishedTask {
+ fn name(&self) -> &'static str { "ConnectionEstablishedTask" }
+
fn handler(self: Box<Self>) {
let ws = self.address.root();
let global = ws.r().global();
@@ -510,6 +512,8 @@ impl Runnable for BufferedAmountTask {
// To be compliant with standards, we need to reset bufferedAmount only when the event loop
// reaches step 1. In our implementation, the bytes will already have been sent on a background
// thread.
+ fn name(&self) -> &'static str { "BufferedAmountTask" }
+
fn handler(self: Box<Self>) {
let ws = self.address.root();
@@ -526,6 +530,8 @@ struct CloseTask {
}
impl Runnable for CloseTask {
+ fn name(&self) -> &'static str { "CloseTask" }
+
fn handler(self: Box<Self>) {
let ws = self.address.root();
let ws = ws.r();
@@ -568,6 +574,8 @@ struct MessageReceivedTask {
}
impl Runnable for MessageReceivedTask {
+ fn name(&self) -> &'static str { "MessageReceivedTask" }
+
#[allow(unsafe_code)]
fn handler(self: Box<Self>) {
let ws = self.address.root();
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 9401eae5a46..ebd9550d117 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -28,7 +28,10 @@ use dom::crypto::Crypto;
use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration};
use dom::document::Document;
use dom::element::Element;
+use dom::event::Event;
use dom::eventtarget::EventTarget;
+use dom::history::History;
+use dom::htmliframeelement::build_mozbrowser_custom_event;
use dom::location::Location;
use dom::navigator::Navigator;
use dom::node::{Node, from_untrusted_node_address, window_from_node};
@@ -43,11 +46,11 @@ use js::jsapi::{JS_GetRuntime, JS_GC, MutableHandleValue, SetWindowProxy};
use js::rust::CompileOptionsWrapper;
use js::rust::Runtime;
use libc;
-use msg::constellation_msg::{FrameType, LoadData, PanicMsg, PipelineId, SubpageId, WindowSizeType};
+use msg::constellation_msg::{FrameType, LoadData, PipelineId, SubpageId, WindowSizeType};
+use net_traits::ResourceThreads;
use net_traits::bluetooth_thread::BluetoothMethodMsg;
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
use net_traits::storage_thread::StorageType;
-use net_traits::{ResourceThreads, CustomResponseSender};
use num_traits::ToPrimitive;
use open;
use profile_traits::mem;
@@ -63,7 +66,7 @@ use script_runtime::{ScriptChan, ScriptPort, maybe_take_panic_result};
use script_thread::SendableMainThreadScriptChan;
use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, RunnableWrapper};
use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
-use script_traits::{ConstellationControlMsg, UntrustedNodeAddress};
+use script_traits::{ConstellationControlMsg, MozBrowserEvent, UntrustedNodeAddress};
use script_traits::{DocumentState, MsDuration, TimerEvent, TimerEventId};
use script_traits::{ScriptMsg as ConstellationMsg, TimerEventRequest, TimerSource, WindowSizeData};
use std::ascii::AsciiExt;
@@ -92,7 +95,7 @@ use task_source::networking::NetworkingTaskSource;
use task_source::user_interaction::UserInteractionTaskSource;
use time;
use timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle, OneshotTimers, TimerCallback};
-#[cfg(any(target_os = "macos", target_os = "linux"))]
+#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
use tinyfiledialogs::{self, MessageBoxIcon};
use url::Url;
use util::geometry::{self, MAX_RECT};
@@ -155,9 +158,8 @@ pub struct Window {
image_cache_thread: ImageCacheThread,
#[ignore_heap_size_of = "channels are hard"]
image_cache_chan: ImageCacheChan,
- #[ignore_heap_size_of = "channels are hard"]
- custom_message_chan: IpcSender<CustomResponseSender>,
browsing_context: MutNullableHeap<JS<BrowsingContext>>,
+ history: MutNullableHeap<JS<History>>,
performance: MutNullableHeap<JS<Performance>>,
navigation_start: u64,
navigation_start_precise: f64,
@@ -266,9 +268,6 @@ pub struct Window {
/// A list of scroll offsets for each scrollable element.
scroll_offsets: DOMRefCell<HashMap<UntrustedNodeAddress, Point2D<f32>>>,
-
- #[ignore_heap_size_of = "Defined in ipc-channel"]
- panic_chan: IpcSender<PanicMsg>,
}
impl Window {
@@ -302,7 +301,7 @@ impl Window {
self.history_traversal_task_source.clone()
}
- pub fn file_reading_task_source(&self) -> Box<ScriptChan + Send> {
+ pub fn file_reading_task_source(&self) -> FileReadingTaskSource {
self.file_reading_task_source.clone()
}
@@ -314,10 +313,6 @@ impl Window {
self.image_cache_chan.clone()
}
- pub fn custom_message_chan(&self) -> IpcSender<CustomResponseSender> {
- self.custom_message_chan.clone()
- }
-
pub fn get_next_worker_id(&self) -> WorkerId {
let worker_id = self.next_worker_id.get();
let WorkerId(id_num) = worker_id;
@@ -366,14 +361,14 @@ impl Window {
}
}
-#[cfg(any(target_os = "macos", target_os = "linux"))]
+#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
fn display_alert_dialog(message: &str) {
tinyfiledialogs::message_box_ok("Alert!", message, MessageBoxIcon::Warning);
}
-#[cfg(not(any(target_os = "macos", target_os = "linux")))]
+#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
fn display_alert_dialog(_message: &str) {
- // tinyfiledialogs not supported on Windows
+ // tinyfiledialogs not supported on Android
}
// https://html.spec.whatwg.org/multipage/#atob
@@ -455,13 +450,15 @@ impl WindowMethods for Window {
// Right now, just print to the console
// Ensure that stderr doesn't trample through the alert() we use to
// communicate test results (see executorservo.py in wptrunner).
- let stderr = stderr();
- let mut stderr = stderr.lock();
- let stdout = stdout();
- let mut stdout = stdout.lock();
- writeln!(&mut stdout, "ALERT: {}", s).unwrap();
- stdout.flush().unwrap();
- stderr.flush().unwrap();
+ {
+ let stderr = stderr();
+ let mut stderr = stderr.lock();
+ let stdout = stdout();
+ let mut stdout = stdout.lock();
+ writeln!(&mut stdout, "ALERT: {}", s).unwrap();
+ stdout.flush().unwrap();
+ stderr.flush().unwrap();
+ }
let (sender, receiver) = ipc::channel().unwrap();
self.constellation_chan().send(ConstellationMsg::Alert(self.pipeline(), s.to_string(), sender)).unwrap();
@@ -482,6 +479,11 @@ impl WindowMethods for Window {
self.browsing_context().active_document()
}
+ // https://html.spec.whatwg.org/multipage/#dom-history
+ fn History(&self) -> Root<History> {
+ self.history.or_init(|| History::new(self))
+ }
+
// https://html.spec.whatwg.org/multipage/#dom-location
fn Location(&self) -> Root<Location> {
self.Document().GetLocation().unwrap()
@@ -1034,6 +1036,12 @@ impl Window {
recv.recv().unwrap_or((Size2D::zero(), Point2D::zero()))
}
+ /// Advances the layout animation clock by `delta` milliseconds, and then
+ /// forces a reflow.
+ pub fn advance_animation_clock(&self, delta: i32) {
+ self.layout_chan.send(Msg::AdvanceClockMs(delta)).unwrap();
+ }
+
/// Reflows the page unconditionally if possible and not suppressed. This
/// method will wait for the layout thread to complete (but see the `TODO`
/// below). If there is no window size yet, the page is presumed invisible
@@ -1422,10 +1430,6 @@ impl Window {
&self.scheduler_chan
}
- pub fn panic_chan(&self) -> &IpcSender<PanicMsg> {
- &self.panic_chan
- }
-
pub fn schedule_callback(&self, callback: OneshotTimerCallback, duration: MsDuration) -> OneshotTimerHandle {
self.timers.schedule_callback(callback,
duration,
@@ -1594,6 +1598,13 @@ impl Window {
_ => false,
}
}
+
+ #[allow(unsafe_code)]
+ pub fn dispatch_mozbrowser_event(&self, event: MozBrowserEvent) {
+ assert!(PREFS.is_mozbrowser_enabled());
+ let custom_event = build_mozbrowser_custom_event(&self, event);
+ custom_event.upcast::<Event>().fire(self.upcast());
+ }
}
impl Window {
@@ -1605,7 +1616,6 @@ impl Window {
history_task_source: HistoryTraversalTaskSource,
file_task_source: FileReadingTaskSource,
image_cache_chan: ImageCacheChan,
- custom_message_chan: IpcSender<CustomResponseSender>,
image_cache_thread: ImageCacheThread,
resource_threads: ResourceThreads,
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
@@ -1615,7 +1625,6 @@ impl Window {
constellation_chan: IpcSender<ConstellationMsg>,
control_chan: IpcSender<ConstellationControlMsg>,
scheduler_chan: IpcSender<TimerEventRequest>,
- panic_chan: IpcSender<PanicMsg>,
timer_event_chan: IpcSender<TimerEvent>,
layout_chan: Sender<Msg>,
id: PipelineId,
@@ -1641,7 +1650,6 @@ impl Window {
history_traversal_task_source: history_task_source,
file_reading_task_source: file_task_source,
image_cache_chan: image_cache_chan,
- custom_message_chan: custom_message_chan,
console: Default::default(),
crypto: Default::default(),
navigator: Default::default(),
@@ -1649,6 +1657,7 @@ impl Window {
mem_profiler_chan: mem_profiler_chan,
time_profiler_chan: time_profiler_chan,
devtools_chan: devtools_chan,
+ history: Default::default(),
browsing_context: Default::default(),
performance: Default::default(),
navigation_start: (current_time.sec * 1000 + current_time.nsec as i64 / 1000000) as u64,
@@ -1686,7 +1695,6 @@ impl Window {
ignore_further_async_events: Arc::new(AtomicBool::new(false)),
error_reporter: error_reporter,
scroll_offsets: DOMRefCell::new(HashMap::new()),
- panic_chan: panic_chan,
};
WindowBinding::Wrap(runtime.cx(), win)
diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs
index 2cf1d1c4e46..c1ad7cf5a96 100644
--- a/components/script/dom/worker.rs
+++ b/components/script/dom/worker.rs
@@ -2,9 +2,9 @@
* 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 devtools_traits::{ScriptToDevtoolsControlMsg, DevtoolsPageInfo};
+use dom::abstractworker::WorkerScriptMsg;
use dom::abstractworker::{SimpleWorkerErrorHandler, SharedRt, WorkerErrorHandler};
-use dom::abstractworker::{WorkerScriptLoadOrigin, WorkerScriptMsg};
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::WorkerBinding;
use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods;
@@ -26,6 +26,8 @@ use ipc_channel::ipc;
use js::jsapi::{HandleValue, JSContext, JSAutoCompartment};
use js::jsval::UndefinedValue;
use script_thread::Runnable;
+use script_traits::WorkerScriptLoadOrigin;
+use std::cell::Cell;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{Sender, channel};
use std::sync::{Arc, Mutex};
@@ -42,7 +44,8 @@ pub struct Worker {
sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
closing: Arc<AtomicBool>,
#[ignore_heap_size_of = "Defined in rust-mozjs"]
- runtime: Arc<Mutex<Option<SharedRt>>>
+ runtime: Arc<Mutex<Option<SharedRt>>>,
+ terminated: Cell<bool>,
}
impl Worker {
@@ -52,7 +55,8 @@ impl Worker {
eventtarget: EventTarget::new_inherited(),
sender: sender,
closing: closing,
- runtime: Arc::new(Mutex::new(None))
+ runtime: Arc::new(Mutex::new(None)),
+ terminated: Cell::new(false),
}
}
@@ -81,21 +85,28 @@ impl Worker {
let worker_load_origin = WorkerScriptLoadOrigin {
referrer_url: None,
referrer_policy: None,
- request_source: global.request_source(),
pipeline_id: Some(global.pipeline())
};
let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
+ let worker_id = global.get_next_worker_id();
+ if let Some(ref chan) = global.devtools_chan() {
+ let pipeline_id = global.pipeline();
+ let title = format!("Worker for {}", worker_url);
+ let page_info = DevtoolsPageInfo {
+ title: title,
+ url: worker_url.clone(),
+ };
+ let _ = chan.send(ScriptToDevtoolsControlMsg::NewGlobal((pipeline_id, Some(worker_id)),
+ devtools_sender.clone(),
+ page_info));
+ }
- let init = prepare_workerscope_init(global,
- "Worker".to_owned(),
- worker_url.clone(),
- devtools_sender.clone(),
- closing);
+ let init = prepare_workerscope_init(global, Some(devtools_sender));
DedicatedWorkerGlobalScope::run_worker_scope(
init, worker_url, global.pipeline(), devtools_receiver, worker.runtime.clone(), worker_ref,
- global.script_chan(), sender, receiver, worker_load_origin);
+ global.script_chan(), sender, receiver, worker_load_origin, closing);
Ok(worker)
}
@@ -104,11 +115,15 @@ impl Worker {
self.closing.load(Ordering::SeqCst)
}
+ pub fn is_terminated(&self) -> bool {
+ self.terminated.get()
+ }
+
pub fn handle_message(address: TrustedWorkerAddress,
data: StructuredCloneData) {
let worker = address.root();
- if worker.is_closing() {
+ if worker.is_terminated() {
return;
}
@@ -129,7 +144,7 @@ impl Worker {
filename: DOMString, lineno: u32, colno: u32) {
let worker = address.root();
- if worker.is_closing() {
+ if worker.is_terminated() {
return;
}
@@ -161,7 +176,10 @@ impl WorkerMethods for Worker {
return;
}
- // Step 4
+ // Step 2
+ self.terminated.set(true);
+
+ // Step 3
if let Some(runtime) = *self.runtime.lock().unwrap() {
runtime.request_interrupt();
}
diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs
index 2e1c983bfd4..16388d54d73 100644
--- a/components/script/dom/workerglobalscope.rs
+++ b/components/script/dom/workerglobalscope.rs
@@ -2,7 +2,7 @@
* 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 devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId, DevtoolsPageInfo};
+use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
use dom::bindings::error::{Error, ErrorResult, Fallible, report_pending_exception};
@@ -19,17 +19,18 @@ use dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
use dom::window::{base64_atob, base64_btoa};
use dom::workerlocation::WorkerLocation;
use dom::workernavigator::WorkerNavigator;
-use ipc_channel::ipc::{self, IpcSender};
-use ipc_channel::router::ROUTER;
+use ipc_channel::ipc::IpcSender;
use js::jsapi::{HandleValue, JSContext, JSRuntime};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
-use msg::constellation_msg::{PipelineId, ReferrerPolicy, PanicMsg};
+use msg::constellation_msg::{PipelineId, ReferrerPolicy};
use net_traits::{LoadContext, ResourceThreads, load_whole_resource};
-use net_traits::{RequestSource, LoadOrigin, CustomResponseSender, IpcSend};
+use net_traits::{LoadOrigin, IpcSend};
use profile_traits::{mem, time};
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, maybe_take_panic_result};
+use script_thread::RunnableWrapper;
use script_traits::ScriptMsg as ConstellationMsg;
+use script_traits::WorkerGlobalScopeInit;
use script_traits::{MsDuration, TimerEvent, TimerEventId, TimerEventRequest, TimerSource};
use std::cell::Cell;
use std::default::Default;
@@ -38,6 +39,7 @@ use std::rc::Rc;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::Receiver;
+use task_source::file_reading::FileReadingTaskSource;
use timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle, OneshotTimers, TimerCallback};
use url::Url;
@@ -46,52 +48,18 @@ pub enum WorkerGlobalScopeTypeId {
DedicatedWorkerGlobalScope,
}
-pub struct WorkerGlobalScopeInit {
- pub resource_threads: ResourceThreads,
- pub mem_profiler_chan: mem::ProfilerChan,
- pub time_profiler_chan: time::ProfilerChan,
- pub to_devtools_sender: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
- pub from_devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
- pub constellation_chan: IpcSender<ConstellationMsg>,
- pub scheduler_chan: IpcSender<TimerEventRequest>,
- pub panic_chan: IpcSender<PanicMsg>,
- pub worker_id: WorkerId,
- pub closing: Arc<AtomicBool>,
-}
-
pub fn prepare_workerscope_init(global: GlobalRef,
- worker_type: String,
- worker_url: Url,
- devtools_sender: IpcSender<DevtoolScriptControlMsg>,
- closing: Arc<AtomicBool>) -> WorkerGlobalScopeInit {
+ devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>) -> WorkerGlobalScopeInit {
let worker_id = global.get_next_worker_id();
- let optional_sender = match global.devtools_chan() {
- Some(ref chan) => {
- let pipeline_id = global.pipeline();
- let title = format!("{} for {}", worker_type, worker_url);
- let page_info = DevtoolsPageInfo {
- title: title,
- url: worker_url,
- };
- chan.send(ScriptToDevtoolsControlMsg::NewGlobal((pipeline_id, Some(worker_id)),
- devtools_sender.clone(),
- page_info)).unwrap();
- Some(devtools_sender)
- },
- None => None,
- };
-
let init = WorkerGlobalScopeInit {
resource_threads: global.resource_threads(),
mem_profiler_chan: global.mem_profiler_chan().clone(),
to_devtools_sender: global.devtools_chan(),
time_profiler_chan: global.time_profiler_chan().clone(),
- from_devtools_sender: optional_sender,
+ from_devtools_sender: devtools_sender,
constellation_chan: global.constellation_chan().clone(),
- panic_chan: global.panic_chan().clone(),
scheduler_chan: global.scheduler_chan().clone(),
- worker_id: worker_id,
- closing: closing,
+ worker_id: worker_id
};
init
@@ -103,7 +71,7 @@ pub struct WorkerGlobalScope {
eventtarget: EventTarget,
worker_id: WorkerId,
worker_url: Url,
- closing: Arc<AtomicBool>,
+ closing: Option<Arc<AtomicBool>>,
#[ignore_heap_size_of = "Defined in js"]
runtime: Runtime,
next_worker_id: Cell<WorkerId>,
@@ -141,15 +109,6 @@ pub struct WorkerGlobalScope {
#[ignore_heap_size_of = "Defined in std"]
scheduler_chan: IpcSender<TimerEventRequest>,
-
- #[ignore_heap_size_of = "Defined in ipc-channel"]
- panic_chan: IpcSender<PanicMsg>,
-
- #[ignore_heap_size_of = "Defined in ipc-channel"]
- custom_msg_chan: IpcSender<CustomResponseSender>,
-
- #[ignore_heap_size_of = "Defined in std"]
- custom_msg_port: Receiver<CustomResponseSender>,
}
impl WorkerGlobalScope {
@@ -157,16 +116,15 @@ impl WorkerGlobalScope {
worker_url: Url,
runtime: Runtime,
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
- timer_event_chan: IpcSender<TimerEvent>)
+ timer_event_chan: IpcSender<TimerEvent>,
+ closing: Option<Arc<AtomicBool>>)
-> WorkerGlobalScope {
- let (msg_chan, msg_port) = ipc::channel().unwrap();
- let custom_msg_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(msg_port);
WorkerGlobalScope {
eventtarget: EventTarget::new_inherited(),
next_worker_id: Cell::new(WorkerId(0)),
worker_id: init.worker_id,
worker_url: worker_url,
- closing: init.closing,
+ closing: closing,
runtime: runtime,
resource_threads: init.resource_threads,
location: Default::default(),
@@ -182,9 +140,6 @@ impl WorkerGlobalScope {
devtools_wants_updates: Cell::new(false),
constellation_chan: init.constellation_chan,
scheduler_chan: init.scheduler_chan,
- panic_chan: init.panic_chan,
- custom_msg_chan: msg_chan,
- custom_msg_port: custom_msg_port
}
}
@@ -234,16 +189,12 @@ impl WorkerGlobalScope {
self.runtime.cx()
}
- pub fn custom_message_chan(&self) -> IpcSender<CustomResponseSender> {
- self.custom_msg_chan.clone()
- }
-
- pub fn custom_message_port(&self) -> &Receiver<CustomResponseSender> {
- &self.custom_msg_port
- }
-
pub fn is_closing(&self) -> bool {
- self.closing.load(Ordering::SeqCst)
+ if let Some(ref closing) = self.closing {
+ closing.load(Ordering::SeqCst)
+ } else {
+ false
+ }
}
pub fn resource_threads(&self) -> &ResourceThreads {
@@ -265,8 +216,10 @@ impl WorkerGlobalScope {
worker_id
}
- pub fn panic_chan(&self) -> &IpcSender<PanicMsg> {
- &self.panic_chan
+ pub fn get_runnable_wrapper(&self) -> RunnableWrapper {
+ RunnableWrapper {
+ cancelled: self.closing.clone().unwrap(),
+ }
}
}
@@ -277,9 +230,6 @@ impl LoadOrigin for WorkerGlobalScope {
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
None
}
- fn request_source(&self) -> RequestSource {
- RequestSource::None
- }
fn pipeline_id(&self) -> Option<PipelineId> {
Some(self.pipeline())
}
@@ -443,16 +393,17 @@ impl WorkerGlobalScope {
pub fn script_chan(&self) -> Box<ScriptChan + Send> {
let dedicated =
self.downcast::<DedicatedWorkerGlobalScope>();
- let service_worker = self.downcast::<ServiceWorkerGlobalScope>();
if let Some(dedicated) = dedicated {
return dedicated.script_chan();
- } else if let Some(service_worker) = service_worker {
- return service_worker.script_chan();
} else {
- panic!("need to implement a sender for SharedWorker")
+ panic!("need to implement a sender for SharedWorker/ServiceWorker")
}
}
+ pub fn file_reading_task_source(&self) -> FileReadingTaskSource {
+ FileReadingTaskSource(self.script_chan())
+ }
+
pub fn pipeline(&self) -> PipelineId {
let dedicated = self.downcast::<DedicatedWorkerGlobalScope>();
let service_worker = self.downcast::<ServiceWorkerGlobalScope>();
@@ -467,13 +418,10 @@ impl WorkerGlobalScope {
pub fn new_script_pair(&self) -> (Box<ScriptChan + Send>, Box<ScriptPort + Send>) {
let dedicated = self.downcast::<DedicatedWorkerGlobalScope>();
- let service_worker = self.downcast::<ServiceWorkerGlobalScope>();
if let Some(dedicated) = dedicated {
return dedicated.new_script_pair();
- } else if let Some(service_worker) = service_worker {
- return service_worker.new_script_pair();
} else {
- panic!("need to implement a sender for SharedWorker")
+ panic!("need to implement a sender for SharedWorker/ServiceWorker")
}
}
@@ -496,4 +444,10 @@ impl WorkerGlobalScope {
pub fn set_devtools_wants_updates(&self, value: bool) {
self.devtools_wants_updates.set(value);
}
+
+ pub fn close(&self) {
+ if let Some(ref closing) = self.closing {
+ closing.store(true, Ordering::SeqCst);
+ }
+ }
}
diff --git a/components/script/dom/xmldocument.rs b/components/script/dom/xmldocument.rs
index b291c912089..5f6b6e1919c 100644
--- a/components/script/dom/xmldocument.rs
+++ b/components/script/dom/xmldocument.rs
@@ -41,7 +41,9 @@ impl XMLDocument {
content_type,
last_modified,
source,
- doc_loader),
+ doc_loader,
+ None,
+ None),
}
}
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index 148a51c8c6b..5cef702c01a 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -25,6 +25,7 @@ use dom::document::DocumentSource;
use dom::document::{Document, IsHTMLDocument};
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
+use dom::headers::is_forbidden_header_name;
use dom::progressevent::ProgressEvent;
use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget;
use dom::xmlhttprequestupload::XMLHttpRequestUpload;
@@ -47,7 +48,7 @@ use net_traits::CoreResourceMsg::Fetch;
use net_traits::request::{CredentialsMode, Destination, RequestInit, RequestMode};
use net_traits::trim_http_whitespace;
use net_traits::{CoreResourceThread, LoadOrigin};
-use net_traits::{FetchResponseListener, Metadata, NetworkError, RequestSource};
+use net_traits::{FetchResponseListener, Metadata, NetworkError};
use network_listener::{NetworkListener, PreInvoke};
use parse::html::{ParseContext, parse_html};
use parse::xml::{self, parse_xml};
@@ -274,13 +275,6 @@ impl LoadOrigin for XMLHttpRequest {
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
return self.referrer_policy;
}
- fn request_source(&self) -> RequestSource {
- if self.sync.get() {
- RequestSource::None
- } else {
- self.global().r().request_source()
- }
- }
fn pipeline_id(&self) -> Option<PipelineId> {
let global = self.global();
Some(global.r().pipeline())
@@ -368,6 +362,12 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
// Step 11 - abort existing requests
self.terminate_ongoing_fetch();
+ // TODO(izgzhen): In the WPT test: FileAPI/blob/Blob-XHR-revoke.html,
+ // the xhr.open(url) is expected to hold a reference to the URL,
+ // thus renders following revocations invalid. Though we won't
+ // implement this for now, if ever needed, we should check blob
+ // scheme and trigger corresponding actions here.
+
// Step 12
*self.request_method.borrow_mut() = parsed_method;
*self.request_url.borrow_mut() = Some(parsed_url);
@@ -410,21 +410,8 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
// Step 5
// Disallowed headers and header prefixes:
// https://fetch.spec.whatwg.org/#forbidden-header-name
- let disallowedHeaders =
- ["accept-charset", "accept-encoding",
- "access-control-request-headers",
- "access-control-request-method",
- "connection", "content-length",
- "cookie", "cookie2", "date", "dnt",
- "expect", "host", "keep-alive", "origin",
- "referer", "te", "trailer", "transfer-encoding",
- "upgrade", "via"];
-
- let disallowedHeaderPrefixes = ["sec-", "proxy-"];
-
- if disallowedHeaders.iter().any(|header| *header == s) ||
- disallowedHeaderPrefixes.iter().any(|prefix| s.starts_with(prefix)) {
- return Ok(())
+ if is_forbidden_header_name(s) {
+ return Ok(());
} else {
s
}
@@ -1234,7 +1221,10 @@ impl XMLHttpRequest {
is_html_document,
content_type,
None,
- DocumentSource::FromParser, docloader)
+ DocumentSource::FromParser,
+ docloader,
+ None,
+ None)
}
fn filter_response_headers(&self) -> Headers {