forked from gopherjs/gopherjs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This is an initial cut of 1.13 support. internal/reflectlite is a new package in Go 1.13 that presents a subset of the API of reflect. internal/reflectlite support has been added according to the following steps: * in the build step, override the .GoFiles for internal/reflectlite to be empty, i.e. we will only take the native (GopherJS) implementation and won't augment any GOROOT definitions * taking the current native (GopherJS) implementation of reflect * taking the Go 1.13 implementation of reflect * adding all files into natives/src/internal/reflectlite (marking the Go 1.13 reflect files as _original.go) * progressively removing definitions from the *_original.go files until we get back to a package that compiles. This involves removing certain superfluous definitions (that only exist in the API of reflect) that bring in unwanted imports, e.g. strconv). We also then special case internal/reflectlite in the same places that reflect is special-cased. To handle the new core vendor of golang.org/x/net/dns/dnsmessage and friends, we use .ImportMap from the output of go list to resolve the correct package for any given import within a package. WIP - we still need to fix the handling of import paths at test time.
- Loading branch information
Showing
20 changed files
with
6,148 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
136 changes: 136 additions & 0 deletions
136
compiler/natives/src/internal/reflectlite/deepequal_original.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// +build js | ||
|
||
// Copyright 2009 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// Deep equality test via reflection | ||
|
||
package reflectlite | ||
|
||
import "unsafe" | ||
|
||
// During deepValueEqual, must keep track of checks that are | ||
// in progress. The comparison algorithm assumes that all | ||
// checks in progress are true when it reencounters them. | ||
// Visited comparisons are stored in a map indexed by visit. | ||
type visit struct { | ||
a1 unsafe.Pointer | ||
a2 unsafe.Pointer | ||
typ Type | ||
} | ||
|
||
// Tests for deep equality using reflected types. The map argument tracks | ||
// comparisons that have already been seen, which allows short circuiting on | ||
// recursive types. | ||
func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool { | ||
if !v1.IsValid() || !v2.IsValid() { | ||
return v1.IsValid() == v2.IsValid() | ||
} | ||
if v1.Type() != v2.Type() { | ||
return false | ||
} | ||
|
||
// if depth > 10 { panic("deepValueEqual") } // for debugging | ||
|
||
// We want to avoid putting more in the visited map than we need to. | ||
// For any possible reference cycle that might be encountered, | ||
// hard(t) needs to return true for at least one of the types in the cycle. | ||
hard := func(k Kind) bool { | ||
switch k { | ||
case Map, Slice, Ptr, Interface: | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) { | ||
addr1 := unsafe.Pointer(v1.UnsafeAddr()) | ||
addr2 := unsafe.Pointer(v2.UnsafeAddr()) | ||
if uintptr(addr1) > uintptr(addr2) { | ||
// Canonicalize order to reduce number of entries in visited. | ||
// Assumes non-moving garbage collector. | ||
addr1, addr2 = addr2, addr1 | ||
} | ||
|
||
// Short circuit if references are already seen. | ||
typ := v1.Type() | ||
v := visit{addr1, addr2, typ} | ||
if visited[v] { | ||
return true | ||
} | ||
|
||
// Remember for later. | ||
visited[v] = true | ||
} | ||
|
||
switch v1.Kind() { | ||
case Array: | ||
for i := 0; i < v1.Len(); i++ { | ||
if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) { | ||
return false | ||
} | ||
} | ||
return true | ||
case Slice: | ||
if v1.IsNil() != v2.IsNil() { | ||
return false | ||
} | ||
if v1.Len() != v2.Len() { | ||
return false | ||
} | ||
if v1.Pointer() == v2.Pointer() { | ||
return true | ||
} | ||
for i := 0; i < v1.Len(); i++ { | ||
if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) { | ||
return false | ||
} | ||
} | ||
return true | ||
case Interface: | ||
if v1.IsNil() || v2.IsNil() { | ||
return v1.IsNil() == v2.IsNil() | ||
} | ||
return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1) | ||
case Ptr: | ||
if v1.Pointer() == v2.Pointer() { | ||
return true | ||
} | ||
return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1) | ||
case Struct: | ||
for i, n := 0, v1.NumField(); i < n; i++ { | ||
if !deepValueEqual(v1.Field(i), v2.Field(i), visited, depth+1) { | ||
return false | ||
} | ||
} | ||
return true | ||
case Map: | ||
if v1.IsNil() != v2.IsNil() { | ||
return false | ||
} | ||
if v1.Len() != v2.Len() { | ||
return false | ||
} | ||
if v1.Pointer() == v2.Pointer() { | ||
return true | ||
} | ||
for _, k := range v1.MapKeys() { | ||
val1 := v1.MapIndex(k) | ||
val2 := v2.MapIndex(k) | ||
if !val1.IsValid() || !val2.IsValid() || !deepValueEqual(val1, val2, visited, depth+1) { | ||
return false | ||
} | ||
} | ||
return true | ||
case Func: | ||
if v1.IsNil() && v2.IsNil() { | ||
return true | ||
} | ||
// Can't do better than this: | ||
return false | ||
default: | ||
// Normal equality suffices | ||
return valueInterface(v1, false) == valueInterface(v2, false) | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
compiler/natives/src/internal/reflectlite/makefunc_original.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// +build js | ||
|
||
// Copyright 2012 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// MakeFunc implementation. | ||
|
||
package reflectlite | ||
|
||
// makeFuncImpl is the closure value implementing the function | ||
// returned by MakeFunc. | ||
// The first three words of this type must be kept in sync with | ||
// methodValue and runtime.reflectMethodValue. | ||
// Any changes should be reflected in all three. | ||
type makeFuncImpl struct { | ||
code uintptr | ||
stack *bitVector // ptrmap for both args and results | ||
argLen uintptr // just args | ||
ftyp *funcType | ||
fn func([]Value) []Value | ||
} | ||
|
||
// makeFuncStub is an assembly function that is the code half of | ||
// the function returned from MakeFunc. It expects a *callReflectFunc | ||
// as its context register, and its job is to invoke callReflect(ctxt, frame) | ||
// where ctxt is the context register and frame is a pointer to the first | ||
// word in the passed-in argument frame. | ||
func makeFuncStub() | ||
|
||
// The first 3 words of this type must be kept in sync with | ||
// makeFuncImpl and runtime.reflectMethodValue. | ||
// Any changes should be reflected in all three. | ||
type methodValue struct { | ||
fn uintptr | ||
stack *bitVector // ptrmap for both args and results | ||
argLen uintptr // just args | ||
method int | ||
rcvr Value | ||
} | ||
|
||
// methodValueCall is an assembly function that is the code half of | ||
// the function returned from makeMethodValue. It expects a *methodValue | ||
// as its context register, and its job is to invoke callMethod(ctxt, frame) | ||
// where ctxt is the context register and frame is a pointer to the first | ||
// word in the passed-in argument frame. | ||
func methodValueCall() |
Oops, something went wrong.