Skip to content
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

TSX Sourcemaps #518

Merged
merged 47 commits into from
Oct 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
7679970
Add tests for sourcemaps
Princesseuh Jul 13, 2022
0e0c8b1
chore: update lockfile
natemoo-re Aug 24, 2022
314b2a6
wip: improved tsx sourcemaps
natemoo-re Sep 22, 2022
7261c5e
feat(tsx): update sourcemappings
natemoo-re Sep 23, 2022
a807207
fix: remove print from token_test
natemoo-re Sep 24, 2022
82f3f20
chore: fix lint
natemoo-re Sep 26, 2022
ffc8091
chore: update loc tests
natemoo-re Sep 26, 2022
1d88481
feat(sourcemaps): improve test coverage
natemoo-re Sep 27, 2022
235d483
chore: update wasm
natemoo-re Sep 27, 2022
77295a5
chore: update wasm
natemoo-re Sep 27, 2022
46d3f03
chore: add changeset
natemoo-re Sep 27, 2022
61b3fb4
fix(tsx): more accurate frontmatter sourcemaps
natemoo-re Sep 27, 2022
7fce35f
test: better debug output
natemoo-re Sep 27, 2022
9f8f48c
fix(tsx): frontmatter mapping
natemoo-re Sep 27, 2022
0027fc8
fix(types): expose SourceMap type
natemoo-re Sep 27, 2022
0595e59
fix(tsx): end tag position
natemoo-re Sep 27, 2022
ddcb4cf
fix(tsx): attribute space mapping
natemoo-re Sep 27, 2022
02fe1a8
fix(tsx): always print prefix/suffix for scripts
natemoo-re Sep 27, 2022
ef5a69c
feat(tsx): move semicolon to body open
natemoo-re Sep 27, 2022
5760974
feat(tsx): fix expression off-by-one-mapping, double end tag mapping
natemoo-re Sep 27, 2022
0db24ad
fix(tsx): improve expression attribute mapping
natemoo-re Sep 27, 2022
ba152b5
fix(tsx): improved handling of incomplete frontmatter
natemoo-re Sep 27, 2022
b6c67b7
feat(tsx): support typed props, update tests
natemoo-re Sep 27, 2022
5a2042a
fix(tsx): ensure no props and scoped props are not supported
natemoo-re Sep 27, 2022
90100db
test(tsx): add polymorphic test
natemoo-re Sep 27, 2022
7e14494
chore: format
natemoo-re Sep 27, 2022
67e0c66
fix(tsx): prop detection edge case
natemoo-re Sep 28, 2022
ae72b51
fix(tsx): better handling for unclosed tags
natemoo-re Sep 28, 2022
09a2adb
fix(tsx): always wrap with Fragment
natemoo-re Sep 28, 2022
a9de935
fix(tsx): map newlines
natemoo-re Sep 28, 2022
913dc43
fix: lint
natemoo-re Sep 28, 2022
91cea6d
chore: add comments
natemoo-re Sep 28, 2022
09282a2
fix: shorthand attribute mapping
natemoo-re Sep 28, 2022
a2b9fbc
fix(tsx): update semicolon logic
natemoo-re Sep 28, 2022
8cbffb9
fix(tsx): support template literal attributes
natemoo-re Sep 28, 2022
2725cda
fix(tsx): better mapping for shorthand attribute
natemoo-re Sep 28, 2022
10579d8
fix(tsx): shorthand = mapping
natemoo-re Sep 28, 2022
35ee810
fix(tsx): improve script mapping
natemoo-re Sep 28, 2022
9fe7e8a
fix(tsx): improve script mapping
natemoo-re Sep 28, 2022
0e6ec62
fix(tsx): improve mapping for newlines, end tags; add virtual astro:r…
natemoo-re Sep 29, 2022
0d10cfb
fix(tsx): ensure last newline and eof are mapped
natemoo-re Sep 29, 2022
d7affb6
fix(tsx): update end tag mappings
natemoo-re Sep 30, 2022
6b158d3
chore: format
natemoo-re Sep 30, 2022
c308db4
fix(tsx): attribute mapping
natemoo-re Oct 3, 2022
cb02bad
test(tsx): update test output
natemoo-re Oct 3, 2022
f5df8da
fix: windows handle EOF
natemoo-re Oct 3, 2022
ae14f48
chore: run wasm tests on Windows
natemoo-re Oct 3, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/twelve-waves-help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/compiler': minor
---

