Skip to content

Commit 23bfde2

Browse files
committed
Merge pull request #285 from gopherjs/fix-timeTime-Date-inexternalization
Fix possible panic during internalization/externalization of time.Time/Date.
2 parents 6d932be + 8bffb58 commit 23bfde2

File tree

8 files changed

+68
-5
lines changed

8 files changed

+68
-5
lines changed

circle.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ dependencies:
66
pre:
77
- cd /usr/local && sudo rm -rf go && curl https://storage.googleapis.com/golang/go1.5.linux-amd64.tar.gz | sudo tar -xz && sudo chmod a+w go/src/path/filepath
88
post:
9+
- mv ./gopherjs $HOME/bin
910
- npm install --global node-gyp
1011
- cd node-syscall && node-gyp rebuild && mkdir -p ~/.node_libraries/ && cp build/Release/syscall.node ~/.node_libraries/syscall.node
1112

1213
test:
1314
override:
14-
- ./gopherjs test --short --minify github.com/gopherjs/gopherjs/tests github.com/gopherjs/gopherjs/tests/main github.com/gopherjs/gopherjs/js archive/tar archive/zip bufio bytes compress/bzip2 compress/flate compress/gzip compress/lzw compress/zlib container/heap container/list container/ring crypto/aes crypto/cipher crypto/des crypto/dsa crypto/ecdsa crypto/elliptic crypto/hmac crypto/md5 crypto/rand crypto/rc4 crypto/rsa crypto/sha1 crypto/sha256 crypto/sha512 crypto/subtle crypto/x509 database/sql database/sql/driver debug/dwarf debug/elf debug/gosym debug/macho debug/pe encoding/ascii85 encoding/asn1 encoding/base32 encoding/base64 encoding/binary encoding/csv encoding/gob encoding/hex encoding/json encoding/pem encoding/xml errors expvar flag fmt go/ast go/constant go/doc go/format go/parser go/printer go/scanner go/token hash/adler32 hash/crc32 hash/crc64 hash/fnv html html/template image image/color image/draw image/gif image/jpeg image/png index/suffixarray io io/ioutil math math/big math/cmplx math/rand mime mime/multipart mime/quotedprintable net/http/cookiejar net/http/fcgi net/mail net/rpc/jsonrpc net/textproto net/url path path/filepath reflect regexp regexp/syntax sort strconv strings sync sync/atomic testing/quick text/scanner text/tabwriter text/template text/template/parse time unicode unicode/utf16 unicode/utf8
15+
- gopherjs test --short --minify github.com/gopherjs/gopherjs/tests github.com/gopherjs/gopherjs/tests/main github.com/gopherjs/gopherjs/js archive/tar archive/zip bufio bytes compress/bzip2 compress/flate compress/gzip compress/lzw compress/zlib container/heap container/list container/ring crypto/aes crypto/cipher crypto/des crypto/dsa crypto/ecdsa crypto/elliptic crypto/hmac crypto/md5 crypto/rand crypto/rc4 crypto/rsa crypto/sha1 crypto/sha256 crypto/sha512 crypto/subtle crypto/x509 database/sql database/sql/driver debug/dwarf debug/elf debug/gosym debug/macho debug/pe encoding/ascii85 encoding/asn1 encoding/base32 encoding/base64 encoding/binary encoding/csv encoding/gob encoding/hex encoding/json encoding/pem encoding/xml errors expvar flag fmt go/ast go/constant go/doc go/format go/parser go/printer go/scanner go/token hash/adler32 hash/crc32 hash/crc64 hash/fnv html html/template image image/color image/draw image/gif image/jpeg image/png index/suffixarray io io/ioutil math math/big math/cmplx math/rand mime mime/multipart mime/quotedprintable net/http/cookiejar net/http/fcgi net/mail net/rpc/jsonrpc net/textproto net/url path path/filepath reflect regexp regexp/syntax sort strconv strings sync sync/atomic testing/quick text/scanner text/tabwriter text/template text/template/parse time unicode unicode/utf16 unicode/utf8
1516
- go test -v -race ./...

