Merge pull request #331 from evq/wasm

basic wasm support
This commit is contained in:
Brandon W Maister 2019-08-23 15:54:20 -04:00 committed by GitHub
commit 3e180b711e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 3 deletions

View File

@ -21,6 +21,11 @@ env:
global: global:
- LD_LIBRARY_PATH: /usr/local/lib - LD_LIBRARY_PATH: /usr/local/lib
- CLIPPY: n - CLIPPY: n
install:
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then source $HOME/.nvm/nvm.sh; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then nvm install 10; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then nvm use 10; fi
- if [ "$TRAVIS_RUST_VERSION" != "1.13.0" ]; then curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh; fi
script: ./ci/travis.sh script: ./ci/travis.sh
notifications: notifications:
email: false email: false

View File

@ -35,6 +35,11 @@ num-traits = { version = "0.2", default-features = false }
rustc-serialize = { version = "0.3.20", optional = true } rustc-serialize = { version = "0.3.20", optional = true }
serde = { version = "1", optional = true } serde = { version = "1", optional = true }
[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies]
wasm-bindgen = { version = "0.2" }
js-sys = "0.3" # contains FFI bindings for the JS Date API
[dev-dependencies] [dev-dependencies]
serde_json = { version = "1" } serde_json = { version = "1" }
serde_derive = { version = "1" } serde_derive = { version = "1" }
@ -42,6 +47,9 @@ bincode = { version = "0.8.0" }
num-iter = { version = "0.1.35", default-features = false } num-iter = { version = "0.1.35", default-features = false }
doc-comment = "0.3" doc-comment = "0.3"
[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dev-dependencies]
wasm-bindgen-test = "0.2"
[package.metadata.docs.rs] [package.metadata.docs.rs]
all-features = true all-features = true

View File

@ -48,6 +48,18 @@ build_and_test() {
channel build -v --no-default-features --features serde,rustc-serialize channel build -v --no-default-features --features serde,rustc-serialize
TZ=Asia/Katmandu channel test -v --no-default-features --features serde,rustc-serialize --lib TZ=Asia/Katmandu channel test -v --no-default-features --features serde,rustc-serialize --lib
if [ -n "${TRAVIS}" ] && [ "${TRAVIS_RUST_VERSION}" != "1.13.0" ]; then
# wasm tests
touch tests/wasm.rs # ensure rebuild happens so TZ / NOW take effect
TZ=ACST-9:30 NOW=$(date +%s) wasm-pack test --node
touch tests/wasm.rs
TZ=EST4 NOW=$(date +%s) wasm-pack test --node
touch tests/wasm.rs
TZ=UTC0 NOW=$(date +%s) wasm-pack test --node
touch tests/wasm.rs
TZ=Asia/Katmandu NOW=$(date +%s) wasm-pack test --node
fi
if [[ "$CHANNEL" == stable ]]; then if [[ "$CHANNEL" == stable ]]; then
if [[ -n "$TRAVIS" ]] ; then if [[ -n "$TRAVIS" ]] ; then
check_readme check_readme
@ -82,6 +94,7 @@ check_readme() {
rustc --version rustc --version
cargo --version cargo --version
node --version
CHANNEL=nightly CHANNEL=nightly
if [ "x${CLIPPY}" = xy ] ; then if [ "x${CLIPPY}" = xy ] ; then

View File

@ -414,6 +414,10 @@ extern crate serde as serdelib;
#[cfg(test)] #[cfg(test)]
#[macro_use] #[macro_use]
extern crate doc_comment; extern crate doc_comment;
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
extern crate wasm_bindgen;
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
extern crate js_sys;
#[cfg(test)] #[cfg(test)]
doctest!("../README.md"); doctest!("../README.md");

View File

@ -87,9 +87,21 @@ impl Local {
} }
/// Returns a `DateTime` which corresponds to the current date. /// Returns a `DateTime` which corresponds to the current date.
#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
pub fn now() -> DateTime<Local> { pub fn now() -> DateTime<Local> {
tm_to_datetime(oldtime::now()) tm_to_datetime(oldtime::now())
} }
/// Returns a `DateTime` which corresponds to the current date.
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
pub fn now() -> DateTime<Local> {
use super::Utc;
let now: DateTime<Utc> = super::Utc::now();
// Workaround missing timezone logic in `time` crate
let offset = FixedOffset::west((js_sys::Date::new_0().get_timezone_offset() as i32) * 60);
DateTime::from_utc(now.naive_utc(), offset)
}
} }
impl TimeZone for Local { impl TimeZone for Local {
@ -179,4 +191,3 @@ mod tests {
"unexpected timestr {:?}", timestr); "unexpected timestr {:?}", timestr);
} }
} }

