diff --git a/version7.go b/version7.go index 3fec671..ab6103d 100644 --- a/version7.go +++ b/version7.go @@ -91,8 +91,19 @@ func getV7Time() (milli, seq int64) { nano := timeNow().UnixNano() milli = nano / nanoPerMilli - // Sequence number is between 0 and 3906 (nanoPerMilli>>8) - seq = (nano - milli*nanoPerMilli) >> 8 + if hasSubMilliClock { + // Sequence number is between 0 and 3906 (nanoPerMilli>>8) + seq = (nano - milli*nanoPerMilli) >> 8 + } else { + // The platform's wall clock has only millisecond resolution (e.g. on + // wasm), so the sub-millisecond fraction above would always be zero. + // Fill the 12-bit rand_a field with random data instead, as permitted + // by RFC 9562. Ordering within a millisecond is still preserved by the + // lastV7time+1 step below. + var b [2]byte + randomBits(b[:]) + seq = int64(b[0]&0x0f)<<8 | int64(b[1]) + } now := milli<<12 + seq if now <= lastV7time { now = lastV7time + 1 diff --git a/version7_other.go b/version7_other.go new file mode 100644 index 0000000..23d8929 --- /dev/null +++ b/version7_other.go @@ -0,0 +1,12 @@ +// Copyright 2026 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !js,!wasip1 + +package uuid + +// hasSubMilliClock reports whether the platform's wall clock is guaranteed to +// have sub-millisecond resolution. Non-wasm targets provide it, so v7 derives +// the rand_a field from a real sub-millisecond timestamp fraction. +const hasSubMilliClock = true diff --git a/version7_wasm.go b/version7_wasm.go new file mode 100644 index 0000000..511b521 --- /dev/null +++ b/version7_wasm.go @@ -0,0 +1,14 @@ +// Copyright 2026 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build js wasip1 + +package uuid + +// hasSubMilliClock reports whether the platform's wall clock is guaranteed to +// have sub-millisecond resolution. On the wasm targets (js and wasip1) the +// resolution is host-dependent and sub-millisecond precision is not +// guaranteed, so v7 fills the rand_a field with random bits instead of a +// timestamp fraction. +const hasSubMilliClock = false