github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/compiler/natives/src/crypto/rand/rand.go (about) 1 //go:build js 2 // +build js 3 4 package rand 5 6 import ( 7 "errors" 8 9 "github.com/gopherjs/gopherjs/js" 10 ) 11 12 type reader struct{} 13 14 func (r *reader) Read(b []byte) (n int, err error) { 15 array := js.InternalObject(b).Get("$array") 16 offset := js.InternalObject(b).Get("$offset").Int() 17 18 // browser 19 crypto := js.Global.Get("crypto") 20 if crypto == js.Undefined { 21 crypto = js.Global.Get("msCrypto") 22 } 23 if crypto != js.Undefined { 24 if crypto.Get("getRandomValues") != js.Undefined { 25 n = len(b) 26 if n > 65536 { 27 // Avoid QuotaExceededError thrown by getRandomValues 28 // when length is more than 65536, as specified in 29 // http://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues 30 n = 65536 31 } 32 crypto.Call("getRandomValues", array.Call("subarray", offset, offset+n)) 33 return n, nil 34 } 35 } 36 37 // Node.js 38 if require := js.Global.Get("require"); require != js.Undefined { 39 if randomBytes := require.Invoke("crypto").Get("randomBytes"); randomBytes != js.Undefined { 40 array.Call("set", randomBytes.Invoke(len(b)), offset) 41 return len(b), nil 42 } 43 } 44 45 return 0, errors.New("crypto/rand not available in this environment") 46 }