View File

@ -4,7 +4,7 @@
//! The UTC (Coordinated Universal Time) time zone. //! The UTC (Coordinated Universal Time) time zone.
use std::fmt; use std::fmt;
#[cfg(feature="clock")] #[cfg(all(feature="clock", not(all(target_arch = "wasm32", not(target_os = "emscripten")))))]
use oldtime; use oldtime;
use naive::{NaiveDate, NaiveDateTime}; use naive::{NaiveDate, NaiveDateTime};
@ -38,11 +38,23 @@ impl Utc {
pub fn today() -> Date<Utc> { Utc::now().date() } pub fn today() -> Date<Utc> { Utc::now().date() }
/// Returns a `DateTime` which corresponds to the current date. /// Returns a `DateTime` which corresponds to the current date.
#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
pub fn now() -> DateTime<Utc> { pub fn now() -> DateTime<Utc> {
let spec = oldtime::get_time(); let spec = oldtime::get_time();
let naive = NaiveDateTime::from_timestamp(spec.sec, spec.nsec as u32); let naive = NaiveDateTime::from_timestamp(spec.sec, spec.nsec as u32);
DateTime::from_utc(naive, Utc) DateTime::from_utc(naive, Utc)
} }
/// Returns a `DateTime` which corresponds to the current date.
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
pub fn now() -> DateTime<Utc> {
let now = js_sys::Date::new_0();
let millisecs_since_unix_epoch: u64 = now.get_time() as u64;
let secs = millisecs_since_unix_epoch / 1000;
let nanos = 1_000_000 * (millisecs_since_unix_epoch - 1000 * secs);
let naive = NaiveDateTime::from_timestamp(secs as i64, nanos as u32);
DateTime::from_utc(naive, Utc)
}
} }
impl TimeZone for Utc { impl TimeZone for Utc {
@ -72,4 +84,3 @@ impl fmt::Debug for Utc {
impl fmt::Display for Utc { impl fmt::Display for Utc {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "UTC") } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "UTC") }
} }

30
tests/wasm.rs Normal file
View File

@ -0,0 +1,30 @@
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
mod test {
extern crate chrono;
extern crate wasm_bindgen_test;
use self::chrono::prelude::*;
use self::wasm_bindgen_test::*;
use std::env;
#[wasm_bindgen_test]
fn now() {
let utc: DateTime<Utc> = Utc::now();
let local: DateTime<Local> = Local::now();
// Ensure time fetched is correct
let actual = Utc.datetime_from_str(env!("NOW"), "%s").unwrap();
assert!(utc - actual < chrono::Duration::minutes(5));
// Ensure offset retrieved when getting local time is correct
let expected_offset = match env!("TZ") {
"ACST-9:30" => FixedOffset::east(19 * 30 * 60),
"Asia/Katmandu" => FixedOffset::east(23 * 15 * 60), // No DST thankfully
"EST4" => FixedOffset::east(-4 * 60 * 60),
"UTC0" => FixedOffset::east(0),
_ => panic!("unexpected TZ"),
};
assert_eq!(&expected_offset, local.offset());
}
}