compiler/natives/time/time.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ import (
99
"github.com/gopherjs/gopherjs/js"
1010
)
1111

12+
// Make sure time.Unix func and time.Time struct it returns are always included with this package (despite DCE),
13+
// because they're needed for internalization/externalization of time.Time/Date. See issue https://github.com/gopherjs/gopherjs/issues/279.
14+
func init() {
15+
// avoid dead code elimination
16+
var _ Time = Unix(0, 0)
17+
}
18+
1219
type runtimeTimer struct {
1320
i int32
1421
when int64

compiler/prelude/jsmapping.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ var $externalize = function(v, t) {
8989
return s;
9090
case $kindStruct:
9191
var timePkg = $packages["time"];
92-
if (timePkg && v.constructor === timePkg.Time.ptr) {
92+
if (timePkg !== undefined && v.constructor === timePkg.Time.ptr) {
9393
var milli = $div64(v.UnixNano(), new $Int64(0, 1000000));
9494
return new Date($flatten64(milli));
9595
}
@@ -271,9 +271,11 @@ var $internalize = function(v, t, recv) {
271271
return new $Bool(!!v);
272272
case Date:
273273
var timePkg = $packages["time"];
274-
if (timePkg) {
275-
return new timePkg.Time(timePkg.Unix(new $Int64(0, 0), new $Int64(0, v.getTime() * 1000000)));
274+
if (timePkg === undefined) {
275+
/* time package is not present, internalize as &js.Object{Date} so it can be externalized into original Date. */
276+
return new $jsObjectPtr(v);
276277
}
278+
return new timePkg.Time(timePkg.Unix(new $Int64(0, 0), new $Int64(0, v.getTime() * 1000000)));
277279
case Function:
278280
var funcType = $funcType([$sliceType($emptyInterface)], [$jsObjectPtr], true);
279281
return new funcType($internalize(v, funcType));

tests/doc.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Package tests contains tests for GopherJS.
2+
package tests

tests/empty.go

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/lowlevel_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// +build !js
2+
3+
package tests_test
4+
5+
import (
6+
"bytes"
7+
"io/ioutil"
8+
"os/exec"
9+
"path/filepath"
10+
"testing"
11+
)
12+
13+
// Test for internalization/externalization of time.Time/Date when time package is imported
14+
// but time.Time is unused, causing it to be DCEed (or time package not imported at all).
15+
//
16+
// See https://github.com/gopherjs/gopherjs/issues/279.
17+
func TestTimeInternalizationExternalization(t *testing.T) {
18+
got, err := exec.Command("gopherjs", "run", filepath.Join("testdata", "time_inexternalization.go")).CombinedOutput()
19+
if err != nil {
20+
t.Fatalf("%v:\n%s", err, got)
21+
}
22+
23+
want, err := ioutil.ReadFile(filepath.Join("testdata", "time_inexternalization.out"))
24+
if err != nil {
25+
t.Fatalf("error reading .out file: %v", err)
26+
}
27+
28+
if !bytes.Equal(got, want) {
29+
t.Fatalf("got != want:\ngot:\n%s\nwant:\n%s", got, want)
30+
}
31+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package main
2+
3+
import (
4+
"time"
5+
6+
"github.com/gopherjs/gopherjs/js"
7+
)
8+
9+
var _ = time.Sleep // Force "time" package to be imported but let time.Time and time.Unix be DCEed since they're not used.
10+
11+
func main() {
12+
// Excercise externalization of Go struct (with its special handling of time.Time).
13+
js.Global.Get("console").Call("log", struct{ S string }{"externalization ok"})
14+
15+
// Excercise internalization of JavaScript Date object (with its special handling of time.Time).
16+
date := js.Global.Get("Date").New("2015-08-29T20:56:00.869Z").Interface()
17+
js.Global.Set("myDate", date)
18+
js.Global.Get("console").Call("log", js.Global.Get("myDate").Call("toUTCString"))
19+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{ S: 'externalization ok' }
2+
Sat, 29 Aug 2015 20:56:00 GMT

0 commit comments

Comments
 (0)