Skip to content

GopherJS incorrectly uses stale archive files when latest source code fails to build. #559

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
alltom opened this issue Dec 22, 2016 · 7 comments
Labels
bug gopherjs-tool Related to the gopherjs tool or its build system (but not the compiler itself).

Comments

@alltom
Copy link

alltom commented Dec 22, 2016

  1. Create the following three files.
  2. Run gopherjs serve and load alltom/ in your browser.
  3. Edit iface.go to change Bar() int to Bar2() int.
  4. Edit main.go to change impl.MakeFoo().Bar() to impl.MakeFoo().Bar2().
  5. Reload your browser.

Instead of seeing a compile error about FooImpl no longer implementing Foo, you get a runtime error saying "Uncaught TypeError: impl.MakeFoo(...).Bar2 is not a function". It looks like gopherjs serve doesn't realize that impl.go needs to be recompiled.

alltom/iface/iface.go

package iface

type Foo interface {
	Bar() int
}

alltom/impl/impl.go

package impl

import "alltom/iface"

type FooImpl int

func MakeFoo() iface.Foo {
	return FooImpl(0)
}

func (f FooImpl) Bar() int {
	return 42
}

alltom/main.go

package main

import "alltom/impl"

func main() {
	impl.MakeFoo().Bar()
}
@dmitshur
Copy link
Member

dmitshur commented Dec 22, 2016

Thank you for posting detailed reproduce steps, that's very helpful.

@dmitshur
Copy link
Member

dmitshur commented Dec 24, 2016

I can reproduce. It also happens with gopherjs build or gopherjs run too, not just gopherjs serve.

Deleting impl.a from GOPATH/pkg/darwin_js/alltom/impl.a makes it produce correct compile error:

$ gopherjs run main.go 
impl/impl.go:8:9: cannot use FooImpl(0) (constant 0 of type FooImpl) as alltom/iface.Foo value in return statement: missing method Bar2

Since there's a compilation error, that impl.a doesn't get created. But if it already exists from a previous successful compilation run, it gets incorrectly used despite being stale.

It appears the problem is something like this. When a built archive file is stale, GopherJS correctly tries to rebuild it. However, if that package fails to build due to errors, it problematically still goes ahead and uses the stale file.

This is a bug in the build logic.

@dmitshur dmitshur added bug gopherjs-tool Related to the gopherjs tool or its build system (but not the compiler itself). labels Dec 24, 2016
@dmitshur dmitshur changed the title gopherjs serve misses some out-of-date files GopherJS uses stale archive files when building latest version fails due to compilation errors. Dec 24, 2016
@flimzy
Copy link
Member

flimzy commented Jan 9, 2017

I'm not completely sure this diagnosis is correct. While investigating #568, I added some debugging output to build.go, and I found that the caching/building logic appears to be working.

On a per-package basis, the cache is correctly used. Using my example in #568, for instance, after my change to bar.go, the bar package is re-built. However, the compile error is never detected, because foo is not rebuilt--because it hasn't changed.

So it seems that because 'foo' was valid at the time it was created, there is no compilation error, and the cached object is used. And because bar is valid now, there is no compilation error. The error is the failure to validate that foo and bar still link together properly. I don't know where that check belongs. My compiler/linking theory is weak-to-non-existent.

@dmitshur
Copy link
Member

dmitshur commented Jan 9, 2017

For our reference, there may be additional information in the duplicate issue #568.

@dmitshur dmitshur changed the title GopherJS uses stale archive files when building latest version fails due to compilation errors. GopherJS incorrectly uses stale archive files when latest source code fails to build. Feb 8, 2017
@dmitshur
Copy link
Member

dmitshur commented Mar 4, 2017

#598 (comment) is related too.

@dmitshur
Copy link
Member

dmitshur commented Mar 4, 2017

So it seems that because 'foo' was valid at the time it was created, there is no compilation error, and the cached object is used. And because bar is valid now, there is no compilation error. The error is the failure to validate that foo and bar still link together properly. I don't know where that check belongs. My compiler/linking theory is weak-to-non-existent.

Here's what I think should happen. I'll use original example from this bug report, since I was able to reproduce it earlier.

Say you have iface and impl that compile initially, and main uses both.

In reality, impl imports iface, and main imports impl.

As soon as you "edit iface.go to change Bar() int to Bar2() int", that should make archive file for impl stale, because a dependency has been modified more recently than the archive file was built.

So, when compiling main, which imports impl, impl should be rebuilt, and an error should occur then.

I haven't looked at your example yet, I just wanted to think this through with the one I tried earlier.

@dmitshur
Copy link
Member

dmitshur commented Mar 4, 2017

I suppose it's also possible for impl not to import iface, but for main to import both impl and iface. But in that case the build error should happen when rebuilding main.

dmitshur added a commit that referenced this issue Apr 27, 2017
The parent scope pkg variable was inadvertently shadowed in #411. As a
result, the value of impModeTime was wrong, and the if statement could
never be true, and pkg.SrcModTime was never updated to a later time.

Fixes #559 (possibly other similar issues, but they'll need to be verified).
dmitshur added a commit that referenced this issue Apr 27, 2017
The parent scope pkg variable was inadvertently shadowed in #411. As a
result, the value of impModeTime was wrong, and the if statement could
never be true, and pkg.SrcModTime was never updated to a later time.

Fixes #559 (possibly other similar issues, but they'll need to be verified).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug gopherjs-tool Related to the gopherjs tool or its build system (but not the compiler itself).
Projects
None yet
Development

No branches or pull requests

3 participants