Improve sourcemap support for TSX output
13 changes: 8 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Test

on:
push:
branches: ['main', 'next']
branches: ["main", "next"]
pull_request:
branches: ['main', 'next']
branches: ["main", "next"]

# Automatically cancel in-progress actions on the same branch
concurrency:
Expand All @@ -26,7 +26,10 @@ jobs:
run: go test -v ./internal/...

test-wasm:
runs-on: ubuntu-latest
strategy:
matrix:
OS: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.OS }}
steps:
- uses: actions/checkout@v2

Expand All @@ -42,7 +45,7 @@ jobs:
uses: actions/setup-node@v2
with:
node-version: 14
cache: 'pnpm'
cache: "pnpm"

- name: Build WASM
run: make wasm
Expand Down Expand Up @@ -75,6 +78,6 @@ jobs:
- uses: actions/setup-node@v2
with:
node-version: 14
cache: 'pnpm'
cache: "pnpm"
- run: pnpm install
- run: pnpm run lint
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ node_modules
*.wasm
/astro
debug.test
packages/compiler/sourcemap.mjs
17 changes: 12 additions & 5 deletions cmd/astro-wasm/astro-wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,16 @@ func ConvertToTSX() interface{} {
}
result := printer.PrintToTSX(source, doc, transformOptions)

sourcemapString := createSourceMapString(source, result, transformOptions)
code := string(result.Output)
if transformOptions.SourceMap != "external" {
inlineSourcemap := `//# sourceMappingURL=data:application/json;charset=utf-8;base64,` + base64.StdEncoding.EncodeToString([]byte(sourcemapString))
code += "\n" + inlineSourcemap
}

return vert.ValueOf(TSXResult{
Code: string(result.Output),
Map: createSourceMapString(source, result, transformOptions),
Code: code,
Map: sourcemapString,
})
})
}
Expand Down Expand Up @@ -328,7 +335,7 @@ func Transform() interface{} {
output = append(output, []byte(strings.TrimSpace(node.FirstChild.Data))...)
}
sourcemap := fmt.Sprintf(
`{ "version": 3, "sources": ["%s"], "sourcesContent": [%s], "mappings": "%s", "names": [] }`,
`{ "version": 3, "sources": ["%s", "astro:runtime"], "sourcesContent": [%s, "Please open an issue: https://astro.build/issues"], "mappings": "%s", "names": [] }`,
transformOptions.Filename,
string(sourcesContent),
string(builder.GenerateChunk(output).Buffer),
Expand Down Expand Up @@ -408,8 +415,8 @@ func createSourceMapString(source string, result printer.PrintResult, transformO
}
return fmt.Sprintf(`{
"version": 3,
"sources": ["%s"],
"sourcesContent": [%s],
"sources": ["%s", "astro:runtime"],
"sourcesContent": [%s, "Please open an issue: https://astro.build/issues"],
"mappings": "%s",
"names": []
}`, sourcemap.Sources[0], sourcemap.SourcesContent[0], sourcemap.Mappings)
Expand Down
157 changes: 157 additions & 0 deletions internal/js_scanner/js_scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"io"
"strings"

"github.com/iancoleman/strcase"
"github.com/tdewolff/parse/v2"
Expand Down Expand Up @@ -179,6 +180,162 @@ func HoistImports(source []byte) HoistedScripts {
return HoistedScripts{Hoisted: imports, Body: body}
}

type Props struct {
Ident string
Statement string
Generics string
}

func GetPropsType(source []byte) Props {
defaultPropType := "Record<string, any>"
ident := defaultPropType
genericsIdents := make([]string, 0)
generics := ""
statement := ""

if !bytes.Contains(source, []byte("Props")) {
return Props{
Ident: ident,
Statement: statement,
Generics: generics,
}
}
l := js.NewLexer(parse.NewInputBytes(source))
i := 0
pairs := make(map[byte]int)
idents := make([]string, 0)

start := 0
end := 0

outer:
for {
token, value := l.Next()

if token == js.DivToken || token == js.DivEqToken {
lns := bytes.Split(source[i+1:], []byte{'\n'})
if bytes.Contains(lns[0], []byte{'/'}) {
token, value = l.RegExp()
}
}

if token == js.ErrorToken {
if l.Err() != io.EOF {
return Props{
Ident: ident,
}
}
break
}

// Common delimeters. Track their length, then skip.
if token == js.WhitespaceToken || token == js.LineTerminatorToken || token == js.SemicolonToken {
i += len(value)
continue
}

if token == js.ExtendsToken {
if bytes.Equal(value, []byte("extends")) {
idents = append(idents, "extends")
}
i += len(value)
continue
}

if pairs['{'] == 0 && pairs['('] == 0 && pairs['['] == 0 && pairs['<'] == 1 && token == js.CommaToken {
idents = make([]string, 0)
i += len(value)
continue
}

if js.IsIdentifier(token) {
if isKeyword(value) {
i += len(value)
continue
}
if pairs['<'] == 1 && pairs['{'] == 0 {
foundExtends := false
for _, id := range idents {
if id == "extends" {
foundExtends = true
}
}
if !foundExtends {
genericsIdents = append(genericsIdents, string(value))
}
i += len(value)
continue
}
// Note: do not check that `pairs['{'] == 0` to support named imports
if pairs['('] == 0 && pairs['['] == 0 && string(value) == "Props" {
ident = "Props"
}
idents = append(idents, string(value))
i += len(value)
continue
}

if bytes.ContainsAny(value, "<>") {
if len(idents) > 0 && idents[len(idents)-1] == "Props" {
start = i
ident = "Props"
idents = make([]string, 0)
}
for _, c := range value {
if c == '<' {
pairs['<']++
i += len(value)
continue
}
if c == '>' {
pairs['<']--
if pairs['<'] == 0 {
end = i
break outer
}
}
}
}

if token == js.QuestionToken || (pairs['{'] == 0 && token == js.ColonToken) {
idents = make([]string, 0)
idents = append(idents, "extends")
}

// Track opening and closing braces
if js.IsPunctuator(token) {
if value[0] == '{' || value[0] == '(' || value[0] == '[' {
idents = make([]string, 0)
pairs[value[0]]++
i += len(value)
continue
} else if value[0] == '}' {
pairs['{']--
if pairs['<'] == 0 && pairs['{'] == 0 && ident != defaultPropType {
end = i
break outer
}
} else if value[0] == ')' {
pairs['(']--
} else if value[0] == ']' {
pairs['[']--
}
}

// Track our current position
i += len(value)
}
if len(genericsIdents) > 0 && ident != defaultPropType {
generics = fmt.Sprintf("<%s>", strings.Join(genericsIdents, ", "))
statement = strings.TrimSpace(string(source[start:end]))
}
return Props{
Ident: ident,
Statement: statement,
Generics: generics,
}
}

func isIdentifier(value []byte) bool {
valid := true
for i, b := range value {
Expand Down
2 changes: 2 additions & 0 deletions internal/printer/print-to-js.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ func render1(p *printer, n *Node, opts RenderOptions) {

// Root of the document, print all children
if n.Type == DocumentNode {
p.addNilSourceMapping()
p.printInternalImports(p.opts.InternalURL)
if opts.opts.StaticExtraction && n.FirstChild != nil && n.FirstChild.Type != FrontmatterNode {
p.printCSSImports(opts.cssLen)
Expand Down Expand Up @@ -134,6 +135,7 @@ func render1(p *printer, n *Node, opts RenderOptions) {

for c := n.FirstChild; c != nil; c = c.NextSibling {
if c.Type == TextNode {
p.addNilSourceMapping()
p.printInternalImports(p.opts.InternalURL)

if len(n.Loc) > 0 {
Expand Down
Loading