mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Auto merge of #17061 - servo:utf8, r=nox
EventSource: decode UTF-8 code points across network packets <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17061) <!-- Reviewable:end -->
This commit is contained in:
commit
25d0c56141
10 changed files with 48 additions and 27 deletions
|
@ -11,7 +11,6 @@ path = "lib.rs"
|
|||
|
||||
[dependencies]
|
||||
devtools_traits = {path = "../devtools_traits"}
|
||||
encoding = "0.2"
|
||||
hyper = "0.10"
|
||||
hyper_serde = "0.6"
|
||||
ipc-channel = "0.7"
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
use actor::{Actor, ActorMessageStatus, ActorRegistry};
|
||||
use devtools_traits::HttpRequest as DevtoolsHttpRequest;
|
||||
use devtools_traits::HttpResponse as DevtoolsHttpResponse;
|
||||
use encoding::all::UTF_8;
|
||||
use encoding::types::{DecoderTrap, Encoding};
|
||||
use hyper::header::{ContentType, Cookie};
|
||||
use hyper::header::Headers;
|
||||
use hyper::http::RawStatus;
|
||||
|
@ -361,7 +359,7 @@ impl NetworkEventActor {
|
|||
pub fn add_response(&mut self, response: DevtoolsHttpResponse) {
|
||||
self.response.headers = response.headers.clone();
|
||||
self.response.status = response.status.as_ref().map(|&(s, ref st)| {
|
||||
let status_text = UTF_8.decode(st, DecoderTrap::Replace).unwrap();
|
||||
let status_text = String::from_utf8_lossy(st).into_owned();
|
||||
RawStatus(s, Cow::from(status_text))
|
||||
});
|
||||
self.response.body = response.body.clone();
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#![feature(box_syntax)]
|
||||
|
||||
extern crate devtools_traits;
|
||||
extern crate encoding;
|
||||
extern crate hyper;
|
||||
extern crate ipc_channel;
|
||||
#[macro_use]
|
||||
|
|
|
@ -89,6 +89,7 @@ swapper = "0.0.4"
|
|||
time = "0.1.12"
|
||||
unicode-segmentation = "1.1.0"
|
||||
url = {version = "1.2", features = ["heap_size", "query_encoding"]}
|
||||
utf-8 = "0.7"
|
||||
uuid = {version = "0.4", features = ["v4"]}
|
||||
xml5ever = {version = "0.7", features = ["unstable"]}
|
||||
webrender_traits = {git = "https://github.com/servo/webrender", features = ["ipc"]}
|
||||
|
|
|
@ -11,8 +11,6 @@ use dom::blob::{Blob, BlobImpl};
|
|||
use dom::formdata::FormData;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::promise::Promise;
|
||||
use encoding::all::UTF_8;
|
||||
use encoding::types::{DecoderTrap, Encoding};
|
||||
use js::jsapi::JSContext;
|
||||
use js::jsapi::JS_ClearPendingException;
|
||||
use js::jsapi::JS_ParseJSON;
|
||||
|
@ -110,14 +108,13 @@ fn run_package_data_algorithm<T: BodyOperations + DomObject>(object: &T,
|
|||
}
|
||||
|
||||
fn run_text_data_algorithm(bytes: Vec<u8>) -> Fallible<FetchedData> {
|
||||
let text = UTF_8.decode(&bytes, DecoderTrap::Replace).unwrap();
|
||||
Ok(FetchedData::Text(text))
|
||||
Ok(FetchedData::Text(String::from_utf8_lossy(&bytes).into_owned()))
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn run_json_data_algorithm(cx: *mut JSContext,
|
||||
bytes: Vec<u8>) -> Fallible<FetchedData> {
|
||||
let json_text = UTF_8.decode(&bytes, DecoderTrap::Replace).unwrap();
|
||||
let json_text = String::from_utf8_lossy(&bytes);
|
||||
let json_text: Vec<u16> = json_text.encode_utf16().collect();
|
||||
rooted!(in(cx) let mut rval = UndefinedValue());
|
||||
unsafe {
|
||||
|
|
|
@ -12,8 +12,6 @@ use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
|||
use dom::bindings::str::DOMString;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom_struct::dom_struct;
|
||||
use encoding::all::UTF_8;
|
||||
use encoding::types::{EncoderTrap, Encoding};
|
||||
use ipc_channel::ipc;
|
||||
use net_traits::{CoreResourceMsg, IpcSend};
|
||||
use net_traits::blob_url_store::{BlobBuf, get_blob_origin};
|
||||
|
@ -337,12 +335,11 @@ pub fn blob_parts_to_bytes(blobparts: Vec<BlobOrString>) -> Result<Vec<u8>, ()>
|
|||
for blobpart in &blobparts {
|
||||
match blobpart {
|
||||
&BlobOrString::String(ref s) => {
|
||||
let mut bytes = UTF_8.encode(s, EncoderTrap::Replace).map_err(|_|())?;
|
||||
ret.append(&mut bytes);
|
||||
ret.extend(s.as_bytes());
|
||||
},
|
||||
&BlobOrString::Blob(ref b) => {
|
||||
let mut bytes = b.get_bytes().unwrap_or(vec![]);
|
||||
ret.append(&mut bytes);
|
||||
let bytes = b.get_bytes().unwrap_or(vec![]);
|
||||
ret.extend(bytes);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@ use dom::eventtarget::EventTarget;
|
|||
use dom::globalscope::GlobalScope;
|
||||
use dom::messageevent::MessageEvent;
|
||||
use dom_struct::dom_struct;
|
||||
use encoding::Encoding;
|
||||
use encoding::all::UTF_8;
|
||||
use euclid::length::Length;
|
||||
use hyper::header::{Accept, qitem};
|
||||
use ipc_channel::ipc;
|
||||
|
@ -39,6 +37,7 @@ use std::str::{Chars, FromStr};
|
|||
use std::sync::{Arc, Mutex};
|
||||
use task_source::TaskSource;
|
||||
use timers::OneshotTimerCallback;
|
||||
use utf8;
|
||||
|
||||
header! { (LastEventId, "Last-Event-ID") => [String] }
|
||||
|
||||
|
@ -76,6 +75,8 @@ enum ParserState {
|
|||
}
|
||||
|
||||
struct EventSourceContext {
|
||||
incomplete_utf8: Option<utf8::Incomplete>,
|
||||
|
||||
event_source: Trusted<EventSource>,
|
||||
gen_id: GenerationId,
|
||||
action_sender: ipc::IpcSender<FetchResponseMsg>,
|
||||
|
@ -293,12 +294,41 @@ impl FetchResponseListener for EventSourceContext {
|
|||
}
|
||||
|
||||
fn process_response_chunk(&mut self, chunk: Vec<u8>) {
|
||||
let mut stream = String::new();
|
||||
UTF_8.raw_decoder().raw_feed(&chunk, &mut stream);
|
||||
self.parse(stream.chars())
|
||||
let mut input = &*chunk;
|
||||
if let Some(mut incomplete) = self.incomplete_utf8.take() {
|
||||
match incomplete.try_complete(input) {
|
||||
None => return,
|
||||
Some((result, remaining_input)) => {
|
||||
self.parse(result.unwrap_or("\u{FFFD}").chars());
|
||||
input = remaining_input;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while !input.is_empty() {
|
||||
match utf8::decode(&input) {
|
||||
Ok(s) => {
|
||||
self.parse(s.chars());
|
||||
return
|
||||
}
|
||||
Err(utf8::DecodeError::Invalid { valid_prefix, remaining_input, .. }) => {
|
||||
self.parse(valid_prefix.chars());
|
||||
self.parse("\u{FFFD}".chars());
|
||||
input = remaining_input;
|
||||
}
|
||||
Err(utf8::DecodeError::Incomplete { valid_prefix, incomplete_suffix }) => {
|
||||
self.parse(valid_prefix.chars());
|
||||
self.incomplete_utf8 = Some(incomplete_suffix);
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn process_response_eof(&mut self, _response: Result<(), NetworkError>) {
|
||||
if let Some(_) = self.incomplete_utf8.take() {
|
||||
self.parse("\u{FFFD}".chars());
|
||||
}
|
||||
self.reestablish_the_connection();
|
||||
}
|
||||
}
|
||||
|
@ -378,6 +408,8 @@ impl EventSource {
|
|||
// Step 14
|
||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||
let context = EventSourceContext {
|
||||
incomplete_utf8: None,
|
||||
|
||||
event_source: Trusted::new(&ev),
|
||||
gen_id: ev.generation_id.get(),
|
||||
action_sender: action_sender.clone(),
|
||||
|
|
|
@ -11,9 +11,6 @@ use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
|||
use dom::bindings::str::{DOMString, USVString};
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom_struct::dom_struct;
|
||||
use encoding::EncoderTrap;
|
||||
use encoding::Encoding;
|
||||
use encoding::all::UTF_8;
|
||||
use js::jsapi::{JSContext, JSObject};
|
||||
use js::typedarray::{Uint8Array, CreateWith};
|
||||
use std::ptr;
|
||||
|
@ -45,13 +42,13 @@ impl TextEncoder {
|
|||
impl TextEncoderMethods for TextEncoder {
|
||||
// https://encoding.spec.whatwg.org/#dom-textencoder-encoding
|
||||
fn Encoding(&self) -> DOMString {
|
||||
DOMString::from(UTF_8.name())
|
||||
DOMString::from("utf-8")
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
// https://encoding.spec.whatwg.org/#dom-textencoder-encode
|
||||
unsafe fn Encode(&self, cx: *mut JSContext, input: USVString) -> NonZero<*mut JSObject> {
|
||||
let encoded = UTF_8.encode(&input.0, EncoderTrap::Strict).unwrap();
|
||||
let encoded = input.0.as_bytes();
|
||||
|
||||
rooted!(in(cx) let mut js_object = ptr::null_mut());
|
||||
assert!(Uint8Array::create(cx, CreateWith::Slice(&encoded), js_object.handle_mut()).is_ok());
|
||||
|
|
|
@ -102,6 +102,7 @@ extern crate time;
|
|||
extern crate tinyfiledialogs;
|
||||
extern crate unicode_segmentation;
|
||||
extern crate url;
|
||||
extern crate utf8;
|
||||
extern crate uuid;
|
||||
extern crate webrender_traits;
|
||||
extern crate webvr_traits;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue